@charset "UTF-8";
/* fig-colors tokens, spec: fig/styles/tokens/fig-colors.md, edit via /design:create-or-update-token */
:root {
  /*============ Primary, Navy (brand anchor, CTAs) ============*/
  --fig-color-primary-000: #e6e6ed;
  --fig-color-primary-100: #ccceda;
  --fig-color-primary-200: #999db5;
  --fig-color-primary-300: #666b91;
  --fig-color-primary-400: #333a6c;
  --fig-color-primary-500: #000947; /* NAVY, brand anchor */
  --fig-color-primary-600: #00083c;
  --fig-color-primary-700: #000632;
  --fig-color-primary-800: #000527;
  --fig-color-primary-900: #00041c;
  /*============ Secondary, Teal (secondary accents, alt interactive) ============*/
  --fig-color-secondary-000: #f7fcfb;
  --fig-color-secondary-100: #effaf9;
  --fig-color-secondary-200: #d6f1ee;
  --fig-color-secondary-300: #a9e0d9;
  --fig-color-secondary-400: #6bc9bd;
  --fig-color-secondary-500: #1aad9b; /* TEAL, secondary anchor */
  --fig-color-secondary-600: #0d9488;
  --fig-color-secondary-700: #0a786e;
  --fig-color-secondary-800: #085c54;
  --fig-color-secondary-900: #05413b;
  /*============ Accent, Sky Blue (primary interactive, focus, hover, brand accent) ============
    Brand-true accent lane. Paints focus rings, primary links, filled CTAs
    that want the cool-blue brand signature instead of navy emphasis. Anchor at
    -500 is #76c3f9. Ramp follows the roughly-perceptual step spacing used by
    primary / secondary / success / danger: very light at -000, anchor at
    -500, deep at -900. Paired with fg-on-accent = white via semantic tokens. */
  --fig-color-accent-000: #f0f8ff;
  --fig-color-accent-100: #cde8fe;
  --fig-color-accent-200: #bfe0fd;
  --fig-color-accent-300: #a2d2fc;
  --fig-color-accent-400: #85c4f5;
  --fig-color-accent-500: #76c3f9; /* SKY BLUE, accent anchor */
  --fig-color-accent-600: #4e9ee0;
  --fig-color-accent-700: #2d7ec0;
  --fig-color-accent-800: #16629d;
  --fig-color-accent-900: #0f4a76;
  /*============ Tertiary, Violet (tertiary interactive, project-type surfaces) ============
    Third lane distinct from sky-blue primary accent. Paints project-type
    affordances (mention chips, project cards), informational chrome, and any
    surface that needs a violet counterpoint to the cool-blue primary accent.
    Ramp restored to the post-2026-04-24 violet tier, anchor at -500 is #8b5df6. */
  --fig-color-tertiary-000: #f5f0ff;
  --fig-color-tertiary-100: #ede4ff;
  --fig-color-tertiary-200: #dbc9ff;
  --fig-color-tertiary-300: #c5a7ff;
  --fig-color-tertiary-400: #ab87fa;
  --fig-color-tertiary-500: #8b5df6; /* VIOLET, tertiary anchor */
  --fig-color-tertiary-600: #7442e0;
  --fig-color-tertiary-700: #5d30bf;
  --fig-color-tertiary-800: #472495;
  --fig-color-tertiary-900: #321968;
  /*============ Neutral, Slate (surfaces, borders, body text) ============
    Cool blue-grey ramp. Mirrored 1:1 in tokens.json `gf-neutral` for 1.0 surfaces. */
  --fig-color-neutral-000: #f8fafc;
  --fig-color-neutral-100: #f1f5f9;
  --fig-color-neutral-200: #e2e8f0;
  --fig-color-neutral-300: #cbd5e1;
  --fig-color-neutral-400: #94a3b8;
  --fig-color-neutral-500: #64748b;
  --fig-color-neutral-600: #475569;
  --fig-color-neutral-700: #334155;
  --fig-color-neutral-800: #1e293b;
  --fig-color-neutral-900: #0f172a;
  /*============ Success, Green (confirmations, positive states) ============*/
  --fig-color-success-000: #f0fdf4;
  --fig-color-success-100: #dcfce7;
  --fig-color-success-200: #bbf7d0;
  --fig-color-success-300: #86efac;
  --fig-color-success-400: #4ade80;
  --fig-color-success-500: #22c55e;
  --fig-color-success-600: #16a34a;
  --fig-color-success-700: #15803d;
  --fig-color-success-800: #166534;
  --fig-color-success-900: #14532d;
  /*============ Warning, Amber (warnings, alerts) ============*/
  --fig-color-warning-000: #fffbeb;
  --fig-color-warning-100: #fef3c7;
  --fig-color-warning-200: #fde68a;
  --fig-color-warning-300: #fcd34d;
  --fig-color-warning-400: #fbbf24;
  --fig-color-warning-500: #f59e0b;
  --fig-color-warning-600: #d97706;
  --fig-color-warning-700: #b45309;
  --fig-color-warning-800: #92400e;
  --fig-color-warning-900: #78350f;
  /*============ Danger, Red (errors, destructive actions) ============*/
  --fig-color-danger-000: #fef2f2;
  --fig-color-danger-100: #fee2e2;
  --fig-color-danger-200: #fecaca;
  --fig-color-danger-300: #fca5a5;
  --fig-color-danger-400: #f87171;
  --fig-color-danger-500: #ef4444;
  --fig-color-danger-600: #dc2626;
  --fig-color-danger-700: #b91c1c;
  --fig-color-danger-800: #991b1b;
  --fig-color-danger-900: #7f1d1d;
  /*============ Gold, Bright yellow (Signal Spotlight insight pill) ============
    Theatrical stage-spotlight color. Distinct from warning amber (#f59e0b):
    gold-500 sits in the yellow-yellow zone, warning-500 in the amber-orange
    zone. Anchor at -500 is #facc15. Ramp follows the same perceptual-step
    spacing as the rest of the palette. Only Signal pill consumes it today
    (apps/insights/models.py:INSIGHT_TYPE_PILL_VARIANT). */
  --fig-color-gold-000: #fefce8;
  --fig-color-gold-100: #fef9c3;
  --fig-color-gold-200: #fef08a;
  --fig-color-gold-300: #fde047;
  --fig-color-gold-400: #fbe040;
  --fig-color-gold-500: #facc15; /* GOLD, Spotlight anchor */
  --fig-color-gold-600: #eab308;
  --fig-color-gold-700: #a16207;
  --fig-color-gold-800: #854d0e;
  --fig-color-gold-900: #713f12;
  /*============ Generic (no ramp, singletons) ============*/
  --fig-color-generic-white: #ffffff;
  --fig-color-generic-black: #000000;
  --fig-color-generic-transparent: transparent;
}

/* fig-space tokens, spec: fig/styles/tokens/fig-space.md, edit via /design:create-or-update-token */
:root {
  /*============ Knobs ============*/
  /* Multiplicative ratio. 1.25 = GoFig calibrated (dense B2B).
     1.333 (perfect fourth), 1.5 (Every Layout default), 1.618 (golden) also valid. */
  --fig-space-ratio: 1.25;
  /* Typographic measure, line-length cap in characters.
     Referenced by Switcher threshold, body-text max-inline-size. */
  --fig-typographic-measure: 60ch;
  /*============ Space scale, derived, do not hand-tune ============*/
  --fig-space-3: 1rem; /* base, body rhythm */
  /* Upward steps, section + hero spacing */
  --fig-space-4: calc(var(--fig-space-3) * var(--fig-space-ratio));
  --fig-space-5: calc(var(--fig-space-4) * var(--fig-space-ratio));
  --fig-space-6: calc(var(--fig-space-5) * var(--fig-space-ratio));
  --fig-space-7: calc(var(--fig-space-6) * var(--fig-space-ratio));
  --fig-space-8: calc(var(--fig-space-7) * var(--fig-space-ratio));
  --fig-space-9: calc(var(--fig-space-8) * var(--fig-space-ratio));
  --fig-space-10: calc(var(--fig-space-9) * var(--fig-space-ratio));
  --fig-space-11: calc(var(--fig-space-10) * var(--fig-space-ratio));
  --fig-space-12: calc(var(--fig-space-11) * var(--fig-space-ratio));
  /* Downward steps, micro spacing */
  --fig-space-2: calc(var(--fig-space-3) / var(--fig-space-ratio));
  --fig-space-1: calc(var(--fig-space-2) / var(--fig-space-ratio));
  --fig-space-0: calc(var(--fig-space-1) / var(--fig-space-ratio));
  --fig-space--1: calc(var(--fig-space-0) / var(--fig-space-ratio));
  --fig-space--2: calc(var(--fig-space--1) / var(--fig-space-ratio));
  --fig-space--3: calc(var(--fig-space--2) / var(--fig-space-ratio));
  --fig-space--4: calc(var(--fig-space--3) / var(--fig-space-ratio));
  /*============ Semantic spacing ============*/
  /* Default page padding, the even inset applied around page-level content
     (the filter sidebar, content columns). One constant so every page gutter
     matches; = the content gutter fig-center-layout already uses, so the sidebar
     and the centered feed column read as the same inset. Derived, never raw. */
  --fig-page-padding: var(--fig-space-3);
}

/* fig-text tokens, spec: fig/styles/tokens/fig-text.md, edit via /design:create-or-update-token */
:root {
  /*============ Knobs ============*/
  /* Multiplicative ratio. 1.25 = GoFig calibrated, matches --fig-space-ratio.
     1.2 (minor third), 1.333 (perfect fourth), 1.5, 1.618 (golden) also valid. */
  --fig-text-ratio: 1.25;
  /* Readable floor, no text in the app renders below this. The derived
     downward steps (--fig-text-2/1/0) fall to 12.8/10.2/8.2px on the raw
     scale, which is too small for filter labels, select chips, captions, etc.
     max()-clamping them here lifts every sub-body size to the floor app-wide
     without per-component overrides. Body (--fig-text-3, 16px) stays above it,
     so the body/secondary hierarchy is preserved (16 vs 14). */
  --fig-text-min: 0.875rem; /* 14px */
  /*============ Type scale, derived, do not hand-tune ============*/
  /* Anchor, body text default. 1rem (16px) matches web baseline and the
     density of 1.0's --gf-text-body cap (12.5px) without going as dense.
     Was `clamp(1rem, ..., 1.2rem)` which pushed body to 19px at desktop
     and, combined with the old :root font-size re-anchoring, zoomed the
     whole fig surface ~50% larger than the rest of the app. */
  --fig-text-3: 1rem;
  --fig-text-4: calc(var(--fig-text-3) * var(--fig-text-ratio));
  --fig-text-5: calc(var(--fig-text-4) * var(--fig-text-ratio));
  --fig-text-6: calc(var(--fig-text-5) * var(--fig-text-ratio));
  --fig-text-7: calc(var(--fig-text-6) * var(--fig-text-ratio));
  --fig-text-8: calc(var(--fig-text-7) * var(--fig-text-ratio));
  --fig-text-9: calc(var(--fig-text-8) * var(--fig-text-ratio));
  --fig-text-2: max(var(--fig-text-min), calc(var(--fig-text-3) / var(--fig-text-ratio)));
  --fig-text-1: max(var(--fig-text-min), calc(var(--fig-text-2) / var(--fig-text-ratio)));
  --fig-text-0: max(var(--fig-text-min), calc(var(--fig-text-1) / var(--fig-text-ratio)));
  /*============ Line-height anchors ============*/
  --fig-line-height-tight: 1.1; /* display + h1 */
  --fig-line-height-snug: 1.25; /* h2..h6 */
  --fig-line-height-body: 1.5; /* paragraphs (default on :root) */
  --fig-line-height-loose: 1.7; /* prose-heavy blocks */
  /*============ Font weights ============*/
  --fig-font-weight-thin: 100;
  --fig-font-weight-extralight: 200;
  --fig-font-weight-light: 300;
  --fig-font-weight-regular: 400;
  --fig-font-weight-medium: 500;
  --fig-font-weight-semibold: 600;
  --fig-font-weight-bold: 700;
  --fig-font-weight-extrabold: 800;
  --fig-font-weight-black: 900;
  /*============ Letter spacing ============*/
  --fig-letter-spacing-tight: -0.01em;
  --fig-letter-spacing-normal: 0;
  --fig-letter-spacing-wide: 0.01em;
  --fig-letter-spacing-xwide: 0.04em;
  /*============ Font families ============*/
  --fig-font-family-sans: "Inter", ui-sans-serif, system-ui, -apple-system,
    BlinkMacSystemFont, Arial, "Noto Sans", sans-serif, "Apple Color Emoji",
    "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
  --fig-font-family-mono: "JetBrains Mono", "Fira Code", Monaco, Consolas, monospace;
}

/* fig-border-radius tokens, spec: fig/styles/tokens/fig-border-radius.md, edit via /design:create-or-update-token */
:root {
  --fig-border-radius-0: 0; /* sharp */
  --fig-border-radius-1: 0.125rem; /* 2px, subtle */
  --fig-border-radius-2: 0.25rem; /* 4px, inputs, compact buttons */
  --fig-border-radius-3: 0.375rem; /* 6px, buttons, tags */
  --fig-border-radius-4: 0.5rem; /* 8px, boxes, popovers */
  --fig-border-radius-5: 0.75rem; /* 12px, cards, modals */
  --fig-border-radius-6: 2.5rem; /* 40px, device bezel (iPhone-shaped mockups) */
  --fig-border-radius-pill: 9999px; /* full-round (pill buttons, avatars) */
}

/* fig-shadow tokens, spec: fig/styles/tokens/fig-shadow.md, edit via /design:create-or-update-token */
:root {
  --fig-shadow-0: none;
  --fig-shadow-1: 0 1px 2px rgb(20 19 13 / 0.06);
  --fig-shadow-2: 0 1px 2px rgb(20 19 13 / 0.06), 0 2px 4px rgb(20 19 13 / 0.06);
  --fig-shadow-3: 0 4px 8px rgb(20 19 13 / 0.08), 0 2px 4px rgb(20 19 13 / 0.05);
  --fig-shadow-4: 0 12px 24px rgb(20 19 13 / 0.12), 0 4px 8px rgb(20 19 13 / 0.08);
  /* Palette glow rings, focus / context-highlight / hover affordance. The
     secondary (teal) halo is the chat-input's signature; the primary halo is
     the card-context ring (the source element of an active chat chip), paired
     with the primary-tinted chip so the two read as one control. Primary rides
     the semantic --fig-bg-emphasis so it follows each deployment's primary
     theme; secondary keeps its light-tint primitive. Used by fig-chat-input
     (focus-within), the [data-chat-context-active] source ring, landing-page
     buttons (hover), and any surface wanting a glow halo. */
  --fig-glow-primary: 0 0 0 3px color-mix(in srgb, var(--fig-bg-emphasis) 22%, transparent);
  --fig-glow-secondary: 0 0 0 3px var(--fig-color-secondary-100);
}

[data-theme=dark] {
  --fig-shadow-0: none;
  --fig-shadow-1: 0 1px 2px rgb(0 0 0 / 0.4);
  --fig-shadow-2: 0 1px 2px rgb(0 0 0 / 0.4), 0 2px 4px rgb(0 0 0 / 0.4);
  --fig-shadow-3: 0 4px 8px rgb(0 0 0 / 0.5), 0 2px 4px rgb(0 0 0 / 0.4);
  --fig-shadow-4: 0 12px 24px rgb(0 0 0 / 0.6), 0 4px 8px rgb(0 0 0 / 0.4);
}

/* DARK MODE DISABLED, uncomment to re-enable OS-preference auto-dark.
   The explicit [data-theme="dark"] block above still applies when opted in.
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --fig-shadow-0: none;
    --fig-shadow-1: 0 1px 2px rgb(0 0 0 / 0.4);
    --fig-shadow-2: 0 1px 2px rgb(0 0 0 / 0.4), 0 2px 4px rgb(0 0 0 / 0.4);
    --fig-shadow-3: 0 4px 8px rgb(0 0 0 / 0.5), 0 2px 4px rgb(0 0 0 / 0.4);
    --fig-shadow-4: 0 12px 24px rgb(0 0 0 / 0.6), 0 4px 8px rgb(0 0 0 / 0.4);
  }
}
*/
/* fig-motion, spec: fig/styles/tokens/fig-motion.md, edit via /design:create-or-update-token */
:root {
  /* Durations, discrete scale (not ratio-derived; tuned to UX roles) */
  --fig-duration-0: 80ms; /* flash       , micro-feedback */
  --fig-duration-1: 120ms; /* fast        , tabs, breadcrumbs */
  --fig-duration-2: 150ms; /* standard    , default UI transitions */
  --fig-duration-3: 200ms; /* deliberate  , toasts, steps */
  --fig-duration-4: 300ms; /* slow        , drawers, bigger moves */
  --fig-duration-5: 400ms; /* entrance    , panels, staged reveals */
  --fig-duration-6: 600ms; /* hero        , page-level choreography */
  /* Eases, cubic-bezier curves tuned to motion roles */
  --fig-ease-0: linear; /* continuous, spinners */
  --fig-ease-1: cubic-bezier(0, 0, 0.2, 1); /* out       , entrances (decelerate) */
  --fig-ease-2: cubic-bezier(0.4, 0, 0.2, 1); /* standard  , symmetric (Material) */
  --fig-ease-3: cubic-bezier(0.4, 0, 1, 1); /* in        , exits (accelerate) */
  --fig-ease-4: cubic-bezier(0.34, 1.56, 0.64, 1); /* emphasized, overshoot for attention */
  --fig-ease-5: cubic-bezier(0.22, 1, 0.36, 1); /* expand    , large-surface grow/reveal (card edit-open, detail folds) */
}

/* fig-container tokens, spec: fig/styles/tokens/fig-container.md, edit via /design:create-or-update-token */
:root {
  /* Popover-tier (negative steps), sized below the container-0 floor for
     floating-panel chrome (context menu, popover, color picker, type
     selector). Double-dash naming matches fig-space's negative-step idiom. */
  --fig-container--3: 12rem; /* 192px, tooltip / mini-menu */
  --fig-container--2: 14rem; /* 224px, popover / picker min */
  --fig-container--1: 16rem; /* 256px, compact container */
  /* Page-tier */
  --fig-container-0: 18rem; /* 288px, narrow prompt */
  --fig-container-1: 24rem; /* 384px, auth card */
  --fig-container-2: 32rem; /* 512px, landing hero, default gate */
  --fig-container-3: 40rem; /* 640px, wide landing */
  --fig-container-4: 48rem; /* 768px, text column */
  --fig-container-5: 64rem; /* 1024px, content column */
  --fig-container-6: 80rem; /* 1280px, wide content */
  --fig-container-7: 100rem; /* 1600px, viewport cap */
}

/* fig-semantic tokens, spec: fig/styles/tokens/fig-semantic.md, edit via /design:create-or-update-token */
/*============ Light (default) ============*/
:root {
  /* Foreground */
  --fig-fg-default: var(--fig-color-neutral-900); /* body text, headings */
  --fig-fg-muted: var(--fig-color-neutral-600); /* descriptions, help text */
  --fig-fg-subtle: var(--fig-color-neutral-400); /* tertiary, timestamps */
  --fig-fg-on-accent: var(--fig-color-generic-white); /* text on bg-accent (sky blue) */
  --fig-fg-on-tertiary: var(--fig-color-tertiary-900); /* text on bg-tertiary, dark violet; violet-500 (#8b5df6) too light to carry white at AA reliably */
  --fig-fg-on-emphasis: var(--fig-color-generic-white); /* text on bg-emphasis (navy) */
  --fig-fg-on-secondary: var(--fig-color-generic-white); /* text on bg-secondary (teal) */
  --fig-fg-on-danger: var(--fig-color-generic-white); /* text on bg-danger (red) */
  --fig-fg-on-success: var(--fig-color-generic-white); /* text on bg-success (green) */
  --fig-fg-on-warning: var(--fig-color-neutral-900); /* text on bg-warning (amber, dark text for contrast) */
  /* Domain pills, six categorical brand slots, cycled by the view
     (data-domain="1".."6" on a .fig-badge). Each slot is a soft chip: a light
     tint background + a deep ink foreground for AA at badge size. These defaults
     map to the shared brand ramps; a per-deployment theme (theme-warm.css,
     theme-vertech.css) re-points all six to its OWN org brand palette, so the
     same markup recolors per client with no template change. */
  --fig-domain-1-bg: var(--fig-color-secondary-100);
  --fig-domain-1-fg: var(--fig-color-secondary-700);
  --fig-domain-2-bg: var(--fig-color-primary-100);
  --fig-domain-2-fg: var(--fig-color-primary-700);
  --fig-domain-3-bg: var(--fig-color-accent-100);
  --fig-domain-3-fg: var(--fig-color-accent-800);
  --fig-domain-4-bg: var(--fig-color-tertiary-100);
  --fig-domain-4-fg: var(--fig-color-tertiary-700);
  --fig-domain-5-bg: var(--fig-color-gold-100);
  --fig-domain-5-fg: var(--fig-color-gold-800);
  --fig-domain-6-bg: var(--fig-color-warning-100);
  --fig-domain-6-fg: var(--fig-color-warning-800);
  /* Background, surfaces. Two-tier: page = slate, cards = white. */
  --fig-bg-default: var(--fig-color-neutral-000); /* page, slate-50 */
  --fig-bg-subtle: var(--fig-color-generic-white); /* elevated surfaces (cards) */
  --fig-bg-muted: var(--fig-color-neutral-100); /* input field fills, subtle neutral hovers */
  --fig-bg-tint: color-mix(in srgb, var(--fig-color-neutral-200) 50%, transparent); /* semi-transparent umber tint for decorative backdrops */
  --fig-bg-overlay: rgb(20 19 13 / 0.5); /* modal backdrop (neutral-900 @ 50%) */
  --fig-bg-overlay-glass: rgb(255 255 255 / 0.82); /* glass-panel surface; pair with `backdrop-filter: blur(10px)` (project-graph minimap, controls, popovers) */
  /* Background, gradients (for hero panels, brand surfaces)
     Category-subcategory naming: `bg-gradient-{palette}-{tone}` or
     `bg-gradient-{variant}`. Three tones map to role: -light (soft tint),
     -bold (saturated brand presence), plus cross-palette duotones and
     radial spotlights. See fig/styles/utilities/fig-bg-gradient.md. */
  --fig-bg-gradient-subtle: linear-gradient(135deg, var(--fig-color-neutral-000) 0%, var(--fig-color-neutral-100) 100%);
  /* Mono-light, pale tints within a single palette */
  --fig-bg-gradient-primary-light: linear-gradient(135deg, var(--fig-color-primary-000) 0%, var(--fig-color-primary-200) 100%);
  --fig-bg-gradient-secondary-light: linear-gradient(135deg, var(--fig-color-secondary-000) 0%, var(--fig-color-secondary-200) 100%);
  --fig-bg-gradient-tertiary-light: linear-gradient(135deg, var(--fig-color-tertiary-000) 0%, var(--fig-color-tertiary-200) 100%);
  --fig-bg-gradient-accent-light: linear-gradient(135deg, var(--fig-color-accent-000) 0%, var(--fig-color-accent-200) 100%);
  --fig-bg-gradient-neutral-light: linear-gradient(135deg, var(--fig-color-neutral-000) 0%, var(--fig-color-neutral-200) 100%);
  --fig-bg-gradient-success-light: linear-gradient(135deg, var(--fig-color-success-000) 0%, var(--fig-color-success-200) 100%);
  --fig-bg-gradient-warning-light: linear-gradient(135deg, var(--fig-color-warning-000) 0%, var(--fig-color-warning-200) 100%);
  --fig-bg-gradient-danger-light: linear-gradient(135deg, var(--fig-color-danger-000) 0%, var(--fig-color-danger-200) 100%);
  /* Mono-bold, saturated single-palette gradients for hero panels */
  --fig-bg-gradient-primary-bold: linear-gradient(135deg, var(--fig-color-primary-400) 0%, var(--fig-color-primary-700) 100%);
  --fig-bg-gradient-secondary-bold: linear-gradient(135deg, var(--fig-color-secondary-400) 0%, var(--fig-color-secondary-700) 100%);
  --fig-bg-gradient-tertiary-bold: linear-gradient(135deg, var(--fig-color-tertiary-400) 0%, var(--fig-color-tertiary-700) 100%);
  --fig-bg-gradient-accent-bold: linear-gradient(135deg, var(--fig-color-accent-400) 0%, var(--fig-color-accent-700) 100%);
  --fig-bg-gradient-neutral-bold: linear-gradient(135deg, var(--fig-color-neutral-400) 0%, var(--fig-color-neutral-700) 100%);
  --fig-bg-gradient-success-bold: linear-gradient(135deg, var(--fig-color-success-400) 0%, var(--fig-color-success-700) 100%);
  --fig-bg-gradient-warning-bold: linear-gradient(135deg, var(--fig-color-warning-400) 0%, var(--fig-color-warning-700) 100%);
  --fig-bg-gradient-danger-bold: linear-gradient(135deg, var(--fig-color-danger-400) 0%, var(--fig-color-danger-700) 100%);
  /* Duotone, every cross-palette brand pair (4 colors × C(4,2) = 6 pairs) */
  --fig-bg-gradient-primary-secondary: linear-gradient(135deg, var(--fig-color-primary-500) 0%, var(--fig-color-secondary-500) 100%);
  --fig-bg-gradient-primary-tertiary: linear-gradient(135deg, var(--fig-color-primary-500) 0%, var(--fig-color-tertiary-500) 100%);
  --fig-bg-gradient-primary-accent: linear-gradient(135deg, var(--fig-color-primary-500) 0%, var(--fig-color-accent-500) 100%);
  --fig-bg-gradient-secondary-tertiary: linear-gradient(135deg, var(--fig-color-secondary-500) 0%, var(--fig-color-tertiary-500) 100%);
  --fig-bg-gradient-secondary-accent: linear-gradient(135deg, var(--fig-color-secondary-500) 0%, var(--fig-color-accent-500) 100%);
  --fig-bg-gradient-tertiary-accent: linear-gradient(135deg, var(--fig-color-tertiary-500) 0%, var(--fig-color-accent-500) 100%);
  /* Radial spotlights, off-center focal for illustrative surfaces */
  --fig-bg-gradient-radial-primary: radial-gradient(circle at 30% 30%, var(--fig-color-primary-300) 0%, var(--fig-color-primary-700) 100%);
  --fig-bg-gradient-radial-secondary: radial-gradient(circle at 30% 30%, var(--fig-color-secondary-300) 0%, var(--fig-color-secondary-700) 100%);
  --fig-bg-gradient-radial-tertiary: radial-gradient(circle at 30% 30%, var(--fig-color-tertiary-300) 0%, var(--fig-color-tertiary-700) 100%);
  --fig-bg-gradient-radial-accent: radial-gradient(circle at 30% 30%, var(--fig-color-accent-300) 0%, var(--fig-color-accent-700) 100%);
  /* Brand, multi-stop sweeps that carry the full palette in one surface */
  --fig-bg-gradient-brand-cool: linear-gradient(135deg, var(--fig-color-primary-500) 0%, var(--fig-color-secondary-500) 50%, var(--fig-color-tertiary-500) 100%);
  --fig-bg-gradient-brand-full: linear-gradient(135deg, var(--fig-color-primary-500) 0%, var(--fig-color-secondary-500) 33%, var(--fig-color-tertiary-500) 66%, var(--fig-color-accent-500) 100%);
  /* Amorphous, overlapping radial blobs for landing / hero surfaces.
     Five variants from light to dark, each with a dominant color personality. */
  /* amorphous: light, airy, all five palette tints on neutral base */
  --fig-bg-gradient-amorphous:
    radial-gradient(ellipse 80% 60% at 15% 20%, color-mix(in srgb, var(--fig-color-primary-200) 40%, transparent) 0%, transparent 70%),
    radial-gradient(ellipse 60% 80% at 75% 15%, color-mix(in srgb, var(--fig-color-secondary-200) 35%, transparent) 0%, transparent 65%),
    radial-gradient(ellipse 50% 50% at 50% 60%, color-mix(in srgb, var(--fig-color-tertiary-100) 30%, transparent) 0%, transparent 60%),
    radial-gradient(ellipse 70% 50% at 85% 75%, color-mix(in srgb, var(--fig-color-accent-200) 25%, transparent) 0%, transparent 65%),
    radial-gradient(ellipse 90% 40% at 30% 85%, color-mix(in srgb, var(--fig-color-neutral-100) 20%, transparent) 0%, transparent 55%),
    var(--fig-color-neutral-000);
  /* amorphous-deep: navy dominant, dusty violet + warm teal flecks, muted neutral base */
  --fig-bg-gradient-amorphous-deep:
    radial-gradient(ellipse 90% 70% at 40% 40%, color-mix(in srgb, var(--fig-color-primary-300) 65%, transparent) 0%, transparent 70%),
    radial-gradient(ellipse 60% 60% at 80% 20%, color-mix(in srgb, var(--fig-color-tertiary-300) 40%, transparent) 0%, transparent 60%),
    radial-gradient(ellipse 50% 70% at 15% 75%, color-mix(in srgb, var(--fig-color-secondary-300) 25%, transparent) 0%, transparent 55%),
    radial-gradient(ellipse 40% 40% at 70% 80%, color-mix(in srgb, var(--fig-color-accent-300) 20%, transparent) 0%, transparent 50%),
    var(--fig-color-primary-100);
  /* amorphous-ocean: teal-primary blend, cool and expansive */
  --fig-bg-gradient-amorphous-ocean:
    radial-gradient(ellipse 80% 80% at 30% 30%, color-mix(in srgb, var(--fig-color-primary-200) 50%, transparent) 0%, transparent 70%),
    radial-gradient(ellipse 70% 60% at 70% 50%, color-mix(in srgb, var(--fig-color-secondary-200) 45%, transparent) 0%, transparent 65%),
    radial-gradient(ellipse 50% 50% at 50% 80%, color-mix(in srgb, var(--fig-color-accent-200) 30%, transparent) 0%, transparent 55%),
    radial-gradient(ellipse 40% 40% at 90% 10%, color-mix(in srgb, var(--fig-color-tertiary-100) 15%, transparent) 0%, transparent 45%),
    var(--fig-color-neutral-000);
  /* amorphous-dusk: violet dominant with warm primary undertones */
  --fig-bg-gradient-amorphous-dusk:
    radial-gradient(ellipse 85% 70% at 55% 35%, color-mix(in srgb, var(--fig-color-tertiary-300) 55%, transparent) 0%, transparent 70%),
    radial-gradient(ellipse 70% 60% at 20% 60%, color-mix(in srgb, var(--fig-color-primary-300) 45%, transparent) 0%, transparent 65%),
    radial-gradient(ellipse 45% 50% at 85% 75%, color-mix(in srgb, var(--fig-color-accent-200) 25%, transparent) 0%, transparent 50%),
    radial-gradient(ellipse 35% 35% at 10% 15%, color-mix(in srgb, var(--fig-color-secondary-200) 15%, transparent) 0%, transparent 45%),
    var(--fig-color-primary-000);
  /* amorphous-midnight: deep navy-violet, dark mood, accent sparks */
  --fig-bg-gradient-amorphous-midnight:
    radial-gradient(ellipse 90% 80% at 35% 45%, color-mix(in srgb, var(--fig-color-primary-500) 70%, transparent) 0%, transparent 75%),
    radial-gradient(ellipse 60% 70% at 75% 25%, color-mix(in srgb, var(--fig-color-tertiary-400) 45%, transparent) 0%, transparent 60%),
    radial-gradient(ellipse 40% 40% at 15% 80%, color-mix(in srgb, var(--fig-color-secondary-400) 20%, transparent) 0%, transparent 50%),
    radial-gradient(ellipse 30% 30% at 85% 85%, color-mix(in srgb, var(--fig-color-accent-400) 15%, transparent) 0%, transparent 40%),
    var(--fig-color-primary-400);
  /* Sheen overlays, alpha gradients designed to composite OVER a colored
     background (solid or gradient). Different from `bg-gradient-*` above:
     those are opaque color gradients replacing bg; these are light/dark
     alpha overlays stacked on top (typically via a ::before layer) to add
     3D lighting without hiding the underlying color. Consumed by
     fig-button[data-style="beveled" | "neumorphic"]. Reusable by any future
     style that wants the same optical lighting without re-deriving rgba. */
  --fig-bg-sheen-bevel: linear-gradient(to bottom, rgb(255 255 255 / 0.22) 0%, rgb(0 0 0 / 0.12) 100%);
  --fig-bg-sheen-bevel-pressed: linear-gradient(to bottom, rgb(0 0 0 / 0.10) 0%, rgb(255 255 255 / 0.10) 100%);
  --fig-bg-sheen-neumorphic: linear-gradient(145deg, rgb(255 255 255 / 0.12) 0%, rgb(0 0 0 / 0.10) 100%);
  --fig-bg-sheen-glassy: linear-gradient(to bottom, rgb(255 255 255 / 0.30) 0%, rgb(255 255 255 / 0) 55%, rgb(0 0 0 / 0.12) 100%);
  /* Background, filled emphasis roles (paired with fg-on-* for contrast) */
  --fig-bg-emphasis: var(--fig-color-primary-500); /* navy, primary buttons, nav active */
  --fig-bg-emphasis-hover: var(--fig-color-primary-600);
  --fig-bg-secondary: var(--fig-color-secondary-500); /* teal, secondary buttons */
  --fig-bg-secondary-hover: var(--fig-color-secondary-600);
  --fig-bg-danger: var(--fig-color-danger-500); /* filled red, destructive buttons */
  --fig-bg-danger-hover: var(--fig-color-danger-600);
  --fig-bg-success: var(--fig-color-success-500); /* filled green */
  --fig-bg-success-hover: var(--fig-color-success-600);
  --fig-bg-warning: var(--fig-color-warning-500); /* filled amber */
  --fig-bg-warning-hover: var(--fig-color-warning-600);
  --fig-bg-accent: var(--fig-color-accent-600); /* filled sky blue, -600 for AA contrast with white fg (sky-500 marginal at 4.2:1) */
  --fig-bg-accent-hover: var(--fig-color-accent-700);
  --fig-bg-tertiary: var(--fig-color-tertiary-500); /* filled violet, project-type surfaces (mention chip, project cards) */
  /* Inverse, for data-invert primitives (Box §5.2) */
  --fig-fg-inverse: var(--fig-color-neutral-000); /* light text for dark bg */
  --fig-bg-inverse: var(--fig-color-neutral-900); /* dark bg for light text */
  /* Border */
  --fig-border-default: var(--fig-color-neutral-200);
  --fig-border-muted: var(--fig-color-neutral-200);
  --fig-border-emphasis: var(--fig-color-neutral-400);
  /* Accent (sky blue), NOT USED in active UI. Sky blue palette primitives stay
     shipped (may be used in charts, illustrations, or future surfaces), but
     no component should reference these semantic tokens right now. Navy
     primary + teal secondary carry the full interactive system.
     Kept here for forward-compat; flag for removal if still unused after
     the next major surface lands. */
  --fig-accent-fg: var(--fig-color-accent-500);
  --fig-accent-bg: var(--fig-color-accent-500);
  --fig-accent-bg-subtle: var(--fig-color-accent-000); /* soft tint, drag-over states, light accent fills */
  --fig-accent-border: var(--fig-color-accent-500);
  --fig-accent-hover: var(--fig-color-accent-600);
  --fig-accent-active: var(--fig-color-accent-700);
  /* Secondary (teal), general-purpose non-primary interactive + default
     "brand teal" presence. Links, focus rings, spinner accents, info
     banners, subtle-accent gradients all pull from here. Pairs with primary
     (navy, bg-emphasis) for two-tier interactive hierarchies.

     Anchored at -500 across fg/border/bg for consistency with every other
     brand palette. Hover steps one darker (-600), active two (-700). */
  --fig-secondary-fg: var(--fig-color-secondary-500);
  --fig-secondary-border: var(--fig-color-secondary-500);
  --fig-secondary-hover: var(--fig-color-secondary-600);
  --fig-secondary-active: var(--fig-color-secondary-700);
  /* Status families. Role rule: -fg is TEXT INK ONLY (light rungs are darkened
     for AA contrast; darkened amber loses its hue and reads brick). Anything
     painted as a solid fill or decoration (dots, bars, strong borders/rings
     meant to read as the status colour) uses the --fig-bg-<status> fill
     anchors above, which hold apparent hue in both themes. */
  /* Status, danger */
  --fig-status-danger-fg: var(--fig-color-danger-700);
  --fig-status-danger-bg: var(--fig-color-danger-000);
  --fig-status-danger-border: var(--fig-color-danger-200);
  /* Status, warning */
  --fig-status-warning-fg: var(--fig-color-warning-700);
  --fig-status-warning-bg: var(--fig-color-warning-000);
  --fig-status-warning-border: var(--fig-color-warning-200);
  /* Status, success */
  --fig-status-success-fg: var(--fig-color-success-700);
  --fig-status-success-bg: var(--fig-color-success-000);
  --fig-status-success-border: var(--fig-color-success-200);
  /* Status, info (teal, to keep accent reserved for links) */
  --fig-status-info-fg: var(--fig-color-secondary-700);
  --fig-status-info-bg: var(--fig-color-secondary-000);
  /* Status, neutral (default soft surface for toasts / callouts before
     a severity is assigned). Completes the status family so neutral soft
     surfaces theme-flip alongside success/warning/danger. */
  --fig-status-neutral-fg: var(--fig-color-neutral-700);
  --fig-status-neutral-bg: var(--fig-color-neutral-000);
  --fig-status-neutral-border: var(--fig-color-neutral-200);
  /* Status, scheduled (sky-blue rail for healthy scheduled flows/boards on the
     project-graph canvas). Sources from the accent palette, sky blue anchor at
     accent-500 (#76c3f9). Triad mirrors success/warning/danger; ring extends the
     family for pulse animations. */
  --fig-status-scheduled-fg: var(--fig-color-accent-600);
  --fig-status-scheduled-bg: var(--fig-color-accent-000);
  --fig-status-scheduled-border: var(--fig-color-accent-400);
  --fig-status-scheduled-ring: color-mix(in srgb, var(--fig-color-accent-500) 18%, transparent);
  /* Status pulse rings, soft alpha mixes for keyframe glow halos. Replace
     hardcoded rgba() in graph-canvas + node-card pulse animations. Same 18%
     mix anchor across severities so animations share a single tunable. */
  --fig-status-success-ring: color-mix(in srgb, var(--fig-color-success-500) 18%, transparent);
  --fig-status-danger-ring: color-mix(in srgb, var(--fig-color-danger-500) 18%, transparent);
  --fig-status-warning-ring: color-mix(in srgb, var(--fig-color-warning-500) 18%, transparent);
  /* Semantic, pivot field categories (Excel parlance: dimension = category
     axis, metric = numeric value). Used by fig-field-list to color-code each
     section + its draggable items. Dimension borrows the tertiary (violet)
     palette; metric borrows the success (green) palette. Three shades per
     role: bg (section tint), border (item outline / hover), fg (label). */
  --fig-dimension-bg: var(--fig-color-tertiary-000);
  --fig-dimension-border: var(--fig-color-tertiary-300);
  --fig-dimension-fg: var(--fig-color-tertiary-700);
  --fig-metric-bg: var(--fig-color-success-000);
  --fig-metric-border: var(--fig-color-success-300);
  --fig-metric-fg: var(--fig-color-success-700);
}

/*============ Dark (explicit toggle OR system preference) ============

Inverted foreground/background. Accent and status foregrounds brighten
(saturation holds, lightness bumps) for readability on dark surfaces.
Accent background stays at the brand anchor so CTAs feel consistent.

Both selectors list separately (not grouped with comma) so each is a
complete override, if the user explicitly toggles to `light` via
`data-theme="light"`, the media-query block below does not apply. */
[data-theme=dark] {
  --fig-fg-default: var(--fig-color-neutral-000);
  --fig-fg-muted: var(--fig-color-neutral-300);
  --fig-fg-subtle: var(--fig-color-neutral-500);
  --fig-fg-on-accent: var(--fig-color-generic-white);
  --fig-fg-on-tertiary: var(--fig-color-tertiary-900);
  --fig-fg-on-emphasis: var(--fig-color-generic-white);
  --fig-fg-on-secondary: var(--fig-color-generic-white);
  --fig-fg-on-danger: var(--fig-color-generic-white);
  --fig-fg-on-success: var(--fig-color-generic-white);
  --fig-fg-on-warning: var(--fig-color-neutral-900);
  --fig-bg-default: var(--fig-color-neutral-900);
  --fig-bg-subtle: var(--fig-color-neutral-800);
  --fig-bg-muted: var(--fig-color-neutral-700);
  --fig-bg-tint: color-mix(in srgb, var(--fig-color-neutral-700) 50%, transparent);
  --fig-bg-overlay: rgb(0 0 0 / 0.7);
  --fig-bg-overlay-glass: rgb(20 19 13 / 0.72); /* glass panel on dark canvas, neutral-900 raw @ 72%, less opaque than modal overlay so backdrop-blur reads */
  --fig-bg-gradient-subtle: linear-gradient(135deg, var(--fig-color-neutral-900) 0%, var(--fig-color-neutral-800) 100%);
  --fig-bg-gradient-primary-light: linear-gradient(135deg, var(--fig-color-primary-900) 0%, var(--fig-color-primary-700) 100%);
  --fig-bg-gradient-secondary-light: linear-gradient(135deg, var(--fig-color-secondary-900) 0%, var(--fig-color-secondary-700) 100%);
  --fig-bg-gradient-tertiary-light: linear-gradient(135deg, var(--fig-color-tertiary-900) 0%, var(--fig-color-tertiary-700) 100%);
  --fig-bg-gradient-accent-light: linear-gradient(135deg, var(--fig-color-accent-900) 0%, var(--fig-color-accent-700) 100%);
  --fig-bg-gradient-neutral-light: linear-gradient(135deg, var(--fig-color-neutral-900) 0%, var(--fig-color-neutral-700) 100%);
  --fig-bg-gradient-success-light: linear-gradient(135deg, var(--fig-color-success-900) 0%, var(--fig-color-success-700) 100%);
  --fig-bg-gradient-warning-light: linear-gradient(135deg, var(--fig-color-warning-900) 0%, var(--fig-color-warning-700) 100%);
  --fig-bg-gradient-danger-light: linear-gradient(135deg, var(--fig-color-danger-900) 0%, var(--fig-color-danger-700) 100%);
  --fig-bg-gradient-primary-bold: linear-gradient(135deg, var(--fig-color-primary-600) 0%, var(--fig-color-primary-300) 100%);
  --fig-bg-gradient-secondary-bold: linear-gradient(135deg, var(--fig-color-secondary-600) 0%, var(--fig-color-secondary-300) 100%);
  --fig-bg-gradient-tertiary-bold: linear-gradient(135deg, var(--fig-color-tertiary-600) 0%, var(--fig-color-tertiary-300) 100%);
  --fig-bg-gradient-accent-bold: linear-gradient(135deg, var(--fig-color-accent-600) 0%, var(--fig-color-accent-300) 100%);
  --fig-bg-gradient-neutral-bold: linear-gradient(135deg, var(--fig-color-neutral-600) 0%, var(--fig-color-neutral-300) 100%);
  --fig-bg-gradient-success-bold: linear-gradient(135deg, var(--fig-color-success-600) 0%, var(--fig-color-success-300) 100%);
  --fig-bg-gradient-warning-bold: linear-gradient(135deg, var(--fig-color-warning-600) 0%, var(--fig-color-warning-300) 100%);
  --fig-bg-gradient-danger-bold: linear-gradient(135deg, var(--fig-color-danger-600) 0%, var(--fig-color-danger-300) 100%);
  --fig-bg-gradient-primary-secondary: linear-gradient(135deg, var(--fig-color-primary-400) 0%, var(--fig-color-secondary-400) 100%);
  --fig-bg-gradient-primary-tertiary: linear-gradient(135deg, var(--fig-color-primary-400) 0%, var(--fig-color-tertiary-400) 100%);
  --fig-bg-gradient-primary-accent: linear-gradient(135deg, var(--fig-color-primary-400) 0%, var(--fig-color-accent-400) 100%);
  --fig-bg-gradient-secondary-tertiary: linear-gradient(135deg, var(--fig-color-secondary-400) 0%, var(--fig-color-tertiary-400) 100%);
  --fig-bg-gradient-secondary-accent: linear-gradient(135deg, var(--fig-color-secondary-400) 0%, var(--fig-color-accent-400) 100%);
  --fig-bg-gradient-tertiary-accent: linear-gradient(135deg, var(--fig-color-tertiary-400) 0%, var(--fig-color-accent-400) 100%);
  --fig-bg-gradient-radial-primary: radial-gradient(circle at 30% 30%, var(--fig-color-primary-500) 0%, var(--fig-color-primary-900) 100%);
  --fig-bg-gradient-radial-secondary: radial-gradient(circle at 30% 30%, var(--fig-color-secondary-500) 0%, var(--fig-color-secondary-900) 100%);
  --fig-bg-gradient-radial-tertiary: radial-gradient(circle at 30% 30%, var(--fig-color-tertiary-500) 0%, var(--fig-color-tertiary-900) 100%);
  --fig-bg-gradient-radial-accent: radial-gradient(circle at 30% 30%, var(--fig-color-accent-500) 0%, var(--fig-color-accent-900) 100%);
  --fig-bg-gradient-brand-cool: linear-gradient(135deg, var(--fig-color-primary-400) 0%, var(--fig-color-secondary-400) 50%, var(--fig-color-tertiary-400) 100%);
  --fig-bg-gradient-brand-full: linear-gradient(135deg, var(--fig-color-primary-400) 0%, var(--fig-color-secondary-400) 33%, var(--fig-color-tertiary-400) 66%, var(--fig-color-accent-400) 100%);
  /* Sheen overlays, same alpha values as light theme; overlays are
     tone-agnostic since they composite over whatever color sits below. */
  --fig-bg-sheen-bevel: linear-gradient(to bottom, rgb(255 255 255 / 0.22) 0%, rgb(0 0 0 / 0.12) 100%);
  --fig-bg-sheen-bevel-pressed: linear-gradient(to bottom, rgb(0 0 0 / 0.10) 0%, rgb(255 255 255 / 0.10) 100%);
  --fig-bg-sheen-neumorphic: linear-gradient(145deg, rgb(255 255 255 / 0.12) 0%, rgb(0 0 0 / 0.10) 100%);
  --fig-bg-sheen-glassy: linear-gradient(to bottom, rgb(255 255 255 / 0.30) 0%, rgb(255 255 255 / 0) 55%, rgb(0 0 0 / 0.12) 100%);
  --fig-bg-emphasis: var(--fig-color-primary-500);
  --fig-bg-emphasis-hover: var(--fig-color-primary-400);
  --fig-bg-secondary: var(--fig-color-secondary-500);
  --fig-bg-secondary-hover: var(--fig-color-secondary-400);
  --fig-bg-danger: var(--fig-color-danger-500);
  --fig-bg-danger-hover: var(--fig-color-danger-400);
  --fig-bg-success: var(--fig-color-success-500);
  --fig-bg-success-hover: var(--fig-color-success-400);
  --fig-bg-warning: var(--fig-color-warning-500);
  --fig-bg-warning-hover: var(--fig-color-warning-400);
  --fig-bg-accent: var(--fig-color-accent-600);
  --fig-bg-accent-hover: var(--fig-color-accent-500);
  --fig-bg-tertiary: var(--fig-color-tertiary-500);
  --fig-fg-inverse: var(--fig-color-neutral-900);
  --fig-bg-inverse: var(--fig-color-neutral-000);
  --fig-border-default: var(--fig-color-neutral-700);
  --fig-border-muted: var(--fig-color-neutral-700);
  --fig-border-emphasis: var(--fig-color-neutral-500);
  --fig-accent-fg: var(--fig-color-accent-400);
  --fig-accent-bg: var(--fig-color-accent-500);
  --fig-accent-bg-subtle: var(--fig-color-accent-900);
  --fig-accent-border: var(--fig-color-accent-400);
  --fig-accent-hover: var(--fig-color-accent-400);
  --fig-accent-active: var(--fig-color-accent-300);
  --fig-secondary-fg: var(--fig-color-secondary-400);
  --fig-secondary-border: var(--fig-color-secondary-400);
  --fig-secondary-hover: var(--fig-color-secondary-400);
  --fig-secondary-active: var(--fig-color-secondary-300);
  --fig-status-danger-fg: var(--fig-color-danger-400);
  --fig-status-danger-bg: var(--fig-color-danger-900);
  --fig-status-danger-border: var(--fig-color-danger-700);
  --fig-status-warning-fg: var(--fig-color-warning-400);
  --fig-status-warning-bg: var(--fig-color-warning-900);
  --fig-status-warning-border: var(--fig-color-warning-700);
  --fig-status-success-fg: var(--fig-color-success-400);
  --fig-status-success-bg: var(--fig-color-success-900);
  --fig-status-success-border: var(--fig-color-success-700);
  --fig-status-info-fg: var(--fig-color-secondary-400);
  --fig-status-info-bg: var(--fig-color-secondary-900);
  --fig-status-neutral-fg: var(--fig-color-neutral-300);
  --fig-status-neutral-bg: var(--fig-color-neutral-800);
  --fig-status-neutral-border: var(--fig-color-neutral-700);
  --fig-status-scheduled-fg: var(--fig-color-accent-400);
  --fig-status-scheduled-bg: var(--fig-color-accent-900);
  --fig-status-scheduled-border: var(--fig-color-accent-700);
  --fig-status-scheduled-ring: color-mix(in srgb, var(--fig-color-accent-500) 18%, transparent);
  --fig-status-success-ring: color-mix(in srgb, var(--fig-color-success-500) 18%, transparent);
  --fig-status-danger-ring: color-mix(in srgb, var(--fig-color-danger-500) 18%, transparent);
  --fig-status-warning-ring: color-mix(in srgb, var(--fig-color-warning-500) 18%, transparent);
  --fig-dimension-bg: var(--fig-color-tertiary-900);
  --fig-dimension-border: var(--fig-color-tertiary-700);
  --fig-dimension-fg: var(--fig-color-tertiary-300);
  --fig-metric-bg: var(--fig-color-success-900);
  --fig-metric-border: var(--fig-color-success-700);
  --fig-metric-fg: var(--fig-color-success-300);
}

/* fig-globals, composition layer (CUBE C), spec: fig/styles/CLAUDE §"_fig-globals.scss inventory" */
/*============ §2, box-sizing axiom ============*/
*,
*::before,
*::after {
  box-sizing: border-box;
}

/*============ §2, :root inherited defaults ============*/
/* Global UI scale. Re-prices the rem unit every token is denominated in
   (text, space, container scales alike), so the whole surface renders at
   13/16 of browser-default size, the dense-B2B norm (13px body). A raw
   percentage is NOT the forbidden pattern warned about below `:root`: that
   ban is on rem-BASED tokens re-anchoring themselves (circular). Percentage
   stays relative to the user's browser font-size preference. */
html {
  font-size: 81.25%;
}

:root {
  font-family: var(--fig-font-family-sans);
  line-height: var(--fig-line-height-body);
  color: var(--fig-fg-default);
  /* Page surface, paints the viewport even when <body> is shorter than the
     viewport (otherwise the browser default white bleeds in below body). */
  background-color: var(--fig-bg-default);
}

/* Body default font-size MUST live on `body`, not `:root`. Setting
   `font-size` on `:root` using a rem-based token re-anchors `1rem` to the
   bumped root size, every downstream `var(--fig-text-*)` then re-clamps,
   compounding the type scale ~20% larger than intended and zooming the
   whole fig surface relative to 1.0 (which uses rem-fixed tokens). Body
   inheritance gives the same reading size without remapping the rem unit
   globally. */
body {
  margin: 0;
  font-size: var(--fig-text-3);
  background-color: var(--fig-bg-default);
  color: var(--fig-fg-default);
  /* Container scope for blocks that want @container-driven responsive layout
     (e.g. fig-nav collapsing brand+tabs into two rows below the threshold).
     Single named container "app" keeps queries unambiguous and discoverable. */
  container-type: inline-size;
  container-name: app;
  /* Kill the spurious document-level horizontal scrollbar. Full-bleed blocks
     (.fig-table-scroll[data-bleed]) reach the viewport edges via
     `margin-inline: calc(50% - 50vw)`; when the vertical scrollbar takes layout
     width, 50vw (scrollbar-inclusive) overshoots the content half-width (50%,
     scrollbar-exclusive) by ~one scrollbar, pushing the block a few px past each
     edge. `clip` trims that overshoot without becoming a scroll container, so
     vertical scroll (on <html>) and `position: sticky` descendants are untouched;
     a too-wide table still scrolls inside its own `overflow-x: auto` wrapper. */
  overflow-x: clip;
}

/*============ Heading element defaults (sparknotes Ch. 4) ============*/
h1, h2, h3, h4, h5, h6, p {
  margin: 0;
}

h1 {
  font-size: var(--fig-text-8);
  line-height: var(--fig-line-height-tight);
  letter-spacing: var(--fig-letter-spacing-tight);
  font-weight: var(--fig-font-weight-bold);
}

h2 {
  font-size: var(--fig-text-7);
  line-height: var(--fig-line-height-snug);
  letter-spacing: var(--fig-letter-spacing-tight);
  font-weight: var(--fig-font-weight-bold);
}

h3 {
  font-size: var(--fig-text-6);
  line-height: var(--fig-line-height-snug);
  letter-spacing: var(--fig-letter-spacing-tight);
  font-weight: var(--fig-font-weight-semibold);
}

h4 {
  font-size: var(--fig-text-5);
  line-height: var(--fig-line-height-snug);
  font-weight: var(--fig-font-weight-semibold);
}

h5 {
  font-size: var(--fig-text-4);
  line-height: var(--fig-line-height-snug);
  font-weight: var(--fig-font-weight-semibold);
}

h6 {
  font-size: var(--fig-text-3);
  line-height: var(--fig-line-height-snug);
  font-weight: var(--fig-font-weight-semibold);
  letter-spacing: var(--fig-letter-spacing-wide);
  text-transform: uppercase;
}

/*============ Code / pre / kbd / samp element defaults ============*/
code,
pre,
kbd,
samp {
  font-family: var(--fig-font-family-mono);
  font-weight: var(--fig-font-weight-medium);
}

/*============ Anchor element default ============*/
a {
  color: var(--fig-secondary-fg);
  text-decoration: none;
}

/*============ Ordered list default (logical property) ============*/
ol {
  padding-inline-start: var(--fig-space-4);
  list-style-type: decimal;
}

/*============ Scrollbars hidden by default, opt in via data-scrollbar="visible" ============*/
* {
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* IE/Edge */
}

*::-webkit-scrollbar {
  display: none; /* Chrome / Safari / WebKit */
}

[data-scrollbar=visible] {
  scrollbar-width: auto;
  -ms-overflow-style: auto;
}

[data-scrollbar=visible]::-webkit-scrollbar {
  display: block;
}

/*============ Alpine.js bootstrap, x-cloak hides x-cloak'd elements until hydrated ============*/
[x-cloak] {
  display: none !important;
}

/*============ §9, prefers-reduced-motion global honor ============*/
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition: none !important;
    animation: none !important;
  }
}
/* <fig-stack-layout>, spec: fig/styles/primitives/fig-stack-layout.md, edit via /design:create-or-update-primitive */
fig-stack-layout {
  display: flex;
  flex-direction: column;
}

fig-stack-layout > * + * {
  margin-block-start: var(--fig-space-3);
}

/* <fig-box-layout>, spec: fig/styles/primitives/fig-box-layout.md, edit via /design:create-or-update-primitive */
/* Tag-selector base, reliable whether or not the JS runtime has upgraded
   the element yet. The JS emits per-instance `[data-i="iBox-..."]` rules
   (specificity 0,0,1,0) that override properties it sets (padding, border-
   width); this block's defaults fill in everything else.

   BG + border are both transparent / zero by default (fig deviation from
   Every Layout's original Box spec which sets bg-subtle + 1px border).
   Rationale: consumers that want a filled or bordered box opt in explicitly
  , via utility class (.fig-bg-gradient:*, a future .fig-bg:subtle), the
   `border-width` primitive attr (e.g. <fig-box-layout border-width="1">),
   or a data-attribute variant (data-invert). This keeps nested box
   compositions from stacking opaque surfaces by accident and lets boxes
   sit cleanly on top of decorative backdrops (fig-backdrop).

   border-color stays defined so any consumer that opts in to a border just
   needs to set border-width; they get the design-system border color free. */
fig-box-layout {
  display: block;
  padding: var(--fig-space-3);
  border: 0 solid var(--fig-border-default);
  border-radius: var(--fig-border-radius-4);
  outline: 1px solid transparent;
  outline-offset: -1px;
  color: var(--fig-fg-default);
  background-color: transparent;
}

fig-box-layout * {
  color: inherit;
}

fig-box-layout[data-invert] {
  color: var(--fig-fg-inverse);
  background-color: var(--fig-bg-inverse);
}

/* Content-alignment exceptions, flip box to flex column and align its
   direct children on one or both axes. Useful when the box stretches to
   match a sibling's height (inside fig-switcher-layout or fig-sidebar-layout)
   and its contents should sit centered rather than hugging a corner.

   `center`           , both axes (most common; mirrors CSS `place-content: center`)
   `center-vertical`  , vertical only (content centered top-to-bottom, natural horizontal)
   `center-horizontal`, horizontal only (content centered left-to-right, hugs top)

   Names are spelled out per fig naming rule (no `v-`/`h-` abbreviations).

   Uses tag selector instead of [data-i^="Box-"] because the JS runtime
   writes `data-i="iBox-..."` not `"Box-..."`, tag selector is reliable
   across both the static-fallback and runtime-written cases. */
fig-box-layout[data-align=center],
fig-box-layout[data-align=center-vertical],
fig-box-layout[data-align=center-horizontal] {
  display: flex;
  flex-direction: column;
}

fig-box-layout[data-align=center],
fig-box-layout[data-align=center-vertical] {
  justify-content: center; /* main axis (vertical for column flex) */
}

fig-box-layout[data-align=center],
fig-box-layout[data-align=center-horizontal] {
  align-items: center; /* cross axis (horizontal for column flex) */
}

/* <fig-center-layout>, spec: fig/styles/primitives/fig-center-layout.md, edit via /design:create-or-update-primitive */
fig-center-layout {
  display: block;
  box-sizing: content-box;
  max-inline-size: var(--fig-typographic-measure);
  margin-inline: auto;
  padding-inline: var(--fig-space-3);
}

/* Standard page-width options. The bare default (no attr) keeps the prose
   measure for text pages; app/content pages declare width via `max=` instead of
   one-off `--fig-typographic-measure` overrides in px/rem/ch. Three options only:
     5    → 1024px  content column (reading, chat, forms, detail pages)
     7    → 1600px  dashboards (bounded multi-column grids + charts)
     full → 100%    full-bleed data pages (wide tables, card grids) */
fig-center-layout[max="5"] {
  --fig-typographic-measure: var(--fig-container-5);
}

fig-center-layout[max="7"] {
  --fig-typographic-measure: var(--fig-container-7);
}

fig-center-layout[max=full] {
  max-inline-size: none;
  box-sizing: border-box;
}

/* <fig-cluster-layout>, spec: fig/styles/primitives/fig-cluster-layout.md, edit via /design:create-or-update-primitive */
fig-cluster-layout {
  display: flex;
  flex-wrap: wrap;
  gap: var(--fig-space-3);
  justify-content: var(--fig-cluster-justify, flex-start);
  align-items: center;
  /* Neutralize HTML's legacy `align="center"` UA-stylesheet → text-align: center
     leak. Cluster's primitive API uses `align=` for cross-axis flex alignment;
     without this reset, every cluster child inherits centered text. 🦕 */
  text-align: start;
}

/* justify, main-axis distribution. Mirrors fig-app's cluster-layout, but only
   this one attribute is wired in the subset so far: no command-center cluster
   passes `justify=` today, so enabling it ripples nothing. `space=`/`align=` are
   wired upstream too, yet every cluster here passes one of them, adopting them
   needs an app-wide visual pass first, so they stay deferred (tracked drift from
   fig-app, not a new divergence). */
fig-cluster-layout[justify=flex-start] {
  --fig-cluster-justify: flex-start;
}

fig-cluster-layout[justify=flex-end] {
  --fig-cluster-justify: flex-end;
}

fig-cluster-layout[justify=center] {
  --fig-cluster-justify: center;
}

fig-cluster-layout[justify=space-between] {
  --fig-cluster-justify: space-between;
}

fig-cluster-layout[justify=space-around] {
  --fig-cluster-justify: space-around;
}

fig-cluster-layout[justify=space-evenly] {
  --fig-cluster-justify: space-evenly;
}

fig-cluster-layout[justify=start] {
  --fig-cluster-justify: start;
}

fig-cluster-layout[justify=end] {
  --fig-cluster-justify: end;
}

fig-cluster-layout[justify=stretch] {
  --fig-cluster-justify: stretch;
}

/* <fig-grid-layout>, spec: fig/styles/primitives/fig-grid-layout.md, edit via /design:create-or-update-primitive
   figclaw divergence from fig-app's responsive auto-fill grid: this surface
   wants a fixed three-up row (the catalog grid spans the full content width, so
   auto-fill would pack 6+ columns). Three columns on desktop, collapsing to two
   then one as the viewport narrows. */
fig-grid-layout {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--fig-space-3);
}

@media (max-width: 60rem) {
  fig-grid-layout {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 40rem) {
  fig-grid-layout {
    grid-template-columns: minmax(0, 1fr);
  }
}
/* Equal-height cards in a row: stretch each card to the tallest in its row
   (grid default) and let the body absorb the slack so footers, the Subscribe
   action row, line up across the row regardless of description length. */
fig-grid-layout > .fig-card {
  display: flex;
  flex-direction: column;
}

fig-grid-layout > .fig-card > .fig-card-body {
  flex: 1;
}

/* <fig-sidebar-layout>, spec: fig/styles/primitives/fig-sidebar-layout.md, edit via /design:create-or-update-primitive */
/* Every Layout's Sidebar: two columns that collapse to one *intrinsically*, the
   content column carries a min-inline-size, so the row wraps (sidebar above
   content) the moment content would drop below that min. No viewport @media, no
   breakpoint: the same component is correct in a 320px panel or a 1440px page. */
fig-sidebar-layout {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--fig-sidebar-gap, var(--fig-space-6));
}

/* The sidebar column: sizes to --fig-sidebar-side-width (content-sized if unset),
   grows to absorb slack on the wide layout. */
fig-sidebar-layout > :first-child {
  flex-basis: var(--fig-sidebar-side-width, auto);
  flex-grow: 1;
}

/* The content column: grows hugely + holds a min so it triggers the wrap. */
fig-sidebar-layout > :last-child {
  flex-basis: 0;
  flex-grow: 999;
  min-inline-size: var(--fig-sidebar-content-min, 50%);
}

/* <fig-scroll-fade-layout>, spec: fig/styles/primitives/fig-scroll-fade-layout.md, edit via /design:create-or-update-primitive */
/* Every Layout's only genuinely-dynamic layout primitive, it needs JS to read
   scroll position + a ResizeObserver to toggle which edges are faded. But the
   BASE mask geometry is static (here, render-blocking) instead of injected at
   runtime, so the element no longer flashes before its JS runs. The JS only flips
   `--fade-top/-bottom/-left/-right` between 0 and 1 as the user scrolls; they
   default to 0 so an unupgraded element simply shows no fade.

   `fade-size` → `--fade-size` (edge gradient length), via attribute selectors. */
:root {
  /* The prominent fade band the filter sidebar's scroll fade
     (<fig-scroll-fade-layout>) opts into. Retune here and it follows. (Distinct from
     the primitive's own --fade-size default below, the gentle space-3 a bare
     scroll-fade gets.) */
  --fig-fade-size: var(--fig-space-11);
}

fig-scroll-fade-layout {
  display: block;
  overflow: auto;
  max-inline-size: none;
  --fade-size: var(--fig-space-3);
  --fade-top: 0;
  --fade-bottom: 0;
  --fade-left: 0;
  --fade-right: 0;
  mask-image: linear-gradient(to bottom, transparent 0, black calc(var(--fade-size) * var(--fade-top)), black calc(100% - var(--fade-size) * var(--fade-bottom)), transparent 100%), linear-gradient(to right, transparent 0, black calc(var(--fade-size) * var(--fade-left)), black calc(100% - var(--fade-size) * var(--fade-right)), transparent 100%);
  mask-composite: intersect;
}

fig-scroll-fade-layout[fade-size="-4"] {
  --fade-size: var(--fig-space--4);
}

fig-scroll-fade-layout[fade-size="-3"] {
  --fade-size: var(--fig-space--3);
}

fig-scroll-fade-layout[fade-size="-2"] {
  --fade-size: var(--fig-space--2);
}

fig-scroll-fade-layout[fade-size="-1"] {
  --fade-size: var(--fig-space--1);
}

fig-scroll-fade-layout[fade-size="0"] {
  --fade-size: var(--fig-space-0);
}

fig-scroll-fade-layout[fade-size="1"] {
  --fade-size: var(--fig-space-1);
}

fig-scroll-fade-layout[fade-size="2"] {
  --fade-size: var(--fig-space-2);
}

fig-scroll-fade-layout[fade-size="3"] {
  --fade-size: var(--fig-space-3);
}

fig-scroll-fade-layout[fade-size="4"] {
  --fade-size: var(--fig-space-4);
}

fig-scroll-fade-layout[fade-size="5"] {
  --fade-size: var(--fig-space-5);
}

fig-scroll-fade-layout[fade-size="6"] {
  --fade-size: var(--fig-space-6);
}

fig-scroll-fade-layout[fade-size="7"] {
  --fade-size: var(--fig-space-7);
}

fig-scroll-fade-layout[fade-size="8"] {
  --fade-size: var(--fig-space-8);
}

fig-scroll-fade-layout[fade-size="9"] {
  --fade-size: var(--fig-space-9);
}

fig-scroll-fade-layout[fade-size="10"] {
  --fade-size: var(--fig-space-10);
}

fig-scroll-fade-layout[fade-size="11"] {
  --fade-size: var(--fig-space-11);
}

fig-scroll-fade-layout[fade-size="12"] {
  --fade-size: var(--fig-space-12);
}

/* fig-font-size utility, spec: fig/styles/utilities/fig-font-size.md, edit via /design:create-or-update-utility */
.fig-font-size\:0 {
  font-size: var(--fig-text-0) !important;
}

.fig-font-size\:1 {
  font-size: var(--fig-text-1) !important;
}

.fig-font-size\:2 {
  font-size: var(--fig-text-2) !important;
}

.fig-font-size\:3 {
  font-size: var(--fig-text-3) !important;
}

.fig-font-size\:4 {
  font-size: var(--fig-text-4) !important;
}

.fig-font-size\:5 {
  font-size: var(--fig-text-5) !important;
}

.fig-font-size\:6 {
  font-size: var(--fig-text-6) !important;
}

.fig-font-size\:7 {
  font-size: var(--fig-text-7) !important;
}

.fig-font-size\:8 {
  font-size: var(--fig-text-8) !important;
}

.fig-font-size\:9 {
  font-size: var(--fig-text-9) !important;
}

/* fig-font-weight utility, spec: fig/styles/utilities/fig-font-weight.md, edit via /design:create-or-update-utility */
.fig-font-weight\:thin {
  font-weight: var(--fig-font-weight-thin) !important;
}

.fig-font-weight\:extralight {
  font-weight: var(--fig-font-weight-extralight) !important;
}

.fig-font-weight\:light {
  font-weight: var(--fig-font-weight-light) !important;
}

.fig-font-weight\:regular {
  font-weight: var(--fig-font-weight-regular) !important;
}

.fig-font-weight\:medium {
  font-weight: var(--fig-font-weight-medium) !important;
}

.fig-font-weight\:semibold {
  font-weight: var(--fig-font-weight-semibold) !important;
}

.fig-font-weight\:bold {
  font-weight: var(--fig-font-weight-bold) !important;
}

.fig-font-weight\:extrabold {
  font-weight: var(--fig-font-weight-extrabold) !important;
}

.fig-font-weight\:black {
  font-weight: var(--fig-font-weight-black) !important;
}

/* fig-line-height utility, spec: fig/styles/utilities/fig-line-height.md, edit via /design:create-or-update-utility */
.fig-line-height\:tight {
  line-height: var(--fig-line-height-tight) !important;
}

.fig-line-height\:snug {
  line-height: var(--fig-line-height-snug) !important;
}

.fig-line-height\:body {
  line-height: var(--fig-line-height-body) !important;
}

.fig-line-height\:loose {
  line-height: var(--fig-line-height-loose) !important;
}

/* fig-text-align utility, spec: fig/styles/utilities/fig-text-align.md, edit via /design:create-or-update-utility */
.fig-text-align\:left {
  text-align: left !important;
}

.fig-text-align\:center {
  text-align: center !important;
}

.fig-text-align\:right {
  text-align: right !important;
}

.fig-text-align\:justify {
  text-align: justify !important;
}

/* fig-padding utility, spec: fig/styles/utilities/fig-padding.md, edit via /design:create-or-update-utility */
/* Full padding, steps 0-12; CSS padding can't be negative so -1/-2 not included */
.fig-padding\:0 {
  padding: var(--fig-space-0) !important;
}

.fig-padding\:1 {
  padding: var(--fig-space-1) !important;
}

.fig-padding\:2 {
  padding: var(--fig-space-2) !important;
}

.fig-padding\:3 {
  padding: var(--fig-space-3) !important;
}

.fig-padding\:4 {
  padding: var(--fig-space-4) !important;
}

.fig-padding\:5 {
  padding: var(--fig-space-5) !important;
}

.fig-padding\:6 {
  padding: var(--fig-space-6) !important;
}

.fig-padding\:7 {
  padding: var(--fig-space-7) !important;
}

.fig-padding\:8 {
  padding: var(--fig-space-8) !important;
}

.fig-padding\:9 {
  padding: var(--fig-space-9) !important;
}

.fig-padding\:10 {
  padding: var(--fig-space-10) !important;
}

.fig-padding\:11 {
  padding: var(--fig-space-11) !important;
}

.fig-padding\:12 {
  padding: var(--fig-space-12) !important;
}

/* Block (vertical) padding */
.fig-padding-block\:0 {
  padding-block: var(--fig-space-0) !important;
}

.fig-padding-block\:1 {
  padding-block: var(--fig-space-1) !important;
}

.fig-padding-block\:2 {
  padding-block: var(--fig-space-2) !important;
}

.fig-padding-block\:3 {
  padding-block: var(--fig-space-3) !important;
}

.fig-padding-block\:4 {
  padding-block: var(--fig-space-4) !important;
}

.fig-padding-block\:5 {
  padding-block: var(--fig-space-5) !important;
}

.fig-padding-block\:6 {
  padding-block: var(--fig-space-6) !important;
}

.fig-padding-block\:7 {
  padding-block: var(--fig-space-7) !important;
}

.fig-padding-block\:8 {
  padding-block: var(--fig-space-8) !important;
}

.fig-padding-block\:9 {
  padding-block: var(--fig-space-9) !important;
}

.fig-padding-block\:10 {
  padding-block: var(--fig-space-10) !important;
}

.fig-padding-block\:11 {
  padding-block: var(--fig-space-11) !important;
}

.fig-padding-block\:12 {
  padding-block: var(--fig-space-12) !important;
}

/* Inline (horizontal) padding */
.fig-padding-inline\:0 {
  padding-inline: var(--fig-space-0) !important;
}

.fig-padding-inline\:1 {
  padding-inline: var(--fig-space-1) !important;
}

.fig-padding-inline\:2 {
  padding-inline: var(--fig-space-2) !important;
}

.fig-padding-inline\:3 {
  padding-inline: var(--fig-space-3) !important;
}

.fig-padding-inline\:4 {
  padding-inline: var(--fig-space-4) !important;
}

.fig-padding-inline\:5 {
  padding-inline: var(--fig-space-5) !important;
}

.fig-padding-inline\:6 {
  padding-inline: var(--fig-space-6) !important;
}

.fig-padding-inline\:7 {
  padding-inline: var(--fig-space-7) !important;
}

.fig-padding-inline\:8 {
  padding-inline: var(--fig-space-8) !important;
}

.fig-padding-inline\:9 {
  padding-inline: var(--fig-space-9) !important;
}

.fig-padding-inline\:10 {
  padding-inline: var(--fig-space-10) !important;
}

.fig-padding-inline\:11 {
  padding-inline: var(--fig-space-11) !important;
}

.fig-padding-inline\:12 {
  padding-inline: var(--fig-space-12) !important;
}

/* Block-start (top) padding */
.fig-padding-block-start\:0 {
  padding-block-start: var(--fig-space-0) !important;
}

.fig-padding-block-start\:1 {
  padding-block-start: var(--fig-space-1) !important;
}

.fig-padding-block-start\:2 {
  padding-block-start: var(--fig-space-2) !important;
}

.fig-padding-block-start\:3 {
  padding-block-start: var(--fig-space-3) !important;
}

.fig-padding-block-start\:4 {
  padding-block-start: var(--fig-space-4) !important;
}

.fig-padding-block-start\:5 {
  padding-block-start: var(--fig-space-5) !important;
}

.fig-padding-block-start\:6 {
  padding-block-start: var(--fig-space-6) !important;
}

.fig-padding-block-start\:7 {
  padding-block-start: var(--fig-space-7) !important;
}

.fig-padding-block-start\:8 {
  padding-block-start: var(--fig-space-8) !important;
}

.fig-padding-block-start\:9 {
  padding-block-start: var(--fig-space-9) !important;
}

.fig-padding-block-start\:10 {
  padding-block-start: var(--fig-space-10) !important;
}

.fig-padding-block-start\:11 {
  padding-block-start: var(--fig-space-11) !important;
}

.fig-padding-block-start\:12 {
  padding-block-start: var(--fig-space-12) !important;
}

/* Block-end (bottom) padding */
.fig-padding-block-end\:0 {
  padding-block-end: var(--fig-space-0) !important;
}

.fig-padding-block-end\:1 {
  padding-block-end: var(--fig-space-1) !important;
}

.fig-padding-block-end\:2 {
  padding-block-end: var(--fig-space-2) !important;
}

.fig-padding-block-end\:3 {
  padding-block-end: var(--fig-space-3) !important;
}

.fig-padding-block-end\:4 {
  padding-block-end: var(--fig-space-4) !important;
}

.fig-padding-block-end\:5 {
  padding-block-end: var(--fig-space-5) !important;
}

.fig-padding-block-end\:6 {
  padding-block-end: var(--fig-space-6) !important;
}

.fig-padding-block-end\:7 {
  padding-block-end: var(--fig-space-7) !important;
}

.fig-padding-block-end\:8 {
  padding-block-end: var(--fig-space-8) !important;
}

.fig-padding-block-end\:9 {
  padding-block-end: var(--fig-space-9) !important;
}

.fig-padding-block-end\:10 {
  padding-block-end: var(--fig-space-10) !important;
}

.fig-padding-block-end\:11 {
  padding-block-end: var(--fig-space-11) !important;
}

.fig-padding-block-end\:12 {
  padding-block-end: var(--fig-space-12) !important;
}

/* fig-button, spec: fig/styles/blocks/fig-button.md, edit via /design:create-or-update-block */
.fig-button {
  display: inline-block;
  padding-block: var(--fig-space-2);
  padding-inline: var(--fig-space-4);
  border: 1px solid transparent;
  border-radius: var(--fig-border-radius-3);
  font-family: inherit;
  font-size: var(--fig-text-3);
  font-weight: var(--fig-font-weight-medium);
  line-height: var(--fig-line-height-snug);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  user-select: none;
  opacity: 0.9;
  transition: background-color var(--fig-duration-2) var(--fig-ease-2), border-color var(--fig-duration-2) var(--fig-ease-2), color var(--fig-duration-2) var(--fig-ease-2), opacity var(--fig-duration-2) var(--fig-ease-2);
}

.fig-button:hover,
.fig-button:focus-visible {
  opacity: 1;
}

.fig-button:focus-visible {
  outline: 2px solid var(--fig-secondary-border);
  outline-offset: 2px;
}

/* -- Filled variants (spec §8: data-attr state, not `--modifier`) --
   `primary` uses the `emphasis` semantic role (navy); other two use
   the uniform `--fig-bg-{color}` pattern. Hover bumps one shade darker. */
.fig-button[data-variant=primary] {
  color: var(--fig-fg-on-emphasis);
  background-color: var(--fig-bg-emphasis);
  border-color: var(--fig-bg-emphasis);
}

.fig-button[data-variant=primary]:hover {
  background-color: var(--fig-bg-emphasis-hover);
  border-color: var(--fig-bg-emphasis-hover);
}

.fig-button[data-variant=secondary] {
  color: var(--fig-fg-on-secondary);
  background-color: var(--fig-bg-secondary);
  border-color: var(--fig-bg-secondary);
}

.fig-button[data-variant=secondary]:hover {
  background-color: var(--fig-bg-secondary-hover);
  border-color: var(--fig-bg-secondary-hover);
}

.fig-button[data-variant=danger] {
  color: var(--fig-fg-on-danger);
  background-color: var(--fig-bg-danger);
  border-color: var(--fig-bg-danger);
}

.fig-button[data-variant=danger]:hover {
  background-color: var(--fig-bg-danger-hover);
  border-color: var(--fig-bg-danger-hover);
}

/* -- Ghost variant --
   No fill, no border, no paint shift on hover (cursor + opacity lift only).
   Inherits foreground from context, use for borderless inline toggles
   (See more / See less, dismiss). Disables the base .fig-button opacity-on-hover
   lift so hover is truly inert. Maps to fig-app's `transparent` data-variant. */
.fig-button[data-variant=ghost],
.fig-button[data-variant=ghost]:hover,
.fig-button[data-variant=ghost]:focus-visible {
  color: inherit;
  background-color: transparent;
  border-color: transparent;
  opacity: 1;
}

/* -- Filter / toggle variant --
   Reusable segmented-filter button (the audit page's filter group implements
   it). Both states stay in the primary palette so the group reads as one
   control: the resting/inactive option is a soft primary *tint* fill with a
   stronger primary border (same palette as its bg, visible against the tint,
   not bare text like `ghost`); the active option is the full emphasis fill with
   a darker-primary border so its geometry matches. Tints are color-mixed off
   `--fig-bg-emphasis`, so they track the deployment's primary hue (Vertech gold
   / navy default) without hardcoding a color. Consumers flag the selected
   option with `data-active="true"`. */
.fig-button[data-variant=filter] {
  color: var(--fig-fg-default);
  background-color: color-mix(in srgb, var(--fig-bg-emphasis) 14%, transparent);
  border-color: color-mix(in srgb, var(--fig-bg-emphasis) 55%, transparent);
  opacity: 1;
}

.fig-button[data-variant=filter]:hover,
.fig-button[data-variant=filter]:focus-visible {
  background-color: color-mix(in srgb, var(--fig-bg-emphasis) 24%, transparent);
  border-color: color-mix(in srgb, var(--fig-bg-emphasis) 75%, transparent);
  opacity: 1;
}

.fig-button[data-variant=filter][data-active=true] {
  color: var(--fig-fg-on-emphasis);
  background-color: var(--fig-bg-emphasis);
  border-color: var(--fig-bg-emphasis-hover);
}

.fig-button[data-variant=filter][data-active=true]:hover,
.fig-button[data-variant=filter][data-active=true]:focus-visible {
  background-color: var(--fig-bg-emphasis-hover);
  border-color: var(--fig-bg-emphasis-hover);
}

/* Secondary-palette filter buttons (the agent filters use this), identical
   tint/border logic on the teal secondary palette, so scope filters (primary)
   and agent filters (secondary) read as two distinct control groups. */
.fig-button[data-variant=filter][data-palette=secondary] {
  /* Match the popover panel's resting fill (_fig-popover.scss, secondary palette)
     so the trigger and its open dropdown read as one control, an 8% secondary tint
     over --fig-bg-subtle, not a heavier 14%-over-transparent wash. */
  background-color: color-mix(in srgb, var(--fig-bg-secondary) 8%, var(--fig-bg-subtle));
  border-color: color-mix(in srgb, var(--fig-bg-secondary) 55%, transparent);
}

.fig-button[data-variant=filter][data-palette=secondary]:hover,
.fig-button[data-variant=filter][data-palette=secondary]:focus-visible {
  background-color: color-mix(in srgb, var(--fig-bg-secondary) 24%, transparent);
  border-color: color-mix(in srgb, var(--fig-bg-secondary) 75%, transparent);
}

.fig-button[data-variant=filter][data-palette=secondary][data-active=true] {
  color: var(--fig-fg-on-secondary);
  background-color: var(--fig-bg-secondary);
  border-color: var(--fig-bg-secondary-hover);
}

.fig-button[data-variant=filter][data-palette=secondary][data-active=true]:hover,
.fig-button[data-variant=filter][data-palette=secondary][data-active=true]:focus-visible {
  background-color: var(--fig-bg-secondary-hover);
  border-color: var(--fig-bg-secondary-hover);
}

/* Neutral-palette filter buttons (quiet in-form segmented pickers, e.g. the
   add-to-do due presets): identical tint/border logic anchored on the neutral
   ramp (--fig-bg-inverse) instead of a brand color, so the group recedes into
   the form beside the fields rather than competing with the primary actions.
   The active option deepens to a mid shade of the same ramp — a solid inverse
   fill read heavier than the primary submit beside it — clearly selected next
   to the 6%-tint resting rungs, still brand-free. */
.fig-button[data-variant=filter][data-palette=neutral] {
  background-color: color-mix(in srgb, var(--fig-bg-inverse) 6%, transparent);
  border-color: color-mix(in srgb, var(--fig-bg-inverse) 25%, transparent);
}

.fig-button[data-variant=filter][data-palette=neutral]:hover,
.fig-button[data-variant=filter][data-palette=neutral]:focus-visible {
  background-color: color-mix(in srgb, var(--fig-bg-inverse) 12%, transparent);
  border-color: color-mix(in srgb, var(--fig-bg-inverse) 45%, transparent);
}

.fig-button[data-variant=filter][data-palette=neutral][data-active=true] {
  color: var(--fig-fg-default);
  background-color: color-mix(in srgb, var(--fig-bg-inverse) 18%, transparent);
  border-color: color-mix(in srgb, var(--fig-bg-inverse) 65%, transparent);
}

.fig-button[data-variant=filter][data-palette=neutral][data-active=true]:hover,
.fig-button[data-variant=filter][data-palette=neutral][data-active=true]:focus-visible {
  background-color: color-mix(in srgb, var(--fig-bg-inverse) 24%, transparent);
  border-color: color-mix(in srgb, var(--fig-bg-inverse) 65%, transparent);
}

/* -- Size axis --
   Default size pads 2/4 + text-3. `sm` shrinks padding + drops one type step
   for inline / card-footer toggles. `xs` shrinks one step further, the dense
   filter-bar pills, where many controls share one row and width is at a
   premium (each step drops both paddings + one type step). */
.fig-button[data-size=sm] {
  padding-block: var(--fig-space-1);
  padding-inline: var(--fig-space-2);
  font-size: var(--fig-text-2);
}

.fig-button[data-size=xs] {
  padding-block: var(--fig-space-0);
  padding-inline: var(--fig-space-1);
  font-size: var(--fig-text-1);
}

/* -- States -- */
.fig-button[disabled],
.fig-button[aria-disabled=true] {
  opacity: 0.6;
  cursor: not-allowed;
  pointer-events: none;
  box-shadow: none;
  transform: none;
}

/* Busy state, an in-flight one-shot action (Run now). The resting label swaps for a
   spinner + a busy label while its blocking POST is in flight; the page reload on
   completion resets it. Triggered by aria-busy="true" (set on submit by
   fig-run-now.js), so it's progressive: the button still works without JS, just
   without the spinner. The label pair rides INSIDE the button as [data-btn-idle] /
   [data-btn-busy] spans, the local analog of base.html's htmx idle/busy swap. */
.fig-button [data-btn-busy] {
  display: none;
}

.fig-button[aria-busy=true] {
  cursor: progress;
  pointer-events: none; /* block a double-fire without the greyed disabled look */
}
.fig-button[aria-busy=true] [data-btn-idle] {
  display: none;
}
.fig-button[aria-busy=true] [data-btn-busy] {
  display: inline-flex;
  align-items: center;
  gap: var(--fig-space-1);
}

.fig-button__spinner {
  inline-size: var(--fig-text-3);
  block-size: var(--fig-text-3);
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: var(--fig-border-radius-pill);
  animation: fig-button-spin 0.6s var(--fig-ease-0) infinite;
}

@keyframes fig-button-spin {
  to {
    transform: rotate(360deg);
  }
}
@media (prefers-reduced-motion: reduce) {
  .fig-button {
    transition: none;
  }
  .fig-button__spinner {
    animation-duration: 1.4s;
  }
}
/* fig-card, unified card surface
   spec: fig/styles/blocks/fig-card.md, edit via /design:create-or-update-block
   figclaw MVP subset: default variant only. Deferred (port from fig-app when needed):
   panel / dashed / transparent / outline variants, raised / flat / selected / error /
   warning / success state colorways, data-interactive hover lift, data-fluid grid
   sizing, anchor-header link styling. */
:root {
  /* Card paint shared with future fig-node-card + fig-canvas-widget so modal,
     workflow, and dashboard surfaces render with one visual language. */
  --fig-card-bg: var(--fig-bg-subtle);
  --fig-card-border-color: var(--fig-border-muted);
  --fig-card-border-width: 1px;
  --fig-card-border-radius: var(--fig-border-radius-5);
  --fig-card-shadow-rest: none;
  --fig-card-shadow-hover: var(--fig-shadow-2);
  --fig-card-shadow-raised: var(--fig-shadow-3);
  /* One padding knob for every card section (header / body / meta / footer).
     Change it once and all cards move together, templates never hand-set
     section padding (no per-card fig-box-layout wrappers). */
  --fig-card-padding: var(--fig-space-3);
  /* The two-column approval card's OUTPUT column, the writable draft panel. A
     tint between the card surface and the muted input fill (--fig-bg-muted), so
     the mix inherits each theme's own temperature: manila on a warm cream card,
     warm chocolate one step off a dark charcoal card, cool slate on the stock
     palette. Never mix toward generic-white here, on a near-white light card
     the tint vanishes entirely, and on a dark card 32% white desaturates the
     surface into an ashy, disabled-looking grey (the 2026-07-03 outgoing-column
     regression). Semantic tokens only (health-check Check 8). */
  --fig-card-col-output-bg: color-mix(in srgb, var(--fig-card-bg) 45%, var(--fig-bg-muted));
}

.fig-card {
  color: var(--fig-fg-default);
  background-color: var(--fig-card-bg);
  border: var(--fig-card-border-width) solid var(--fig-card-border-color);
  border-radius: var(--fig-card-border-radius);
  box-shadow: var(--fig-card-shadow-rest);
  transition: box-shadow var(--fig-duration-2) var(--fig-ease-2);
}

/* -- Outline variant, sectioned card with full-bleed dividers --
   Ported from fig-app fig-card. Header / body / footer sit as DIRECT children
   of the shell (no inner box-layout around the section elements) so their
   dividers bleed the full card width. Mirrors fig-accordion[data-variant="card"]:
   header section on top, body below, optional footer at the base, all inside one
   bordered shell. Section padding comes from an inner fig-box-layout (body/footer)
   or from the header rule below.

   Command-center divergence from fig-app: keep the default card fill
   (--fig-bg-subtle, white in light mode) rather than fig-app's flat --fig-bg-default
  , figclaw wants the outline card to read as an elevated tinted surface, just
   sectioned. Only the border + internal dividers change. */
.fig-card[data-variant=outline] {
  border-color: var(--fig-border-default);
  box-shadow: none;
  overflow: hidden; /* clip internal dividers to the rounded corners */
}

/* Outline header is a direct child of the shell so its divider bleeds full
   width. Padding comes from the shared sub-element hook below; margin-block-end
   reset since the border replaces the default header gap. */
.fig-card[data-variant=outline] > .fig-card-header {
  margin-block-end: 0;
  border-block-end: 1px solid var(--fig-border-default);
}

/* When the whole card is one <form> (header control + body inputs submit
   together, e.g. a settings card's header toggle + Save), the header is a child
   of the form, not the shell, so the rule above no longer matches. Restore the
   divider for that nesting. */
.fig-card[data-variant=outline] > form > .fig-card-header {
  margin-block-end: 0;
  border-block-end: 1px solid var(--fig-border-default);
}

/* Footer mirror of the header divider, line above the action row. Padding
   comes from the inner fig-box-layout. (Command-center addition: fig-app's
   outline styles the header divider only, sync back when fig-app gains a
   footer-divided card.) */
.fig-card[data-variant=outline] > .fig-card-footer {
  border-block-start: 1px solid var(--fig-border-default);
}

/* -- Split footer, content pushed to opposite edges --
   Left slot (e.g. a Credentials line) and a trailing action button sit on
   opposite sides of the footer, vertically centered. The left child takes the
   slack; the button keeps its intrinsic size. An empty <span> placeholder on
   the left still parks the button at the right edge. (Command-center helper.) */
.fig-card-footer--split {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fig-space-3);
}

.fig-card-footer--split > p {
  margin: 0;
  min-inline-size: 0;
}

/* -- Catalog automate row, optical centering --
   The toggle ships wrapped in a <form> (a flex item) and its label text uses a
   small size whose line-height leading drops the glyphs below the flex line-box
   center, so the toggle (and the Manage/Remove buttons opposite) read as sitting a
   little high. Collapse the form wrapper to its content and the label's leading so
   the control and its glyphs share one center line. */
.catalog-card-automate {
  align-items: center;
}

.catalog-card-automate > form {
  margin: 0;
  display: inline-flex;
  align-items: center;
}

.catalog-card-automate > span {
  line-height: 1;
}

/* -- Footer action row, equal-width, full-bleed buttons --
   For card footers presenting a row of mutually-exclusive actions (approve /
   edit / reject). Each direct child (a <form> wrapping its button, or a bare
   button) flexes equally; the nested fig-button fills its cell so the row reads
   as a segmented control. (Command-center helper, no fig-app equivalent yet.) */
.fig-card-actions {
  display: flex;
  gap: var(--fig-space-2);
}

.fig-card-actions > * {
  flex: 1 1 0;
  min-inline-size: 0;
}

.fig-card-actions .fig-button {
  display: block;
  inline-size: 100%;
}

/* -- Sub-element hooks, every section pads by the one --fig-card-padding knob,
   so card padding is defined here once rather than per-template. -- */
.fig-card-header,
.fig-card-body,
.fig-card-footer {
  margin: 0;
  padding: var(--fig-card-padding);
}

.fig-card-header :is(h1, h2, h3, h4, h5, h6) {
  margin: 0;
  font-size: var(--fig-text-4);
}

.fig-card-header p {
  margin: 0;
  font-weight: var(--fig-font-weight-regular);
  color: var(--fig-fg-muted);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Header sits tighter to its own subtitle (inner stack) than to the body
   below it, give the header extra breathing room before the first body row. */
.fig-card-header {
  margin-block-end: var(--fig-space-2);
}

/* Catalog-card subtitle, the slash command under the title (which skill this
   card is, under the hood). One step down, muted, monospace, no clamp. */
.fig-card-command {
  font-size: var(--fig-text-1);
  color: var(--fig-fg-muted);
}

.fig-card-command code {
  font-family: var(--fig-font-mono, monospace);
}

/* Header row with a title block on the left and a control/badge pushed to the
   right, vertically centered, the codebase's shared "header with a trailing
   action" pattern (settings cards, detail headers). */
.approval-card-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fig-space-3);
}

.approval-card-header-row > fig-stack-layout {
  min-inline-size: 0;
}

/* Catalog card header, one edge-justified row. Left: the title + slash-command
   subtitle as a tight column (so they read as one block, no wasted gap). Right: a
   control cluster, the labelless on/off toggle then the plugin pill. */
.catalog-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fig-space-3);
}

/* Title + subtitle stacked tight (one step below body rhythm) so the slash
   command hugs the title rather than floating off as its own row. */
.catalog-card-titles {
  display: flex;
  flex-direction: column;
  gap: var(--fig-space-0);
  min-inline-size: 0;
}

/* Trailing control cluster, plugin pill then the on/off toggle (toggle on the
   right edge), both vertically centered against the title block. */
.catalog-card-head-actions {
  display: flex;
  align-items: center;
  gap: var(--fig-space-2);
  flex-shrink: 0;
}

/* The header toggle stands level with the plugin pill, its track height is
   derived from the pill's box model (.fig-badge: text-2 cap × line-height 1 +
   2× space-1 padding-block) so the two read as the same height. Width is ~1.8×
   the track height for normal switch proportions; the thumb is inset symmetrically
   by the smallest space step, so its checked travel reduces to width − height. */
.catalog-card-head .fig-toggle-track {
  --tgl-h: calc(var(--fig-text-2) + (2 * var(--fig-space-1)));
  block-size: var(--tgl-h);
  inline-size: calc(var(--tgl-h) * 1.8);
}

.catalog-card-head .fig-toggle-track::before {
  inline-size: calc(var(--tgl-h) - 2 * var(--fig-space--4));
  block-size: calc(var(--tgl-h) - 2 * var(--fig-space--4));
  inset-block-start: var(--fig-space--4);
  inset-inline-start: var(--fig-space--4);
}

.catalog-card-head .fig-toggle > input:checked ~ .fig-toggle-track::before {
  transform: translateX(calc(var(--tgl-h) * 0.8));
}

/* Approval-card header top row, integration logos on the left, then the card
   title filling the middle, then the priority badge trailing on the right, all on
   ONE row (the title shares the logo/badge row rather than stacking below it,
   saving a row of header height). The title flexes to fill, so the badge cluster
   pins to the right edge whether or not the card renders an integration-icon row;
   the provenance subtitle stacks full-width below. */
.approval-card-header-top {
  display: flex;
  align-items: center;
  gap: var(--fig-space-2);
}

.approval-card-header-top > .approval-card-title {
  flex: 1;
  min-inline-size: 0;
  /* Title rides the flex row, so it carries no block margin of its own (the
     header stack-layout owns the gap down to the provenance subline). */
  margin-block: 0;
}

.approval-card-header-top > :last-child {
  margin-inline-start: auto;
}

/* Header edit-mode Cancel, a bare inline text link rather than a .fig-button.
   It shares the .fig-icon-button-group row with the Save/Chat icon buttons, so
   any button padding would (1) grow the row past the space-6 icon-button height
   (padding-block) and shift the layout when Edit is clicked, and (2) push the
   neighbouring Save icon a padding-width out, breaking the group's tight
   space-1 gap. Zero-padding + inline text sizing keeps it at the row height the
   icon buttons already set (no shift vs. read mode) and tight in the rhythm.
   The FOOTER Cancel (_approval_edit_actions.html) stays a ghost .fig-button, it
   pairs next to Save there so the two read as one control group. */
.approval-card-cancel-edit {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--fig-text-2);
  font-weight: var(--fig-font-weight-medium);
  color: var(--fig-fg-muted);
  cursor: pointer;
  text-decoration: none;
}

.approval-card-cancel-edit:hover,
.approval-card-cancel-edit:focus-visible {
  color: var(--fig-fg-default);
  text-decoration: underline;
}

/* Header <select> fallback (edit mode only): a reply-card Type that is EMPTY
   while editing renders as a small caption stacked above a real <select> (an
   empty chip face would be invisible, nothing to click). Every OTHER
   Customer / Type state, in both modes, uses the always-on inline
   .fig-chip-edit overlay below (edit mode just drops its auto-save, see
   _chip_edit.html). The priority coin is neither: it's the design-system
   .fig-priority-picker popover (_fig-todo.scss), never a native <select>. */
.approval-card-label-edit {
  display: inline-flex;
  flex-direction: column;
  gap: var(--fig-space-0);
  font-size: var(--fig-text-2);
  color: var(--fig-fg-muted);
  white-space: nowrap;
}

.approval-card-label-edit > .fig-field__input {
  font-size: var(--fig-text-2);
  padding-block: var(--fig-space-1);
}

/* Always-on inline chip editor (_chip_edit.html): the visible category chip
   (`__face`) sits over a full-size transparent native <select> (`__control`).
   The select captures the click and opens the field's menu (so one click on the
   chip edits it, no Edit button); the face keeps the exact resting look, a
   solid-filled colored chip, so the row doesn't read as a busy strip of
   dropdowns. A hover / keyboard-focus ring is the only affordance that it's
   editable. */
.fig-chip-edit {
  position: relative;
  display: inline-flex;
  align-items: center;
  border-radius: var(--fig-border-radius-pill);
}

.fig-chip-edit__face {
  display: inline-flex;
}

.fig-chip-edit__control {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  font: inherit;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
}

.fig-chip-edit:hover,
.fig-chip-edit:focus-within {
  box-shadow: 0 0 0 2px var(--fig-border-strong, var(--fig-border-default));
}

/* Provenance subline sits a hair below the title row (the .fig-card-header reset
   zeroes heading margins), so title and subline read as one tight block. The
   header's stack-layout declares space="1" but the subset primitive doesn't wire
   space= (fixed space-3 rhythm, see _fig-stack-layout.scss), which left a full
   base-rhythm gap under the title; the intended tight gap is enforced here. */
.approval-card .fig-card-header :is(h1, h2, h3, h4, h5, h6) {
  margin-block-end: var(--fig-space-0);
}

.approval-card .fig-card-header > fig-stack-layout > * + * {
  margin-block-start: var(--fig-space-1);
}

/* Subline row: the card's email-category chips (Customer / Type, or the deal
   card's `categories`) lead the "Suggested by …" provenance text on one row,
   left-aligned under the title (they moved here from the header-top's right
   badge cluster so the right edge stays reserved for actions + the priority
   coin). Wraps on narrow cards; a card with no chips renders just the text.
   Chip-to-chip gap is the tight space-1 so the chips read as one group; the
   provenance <p> adds a small extra start margin (only when chips precede it) so
   the group-to-text gap reads one step larger than the gaps inside the group
   without the text drifting away from its chips. */
.approval-card-subline {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--fig-space-1);
}

.approval-card-subline > p {
  margin-block: 0;
}

.approval-card-subline > p:not(:first-child) {
  margin-inline-start: var(--fig-space-1);
}

/* Header badge band sized to the icon buttons: the priority coin shares the
   cluster with the .fig-icon-button group (--fig-space-6 square, see
   _fig-icon-button.scss), so the header's --fig-badge-size steps up one rung to
   match; elsewhere the coin keeps the compact base diameter (_fig-badge.scss). */
.approval-card-header-top {
  --fig-badge-size: var(--fig-space-6);
}

/* Header logos sized to the priority badge via the shared --fig-badge-size token
   (in _fig-badge.scss, stepped up above) so the row reads as one band of
   equal-height chips and the two can never drift. Width + the wide-wordmark cap
   come from _fig-integration-icons.scss. Scoped to the card header, catalog-footer /
   collapsed-card icon rows keep the compact base size. */
.approval-card-header-top .integration-icon {
  height: var(--fig-badge-size);
}

.approval-card-header-top .integration-icons {
  margin-block-end: 0;
}

/* Approval/feed card column runs wider than the prose measure. Cards lay input
   and output (draft) side by side (.approval-card-cols), needing room for two
   readable columns; widen to the app-floor width tier (`max="5"` → container-5)
   so the feed is on the standard page scale, not a one-off measure. Scoped to the
   wrapping fig-center-layout via the inherited custom prop, the global token
   stays 60ch for body prose. */
.approval-column {
  --fig-typographic-measure: var(--fig-container-5);
}

/* -- Two-column card interior, input vs output / suggested action --
   The approval card splits its middle into a left "input" column (the source
   material the agent worked from, call summary, incoming message, deal fields +
   metadata) and a right "output" column (the agent's draft plus the action
   footer). Replaces the tall single-column stack for cards that carry both; the
   template emits this only when there's a draft AND context to pair (see
   cc_humanize.split_payload `two_column`). The header stays full-width above. */
.approval-card-cols {
  display: grid;
  /* Output a touch wider, the draft is the thing being read and edited.
     The 1.15 recurs in the two-action footer rule below (the buttons split at
     the same ratio so their gap sits under the inter-column seam), change both
     together. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  align-items: stretch;
}

/* Footer buttons under a two-column card: an action row of exactly two splits
   at the columns' 1 : 1.15 ratio (grid-template above) so the button gap lands
   under the inter-column seam instead of at the 50% line. One or three-plus
   actions keep .fig-card-actions' equal split, there's no seam to map them
   onto. */
.fig-card:has(.approval-card-cols) .fig-card-actions > :nth-child(2):last-child {
  flex-grow: 1.15;
}

/* Vertical hairline between the columns, the inline mirror of the full-bleed
   section dividers. Owned by the output column so it draws only between the two. */
.approval-card-cols > .approval-card-col--output {
  border-inline-start: 1px solid var(--fig-border-default);
}

/* The grid's align-items:stretch lines the two columns' bases up even when one
   side is taller (the inter-column hairline spans the full stretched height).
   The follow-up thread + action footer are full-width rows BELOW the columns,
   not pinned inside the output column. */
/* Output column, a tint apart from the card (the writable draft panel). The
   bg fills the cell behind both the label band (its own --fig-bg-muted) and the
   content below it. */
.approval-card-col--output {
  min-inline-size: 0;
  background-color: var(--fig-card-col-output-bg);
}

.approval-card-col--input {
  min-inline-size: 0;
}

/* Per-column fold, each column scrolls independently inside a half-viewport cap
   so a long draft or thread never lets the card dominate the feed. svh, not vh: a
   mobile URL-bar show/hide must not resize the cap mid-scroll. The grid's
   align-items:stretch makes the shorter column match the taller one's height, so
   the inter-column hairline still spans the full capped height. A single-column
   card (--single) folds the same way. There is no Show more toggle. Read-mode
   columns are <fig-scroll-fade-layout> (rule below), scrollbar hidden, a bottom
   fade is the affordance; edit-mode columns are plain divs that keep the scrollbar. */
.approval-card-col {
  max-block-size: 50svh;
  overflow-y: auto;
}

/* Read-mode columns ARE the <fig-scroll-fade-layout> primitive (see
   _approval_card.html): its JS flips --fade-bottom by scroll position, so a bottom
   fade appears only while more content sits below the cap and recedes at the end,
   the scroll cue. We hide the scrollbar so the fade is the SOLE affordance (the
   user's call), and pin the band to the prominent --fig-fade-size (the primitive's
   gentle space-3 default is too subtle here). fade-sides="bottom" in the markup
   keeps the top opaque, so the sticky Incoming/Outgoing label never fades. Edit-mode
   columns are plain .approval-card-col divs, unaffected, scrollbar intact. */
fig-scroll-fade-layout.approval-card-col {
  --fade-size: var(--fig-fade-size);
  overflow-x: hidden;
  scrollbar-width: none; /* Firefox */
}

fig-scroll-fade-layout.approval-card-col::-webkit-scrollbar {
  display: none; /* Chromium / WebKit */
}

/* Tiny column header row, "Incoming" (left) / "Outgoing" (right). Unobtrusive:
   the smallest text step, muted neutral, uppercase tracking so it reads as a
   label, not content. Full-bleed band across the top of each column, centered, on
   a slightly darker neutral fill with the same hairline the columns use, padded by
   the design system's smallest spatial unit. */
.approval-card-col-label {
  margin: 0;
  padding: var(--fig-space--4);
  /* Sticks to the top of its scrolling column so "Incoming" / "Outgoing" stays
     legible as the body scrolls past beneath it (the band carries its own fill +
     bottom hairline, so it reads cleanly over the content it covers). */
  position: sticky;
  inset-block-start: 0;
  z-index: 1;
  text-align: center;
  font-size: var(--fig-text-1);
  font-weight: var(--fig-font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--fig-fg-muted);
  background-color: var(--fig-bg-muted);
  border-block-end: 1px solid var(--fig-border-default);
}

/* The Outgoing label band carries a brand-emphasis underline, the same lane as
   the Approve action the draft feeds, so the writable side reads "active", not
   disabled. Label text stays the shared muted color; the underline + panel tint
   + seam carry the direction together, no single cue relies on hue. */
.approval-card-col--output .approval-card-col-label {
  border-block-end: 2px solid var(--fig-bg-emphasis);
  /* Restate the inter-column seam across the header band. The column's own
     border-inline-start is --fig-border-default, which in dark mode is the same
     neutral-700 as the band's --fig-bg-muted fill, so it vanishes exactly across
     the band while staying visible below. --fig-border-emphasis reads against the
     fill in both themes; the 1px lateral offset from the column border is masked
     by the band's bottom hairline where the two meet. */
  border-inline-start: 1px solid var(--fig-border-emphasis);
}

/* The input band pads out the 1px the output band's thicker underline adds
   (2px emphasis vs 1px hairline), so the two bands occupy the same block size
   and the rows below them start level, keeping the columns' shared hairlines
   on one line all the way down. */
.approval-card-col--input .approval-card-col-label {
  padding-block-end: calc(var(--fig-space--4) + 1px);
}

/* Narrow viewports: drop to a single stacked column, input above output, and
   shed the inter-column seam (the footer keeps its own top divider). */
@media (max-width: 48rem) {
  .approval-card-cols {
    grid-template-columns: minmax(0, 1fr);
  }
  .approval-card-cols > .approval-card-col--output {
    border-inline-start: none;
  }
  .approval-card-col--output .approval-card-col-label {
    border-inline-start: none;
  }
  /* Stacked columns have no seam, restore the equal footer split. */
  .fig-card:has(.approval-card-cols) .fig-card-actions > :nth-child(2):last-child {
    flex-grow: 1;
  }
}
/* dl rhythm, label / value rows in card body. Keeps dt close to its dd,
   adds breathing room between rows. Values are flush-left (no indent). */
.fig-card-body dl {
  margin: 0;
}

/* Body-section labels ("Message", "Call summary") match the thread cell's
   "Email" label (_fig-thread.scss .fig-thread-label) and the meta-grid field
   labels (Sender / Subject): small, semibold, muted, so every cell header in
   both columns reads as one labelling system instead of the draft's label
   shouting in full-size default ink. */
.fig-card-body dt {
  margin-block-start: var(--fig-space-3);
  font-size: var(--fig-text-2);
  font-weight: var(--fig-font-weight-semibold);
  color: var(--fig-fg-muted);
}

/* First row hugs the body's top padding so the gap above it equals the body's
   inline padding, covers a leading dt and a leading markdown dd (which carries
   no dt), so a draft/markdown body doesn't open with a fatter top gap. */
.fig-card-body dl > :first-child {
  margin-block-start: 0;
}

.fig-card-body dd {
  margin: var(--fig-space-1) 0 0 0;
  /* Plain-text drafts (reply/deal body) carry author line breaks as bare "\n";
     pre-line keeps them as paragraph breaks. */
  white-space: pre-line;
  /* Long unbreakable tokens, tracking/redirect URLs in an incoming snippet,
     have no break opportunity and would blow past the column width. Break them
     anywhere so they wrap inside the card instead of overflowing. */
  overflow-wrap: anywhere;
}

/* Rendered-markdown bodies (notice cards' filled_markdown) emit block elements
  , <p>, <h*>, <pre>, tables, quotes, straight into the dd, no wrapper class.
   Reset pre-line so the newlines BETWEEN those tags don't render as blank lines,
   then give the markdown HTML its own rhythm + chrome: _fig-globals zeroes
   heading/paragraph margins (spacing is meant to come from layout primitives),
   and converted markdown carries no class of its own, so the dd scope supplies
   both the block margins and the code/table/quote chrome. Plain element selectors
   on purpose, no markdown-specific class, which would drift from the design
   system. (Ported off the old global markdown styles, now deleted.) */
.fig-card-body dd:has(> :is(p, pre, ul, ol, h1, h2, h3, h4, h5, h6, blockquote, table)) {
  white-space: normal;
}

.fig-card-body dd > :is(p, pre, ul, ol, blockquote, table) {
  margin-block: 0 var(--fig-space-2);
}

.fig-card-body dd > :is(h1, h2, h3, h4, h5, h6) {
  margin-block: var(--fig-space-3) var(--fig-space-1);
  line-height: var(--fig-line-height-snug);
}

/* A heading hugs the block it introduces, kill the next element's top margin so
   "Original error" sits tight to its code block, not floating in a paragraph gap. */
.fig-card-body dd :is(h1, h2, h3, h4, h5, h6) + * {
  margin-block-start: 0;
}

/* Prose headings ride the type-scale tokens (health-check C19): the ramp steps
   16 → 20px with nothing between, so the four markdown levels collapse to two
   honest tiers — a display tier (h1/h2 → text-4) over the body tier (h3–h6 →
   text-3) — rather than inventing off-scale rem values. */
.fig-card-body dd :is(h1, h2) {
  font-size: var(--fig-text-4);
}

.fig-card-body dd :is(h3, h4, h5, h6) {
  font-size: var(--fig-text-3);
}

.fig-card-body dd ul, .fig-card-body dd ol {
  padding-inline-start: var(--fig-space-5);
}

.fig-card-body dd > :first-child {
  margin-block-start: 0;
}

.fig-card-body dd > :last-child {
  margin-block-end: 0;
}

/* Inline source-citation marker (<sup>[n]</sup>, a superscript anchor to the
   Sources list): quiet the *brackets* to a subtle neutral so the marker reads as a
   reference, but keep the *number* a link, it jumps to the Sources entry, so it
   carries the normal link color. The brackets sit bare in the <sup> (muted here);
   the number is the inner <a>, restored to the default link color. */
.fig-card-body sup {
  color: var(--fig-fg-muted);
  white-space: nowrap;
}

.fig-card-body sup a {
  color: var(--fig-secondary-fg);
  text-decoration: none;
}

/* Tables / inline code / code blocks / blockquotes inside a markdown body. */
.fig-card-body dd table {
  width: 100%;
  border-collapse: collapse;
}

.fig-card-body dd th, .fig-card-body dd td {
  padding: var(--fig-space-2) var(--fig-space-3);
  border-block-end: 1px solid var(--fig-border-muted);
  text-align: start;
}

.fig-card-body dd thead th {
  border-block-end: 1px solid var(--fig-border-default);
}

.fig-card-body dd code {
  font-family: var(--fig-font-mono, monospace);
  background: var(--fig-bg-muted);
  color: var(--fig-fg-default);
  padding: 0 var(--fig-space-1);
  border-radius: var(--fig-border-radius-1);
}

.fig-card-body dd pre {
  /* Neutral surface, not --fig-bg-emphasis (= brand primary-500): a brand fill
     made code text contrast unpredictable across light/dark. Muted is mode-aware
     (neutral-100 light / neutral-700 dark) so the captured error stays legible. */
  background: var(--fig-bg-muted);
  color: var(--fig-fg-default);
  padding: var(--fig-space-3);
  border-radius: var(--fig-border-radius-2);
  /* Wrap long error text instead of a horizontal scrollbar, a captured
     stack/Sentry message must read in full without scrolling sideways. */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.fig-card-body dd pre code {
  background: none;
  padding: 0;
}

.fig-card-body dd blockquote {
  border-inline-start: 2px solid var(--fig-border-default);
  padding-inline-start: var(--fig-space-3);
  color: var(--fig-fg-muted);
}

/* Card metadata section, wraps a fig-meta-grid as a card section. Full-bleed:
   the grid's own cell padding (--fig-space-3, == --fig-card-padding) supplies the
   inline inset, so the first column's text lines up with body/header text instead
   of stacking the wrapper padding on top of the cell padding. The grid's hairline
   dividers are internal-only (cell borders, outer edges clipped), so a full-bleed
   grid still reads cleanly. Vertical rhythm comes from the cells' own padding.
   When a body precedes it, a full-width hairline (drawn on the grid) marks where
   metadata begins; an all-metadata card has no body so needs no extra line under
   the header divider. */
.fig-card-meta {
  padding-inline: 0;
}

.fig-card-body + .fig-card-meta .fig-meta-grid {
  border-block-start: 1px solid var(--fig-border-default);
}

/* -- Inline edit mode (approval cards) --
   Clicking Edit swaps the whole card into one <form>: body drafts become
   textareas, metadata cells become inline inputs in place, and the "Revise
   with AI" reviser panel rides the footer. The editable-field look (seamless at
   rest, reveal on hover) is the reusable `.is-editable` block, see
   `_fig-editable.scss`. Only the approval-card-specific chrome lives here. */
/* In edit mode the footer is nested inside the form, so the outline variant's
   `> .fig-card-footer` direct-child divider no longer matches, restore it. */
.approval-card.is-editing .fig-card-footer {
  border-block-start: 1px solid var(--fig-border-default);
}

/* Conversational reviser panel (UI/UX Q4): the streaming "Revise with AI" chat
   that stages edits into the edit form. A scrolling transcript above an input
   row; agent-staged form fields get a brief highlight (.is-agent-edited). */
.approval-reviser {
  display: flex;
  flex-direction: column;
  gap: var(--fig-space-2);
  /* A distinct "Revise with AI" surface: a soft accent tint + a leading accent
     stripe set the agent zone apart from the neutral card body above. */
  padding: var(--fig-space-3);
  background: var(--fig-accent-bg-subtle);
  border: var(--fig-card-border-width) solid var(--fig-border-muted);
  border-inline-start: var(--fig-space-1) solid var(--fig-accent-border);
  border-radius: var(--fig-border-radius-4);
}

.approval-reviser__log {
  display: flex;
  flex-direction: column;
  gap: var(--fig-space-1);
  max-block-size: var(--fig-container--2); /* 14rem cap on the scrollable log — sizing token, not a raw rem (health-check C15) */
  overflow-y: auto;
  font-size: var(--fig-text-2);
}

.approval-reviser__log:empty {
  display: none;
}

.approval-reviser__line {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.approval-reviser__line--user {
  align-self: flex-end;
  background: var(--fig-bg-muted);
  border-radius: var(--fig-border-radius-2);
  padding: var(--fig-space-1) var(--fig-space-2);
}

.approval-reviser__chip {
  font-size: var(--fig-text-1);
  color: var(--fig-fg-muted);
}

.approval-reviser__chip--done {
  color: var(--fig-fg-default);
}

.approval-reviser__err {
  color: var(--fig-danger-fg, var(--fig-fg-default));
}

/* Thinking indicator: three pulsing dots shown from Send until the agent's first
   token / tool chip / patch lands, so the operator sees the turn is in flight
   during the pre-stream latency gap (the transcript would otherwise sit empty
   and read as "nothing happened"). Cleared by the reviser on the first event. */
.approval-reviser__thinking {
  display: inline-flex;
  align-items: center;
  gap: var(--fig-space-1);
  padding-block: var(--fig-space-1);
  color: var(--fig-fg-muted);
}

.approval-reviser__thinking > span {
  inline-size: 0.375rem;
  block-size: 0.375rem;
  border-radius: var(--fig-border-radius-pill);
  background: currentColor;
  animation: fig-reviser-thinking 1.2s ease-in-out infinite;
}

.approval-reviser__thinking > span:nth-child(2) {
  animation-delay: 0.15s;
}

.approval-reviser__thinking > span:nth-child(3) {
  animation-delay: 0.3s;
}

@keyframes fig-reviser-thinking {
  0%, 80%, 100% {
    opacity: 0.3;
    transform: translateY(0);
  }
  40% {
    opacity: 1;
    transform: translateY(-0.125rem);
  }
}
.approval-reviser__input-row {
  display: flex;
  gap: var(--fig-space-2);
  align-items: flex-end;
}

.approval-reviser__input-row > textarea {
  flex: 1 1 auto;
}

/* Staged to-dos (the reviser's add_todo): removable chips just above the reviser
   panel, inside the Save form — committed to the To-Do List on Save, discarded on
   Cancel / the chip's ✕. Built by fig-card-reviser.js (stageTodo). */
.approval-reviser__todos {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--fig-space-1);
  margin-block-end: var(--fig-space-2);
}

.approval-reviser__todo {
  display: inline-flex;
  align-items: center;
  gap: var(--fig-space-1);
  padding: var(--fig-space-1) var(--fig-space-2);
  border: 1px solid var(--fig-border-default);
  border-radius: var(--fig-border-radius-pill);
  background: var(--fig-bg-subtle);
  font-size: var(--fig-text-1);
  color: var(--fig-fg-default);
}

.approval-reviser__todo-remove {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-1);
  line-height: 1;
}
.approval-reviser__todo-remove:hover {
  color: var(--fig-fg-default);
}

/* A field the agent just staged, a green flash so the operator sees what changed.
   `.is-agent-flash` is transient (the reviser removes + re-adds it per incremental
   `card_patch` so the animation re-fires when a field is staged again across the
   turn); `.is-agent-edited` persists as the marker for the staged-this-session set. */
.is-agent-flash {
  animation: fig-agent-edit-flash 1.2s ease-out;
}

@keyframes fig-agent-edit-flash {
  0% {
    background-color: var(--fig-status-success-bg);
  }
  100% {
    background-color: transparent;
  }
}
/* The outline card clips to its rounded corners with overflow:hidden, which
   would chop off the Postpone popover panel anchored in the footer. Let the
   approval card overflow so the menu floats free (same tradeoff as the
   schedule-builder popover). */
.fig-card.approval-card {
  overflow: visible;
}

/* -- Compact tall cards, generic feed behavior, not skill-specific --
   A long card shouldn't dominate the feed. The two modes fold differently:

   READ mode caps each card column at half the viewport and lets it scroll on its
   own (see .approval-card-col above). No Show more toggle and no scrollbar, each
   read column is a <fig-scroll-fade-layout> whose bottom fade is the scroll
   affordance (fig-scroll-fade-layout.approval-card-col above). The article itself is NOT height-capped, so
   the footer's Postpone popover (which relies on the article's `overflow: visible`
   above) is never clipped, and the follow-up thread + actions stay full-width below
   the scroll. See _approval_card.html.

   EDIT mode is an inline editor that grows with its content, capped at the
   viewport (minus the sticky nav, measured into --cc-sticky-offset by
   fig-card-edit.js). A short card stays short (footer right under its content); a
   dense deal grid expands until it hits the cap, then its body scrolls. That same
   script scrolls the card on edit-open so its top pins just below the nav (the
   matching scroll-margin-block-start below). It stays a flex column with a pinned
   header + pinned Save/Cancel footer; the body (.approval-edit-scroll) takes the
   slack and scrolls. svh, not vh, so a mobile URL-bar show/hide doesn't resize the
   card mid-edit. Decided 2026-06-25 (UI/UX quest log Q1): inline (no takeover/dim),
   viewport-capped, pinned to top, all editable card kinds. (Revised 2026-06-26:
   grow-to-content cap, was a fixed full-viewport height that stretched short cards
   and shoved the footer off the bottom.) */
.approval-card.is-editing {
  display: flex;
  flex-direction: column;
  /* Edit-open choreography lives on .is-entering below: fig-card-edit.js clamps
     the freshly-swapped editor at the read card's height, scrolls it up under
     the nav, then releases the clamp so this cap is reached via a transition
     instead of a one-frame slam. */
  /* Grow WITH the content, but never past the viewport below the sticky nav
     (less the even frame gutter top + bottom, see --cc-edit-gutter below, so the
     pinned Save/Cancel footer clears the bottom edge and never gets clipped by
     sub-pixel rounding). max-block-size, NOT
     block-size: a short card stays short, so its footer sits right under the
     content, instead of being stretched to the full viewport with the footer
     shoved off the bottom (the bug). A card taller than the cap clamps here and
     its body scrolls (.approval-edit-scroll below). --cc-sticky-offset is the
     measured nav height (fig-card-edit.js); the fallback is the published
     --fig-nav-height SSoT (_fig-nav.scss), the SAME constant the feed's scroll
     column subtracts (fig-sidebar-filter-layout: 100dvh - --fig-nav-height), so
     the header is fully accounted for even before/without the JS measure, instead
     of a magic 3.5rem that under-counted it and let the card grow a hair too tall
     (footer creeping off the bottom). */
  /* Even frame: the same --fig-space-6 gutter the feed column pads on all four
     sides (_fig-sidebar-filter.scss) rides the top AND bottom of the edit card,
     so an expanded card isn't flush against the nav (the top gap was 0, bug) and
     its bottom clears the viewport by the same inset the sides already keep.
     --cc-edit-gutter is that one gutter, referenced by both the height cap (top +
     bottom, ×2) and the top scroll-margin, so the two can't drift. */
  --cc-edit-gutter: var(--fig-space-6);
  max-block-size: calc(100svh - var(--cc-sticky-offset, var(--fig-nav-height)) - var(--cc-edit-gutter) * 2);
  /* Pin below the nav with the gutter gap. fig-card-edit.js measures the nav's
     overlap of THIS card's scroll container into --cc-scroll-overlap (0 for an
     inner scroll column that starts below the nav, the nav height when the
     document scrolls under it); the gutter is added here, once, so the top gap
     matches the frame even before/without the JS measure. */
  scroll-margin-block-start: calc(var(--cc-scroll-overlap, var(--cc-sticky-offset, var(--fig-nav-height))) + var(--cc-edit-gutter));
}

/* Two-column edit: the whole body scrolls as ONE region (.approval-edit-scroll
   below), so the columns grow to their content, no 50svh read cap, no per-column
   scrollbar. (Read mode caps + scrolls each column at 50svh; edit mode lifts both
   so the single outer scroll + the pinned footer are the only chrome.) The grid's
   align-items:stretch still levels the two columns to equal height. A single-column
   card has no .approval-card-col, so its body just scrolls in .approval-edit-scroll. */
.approval-card.is-editing .approval-card-col {
  max-block-size: none;
  overflow: visible;
}

.approval-card.is-editing > .fig-card-header,
.approval-card.is-editing > form > .fig-card-footer {
  flex: 0 0 auto;
}

/* The edit form takes the card's slack and is itself a flex column (header sits
   above it as the card's own child; the form holds the scroll body + pinned
   footer). It does NOT scroll, its inner `.approval-edit-scroll` does. */
.approval-card.is-editing > form {
  flex: 1 1 auto;
  min-block-size: 0;
  display: flex;
  flex-direction: column;
}

.approval-card.is-editing > form > .approval-edit-scroll {
  flex: 1 1 auto;
  min-block-size: 0;
  overflow-y: auto;
}

/* Edit-open ride (fig-card-edit.js): while `.is-entering`, the card is clamped
   at the read card's height via an inline max-block-size; dropping that inline
   value hands max-block-size back to the .is-editing cap above, and this
   transition eases the card open (header + Save/Cancel footer stay pinned, the
   .approval-edit-scroll region takes the growth). overflow:hidden only for the
   ride, content would poke past the clamp under the card's usual
   `overflow: visible` (needed for popovers, none of which can be open this
   early); the class is removed on transitionend. NOT qualified on .is-editing:
   during htmx's ~20ms settle window the fresh editor still wears the old card's
   classes (no .is-editing yet) but must already hold the clamp, see the settle
   quirk in fig-card-edit.js. */
.approval-card.is-entering {
  overflow: hidden;
  transition: max-block-size var(--fig-duration-5) var(--fig-ease-5);
}

@media (prefers-reduced-motion: reduce) {
  .approval-card.is-entering {
    transition: none;
  }
}
/* -- Body fold bar, the card's minimized ⇄ expanded toggle --
   Native <details> (the figclaw foldbar, same vocabulary as fig-followups /
   fig-thread): the <summary> is a full-width bar that folds the whole body +
   follow-up thread away, leaving header + bar + footer actions, the card's
   "fully minimized" state. Linked (chain) cards carry .is-foldable and start
   closed so a company→contact→deal stack reads as three tight rows; a standalone
   card's <details> is `open` with the bar suppressed, so it renders as a plain
   body (no behavior change). The bar sits OUTSIDE .fig-card-actions, so it stays
   clickable even on an aria-disabled chain card (preview a blocked deal before its
   prerequisites land, see the disabled-card rule below). The expanded body keeps
   the per-column 50svh scroll cap (.approval-card-col), so "expanded" still folds
   tall content rather than letting one card dominate the feed. */
.approval-card-fold {
  display: block;
}

/* Standalone (non-foldable) cards, open <details> with the bar hidden, renders the
   body exactly as it did before the fold existed. */
.approval-card-fold:not(.is-foldable) > .approval-card-fold-bar {
  display: none;
}

/* The bar, the always-visible clickable row. Kill the native disclosure triangle
   so the chevron is the only affordance; padded by the one card-padding knob like
   every other card section. */
.approval-card-fold-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fig-space-2);
  padding: var(--fig-card-padding);
  cursor: pointer;
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-2);
  font-weight: var(--fig-font-weight-semibold);
  list-style: none;
  user-select: none;
}

.approval-card-fold-bar::-webkit-details-marker {
  display: none;
}

.approval-card-fold-bar:hover {
  color: var(--fig-fg-default);
}

/* Open + foldable: a full-bleed seam under the bar divides it from the body it
   reveals, matching the card's other section dividers, and the bar takes the
   same muted fill as the Incoming/Outgoing column-label bands so the expanded
   state reads as one banded header stack. The seam can't be a plain
   --fig-border-default hairline: it sits between two --fig-bg-muted bands (this
   bar and the column-label bands), and dark themes map --fig-border-default to
   the SAME ramp step as --fig-bg-muted, so the line vanished there (2026-07-03).
   Derive it from the band fill nudged toward the text color instead, contrast
   against the muted fill on both sides is then guaranteed in every theme/mode. */
.approval-card-fold.is-foldable[open] > .approval-card-fold-bar {
  background-color: var(--fig-bg-muted);
  border-block-end: 1px solid color-mix(in srgb, var(--fig-bg-muted) 80%, var(--fig-fg-muted));
}

/* "Show details" when closed, "Hide details" when open, CSS text swap, no JS. */
.approval-card-fold-hide {
  display: none;
}

.approval-card-fold[open] > .approval-card-fold-bar .approval-card-fold-show {
  display: none;
}

.approval-card-fold[open] > .approval-card-fold-bar .approval-card-fold-hide {
  display: inline;
}

/* Single chevron glyph; rotates 180° when the body is open (mirrors fig-followups
   / fig-thread). */
.approval-card-fold-chevron {
  transition: transform 150ms var(--fig-ease-1);
  flex: none;
}

.approval-card-fold[open] .approval-card-fold-chevron {
  transform: rotate(180deg);
}

/* Fold open/close eases with the SAME design-system transition as the card's
   edit-open ride (.is-entering above): duration-5 + ease-5, one expand feel
   across the card. Pure CSS via the ::details-content height interpolation;
   browsers without interpolate-size keep today's instant snap (the fold still
   works, it just doesn't glide). content-visibility rides along discretely so
   the body stays painted through the close animation instead of vanishing on
   the first frame. */
.approval-card-fold.is-foldable {
  interpolate-size: allow-keywords;
}

.approval-card-fold.is-foldable::details-content {
  block-size: 0;
  overflow-y: clip;
  transition: block-size var(--fig-duration-5) var(--fig-ease-5), content-visibility var(--fig-duration-5) allow-discrete;
}

.approval-card-fold.is-foldable[open]::details-content {
  block-size: auto;
}

@media (prefers-reduced-motion: reduce) {
  .approval-card-fold-chevron {
    transition: none;
  }
  .approval-card-fold.is-foldable::details-content {
    transition: none;
  }
}
/* Disabled card, generic dimmed, not-yet-actionable state for any fig-card whose
   actions aren't available yet. Set aria-disabled="true" on the card; the content
   dims and the decision footer (Approve / Send Email) is locked with a
   not-allowed cursor, but the body fold bar (.approval-card-fold-bar) stays clickable
   so the body can still be previewed. DRY: the visual lives here on the block; the
   *reason* it's set is the consumer's job, an approval card reads its chain depends_on
   (a deal waits on its company + contact) and sets the attribute.

   Dismiss is the exception: the danger control (data-variant="danger") is ALWAYS a valid
   escape hatch, you must be able to reject an unwanted card even while its chain
   dependencies are unmet (else a blocked chain dependent can never be cleared). It keeps
   pointer-events AND full opacity, so it reads as the one live action on an otherwise
   greyed card.

   The dim is applied per-section, NOT as opacity on the card root: a child cannot
   render at higher opacity than an opacity'd ancestor, so a whole-card dim would drag
   the escape hatches down with everything else. Both escape hatches (the Dismiss ✕ +
   Edit) now ride the HEADER's icon-button group (_approval_card_header.html), so the
   header is excluded from the blanket section dim alongside the footer and its content
   dims piecewise instead (the rules after the footer block below), leaving the danger ✕
   and Edit at full strength. Inside the footer the locked (non-danger) buttons still dim
   one by one.

   Opacity alone is NOT the signal — on a dark surface, translucent light-on-dark just
   reads as slightly quieter text and the saturated Approve/Link fills stay recognizably
   colorful (a locked card was near-indistinguishable from a live one, 2026-07-03). The
   grayscale() on every dimmed piece is what carries "inert": the colored buttons go
   grey. Adding filter creates a stacking context on each dimmed element, but the
   opacity already did that, so popover z-index behavior is unchanged (panels are
   position:absolute in their own relative wrapper, not fixed). */
.fig-card[aria-disabled=true] > :not(.fig-card-footer):not(.fig-card-header),
.fig-card[data-approve-block] > :not(.fig-card-footer):not(.fig-card-header) {
  opacity: 0.6;
  filter: grayscale(0.65);
}

/* Surface: a locked card also loses its elevation — the card bg blends most of the
   way to the page bg and the resting shadow drops, so the whole card sits flat and
   receded next to a live one. Token-based, so it tracks both modes and any client
   theme. Riding --fig-card-bg also flattens the derived outgoing-column tint. The
   escape hatches paint their own fills, so they stay bright on the receded surface. */
.fig-card[aria-disabled=true],
.fig-card[data-approve-block] {
  --fig-card-bg: color-mix(in srgb, var(--fig-bg-subtle) 45%, var(--fig-bg-default));
  box-shadow: none;
}

/* not-allowed cursor on the footer; the locked controls drop pointer-events so a click
   never lands (the cursor still reads from the footer container), and dim individually
   so the footer greys with the rest while the danger Dismiss button stays bright.
   Two escape hatches stay live + fully opaque on a locked card: the danger Dismiss
   (always a valid reject) and Edit (`data-card-action="edit"`), so the operator can
   always open the card to fix a field / link an existing record (the identity cell's
   link-or-create combobox lives behind Edit) rather than being forced to throw the
   card away. `summary` stays in the list for any footer <details> trigger styled as
   a button. */
.fig-card[aria-disabled=true] .fig-card-actions,
.fig-card[data-approve-block] .fig-card-actions {
  cursor: not-allowed;
}

.fig-card[aria-disabled=true] .fig-card-actions :is(button, a, [role=button], summary):not([data-variant=danger]):not([data-card-action=edit]),
.fig-card[data-approve-block] .fig-card-actions :is(button, a, [role=button], summary):not([data-variant=danger]):not([data-card-action=edit]) {
  opacity: 0.6;
  filter: grayscale(0.65);
  pointer-events: none;
}

/* Header of a locked card, the piecewise dim (see the escape-hatch note above). The
   header can't dim as one block, its icon-button group holds the two always-live escape
   hatches (the Dismiss ✕ + Edit), and a child can never render brighter than an
   opacity'd ancestor. So each header piece dims individually along the path AROUND the
   icon-button group: the title row's logos + title, the cluster's chips + priority coin,
   the provenance subtitle, and inside the group anything that is NOT an escape hatch
   (Copy/Download, and the Add To Do / Postpone popover wrappers). The selectors are
   disjoint (none is an ancestor of another), so nothing double-dims. Header controls
   keep pointer-events (the hard gate is server-side); the dimmed queue moves stay
   usable, parking or to-do-ing a blocked chain dependent decides nothing, so there's
   no client lock to preserve. */
.fig-card[aria-disabled=true] > .fig-card-header .approval-card-header-top > :not(fig-cluster-layout),
.fig-card[data-approve-block] > .fig-card-header .approval-card-header-top > :not(fig-cluster-layout),
.fig-card[aria-disabled=true] > .fig-card-header .approval-card-header-top > fig-cluster-layout > :not(.fig-icon-button-group),
.fig-card[data-approve-block] > .fig-card-header .approval-card-header-top > fig-cluster-layout > :not(.fig-icon-button-group),
.fig-card[aria-disabled=true] > .fig-card-header .fig-icon-button-group > :not([data-variant=danger]):not([data-card-action=edit]),
.fig-card[data-approve-block] > .fig-card-header .fig-icon-button-group > :not([data-variant=danger]):not([data-card-action=edit]),
.fig-card[aria-disabled=true] > .fig-card-header > fig-stack-layout > :not(.approval-card-header-top),
.fig-card[data-approve-block] > .fig-card-header > fig-stack-layout > :not(.approval-card-header-top) {
  opacity: 0.6;
  filter: grayscale(0.65);
}

/* The deal card's approve-block (`data-approve-block`, set when its required Company /
   Contact parties aren't linked, `deal_party_block` in _feed_filters.py) SHARES the
   dimmed treatment above, so a gated deal reads as "waiting in the sequence"
   consistently with its greyed-out chain siblings (Contact) instead of standing fully
   lit while they dim. It keeps the same two escape hatches (Dismiss + Edit stay bright),
   so the operator can still Edit -> link an existing Company / Contact to clear it. It
   gates only on the REQUIRED parties (Company + Contact), NOT the optional Site, so the
   deal un-dims as soon as those two resolve even while the Site card is still pending. */
@media (prefers-reduced-motion: reduce) {
  .fig-card {
    transition: none;
  }
}
/* fig-chain-group, spec: fig/styles/blocks/fig-chain-group.md, edit via /design:create-or-update-block */
.fig-chain-group {
  box-sizing: border-box;
  max-inline-size: 100%;
  overflow: hidden;
  border: 1px solid var(--fig-border-default);
  border-inline-start: 3px solid var(--fig-accent-border);
  border-radius: var(--fig-border-radius-3);
  background: var(--fig-accent-bg-subtle);
}
.fig-chain-group__header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--fig-space-2);
  padding: var(--fig-space-3);
}
.fig-chain-group__header fig-cluster-layout {
  gap: var(--fig-space-1);
}
.fig-chain-group__count {
  margin-inline-start: auto;
  color: var(--fig-fg-muted);
}
.fig-chain-group__body {
  padding: 0 var(--fig-space-3) var(--fig-space-3);
}

/* fig-dashboard, the one dashboard grammar, shared by every analytics surface
   (the global Usage page, the per-skill Usage tab, the Skill Dashboards/Insights
   tab). A dashboard is an eyebrow'd stack of panels, a band of stat cards, a few
   leaderboards, and a table, all .fig-card + semantic --fig-* tokens, so it
   tracks the warm/dark/vertech themes with no hardcoded hues. This is the SSoT:
   compose these classes, never re-copy them into a page-scoped <style> under a
   new prefix (the parallel .usage-*, .skill-*, .sd-* copies are how the surfaces
   drifted apart). Loads after fig-card, every surface here is a .fig-card with a
   modifier. */
/* ── Eyebrow + section heads ──────────────────────────────────────────────── */
/* The small uppercase label that titles each panel / section. */
.fig-dash-eyebrow {
  font-size: var(--fig-text-0);
  font-weight: var(--fig-font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--fig-fg-subtle);
}

/* A section wrapper (eyebrow + a control cluster + its body), and the header
   row that edge-justifies an eyebrow against a trailing control cluster. */
.fig-dash-section {
  display: flex;
  flex-direction: column;
  gap: var(--fig-space-3);
}

.fig-dash-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fig-space-3);
  flex-wrap: wrap;
}

/* ── Cards: panel · control · stat ────────────────────────────────────────────
   Three .fig-card flavours, all padded by space-4 and laid out as a column; they
   differ only in the internal gap (a dense KPI hugs its label; a panel breathes).
   position:relative + overflow:hidden so the accent rail (::before) clips to the
   rounded corners and an absolutely-positioned affordance (e.g. clear-filters)
   anchors to the card. */
.fig-dash-panel,
.fig-dash-control-card,
.fig-dash-stat {
  position: relative;
  padding: var(--fig-space-4);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.fig-dash-panel {
  gap: var(--fig-space-3);
} /* chart / table / leaderboard section */
.fig-dash-control-card {
  gap: var(--fig-space-2);
} /* a filter card (eyebrow + control) */
.fig-dash-stat {
  gap: 0.35rem;
} /* a single KPI metric */
.fig-dash-stat__label {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: var(--fig-text-0);
  font-weight: var(--fig-font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--fig-fg-subtle);
}

.fig-dash-stat__value {
  font-size: var(--fig-text-6);
  font-weight: var(--fig-font-weight-bold);
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--fig-fg-default);
  font-variant-numeric: tabular-nums;
}

/* A KPI value can wrap a deep-link (e.g. the per-skill "Autonomous" tile jumps to
   the run feed), keep it looking like the number, not a link. */
.fig-dash-stat__value a {
  color: inherit;
  text-decoration: none;
}

.fig-dash-stat__note {
  font-size: var(--fig-text-1);
  color: var(--fig-fg-muted);
}

/* Accent rail, a 3px brand bar down the inline-start edge, marking a highlighted
   (--accent) or the active (--active, the clickable metric toggle) stat card. */
.fig-dash-stat--accent::before,
.fig-dash-stat--active::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  inline-size: 3px;
  background: var(--fig-bg-secondary);
}

/* Clickable stat cards double as a metric selector (the Usage page's tokens/cost
   toggle): reset link chrome, hint interactivity, ring + rail the active one. */
.fig-dash-stat--toggle {
  text-decoration: none;
  color: inherit;
  cursor: pointer;
  transition: border-color 0.12s ease, box-shadow 0.12s ease, transform 0.12s ease;
}

.fig-dash-stat--toggle:hover {
  border-color: color-mix(in srgb, var(--fig-bg-secondary) 45%, transparent);
}

.fig-dash-stat--active {
  border-color: var(--fig-bg-secondary);
  box-shadow: inset 0 0 0 1px var(--fig-bg-secondary);
}

/* ── Grids: KPI band · control bar · two-column ───────────────────────────────
   All auto-fit so any count of metrics / filters flows to one row on a wide page
   and wraps gracefully, no per-surface column counts or media queries. The
   min-track widths differ by content: a stat needs ~9.5rem, a filter ~11rem. */
.fig-dash-kpis {
  display: grid;
  gap: var(--fig-space-3);
  grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
}

.fig-dash-controls {
  display: grid;
  gap: var(--fig-space-3);
  align-items: stretch;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
}

/* A control card's mini GET-form is flush; its select fills the card width. */
.fig-dash-control-card form {
  margin: 0;
}

.fig-dash-control-card .fig-select {
  inline-size: 100%;
}

/* Two equal panels side by side (the Usage page's user + skill leaderboards),
   collapsing to one column on a narrow viewport. */
.fig-dash-two-col {
  display: grid;
  gap: var(--fig-space-3);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (max-width: 720px) {
  .fig-dash-two-col {
    grid-template-columns: minmax(0, 1fr);
  }
}
/* ── Leaderboard bars ─────────────────────────────────────────────────────────
   A column of [label · track · value] rows; add --ranked for a leading rank
   column. The fill is a brand gradient scaled server-side (inline width %). */
.fig-dash-bars {
  display: flex;
  flex-direction: column;
}

.fig-dash-bar {
  display: grid;
  grid-template-columns: minmax(0, 12rem) 1fr auto;
  align-items: center;
  gap: var(--fig-space-3);
  padding: 0.4rem 0.5rem;
  border-radius: var(--fig-border-radius-3);
}

.fig-dash-bars--ranked .fig-dash-bar {
  grid-template-columns: 1.25rem minmax(0, 8.5rem) 1fr auto;
}

/* The viewer's own row, tinted so they can find themselves in the board. */
.fig-dash-bar--me {
  background: color-mix(in srgb, var(--fig-bg-secondary) 10%, transparent);
}

.fig-dash-bar__rank {
  font-size: var(--fig-text-1);
  font-variant-numeric: tabular-nums;
  color: var(--fig-fg-subtle);
  text-align: end;
}

.fig-dash-bar__label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--fig-text-2);
  color: var(--fig-fg-default);
}

.fig-dash-bar__you {
  color: var(--fig-fg-subtle);
  font-weight: var(--fig-font-weight-regular);
}

.fig-dash-bar__track {
  block-size: 0.5rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--fig-fg-default) 8%, transparent);
  overflow: hidden;
}

.fig-dash-bar__fill {
  display: block;
  block-size: 100%;
  min-inline-size: 3px;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--fig-bg-secondary), color-mix(in srgb, var(--fig-bg-secondary) 55%, var(--fig-color-accent-500)));
}

.fig-dash-bar__value {
  font-size: var(--fig-text-2);
  font-weight: var(--fig-font-weight-medium);
  font-variant-numeric: tabular-nums;
  text-align: end;
  color: var(--fig-fg-default);
}

/* ── Shared bits ──────────────────────────────────────────────────────────── */
/* A label that links to a record (a skill name → its catalog page): inherit the
   row's color at rest, reveal the accent on hover. */
.fig-dash-link {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
}

.fig-dash-link:hover {
  color: var(--fig-bg-secondary);
  text-decoration: underline;
}

/* The empty state for a panel with no data in the current window. */
.fig-dash-empty {
  text-align: center;
  padding-block: var(--fig-space-6);
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-2);
}

/* fig-todo, spec: fig/styles/blocks/fig-todo.md, edit via /design:create-or-update-block */
.fig-todo-widget {
  display: flex;
  flex-direction: column;
}
.fig-todo-widget .fig-todo-body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-block-size: 0;
}
.fig-todo-widget .fig-todo-body .fig-todo-add-accordion {
  margin-block-start: auto;
}

.fig-todo-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--fig-space-1);
}

.fig-todo-row {
  display: flex;
  align-items: center;
  gap: var(--fig-space-2);
  padding: var(--fig-space-2) 0;
  border-block-end: 1px solid var(--fig-border-muted);
}
.fig-todo-row:last-child {
  border-block-end: 0;
}
.fig-todo-row__check-form {
  margin: 0;
  display: inline-flex;
}
.fig-todo-row__check {
  inline-size: var(--fig-space-4);
  block-size: var(--fig-space-4);
  border: 1px solid var(--fig-border-emphasis);
  border-radius: var(--fig-border-radius-pill);
  background: transparent;
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-0);
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}
.fig-todo-row__check:hover, .fig-todo-row__check:focus-visible {
  background: var(--fig-bg-muted);
  color: var(--fig-border-emphasis);
}
.fig-todo-row__check-glyph {
  opacity: 0;
  transition: opacity 0.1s ease;
  display: inline-flex;
}
.fig-todo-row__check-glyph > svg {
  inline-size: var(--fig-space-2);
  block-size: var(--fig-space-2);
}
.fig-todo-row:hover .fig-todo-row__check-glyph, .fig-todo-row__check:hover .fig-todo-row__check-glyph, .fig-todo-row__check:focus-visible .fig-todo-row__check-glyph {
  opacity: 1;
}
.fig-todo-row__main {
  flex: 1 1 auto;
  min-inline-size: 0;
  display: flex;
  flex-direction: column;
  gap: var(--fig-space-0);
}
.fig-todo-row__text {
  min-inline-size: 0;
  color: var(--fig-fg-default);
  font-size: var(--fig-text-1);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fig-todo-row__note {
  min-inline-size: 0;
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-0);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fig-todo-row__due {
  flex: 0 0 auto;
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-0);
  white-space: nowrap;
  background: none;
  border: 0;
  padding: 0;
  font-family: inherit;
}
.fig-todo-row__due[data-overdue] {
  color: var(--fig-status-danger-fg);
  font-weight: var(--fig-font-weight-medium);
}

.fig-todo-add {
  margin-block-start: var(--fig-space-3);
}
.fig-todo-add .fig-field {
  inline-size: auto;
}
.fig-todo-add__title {
  flex: 1 1 auto;
  min-inline-size: 0;
}
.fig-todo-add__prio {
  flex: 0 0 auto;
  inline-size: var(--fig-container--3);
  align-items: center;
}
.fig-todo-add__prio .fig-select {
  inline-size: 100%;
}
.fig-todo-add__note {
  inline-size: 100%;
}
.fig-todo-add__note-toggle {
  cursor: pointer;
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-2);
  list-style: none;
  user-select: none;
}
.fig-todo-add__note-toggle::-webkit-details-marker {
  display: none;
}
.fig-todo-add__note-input {
  inline-size: 100%;
  margin-block-start: var(--fig-space-1);
  resize: vertical;
}
.fig-todo-add__presets {
  flex-wrap: nowrap;
}
.fig-todo-add__presets .fig-button {
  flex: 1 1 0;
  min-inline-size: 0;
}
.fig-todo-add__date-field {
  flex: 1 1 auto;
  min-inline-size: 0;
}
.fig-todo-add__submit {
  flex: 0 0 auto;
}
.fig-todo-add__date-row {
  align-items: flex-end;
}

.fig-todo-line-pop .fig-todo-add,
.add-todo-pop .fig-todo-add {
  margin-block-start: 0;
}

.fig-todo-add-card {
  margin-block-end: var(--fig-space-5);
}
.fig-todo-add-card .fig-todo-add {
  margin-block-start: 0;
}

.fig-todo-add-accordion__toggle {
  cursor: pointer;
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-1);
  font-weight: var(--fig-font-weight-medium);
  list-style: none;
  user-select: none;
  padding-block: var(--fig-space-1);
}
.fig-todo-add-accordion__toggle::-webkit-details-marker {
  display: none;
}
.fig-todo-add-accordion__toggle:hover {
  color: var(--fig-fg-default);
}

.fig-todo-body__count {
  font-size: var(--fig-text-0);
  color: var(--fig-fg-muted);
}

.fig-todo-body__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fig-space-2);
  margin-block-start: var(--fig-space-3);
  font-size: var(--fig-text-0);
  color: var(--fig-fg-muted);
}

.fig-todo-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--fig-space-2);
  margin-block-end: var(--fig-space-3);
  padding-block-end: var(--fig-space-2);
  border-block-end: 1px solid var(--fig-border-muted);
}

.fig-todo-count {
  flex: 0 0 auto;
  font-size: var(--fig-text-1);
  color: var(--fig-fg-muted);
}
.fig-todo-count__overdue {
  color: var(--fig-status-danger-fg);
  font-weight: var(--fig-font-weight-medium);
}

.fig-todo-group {
  margin-block-end: var(--fig-space-5);
}
.fig-todo-group__head {
  display: flex;
  align-items: baseline;
  gap: var(--fig-space-1);
  margin-block-end: var(--fig-space-2);
}
.fig-todo-group__count {
  color: var(--fig-fg-subtle);
  font-weight: var(--fig-font-weight-regular);
}
.fig-todo-group .fig-todo-list {
  gap: var(--fig-space-2);
}
.fig-todo-group .fig-todo-row {
  align-items: flex-start;
  flex-wrap: wrap;
  gap: var(--fig-space-2) var(--fig-space-3);
  padding: var(--fig-space-3);
  background: var(--fig-bg-subtle);
  border: 1px solid var(--fig-border-muted);
  border-radius: var(--fig-border-radius-3);
  border-inline-start: var(--fig-space-1) solid var(--fig-border-muted);
  box-shadow: var(--fig-shadow-1);
}
.fig-todo-group .fig-todo-row[data-priority=p0] {
  border-inline-start-color: var(--fig-bg-danger);
}
.fig-todo-group .fig-todo-row[data-priority=p1] {
  border-inline-start-color: var(--fig-bg-emphasis);
}
.fig-todo-group .fig-todo-row[data-priority=p2] {
  border-inline-start-color: var(--fig-bg-secondary);
}
.fig-todo-group .fig-todo-row[data-priority=p3] {
  border-inline-start-color: var(--fig-border-emphasis);
}
.fig-todo-group .fig-todo-row.fig-todo-row--overdue {
  background: color-mix(in srgb, var(--fig-status-danger-bg) 40%, var(--fig-bg-subtle));
  border-color: var(--fig-status-danger-border);
  border-inline-start-color: var(--fig-status-danger-border);
}
.fig-todo-group .fig-todo-row.fig-todo-row--overdue .fig-todo-row__check {
  border-color: var(--fig-status-danger-border);
  color: var(--fig-status-danger-fg);
}
.fig-todo-group .fig-todo-row.fig-todo-row--overdue .fig-todo-row__check:hover, .fig-todo-group .fig-todo-row.fig-todo-row--overdue .fig-todo-row__check:focus-visible {
  background: var(--fig-status-danger-bg);
  color: var(--fig-status-danger-fg);
}
.fig-todo-group .fig-todo-row.fig-todo-row--overdue .fig-icon-button {
  border-color: var(--fig-status-danger-border);
  color: var(--fig-status-danger-fg);
}
.fig-todo-group .fig-todo-row .fig-todo-row__main {
  gap: var(--fig-space-1);
}
.fig-todo-group .fig-todo-row .fig-todo-row__text {
  white-space: normal;
  font-weight: var(--fig-font-weight-medium);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.fig-todo-group .fig-todo-row .fig-todo-row__note {
  white-space: normal;
  line-height: var(--fig-line-height-snug);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
}

.fig-todo-row__headline {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--fig-space-2);
}
.fig-todo-row__headline .fig-todo-row__text {
  flex: 1 1 auto;
}
.fig-todo-row__headline .fig-todo-row__due-edit,
.fig-todo-row__headline .fig-todo-row__due {
  flex: 0 0 auto;
}

.fig-todo-row__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--fig-space-2);
  margin-block-start: var(--fig-space-1);
}
.fig-todo-row__meta .fig-todo-row__more {
  margin-inline-start: auto;
}

.fig-todo-row__card,
.fig-todo-row__hs-push {
  flex: 0 0 auto;
  white-space: nowrap;
}

.fig-priority-picker {
  display: inline-flex;
}
.fig-priority-picker__trigger {
  display: inline-flex;
  align-items: center;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.fig-priority-picker__menu {
  display: flex;
  flex-direction: column;
  gap: var(--fig-space-1);
  min-inline-size: var(--fig-container--2);
  padding: var(--fig-space-2);
}
.fig-priority-picker__opt {
  display: flex;
  align-items: center;
  gap: var(--fig-space-2);
  text-align: start;
  background: none;
  border: 0;
  border-radius: var(--fig-border-radius-2);
  padding: var(--fig-space-1) var(--fig-space-2);
  cursor: pointer;
  color: var(--fig-fg-default);
  font: inherit;
  font-size: var(--fig-text-1);
}
.fig-priority-picker__opt:hover {
  background: var(--fig-bg-muted);
}

.fig-todo-row__due-edit {
  display: inline-flex;
}

.fig-todo-row__due-menu {
  display: flex;
  flex-direction: column;
  gap: var(--fig-space-2);
  padding: var(--fig-space-2);
}

.fig-todo-row__due-clear {
  text-align: start;
  background: none;
  border: 0;
  padding: var(--fig-space-1) var(--fig-space-2);
  border-radius: var(--fig-border-radius-2);
  cursor: pointer;
  color: var(--fig-fg-muted);
  font: inherit;
  font-size: var(--fig-text-1);
}
.fig-todo-row__due-clear:hover {
  background: var(--fig-bg-muted);
  color: var(--fig-fg-default);
}

.fig-todo-row__more {
  flex: 0 0 auto;
}

.fig-todo-row__more-trigger {
  background: none;
  border: 0;
  padding: 0 var(--fig-space-1);
  cursor: pointer;
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-3);
  line-height: 1;
}
.fig-todo-row__more-trigger:hover {
  color: var(--fig-fg-default);
}

.fig-todo-row__more-menu {
  display: flex;
  flex-direction: column;
  gap: var(--fig-space-1);
  min-inline-size: var(--fig-container--2);
  padding: var(--fig-space-2);
}

.fig-todo-row__more-opt {
  display: flex;
  align-items: center;
  gap: var(--fig-space-2);
  text-align: start;
  background: none;
  border: 0;
  border-radius: var(--fig-border-radius-2);
  padding: var(--fig-space-1) var(--fig-space-2);
  cursor: pointer;
  color: var(--fig-fg-default);
  font: inherit;
  font-size: var(--fig-text-1);
}
.fig-todo-row__more-opt:hover {
  background: var(--fig-bg-muted);
}

.fig-todo-row__open {
  flex: 1 1 auto;
  min-inline-size: 0;
  text-align: start;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: var(--fig-fg-default);
  font: inherit;
  font-size: var(--fig-text-1);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fig-todo-row__open:hover {
  color: var(--fig-accent-fg);
  text-decoration: underline;
}

.fig-approval-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--fig-space-1);
  margin-block-end: var(--fig-space-2);
}

.fig-approval-count {
  font-weight: var(--fig-font-weight-semibold);
  color: var(--fig-fg-muted);
}

.fig-todo-widget__sort {
  display: flex;
  flex: 0 0 auto;
  gap: var(--fig-space-1);
}

.fig-todo-popover__trigger {
  position: relative;
}
.fig-todo-popover__badge {
  position: absolute;
  inset-block-start: 0;
  inset-inline-end: 0;
  transform: translate(25%, -25%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: var(--fig-space-3);
  block-size: var(--fig-space-3);
  padding: 0 var(--fig-space-1);
  border-radius: var(--fig-border-radius-pill);
  background: var(--fig-bg-emphasis);
  color: var(--fig-fg-inverse);
  font-size: var(--fig-text-1);
  line-height: 1;
  font-weight: var(--fig-font-weight-semibold);
}
.fig-todo-popover__badge[data-overdue] {
  background: var(--fig-bg-danger);
}
.fig-todo-popover__panel {
  min-inline-size: var(--fig-container-1);
}

/* fig-todo-line — per-bullet "save to-do" affordance on itemized card bodies.
 *
 * A "+" button injected into a left gutter beside every bullet, at every nesting
 * tier, of a sections-layout card body (briefs today, any itemized card later) —
 * each nested <ul> supplies the same gutter its parent list has. Faint at rest so
 * the gutter still reads as a list; brightens on row hover / keyboard focus; clicking
 * opens the shared line-add popover. Behaviour: fig-todo-line.js. The popover reuses
 * the quick-add form (_todo_add_form.html) and the panel chrome below mirrors
 * .fig-popover-panel, but it is positioned by JS (position:fixed, set inline) rather
 * than anchored to a trigger, so it manages its own visibility via [data-open].
 */
/* Decorated bullet: the "+" is absolutely positioned into the gutter the list
   marker vacated, so the li's own text stays a single continuous inline run. A
   flex row here would split the leading `<strong>label</strong>` and the `: body`
   run into separate flex items — the `gap` then opens a space before the colon and
   squeezes the trailing `<sup>` citations into their own wrapping columns. */
.fig-todo-line {
  position: relative;
  list-style: none;
}

.fig-todo-line__add {
  position: absolute;
  inset-inline-start: -1.55em; /* the gutter the list marker vacated */
  inset-block-start: 0.05em; /* nudge onto the first text line */
  inline-size: 1.3em;
  block-size: 1.3em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--fig-border-radius-2);
  background: transparent;
  color: var(--fig-fg-muted);
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  opacity: 0.3; /* faint at rest — the gutter still reads, no reflow on hover */
  transition: opacity var(--fig-duration-1) var(--fig-ease-1), background-color var(--fig-duration-1) var(--fig-ease-1), color var(--fig-duration-1) var(--fig-ease-1);
}

/* Reveal on row hover OR keyboard focus — never hover-only (keyboard + SR reach). */
.fig-todo-line:hover .fig-todo-line__add,
.fig-todo-line:focus-within .fig-todo-line__add,
.fig-todo-line__add:focus-visible {
  opacity: 1;
}

.fig-todo-line__add:hover {
  background: var(--fig-bg-subtle);
  color: var(--fig-fg-default);
}

.fig-todo-line__add:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 1px;
}

/* Saved confirmation — stays visible, no longer interactive. */
.fig-todo-line__add--saved,
.fig-todo-line__add--saved:hover {
  opacity: 1;
  color: var(--fig-status-success-fg);
  background: transparent;
  cursor: default;
}

/* The shared line-add popover (one per card body, JS-positioned). Mirrors the
   .fig-popover-panel chrome; visibility is driven by [data-open], not a parent
   .fig-popover, because the JS anchors it to an arbitrary bullet. */
.fig-todo-line-pop {
  display: none;
  /* Above the 1065 popover band. The in-page modal (fig-modal) is a top-layer
     <dialog> no z-index can clear, so fig-todo-line.js portals the panel INTO
     the open dialog (not <body>) when the bullet lives there; this z only has
     to win within its own context (page or dialog). The portal itself exists
     to escape the card column's scroll-fade mask, which is a containing block
     that clips position:fixed descendants. */
  z-index: 1110;
  /* Sized to hold the flat add-to-do form (title + priority, description, due row),
     matching the card popover's `m` band. */
  inline-size: var(--fig-container-2);
  max-inline-size: min(var(--fig-container-2), 100vw - var(--fig-space-6));
  padding: var(--fig-space-2);
  border: 1px solid var(--fig-border-default);
  border-radius: var(--fig-border-radius-4);
  color: var(--fig-fg-default);
  background-color: var(--fig-bg-subtle);
  box-shadow: var(--fig-shadow-4);
}

.fig-todo-line-pop[data-open] {
  display: block;
}

/* fig-table, spec: fig/styles/blocks/fig-table.md, edit via /design:create-or-update-block
   Ported subset from fig-app for figclaw command_center. Drops tfoot +
   data-editable exception; figclaw renders tables flat (no inline form controls,
   no totals row yet). Re-add when a real consumer needs them. */
/* Horizontal-scroll wrapper. A multi-column table (the audit log: When · Plugin ·
   Skill · Actor · Event · Outcome) is wider than a phone, and the table's own
   `overflow: hidden` (rounded corners) would CLIP the right-hand columns. Wrap
   every fig-table in this so a narrow viewport scrolls the table sideways instead
   of losing columns; on desktop it never overflows, so the scrollbar never shows. */
.fig-table-scroll {
  overflow-x: auto;
  overscroll-behavior-x: contain;
}

/* Full-bleed variant, break the wrapper out of the page's padded center
   layout so the table spans the full viewport width (wide data pages: audit
   log, skill registry). Negative inline margins of exactly the parent's
   padding pull both edges to the viewport: 50% is the parent content half-width
   (= 50vw − padding), so each margin resolves to −padding and the block's auto
   width grows to 100vw, regardless of which padding the page declared. */
.fig-table-scroll[data-bleed] {
  margin-inline: calc(50% - 50vw);
}

.fig-table {
  inline-size: 100%;
  border-collapse: collapse;
  border-spacing: 0;
  background-color: var(--fig-bg-subtle);
  color: var(--fig-fg-default);
  border: 1px solid var(--fig-border-default);
  border-radius: var(--fig-border-radius-4);
  overflow: hidden;
  /* Three row tints, declared once so every consumer (zebra base + stripe, hover,
     an open/active row) references the same value. All stay on the neutral ramp,
     no off-palette white. The resting bands tint the surface toward the theme-aware
     fg, so they auto-flip; `active` is the row-lift for hover / an open row. */
  --fig-table-row-base: color-mix(in srgb, var(--fig-bg-subtle) 95%, var(--fig-fg-default) 5%);
  --fig-table-row-stripe: color-mix(in srgb, var(--fig-bg-subtle) 88%, var(--fig-fg-default) 12%);
  /* Light: the card surface is already the lightest neutral, so a hovered / open
     row returns to the clean surface and reads bright against the tinted bands. */
  --fig-table-row-active: var(--fig-bg-subtle);
}

/* Dark: the surface is the DARKEST neutral, so "clean surface" would sink. Lift to
   a higher ramp step that clears the stripe band and keeps light text legible.
   Mirrors the two selectors the semantic tokens flip on (toggle + system pref). */
[data-theme=dark] .fig-table {
  --fig-table-row-active: var(--fig-color-neutral-600);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme=light]) .fig-table {
    --fig-table-row-active: var(--fig-color-neutral-600);
  }
}
.fig-table th,
.fig-table td {
  padding-block: var(--fig-space-1);
  padding-inline: var(--fig-space-2);
  font-size: var(--fig-text-2);
  text-align: start;
  vertical-align: middle;
  border-inline-end: 1px solid var(--fig-border-muted);
  border-block-end: 1px solid var(--fig-border-muted);
}

.fig-table th:last-child,
.fig-table td:last-child {
  border-inline-end: none;
}

.fig-table thead th {
  background-color: var(--fig-bg-muted);
  color: var(--fig-fg-default);
  font-weight: var(--fig-font-weight-semibold);
  border-block-end: 1px solid var(--fig-border-default);
  user-select: none;
}

.fig-table tbody tr td {
  background-color: var(--fig-table-row-base);
}

.fig-table tbody tr:nth-child(even) td {
  background-color: var(--fig-table-row-stripe);
}

.fig-table tbody tr:hover td {
  background-color: var(--fig-table-row-active);
}

.fig-table tbody tr:last-child td {
  border-block-end: none;
}

/* -- Exceptions (state variants) -- */
.fig-table[data-borderless] {
  border-color: transparent;
}

.fig-table[data-borderless] th,
.fig-table[data-borderless] td {
  border-inline-end-color: transparent;
}

/* Width-priority columns, opt in per <th>/<td> with data-nowrap so the
   cell never wraps and claims the width it needs; unmarked columns keep
   wrapping and absorb the remainder. */
.fig-table th[data-nowrap],
.fig-table td[data-nowrap] {
  white-space: nowrap;
}

/* fig-input, spec: fig/styles/blocks/fig-input.md, edit via /design:create-or-update-block */
.fig-input {
  /* Strip native platform chrome (Safari/Chrome type="search" round-cornered inner
     pill; Firefox search field chrome) so our tokens own the visual language. */
  appearance: none;
  -webkit-appearance: none;
  display: block;
  /* Default fills its parent's row; consumers that want a content-sized input
     (e.g. small numeric input inline in a footer cluster) override via inline
     style: `style="--fig-input-inline-size: 8ch"`. Custom-property assignments
     are an allowed inline-style category. */
  inline-size: var(--fig-input-inline-size, 100%);
  padding-block: var(--fig-space-2);
  padding-inline: var(--fig-space-3);
  font-family: inherit;
  font-size: var(--fig-text-3);
  line-height: var(--fig-line-height-snug);
  color: var(--fig-fg-default);
  /* Transparent default, input blends into parent surface (cards, banners,
     minimal gate forms). Consumers that want a filled input override via
     inline style or a page-local rule, e.g. `background-color: var(--fig-bg-muted)`. */
  background-color: transparent;
  border: 1px solid var(--fig-border-default);
  border-radius: var(--fig-border-radius-2);
  transition: border-color var(--fig-duration-2) var(--fig-ease-2), box-shadow var(--fig-duration-2) var(--fig-ease-2);
}

/* Suppress the native Webkit clear-X button on type="search", consumers slot
   their own clear button via the fig-search-bar trailing slot. */
.fig-input::-webkit-search-decoration,
.fig-input::-webkit-search-cancel-button,
.fig-input::-webkit-search-results-button,
.fig-input::-webkit-search-results-decoration {
  appearance: none;
  -webkit-appearance: none;
}

/* Chromium's date/time inputs grow past the button-height contract: the shadow
   fields-wrapper carries 1px UA block padding and the calendar glyph's padded
   box overshoots the line box by another 1px. Flatten both so a date input
   measures exactly like a text input (and therefore like a default button). */
.fig-input::-webkit-datetime-edit-fields-wrapper {
  padding-block: 0;
}

.fig-input::-webkit-calendar-picker-indicator {
  padding-block: 0;
  block-size: var(--fig-text-3);
}

.fig-input::placeholder {
  color: var(--fig-fg-subtle);
}

.fig-input:hover {
  border-color: var(--fig-border-emphasis);
}

.fig-input:focus-visible {
  outline: none;
  border-color: var(--fig-secondary-border);
  box-shadow: 0 0 0 2px var(--fig-secondary-border);
}

/* -- Exceptions (state variants) -- */
/* Error chrome uses the --fig-bg-danger fill anchor (hue-true 500), not the
   -fg text ink, mirroring how the normal focus ring uses the secondary-500
   anchor: inks are darkened per-mode for text contrast and hue-shift when
   painted as decoration. */
.fig-input[data-state=error] {
  border-color: var(--fig-bg-danger);
}

.fig-input[data-state=error]:focus-visible {
  box-shadow: 0 0 0 2px var(--fig-bg-danger);
}

.fig-input[disabled] {
  opacity: 0.6;
  cursor: not-allowed;
}

/* Bare exception, opt-in via data-shape="bare" when the input lives inside a
   surface that already owns padding + borders (e.g. a fig-table[data-editable]
   <td>). Strips the input's own chrome so it visually merges with its host
   cell. Focus ring still appears, anchored to the input's border-radius for
   discoverability. */
.fig-input[data-shape=bare] {
  padding: 0;
  border: 0;
  border-radius: 0;
  background-color: transparent;
}

.fig-input[data-shape=bare]:hover {
  border: 0;
}

.fig-input[data-shape=bare]:focus-visible {
  border: 0;
  border-radius: var(--fig-border-radius-1);
  box-shadow: 0 0 0 2px var(--fig-secondary-border);
}

/* Filled exception, opt-in via data-shape="filled" when the input lives inside a
   muted/subtle modal-config surface (Transform Advanced tab, similar dense form
   contexts) where the default transparent + faint border reads as a banded row.
   Fills with bg-default (white on light) + emphasis-tier border so the field
   reads as a discrete editable element. Hover/focus rules inherited unchanged. */
.fig-input[data-shape=filled] {
  background-color: var(--fig-bg-default);
  border-color: var(--fig-border-emphasis);
}

/* Native-picker glyphs (the calendar/clock indicator on date/datetime/time
   inputs, spin buttons on number) draw their color from the element's
   color-scheme, NOT our tokens, so under the dark theme they stay near-black
   and vanish against the dark field. Telling the input it's dark inverts the
   webkit picker indicator to a light stroke. Scoped to the explicit toggle;
   OS-auto dark is disabled (see _fig-semantic.scss). */
[data-theme=dark] .fig-input {
  color-scheme: dark;
}

@media (prefers-reduced-motion: reduce) {
  .fig-input {
    transition: none;
  }
}
/* fig-select, generic styled native <select>.
   Lifted out of the filter bar (was .fig-filter-bar__select) so any surface can
   reuse the same paint: appearance suppressed, custom chevron via inline SVG in
   currentColor (tracks fg in light/dark), same fill/border as the fig field
   inputs (login's .fig-field__input). Default arrow killed; the chevron sits in
   the inline-end padding gutter. */
.fig-select {
  appearance: none;
  min-inline-size: 8rem;
  padding-block: var(--fig-space-1);
  padding-inline: var(--fig-space-2) var(--fig-space-6);
  border: 1px solid var(--fig-border-default);
  border-radius: var(--fig-border-radius-1);
  background-color: var(--fig-bg-subtle);
  color: var(--fig-fg-default);
  font-size: var(--fig-text-2);
  line-height: 1.4;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='currentColor' stroke-width='1.5'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--fig-space-2) center;
  background-size: 1em;
  transition: border-color var(--fig-duration-1) var(--fig-ease-2);
}

.fig-select:hover {
  border-color: var(--fig-border-emphasis);
}

.fig-select:focus-visible {
  outline: 2px solid var(--fig-accent-border);
  outline-offset: 1px;
}

/* -- Size axis --
   `xs` shrinks padding + drops one type step + tightens the width floor, the
   dense filter-bar row where width is at a premium (mirrors fig-button's xs). */
.fig-select[data-size=xs] {
  min-inline-size: 6.5rem;
  padding-block: var(--fig-space-0);
  padding-inline: var(--fig-space-1) var(--fig-space-5);
  font-size: var(--fig-text-1);
}

@media (prefers-reduced-motion: reduce) {
  .fig-select {
    transition: none;
  }
}
/* fig-field, spec: fig/styles/blocks/fig-field.md, edit via /design:create-or-update-block */
.fig-field {
  display: flex;
  flex-direction: column;
  gap: var(--fig-space-1);
  inline-size: 100%;
}

.fig-field__label {
  display: block;
  font-size: var(--fig-text-2);
  font-weight: var(--fig-font-weight-medium);
  color: var(--fig-fg-default);
}

/* The generic input blocks own the control's paint and the default-button
   height contract, a field control carries `fig-input` (or `fig-select`) in
   its markup beside this class. This class adds only the field-context fill:
   fields sit on card/popover surfaces where the generic transparent input
   would vanish. */
.fig-field__input {
  background-color: var(--fig-bg-muted);
}

.fig-field__help {
  font-size: var(--fig-text-2);
  color: var(--fig-fg-subtle);
}

.fig-field__error {
  font-size: var(--fig-text-2);
  color: var(--fig-status-danger-fg);
}

/* -- Exceptions (state variants) -- */
.fig-field[data-error=true] .fig-field__input {
  border-color: var(--fig-status-danger-border);
}

.fig-field[data-layout=inline] {
  display: grid;
  grid-template-columns: minmax(8rem, max-content) 1fr;
  align-items: center;
  gap: var(--fig-space-3);
}

.fig-field[data-layout=inline] .fig-field__label {
  text-align: end;
}

/* Inline layout shrinks the input to match a `data-size="sm"` button so
   card-footer toggles (input + Approve/Reject) line up at one height. */
.fig-field[data-layout=inline] .fig-field__input {
  padding-block: var(--fig-space-1);
  padding-inline: var(--fig-space-2);
  font-size: var(--fig-text-2);
}

/* fig-schedule, friendly schedule picker over a raw cron field.
   Template: templates/design_system/blocks/fig_schedule_field.html
   Behavior: javascript/fig-schedule.js

   The frequency/time/day pickers are progressive enhancement that write into a
   hidden cron <input>; the builder fields share one row, the day-of-week ticks
   wrap, and the cron field hides behind an Advanced <details>. */
[data-schedule] [hidden] {
  display: none !important;
}

/* Builder fields share the row (.fig-field is inline-size:100% by default,
   which would wrap each onto its own full-width line). */
[data-schedule] [data-schedule-builder] .fig-field {
  flex: 1 1 0;
  inline-size: auto;
  min-inline-size: 0;
}

[data-schedule] .fig-schedule-dows {
  display: flex;
  flex-wrap: wrap;
  gap: var(--fig-space-2);
}

[data-schedule] .fig-schedule-dows label {
  display: inline-flex;
  align-items: center;
  gap: var(--fig-space-1);
  font-size: var(--fig-text-2);
}

[data-schedule] [data-schedule-preview]:not(:empty) {
  color: var(--fig-fg-muted);
  font-style: italic;
}

[data-schedule] [data-schedule-advanced] summary {
  cursor: pointer;
  font-size: var(--fig-text-2);
  color: var(--fig-fg-muted);
}

/* fig-record-search, the record_search edit widget's combobox.

   A text input (the typeahead) over a hidden id input, with a floating results
   list htmx swaps in. Used by design_system/blocks/_edit_widget.html (kind=
   record_search) for a card's live CRM-record fields (contact / company / owner).
   Behavior (click-to-select, click-outside-close) is fig-record-search.js. */
.fig-record-search {
  position: relative;
}

/* Floating option list, overlays content below the input, like a native
   <datalist>/<select> popup. Empty by default; fig-record-search.js clears it on
   select or click-outside, htmx fills it on input. */
.fig-record-search__results:not(:empty) {
  position: absolute;
  z-index: 1065; /* same band as fig-popover panels */
  inset-inline: 0;
  margin-block-start: var(--fig-space-1);
  max-block-size: var(--fig-container--1);
  overflow-y: auto;
  padding: var(--fig-space-1);
  border: 1px solid var(--fig-border-default);
  border-radius: var(--fig-border-radius-4);
  background-color: var(--fig-bg-subtle);
  box-shadow: var(--fig-shadow-4);
}

.fig-record-search__option {
  display: block;
  inline-size: 100%;
  text-align: start;
  padding: var(--fig-space-1) var(--fig-space-2);
  border: 0;
  border-radius: var(--fig-border-radius-2);
  color: var(--fig-fg-default);
  background: transparent;
  cursor: pointer;
  font: inherit;
  /* Hover, keyboard focus, AND the keyboard-active option the combobox tracks
     via aria-activedescendant (Arrow keys) all read the same highlight, so mouse
     and keyboard selection look identical. */
}
.fig-record-search__option:hover, .fig-record-search__option:focus-visible, .fig-record-search__option[aria-selected=true] {
  background-color: var(--fig-bg-emphasis);
}

.fig-record-search__empty {
  padding: var(--fig-space-1) var(--fig-space-2);
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-2);
}

/* fig-nav, spec: fig/styles/blocks/fig-nav.md, edit via /design:create-or-update-block */
/* ------------------------------------------------------------------
   Topbar shell. Container-query'd: collapses to two stacked rows
   below --fig-container-4 (768px). Wide = one sticky row.
   Narrow = brand row scrolls + tabs row sticky.
   Body ("app" container) is declared in _fig-globals.scss.
   ------------------------------------------------------------------ */
/* Published nav height, the SSoT for "how tall is the topbar" so sticky content
   below it (e.g. the filter sidebar) offsets by one constant. Composed from the
   tokens that actually produce the wide single-row height (see the wide-layout
   block below): the brand logo (--fig-space-5) + the brand-row's block padding
   (--fig-space-3 top & bottom) + the nav's own 1px bottom-border hairline. Derived,
   not a magic number, it tracks logo/padding token changes automatically. (The 1px
   mirrors `.fig-nav` border-block-end just below; hairline borders are raw 1px
   everywhere, there is no border-width token to reference.) */
:root {
  --fig-nav-height: calc(var(--fig-space-5) + var(--fig-space-3) * 2 + 1px);
}

.fig-nav {
  background-color: var(--fig-bg-subtle);
  border-block-end: 1px solid var(--fig-border-muted);
}

.fig-nav__inner {
  display: flex;
  flex-direction: column;
}

.fig-nav__brand-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Wrap the account/links group below the brand on a narrow phone rather than
     overflowing the row. */
  flex-wrap: wrap;
  gap: var(--fig-space-3);
  padding-block: var(--fig-space-3);
  padding-inline: var(--fig-space-4);
}

.fig-nav__brand {
  display: flex;
  align-items: center;
  gap: var(--fig-space-2);
  color: var(--fig-fg-default);
  font-size: var(--fig-text-3);
  font-weight: var(--fig-font-weight-bold);
  text-decoration: none;
}

.fig-nav__brand-logo {
  block-size: var(--fig-space-5);
  inline-size: auto;
}

/* Light/dark brand-logo swap. Only engages when a client ships both variants
   (the --light/--dark modifiers); a single unmodified logo is untouched and
   shows in both themes. Dark variant hidden by default (light nav), shown when
   the theme is dark, either opted in via [data-theme="dark"] or auto via
   prefers-color-scheme (unless the user opted into light). Mirrors the token
   files' theme selectors. */
.fig-nav__brand-logo--dark {
  display: none;
}

[data-theme=dark] .fig-nav__brand-logo--light {
  display: none;
}
[data-theme=dark] .fig-nav__brand-logo--dark {
  display: inline-block;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme=light]) .fig-nav__brand-logo--light {
    display: none;
  }
  :root:not([data-theme=light]) .fig-nav__brand-logo--dark {
    display: inline-block;
  }
}
.fig-nav__tabs-row {
  display: flex;
  align-items: stretch;
  padding-inline: var(--fig-space-4);
  background-color: var(--fig-bg-subtle);
  position: sticky;
  top: 0;
  z-index: 10;
}

.fig-nav__tabs-row > .fig-tabs {
  flex-grow: 1;
}

/* Demo pack/client picker, rides in the tabs row, right of the last tab (the
   public demo's only chrome; absent on every authed page). Centered against the
   tabs' stretch height; its forms keep their inline-styled selects. */
.fig-nav__demo {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--fig-space-4);
}

.fig-nav__demo-form {
  display: flex;
  align-items: center;
  gap: var(--fig-space-2);
  margin: 0;
}

.fig-nav__end {
  display: flex;
  align-items: center;
  gap: var(--fig-space-2);
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-2);
}

/* The round icon buttons (settings + theme toggle) cluster as one control group
   via the shared .fig-icon-button-group (gap --fig-space-1), the same class the
   catalog's card/table toggle uses, so the two never drift. */
/* -- Legacy link-list slots (kept for non-tabs consumers) -- */
.fig-nav__items {
  display: flex;
  align-items: center;
  gap: var(--fig-space-3);
  flex-grow: 1;
  margin: 0;
  padding: 0;
  list-style: none;
}

.fig-nav__item {
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-3);
  font-weight: var(--fig-font-weight-regular);
  text-decoration: none;
}

.fig-nav__item:hover,
.fig-nav__item:focus-visible {
  color: var(--fig-fg-default);
}

.fig-nav__item[data-current=true],
.fig-nav__item[aria-current=page] {
  color: var(--fig-bg-emphasis);
  font-weight: var(--fig-font-weight-semibold);
}

/* -- Wide layout: flatten into one sticky row -- */
@container app (min-width: 48rem) /* --fig-container-4 */ {
  .fig-nav {
    position: sticky;
    top: 0;
    z-index: 10;
  }
  /* Single-row 3-col grid pinned by named areas: brand + tabs packed at the
     left (the tabs live right next to the logo), end pushed right by the
     trailing 1fr track. Named areas make the layout intent visible at the
     parent and pin every child to row 1, prevents grid auto-placement from
     spilling later DOM siblings into an implicit row 2. Brand + tabs span the
     full nav height (labels center inside); end stays at its natural height,
     centered. Active tab's bottom border still lands ON fig-nav's bottom
     border. */
  .fig-nav__inner {
    display: grid;
    grid-template-columns: auto auto 1fr;
    grid-template-areas: "brand tabs end";
    column-gap: var(--fig-space-5);
    align-items: stretch;
    padding-block: 0;
    padding-inline: var(--fig-space-4);
  }
  /* Brand row dissolves so brand + end land in their own grid areas. The tabs
     row stays a flex box (the `tabs` area) so the tabs and the optional demo
     picker ride together on row 1, picker pinned right of the last tab. */
  .fig-nav__brand-row {
    display: contents;
  }
  .fig-nav__tabs-row {
    grid-area: tabs;
    position: static;
    display: flex;
    align-items: stretch;
    gap: var(--fig-space-4);
  }
  .fig-nav__brand {
    grid-area: brand;
    justify-self: start;
    display: flex;
    align-items: center;
    padding-block: var(--fig-space-3);
  }
  .fig-nav__tabs-row > .fig-tabs {
    display: flex;
    align-items: stretch;
    border-block-end: none;
  }
  .fig-nav__end {
    grid-area: end;
    justify-self: end;
    align-self: center;
  }
}
/* -- Modal open: un-stick the nav -- */
/* Chromium compositing bug: with `body` as the app @container (container-type
   in _fig-globals.scss), the sticky nav's composited layer paints over every
   fixed and even top-layer element — an open <dialog>'s scrim included — leaving
   an undimmed nav strip across the top of the modal overlay. Un-stick the nav
   while any modal dialog is open: it sits behind the scrim then anyway, layout
   doesn't shift (sticky/static occupy the same flow position), and stickiness
   returns the moment the dialog closes. */
body:has(dialog:modal) .fig-nav,
body:has(dialog:modal) .fig-nav__tabs-row {
  position: static;
}

/* fig-tabs, spec: fig/styles/blocks/fig-tabs.md, edit via /design:create-or-update-block */
.fig-tabs {
  border-block-end: 1px solid var(--fig-border-default);
}

.fig-tabs-tab {
  display: inline-flex;
  align-items: center;
  gap: var(--fig-space-2);
  padding-block: var(--fig-space-2);
  padding-inline: var(--fig-space-1);
  margin-block-end: -1px;
  border: 0;
  border-block-end: 2px solid transparent;
  background: transparent;
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-2);
  font-weight: var(--fig-font-weight-medium);
  line-height: 1.4;
  white-space: nowrap;
  cursor: pointer;
  text-decoration: none;
  transition: color var(--fig-duration-1) var(--fig-ease-2), border-color var(--fig-duration-1) var(--fig-ease-2);
}

.fig-tabs-tab:hover {
  color: var(--fig-fg-default);
}

.fig-tabs-tab:focus-visible {
  outline: 2px solid var(--fig-accent-border);
  outline-offset: 2px;
  border-radius: var(--fig-border-radius-1);
}

/* -- Exceptions (state variants) -- */
.fig-tabs-tab[aria-selected=true] {
  color: var(--fig-fg-default);
  font-weight: var(--fig-font-weight-semibold);
  border-block-end-color: var(--fig-secondary-fg);
}

.fig-tabs-tab[aria-disabled=true] {
  color: var(--fig-fg-subtle);
  cursor: not-allowed;
}

.fig-tabs-tab[aria-disabled=true]:hover {
  color: var(--fig-fg-subtle);
}

.fig-tabs[data-size=sm] .fig-tabs-tab {
  padding-block: var(--fig-space-1);
  font-size: var(--fig-text-1);
}

.fig-tabs[data-size=lg] .fig-tabs-tab {
  padding-block: var(--fig-space-3);
  font-size: var(--fig-text-3);
}

.fig-tabs[data-emphasis=strong] {
  border-block-end-width: 2px;
}

.fig-tabs[data-emphasis=strong] .fig-tabs-tab {
  border-block-end-width: 3px;
  margin-block-end: -2px;
}

/* -- fig-tabs-bar, tab strip + trailing controls on one baseline rule -- */
/* A header band: the tab strip sits at the start, a control cluster (filters,
   actions) at the end, both riding one full-width bottom border. The bar owns
   the rule so it spans the whole width; the tabs' own border is dropped (the
   tabs keep their -1px overlap so the selected underline still straddles it). */
.fig-tabs-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--fig-space-3) var(--fig-space-4);
  border-block-end: 1px solid var(--fig-border-default);
}

.fig-tabs-bar > .fig-tabs {
  border-block-end: 0;
}

/* One fixed band height for EVERY tab/filter bar (home, approvals, catalog,
   settings), so a tabs-only bar (settings) never reads skinny next to one with
   filter controls (catalog). The value is the filter bar's own min height
   (--fig-filter-bar-min-block-size, set in _fig-filter-bar.scss), i.e. whatever
   the control-bearing tabs happen to be. flex-end keeps the tabs' underline on
   the bottom rule with the headroom above. */
.fig-tabs-bar {
  min-block-size: var(--fig-filter-bar-min-block-size);
}

@media (prefers-reduced-motion: reduce) {
  .fig-tabs-tab {
    transition: none;
  }
}
/* fig-icon, inline sizing wrapper for an `_fig_icon.html` SVG dropped into
   running text (a check beside a label, a chevron in a chip). The icon SVG itself
   fills 100% of its box; this makes that box 1em square and optically centers it
   on the text baseline, so the glyph sits inline with adjacent words and inherits
   their color (stroke=currentColor). Button contexts that already size the icon
   (`.fig-icon-button`) don't need this. One home for "an icon in text". */
.fig-icon {
  display: inline-flex;
  inline-size: 1em;
  block-size: 1em;
  vertical-align: -0.125em;
}
.fig-icon > svg {
  inline-size: 100%;
  block-size: 100%;
}

/* fig-icon-button, generic round icon button. Same visual as fig-theme-toggle:
   square pill-radius button wrapping a single svg glyph. Works as <button> or
   <a> (anchor needs text-decoration: none). Keep generic, no per-icon rules. */
.fig-icon-button {
  inline-size: var(--fig-space-6);
  block-size: var(--fig-space-6);
  padding: var(--fig-space--1);
  border: 1px solid var(--fig-border-default);
  border-radius: var(--fig-border-radius-pill);
  /* Translucent at rest (and a stronger translucent tint on hover) so the
     button sits on any backdrop, card body, accent-tinted chain-group banner,
     without reading as an opaque coin. The filled states below (active,
     secondary, danger hover) are the deliberate opaque exceptions. */
  background-color: var(--fig-bg-tint);
  color: var(--fig-fg-default);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  transition: background-color var(--fig-duration-1) var(--fig-ease-1);
}
.fig-icon-button:hover {
  background-color: color-mix(in srgb, var(--fig-bg-muted) 70%, transparent);
}
.fig-icon-button:focus-visible {
  outline: 2px solid var(--fig-bg-emphasis);
  outline-offset: 1px;
}
.fig-icon-button {
  /* Disabled (the demo's read_only action surface renders the header's Dismiss ✕
     and Add To Do / Postpone icons wired to nothing), half strength, any variant. */
}
.fig-icon-button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.fig-icon-button {
  /* Selected state, used when the button is a toggle in a group (e.g. the
     filter-bar sort glyphs). Full emphasis fill, same as the segmented filter
     pill's active option, so the two control styles read as one system. */
}
.fig-icon-button[data-active=true], .fig-icon-button[aria-pressed=true] {
  color: var(--fig-fg-on-emphasis);
  background-color: var(--fig-bg-emphasis);
  border-color: var(--fig-bg-emphasis-hover);
}
.fig-icon-button[data-active=true]:hover, .fig-icon-button[aria-pressed=true]:hover {
  background-color: var(--fig-bg-emphasis-hover);
}
.fig-icon-button {
  /* Secondary-palette variant (teal), same selected logic on the secondary
     role, matching `.fig-button[data-palette="secondary"]`. Used by the Skills
     card/table layout toggle so it reads as a distinct control from the
     primary-filled sort/header glyphs. */
}
.fig-icon-button[data-palette=secondary][data-active=true], .fig-icon-button[data-palette=secondary][aria-pressed=true] {
  color: var(--fig-fg-on-secondary);
  background-color: var(--fig-bg-secondary);
  border-color: var(--fig-bg-secondary-hover);
}
.fig-icon-button[data-palette=secondary][data-active=true]:hover, .fig-icon-button[data-palette=secondary][aria-pressed=true]:hover {
  background-color: var(--fig-bg-secondary-hover);
}
.fig-icon-button {
  /* Danger variant, the card header's Dismiss ✕ and the chain-group header's
     group ✕. At rest it is indistinguishable from a neutral icon button (glyph
     included); hover paints the full danger treatment, red glyph + soft danger
     fill + danger outline, so the destructive read arrives exactly when the
     user is deciding whether to click, and the resting card stays calm. Same
     ink-on-soft-fill pairing as fig-callout/fig-badge (the -fg ink is TEXT on
     the -bg fill, per the status role rule in _fig-semantic.scss). Disabled
     falls through to the generic half-strength rule above. */
}
.fig-icon-button[data-variant=danger]:hover:not(:disabled) {
  color: var(--fig-status-danger-fg);
  background-color: var(--fig-status-danger-bg);
  border-color: var(--fig-status-danger-border);
}
.fig-icon-button svg {
  inline-size: 100%;
  block-size: 100%;
}

/* A horizontal cluster of icon buttons sharing one tight gap, the nav header's
   settings/theme glyphs AND the catalog's card/table layout toggle both wrap in
   this, so every icon-button row reads as the same control group with the same
   --fig-space-1 spacing (matches the filter-bar sort glyphs). One class, no
   per-consumer gap drift. */
.fig-icon-button-group {
  display: flex;
  align-items: center;
  gap: var(--fig-space-1);
}

/* fig-theme-toggle, sun/moon button that flips [data-theme] on <html>.
   Companion JS (theme-toggle.js) runs synchronously in <head> to set the
   initial theme before paint (prevents flash-of-incorrect-theme), then
   binds click handlers after DOMContentLoaded. localStorage key: fig-theme.
   Dark-mode token overrides live in tokens/_fig-semantic.scss under
   [data-theme="dark"], no token wiring needed here. */
.fig-theme-toggle {
  inline-size: var(--fig-space-6);
  block-size: var(--fig-space-6);
  padding: var(--fig-space--1);
  border: 1px solid var(--fig-border-default);
  border-radius: var(--fig-border-radius-pill);
  /* Translucent rest/hover fills, kept in lockstep with .fig-icon-button
     (the two blocks share one visual). */
  background-color: var(--fig-bg-tint);
  color: var(--fig-fg-default);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background-color var(--fig-duration-1) var(--fig-ease-1);
}
.fig-theme-toggle:hover {
  background-color: color-mix(in srgb, var(--fig-bg-muted) 70%, transparent);
}
.fig-theme-toggle:focus-visible {
  outline: 2px solid var(--fig-bg-emphasis);
  outline-offset: 1px;
}
.fig-theme-toggle svg {
  inline-size: 100%;
  block-size: 100%;
}
.fig-theme-toggle .fig-theme-toggle__sun {
  display: block;
}
.fig-theme-toggle .fig-theme-toggle__moon {
  display: none;
}

[data-theme=dark] .fig-theme-toggle .fig-theme-toggle__sun {
  display: none;
}
[data-theme=dark] .fig-theme-toggle .fig-theme-toggle__moon {
  display: block;
}

/* fig-toggle, spec: fig/styles/blocks/fig-toggle.md, edit via /design:create-or-update-block */
.fig-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--fig-space-2);
  cursor: pointer;
  user-select: none;
}

/* Visually hidden checkbox, native element is the source of truth. */
.fig-toggle > input[type=checkbox] {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.fig-toggle-track {
  position: relative;
  display: inline-block;
  inline-size: var(--fig-space-7);
  block-size: var(--fig-space-4);
  background-color: var(--fig-bg-muted);
  border: 1px solid var(--fig-border-default);
  border-radius: var(--fig-border-radius-pill);
  transition: background-color var(--fig-duration-2) var(--fig-ease-2), border-color var(--fig-duration-2) var(--fig-ease-2);
}

/* Thumb rides on the track as a pseudo, no extra element required. */
.fig-toggle-track::before {
  content: "";
  position: absolute;
  inset-block-start: 1px;
  inset-inline-start: 1px;
  inline-size: var(--fig-space-3);
  block-size: var(--fig-space-3);
  background-color: var(--fig-bg-subtle);
  border-radius: var(--fig-border-radius-pill);
  box-shadow: var(--fig-shadow-1);
  transition: transform var(--fig-duration-2) var(--fig-ease-2), background-color var(--fig-duration-2) var(--fig-ease-2);
}

.fig-toggle > input:checked ~ .fig-toggle-track {
  background-color: var(--fig-bg-emphasis);
  border-color: var(--fig-bg-emphasis);
}

.fig-toggle > input:checked ~ .fig-toggle-track::before {
  transform: translateX(var(--fig-space-4));
}

/* Secondary-palette variant (teal), checked track on the secondary role,
   matching `.fig-button`/`.fig-icon-button` `[data-palette="secondary"]`. Used
   by the filter bar's boolean toggles (e.g. "Enabled only") so they read as one
   secondary control group with the bar's filter pills + checklists. */
.fig-toggle[data-palette=secondary] > input:checked ~ .fig-toggle-track {
  background-color: var(--fig-bg-secondary);
  border-color: var(--fig-bg-secondary);
}

.fig-toggle > input:focus-visible ~ .fig-toggle-track {
  outline: 2px solid var(--fig-secondary-border);
  outline-offset: 2px;
}

.fig-toggle[data-disabled] {
  opacity: 0.6;
  cursor: not-allowed;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .fig-toggle-track,
  .fig-toggle-track::before {
    transition: none;
  }
}
/* fig-checkbox, a design-system checkbox: a neutral-bordered, subtly-rounded box
   that's transparent until checked, then fills with the secondary colour. A real
   <input type="checkbox"> under appearance:none, so it keeps native semantics,
   keyboard, and form submission. (For a boolean on/off SWITCH, reach for
   fig-toggle instead, this is the multi-select tick, not the switch.) */
.fig-checkbox {
  appearance: none;
  -webkit-appearance: none;
  flex: 0 0 auto;
  inline-size: var(--fig-checkbox-size, var(--fig-space-5));
  block-size: var(--fig-checkbox-size, var(--fig-space-5));
  margin: 0;
  display: inline-grid;
  place-content: center;
  border: 1px solid var(--fig-border-default);
  border-radius: var(--fig-border-radius-1);
  background-color: transparent;
  cursor: pointer;
  transition: background-color var(--fig-duration-1) var(--fig-ease-1), border-color var(--fig-duration-1) var(--fig-ease-1);
}

/* The tick, two logical borders that, rotated 45°, read as a checkmark. Scaled
   to 0 (hidden) until checked. */
.fig-checkbox::after {
  content: "";
  inline-size: 0.32em;
  block-size: 0.58em;
  margin-block-start: -0.1em;
  border-inline-end: 2px solid var(--fig-fg-on-secondary);
  border-block-end: 2px solid var(--fig-fg-on-secondary);
  transform: rotate(45deg) scale(0);
  transition: transform var(--fig-duration-1) var(--fig-ease-1);
}

.fig-checkbox:hover:not(:checked) {
  border-color: var(--fig-border-emphasis);
}

.fig-checkbox:checked {
  background-color: var(--fig-bg-secondary);
  border-color: var(--fig-bg-secondary);
}

.fig-checkbox:checked::after {
  transform: rotate(45deg) scale(1);
}

.fig-checkbox:focus-visible {
  outline: 2px solid var(--fig-bg-secondary);
  outline-offset: 1px;
}

/* fig-radio, a design-system radio: the round sibling of fig-checkbox. Neutral
   border, transparent until selected, then fills with the secondary colour and
   shows a centre dot. A real <input type="radio"> under appearance:none, so it
   keeps native single-select semantics, keyboard, and form submission. */
.fig-radio {
  appearance: none;
  -webkit-appearance: none;
  flex: 0 0 auto;
  inline-size: var(--fig-radio-size, var(--fig-space-4));
  block-size: var(--fig-radio-size, var(--fig-space-4));
  margin: 0;
  display: inline-grid;
  place-content: center;
  border: 1px solid var(--fig-border-default);
  border-radius: var(--fig-border-radius-pill);
  background-color: transparent;
  cursor: pointer;
  transition: background-color var(--fig-duration-1) var(--fig-ease-1), border-color var(--fig-duration-1) var(--fig-ease-1);
}

/* The centre dot, scaled to 0 (hidden) until selected. */
.fig-radio::after {
  content: "";
  inline-size: 0.5em;
  block-size: 0.5em;
  border-radius: var(--fig-border-radius-pill);
  background-color: var(--fig-fg-on-secondary);
  transform: scale(0);
  transition: transform var(--fig-duration-1) var(--fig-ease-1);
}

.fig-radio:hover:not(:checked) {
  border-color: var(--fig-border-emphasis);
}

.fig-radio:checked {
  background-color: var(--fig-bg-secondary);
  border-color: var(--fig-bg-secondary);
}

.fig-radio:checked::after {
  transform: scale(1);
}

.fig-radio:focus-visible {
  outline: 2px solid var(--fig-bg-secondary);
  outline-offset: 1px;
}

/* fig-decision-toggle, segmented decision pill for any card that carries multiple
   possible decisions (candidate_review's Approve / Reject; triage_email's
   filter_proposal Archive / Create filter / Respond). N HTMX forms (one per
   segment) sit inside a single rounded track so the control reads as ONE toggle,
   not separate buttons: the chosen segment fills with its tone, the others stay
   transparent with muted text. Tones are semantic (`emphasis` = primary fill,
   `danger` = destructive/dismissive, `neutral` = an alternative); the producer
   tags each option's tone in payload.decision_options. Centered in its column,
   wraps when the segments outrun the width. Each segment stays its own <form> so a
   plain POST carries the decision (see _decision_toggle.html). */
.fig-decision-toggle {
  display: flex;
  flex-wrap: wrap;
  inline-size: fit-content;
  max-inline-size: 100%;
  /* Centered, with breathing room above + below so the pill isn't crammed
     against the Decision band and the card footer. */
  margin-block: var(--fig-space-3);
  margin-inline: auto;
  padding: var(--fig-space--2);
  gap: var(--fig-space--2);
  border: 1px solid var(--fig-border-default);
  border-radius: var(--fig-border-radius-pill);
  background-color: var(--fig-bg-muted);
}

/* Each side is a transparent flex cell so its button fills the whole segment. */
.fig-decision-toggle > form {
  display: flex;
  flex: 1 1 0;
  min-inline-size: 0;
  margin: 0;
}

.fig-decision-toggle__option {
  flex: 1 1 0;
  min-inline-size: 5rem;
  padding-block: var(--fig-space-1);
  padding-inline: var(--fig-space-3);
  border: 1px solid transparent;
  border-radius: var(--fig-border-radius-pill);
  font-family: inherit;
  font-size: var(--fig-text-2);
  font-weight: var(--fig-font-weight-medium);
  line-height: var(--fig-line-height-snug);
  text-align: center;
  color: var(--fig-fg-muted);
  background-color: transparent;
  cursor: pointer;
  user-select: none;
  transition: background-color var(--fig-duration-2) var(--fig-ease-2), color var(--fig-duration-2) var(--fig-ease-2);
}

.fig-decision-toggle__option:hover {
  color: var(--fig-fg-default);
}

.fig-decision-toggle__option:focus-visible {
  outline: 2px solid var(--fig-secondary-border);
  outline-offset: 2px;
}

/* Selected segment fills with its tone; the unselected segments stay transparent.
   Three tones, set by the producer in payload.decision_options (the Approve/Reject
   default lives in decision_toggle_options). */
.fig-decision-toggle__option[data-state=on][data-tone=emphasis] {
  color: var(--fig-fg-on-emphasis);
  background-color: var(--fig-bg-emphasis);
}

.fig-decision-toggle__option[data-state=on][data-tone=danger] {
  color: var(--fig-fg-on-danger);
  background-color: var(--fig-bg-danger);
}

/* Neutral: a raised surface against the muted track, so the chosen alternative
   reads as selected without claiming the primary/destructive palette. */
.fig-decision-toggle__option[data-state=on][data-tone=neutral] {
  color: var(--fig-fg-default);
  background-color: var(--fig-bg-default);
  border-color: var(--fig-border-default);
}

@media (prefers-reduced-motion: reduce) {
  .fig-decision-toggle__option {
    transition: none;
  }
}
/* fig-filter-bar, spec: command-center-nav-ia-spec-2026-05-28.md §"The filter bar" */
/* The one fixed bar height shared by every filter/tab bar (home, approvals,
   catalog, settings). Equals the bar's own natural height, an xs filter control
   (~36px) inside space-3 padding-block, frozen so a tabs-only bar (settings,
   which has no controls to size it) matches the control-bearing ones instead of
   reading skinny. :root so _fig-tabs.scss can reuse it. */
:root {
  --fig-filter-bar-min-block-size: 4.25rem;
}

/* Wrapper: stacked filter rows above a card list. Agent pills reuse .fig-tabs
   paint; this block owns row layout, the inline labels, the styled native
   <select>, and the "+ More" affordance. */
.fig-filter-bar {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--fig-space-3);
  padding-block: var(--fig-space-3);
  min-block-size: var(--fig-filter-bar-min-block-size);
}

.fig-filter-bar__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--fig-space-3) var(--fig-space-4);
}

/* Center variant, centers each row's controls horizontally (e.g. the audit
   page's filter group sits centered above a full-bleed table). */
.fig-filter-bar--center .fig-filter-bar__row {
  justify-content: center;
}

/* Inline variant, the home + approvals feed bar. Every control sits on one
   row, the bar sizes to its content and centers over the card column (which is
   itself centered on the page), so the row is free to be wider than that
   column instead of wrapping into stacked rows. Caps at 100% so a narrow
   viewport still wraps gracefully. */
.fig-filter-bar--inline {
  inline-size: max-content;
  max-inline-size: 100%;
  margin-inline: auto;
}

.fig-filter-bar--inline .fig-filter-bar__row {
  justify-content: center;
  gap: var(--fig-space-3) var(--fig-space-5);
}

/* A labelled control cluster (agent pills, sort buttons) that stays together
   as one unit on the single-row bar. */
.fig-filter-bar__group {
  display: inline-flex;
  align-items: center;
  gap: var(--fig-space-2);
}

.fig-filter-bar__label {
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-2);
  font-weight: var(--fig-font-weight-medium);
  white-space: nowrap;
}

/* The pill row sits inline with its label; drop the fig-tabs bottom border so
   it reads as a control group, not a tab strip. */
.fig-filter-bar__pills.fig-tabs {
  border-block-end: 0;
  flex-wrap: wrap;
}

/* Tight variant, the round sort-icon buttons read as one segmented control,
   so they sit closer than the default cluster gap (--fig-space-3). */
.fig-filter-bar__pills--tight {
  gap: var(--fig-space-1);
}

.fig-filter-bar__control {
  display: inline-flex;
  align-items: center;
  gap: var(--fig-space-2);
}

/* The dropdowns are the generic fig-select block (styles/blocks/_fig-select.scss).
   The filter bar only owns the surrounding __control/label layout + the "+ More"
   overlay below; the select paint + the compact xs size live with fig-select. */
/* "+ More", the long-tail agent collapse. The select overlays the label text
   so the trigger reads as one chip but stays a real, keyboard-native control. */
.fig-filter-bar__more {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.fig-filter-bar__more-text {
  pointer-events: none;
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-2);
  font-weight: var(--fig-font-weight-medium);
  white-space: nowrap;
}

.fig-filter-bar__more .fig-select {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  min-inline-size: 0;
  block-size: 100%;
  opacity: 0;
  cursor: pointer;
}

/* -- Multi-select checklist dropdown (_fig_checklist.html) --
   The dropdown filters are fig-popover panels of checkboxes, not native
   <select>s, so several values toggle on at once. The popover block owns the
   floating panel + open/close; this block owns the inline trigger layout, the
   caret, and the checkbox-row chrome (the same way __more owns the agent
   long-tail overlay). */
/* Id'd box around the links-mode pill groups so a list-swapping tab can
   OOB-refresh them; display:contents keeps it out of the flex row's layout. */
.fig-filter-bar__linkwrap {
  display: contents;
}

/* Links mode wraps the checklist (and the boolean toggle) in its own
   self-submitting GET form; keep it inline + vertically centered with its label
   like the other __control clusters. */
.fig-filter-bar__checklist-form,
.fig-filter-bar__toggle-form {
  display: inline-flex;
  align-items: center;
}

/* The trigger is a fig-button[data-variant="filter"]; lay its summary text and
   caret out as one row. */
.fig-filter-bar__checklist-trigger {
  display: inline-flex;
  align-items: center;
  gap: var(--fig-space-1);
}

/* Down-caret built from borders so it inherits the trigger's text color (no
   color literal, no extra asset). Flips via the trigger's aria-expanded. */
.fig-filter-bar__caret {
  inline-size: 0;
  block-size: 0;
  border-inline: var(--fig-space-1) solid transparent;
  border-block-start: var(--fig-space-1) solid currentColor;
  transition: transform var(--fig-duration-1) var(--fig-ease-1);
}

.fig-popover[data-open] .fig-filter-bar__caret {
  transform: rotate(180deg);
}

/* The checkbox column inside the popover panel. Caps height so a long list
   (e.g. every skill) scrolls instead of running off-screen. */
.fig-filter-bar__checklist {
  max-block-size: 60vh;
  overflow-y: auto;
}

/* Rows sit flush, the column is a settings list, each row its own hover target,
   not spaced cards. The fig-stack-layout primitive defaults to a space-3 inter-row
   margin and its `space="0"` attribute is not wired in this subset, so it would
   gap every checklist item apart; pin it back to zero here. */
.fig-filter-bar__checklist > * + * {
  margin-block-start: 0;
}

/* One toggle row: a full-width fig-toggle with a subtle hover. The label rides
   to the start, the switch to the end, so the column reads as a settings list. */
.fig-filter-bar__check {
  border-radius: var(--fig-border-radius-2);
}

/* Hover rides the panel's palette (--fig-popover-item-hover-bg, set by
   .fig-popover-panel[data-palette], _fig-popover.scss) so a row inside a
   secondary-tinted checklist hovers in the same hue as its trigger; neutral
   fallback for a panel with no palette. */
.fig-filter-bar__check:hover {
  background-color: var(--fig-popover-item-hover-bg, var(--fig-bg-muted));
}

.fig-filter-bar__check .fig-toggle {
  inline-size: 100%;
  flex-direction: row-reverse;
  justify-content: space-between;
  padding: var(--fig-space-1) var(--fig-space-2);
  font-size: var(--fig-text-2);
  white-space: nowrap;
}

/* -- When date-range picker (_fig_when.html) --
   Reuses the checklist trigger + caret + scrolling panel (.fig-filter-bar__checklist);
   adds single-select radio rows, a hairline before the Custom row, and the revealed
   from/to date block. One window at a time, so radios, not the toggle switches. */
/* One preset row: the radio + its label as a full-width hover target, matching the
   checklist's row rhythm so the two controls read identically in the bar. */
.fig-when__option {
  display: flex;
  align-items: center;
  gap: var(--fig-space-2);
  padding: var(--fig-space-1) var(--fig-space-2);
  border-radius: var(--fig-border-radius-2);
  font-size: var(--fig-text-2);
  white-space: nowrap;
  cursor: pointer;
}

/* Same palette-aware hover as the checklist rows above. */
.fig-when__option:hover {
  background-color: var(--fig-popover-item-hover-bg, var(--fig-bg-muted));
}

/* Hairline splitting the relative presets from the explicit Custom range row. */
.fig-when__divider {
  block-size: 1px;
  margin: var(--fig-space-1) var(--fig-space-2);
  background-color: var(--fig-border-muted);
}

/* The from/to inputs, stacked. Revealed by clearing [hidden] when Custom is picked. */
.fig-when__custom {
  display: flex;
  flex-direction: column;
  gap: var(--fig-space-2);
  padding: var(--fig-space-2);
}

.fig-when__date {
  display: flex;
  align-items: center;
  gap: var(--fig-space-2);
  font-size: var(--fig-text-2);
}

/* Fixed-width label gutter so the two date inputs left-align under each other. */
.fig-when__date-label {
  inline-size: 2.75rem;
  color: var(--fig-fg-muted);
}

.fig-when__date .fig-input {
  flex: 1 1 auto;
  min-inline-size: 0;
}

@media (prefers-reduced-motion: reduce) {
  .fig-filter-bar__caret {
    transition: none;
  }
}
/* fig-sidebar-filter, spec: command-center-nav-ia-spec-2026-05-28.md §"The filter bar", the vertical, Amazon-style left filter sidebar (sibling of fig-filter-bar; see fig_sidebar_filter.html). */
/* -- The page LAYOUT: a two-column shell that places a fig-sidebar-filter beside
   the list/content column. The columns + intrinsic single-column collapse come
   from <fig-sidebar-layout>; this wrapper adds the page inset, the shared sizing
   vars, and the divider. It is NOT the filter, it hosts one (+ the content). -- */
.fig-sidebar-filter-layout {
  /* Filter column: fluid ~20% of the viewport, floored at container--1 (256px)
     so it never gets cramped on a laptop and capped at container-1 (384px) so it
     doesn't sprawl on David's ultra-wide. (Bump the cap to container-2 / 512px if
     the rail should run wider.) Held in its own var (not --fig-sidebar-side-width
     directly) because the collapsed rail still needs the EXPANDED width, the
     scroll region stays pinned to it so the facets slide behind the edge like a
     drawer instead of rewrapping. */
  --fig-sidebar-rail-width: clamp(var(--fig-container--1), 20vw, var(--fig-container-1));
  --fig-sidebar-side-width: var(--fig-sidebar-rail-width);
  --fig-sidebar-content-min: 60%;
  /* No inter-column gap: the divider + the __main padding-inline-start own the
     gutter between the filter rail and the content, so the layout's own gap
     would double it. Zero it here only, the base primitive keeps space-6. */
  --fig-sidebar-gap: 0;
  /* Own a query container so the divider can drop when the layout has wrapped
     (the column collapse itself is intrinsic, no @media). */
  container-type: inline-size;
  /* No page padding here, the layout is a bare two-column shell. The gutters are
     owned by the components it hosts (the sidebar + the content column). */
  /* App-shell height: pin the two-pane feed to exactly the viewport below the
     nav and never let it grow the document, so the rail runs full-height and the
     CARDS scroll inside their own column, not the page. Without this the page
     itself scrolled and you could slide the cards out from under a shorter rail,
     ending up in dead space beneath it. Released back to natural page flow once
     stacked (the container query below). */
  block-size: calc(100dvh - var(--fig-nav-height));
  overflow: hidden;
  /* Stretch both columns to the shell height (the base primitive top-aligns
     them): the rail fills floor-to-ceiling, and the content column inherits a
     definite height to scroll within. */
  align-items: stretch;
}

/* Collapsed (the header's chevron toggle, class set by fig_sidebar_filter.html's
   wiring): the rail slides down to just the toggle button plus its gutters, and
   the content column absorbs the freed width. The glide itself is the aside's
   flex-basis transition below. */
.fig-sidebar-filter-layout:has(> .fig-sidebar-filter--collapsed) {
  --fig-sidebar-side-width: calc(var(--fig-space-6) + var(--fig-page-padding) * 2);
}

/* -- The base component: the filter sidebar itself (the <aside> in the layout's
   first column). Fills the app-shell so it runs floor-to-ceiling; a flex column
   holding the header row (title + collapse toggle) over the scroll region + the
   facet panel. -- */
.fig-sidebar-filter {
  /* A positioning context (NOT static): the facet controls hide their native
     radios/checkboxes with position:absolute, and a static rail would resolve
     those against the document and stretch the page below the fold. The rail no
     longer needs position:sticky either, the app-shell holds it in view. */
  position: relative;
  min-inline-size: 0;
  /* Fill the shell height (owned by the layout) so the rail + its divider run
     floor-to-ceiling no matter how short the card list is; min-block-size:0 lets
     it shrink to the shell rather than to its taller content, which the inner
     __scroll region scrolls on its own. */
  block-size: 100%;
  min-block-size: 0;
  /* The divider rides the sidebar's own trailing edge (not the content column),
     so it always spans the full viewport height, the content column can be
     shorter than the viewport without leaving a gap below the rule. */
  border-inline-end: 1px solid var(--fig-border-muted);
  /* The sidebar owns its own gutter (the layout adds none): even page padding on
     all four sides, one value, from the --fig-page-padding constant. */
  padding: var(--fig-page-padding);
  /* Header over scroll region; the scroll region's height is whatever's left. */
  display: flex;
  flex-direction: column;
  /* The collapse slide clips the width-pinned facet panel at the rail's edge
     (drawer-style) instead of letting it paint over the content column. */
  overflow: hidden;
  /* The collapse/expand glide, the SAME design-system expand transition as the
     approval card's fold + edit-open ride: duration-5 + ease-5, one expand feel
     across the app. Rides the flex-basis the layout primitive assigns. */
  transition: flex-basis var(--fig-duration-5) var(--fig-ease-5);
}

/* The title row: heading + the collapse toggle pinned to the rail's trailing
   edge (outside the scroll region, so it never scrolls away under a long facet
   list). The gap eases to 0 on collapse so the button alone fits the shut rail. */
.fig-sidebar-filter__header {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fig-space-2);
  /* The rail's "topbar", so it reads as a sibling of fig-nav + the chat drawer
     header, not a one-off. Pin the row to the same published --fig-nav-height
     SSoT (_fig-nav.scss) those two use, so all three header bars are one height
     and stack flush. Content (toggle + title) centers within it. */
  min-block-size: var(--fig-nav-height);
  margin-block-end: var(--fig-space-1);
  transition: gap var(--fig-duration-5) var(--fig-ease-5);
}

.fig-sidebar-filter--collapsed .fig-sidebar-filter__header {
  gap: 0;
}

.fig-sidebar-filter__collapse {
  flex: none;
}

/* Double chevron points at the edge the rail will slide to: « when open (click
   to collapse), flipped » when shut (click to expand). Same 150ms flip as the
   card fold chevron. */
.fig-sidebar-filter__collapse svg {
  transition: transform 150ms var(--fig-ease-1);
}

.fig-sidebar-filter--collapsed .fig-sidebar-filter__collapse svg {
  transform: rotate(180deg);
}

/* The scrollable region inside the sticky column: capped to the space between the
   nav and the viewport bottom (minus the sidebar's own top gutter), so the filters
   scroll on their own while the page's cards scroll independently. Overflow + the
   bottom fade come from <fig-scroll-fade-layout fade-sides="bottom">. */
.fig-sidebar-filter__scroll {
  /* Whatever height the header leaves in the rail's flex column; the
     max-block-size only still binds in the stacked one-column mode, where the
     aside has no definite height to flex within. */
  flex: 1 1 auto;
  min-block-size: 0;
  max-block-size: calc(100dvh - var(--fig-nav-height) - var(--fig-page-padding) * 2);
  /* Fade over the shared band so this scroll fade and the approval-card body fold
     stay visually in lockstep, one knob (_fig-scroll-fade-layout.scss). */
  --fade-size: var(--fig-fade-size);
  /* Pinned to the EXPANDED rail's content width (not the animating aside), so
     the facet rows never rewrap during the collapse slide, they hold their
     layout and clip behind the rail's edge like a drawer. */
  inline-size: calc(var(--fig-sidebar-rail-width) - var(--fig-page-padding) * 2);
  /* visibility rides the slide: transitionable-discrete, so the facets stay
     painted through the whole close glide and only then go hidden (and
     unfocusable); on expand they're back instantly, sliding out from the clip. */
  transition: visibility var(--fig-duration-5);
}

.fig-sidebar-filter--collapsed .fig-sidebar-filter__scroll {
  visibility: hidden;
}

.fig-sidebar-filter-layout__main {
  min-inline-size: 0;
  /* The cards' scroll container: fills the shell height and scrolls on its own,
     independent of the rail. min-block-size:0 lets the flex item shrink to the
     shell (instead of to the tall card stack) so overflow-y actually engages;
     position:relative contains any absolutely-positioned card internals so they
     can't inflate this column's scroll height with dead space below the feed. */
  position: relative;
  block-size: 100%;
  min-block-size: 0;
  overflow-y: auto;
  /* The divider lives on the sidebar's trailing edge now (it owns the full
     viewport height); the content column just keeps its gutters. */
  /* Even inline gutters: the content column owns its OWN left + right page inset
     (the filter sidebar owns the left edge), so cards fill from the divider to a
     matching right gutter, no centered max-width column floating right of centre. */
  padding-inline: var(--fig-space-6);
  /* Top gutter so the first card (or tab strip) isn't flush against the nav,
     matching the inline + bottom gutters for an even frame around the feed. */
  padding-block-start: var(--fig-space-6);
  /* Bottom breathing room rides the content column itself (not the page wrapper),
     so it lengthens the scroll only when cards are tall, a short list leaves the
     full-height sidebar at exactly 100dvh with no stray page scrollbar. */
  padding-block-end: var(--fig-space-6);
}

/* The cards FILL the main column (no centered max-width wrapper), so they anchor
   to the divider and run rightward to the gutter above. The tab strip's hairline
   spans the whole main width; the tab labels centre over the filled feed. */
/* Stacked (layout wrapped to one column): the sidebar sits ABOVE the content, so
   it can't be a viewport-tall fixed frame and its trailing divider would sit on
   top of the cards, release both. Container query, not viewport @media: the
   component responds to its own width, so it's correct in a narrow panel as well
   as a narrow page. */
@container (max-inline-size: 48rem) {
  /* Release the app-shell: one column, let the document scroll naturally again
     (a fixed-height clipped shell would trap the stacked content). */
  .fig-sidebar-filter-layout {
    block-size: auto;
    overflow: visible;
  }
  .fig-sidebar-filter {
    /* Stays position:relative (containing block for the hidden facet inputs); it
       just no longer fills a shell or carries the trailing divider. */
    block-size: auto;
    border-inline-end: 0;
  }
  .fig-sidebar-filter-layout__main {
    block-size: auto;
    overflow-y: visible;
    padding-inline-start: 0;
  }
  /* Stacked, the rail spans the full row, so release the drawer pin and let the
     facets fill it. */
  .fig-sidebar-filter__scroll {
    inline-size: auto;
  }
  /* Stacked + collapsed: drop the hidden facets from layout entirely, the
     shell-mode visibility trick would leave their blank height sitting between
     the toggle and the content (the rail has no fixed height to hide it in). */
  .fig-sidebar-filter--collapsed .fig-sidebar-filter__scroll {
    display: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .fig-sidebar-filter,
  .fig-sidebar-filter__header,
  .fig-sidebar-filter__title,
  .fig-sidebar-filter__scroll,
  .fig-sidebar-filter__collapse svg {
    transition: none;
  }
}
/* -- The filter panel itself: the <form>, a stack of facet sections. -- */
.fig-sidebar-filter__panel {
  display: flex;
  flex-direction: column;
}

/* The heading, a shrinkable flex item: as the rail slides shut it clips (never
   wraps) and fades, leaving the toggle alone in the collapsed rail. The header
   row owns the block margin. */
.fig-sidebar-filter__title {
  font-size: var(--fig-text-4);
  font-weight: var(--fig-font-weight-semibold);
  flex: 1 1 auto;
  min-inline-size: 0;
  overflow: hidden;
  white-space: nowrap;
  transition: opacity var(--fig-duration-5) var(--fig-ease-5);
}

.fig-sidebar-filter--collapsed .fig-sidebar-filter__title {
  opacity: 0;
}

/* One facet section, a heading over its value rows, hairline-separated from the
   next so the column reads as a clean settings column. Compact block padding so
   the stacked sections stay dense. */
.fig-sidebar-filter__facet {
  padding-block: var(--fig-space-2);
}

/* Hairline BETWEEN facet sections, never below the last one, a separator, not a
   trailing rule. Adjacent-sibling (not :last-of-type + strip) so a hidden,
   reveal-gated section at the end can't leave the visible last group with a
   dangling border: whatever group renders last simply has nothing below it. */
.fig-sidebar-filter__facet + .fig-sidebar-filter__facet {
  border-block-start: 1px solid var(--fig-border-muted);
}

/* A bare toggle section (no heading) sits tighter, the switch is self-labelling. */
.fig-sidebar-filter__facet--toggle {
  padding-block: var(--fig-space-2);
}

/* Block-level (the shared fig-toggle is inline-flex for the filter bar's inline
   control row): inline, the toggle rides a text line box whose baseline strut
   leaves ~4px of descender space BELOW it, so the section's symmetric padding
   read as a bigger gap under the switch than above it. */
.fig-sidebar-filter__facet--toggle .fig-toggle {
  display: flex;
}

.fig-sidebar-filter__heading {
  font-size: var(--fig-text-2);
  font-weight: var(--fig-font-weight-semibold);
  color: var(--fig-fg-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-block-end: var(--fig-space-1);
}

/* The faceted list is a <fig-stack-layout space="0">, but `space` isn't wired in
   this subset (the primitive hardcodes space-3), so pin the inter-row margin back
   to zero, the rows are a dense list, not spaced cards. */
.fig-sidebar-filter__list > * + * {
  margin-block-start: 0;
}

/* One value row: checkbox + label, with the card count pinned to the row end.
   The whole row is a hover target so it reads as a list item, like the bar's
   checklist rows. */
.fig-sidebar-filter__check {
  display: flex;
  align-items: center;
  gap: var(--fig-space-2);
  padding: 0.15rem var(--fig-space-2);
  border-radius: var(--fig-border-radius-2);
  font-size: var(--fig-text-2);
  line-height: 1.3;
  cursor: pointer;
}

.fig-sidebar-filter__check:hover {
  background-color: var(--fig-bg-muted);
}

.fig-sidebar-filter__check input {
  flex: 0 0 auto;
  cursor: pointer;
}

.fig-sidebar-filter__check-label {
  flex: 1 1 auto;
  min-inline-size: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Sort rows carry a small leading glyph (the "P" / calendar from
   _fig_filter_icon) between the radio and the label. */
.fig-sidebar-filter__sort-icon {
  flex: 0 0 auto;
  display: inline-flex;
  inline-size: 1rem;
  block-size: 1rem;
  color: var(--fig-fg-muted);
}

.fig-sidebar-filter__sort-icon svg {
  inline-size: 100%;
  block-size: 100%;
}

/* The card count beside each value, muted, tabular, pinned right. */
.fig-sidebar-filter__count {
  flex: 0 0 auto;
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-1);
  font-variant-numeric: tabular-nums;
}

/* -- Priority chips: colour-coded "P" circle badges, multi-select, wrapping into
   1–2 rows. The checkbox is visually hidden; the whole chip is the click target,
   and the checked chip gets a ring so the colour badge stays its own colour. -- */
.fig-sidebar-filter__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--fig-space-0);
}

.fig-sidebar-filter__chip {
  display: inline-flex;
  align-items: center;
  gap: var(--fig-space-1);
  padding: var(--fig-space-1) var(--fig-space-2);
  border: 1px solid var(--fig-border-muted);
  border-radius: 999px;
  cursor: pointer;
  font-size: var(--fig-text-1);
  line-height: 1;
  transition: border-color var(--fig-duration-1) var(--fig-ease-1), background-color var(--fig-duration-1) var(--fig-ease-1);
}

.fig-sidebar-filter__chip input {
  position: absolute;
  opacity: 0;
  inline-size: 1px;
  block-size: 1px;
  pointer-events: none;
}

.fig-sidebar-filter__chip:hover {
  background-color: var(--fig-bg-muted);
}

.fig-sidebar-filter__chip:has(input:checked) {
  border-color: var(--fig-bg-emphasis);
  background-color: color-mix(in srgb, var(--fig-bg-emphasis) 12%, transparent);
}

/* Keyboard focus ring (the input is visually hidden, so paint the chip). */
.fig-sidebar-filter__chip:has(input:focus-visible) {
  outline: 2px solid var(--fig-bg-emphasis);
  outline-offset: 1px;
}

.fig-sidebar-filter__chip-count {
  color: var(--fig-fg-muted);
  font-variant-numeric: tabular-nums;
}

/* -- Segmented Time-Period toggle (24h / 7d / 30d / 90d / 1y / All). Native
   radios styled as a wrapping pill group; the checked pill fills. Native radios
   (not fig-tabs) so a click fires the form's htmx swap with zero JS. -- */
.fig-sidebar-filter__toggleset {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--fig-space-1);
}

.fig-sidebar-filter__seg {
  cursor: pointer;
}

.fig-sidebar-filter__seg input {
  position: absolute;
  opacity: 0;
  inline-size: 1px;
  block-size: 1px;
  pointer-events: none;
}

/* display: flex (not inline-flex) so each button fills its 1fr grid cell, every
   segment ends up the same width. */
.fig-sidebar-filter__seg span {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--fig-space-1) var(--fig-space-2);
  border: 1px solid var(--fig-border-default);
  border-radius: var(--fig-border-radius-2);
  font-size: var(--fig-text-2);
  color: var(--fig-fg-default);
  transition: background-color var(--fig-duration-1) var(--fig-ease-1), color var(--fig-duration-1) var(--fig-ease-1), border-color var(--fig-duration-1) var(--fig-ease-1);
}

.fig-sidebar-filter__seg:hover span {
  background-color: var(--fig-bg-muted);
}

/* Active = secondary palette (teal), like the checkboxes/radios; inactive stays
   neutral-bordered like the rest of the controls. */
.fig-sidebar-filter__seg input:checked + span {
  background-color: var(--fig-bg-secondary);
  color: var(--fig-fg-on-secondary);
  border-color: var(--fig-bg-secondary);
}

.fig-sidebar-filter__seg input:focus-visible + span {
  outline: 2px solid var(--fig-bg-secondary);
  outline-offset: 1px;
}

/* A single-select <select> spans the column width. */
.fig-sidebar-filter__facet .fig-select {
  inline-size: 100%;
}

/* A checklist-dropdown facet (e.g. User, the shared _fig_checklist popover):
   the trigger spans the column like the select above, summary text at the
   start, caret pinned to the end. The panel + rows keep the filter bar's
   chrome (.fig-filter-bar__checklist*), it is the same component. */
.fig-sidebar-filter__facet .fig-popover {
  display: block;
}

.fig-sidebar-filter__facet .fig-filter-bar__checklist-trigger {
  inline-size: 100%;
  justify-content: space-between;
}

/* The panel matches the trigger it drops from: same width (the trigger spans
   the column, so 100% of the wrapper IS the trigger width) and a hair less
   drop gap, so the pair reads as one control. The gap override carries the
   [data-side] attribute to out-specify the popover block's placement rule. */
.fig-sidebar-filter__facet .fig-popover-panel {
  inline-size: 100%;
  min-inline-size: 0;
}

.fig-sidebar-filter__facet .fig-popover-panel[data-side=bottom-start] {
  inset-block-start: calc(100% + var(--fig-space-0));
}

/* "See more / See less" accordion holding the long tail past the cap. Native
   <details>, the leanest JS-free disclosure; the <summary> reads as a small text
   affordance and its label flips with [open]. */
.fig-sidebar-filter__more {
  margin-block-start: var(--fig-space-1);
}

.fig-sidebar-filter__more-summary {
  list-style: none;
  cursor: pointer;
  padding: var(--fig-space-1) var(--fig-space-2);
  font-size: var(--fig-text-2);
  font-weight: var(--fig-font-weight-medium);
  color: var(--fig-secondary-fg);
}

.fig-sidebar-filter__more-summary::-webkit-details-marker {
  display: none;
}

.fig-sidebar-filter__more-summary:hover {
  text-decoration: underline;
}

/* Flip the label: show "See more" when closed, "See less" when open. */
.fig-sidebar-filter__more-hide {
  display: none;
}

.fig-sidebar-filter__more[open] .fig-sidebar-filter__more-show {
  display: none;
}

.fig-sidebar-filter__more[open] .fig-sidebar-filter__more-hide {
  display: inline;
}

/* fig-meta-grid, reusable label / value metadata grid.
   Rows of key→value cells separated by hairline dividers; `--full` takes a whole
   row (long values, JSON, prose).

   Dividers are CELL BORDERS, not a background seam, so cells stay transparent
   and inherit whatever surface they sit on (card, modal, page). Each cell carries
   a leading (block-start + inline-start) hairline; the grid's overflow clip plus
   the -1px pull below hide the outer-edge rules and leave only the internal seams.

   Flex-wrap, NOT CSS grid, on purpose: because the seams are per-cell, an
   unoccupied grid slot would be a hole in the lattice (no borders, no cell
   paint), and grid auto-fit reserves exactly such empty tracks whenever a row
   doesn't fill (a trailing orphan, the cells a mid-list `--full` cell strands).
   The rendered track count is unknowable server-side, so no template logic can
   pre-fill the holes. A wrapped flex row has no slots to leave empty: the cells
   of a short row grow to share it edge-to-edge (the same look `promote_orphans`
   gives a lone trailing cell, generalized to every row at every width), so the
   lattice is always complete. Equal bases + grow keep complete rows reading as
   equal columns, same responsive 1 → 4 column behavior as auto-fit. Every cell
   is floored at the typical one-line-cell height, so short cells (empty value,
   bare label) sit on the same lattice as their neighbors. Used inside cards
   (approval cards) and standalone (skill detail page), same paint either way.
   Metadata reads a step lighter than body text. */
.fig-meta-grid {
  display: flex;
  flex-wrap: wrap;
  /* The height of the TYPICAL cell, a one-line label over a one-line value,
     derived from the same tokens the cell is built from: the cell's block
     padding (2 × space-2) + two text-2 line boxes at the inherited body
     line-height + the label→value gap (the value's space--2 top margin). Every
     cell is floored at it (min-block-size below) and flex stretch levels each
     row to its tallest cell, so all rows land on the same lattice instead of
     hugging their own content; a tall value still grows its row. */
  --fig-meta-grid-cell-min: calc(
    (2 * var(--fig-space-2))
    + (2 * var(--fig-line-height-body) * var(--fig-text-2))
    + var(--fig-space--2)
  );
  margin: 0;
  overflow: hidden; /* clip the 1px leading rules pulled past the edge by the item margins */
  color: var(--fig-fg-muted);
}

/* A record_search edit cell (contact / company / owner typeahead) drops its
   results list BELOW the input, into the next cell. The grid's outer-divider clip
   (overflow:hidden above) would chop that dropdown, z-index can't escape a
   clipping ancestor. A grid carrying a record_search lifts the clip so the popup
   floats free. record_search only renders in edit mode, so read-mode grids keep
   their clean clipped edges; the only cost is this edited grid showing its 1px
   outer rules, a fair trade for an un-clipped dropdown. */
.fig-meta-grid:has(.fig-record-search) {
  overflow: visible;
}

.fig-meta-grid__item {
  display: flex;
  flex-direction: column;
  /* Responsive, capped at 4 columns. The per-row basis floor is
     max(container--2, 25%): the 25% caps at four columns on any width (a cell
     can't be narrower than a quarter), and the container--2 floor (picker min)
     stops a wide container from cramming four tiny columns, so it adapts to the
     container, 1 → 4 cols, without a media query. grow:1 with equal bases keeps
     the cells of each row equal-width. */
  flex: 1 1 max(var(--fig-container--2), 25%);
  min-inline-size: 0;
  min-block-size: var(--fig-meta-grid-cell-min);
  padding-block: var(--fig-space-2);
  padding-inline: var(--fig-space-3);
  /* transparent, inherit the parent surface; dividers come from these borders */
  border-block-start: 1px solid var(--fig-border-default);
  border-inline-start: 1px solid var(--fig-border-default);
  margin-block-start: -1px; /* pull row 1's top rule off the top edge (clipped) */
  margin-inline-start: -1px; /* pull col 1's left rule off the left edge (clipped) */
}

/* A full-row cell: the 100% basis can never share a flex line, so it wraps onto
   its own row and stretches across it. */
.fig-meta-grid__item--full {
  flex-basis: 100%;
}

/* The attachments cell holds one wrapping row of file-type pills (a leading
   `fig-cluster-layout` of `fig-badge`s, see _attachment_pills.html), not a two-line
   text value. The cell-min floor (sized for a label + a TWO-line value) therefore
   pools empty height below the single-line pill row, reading as too much padding
   above and below the badge. It's always a `--full` cell (list value) on its own
   row, so it has NO lattice neighbors to stay level with: let it fit its content.
   Scoped by `:has` to the pills cell only, so ordinary text cells keep the floor
   that levels their rows. */
.fig-meta-grid__item--full:has(> .fig-meta-grid__value > fig-cluster-layout) {
  min-block-size: 0;
}

/* Single-column variant, every cell on its own full-width row, no side-by-side
   split. The header grids that sit above a message (Sender / Subject / Contacts /
   Company) stack so each field reads on its own line. With one column the
   `--full` span is a no-op and `promote_orphans` never fires, every cell is
   already a full row. */
.fig-meta-grid--stacked .fig-meta-grid__item {
  flex-basis: 100%;
}

/* Placement dividers. The internal seams are cell borders (above) with the outer
   edges clipped, so a bare grid carries no outer rule. When a grid sits as a card
   section next to a body it needs ONE outer hairline marking the boundary, on the
   side that faces the body:
     --top    grid lives at the TOP of a column (a subject line above the body) →
              bottom hairline.
     --bottom grid lives at the BOTTOM (sender / token spend below the body) →
              top hairline.
   The `.fig-card-body + .fig-card-meta` adjacency in _fig-card.scss already draws
   the top hairline for the common "metadata directly after a body" case, so
   --bottom is only needed where that adjacency can't reach; --top is needed for
   every grid that precedes its body. */
.fig-meta-grid--top {
  border-block-end: 1px solid var(--fig-border-default);
}

.fig-meta-grid--bottom {
  border-block-start: 1px solid var(--fig-border-default);
}

.fig-meta-grid__label {
  font-size: var(--fig-text-2);
  font-weight: var(--fig-font-weight-semibold);
  color: var(--fig-fg-muted);
}

/* A required field the draft couldn't fill (`missing` on the item). The cell reads
   in the danger palette, a danger background tint + danger label + an asterisk
   after the label. Replaces the old standalone "Missing required" cell: the gap
   now reads on the field it belongs to.

   A background tint (not a border ring) on purpose: the grid clips its outer 1px
   via `overflow:hidden` + the items' -1px block/inline-start margins (that's how
   the outer dividers are hidden). An inset box-shadow ring lands in that clipped
   strip on the top + inline-start edges, so only 2 of its 4 sides paint. A fill
   is clip-proof, it reads the whole visible cell regardless of the edge math. */
.fig-meta-grid__item.is-missing {
  background: var(--fig-status-danger-bg);
}
.fig-meta-grid__item.is-missing .fig-meta-grid__label {
  color: var(--fig-status-danger-fg);
}

.fig-meta-grid__required {
  color: var(--fig-status-danger-fg);
  font-weight: var(--fig-font-weight-semibold);
}

/* A field an update card proposes changing (`changed` on the item). The mirror of
   `is-missing`: a success background tint + success label + a small "updated" tag
   after the label, so the suggested edits read at a glance against the untouched
   HubSpot-prefilled fields. Same fill-not-ring reasoning as is-missing above. */
.fig-meta-grid__item.is-changed {
  background: var(--fig-status-success-bg);
}
.fig-meta-grid__item.is-changed .fig-meta-grid__label {
  color: var(--fig-status-success-fg);
}

.fig-meta-grid__changed {
  color: var(--fig-status-success-fg);
  font-weight: var(--fig-font-weight-semibold);
  font-size: var(--fig-text-0);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.fig-meta-grid__value {
  margin-block: var(--fig-space--2) 0;
  margin-inline: 0;
  font-size: var(--fig-text-2);
  white-space: pre-line;
  overflow-wrap: anywhere;
}

/* A list-valued cell (`items` on the meta entry, rendered by _normalize_meta):
   one bullet per sub-entry, each its own link (a set of same-label peers, e.g.
   similar deals, in one cell instead of one cell each). Indent only enough for
   the markers; the value's pre-line whitespace would double-space the <li>s, so
   reset it. */
.fig-meta-grid__list {
  margin: 0;
  padding-inline-start: var(--fig-space-4);
  white-space: normal;
}

/* The optional one-line gloss under a value, a step lighter + smaller than the
   metadata itself, so it reads as help, not data. Lets the grid carry its own
   field descriptions (built in build_skill_meta) instead of dropping them. */
.fig-meta-grid__help {
  margin-block: var(--fig-space-1) 0;
  margin-inline: 0;
  font-size: var(--fig-text-1);
  color: var(--fig-fg-subtle);
}

/* fig-editable, seamless inline-edit field treatment.
   Mark any slot wrapping a `.fig-field__input` (text / textarea / number /
   datetime / select) with `.is-editable`. The field then reads like plain text
   at rest and reveals itself as editable only on hover, a faint fill plus the
   text (edit) cursor; focus paints the full field so the active editor is
   unambiguous. One rule set, every input kind, anywhere (approval card body dd,
   meta-grid cell, future inline-edit forms), so a new editable surface is a
   class on the wrapper, not new CSS. */
/* Ghost field, indistinguishable from the read-mode value at rest: no box, no
   padding, inheriting the exact surrounding font + colour, stretched to fill the
   slot. Toggling edit mode moves the text by zero pixels; it just becomes
   typeable. (Read mode renders the value flush with no inset, so any padding or
   border here would shove the text on entering edit.) */
.is-editable .fig-field__input {
  inline-size: 100%;
  padding: 0;
  border: 0;
  background-color: transparent;
  color: inherit;
  font: inherit;
  cursor: text;
  transition: background-color var(--fig-duration-1) ease, box-shadow var(--fig-duration-1) ease;
}

/* Size the textarea to its content so a short draft doesn't reserve the full
   `rows` height, edit mode then matches view mode's natural height. `rows`
   stays the pre-`field-sizing` fallback. */
.is-editable textarea.fig-field__input {
  resize: vertical;
  field-sizing: content;
}

/* Hover / focus, the only reveal is a faint fill. A box-shadow halo of the same
   colour gives the fill breathing room WITHOUT padding, so it paints outward and
   the text never shifts. */
.is-editable .fig-field__input:hover,
.is-editable .fig-field__input:focus-visible {
  background-color: var(--fig-bg-muted);
  box-shadow: 0 0 0 var(--fig-space-1) var(--fig-bg-muted);
  border-radius: var(--fig-border-radius-1);
}

/* The halo occupies box-shadow and the ghost field has no border to tint, so
   the focus ring is an outline here (fig-input's ring rides box-shadow, which
   the halo overrides at this specificity). Offset clears the halo. */
.is-editable .fig-field__input:focus-visible {
  outline: 2px solid var(--fig-secondary-border);
  outline-offset: var(--fig-space-1);
}

/* Host containers carry `white-space: pre-line` to keep author line breaks in
   read mode (_fig-card.scss dd, _fig-meta-grid.scss value). In edit mode that
   renders the template's indentation newlines around the widget as blank lines
  , a tall gap above/below the control. Reset to normal wherever an editable
   slot lives. */
.fig-card-body dd:has(> .is-editable),
.fig-meta-grid__item.is-editable .fig-meta-grid__value {
  white-space: normal;
}

/* fig-progress-bar, spec: fig/styles/blocks/fig-progress-bar.md, edit via /design:create-or-update-block */
/* Horizontal determinate progress bar, a track with a fill whose width is
   driven inline (via a CSS custom property or style attr) and whose color
   reflects a [data-level] severity. The block owns shape + severity paint +
   transition; the consumer owns the percent value and the percent→level
   mapping. Chat context-budget, upload progress, and quota meters all share
   this shape. */
.fig-progress-bar {
  /* Track. Default fill = info (accent); overridden by [data-level]. */
  display: block;
  block-size: var(--fig-space-1);
  inline-size: 100%;
  background-color: var(--fig-bg-muted);
  border-radius: var(--fig-border-radius-pill);
  overflow: hidden;
}

.fig-progress-bar-fill {
  display: block;
  block-size: 100%;
  inline-size: var(--fig-progress-value, 0%);
  background-color: var(--fig-bg-accent);
  border-radius: inherit;
  transition: inline-size var(--fig-duration-3) var(--fig-ease-2), background-color var(--fig-duration-2) var(--fig-ease-2);
}

/* -- Exceptions (severity variants) -- */
.fig-progress-bar[data-level=success] .fig-progress-bar-fill {
  background-color: var(--fig-bg-success);
}

.fig-progress-bar[data-level=warning] .fig-progress-bar-fill {
  background-color: var(--fig-bg-warning);
}

.fig-progress-bar[data-level=danger] .fig-progress-bar-fill {
  background-color: var(--fig-bg-danger);
}

@media (prefers-reduced-motion: reduce) {
  .fig-progress-bar-fill {
    transition: none;
  }
}
/* -- Command-center addition: neutral severity --
   A no-signal level for status strips (e.g. an agent with no completed runs).
   The default fill is accent/info blue, which wrongly reads as "active" on a
   health strip; neutral paints a muted grey so "no data" recedes. No fig-app
   equivalent yet, sync back if fig-app gains a neutral meter level. */
.fig-progress-bar[data-level=neutral] .fig-progress-bar-fill {
  background-color: var(--fig-fg-muted);
}

/* -- Command-center addition: fill intensity (opacity) --
   A second visual channel for composite meters: hue still encodes severity
   (the [data-level] fill above), while --fig-progress-intensity fades the fill
   to encode a *separate* low-stakes dimension. The health page uses it for
   liveness, a recently-active agent paints solid, a long-quiet one fades to a
   floor, so "faint green" reads as healthy-but-idle and "solid red" as
   busy-and-failing. Defaults to 1 (fully opaque) so plain progress bars are
   unaffected. No fig-app equivalent yet, sync back if fig-app gains a
   composite/confidence meter. Kept as its own rule so the ported block above
   stays byte-identical to fig-app. */
.fig-progress-bar-fill {
  opacity: var(--fig-progress-intensity, 1);
  transition: inline-size var(--fig-duration-3) var(--fig-ease-2), background-color var(--fig-duration-2) var(--fig-ease-2), opacity var(--fig-duration-2) var(--fig-ease-2);
}

@media (prefers-reduced-motion: reduce) {
  .fig-progress-bar-fill {
    transition: none;
  }
}
/* fig-gauge, spec: fig/styles/blocks/fig-gauge.md, edit via /design:create-or-update-block */
/* A labelled tricolor score gauge: a track painted red below the floor, amber
   between floor and strong-fit, green above strong-fit, with tick marks at those
   two thresholds and a needle at the candidate's score. Built for the culture-test
   verdict card (one gauge per value/mission/import category) so a reviewer reads
   pass/fail at a glance. The consumer sets three inline percents
   (--fig-gauge-val / --fig-gauge-floor / --fig-gauge-strong, 0-100%) and a
   [data-level] (danger|warning|success) that paints the value number. A category
   with no floor sets --fig-gauge-floor:0%, which collapses the red zone cleanly.
   Command-center only, no fig-app equivalent yet; sync back if fig-app gains a
   threshold gauge. */
.fig-gauge {
  display: block;
}

.fig-gauge-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--fig-space-2);
  margin-block-end: var(--fig-space-1);
}

.fig-gauge-label {
  font-size: var(--fig-text-2);
  font-weight: var(--fig-font-weight-medium);
  color: var(--fig-fg-default);
}

.fig-gauge-value {
  font-size: var(--fig-text-2);
  font-weight: var(--fig-font-weight-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--fig-fg-default);
}

/* Value paint by band, the number reads red/amber/green to match the needle's zone. */
.fig-gauge[data-level=danger] .fig-gauge-value {
  color: var(--fig-status-danger-fg);
}

.fig-gauge[data-level=warning] .fig-gauge-value {
  color: var(--fig-status-warning-fg);
}

.fig-gauge[data-level=success] .fig-gauge-value {
  color: var(--fig-status-success-fg);
}

.fig-gauge-track {
  position: relative;
  block-size: var(--fig-space-2);
  border-radius: var(--fig-border-radius-pill);
  /* Tricolor zones with hard stops at the floor and strong-fit thresholds. */
  background: linear-gradient(to right, var(--fig-bg-danger) 0 var(--fig-gauge-floor, 0%), var(--fig-bg-warning) var(--fig-gauge-floor, 0%) var(--fig-gauge-strong, 85%), var(--fig-bg-success) var(--fig-gauge-strong, 85%) 100%);
}

/* Threshold dividers, a thin slice of the card surface cutting the colored zones
   apart at the floor and strong-fit marks. */
.fig-gauge-tick {
  position: absolute;
  inset-block: 0;
  inline-size: 2px;
  transform: translateX(-50%);
  background: var(--fig-bg-default);
}

.fig-gauge-tick--floor {
  inset-inline-start: var(--fig-gauge-floor, 0%);
}

.fig-gauge-tick--strong {
  inset-inline-start: var(--fig-gauge-strong, 85%);
}

/* Needle, the candidate's actual score, a high-contrast line with a surface halo
   so it reads against any zone color. */
.fig-gauge-needle {
  position: absolute;
  inset-block: -2px;
  inline-size: 3px;
  inset-inline-start: var(--fig-gauge-val, 0%);
  transform: translateX(-50%);
  border-radius: var(--fig-border-radius-pill);
  background: var(--fig-fg-default);
  box-shadow: 0 0 0 1.5px var(--fig-bg-default);
}

/* fig-popover, spec: fig/styles/blocks/fig-popover.md, edit via /design:create-or-update-block */
.fig-popover {
  position: relative;
  display: inline-block;
}

.fig-popover-trigger {
  /* Consumers often style the trigger as a button or nav-item; the block only
     contributes cursor + reset. Actual paint comes from whatever class the
     consumer applies on the same element (e.g. `fig-button`, `fig-nav-item`). */
  cursor: pointer;
}

/* Panel, the floating surface. Hidden by default; revealed when the wrapper
   has `[data-open]` (toggled by fig-popover.js). Positioned via `data-side`. */
.fig-popover-panel {
  position: absolute;
  z-index: 1065; /* above sticky sidebars + modal backdrops */
  --fig-popover-max: var(--fig-container-1); /* size-band cap (see [data-size]); clamped to viewport below */
  min-inline-size: var(--fig-container--2);
  /* Never wider than the viewport. The band cap is clamped to the visible width
     (minus a gutter) so a panel can't overflow horizontally on a narrow page.
     Component-level, every popover, every size, every consumer. */
  max-inline-size: min(var(--fig-popover-max), 100vw - var(--fig-space-6));
  /* Viewport nudge, fig-popover.js measures the panel on open and sets this so
     a panel whose trigger sits at the page edge slides back inside the viewport.
     0 by default; pure-CSS / hover popovers that never overflow keep it 0. */
  transform: translateX(var(--fig-popover-shift, 0px));
  padding: var(--fig-space-2);
  border: 1px solid var(--fig-border-default);
  border-radius: var(--fig-border-radius-4);
  color: var(--fig-fg-default);
  background-color: var(--fig-bg-subtle);
  box-shadow: var(--fig-shadow-4);
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--fig-duration-1) var(--fig-ease-1), visibility var(--fig-duration-1) var(--fig-ease-1);
}

.fig-popover[data-open] > .fig-popover-panel {
  visibility: visible;
  opacity: 1;
}

/* -- Size variants (opt-in via [data-size] on the panel) --
   Default (no attribute) keeps the container--2 → container-1 band above.
   Three named widths map onto the fig-container scale so a panel can step up
   from a mini-menu to an index-card surface without a bespoke per-consumer
   min/max. Command-center addition (the agent-status popover needs an index-
   card-sized surface for last-activity detail); no fig-app equivalent yet,
   sync back if fig-app's popover gains a size knob. */
.fig-popover-panel[data-size=s] { /* date-picker / mini-menu, ~224px cap */
  --fig-popover-max: var(--fig-container--2);
  min-inline-size: var(--fig-container--3);
}

.fig-popover-panel[data-size=m] { /* index-card, 384–512px */
  --fig-popover-max: var(--fig-container-2);
  min-inline-size: var(--fig-container-1);
}

.fig-popover-panel[data-size=l] { /* large index-card, 512–640px */
  --fig-popover-max: var(--fig-container-3);
  min-inline-size: var(--fig-container-2);
}

/* -- Palette variants (opt-in via [data-palette] on the panel) --
   A panel dropped from a palette-tinted trigger (the filter/checklist
   dropdowns) carries the same hue on its own chrome, so trigger + menu read
   as one control: the border repeats the filter trigger's resting border
   mix (_fig-button.scss), the surface takes a faint wash of the same color.
   Each palette also exposes --fig-popover-item-hover-bg, the hover wash for
   interactive rows INSIDE the panel (checklist toggles, When presets), in the
   same hue — a row hover on a tinted panel must not fall back to neutral grey
   (it reads as a different control family than the trigger it dropped from).
   The mix strength is the trigger's hover strength minus the panel's resting
   fill, so hovered-row-on-panel composites to the same tint as the hovered
   trigger. Command-center addition; sync back if fig-app's popover gains a
   palette knob. */
.fig-popover-panel[data-palette=primary] {
  --fig-popover-item-hover-bg: color-mix(in srgb, var(--fig-bg-emphasis) 16%, transparent);
  border-color: color-mix(in srgb, var(--fig-bg-emphasis) 55%, transparent);
  background-color: color-mix(in srgb, var(--fig-bg-emphasis) 8%, var(--fig-bg-subtle));
}

.fig-popover-panel[data-palette=secondary] {
  --fig-popover-item-hover-bg: color-mix(in srgb, var(--fig-bg-secondary) 16%, transparent);
  border-color: color-mix(in srgb, var(--fig-bg-secondary) 55%, transparent);
  background-color: color-mix(in srgb, var(--fig-bg-secondary) 8%, var(--fig-bg-subtle));
}

.fig-popover-panel[data-palette=neutral] {
  --fig-popover-item-hover-bg: color-mix(in srgb, var(--fig-bg-inverse) 8%, transparent);
  border-color: color-mix(in srgb, var(--fig-bg-inverse) 25%, transparent);
  background-color: color-mix(in srgb, var(--fig-bg-inverse) 4%, var(--fig-bg-subtle));
}

/* Placement, anchor on each of 6 sides. `*-start` aligns the panel edge
   flush with the trigger's start edge on the cross axis; `*-end` flush with
   the end edge. Logical properties so RTL flips automatically. */
.fig-popover-panel[data-side=bottom-start] {
  inset-block-start: calc(100% + var(--fig-space-1));
  inset-inline-start: 0;
}

.fig-popover-panel[data-side=bottom-end] {
  inset-block-start: calc(100% + var(--fig-space-1));
  inset-inline-end: 0;
}

.fig-popover-panel[data-side=top-start] {
  inset-block-end: calc(100% + var(--fig-space-1));
  inset-inline-start: 0;
}

.fig-popover-panel[data-side=top-end] {
  inset-block-end: calc(100% + var(--fig-space-1));
  inset-inline-end: 0;
}

.fig-popover-panel[data-side=right-start] {
  inset-inline-start: calc(100% + var(--fig-space-2));
  inset-block-start: 0;
}

.fig-popover-panel[data-side=left-start] {
  inset-inline-end: calc(100% + var(--fig-space-2));
  inset-block-start: 0;
}

/* -- Anchored caret (opt-in via [data-arrow] on the wrapper) -- */
.fig-popover[data-arrow] > .fig-popover-panel::before {
  content: "";
  position: absolute;
  inline-size: var(--fig-space-2);
  block-size: var(--fig-space-2);
  background-color: var(--fig-bg-subtle);
  border: 1px solid var(--fig-border-default);
  transform: rotate(45deg);
}

.fig-popover[data-arrow] > .fig-popover-panel[data-side=bottom-start]::before {
  inset-block-start: calc(var(--fig-space-2) / -2);
  inset-inline-start: var(--fig-space-3);
  border-inline-end: 0;
  border-block-end: 0;
}

.fig-popover[data-arrow] > .fig-popover-panel[data-side=bottom-end]::before {
  inset-block-start: calc(var(--fig-space-2) / -2);
  inset-inline-end: var(--fig-space-3);
  border-inline-end: 0;
  border-block-end: 0;
}

.fig-popover[data-arrow] > .fig-popover-panel[data-side=top-start]::before {
  inset-block-end: calc(var(--fig-space-2) / -2);
  inset-inline-start: var(--fig-space-3);
  border-inline-start: 0;
  border-block-start: 0;
}

.fig-popover[data-arrow] > .fig-popover-panel[data-side=top-end]::before {
  inset-block-end: calc(var(--fig-space-2) / -2);
  inset-inline-end: var(--fig-space-3);
  border-inline-start: 0;
  border-block-start: 0;
}

.fig-popover[data-arrow] > .fig-popover-panel[data-side=right-start]::before {
  inset-inline-start: calc(var(--fig-space-2) / -2);
  inset-block-start: var(--fig-space-3);
  border-inline-end: 0;
  border-block-start: 0;
}

.fig-popover[data-arrow] > .fig-popover-panel[data-side=left-start]::before {
  inset-inline-end: calc(var(--fig-space-2) / -2);
  inset-block-start: var(--fig-space-3);
  border-inline-start: 0;
  border-block-end: 0;
}

@media (prefers-reduced-motion: reduce) {
  .fig-popover-panel {
    transition: none;
  }
}
/* -- Command-center addition: hover/focus trigger --
   fig-app drives the panel open via [data-open] toggled by fig-popover.js
   (click). For a read-only, JS-free reveal, e.g. the health page's per-day
   stats on bar hover, opt in with `data-hover` on the wrapper and the panel
   shows on hover or keyboard focus-within. No fig-app equivalent yet; sync
   back if fig-app gains a hover popover. */
.fig-popover[data-hover]:hover > .fig-popover-panel,
.fig-popover[data-hover]:focus-within > .fig-popover-panel {
  visibility: visible;
  opacity: 1;
}

/* fig-agent-status, nav-header liveness dot + popover. The dot colour encodes
   the agent's heartbeat state (data-state on the .fig-popover wrapper); the
   popover states the reason in words so the colour is never ambiguous. Pairs
   with command_center/agent_status.py (the AGENT_STATUS context) and the
   fig_agent_status.html block. Built on .fig-icon-button (the dot trigger) and
   .fig-popover (the panel), see those blocks for the shared chrome. */
.fig-agent-status__dot {
  inline-size: 9px;
  block-size: 9px;
  border-radius: 50%;
  background-color: var(--fig-fg-muted);
  flex: none;
}
.fig-agent-status[data-state=active] .fig-agent-status__dot {
  background-color: var(--fig-bg-success);
}
.fig-agent-status[data-state=idle] .fig-agent-status__dot {
  background-color: var(--fig-bg-warning);
}
.fig-agent-status[data-state=down] .fig-agent-status__dot {
  background-color: var(--fig-bg-danger);
}
.fig-agent-status[data-state=disconnected] .fig-agent-status__dot {
  background-color: var(--fig-fg-muted);
}
.fig-agent-status__panel {
  padding: var(--fig-space-3);
}
.fig-agent-status__heading {
  display: flex;
  align-items: center;
  gap: var(--fig-space-2);
  margin: 0 0 var(--fig-space-1);
  font-weight: 600;
}
.fig-agent-status__reason {
  margin: 0;
  color: var(--fig-fg-muted);
}
.fig-agent-status__stats {
  margin: var(--fig-space-3) 0 0;
  padding-block-start: var(--fig-space-3);
  border-block-start: 1px solid var(--fig-border-default);
}
.fig-agent-status__stat {
  display: flex;
  justify-content: space-between;
  gap: var(--fig-space-3);
}
.fig-agent-status__stat + .fig-agent-status__stat {
  margin-block-start: var(--fig-space-2);
}
.fig-agent-status__stat dt {
  color: var(--fig-fg-muted);
  flex: none;
}
.fig-agent-status__stat dd {
  margin: 0;
  text-align: end;
  min-inline-size: 0;
}
.fig-agent-status__card {
  display: block;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fig-agent-status__card-meta {
  display: block;
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-0);
}
.fig-agent-status__errors {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 21rem), 1fr));
  gap: var(--fig-space-3);
}
.fig-agent-status__errors .fig-error-message {
  flex: 1;
}
.fig-agent-status__error {
  display: flex;
  flex-direction: column;
  padding: var(--fig-space-3);
  border: 1px solid var(--fig-status-danger-border);
  border-radius: var(--fig-border-radius-4);
  background-color: color-mix(in srgb, var(--fig-status-danger-bg) 40%, var(--fig-bg-subtle));
  color: var(--fig-status-danger-fg);
}
.fig-agent-status__error .fig-icon-button {
  color: var(--fig-status-danger-fg);
  border-color: var(--fig-status-danger-border);
}
.fig-agent-status__error .fig-icon-button:hover:not(:disabled) {
  background-color: color-mix(in srgb, var(--fig-status-danger-border) 40%, transparent);
}
.fig-agent-status__error--resolved {
  border-color: var(--fig-status-success-border);
  background-color: var(--fig-status-success-bg);
  color: var(--fig-status-success-fg);
}
.fig-agent-status__error--resolved .fig-agent-status__error-link,
.fig-agent-status__error--resolved .fig-agent-status__error-body .fig-expandable-toggle {
  color: var(--fig-status-success-fg);
}
.fig-agent-status__error--resolved .fig-icon-button {
  color: var(--fig-status-success-fg);
  border-color: var(--fig-status-success-border);
}
.fig-agent-status__error--resolved .fig-icon-button:hover:not(:disabled) {
  background-color: color-mix(in srgb, var(--fig-status-success-border) 40%, transparent);
}
.fig-agent-status__error--resolved .fig-agent-status__error-dismiss {
  border-color: var(--fig-status-success-border);
  color: var(--fig-status-success-fg);
}
.fig-agent-status__error-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fig-space-2);
  margin: 0 0 var(--fig-space-1);
}
.fig-agent-status__error-titlebar {
  display: flex;
  align-items: center;
  gap: var(--fig-space-2);
  min-inline-size: 0;
}
.fig-agent-status__error-title {
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fig-agent-status__error-meta {
  margin: 0 0 var(--fig-space-2);
  font-size: var(--fig-text-0);
  opacity: 0.85;
}
.fig-agent-status__error-body {
  --fig-expandable-max-height: 10rem;
}
.fig-agent-status__error-body .fig-expandable-body {
  font-family: var(--fig-font-mono, monospace);
  font-size: var(--fig-text-0);
}
.fig-agent-status__error-body .fig-expandable-toggle {
  color: var(--fig-status-danger-fg);
}
.fig-agent-status__error-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fig-space-2);
  margin: var(--fig-space-2) 0 0;
}
.fig-agent-status__error-link {
  font-weight: 600;
  color: var(--fig-status-danger-fg);
}
.fig-agent-status__error-dismiss {
  margin-inline-start: auto;
  padding-block: var(--fig-space-1);
  padding-inline: var(--fig-space-3);
  border: 1px solid var(--fig-status-danger-border);
  border-radius: var(--fig-border-radius-3);
  background-color: transparent;
  color: var(--fig-status-danger-fg);
  font-family: inherit;
  font-size: var(--fig-text-0);
  font-weight: 600;
  line-height: var(--fig-line-height-snug);
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--fig-duration-2) var(--fig-ease-2), border-color var(--fig-duration-2) var(--fig-ease-2), color var(--fig-duration-2) var(--fig-ease-2);
}
.fig-agent-status__error-dismiss:hover:not(:disabled) {
  border-color: var(--fig-bg-danger);
  background-color: var(--fig-bg-danger);
  color: var(--fig-fg-on-danger);
}
.fig-agent-status__error-dismiss:focus-visible {
  outline: 2px solid var(--fig-bg-danger);
  outline-offset: 2px;
}
.fig-agent-status__action {
  margin: var(--fig-space-3) 0 0;
  font-weight: 600;
}

/* fig-followups, a card's collapsible follow-up thread (the agent's running
   comments on one approval). Mirrors fig-app's `fig-collapsible`: a full-width
   bar with a counter + chevron that expands vertically, newest first. Native
   <details>/<summary> drives open/closed, no JS. Sits above the card footer. */
.fig-followups {
  border-top: 1px solid var(--fig-border-default);
}

/* The bar, the always-visible clickable row. Kill the native disclosure
   triangle so our own chevron is the only affordance. */
.fig-followups-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fig-space-2);
  cursor: pointer;
  /* Pad by the one card-padding knob on every side so the collapsed bar reads as
     a full card section, its label is vertically centered with equal space above
     and below (matching the body/footer rows), not crammed against the footer
     divider. Inline inset lines the count + chevron up with body text; the
     section's top divider stays full-bleed. */
  padding-block: var(--fig-card-padding);
  padding-inline: var(--fig-card-padding);
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-2);
  list-style: none;
  user-select: none;
}

.fig-followups-bar::-webkit-details-marker {
  display: none;
}

.fig-followups-bar:hover {
  color: var(--fig-fg-default);
}

.fig-followups-count {
  font-weight: var(--fig-font-weight-semibold);
}

/* Single chevron glyph; rotates 180° when the <details> is open. */
.fig-followups-chevron {
  transition: transform 150ms var(--fig-ease-1);
  flex: none;
}

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

@media (prefers-reduced-motion: reduce) {
  .fig-followups-chevron {
    transition: none;
  }
}
/* The expanded thread, vertical stack, newest first (ordering done in the
   view filter). Each item is one comment with a meta line + a prose body. */
.fig-followups-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--fig-space-2);
  /* No top margin: the bar's own padding-block already opens the gap above the
     first comment when the thread expands. */
  /* Comment text shares the card body's inline inset (the bar above sets the
     same), so a follow-up reads flush with the card content, not the raw edge. */
  padding-inline: var(--fig-card-padding);
  /* Bottom inset so the last comment doesn't butt the card footer divider when
     the thread is expanded (the last item zeroes its own padding-block-end). */
  padding-block-end: var(--fig-space-3);
}

.fig-followups-item {
  padding-block-end: var(--fig-space-2);
  border-block-end: 1px solid var(--fig-border-muted);
}

.fig-followups-item:last-child {
  border-block-end: none;
  padding-block-end: 0;
}

.fig-followups-meta {
  display: flex;
  align-items: baseline;
  gap: var(--fig-space-2);
  font-size: var(--fig-text-1);
  color: var(--fig-fg-muted);
  margin-block-end: var(--fig-space-1);
}

.fig-followups-author {
  font-weight: var(--fig-font-weight-semibold);
  color: var(--fig-fg-default);
}

.fig-followups-body {
  font-size: var(--fig-text-2);
}

/* Markdown bodies emit <p> blocks (an Investigation / Fix write-up runs to two or
   three paragraphs); the design system zeroes paragraph margins globally, so
   restore inter-paragraph spacing here, the paragraphs read as separate blocks,
   not one run-on. First/last hug the comment's own bounds. */
.fig-followups-body > p {
  margin-block: 0 var(--fig-space-2);
}

.fig-followups-body > :first-child {
  margin-block-start: 0;
}

.fig-followups-body > :last-child {
  margin-block-end: 0;
}

/* A follow-up's own metadata grid (commit id, Sentry ID, a Link), same
   fig-meta-grid partial as the card, nudged in a touch below the comment body.
   Pulled back out by the list's inline padding so the grid cells' own inset
   (--fig-space-3) aligns the first column with the comment text instead of
   stacking the two paddings. */
.fig-followups-meta-grid {
  margin-block-start: var(--fig-space-2);
  margin-inline: calc(-1 * var(--fig-card-padding));
}

/* fig-expandable, a long read-only value clamped to the height AVAILABLE in its
   column, with a native <details> Expand/Collapse toggle. Used for a card's inbound
   message (_card_body_dl.html) so a long email stays verbatim but doesn't dominate
   the card.

   Height-fit, not line-count: the closed body clamps to --fig-expandable-max-height,
   which fig-expandable.js sets per card to the room left in the Incoming column once
   the (often taller) Outgoing column has set the row height, so on a long HubSpot
   deal card the email fills the column instead of truncating at a fixed few lines.
   [open] releases the clamp. The toggle is hidden until the JS adds .is-overflowing
   (the message is actually taller than the available height), a short message shows
   whole with no toggle. Needs JS (unlike the old pure-CSS line-clamp): with JS off
   the fallback max-height below still clamps, but the toggle won't appear. */
.fig-expandable {
  /* Kill the native disclosure triangle, the toggle text is the only affordance. */
}
.fig-expandable .fig-expandable-summary {
  display: block;
  cursor: pointer;
  list-style: none;
}
.fig-expandable .fig-expandable-summary::-webkit-details-marker {
  display: none;
}
.fig-expandable {
  /* Nothing to expand → no pointer affordance (the JS also blocks the toggle). */
}
.fig-expandable:not(.is-overflowing) .fig-expandable-summary {
  cursor: default;
}
.fig-expandable {
  /* Clamp to the JS-measured column height; fall back to ~9 lines before the JS
     runs / on cards with no Outgoing column to size against. Whitespace preserved
     so the original line breaks survive. */
}
.fig-expandable .fig-expandable-body {
  overflow: hidden;
  white-space: pre-wrap;
  max-height: var(--fig-expandable-max-height, 13.5rem);
}
.fig-expandable[open] .fig-expandable-body {
  max-height: none;
  overflow: visible;
}
.fig-expandable {
  /* Expand / Collapse affordance, hidden until JS flags overflow; label swaps on
     [open] via CSS so no duplicated markup. */
}
.fig-expandable .fig-expandable-toggle {
  display: none;
  margin-block-start: var(--fig-space-1);
  font-size: var(--fig-text-1);
  font-weight: var(--fig-font-weight-semibold);
  color: var(--fig-secondary-fg);
}
.fig-expandable.is-overflowing .fig-expandable-toggle {
  display: inline-block;
}
.fig-expandable .fig-expandable-toggle::after {
  content: "Expand";
}
.fig-expandable[open] .fig-expandable-toggle::after {
  content: "Collapse";
}
.fig-expandable .fig-expandable-summary:hover .fig-expandable-toggle {
  text-decoration: underline;
}

/* fig-thread, the Incoming email thread as a single-open accordion
   (_card_thread_accordion.html). One <details> per message; a shared
   [name="thread-<id>"] makes the browser enforce exactly-one-open natively
   (open one → the others collapse), so no JS. Newest message is rendered first
   and [open] by default.

   Each turn is its own card-style container nested inside the thread container
  , bordered with the --fig-card-* tokens, with a flip-on-open chevron. The summary
   is a clickable header (sender + when + chevron), the body is the message text
   (whitespace preserved). The recipient's own sent replies (.fig-thread-msg--self)
   read as the other side of the conversation, tinted + a "you" tag. */
/* Outer container: box every turn, gapping them off the outline. */
.fig-thread {
  display: flex;
  flex-direction: column;
  gap: var(--fig-space-2);
  border: var(--fig-card-border-width) solid var(--fig-card-border-color);
  border-radius: var(--fig-card-border-radius);
  padding: var(--fig-space-2);
}

/* Section label above the email / thread ("Email", "Email thread"), so the cell
   reads as email content at a glance rather than an unlabelled selector. Matches
   the meta-grid field labels (Sender / Subject) that sit above it in the column. */
.fig-thread-label {
  margin: 0 0 var(--fig-space-2);
  font-size: var(--fig-text-2);
  font-weight: var(--fig-font-weight-semibold);
  color: var(--fig-fg-muted);
}

.fig-thread .fig-thread-label {
  margin-block-end: 0;
}

/* A single incoming email: no accordion, no restated sender/date, just the message
   text under the "Email" label. No box of its own: the partial wraps itself in
   .fig-card-body (_card_thread_accordion.html), which already supplies the card
   section padding, so a nested border/background/padding would read as a redundant
   double frame (the label's own bottom margin gives the label→body gap). */
.fig-thread-single-body {
  white-space: pre-wrap;
  color: var(--fig-fg-default);
}

/* Each turn, a bordered card-style container, like a To-Do card. */
.fig-thread-msg {
  border: var(--fig-card-border-width) solid var(--fig-card-border-color);
  border-radius: var(--fig-border-radius-4);
  background: var(--fig-card-bg);
  overflow: hidden;
  /* The recipient's own sent replies, the other side of the conversation. */
}
.fig-thread-msg--self {
  border-color: var(--fig-accent-border);
  background: color-mix(in srgb, var(--fig-accent-border) 7%, var(--fig-card-bg));
}

.fig-thread-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fig-space-2);
  padding: var(--fig-space-2);
  cursor: pointer;
  list-style: none;
  font-size: var(--fig-text-1);
  /* Kill the native disclosure triangle, the whole header is the affordance. */
}
.fig-thread-summary::-webkit-details-marker {
  display: none;
}
.fig-thread-summary::marker {
  content: "";
}
.fig-thread-summary:hover .fig-thread-who {
  text-decoration: underline;
}
.fig-thread-summary:hover .fig-thread-chevron {
  color: var(--fig-fg-default);
}

.fig-thread-who {
  font-weight: var(--fig-font-weight-semibold);
  color: var(--fig-fg-default);
}

.fig-thread-tag {
  margin-inline-start: var(--fig-space-1);
  padding: 0 var(--fig-space-1);
  border-radius: var(--fig-border-radius-1);
  background: color-mix(in srgb, var(--fig-accent-border) 12%, transparent);
  color: var(--fig-secondary-fg);
  font-size: var(--fig-text-0);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* The right side of the header: timestamp + the disclosure chevron. */
.fig-thread-trailing {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: var(--fig-space-2);
}

.fig-thread-when {
  color: var(--fig-secondary-fg);
  font-size: var(--fig-text-0);
}

/* Chevron flips up when the turn is open. */
.fig-thread-chevron {
  color: var(--fig-fg-muted);
  flex: none;
  transition: transform var(--fig-duration-2) var(--fig-ease-1);
}

.fig-thread-msg[open] .fig-thread-chevron {
  transform: rotate(180deg);
}

.fig-thread-body {
  padding: 0 var(--fig-space-2) var(--fig-space-2);
  white-space: pre-wrap;
  color: var(--fig-fg-default);
  border-block-start: var(--fig-card-border-width) solid var(--fig-card-border-color);
  padding-block-start: var(--fig-space-2);
}

/* Links preserved from the email body (core.mail flattens <a href> to the URL,
   linkify_body wraps it). Long URLs wrap rather than overflow the panel. Shared by
   the accordion turn body and the single-email plain body. */
.fig-thread-body a,
.fig-thread-single-body a {
  color: var(--fig-accent-fg);
  text-decoration: underline;
  overflow-wrap: anywhere;
}

@media (prefers-reduced-motion: reduce) {
  .fig-thread-chevron {
    transition: none;
  }
}
/* fig-badge, spec: fig/styles/blocks/fig-badge.md, edit via /design:create-or-update-block */
:root {
  /* Diameter of the round (data-shape="circle") badge, a component-scoped token
     derived from the space scale (was a raw 1.75rem). Exposed so other chrome
     that must size to the badge, the approval-card header logo row, references
     one value instead of re-hardcoding it. */
  --fig-badge-size: var(--fig-space-5);
}

.fig-badge {
  display: inline-block;
  padding-block: var(--fig-space-1);
  padding-inline: var(--fig-space-2);
  border: 1px solid transparent;
  border-radius: var(--fig-border-radius-pill);
  font-family: inherit;
  font-size: var(--fig-text-2);
  font-weight: var(--fig-font-weight-medium);
  line-height: 1;
  text-align: center;
  white-space: nowrap;
  user-select: none;
}

/* -- Filled variants (spec §8: data-attr state, not `--modifier`) --
   Mirrors fig-button filled map, same semantic roles, same palette names. */
.fig-badge[data-variant=primary] {
  color: var(--fig-fg-on-emphasis);
  background-color: var(--fig-bg-emphasis);
  border-color: var(--fig-bg-emphasis);
}

.fig-badge[data-variant=secondary] {
  color: var(--fig-fg-on-secondary);
  background-color: var(--fig-bg-secondary);
  border-color: var(--fig-bg-secondary);
}

.fig-badge[data-variant=danger] {
  color: var(--fig-fg-on-danger);
  background-color: var(--fig-bg-danger);
  border-color: var(--fig-bg-danger);
}

.fig-badge[data-variant=success] {
  color: var(--fig-fg-on-success);
  background-color: var(--fig-bg-success);
  border-color: var(--fig-bg-success);
}

.fig-badge[data-variant=warning] {
  color: var(--fig-fg-on-warning);
  background-color: var(--fig-bg-warning);
  border-color: var(--fig-bg-warning);
}

.fig-badge[data-variant=accent] {
  color: var(--fig-fg-on-accent);
  background-color: var(--fig-bg-accent);
  border-color: var(--fig-bg-accent);
}

.fig-badge[data-variant=neutral] {
  color: var(--fig-fg-muted);
  background-color: var(--fig-bg-muted);
  border-color: var(--fig-bg-muted);
}

.fig-badge[data-variant=neutral-outline] {
  color: var(--fig-fg-muted);
  background-color: var(--fig-bg-subtle);
  border-color: var(--fig-border-default);
}

/* Category label chip (command-center addition): TWO-TONE in a category's own
   Outlook color, a dark fill of the hue with border + text in the bright version
   of the same hue, so a label reads AS its color (Sales/Quotes green, Rockwell
   dark-orange) exactly the way the new Outlook paints category tags in dark mode.

   Ground truth: David's (Vertech) ACTUAL Outlook category picker, dark mode, was
   pixel-sampled on 2026-07-03; every tag there renders dark-fill + bright-outline
   of one hue (e.g. Sales/Quotes fill #063004 / outline #3BAC55, Accounts
   Recievable #6E0811 / #DC564C, NVIDIA/HITT #202020 / #888888). The chip takes
   ONE identity color (--fig-label-color, set inline by _label_chip.html: a
   var(--fig-cat-<slug>) with the card's snapshot hex as fallback; the hex chain's
   SSoT incl. the sampled pairs is integrations/outlook/colors.py) and derives
   both tones with oklch relative colors. The constants were tuned against those
   sampled pairs: fill = the hue at L .31 with chroma capped at .09 (uncapped
   chroma gamut-clamps and shifts hue at low lightness), ink = the hue no darker
   than L .7 (max() lifts dark identities, black -> the gray outline Outlook
   shows, while already-bright hues keep their exact color). Relative color
   syntax needs Chrome/Edge 119+, Safari 16.4+, FF 128+, fine for this app.

   No color resolved -> the template renders a neutral-outline chip instead (that
   is Outlook parity too: an uncolored category shows a hollow tag there), so this
   variant is only ever emitted with its var set; the fallback ink is
   belt-and-suspenders. */
.fig-badge[data-variant=label] {
  --_label-ink: oklch(from var(--fig-label-color, var(--fig-fg-muted)) max(l, 0.7) c h);
  color: var(--_label-ink);
  background-color: oklch(from var(--fig-label-color, var(--fig-bg-subtle)) min(l, 0.31) min(c, 0.09) h);
  border-color: var(--_label-ink);
}

/* -- Outline variants --
   Same primitive-referencing fallback as fig-button: palette-000 bg,
   palette-500 border, palette-700 text. No outline-semantic family exists
   today and dark mode is paused; re-evaluate when either changes. */
.fig-badge[data-variant=primary-outline] {
  color: var(--fig-color-primary-700);
  background-color: var(--fig-color-primary-000);
  border-color: var(--fig-color-primary-500);
}

.fig-badge[data-variant=secondary-outline] {
  color: var(--fig-color-secondary-700);
  background-color: var(--fig-color-secondary-000);
  border-color: var(--fig-color-secondary-500);
}

.fig-badge[data-variant=tertiary-outline] {
  color: var(--fig-color-tertiary-700);
  background-color: var(--fig-color-tertiary-000);
  border-color: var(--fig-color-tertiary-500);
}

.fig-badge[data-variant=danger-outline] {
  color: var(--fig-color-danger-700);
  background-color: var(--fig-color-danger-000);
  border-color: var(--fig-color-danger-500);
}

.fig-badge[data-variant=success-outline] {
  color: var(--fig-color-success-700);
  background-color: var(--fig-color-success-000);
  border-color: var(--fig-color-success-500);
}

.fig-badge[data-variant=warning-outline] {
  color: var(--fig-color-warning-700);
  background-color: var(--fig-color-warning-000);
  border-color: var(--fig-color-warning-500);
}

.fig-badge[data-variant=accent-outline] {
  color: var(--fig-color-accent-700);
  background-color: var(--fig-color-accent-000);
  border-color: var(--fig-color-accent-500);
}

.fig-badge[data-variant=gold-outline] {
  color: var(--fig-color-gold-700);
  background-color: var(--fig-color-gold-000);
  border-color: var(--fig-color-gold-500);
}

/* -- Shape: circle (command-center addition, no fig-app equivalent yet; sync
   back when fig-app gains a round badge) --
   A fixed-diameter round chip for terse single-token labels (priority "P1").
   Square the box and force a pill radius so it reads as a coin, not a lozenge.
   min-inline-size keeps one- and two-char labels the same width. */
.fig-badge[data-shape=circle] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--fig-badge-size);
  block-size: var(--fig-badge-size);
  min-inline-size: var(--fig-badge-size);
  padding: 0;
}

/* -- Domain pills (command-center addition, no fig-app equivalent yet; sync
   back if fig-app gains categorical chips) --
   Six brand-colored slots cycled by data-domain="1".."6"; each pulls its bg/fg
   from the --fig-domain-N-* semantic tokens, which a deployment theme re-tints
   to its own palette. The --domain modifier pushes the chip to the trailing edge
   of a flex header (top-right of a card). */
.fig-badge--domain {
  margin-inline-start: auto;
}

.fig-badge[data-domain="1"] {
  color: var(--fig-domain-1-fg);
  background-color: var(--fig-domain-1-bg);
  border-color: var(--fig-domain-1-bg);
}

.fig-badge[data-domain="2"] {
  color: var(--fig-domain-2-fg);
  background-color: var(--fig-domain-2-bg);
  border-color: var(--fig-domain-2-bg);
}

.fig-badge[data-domain="3"] {
  color: var(--fig-domain-3-fg);
  background-color: var(--fig-domain-3-bg);
  border-color: var(--fig-domain-3-bg);
}

.fig-badge[data-domain="4"] {
  color: var(--fig-domain-4-fg);
  background-color: var(--fig-domain-4-bg);
  border-color: var(--fig-domain-4-bg);
}

.fig-badge[data-domain="5"] {
  color: var(--fig-domain-5-fg);
  background-color: var(--fig-domain-5-bg);
  border-color: var(--fig-domain-5-bg);
}

.fig-badge[data-domain="6"] {
  color: var(--fig-domain-6-fg);
  background-color: var(--fig-domain-6-bg);
  border-color: var(--fig-domain-6-bg);
}

/* Slot 0, no domain assigned: the synthetic Health groups that aren't roster
   plugins (System, Unassigned) carry color 0. Render a neutral muted chip rather
   than the transparent base, so an un-themed group still reads as a deliberate
   grey pill instead of a borderless label. */
.fig-badge[data-domain="0"] {
  color: var(--fig-fg-muted);
  background-color: var(--fig-bg-muted);
  border-color: var(--fig-bg-muted);
}

/* -- Interactive (orthogonal to data-variant) --
   Mirrors fig-app's shipped `fig-badge[data-interactive]` (opt-in clickable affordance):
   pointer cursor, a hover shadow-1 lift, a `:focus-visible` --fig-secondary-border outline,
   reduced-motion-guarded. Ported into the figclaw subset here (it was fig-app-only). Works
   on a `<button class="fig-badge">` OR an `<a class="fig-badge">` (the extra
   `text-decoration: none` neutralizes the anchor underline). First figclaw consumer: the
   attachment pills (_attachment_pills.html) that open a message in Outlook. inline-flex so a
   composed leading .fig-icon aligns with the label. */
.fig-badge[data-interactive] {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  text-decoration: none;
  transition: box-shadow var(--fig-duration-1) var(--fig-ease-1), transform var(--fig-duration-1) var(--fig-ease-1);
}

.fig-badge[data-interactive]:hover {
  box-shadow: var(--fig-shadow-1);
  transform: translateY(-1px);
}

.fig-badge[data-interactive]:focus-visible {
  outline: 2px solid var(--fig-secondary-border);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .fig-badge[data-interactive] {
    transition: none;
  }
  .fig-badge[data-interactive]:hover {
    transform: none;
  }
}
/* -- State variants (orthogonal to data-variant) -- */
/* Progress, pulsing dot before the label signals an in-flight HTMX-polled
   task. Composes with any data-variant; the dot inherits currentColor so each
   color tints its own dot. Per spec doc: animation is opt-in via this state,
   guarded by prefers-reduced-motion. */
.fig-badge[data-state=progress]::before {
  content: "";
  display: inline-block;
  inline-size: var(--fig-space-2);
  block-size: var(--fig-space-2);
  margin-inline-end: var(--fig-space-1);
  border-radius: var(--fig-border-radius-pill);
  background-color: currentColor;
  vertical-align: middle;
  animation: fig-badge-progress-pulse 1.5s ease-in-out infinite;
}

@keyframes fig-badge-progress-pulse {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.4;
  }
}
@media (prefers-reduced-motion: reduce) {
  .fig-badge[data-state=progress]::before {
    animation: none;
  }
}
/* fig-plugin-glyph, a plugin's brand-image identity mark, the image alternative
   to its emoji glyph. Rendered inline wherever the plugin shows (the catalog/
   audit pill, the approval card header, health job badges) by
   `conf.plugin_glyph_html`, so it sits next to text at the cap height of an
   emoji. Sized to the current font so it tracks whatever text it prefixes. */
.fig-plugin-glyph {
  block-size: 1em;
  inline-size: auto;
  vertical-align: -0.15em; /* sit on the text baseline like an emoji glyph */
}

/* Light/dark variant swap, identical contract to the nav brand logo: only
   engages when a plugin ships both `icon` + `icon_dark` (the --light/--dark
   modifiers); a single unmodified glyph shows in both themes. Dark variant
   hidden by default (light surface), shown on a dark theme (opted in via
   [data-theme="dark"] or auto via prefers-color-scheme unless opted to light). */
.fig-plugin-glyph--dark {
  display: none;
}

[data-theme=dark] .fig-plugin-glyph--light {
  display: none;
}
[data-theme=dark] .fig-plugin-glyph--dark {
  display: inline-block;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme=light]) .fig-plugin-glyph--light {
    display: none;
  }
  :root:not([data-theme=light]) .fig-plugin-glyph--dark {
    display: inline-block;
  }
}
/* fig-toast, spec: fig/styles/blocks/fig-toast.md, edit via /design:create-or-update-block */
/* -- Stack rail -- fixed viewport anchor for a stream of toasts. */
.fig-toast-stack {
  position: fixed;
  inset-block-end: var(--fig-space-4);
  inset-inline-end: var(--fig-space-4);
  z-index: 9999;
  inline-size: min(100vw - var(--fig-space-6), var(--fig-container-3));
  pointer-events: none; /* rail ignores clicks; each toast re-enables */
}

/* -- Entrance -- slide-up + fade with a soft overshoot. */
@keyframes fig-toast-enter {
  from {
    opacity: 0;
    transform: translateY(var(--fig-space-3));
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
/* -- Base toast -- translucent glass surface, deep elevation. Variants
   only swap the tint + accent bar; surface paint stays uniform so every
   toast shares the same depth + blur vocabulary as fig-chat-launcher. */
.fig-toast {
  pointer-events: auto;
  position: relative;
  overflow: hidden; /* clip the accent bar to the rounded corner */
  color: var(--fig-fg-default);
  background-color: color-mix(in srgb, var(--fig-bg-subtle) 80%, transparent);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid color-mix(in srgb, var(--fig-color-neutral-200) 60%, transparent);
  border-radius: var(--fig-border-radius-5);
  box-shadow: var(--fig-shadow-4);
  padding: var(--fig-space-3) var(--fig-space-4);
  animation: fig-toast-enter var(--fig-duration-5) var(--fig-ease-4) both;
  transition: opacity var(--fig-duration-3) var(--fig-ease-3), transform var(--fig-duration-3) var(--fig-ease-3);
}

/* -- Accent bar -- left edge in variant-fg, opt-in per variant.
   Neutral stays quiet by design; signal variants paint the bar. */
.fig-toast::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  inline-size: var(--fig-space--3);
  background-color: currentColor;
  opacity: 0;
}

/* -- Status variants -- color-mix tint over the base glass. */
.fig-toast[data-variant=success] {
  color: var(--fig-status-success-fg);
  background-color: color-mix(in srgb, var(--fig-status-success-bg) 85%, var(--fig-bg-subtle));
  border-color: color-mix(in srgb, var(--fig-status-success-border) 60%, transparent);
}

.fig-toast[data-variant=success]::before {
  opacity: 1;
}

.fig-toast[data-variant=warning] {
  color: var(--fig-status-warning-fg);
  background-color: color-mix(in srgb, var(--fig-status-warning-bg) 85%, var(--fig-bg-subtle));
  border-color: color-mix(in srgb, var(--fig-status-warning-border) 60%, transparent);
}

.fig-toast[data-variant=warning]::before {
  opacity: 1;
}

.fig-toast[data-variant=danger] {
  color: var(--fig-status-danger-fg);
  background-color: color-mix(in srgb, var(--fig-status-danger-bg) 85%, var(--fig-bg-subtle));
  border-color: color-mix(in srgb, var(--fig-status-danger-border) 60%, transparent);
}

.fig-toast[data-variant=danger]::before {
  opacity: 1;
}

/* -- Brand variants -- direct palette shades, same glass + accent treatment.
   No --fig-status-{primary,secondary,accent}-* triad exists yet; soft brand
   surfaces are an open question (re-evaluate when dark mode revives). */
.fig-toast[data-variant=primary] {
  color: var(--fig-color-primary-700);
  background-color: color-mix(in srgb, var(--fig-color-primary-000) 80%, var(--fig-bg-subtle));
  border-color: color-mix(in srgb, var(--fig-color-primary-200) 60%, transparent);
}

.fig-toast[data-variant=primary]::before {
  opacity: 1;
}

.fig-toast[data-variant=secondary] {
  color: var(--fig-color-secondary-700);
  background-color: color-mix(in srgb, var(--fig-color-secondary-000) 80%, var(--fig-bg-subtle));
  border-color: color-mix(in srgb, var(--fig-color-secondary-200) 60%, transparent);
}

.fig-toast[data-variant=secondary]::before {
  opacity: 1;
}

.fig-toast[data-variant=accent] {
  color: var(--fig-color-accent-700);
  background-color: color-mix(in srgb, var(--fig-color-accent-000) 80%, var(--fig-bg-subtle));
  border-color: color-mix(in srgb, var(--fig-color-accent-200) 60%, transparent);
}

.fig-toast[data-variant=accent]::before {
  opacity: 1;
}

/* -- Neutral variant -- explicit alias for the base paint; no accent bar. */
.fig-toast[data-variant=neutral] {
  color: var(--fig-fg-default);
  background-color: color-mix(in srgb, var(--fig-bg-subtle) 80%, transparent);
}

/* -- Inner parts -- */
.fig-toast-message {
  flex: 1;
  min-inline-size: 0; /* lets the flex row truncate rather than overflow */
  font-weight: 500;
}

.fig-toast-action {
  color: currentColor;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  padding: var(--fig-space-1) var(--fig-space-2);
  border-radius: var(--fig-border-radius-3);
  background: transparent;
  border: none;
  transition: background-color var(--fig-duration-2) var(--fig-ease-2);
}

.fig-toast-action:hover {
  background-color: color-mix(in srgb, currentColor 10%, transparent);
}

.fig-toast-action:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

.fig-toast-close {
  display: grid;
  place-items: center;
  inline-size: var(--fig-space-5);
  block-size: var(--fig-space-5);
  color: inherit;
  background: transparent;
  border: none;
  border-radius: var(--fig-border-radius-pill);
  cursor: pointer;
  opacity: 0.6;
  transition: opacity var(--fig-duration-2) var(--fig-ease-2), background-color var(--fig-duration-2) var(--fig-ease-2);
}

.fig-toast-close:hover {
  opacity: 1;
  background-color: color-mix(in srgb, currentColor 10%, transparent);
}

.fig-toast-close:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

/* -- Exceptions (state variants) -- exit downward, matching entrance vocabulary. */
.fig-toast[data-state=closing] {
  opacity: 0;
  transform: translateY(var(--fig-space-2));
  animation: none;
}

@media (prefers-reduced-motion: reduce) {
  .fig-toast {
    animation: none;
    transition: none;
  }
  .fig-toast[data-state=closing] {
    transform: none;
  }
}
/* fig-modal, spec: fig/styles/blocks/fig-modal.md, edit via /design:create-or-update-block

   Subset port of fig-app's _fig-modal.scss (core dialog + close + body; the
   config-modal machinery, fig-modal-inner / -save / -title / -header, isn't
   consumed here and is omitted per the figclaw MVP subset rule). A native
   <dialog> + showModal(), NOT a z-indexed div: body is the app @container
   root (container-type in _fig-globals.scss) and that containment lets the
   sticky nav paint over any fixed z-indexed descendant; the top layer is
   immune (companion un-stick rule in _fig-nav.scss). Markup + open/close JS:
   command_center/templates/_modal.html. */
.fig-modal {
  /* Reset <dialog> UA defaults so fig tokens drive every visual property.
     Border stays on (1px border-default) so the panel has a visible edge on
     dark surfaces where shadow elevation alone disappears.
     Deliberate divergence from fig-app's copy: no `position: relative`, the
     UA's `dialog:modal { position: fixed; inset: 0; margin: auto }` is what
     centers the panel (relative pins it to the viewport top), and a fixed box
     anchors absolute descendants (.fig-modal-close) just the same. */
  padding: 0;
  border: 1px solid var(--fig-border-default);
  color: var(--fig-fg-default);
  background-color: var(--fig-bg-subtle);
  border-radius: var(--fig-border-radius-5);
  box-shadow: var(--fig-shadow-4);
  /* Size, data-size picks a container token; inline-size shrinks for viewport gutters */
  max-inline-size: var(--fig-modal-size, var(--fig-container-2));
  inline-size: calc(100% - var(--fig-space-6));
  max-block-size: calc(100dvh - var(--fig-space-8));
  overflow: auto;
}

.fig-modal[data-size=sm] {
  --fig-modal-size: var(--fig-container-1);
}

.fig-modal[data-size=md] {
  --fig-modal-size: var(--fig-container-2);
}

.fig-modal[data-size=lg] {
  --fig-modal-size: var(--fig-container-5);
}

.fig-modal[data-size=xl] {
  --fig-modal-size: var(--fig-container-6);
}

.fig-modal[data-size=full] {
  --fig-modal-size: min(95vw, var(--fig-container-7));
  max-block-size: 95dvh;
}

/* Native ::backdrop, top layer handles inert + stacking. */
.fig-modal::backdrop {
  background-color: var(--fig-bg-overlay);
}

/* Close chrome button, absolute top-right overlay. */
.fig-modal-close {
  position: absolute;
  inset-block-start: var(--fig-space-3);
  inset-inline-end: var(--fig-space-3);
  display: grid;
  place-items: center;
  inline-size: var(--fig-space-6);
  block-size: var(--fig-space-6);
  font-size: var(--fig-text-4);
  line-height: 1;
  color: var(--fig-fg-muted);
  background: transparent;
  border: none;
  border-radius: var(--fig-border-radius-pill);
  cursor: pointer;
  transition: background-color var(--fig-duration-2) var(--fig-ease-2), color var(--fig-duration-2) var(--fig-ease-2);
}

.fig-modal-close:hover {
  color: var(--fig-fg-default);
  background-color: var(--fig-bg-muted);
}

.fig-modal-close:focus-visible {
  outline: 2px solid var(--fig-accent-border);
  outline-offset: 2px;
}

.fig-modal-body {
  inline-size: 100%;
}

@media (prefers-reduced-motion: reduce) {
  .fig-modal-close {
    transition: none;
  }
}
/* ============ command-center htmx modal (figclaw-side composition) ============
   The one shared in-page modal (_modal.html): content is HTMX-swapped into
   #fig-modal-body and the dialog auto-opens. Two content-driven shapes: */
/* A card in the modal drops the feed's 80svh self-cap (the dialog's own cap
   bounds it) so the card body scrolls and its action footer stays pinned to
   the dialog bottom, the same sticky-actions behavior as the feed's compact
   cards. The dialog turns into a flex column and the card flex-fills it. */
.fig-modal-body .approval-card {
  max-block-size: none;
}

.fig-modal:has(> .fig-modal-body > .approval-card) {
  display: flex;
  flex-direction: column;
  overflow: visible;
}

.fig-modal:has(> .fig-modal-body > .approval-card) > .fig-modal-body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-block-size: 0;
}

.fig-modal-body > .approval-card {
  flex: 1 1 auto;
  min-block-size: 0;
}

/* When the content IS a card, the card is already its own chrome: the dialog
   drops its frame (background, border, shadow) so just the card pops on the
   scrim, and the elevation shadow moves onto the card itself. The ✕ lifts
   out of the (now-frameless) dialog onto the scrim just above the card's
   top-right corner, the lightbox close. It is a CLOSE, never a dismiss: a
   decided card has no dismiss left to take (the header's dismiss ✕ is
   pending-only), so this one only puts the card away, hence the "Close"
   label, "dismiss" means something else in this app. Backdrop click +
   Escape still close too. */
.fig-modal:has(> .fig-modal-body > .approval-card) {
  background: transparent;
  border: none;
  box-shadow: none;
}

.fig-modal:has(> .fig-modal-body > .approval-card) > .fig-modal-close {
  inset-block-start: calc(-1 * var(--fig-space-7));
  inset-inline-end: 0;
  color: rgba(255, 255, 255, 0.85);
}

.fig-modal-body > .approval-card {
  box-shadow: var(--fig-shadow-4);
}

/* The logs viewer (_log_tail.html roots as .fig-log-tail) opens wide,
   monospace log lines need the room; same values as data-size="full",
   driven by content because the one dialog serves every swap. */
.fig-modal:has(> .fig-modal-body > .fig-log-tail) {
  --fig-modal-size: min(95vw, var(--fig-container-7));
  max-block-size: 95dvh;
}

/* The log-tail body carries its own close ✕ inline in the header icon-button row
   (the danger Dismiss control), so the absolute shell ✕ would stack on that row.
   Hide it here; the inline one closes via the [data-modal-close] hook (_modal.html). */
.fig-modal:has(> .fig-modal-body > .fig-log-tail) > .fig-modal-close {
  display: none;
}

/* ============ docked drawer variant (command-center addition) ============
   The universal chat drawer (_chat_drawer.html): a full-height panel docked
   to the inline-end viewport edge, sliding OVER content while the page stays
   scrollable + interactive. Reuse-ladder rationale: fig-popover is trigger-
   anchored (position: absolute in flow) and its JS closes on any outside
   click, both the opposite of a docked, explicit-close drawer; the modal
   dialog (showModal) makes the rest of the page inert, so the operator
   couldn't scroll the feed the conversation is about. So this EXTENDS
   fig-modal: same <dialog> chrome + .fig-modal-close, opened NON-modally via
   the popover API (`popover="manual"` + showPopover(), fig-chat-drawer.js).
   Manual popovers still ride the top layer, so the drawer paints over the
   sticky nav despite the body @container root (see the block header), with
   zero light-dismiss, close is the ✕ / Escape / the toggle, never an outside
   click. Old-browser fallback: dialog.show() (the [open] selector twin). */
.fig-modal[data-dock=end] {
  position: fixed;
  inset: 0 0 0 auto;
  margin: 0;
  flex-direction: column;
  inline-size: 100%;
  max-inline-size: min(var(--fig-container-2), 100vw - var(--fig-space-8));
  block-size: 100dvh;
  max-block-size: none;
  border: 0;
  border-inline-start: 1px solid var(--fig-border-default);
  border-radius: 0;
  overflow: hidden; /* the chat log scrolls internally */
  /* Directional edge shadow, NOT the inherited --fig-shadow-4. That preset is
     a downward-biased elevation for a floating centered dialog; on a full-height
     edge-docked panel its vertical black blur pools sideways and reads as a hard
     black bar. A docked drawer casts LEFTWARD over the content it slides across:
     negative-x offset, negative spread to keep it tight, lower alpha so it reads
     as ambient depth. (No shadow token models a horizontal cast, hence the raw
     value; the color still tracks the tokens' pure-black-on-dark convention.) */
  box-shadow: -12px 0 32px -12px rgba(0, 0, 0, 0.35);
  /* Slide-in/out. display + overlay are discrete-animated so the exit slide
     plays before the top layer drops the panel. */
  transform: translateX(100%);
  transition: transform var(--fig-duration-4) var(--fig-ease-1), display var(--fig-duration-4) allow-discrete, overlay var(--fig-duration-4) allow-discrete;
}

.fig-modal[data-dock=end]:popover-open,
.fig-modal[data-dock=end][open] {
  display: flex;
  transform: translateX(0);
}

@starting-style {
  .fig-modal[data-dock=end]:popover-open,
  .fig-modal[data-dock=end][open] {
    transform: translateX(100%);
  }
}
/* Non-modal: no scrim. The base .fig-modal::backdrop overlay would read as
   modal (and lie, the page stays interactive), so the docked panel drops it. */
.fig-modal[data-dock=end]::backdrop {
  background: none;
}

@media (prefers-reduced-motion: reduce) {
  .fig-modal[data-dock=end] {
    transition: none;
  }
}
/* integration-icons, provider logos for a card/skill's required integrations.
   Rendered by templates/_integration_icons.html above a card title. Markup sets
   img height via the attribute so the row works even before this CSS compiles;
   these rules add the visual polish (consistent box, subtle rounding). */
.integration-icons {
  /* Sits above the title with a hair of breathing room. */
  margin-block-end: var(--fig-space-1);
}

/* In a card footer (catalog cards, where the row stands in for the old
   "Credentials:" text) it shares a centered split row with the action button,
   drop the above-title bottom margin so the logos sit on the button's baseline. */
.fig-card-footer .integration-icons {
  margin-block-end: 0;
}

.integration-icon {
  display: block;
  height: var(--fig-space-4);
  width: auto; /* preserve each logo's aspect ratio */
  max-width: var(--fig-space-10); /* cap wide wordmark logos so one can't dominate */
  object-fit: contain;
  border-radius: var(--fig-border-radius-2);
}

/* fig-error-message, the raw machine error, as a drop-in block: a mono ("code")
   text panel on a danger tint a touch darker than the danger callout, with a copy
   button that fades in at the upper-right on hover/focus. No title, no chrome,
   it IS the error string, so it composes inside cards, popovers, drawers, etc.
   (the surrounding surface supplies the "Error" label / timestamp / links).
   Builds on .fig-icon-button for the copy control. */
.fig-error-message {
  position: relative;
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: var(--fig-space-2) var(--fig-space-3);
  border: 1px solid var(--fig-status-danger-border);
  border-radius: var(--fig-border-radius-2);
  /* A touch darker than the danger callout's bg, nudged toward the border so it
     reads as "stronger danger" in both light and dark themes. */
  background-color: color-mix(in srgb, var(--fig-status-danger-bg) 65%, var(--fig-status-danger-border));
  color: var(--fig-status-danger-fg);
}

/* The error string, always the mono font, whitespace preserved, wrapping.
   Leaves room on the right for the copy button so the first line never slips
   under it. Collapsed by default to N lines (--fig-error-lines, default 7); the
   Show-more toggle (revealed by fig-clamp.js only when it actually overflows)
   flips data-expanded to release the clamp. */
.fig-error-message-text {
  --fig-error-lines: 7;
  --_fig-error-line-height: 1.5;
  display: block;
  max-block-size: calc(var(--fig-error-lines) * var(--_fig-error-line-height) * 1em);
  overflow: hidden;
  padding-inline-end: var(--fig-space-5);
  font-family: var(--fig-font-family-mono);
  font-size: var(--fig-text-1);
  line-height: var(--_fig-error-line-height);
  white-space: pre-wrap;
  word-break: break-word;
  color: inherit;
}

.fig-error-message[data-expanded] .fig-error-message-text {
  /* Released, but still capped so a giant trace scrolls inside the block rather
     than pushing its host (a popover, a card) off-screen. */
  max-block-size: 28rem;
  overflow: auto;
}

/* Show-more / Show-less toggle, a quiet text link under the trace. fig-clamp.js
   un-hides it only when the collapsed text overflows the line clamp. */
.fig-error-message-toggle {
  align-self: start;
  margin-block-start: var(--fig-space-1);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--fig-status-danger-fg);
  font-size: var(--fig-text-1);
  font-weight: var(--fig-font-weight-medium);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

.fig-error-message-toggle:hover {
  opacity: 0.8;
}

.fig-error-message-toggle[hidden] {
  display: none;
}

/* Copy button, pinned upper-right, hidden until the block is hovered or anything
   inside it is focused (keyboard reach). Re-skinned from .fig-icon-button to the
   danger palette and sized down to sit quietly in the corner. */
.fig-error-message-copy.fig-icon-button {
  position: absolute;
  inset-block-start: var(--fig-space-1);
  inset-inline-end: var(--fig-space-1);
  inline-size: var(--fig-space-5);
  block-size: var(--fig-space-5);
  color: var(--fig-status-danger-fg);
  background-color: var(--fig-status-danger-bg);
  border-color: var(--fig-status-danger-border);
  opacity: 0;
  transition: opacity var(--fig-duration-1) var(--fig-ease-1), background-color var(--fig-duration-1) var(--fig-ease-1);
}

.fig-error-message:hover .fig-error-message-copy,
.fig-error-message:focus-within .fig-error-message-copy {
  opacity: 1;
}

/* Keep it reachable on touch (no hover): always show, just dimmer. */
@media (hover: none) {
  .fig-error-message-copy.fig-icon-button {
    opacity: 0.7;
  }
}
.fig-error-message-copy.fig-icon-button:hover {
  background-color: var(--fig-status-danger-border);
}

/* Transient "Copied" confirmation, fig-copy.js flips data-copied for ~1.5s. */
.fig-error-message-copy.fig-icon-button[data-copied=true] {
  opacity: 1;
  color: var(--fig-fg-on-emphasis);
  background-color: var(--fig-bg-success);
  border-color: var(--fig-bg-success);
}

/* fig-chat-input, spec: fig/styles/blocks/fig-chat-input.md, edit via /design:create-or-update-block

   Ported from fig-app's _fig-chat-input.scss (same block, same class names).
   figclaw subset: the composer frame + toolbar + textarea host only. Dropped
   from the fig-app copy: the `.fig-chat-input` sidebar-foot band (figclaw's
   composers sit inside the chat surface / drawer, not a sidebar footer), the
   Quill editor overrides (no Quill here, plain <textarea> always), the legacy
   `.gf-actions` bridge rules (no gf-* in figclaw), and `[data-placement="top"]`
   (no shared-dashboard mode). Token adaptations: focus border uses the semantic
   `--fig-secondary-border` (fig-app referenced the color primitive directly);
   min/max textarea heights use figclaw's space/container scale so the composer
   matches the /chat/ tab's prior proportions. Sync back if fig-app's block
   changes shape. */
/* Clean rounded frame around editor + toolbar. Composer-as-hero: large
   radius, generous internal padding. Focus is a restrained neutral ring, not
   the teal signature halo (that loud glow belongs to the chipped source card,
   [data-chat-context-active] in _fig-chat.scss); the composer just needs a
   quiet "you're here" tint, not to compete with the card it's grounded in. */
.fig-chat-input-container {
  display: flex;
  flex-direction: column;
  gap: var(--fig-space-2);
  padding: var(--fig-space-3);
  background-color: var(--fig-bg-subtle);
  border: 1px solid var(--fig-border-default);
  border-radius: var(--fig-border-radius-5);
  transition: border-color var(--fig-duration-1) var(--fig-ease-2), box-shadow var(--fig-duration-1) var(--fig-ease-2);
}

/* Ring shows while focused OR while a context chip is attached: a chip means
   the turn is already scoped to something, so the composer stays visibly "held"
   even after blur — losing the ring while the chip still rides would read as
   "nothing is in context" when something is. `.fig-chat-chips` is the immediately
   preceding sibling (unhidden only when chips.length, fig-chat-panel.js), so the
   adjacency selector tracks chip presence with no JS. */
.fig-chat-input-container:focus-within,
.fig-chat-chips:not([hidden]) + .fig-chat-input-container {
  border-color: var(--fig-border-emphasis);
  box-shadow: 0 0 0 2px var(--fig-border-muted);
}

/* Toolbar row: attach/context affordances start, send action end. */
.fig-chat-input-toolbar {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: var(--fig-space-2);
}

.fig-chat-input-toolbar-start {
  display: flex;
  align-items: center;
  gap: var(--fig-space-2);
}

.fig-chat-input-toolbar-end {
  display: flex;
  align-items: center;
  gap: var(--fig-space-2);
}

/* Textarea host, the editable surface. Renders flush with the input
   chrome; border / focus treatment live on the parent container. */
.fig-chat-input-textarea {
  display: block;
  inline-size: 100%;
  /* Opt out of the global 60ch measure axiom, the textarea fills the
     composer width set by the chat shell, not a prose column. */
  max-inline-size: none;
  min-block-size: var(--fig-space-8);
  /* Cap so a long multi-line message scrolls internally instead of pushing
     the log off-screen (fig-chat-panel.js autoGrow stops at the same cap). */
  max-block-size: var(--fig-container--3);
  padding: 0;
  font-family: inherit;
  font-size: var(--fig-text-2);
  line-height: var(--fig-line-height-body);
  color: var(--fig-fg-default);
  background-color: transparent;
  border: none;
  outline: none;
  resize: none;
  overflow-y: auto;
}

.fig-chat-input-textarea::placeholder {
  color: var(--fig-fg-subtle);
}

.fig-chat-input-textarea:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

@media (prefers-reduced-motion: reduce) {
  .fig-chat-input-container {
    transition: none;
  }
}
/* fig-chat, the shared chat message surface (log + bubbles + tool chips +
   slash menu + context chips), consumed by BOTH the /chat/ tab (chat.html) and
   the universal docked drawer (_chat_drawer.html). Promoted from chat.html's
   page-scoped inline <style> (the old `.chat-*` classes) when the drawer
   landed, so the two surfaces share one vocabulary instead of a page copy
   drifting (the fig-dash-* lesson). Markup: templates/_chat_panel.html;
   behavior: fig-chat-panel.js. Composes fig-chat-input (the composer frame),
   fig-button (send), fig-icon-button (attach). */
/* Shell. Default fills its parent (the drawer body); the /chat/ tab opts into
   viewport-height sizing via [data-surface="page"]. */
.fig-chat {
  display: flex;
  flex-direction: column;
  block-size: 100%;
  min-block-size: 0;
}

.fig-chat[data-surface=page] {
  /* Component-scoped offset (fig-badge token pattern): viewport height minus
     the nav header + page padding above the shell. Derived from the space
     scale, not a bare rem magic number. */
  --fig-chat-chrome-offset: calc(var(--fig-space-12) + var(--fig-space-9));
  block-size: calc(100vh - var(--fig-chat-chrome-offset));
  min-block-size: var(--fig-container-1);
}

.fig-chat-log {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--fig-space-4);
  padding: var(--fig-space-3) 0;
}

.fig-chat-empty {
  color: var(--fig-fg-muted);
  text-align: center;
  margin: auto 0;
}

.fig-chat-empty code {
  font-family: var(--fig-font-family-mono);
  background: var(--fig-bg-subtle);
  padding: 0 var(--fig-space-0);
  border-radius: var(--fig-border-radius-2);
}

/* -- Messages ------------------------------------------------------------- */
.fig-chat-msg {
  display: flex;
  flex-direction: column;
  gap: var(--fig-space-1);
  max-inline-size: 100%;
}

.fig-chat-msg__role {
  font-size: var(--fig-text-0);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--fig-fg-subtle);
}

.fig-chat-msg__body {
  border-radius: var(--fig-border-radius-3);
  padding: var(--fig-space-2) var(--fig-space-3);
  overflow-wrap: anywhere;
  line-height: var(--fig-line-height-body);
}

.fig-chat-msg--user {
  align-items: flex-end;
}

.fig-chat-msg--user .fig-chat-msg__body {
  background: var(--fig-accent-bg-subtle);
  white-space: pre-wrap;
}

.fig-chat-msg--agent .fig-chat-msg__body {
  background: var(--fig-bg-subtle);
}

/* A photo the user sent, shown in their own bubble above any text. */
.fig-chat-msg__image {
  display: block;
  max-inline-size: min(var(--fig-container-0), 100%);
  block-size: auto;
  border-radius: var(--fig-border-radius-2);
  margin-block-end: var(--fig-space-1);
}

/* Markdown inside an agent bubble, tight vertical rhythm. */
.fig-chat-md > :first-child {
  margin-block-start: 0;
}

.fig-chat-md > :last-child {
  margin-block-end: 0;
}

.fig-chat-md p {
  margin: var(--fig-space-2) 0;
}

.fig-chat-md ul,
.fig-chat-md ol {
  margin: var(--fig-space-2) 0;
  padding-inline-start: var(--fig-space-5);
}

.fig-chat-md h1,
.fig-chat-md h2,
.fig-chat-md h3 {
  margin: var(--fig-space-3) 0 var(--fig-space-1);
  line-height: var(--fig-line-height-snug);
}

.fig-chat-md code {
  font-family: var(--fig-font-family-mono);
  font-size: var(--fig-text-1);
  background: var(--fig-bg-subtle);
  padding: 0 var(--fig-space-0);
  border-radius: var(--fig-border-radius-2);
}

.fig-chat-md pre {
  background: var(--fig-bg-subtle);
  padding: var(--fig-space-2);
  border-radius: var(--fig-border-radius-2);
  overflow-x: auto;
  margin: var(--fig-space-2) 0;
}

.fig-chat-md pre code {
  background: none;
  padding: 0;
}

.fig-chat-md a {
  color: var(--fig-accent-fg);
  text-decoration: underline;
}

/* -- Tool-activity chips, one per tool call, inline above the agent text. -- */
.fig-chat-tools {
  display: flex;
  flex-wrap: wrap;
  gap: var(--fig-space-1);
  margin-block-end: var(--fig-space-1);
}

.fig-chat-tool {
  display: inline-flex;
  align-items: center;
  gap: var(--fig-space-0);
  font-size: var(--fig-text-0);
  font-family: var(--fig-font-family-mono);
  padding: var(--fig-space--4) var(--fig-space-2);
  border-radius: var(--fig-border-radius-pill);
  background: var(--fig-bg-subtle);
  color: var(--fig-fg-muted);
}

.fig-chat-tool[data-state=running] {
  color: var(--fig-secondary-fg);
}

.fig-chat-tool[data-state=done] {
  color: var(--fig-status-success-fg);
}

.fig-chat-tool__check {
  inline-size: var(--fig-space-3);
  block-size: var(--fig-space-3);
}

.fig-chat-tool__spin {
  animation: fig-chat-spin 1s var(--fig-ease-0) infinite;
  display: inline-block;
}

@keyframes fig-chat-spin {
  to {
    transform: rotate(360deg);
  }
}
.fig-chat-tool a {
  margin-inline-start: var(--fig-space-0);
}

.fig-chat-err {
  color: var(--fig-status-danger-fg);
  font-size: var(--fig-text-1);
}

/* -- Composer --------------------------------------------------------------
   The composer form wraps the slash menu + context chips + attachment preview
   + the fig-chat-input-container frame; relative so the slash menu anchors. */
.fig-chat-composer {
  position: relative;
  padding-block-start: var(--fig-space-2);
}

/* Attach preview: the staged image thumbnail + remove. */
.fig-chat-attachment {
  display: flex;
  align-items: center;
  gap: var(--fig-space-2);
  padding-block-end: var(--fig-space-2);
}

.fig-chat-attachment[hidden] {
  display: none;
}

.fig-chat-attachment__thumb {
  inline-size: var(--fig-space-9);
  block-size: var(--fig-space-9);
  object-fit: cover;
  border-radius: var(--fig-border-radius-2);
  border: 1px solid var(--fig-border-default);
}

.fig-chat-attachment__remove {
  border: 0;
  background: none;
  cursor: pointer;
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-2);
  line-height: var(--fig-line-height-tight);
  padding: var(--fig-space-1);
}

.fig-chat-attachment__remove:hover {
  color: var(--fig-status-danger-fg);
}

/* -- Context chips ----------------------------------------------------------
   Per-turn context riders ("card:123") staged in the composer. Modest chip
   chrome, the info-status soft pairing; the LOUD affordance is on the source
   element itself (the [data-chat-context-active] highlight below), not here. */
.fig-chat-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--fig-space-1);
  padding-block-end: var(--fig-space-2);
}

.fig-chat-chips[hidden] {
  display: none;
}

.fig-chat-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--fig-space-0);
  font-size: var(--fig-text-0);
  padding: var(--fig-space--3) var(--fig-space-2);
  border-radius: var(--fig-border-radius-pill);
  /* Primary palette, paired with the [data-chat-context-active] source ring so
     the chip and the card it points at read as one control. Same tint recipe as
     .fig-popover-panel[data-palette="primary"] (border 55% / fill 8% of the
     semantic --fig-bg-emphasis), so it follows each deployment's primary theme. */
  border: 1px solid color-mix(in srgb, var(--fig-bg-emphasis) 55%, transparent);
  background: color-mix(in srgb, var(--fig-bg-emphasis) 8%, var(--fig-bg-subtle));
  color: var(--fig-bg-emphasis);
  max-inline-size: 100%;
}

.fig-chat-chip__label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.fig-chat-chip__remove {
  border: 0;
  background: none;
  cursor: pointer;
  color: inherit;
  font-size: var(--fig-text-1);
  line-height: var(--fig-line-height-tight);
  padding: 0 var(--fig-space--3);
}

.fig-chat-chip__remove:hover {
  color: var(--fig-status-danger-fg);
}

/* Source-element context highlight. While a chip is active in the drawer,
   fig-chat-drawer.js stamps [data-chat-context-active] on every on-page
   element whose [data-chat-context-key] matches the chip (the approval card
   article for "card:<id>"), so the operator sees WHICH thing the conversation
   is grounded in. Generic by design: any future chip type only needs to stamp
   its key on its element, no new JS/CSS. Outline (not border) so the ring
   never shifts layout on an arbitrary host; 2px per the hairline-adjacent
   border-width exception. Primary palette (outline + --fig-glow-primary) to
   match the primary-tinted context chip, so the operator reads chip + source
   ring as one control; both follow the deployment's primary theme. */
[data-chat-context-active] {
  outline: 2px solid var(--fig-bg-emphasis);
  outline-offset: -1px;
  box-shadow: var(--fig-glow-primary);
  transition: box-shadow var(--fig-duration-2) var(--fig-ease-2);
}

/* Approval cards carry [data-variant="outline"], whose `box-shadow: none`
   (_fig-card.scss, specificity 0-2-0) out-specifies the ring above (0-1-0) and
   would eat the glow, leaving a border-only ring. Re-assert the glow at 0-3-0
   so the active card shows the full border + glow. */
.fig-card[data-variant=outline][data-chat-context-active] {
  box-shadow: var(--fig-glow-primary);
}

/* -- Slash autocomplete menu ------------------------------------------------ */
.fig-chat-slash {
  position: absolute;
  inset-inline: 0;
  inset-block-end: calc(100% + var(--fig-space-0));
  max-block-size: var(--fig-container-0);
  overflow-y: auto;
  background: var(--fig-bg-default);
  border: 1px solid var(--fig-border-default);
  border-radius: var(--fig-border-radius-2);
  box-shadow: var(--fig-shadow-2);
  z-index: 20;
}

.fig-chat-slash[hidden] {
  display: none;
}

.fig-chat-slash__item {
  display: flex;
  flex-direction: column;
  gap: var(--fig-space--4);
  padding: var(--fig-space-1) var(--fig-space-3);
  cursor: pointer;
}

.fig-chat-slash__item[aria-selected=true] {
  background: var(--fig-accent-bg-subtle);
}

.fig-chat-slash__head {
  display: flex;
  gap: var(--fig-space-2);
  align-items: baseline;
}

.fig-chat-slash__cmd {
  font-family: var(--fig-font-family-mono);
  font-size: var(--fig-text-1);
  font-weight: var(--fig-font-weight-semibold);
}

.fig-chat-slash__name {
  font-size: var(--fig-text-1);
  color: var(--fig-fg-muted);
}

.fig-chat-slash__desc {
  font-size: var(--fig-text-0);
  color: var(--fig-fg-subtle);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-inline-size: 100%;
}

.fig-chat-slash__empty {
  padding: var(--fig-space-2) var(--fig-space-3);
  color: var(--fig-fg-subtle);
  font-size: var(--fig-text-1);
}

/* -- Drawer inner chrome (the docked shell is fig-modal[data-dock="end"]) --
   The drawer's entry point is a header icon button (fig-icon-button in
   base.html's fig-icon-button-group), matching the approval-card chat
   affordance. Cmd/Ctrl+J opens the drawer anywhere. */
.fig-chat-drawer-head {
  display: flex;
  align-items: center; /* title + close ✕ share one baseline */
  justify-content: space-between; /* title leads, close ✕ trails */
  gap: var(--fig-space-2);
  /* The drawer header is the chat surface's "topbar", so it must read as a
     sibling of fig-nav, not a taller one-off. Pin the height to the published
     --fig-nav-height SSoT (_fig-nav.scss) instead of letting it fall out of the
     close button (space-6) + padding, which ran ~6px taller than the app nav.
     Block padding drops to 0 so the constant alone governs height; contents
     center. Inline padding stays space-4 to match the nav's inline gutter. */
  min-block-size: var(--fig-nav-height);
  padding-block: 0;
  padding-inline: var(--fig-space-4);
  border-block-end: 1px solid var(--fig-border-muted);
}

.fig-chat-drawer-body {
  flex: 1;
  min-block-size: 0;
  display: flex;
  flex-direction: column;
  padding: 0 var(--fig-space-4) var(--fig-space-4);
}

.fig-chat-drawer-body > .fig-chat {
  flex: 1;
  min-block-size: 0;
}

/* Lazy-load placeholder shown between first open and the fragment landing. */
.fig-chat-drawer-loading {
  margin: auto;
  color: var(--fig-fg-muted);
  font-size: var(--fig-text-1);
}

@media (prefers-reduced-motion: reduce) {
  .fig-chat-tool__spin {
    animation: none;
  }
  [data-chat-context-active] {
    transition: none;
  }
}
