import type { RecipeTokenSet, RecipeTokenMap, RecipeTokenMultiDeclaration, RecipeTokenDeclaration } from '../config-types'; export const THEME_BASE_RECIPE_TOKENS = { accordion: { 'provider-border-width': 'var(--border-width)', 'provider-radius': 'var(--radius-lg)', 'outline-provider-bg': 'var(--color-surface-default)', 'outline-provider-border': 'var(--color-border-default)', 'outline-item-border': 'var(--color-border-subtle)', 'outline-content-bg': 'var(--color-surface-default)', 'surface-provider-bg': 'var(--color-surface-raised)', 'surface-provider-border': 'var(--color-border-subtle)', 'surface-provider-shadow': 'var(--shadow-subtle)', 'surface-item-border': 'var(--color-border-subtle)', 'surface-content-bg': 'var(--color-surface-default)', 'ghost-provider-bg': 'transparent', 'ghost-provider-border': 'transparent', 'ghost-item-border': 'var(--color-border-subtle)', 'ghost-content-bg': 'transparent', 'item-border-width': 'var(--border-width)', 'trigger-min-height-xs': 'var(--control-height-xs)', 'trigger-min-height-sm': 'var(--control-height-sm)', 'trigger-min-height-md': 'var(--control-height-md)', 'trigger-min-height-lg': 'var(--control-height-lg)', 'trigger-min-height-full': 'var(--control-height-xl)', 'trigger-px-xs': 'var(--space-2-5)', 'trigger-px-sm': 'var(--space-3)', 'trigger-px-md': 'var(--space-4)', 'trigger-px-lg': 'var(--space-5)', 'trigger-px-full': 'var(--space-6)', 'trigger-py-xs': 'var(--space-2)', 'trigger-py-sm': 'var(--space-2-5)', 'trigger-py-md': 'var(--space-3)', 'trigger-py-lg': 'var(--space-3-5)', 'trigger-py-full': 'var(--space-4)', 'trigger-gap': 'var(--space-3)', 'trigger-font-family': 'var(--font-ui)', 'trigger-font-size-xs': 'var(--text-2-size)', 'trigger-font-size-sm': 'var(--text-3-size)', 'trigger-font-size-md': 'var(--text-4-size)', 'trigger-font-size-lg': 'var(--text-5-size)', 'trigger-font-size-full': 'var(--text-6-size)', 'trigger-font-weight': 'var(--font-weight-medium)', 'trigger-line-height': 'var(--leading-ui)', 'trigger-color': 'var(--color-content-primary)', // Open state: keep the trigger text in the primary content tone. // The chevron rotation + revealed content already signal openness; // recoloring the heading adds noise without information (matches // shadcn/Radix/Ark). 'trigger-color-open': 'var(--color-content-primary)', 'trigger-color-disabled': 'var(--color-content-disabled)', 'trigger-hover-bg': 'var(--color-surface-raised)', 'trigger-hover-color': 'var(--color-content-primary)', 'trigger-transition-duration': 'var(--duration-fast)', 'trigger-transition-ease': 'var(--ease-default)', 'trigger-focus-ring-offset': 'var(--focus-ring-offset)', 'trigger-focus-ring-width': 'var(--focus-ring-width)', 'trigger-focus-ring-color': 'var(--focus-ring-color)', 'content-px-xs': 'var(--space-2-5)', 'content-px-sm': 'var(--space-3)', 'content-px-md': 'var(--space-4)', 'content-px-lg': 'var(--space-5)', 'content-px-full': 'var(--space-6)', 'content-py-xs': 'var(--space-2)', 'content-py-sm': 'var(--space-2-5)', 'content-py-md': 'var(--space-3)', 'content-py-lg': 'var(--space-4)', 'content-py-full': 'var(--space-5)', 'content-font-family': 'var(--font-prose)', 'content-font-size': 'var(--text-4-size)', 'content-line-height': 'var(--leading-prose)', 'content-color': 'var(--color-content-secondary)', 'content-open-duration': 'var(--duration-normal)', 'content-close-duration': 'var(--duration-fast)', 'content-open-ease': 'var(--ease-out)', 'content-close-ease': 'var(--ease-in)', 'indicator-size-xs': 'var(--icon-size-xs)', 'indicator-size-sm': 'var(--icon-size-sm)', 'indicator-size-md': 'var(--icon-size-sm)', 'indicator-size-lg': 'var(--icon-size-md)', 'indicator-color': 'var(--color-content-secondary)', // Indicator turns to the primary content tone when open — a subtle // emphasis without the loud accent recolor. 'indicator-color-open': 'var(--color-content-primary)', 'indicator-rotation': '180deg', 'indicator-transition-duration': 'var(--duration-fast)', 'indicator-transition-ease': 'var(--ease-default)' }, avatar: ((): RecipeTokenMap => { // TSC v2.2 — 2D matrix (variant × color) cascade. // // Avatar's per-instance palette varies across 8 colors × 3 // variants. Each variant flavor (solid/soft/outline) reads // different slots from the same color block. Encoding 24 // composite scopes by hand for 6 tokens (3 on the root, 3 on the // badge part) is 144 lines of boilerplate; this small helper // generates them with the same intent. // // Helper consumed only here — explicit declarations would obscure // the variant logic. Keep the helper local to the entry to avoid // polluting the recipes module surface. const COLORS = [ 'primary', 'secondary', 'neutral', 'affirm', 'fulfill', 'risk', 'threat', 'loss' ] as const; type AvatarColor = (typeof COLORS)[number]; type AvatarVariant = 'solid' | 'soft' | 'outline'; /** Build (variant × color) declarations for a slot getter. */ function matrix( pick: (color: AvatarColor, variant: AvatarVariant) => string | undefined, parts?: readonly string[] ): RecipeTokenMultiDeclaration { const declarations: RecipeTokenDeclaration[] = []; for (const variant of ['solid', 'soft', 'outline'] as const) { for (const color of COLORS) { const value = pick(color, variant); if (value === undefined) continue; declarations.push({ value, scope: [`variant:${variant}`, `color:${color}`] }); } } return parts ? { parts, declarations } : { declarations }; } return { 'size-xs': '24px', 'size-sm': '32px', 'size-md': '40px', 'size-lg': '48px', 'size-xl': '64px', 'size-xxl': '96px', 'font-family': 'var(--font-ui)', 'font-size-xs': 'var(--font-size-xxs)', 'font-size-sm': 'var(--font-size-xs)', 'font-size-md': 'var(--font-size-sm)', 'font-size-lg': 'var(--font-size-md)', 'font-size-xl': 'var(--font-size-lg)', 'font-size-xxl': 'var(--font-size-xl)', 'font-weight': 'var(--font-weight-medium)', 'radius-full': 'var(--radius-full)', 'radius-md': 'var(--radius-md)', 'radius-sm': 'var(--radius-sm)', 'radius-none': '0', 'border-width': 'var(--border-width-medium)', 'primary-solid-bg': 'var(--color-primary-solid)', 'primary-solid-fg': 'var(--color-primary-contrast)', 'primary-soft-bg': 'var(--color-primary-surface)', 'primary-soft-fg': 'var(--color-primary-text)', 'primary-outline-border': 'var(--color-primary-border)', 'primary-outline-fg': 'var(--color-primary-text)', 'secondary-solid-bg': 'var(--color-secondary-solid)', 'secondary-solid-fg': 'var(--color-secondary-contrast)', 'secondary-soft-bg': 'var(--color-secondary-surface)', 'secondary-soft-fg': 'var(--color-secondary-text)', 'secondary-outline-border': 'var(--color-secondary-border)', 'secondary-outline-fg': 'var(--color-secondary-text)', 'neutral-solid-bg': 'var(--color-neutral-solid)', 'neutral-solid-fg': 'var(--color-neutral-contrast)', 'neutral-soft-bg': 'var(--color-neutral-surface)', 'neutral-soft-fg': 'var(--color-neutral-text)', 'neutral-outline-border': 'var(--color-neutral-border)', 'neutral-outline-fg': 'var(--color-neutral-text)', 'affirm-solid-bg': 'var(--color-affirm-solid)', 'affirm-solid-fg': 'var(--color-affirm-contrast)', 'affirm-soft-bg': 'var(--color-affirm-surface)', 'affirm-soft-fg': 'var(--color-affirm-text)', 'affirm-outline-border': 'var(--color-affirm-border)', 'affirm-outline-fg': 'var(--color-affirm-text)', 'fulfill-solid-bg': 'var(--color-fulfill-solid)', 'fulfill-solid-fg': 'var(--color-fulfill-contrast)', 'fulfill-soft-bg': 'var(--color-fulfill-surface)', 'fulfill-soft-fg': 'var(--color-fulfill-text)', 'fulfill-outline-border': 'var(--color-fulfill-border)', 'fulfill-outline-fg': 'var(--color-fulfill-text)', 'risk-solid-bg': 'var(--color-risk-solid)', 'risk-solid-fg': 'var(--color-risk-contrast)', 'risk-soft-bg': 'var(--color-risk-surface)', 'risk-soft-fg': 'var(--color-risk-text)', 'risk-outline-border': 'var(--color-risk-border)', 'risk-outline-fg': 'var(--color-risk-text)', 'threat-solid-bg': 'var(--color-threat-solid)', 'threat-solid-fg': 'var(--color-threat-contrast)', 'threat-soft-bg': 'var(--color-threat-surface)', 'threat-soft-fg': 'var(--color-threat-text)', 'threat-outline-border': 'var(--color-threat-border)', 'threat-outline-fg': 'var(--color-threat-text)', 'loss-solid-bg': 'var(--color-loss-solid)', 'loss-solid-fg': 'var(--color-loss-contrast)', 'loss-soft-bg': 'var(--color-loss-surface)', 'loss-soft-fg': 'var(--color-loss-text)', 'loss-outline-border': 'var(--color-loss-border)', 'loss-outline-fg': 'var(--color-loss-text)', // ── Ring (outline halo around the avatar) ──────────────────────── 'ring-width-sm': '1.5px', 'ring-width-md': '2px', 'ring-width-lg': '3px', // ── Custom color (consumer-provided CSS color string) ──────────── // Set inline by the Svelte file via `style="--avatar-color-custom: …"`. // Declared here so the recipe-css-contract test sees a declaration. 'color-custom': 'currentColor', 'color-custom-contrast': 'white', 'ring-color-custom': 'currentColor', // ── Badge ───────────────────────────────────────────────────────── 'badge-border-width': 'var(--border-width-medium)', 'badge-color-custom': 'currentColor', 'badge-color-custom-contrast': 'white', // ── AvatarGroup ────────────────────────────────────────────────── 'group-gap-xs': 'var(--space-1)', 'group-gap-sm': 'var(--space-2)', 'group-gap-md': 'var(--space-3)', 'group-gap-lg': 'var(--space-4)', 'group-overlap': '-0.6em', 'group-carve-width': 'var(--border-width-medium)', 'group-carve-color': 'var(--color-surface-default)', 'group-reverse-z-max': '20', 'group-max': '99', 'overflow-font-weight': 'var(--font-weight-medium)', // ── TSC v2.2 — composite (variant × color) cascade ──────────────── // 8 colors × 3 variants = 24 composite scopes per slot, applied // to the root for {_bg, _fg, _border} and to the badge part for // {_badge-bg, _badge-fg, _badge-border} (matrix helper above // generates the declarations[] from the slot pickers). // // Defaults at `host` match the legacy CSS base rule (avatar: // neutral-soft; badge: affirm-solid). Outline is the only variant // that touches `_border` / `_badge-border`; solid+soft keep the // transparent / surface-default defaults. _bg: { declarations: [ { value: 'var(--avatar-neutral-soft-bg)', scope: 'host' }, ...matrix((color, variant) => variant === 'outline' ? 'transparent' : `var(--avatar-${color}-${variant}-bg)` ).declarations ] }, _fg: { declarations: [ { value: 'var(--avatar-neutral-soft-fg)', scope: 'host' }, ...matrix((color, variant) => `var(--avatar-${color}-${variant}-fg)`).declarations ] }, _border: { declarations: [ { value: 'transparent', scope: 'host' }, ...matrix((color, variant) => variant === 'outline' ? `var(--avatar-${color}-outline-border)` : undefined ).declarations ] }, '_badge-bg': { parts: ['badge'], declarations: [ { value: 'var(--avatar-affirm-solid-bg)', scope: 'host' }, ...matrix((color, variant) => variant === 'outline' ? 'var(--color-surface-default)' : `var(--avatar-${color}-${variant}-bg)` ).declarations ] }, '_badge-fg': { parts: ['badge'], declarations: [ { value: 'var(--avatar-affirm-solid-fg)', scope: 'host' }, ...matrix((color, variant) => `var(--avatar-${color}-${variant}-fg)`).declarations ] }, '_badge-border': { parts: ['badge'], declarations: [ { value: 'var(--color-surface-default)', scope: 'host' }, ...matrix((color, variant) => variant === 'outline' ? `var(--avatar-${color}-outline-border)` : undefined ).declarations ] } }; })(), badge: { // ── Padding scale ──────────────────────────────────────────────── 'px-xs': 'var(--space-1-5)', 'px-sm': 'var(--space-2)', 'px-md': 'var(--space-2-5)', 'px-lg': 'var(--space-3)', 'py-xs': 'var(--space-0-5)', 'py-sm': 'var(--space-0-5)', 'py-md': 'var(--space-1)', 'py-lg': 'var(--space-1-5)', // ── Gap between dot / icon / label / remove ─────────────────────── 'gap-xs': 'var(--space-1)', 'gap-sm': 'var(--space-1)', 'gap-md': 'var(--space-1-5)', 'gap-lg': 'var(--space-2)', // ── Typography ──────────────────────────────────────────────────── 'font-family': 'var(--font-ui)', 'font-size-xs': 'var(--font-size-xs)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'font-weight': 'var(--font-weight-medium)', 'line-height': 'var(--leading-ui)', 'letter-spacing': '0.01em', // ── Borders + radii ─────────────────────────────────────────────── 'border-width': 'var(--border-width)', 'radius-sm': 'var(--radius-sm)', 'radius-md': 'var(--radius-md)', 'radius-lg': 'var(--radius-lg)', 'radius-full': 'var(--radius-full)', // ── Inner slots ─────────────────────────────────────────────────── // Use em so internal parts scale with the badge's resolved font-size. 'dot-size': '0.5em', 'icon-size': '1em', 'remove-size': '1.25em', 'remove-margin-start': '0.125em', // ── Color palette (mirrors the canonical 8-color matrix) ────────── 'primary-solid': 'var(--color-primary-solid)', 'primary-text': 'var(--color-primary-text)', 'primary-contrast': 'var(--color-primary-contrast)', 'secondary-solid': 'var(--color-secondary-solid)', 'secondary-text': 'var(--color-secondary-text)', 'secondary-contrast': 'var(--color-secondary-contrast)', 'neutral-solid': 'var(--color-neutral-solid)', 'neutral-text': 'var(--color-neutral-text)', 'neutral-contrast': 'var(--color-neutral-contrast)', 'affirm-solid': 'var(--color-affirm-solid)', 'affirm-text': 'var(--color-affirm-text)', 'affirm-contrast': 'var(--color-affirm-contrast)', 'fulfill-track': 'var(--color-fulfill-track)', 'fulfill-border': 'var(--color-fulfill-border)', 'fulfill-solid': 'var(--color-fulfill-solid)', 'fulfill-text': 'var(--color-fulfill-text)', 'fulfill-contrast': 'var(--color-fulfill-contrast)', 'risk-solid': 'var(--color-risk-solid)', 'risk-text': 'var(--color-risk-text)', 'risk-contrast': 'var(--color-risk-contrast)', 'threat-solid': 'var(--color-threat-solid)', 'threat-text': 'var(--color-threat-text)', 'threat-contrast': 'var(--color-threat-contrast)', 'loss-track': 'var(--color-loss-track)', 'loss-border': 'var(--color-loss-border)', 'loss-solid': 'var(--color-loss-solid)', 'loss-text': 'var(--color-loss-text)', 'loss-contrast': 'var(--color-loss-contrast)', // Restored after accidental sed-removal during switch migration. 'primary-track': 'var(--color-primary-track)', 'primary-border': 'var(--color-primary-border)', 'secondary-track': 'var(--color-secondary-track)', 'secondary-border': 'var(--color-secondary-border)', 'neutral-track': 'var(--color-neutral-track)', 'neutral-border': 'var(--color-neutral-border)', 'affirm-track': 'var(--color-affirm-track)', 'affirm-border': 'var(--color-affirm-border)', 'risk-track': 'var(--color-risk-track)', 'risk-border': 'var(--color-risk-border)', 'threat-track': 'var(--color-threat-track)', 'threat-border': 'var(--color-threat-border)', // Private palette (TSC v2.1). 8 colors, 5 slots. _track: { declarations: [ { value: 'var(--badge-primary-track)', scope: 'host' }, { value: 'var(--badge-secondary-track)', scope: 'color:secondary' }, { value: 'var(--badge-neutral-track)', scope: 'color:neutral' }, { value: 'var(--badge-affirm-track)', scope: 'color:affirm' }, { value: 'var(--badge-fulfill-track)', scope: 'color:fulfill' }, { value: 'var(--badge-risk-track)', scope: 'color:risk' }, { value: 'var(--badge-threat-track)', scope: 'color:threat' }, { value: 'var(--badge-loss-track)', scope: 'color:loss' } ] }, _border: { declarations: [ { value: 'var(--badge-primary-border)', scope: 'host' }, { value: 'var(--badge-secondary-border)', scope: 'color:secondary' }, { value: 'var(--badge-neutral-border)', scope: 'color:neutral' }, { value: 'var(--badge-affirm-border)', scope: 'color:affirm' }, { value: 'var(--badge-fulfill-border)', scope: 'color:fulfill' }, { value: 'var(--badge-risk-border)', scope: 'color:risk' }, { value: 'var(--badge-threat-border)', scope: 'color:threat' }, { value: 'var(--badge-loss-border)', scope: 'color:loss' } ] }, _solid: { declarations: [ { value: 'var(--badge-primary-solid)', scope: 'host' }, { value: 'var(--badge-secondary-solid)', scope: 'color:secondary' }, { value: 'var(--badge-neutral-solid)', scope: 'color:neutral' }, { value: 'var(--badge-affirm-solid)', scope: 'color:affirm' }, { value: 'var(--badge-fulfill-solid)', scope: 'color:fulfill' }, { value: 'var(--badge-risk-solid)', scope: 'color:risk' }, { value: 'var(--badge-threat-solid)', scope: 'color:threat' }, { value: 'var(--badge-loss-solid)', scope: 'color:loss' } ] }, _text: { declarations: [ { value: 'var(--badge-primary-text)', scope: 'host' }, { value: 'var(--badge-secondary-text)', scope: 'color:secondary' }, { value: 'var(--badge-neutral-text)', scope: 'color:neutral' }, { value: 'var(--badge-affirm-text)', scope: 'color:affirm' }, { value: 'var(--badge-fulfill-text)', scope: 'color:fulfill' }, { value: 'var(--badge-risk-text)', scope: 'color:risk' }, { value: 'var(--badge-threat-text)', scope: 'color:threat' }, { value: 'var(--badge-loss-text)', scope: 'color:loss' } ] }, _contrast: { declarations: [ { value: 'var(--badge-primary-contrast)', scope: 'host' }, { value: 'var(--badge-secondary-contrast)', scope: 'color:secondary' }, { value: 'var(--badge-neutral-contrast)', scope: 'color:neutral' }, { value: 'var(--badge-affirm-contrast)', scope: 'color:affirm' }, { value: 'var(--badge-fulfill-contrast)', scope: 'color:fulfill' }, { value: 'var(--badge-risk-contrast)', scope: 'color:risk' }, { value: 'var(--badge-threat-contrast)', scope: 'color:threat' }, { value: 'var(--badge-loss-contrast)', scope: 'color:loss' } ] } }, breadcrumb: { 'gap-xs': 'var(--space-0-5)', 'gap-sm': 'var(--space-1)', 'gap-md': 'var(--space-1-5)', 'gap-lg': 'var(--space-2)', 'font-family': 'var(--font-ui)', 'font-size-xs': 'var(--font-size-xs)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'line-height': 'var(--leading-ui)', color: 'var(--color-content-secondary)', 'link-radius': 'var(--radius-sm)', 'link-color': 'var(--color-content-secondary)', 'link-color-hover': 'var(--color-content-primary)', 'link-color-current': 'var(--color-content-primary)', 'link-font-weight': 'var(--font-weight-medium)', 'link-font-weight-current': 'var(--font-weight-semibold)', 'separator-color': 'var(--color-content-muted)', 'ellipsis-size': 'var(--control-height-xs)', 'ellipsis-radius': 'var(--radius-md)', 'ellipsis-border-width': 'var(--border-width)', 'ellipsis-border': 'transparent', 'ellipsis-border-hover': 'var(--color-border-subtle)', 'ellipsis-bg': 'transparent', 'ellipsis-bg-hover': 'var(--color-surface-raised)', 'ellipsis-color': 'var(--color-content-muted)', 'ellipsis-color-hover': 'var(--color-content-primary)', 'focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)' }, card: { // ── Padding scale ──────────────────────────────────────────────── 'px-xs': 'var(--space-3)', 'px-sm': 'var(--space-4)', 'px-md': 'var(--space-5)', 'px-lg': 'var(--space-6)', 'px-xl': 'var(--space-8)', 'py-xs': 'var(--space-3)', 'py-sm': 'var(--space-4)', 'py-md': 'var(--space-5)', 'py-lg': 'var(--space-6)', 'py-xl': 'var(--space-8)', // ── Gap between header / body / footer slots ───────────────────── 'gap-xs': 'var(--space-2)', 'gap-sm': 'var(--space-3)', 'gap-md': 'var(--space-4)', 'gap-lg': 'var(--space-5)', 'gap-xl': 'var(--space-6)', // ── Typography ──────────────────────────────────────────────────── 'font-family': 'var(--font-ui)', 'line-height': 'var(--leading-ui)', 'title-font-family': 'var(--font-heading)', 'title-font-size-xs': 'var(--font-size-sm)', 'title-font-size-sm': 'var(--font-size-md)', 'title-font-size-md': 'var(--font-size-lg)', 'title-font-size-lg': 'var(--font-size-xl)', 'title-font-size-xl': 'var(--font-size-2xl)', 'title-font-weight': 'var(--font-weight-semibold)', 'title-line-height': 'var(--leading-heading)', 'title-letter-spacing': 'var(--tracking-tight)', 'description-font-family': 'var(--font-ui)', 'description-font-size-xs': 'var(--font-size-xs)', 'description-font-size-sm': 'var(--font-size-sm)', 'description-font-size-md': 'var(--font-size-sm)', 'description-font-size-lg': 'var(--font-size-md)', 'description-font-size-xl': 'var(--font-size-md)', 'description-line-height': 'var(--leading-prose)', 'description-color': 'var(--color-content-secondary)', 'body-font-size-xs': 'var(--font-size-sm)', 'body-font-size-sm': 'var(--font-size-sm)', 'body-font-size-md': 'var(--font-size-md)', 'body-font-size-lg': 'var(--font-size-md)', 'body-font-size-xl': 'var(--font-size-lg)', 'body-line-height': 'var(--leading-prose)', // ── Borders + radii ─────────────────────────────────────────────── 'border-width': 'var(--border-width)', 'radius-sm': 'var(--radius-md)', 'radius-md': 'var(--radius-lg)', 'radius-lg': 'var(--radius-xl)', // ── Inner slot spacing ──────────────────────────────────────────── 'header-gap': 'var(--space-1-5)', 'footer-gap': 'var(--space-3)', 'footer-padding-start': 'var(--space-3)', 'footer-border-color': 'var(--color-border-subtle)', // ── Animations ──────────────────────────────────────────────────── 'emerge-duration': 'var(--duration-slow)', 'emerge-ease': 'var(--ease-out)', 'emerge-distance': '8px', 'hover-lift': '-2px', 'hover-shadow': 'var(--depth-overlay-shadow), var(--depth-overlay-halo)', 'press-scale': '0.985', 'press-duration': '80ms', 'selected-ring-width': 'var(--border-width-medium)', 'disabled-opacity': 'var(--opacity-disabled)', // ── Custom color (set inline by consumer via style) ─────────────── // The Svelte file emits `style="--card-color-custom: ;"` // when the consumer passes a non-canonical CSS color. Declared // here so the recipe-css-contract test sees a declaration. 'color-custom': 'currentColor', 'color-custom-contrast': 'white', // ── Color palette (canonical 8-color × 5 slots) ────────────────── 'primary-solid': 'var(--color-primary-solid)', 'primary-text': 'var(--color-primary-text)', 'primary-contrast': 'var(--color-primary-contrast)', 'secondary-solid': 'var(--color-secondary-solid)', 'secondary-text': 'var(--color-secondary-text)', 'secondary-contrast': 'var(--color-secondary-contrast)', 'neutral-solid': 'var(--color-neutral-solid)', 'neutral-text': 'var(--color-neutral-text)', 'neutral-contrast': 'var(--color-neutral-contrast)', 'affirm-solid': 'var(--color-affirm-solid)', 'affirm-text': 'var(--color-affirm-text)', 'affirm-contrast': 'var(--color-affirm-contrast)', 'fulfill-track': 'var(--color-fulfill-track)', 'fulfill-border': 'var(--color-fulfill-border)', 'fulfill-solid': 'var(--color-fulfill-solid)', 'fulfill-text': 'var(--color-fulfill-text)', 'fulfill-contrast': 'var(--color-fulfill-contrast)', 'risk-solid': 'var(--color-risk-solid)', 'risk-text': 'var(--color-risk-text)', 'risk-contrast': 'var(--color-risk-contrast)', 'threat-solid': 'var(--color-threat-solid)', 'threat-text': 'var(--color-threat-text)', 'threat-contrast': 'var(--color-threat-contrast)', 'loss-track': 'var(--color-loss-track)', 'loss-border': 'var(--color-loss-border)', 'loss-solid': 'var(--color-loss-solid)', 'loss-text': 'var(--color-loss-text)', 'loss-contrast': 'var(--color-loss-contrast)', // Restored after accidental sed-removal during switch migration. 'primary-track': 'var(--color-primary-track)', 'primary-border': 'var(--color-primary-border)', 'secondary-track': 'var(--color-secondary-track)', 'secondary-border': 'var(--color-secondary-border)', 'neutral-track': 'var(--color-neutral-track)', 'neutral-border': 'var(--color-neutral-border)', 'affirm-track': 'var(--color-affirm-track)', 'affirm-border': 'var(--color-affirm-border)', 'risk-track': 'var(--color-risk-track)', 'risk-border': 'var(--color-risk-border)', 'threat-track': 'var(--color-threat-track)', 'threat-border': 'var(--color-threat-border)', // Private palette (TSC v2.1). 8 colors, 5 slots. Default = neutral. _track: { declarations: [ { value: 'var(--card-neutral-track)', scope: 'host' }, { value: 'var(--card-primary-track)', scope: 'color:primary' }, { value: 'var(--card-secondary-track)', scope: 'color:secondary' }, { value: 'var(--card-affirm-track)', scope: 'color:affirm' }, { value: 'var(--card-fulfill-track)', scope: 'color:fulfill' }, { value: 'var(--card-risk-track)', scope: 'color:risk' }, { value: 'var(--card-threat-track)', scope: 'color:threat' }, { value: 'var(--card-loss-track)', scope: 'color:loss' } ] }, _border: { declarations: [ { value: 'var(--card-neutral-border)', scope: 'host' }, { value: 'var(--card-primary-border)', scope: 'color:primary' }, { value: 'var(--card-secondary-border)', scope: 'color:secondary' }, { value: 'var(--card-affirm-border)', scope: 'color:affirm' }, { value: 'var(--card-fulfill-border)', scope: 'color:fulfill' }, { value: 'var(--card-risk-border)', scope: 'color:risk' }, { value: 'var(--card-threat-border)', scope: 'color:threat' }, { value: 'var(--card-loss-border)', scope: 'color:loss' } ] }, _solid: { declarations: [ { value: 'var(--card-neutral-solid)', scope: 'host' }, { value: 'var(--card-primary-solid)', scope: 'color:primary' }, { value: 'var(--card-secondary-solid)', scope: 'color:secondary' }, { value: 'var(--card-affirm-solid)', scope: 'color:affirm' }, { value: 'var(--card-fulfill-solid)', scope: 'color:fulfill' }, { value: 'var(--card-risk-solid)', scope: 'color:risk' }, { value: 'var(--card-threat-solid)', scope: 'color:threat' }, { value: 'var(--card-loss-solid)', scope: 'color:loss' } ] }, _text: { declarations: [ { value: 'var(--card-neutral-text)', scope: 'host' }, { value: 'var(--card-primary-text)', scope: 'color:primary' }, { value: 'var(--card-secondary-text)', scope: 'color:secondary' }, { value: 'var(--card-affirm-text)', scope: 'color:affirm' }, { value: 'var(--card-fulfill-text)', scope: 'color:fulfill' }, { value: 'var(--card-risk-text)', scope: 'color:risk' }, { value: 'var(--card-threat-text)', scope: 'color:threat' }, { value: 'var(--card-loss-text)', scope: 'color:loss' } ] }, _contrast: { declarations: [ { value: 'var(--card-neutral-contrast)', scope: 'host' }, { value: 'var(--card-primary-contrast)', scope: 'color:primary' }, { value: 'var(--card-secondary-contrast)', scope: 'color:secondary' }, { value: 'var(--card-affirm-contrast)', scope: 'color:affirm' }, { value: 'var(--card-fulfill-contrast)', scope: 'color:fulfill' }, { value: 'var(--card-risk-contrast)', scope: 'color:risk' }, { value: 'var(--card-threat-contrast)', scope: 'color:threat' }, { value: 'var(--card-loss-contrast)', scope: 'color:loss' } ] } }, checkbox: { 'size-xs-box-size': '14px', 'size-xs-indicator-size': '8px', 'size-xs-indicator-stroke': '2px', 'size-sm-box-size': '16px', 'size-sm-indicator-size': '10px', 'size-sm-indicator-stroke': '2px', 'size-md-box-size': '18px', 'size-md-indicator-size': '12px', 'size-md-indicator-stroke': '2px', 'size-lg-box-size': '22px', 'size-lg-indicator-size': '14px', 'size-lg-indicator-stroke': '2px', 'size-xl-box-size': '26px', 'size-xl-indicator-size': '16px', 'size-xl-indicator-stroke': '2px', radius: 'var(--radius-sm)', 'border-width': 'var(--border-width)', 'focus-ring-offset': 'var(--focus-ring-offset)', 'focus-ring-width': 'var(--focus-ring-width)', 'focus-ring-color': 'var(--focus-ring-color)', 'focus-ring-surface': 'var(--color-surface-default)', 'focus-ring': '0 0 0 var(--checkbox-focus-ring-offset) var(--checkbox-focus-ring-surface), 0 0 0 calc(var(--checkbox-focus-ring-offset) + var(--checkbox-focus-ring-width)) var(--checkbox-focus-ring-color)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', // Checkmark stroke draw — synced with the box transition (--duration-fast). // Was a hardcoded 220ms, which read as laggy next to the 120ms box fill. 'stroke-duration': 'var(--duration-fast)', 'stroke-ease': 'cubic-bezier(0.4, 0, 0.2, 1)', 'bg-off': 'var(--color-surface-default)', 'bg-off-hover': 'color-mix( in srgb, var(--color-surface-default) 82%, var(--color-surface-overlay) )', 'border-off': 'var(--color-border-default)', 'border-off-hover': 'var(--color-border-strong)', 'bg-disabled': 'color-mix( in srgb, var(--color-surface-overlay) 78%, var(--color-surface-default) )', 'border-disabled': 'color-mix( in srgb, var(--color-border-default) 72%, var(--color-border-subtle) )', 'disabled-opacity': 'var(--opacity-disabled)', 'indicator-color': 'var(--color-content-on-solid)', 'indicator-color-disabled': 'color-mix( in srgb, var(--color-content-on-solid) 82%, var(--color-surface-default) )', 'primary-solid': 'var(--color-primary-solid)', 'primary-solid-hover': 'var(--color-primary-solid-hover)', 'neutral-solid': 'var(--color-neutral-solid)', 'neutral-solid-hover': 'var(--color-neutral-solid-hover)', 'secondary-solid': 'var(--color-secondary-solid)', 'secondary-solid-hover': 'var(--color-secondary-solid-hover)', 'affirm-solid': 'var(--color-affirm-solid)', 'affirm-solid-hover': 'var(--color-affirm-solid-hover)', // Private palette (TSC v2.1 `_` prefix → emits `--_checkbox-palette-*`). // Recipe-internal cascade: host default = primary, plus overrides // for the 3 supported color values. Migrated from manual blocks // in checkbox.css. '_palette-solid': { declarations: [ { value: 'var(--checkbox-primary-solid)', scope: 'host' }, { value: 'var(--checkbox-secondary-solid)', scope: 'color:secondary' }, { value: 'var(--checkbox-neutral-solid)', scope: 'color:neutral' }, { value: 'var(--checkbox-affirm-solid)', scope: 'color:affirm' } ] }, '_palette-solid-hover': { declarations: [ { value: 'var(--checkbox-primary-solid-hover)', scope: 'host' }, { value: 'var(--checkbox-secondary-solid-hover)', scope: 'color:secondary' }, { value: 'var(--checkbox-neutral-solid-hover)', scope: 'color:neutral' }, { value: 'var(--checkbox-affirm-solid-hover)', scope: 'color:affirm' } ] }, '_palette-text': { value: 'var(--checkbox-indicator-color)', scope: 'host' }, 'group-gap': 'var(--space-3)', 'group-label-font-family': 'var(--font-ui)', 'group-label-font-size': 'var(--font-size-sm)', 'group-label-font-weight': 'var(--font-weight-medium)', 'group-label-line-height': 'var(--leading-ui)', 'group-label-color': 'var(--color-content-primary)', 'group-label-color-disabled': 'var(--color-content-secondary)' }, collapsible: { 'trigger-font-family': 'var(--font-ui)', 'trigger-font-size': 'var(--font-size-sm)', 'trigger-font-weight': 'var(--font-weight-medium)', 'trigger-color': 'var(--color-content-primary)', 'trigger-color-hover': 'var(--color-content-primary)', 'trigger-bg-hover': 'var(--color-surface-overlay)', 'trigger-radius': 'var(--radius-sm)', 'trigger-padding': 'var(--space-2) var(--space-3)', 'content-padding': 'var(--space-3)', 'transition-duration': 'var(--duration-normal)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)' }, dialog: { 'trigger-font-size': 'var(--font-size-sm)', 'overlay-bg': 'var(--color-overlay)', 'overlay-opacity': '62%', 'overlay-blur': 'var(--blur-lg)', 'overlay-z': '70', 'content-bg': 'var(--color-surface-overlay)', 'content-color': 'var(--color-content-primary)', 'content-border': 'var(--color-border-default)', 'content-border-width': 'var(--border-width)', 'content-radius': 'var(--radius-xl)', 'content-shadow': 'var(--depth-overlay-shadow), var(--depth-overlay-halo)', 'content-max-height': 'calc(100dvh - var(--space-8))', 'content-max-height-sheet': '85dvh', 'content-width-sm': '420px', 'content-width-md': '560px', 'content-width-lg': '760px', 'content-width-xl': '1024px', 'content-width-inset': 'var(--space-6)', 'content-full-inset': 'var(--space-3)', 'content-full-radius': 'var(--radius-xxl)', 'content-position-inset': 'var(--space-4)', 'content-padding-sm': 'var(--space-4)', 'content-padding-md': 'var(--space-5)', 'content-padding-lg': 'var(--space-6)', 'content-padding-full': 'var(--space-6)', 'stack-gap': 'var(--space-4)', 'header-gap': 'var(--space-3)', 'footer-gap': 'var(--space-3)', 'footer-margin-top': 'var(--space-2)', 'title-font-family': 'var(--font-heading)', 'title-font-size': 'var(--font-size-lg)', 'title-font-weight': 'var(--font-weight-semibold)', 'title-line-height': 'var(--leading-heading)', 'title-color': 'var(--color-content-primary)', 'description-font-family': 'var(--font-ui)', 'description-font-size': 'var(--font-size-sm)', 'description-line-height': 'var(--leading-ui)', 'description-color': 'var(--color-content-secondary)', 'close-size': 'var(--control-height-sm)', 'close-px': 'var(--space-2)', 'close-radius': 'var(--radius-md)', 'close-inset': 'var(--space-3)', 'close-bg': 'transparent', 'close-bg-hover': 'color-mix(in srgb, var(--color-neutral-track) 72%, transparent)', 'close-color': 'var(--color-content-secondary)', 'close-color-hover': 'var(--color-content-primary)', 'close-border': 'transparent', 'close-border-width': 'var(--border-width)', 'close-transition-duration': 'var(--duration-fast)', 'close-transition-ease': 'var(--ease-default)', 'close-focus-ring-offset': '1px', 'close-focus-ring-width': 'var(--focus-ring-width)', 'close-focus-ring-color': 'var(--focus-ring-color)' }, field: { 'gap-xs': 'var(--space-1)', 'gap-sm': 'var(--space-1-5)', 'gap-md': 'var(--space-2)', 'gap-lg': 'var(--space-2-5)', 'gap-xl': 'var(--space-3)', 'font-family': 'var(--font-ui)', 'label-gap': 'var(--space-1)', // Label size is derived in field.css (control font − one step), not a // per-size token — keeps it coherent with the segmented fields' calc. 'label-font-weight': 'var(--font-weight-regular)', 'label-line-height': 'var(--leading-ui)', 'label-color': 'var(--color-content-primary)', 'label-color-invalid': 'var(--color-risk-text)', 'label-color-disabled': 'var(--color-content-disabled)', 'layout-column-gap': 'var(--space-4)', 'required-color': 'var(--color-risk-text)', 'control-height-xs': 'var(--control-height-xs)', 'control-height-sm': 'var(--control-height-sm)', 'control-height-md': 'var(--control-height-md)', 'control-height-lg': 'var(--control-height-lg)', 'control-height-xl': 'var(--control-height-xl)', 'control-px-xs': 'var(--space-2)', 'control-px-sm': 'var(--space-2-5)', 'control-px-md': 'var(--space-3)', 'control-px-lg': 'var(--space-3-5)', 'control-px-xl': 'var(--space-4)', 'control-gap-xs': 'var(--space-1)', 'control-gap-sm': 'var(--space-1-5)', 'control-gap-md': 'var(--space-2)', 'control-gap-lg': 'var(--space-2-5)', 'control-gap-xl': 'var(--space-3)', 'control-font-size-xs': 'var(--font-size-xs)', 'control-font-size-sm': 'var(--font-size-sm)', 'control-font-size-md': 'var(--font-size-md)', 'control-font-size-lg': 'var(--font-size-lg)', 'control-font-size-xl': 'var(--font-size-xl)', 'control-line-height': 'var(--leading-ui)', 'control-radius': 'var(--radius-md)', 'control-border-width': 'var(--border-width)', 'control-border': 'var(--color-border-default)', 'control-border-hover': 'var(--color-border-strong)', 'control-border-focus': 'var(--color-focus-ring)', 'control-border-invalid': 'var(--color-risk-border)', 'control-bg': 'var(--color-surface-default)', 'control-ghost-border': 'transparent', 'control-ghost-bg': 'transparent', 'control-bg-readonly': 'var(--color-surface-muted)', 'control-bg-disabled': 'var(--color-surface-muted)', 'control-color': 'var(--color-content-primary)', 'control-placeholder-color': 'var(--color-content-muted)', 'control-focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'affix-color': 'var(--color-content-secondary)', 'message-line-height': 'var(--leading-ui)', 'helper-color': 'var(--color-content-secondary)', 'error-color': 'var(--color-risk-text)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)' }, form: { 'gap-xs': 'var(--space-3)', 'gap-sm': 'var(--space-4)', 'gap-md': 'var(--space-5)', 'gap-lg': 'var(--space-6)', 'gap-xl': 'var(--space-7)', 'font-family': 'var(--font-ui)', color: 'var(--color-content-primary)', radius: 'var(--radius-lg)', 'border-width': 'var(--border-width)', 'panel-padding': 'var(--space-5)', 'panel-border': 'var(--color-border-default)', 'panel-bg': 'var(--color-surface-raised)', 'panel-shadow': 'var(--depth-raised-shadow), var(--depth-raised-halo)', 'grid-min': '18rem', 'grid-column-gap': 'var(--space-5)', 'action-height-xs': 'var(--control-height-xs)', 'action-height-sm': 'var(--control-height-sm)', 'action-height-md': 'var(--control-height-md)', 'action-height-lg': 'var(--control-height-lg)', 'action-height-xl': 'var(--control-height-xl)', 'action-px-xs': 'var(--space-2-5)', 'action-px-sm': 'var(--space-3)', 'action-px-md': 'var(--space-3-5)', 'action-px-lg': 'var(--space-4)', 'action-px-xl': 'var(--space-4-5)', 'action-font-size-xs': 'var(--font-size-xs)', 'action-font-size-sm': 'var(--font-size-xs)', 'action-font-size-md': 'var(--font-size-sm)', 'action-font-size-lg': 'var(--font-size-sm)', 'action-font-size-xl': 'var(--font-size-md)', 'action-font-weight': 'var(--font-weight-medium)', 'action-line-height': 'var(--leading-ui)', 'action-gap': 'var(--space-2)', 'action-radius': 'var(--radius-md)', 'action-border-width': 'var(--border-width)', 'error-summary-padding': 'var(--space-3)', 'error-summary-border-width': 'var(--border-width)', 'error-summary-radius': 'var(--radius-md)', 'error-summary-font-size': 'var(--font-size-sm)', 'error-summary-line-height': 'var(--leading-ui)', 'error-summary-list-indent': 'var(--space-4)', 'link-underline-offset': '0.18em', 'auto-fields-gap': 'var(--space-3)', 'auto-fields-array-padding': 'var(--space-3)', 'auto-fields-border-width': 'var(--border-width)', 'auto-fields-radius': 'var(--radius-md)', 'auto-fields-item-gap': 'var(--space-2)', 'auto-fields-item-padding': 'var(--space-3)', 'widget-px': 'var(--space-3)', 'widget-radius': 'var(--radius-md)', 'widget-border-width': 'var(--border-width)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)' }, drawer: { 'overlay-bg': 'var(--color-overlay)', 'overlay-blur': 'var(--blur-lg)', 'overlay-opacity': '62%', 'overlay-z': '72', 'inline-z': '64', 'handle-bg': 'var(--color-neutral-track)', 'handle-bg-active': 'var(--color-content-secondary)', 'handle-radius': 'var(--radius-full)', 'handle-length': '36px', 'handle-thickness': '4px', 'handle-active-scale': '1.18', 'handle-transition-duration': 'var(--duration-fast)', 'handle-transition-ease': 'var(--ease-out)', 'content-bg': 'var(--color-surface-overlay)', 'content-color': 'var(--color-content-primary)', 'content-border': 'var(--color-border-default)', 'content-border-width': 'var(--border-width)', 'content-radius': 'var(--radius-xl)', 'content-shadow': 'var(--depth-overlay-shadow), var(--depth-overlay-halo)', 'content-shadow-dragging': 'var(--shadow-overlay-strong, var(--depth-overlay-shadow)), var(--depth-overlay-halo)', 'content-ring-dragging-width': 'var(--border-width-medium)', 'content-ring-dragging-color': 'color-mix( in srgb, var(--color-content-secondary) 32%, transparent )', 'content-ring-dragging-offset': '2px', 'content-inset': 'var(--space-3)', 'content-width-sm': '360px', 'content-width-md': '440px', 'content-width-lg': '560px', 'content-height-sm': '260px', 'content-height-md': '360px', 'content-height-lg': '480px', 'content-padding-sm': 'var(--space-4)', 'content-padding-md': 'var(--space-5)', 'content-padding-lg': 'var(--space-6)', 'content-padding-full': 'var(--space-6)', 'stack-gap': 'var(--space-4)', 'header-gap': 'var(--space-3)', 'footer-gap': 'var(--space-3)', 'footer-margin-top': 'var(--space-2)', 'title-font-family': 'var(--font-heading)', 'title-font-size': 'var(--font-size-lg)', 'title-font-weight': 'var(--font-weight-semibold)', 'title-line-height': 'var(--leading-heading)', 'title-color': 'var(--color-content-primary)', 'description-font-family': 'var(--font-ui)', 'description-font-size': 'var(--font-size-sm)', 'description-line-height': 'var(--leading-ui)', 'description-color': 'var(--color-content-secondary)', 'close-size': 'var(--control-height-sm)', 'close-px': 'var(--space-2)', 'close-radius': 'var(--radius-md)', 'close-bg': 'transparent', 'close-bg-hover': 'color-mix(in srgb, var(--color-neutral-track) 72%, transparent)', 'close-color': 'var(--color-content-secondary)', 'close-color-hover': 'var(--color-content-primary)', 'close-border': 'transparent', 'close-border-width': 'var(--border-width)', 'close-transition-duration': 'var(--duration-fast)', 'close-transition-ease': 'var(--ease-default)', 'close-focus-ring-offset': '1px', 'close-focus-ring-width': 'var(--focus-ring-width)', 'close-focus-ring-color': 'var(--focus-ring-color)', 'close-disabled-opacity': '0.5' }, icon: { size: 'var(--icon-size-md)', 'stroke-width': 'var(--icon-stroke-width-md)' }, image: { // ── Size presets (square boxes) ────────────────────────────────── 'size-xs': '64px', 'size-sm': '96px', 'size-md': '160px', 'size-lg': '240px', 'size-xl': '360px', // ── Radius scale ────────────────────────────────────────────────── 'radius-none': '0', 'radius-sm': 'var(--radius-sm)', 'radius-md': 'var(--radius-md)', 'radius-lg': 'var(--radius-lg)', 'radius-full': 'var(--radius-full)', // ── Fade-in transition for the inner ─────────────────────── 'fade-duration': 'var(--duration-normal)', 'fade-ease': 'var(--ease-out)', // ── Skeleton placeholder shimmer ────────────────────────────────── 'placeholder-base': 'var(--color-surface-raised)', 'shimmer-duration': '1.8s', // ── Custom placeholder color (set inline by Svelte file) ───────── 'placeholder-color-custom': 'var(--color-neutral-track)', // ── Fallback typography (for text-only fallback content) ───────── 'font-family': 'var(--font-ui)', 'fallback-color': 'var(--color-content-secondary)', 'fallback-font-size': 'var(--font-size-sm)', 'fallback-line-height': 'var(--leading-ui)', // ── Error state ────────────────────────────────────────────────── 'error-bg': 'var(--color-surface-raised)', 'error-color': 'var(--color-content-muted)', 'error-font-size': 'var(--font-size-sm)', 'error-line-height': 'var(--leading-ui)' }, meter: { 'height-xs': '2px', 'height-sm': '4px', 'height-md': '6px', 'height-lg': '8px', 'height-xl': '12px', 'radius-xs': 'var(--radius-full)', 'radius-sm': 'var(--radius-full)', 'radius-md': 'var(--radius-full)', 'radius-lg': 'var(--radius-full)', 'radius-xl': 'var(--radius-full)', 'ring-size-xs': '2rem', 'ring-size-sm': '2.5rem', 'ring-size-md': '3rem', 'ring-size-lg': '3.5rem', 'ring-size-xl': '4rem', 'ring-thickness-xs': '3px', 'ring-thickness-sm': '4px', 'ring-thickness-md': '6px', 'ring-thickness-lg': '8px', 'ring-thickness-xl': '10px', 'track-bg': 'var(--color-neutral-track)', 'ring-track-bg': 'color-mix(in srgb, var(--color-content-primary) 12%, var(--color-surface-default))', 'ring-center-bg': 'var(--color-surface-default)', 'indicator-bg-below': 'var(--color-risk-solid)', 'indicator-bg-optimum': 'var(--color-fulfill-solid)', 'indicator-bg-above': 'var(--color-threat-solid)', 'transition-duration': 'var(--duration-normal)', 'transition-ease': 'var(--ease-default)' }, // spin-field — shared visual for the stepper-field family (number-field + // css-field). Both reuse these tokens via structural identity (`data-spin- // field*`) and the shared `spin-field.css`. A theme tints per component by // scoping `[data-number-field] { --spin-field-… }`. See THEMING §34. 'spin-field': { 'height-xs': 'var(--control-height-xs)', 'height-sm': 'var(--control-height-sm)', 'height-md': 'var(--control-height-md)', 'height-lg': 'var(--control-height-lg)', 'height-xl': 'var(--control-height-xl)', 'px-xs': 'var(--space-2)', 'px-sm': 'var(--space-2-5)', 'px-md': 'var(--space-3)', 'px-lg': 'var(--space-3-5)', 'px-xl': 'var(--space-4)', 'gap-xs': 'var(--space-0-5)', 'gap-sm': 'var(--space-1)', 'gap-md': 'var(--space-1-5)', 'gap-lg': 'var(--space-2)', 'gap-xl': 'var(--space-2-5)', 'font-family': 'var(--font-ui)', 'font-size-xs': 'var(--font-size-xs)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'font-size-xl': 'var(--font-size-xl)', 'line-height': 'var(--leading-ui)', radius: 'var(--radius-md)', 'border-width': 'var(--border-width)', border: 'var(--color-border-default)', 'border-focus': 'var(--color-focus-ring)', 'border-invalid': 'var(--color-risk-border)', bg: 'var(--color-surface-default)', color: 'var(--color-content-primary)', 'focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', // Steppers are square segments flush to the field edge (the field clips // their outer corners), separated from the input by a divider on the // inner side. 'control-radius': '0', 'control-border-width': 'var(--border-width)', 'control-border': 'transparent', 'control-divider': 'var(--color-border-default)', 'control-border-hover': 'var(--color-border-strong)', 'control-border-active': 'var(--color-primary-border)', 'control-bg': 'transparent', // Higher-contrast hover/focus fill than the field surface. 'control-bg-hover': 'var(--color-neutral-hover)', 'control-bg-focus': 'var(--color-neutral-hover)', 'control-bg-active': 'var(--color-primary-track)', 'control-color': 'var(--color-content-secondary)', 'control-color-hover': 'var(--color-content-primary)', 'control-color-active': 'var(--color-primary-text)', // Default stepper glyphs — themeable, decorative (the buttons carry an // aria-label). Rendered via `:empty::before`, so passing children to a // trigger overrides them. Split uses +/−; the stacked column uses up/down // triangles. A theme retints/reshapes by overriding any of the four. 'control-increment-glyph': "'+'", 'control-decrement-glyph': "'\\2212'", 'control-increment-glyph-stacked': "'\\25B2'", 'control-decrement-glyph-stacked': "'\\25BC'", 'control-focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'control-disabled-opacity': '0.48', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)' }, 'float-panel': { bg: 'var(--color-surface-overlay)', border: 'var(--color-border-default)', 'border-width': 'var(--border-width)', radius: 'var(--radius-lg)', shadow: 'var(--shadow-4)', 'shadow-topmost': 'var(--shadow-5)', // Elevation worn WHILE grabbed (drag/resize): the panel LIFTS to the // theme's highest elevation. Applied on pointerdown so the lift transition // finishes before the move; the shadow is then static during the drag, so // the GPU layer just moves (no per-frame shadow repaint). See float-panel.css. 'shadow-active': 'var(--shadow-6)', color: 'var(--color-content-primary)', 'font-family': 'var(--font-ui)', 'font-size': 'var(--font-size-sm)', 'line-height': 'var(--leading-ui)', 'header-bg': 'var(--color-surface-raised)', 'header-px': 'var(--space-3)', 'header-py': 'var(--space-2)', 'header-gap': 'var(--space-2)', 'controls-gap': 'var(--space-1)', 'title-font-size': 'var(--font-size-sm)', 'title-font-weight': 'var(--font-weight-semibold)', 'title-color': 'var(--color-content-primary)', 'body-px': 'var(--space-3)', 'body-py': 'var(--space-3)', 'resize-size': 'var(--space-3-5)', 'resize-edge': 'var(--space-1-5)', // Header icon-button (close / action / stage-trigger) hit target, and the // se-corner resize grip — sized for comfort, not the tiny resize-handle. 'button-size': 'var(--space-7)', 'grip-size': 'var(--space-5)', accent: 'var(--color-neutral-border)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)' }, 'image-adjustments': { // Vertical rhythm: gap between adjustment rows, and within a row // (label/value line → slider). gap: 'var(--space-3)', 'row-gap': 'var(--space-1-5)', 'label-color': 'var(--color-content-secondary)', 'label-font-size': 'var(--font-size-sm)', 'label-font-weight': 'var(--font-weight-medium)', // Read-out: tabular numerals so the value doesn't jitter while dragging. 'value-color': 'var(--color-content-tertiary)', 'value-font-size': 'var(--font-size-xs)', 'value-font-family': 'var(--font-mono)', 'reset-gap': 'var(--space-2)', 'reset-color': 'var(--color-content-secondary)', 'reset-font-size': 'var(--font-size-xs)', // The `hue` row paints its slider track as a hue wheel so the control // reads as a hue picker. A literal rainbow (the hues ARE the value) — kept // as a token so it's themeable and stays out of the component CSS. 'hue-track': 'linear-gradient(to right, hsl(0 85% 60%), hsl(60 85% 60%), hsl(120 85% 60%), hsl(180 85% 60%), hsl(240 85% 60%), hsl(300 85% 60%), hsl(360 85% 60%))' }, 'image-picker': { // Vertical stack: preview → adjustments. gap: 'var(--space-3)', // Preview box (ready state). The composed fills it. 'preview-radius': 'var(--radius-lg)', 'preview-bg': 'var(--color-surface-muted)', 'preview-border': 'var(--color-border-default)', 'preview-aspect': '4 / 3', // Toolbar floats over the preview's top-right corner. 'toolbar-gap': 'var(--space-1-5)', 'toolbar-inset': 'var(--space-2)', // Icon buttons (rotate / remove). 'button-size': 'var(--space-8)', 'button-bg': 'color-mix(in srgb, var(--color-surface-default) 88%, transparent)', 'button-fg': 'var(--color-content-primary)', 'button-border': 'var(--color-border-default)', 'button-radius': 'var(--radius-md)', 'button-font-size': 'var(--font-size-md)' }, cropper: { 'viewport-bg': 'var(--color-surface-muted)', 'viewport-radius': 'var(--radius-lg)', // The darken-outside mask + the thirds grid carry literal rgba/rgb (an // overlay tint, not a theme color) — kept as tokens so they stay out of // the component CSS (raw-color contract) and remain themeable. 'mask-bg': 'rgb(0 0 0 / 0.55)', 'grid-line': 'rgb(255 255 255 / 0.4)', 'selection-border': 'var(--color-surface-default)', 'selection-border-width': 'var(--border-width)', 'handle-size': 'var(--space-3-5)', 'handle-bg': 'var(--color-surface-default)', 'handle-border': 'var(--color-primary-solid)', 'handle-border-width': 'var(--border-width)', 'zoom-gap': 'var(--space-2)', 'zoom-btn-size': 'var(--space-7)', 'zoom-btn-bg': 'var(--color-surface-muted)', 'zoom-btn-fg': 'var(--color-content-primary)', 'zoom-btn-border': 'var(--color-border-default)' }, 'date-field': { 'stack-gap': 'var(--space-1-5)', 'height-xs': 'var(--control-height-xs)', 'height-sm': 'var(--control-height-sm)', 'height-md': 'var(--control-height-md)', 'height-lg': 'var(--control-height-lg)', 'height-xl': 'var(--control-height-xl)', 'px-xs': 'var(--space-2)', 'px-sm': 'var(--space-2-5)', 'px-md': 'var(--space-3)', 'px-lg': 'var(--space-3-5)', 'px-xl': 'var(--space-4)', 'gap-xs': 'var(--space-0-5)', 'gap-sm': 'var(--space-0-5)', 'gap-md': 'var(--space-1)', 'gap-lg': 'var(--space-1-5)', 'gap-xl': 'var(--space-2)', 'segment-px-xs': 'var(--space-0-5)', 'segment-px-sm': 'var(--space-0-5)', 'segment-px-md': 'var(--space-1)', 'segment-px-lg': 'var(--space-1-5)', 'segment-px-xl': 'var(--space-2)', 'font-family': 'var(--font-ui)', 'font-size-xs': 'var(--font-size-xs)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'font-size-xl': 'var(--font-size-xl)', 'line-height': 'var(--leading-ui)', radius: 'var(--radius-md)', 'border-width': 'var(--border-width)', border: 'var(--color-border-default)', 'border-invalid': 'var(--color-risk-border)', bg: 'var(--color-surface-default)', color: 'var(--color-content-primary)', 'label-color': 'var(--color-content-secondary)', 'label-font-weight': 'var(--font-weight-regular)', 'placeholder-color': 'var(--color-content-muted)', 'literal-color': 'var(--color-content-muted)', 'focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'segment-min-width': '1.5ch', 'segment-height': 'calc(var(--_date-field-height) - var(--space-2))', 'segment-radius': 'var(--radius-sm)', 'segment-color': 'var(--color-content-primary)', 'segment-invalid-color': 'var(--color-risk-text)', 'segment-readonly-bg': 'var(--color-surface-overlay)', 'segment-readonly-color': 'var(--color-content-secondary)', 'segment-readonly-decoration': 'underline dotted var(--color-content-muted)', 'segment-hover-bg': 'color-mix(in srgb, var(--color-content-primary) 6%, transparent)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)' }, 'time-field': { 'stack-gap': 'var(--space-1-5)', 'height-xs': 'var(--control-height-xs)', 'height-sm': 'var(--control-height-sm)', 'height-md': 'var(--control-height-md)', 'height-lg': 'var(--control-height-lg)', 'height-xl': 'var(--control-height-xl)', 'px-xs': 'var(--space-2)', 'px-sm': 'var(--space-2-5)', 'px-md': 'var(--space-3)', 'px-lg': 'var(--space-3-5)', 'px-xl': 'var(--space-4)', 'gap-xs': 'var(--space-0-5)', 'gap-sm': 'var(--space-0-5)', 'gap-md': 'var(--space-1)', 'gap-lg': 'var(--space-1-5)', 'gap-xl': 'var(--space-2)', 'segment-px-xs': 'var(--space-0-5)', 'segment-px-sm': 'var(--space-0-5)', 'segment-px-md': 'var(--space-1)', 'segment-px-lg': 'var(--space-1-5)', 'segment-px-xl': 'var(--space-2)', 'font-family': 'var(--font-ui)', 'font-size-xs': 'var(--font-size-xs)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'font-size-xl': 'var(--font-size-xl)', 'line-height': 'var(--leading-ui)', radius: 'var(--radius-md)', 'border-width': 'var(--border-width)', border: 'var(--color-border-default)', 'border-invalid': 'var(--color-risk-border)', bg: 'var(--color-surface-default)', color: 'var(--color-content-primary)', 'label-color': 'var(--color-content-secondary)', 'label-font-weight': 'var(--font-weight-regular)', 'placeholder-color': 'var(--color-content-muted)', 'literal-color': 'var(--color-content-muted)', 'focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'segment-min-width': '1.5ch', 'segment-height': 'calc(var(--_time-field-height) - var(--space-2))', 'segment-radius': 'var(--radius-sm)', 'segment-color': 'var(--color-content-primary)', 'segment-invalid-color': 'var(--color-risk-text)', 'segment-readonly-bg': 'var(--color-surface-overlay)', 'segment-readonly-color': 'var(--color-content-secondary)', 'segment-readonly-decoration': 'underline dotted var(--color-content-muted)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)' }, 'color-field': { 'stack-gap': 'var(--space-1-5)', 'height-xs': 'var(--control-height-xs)', 'height-sm': 'var(--control-height-sm)', 'height-md': 'var(--control-height-md)', 'height-lg': 'var(--control-height-lg)', 'height-xl': 'var(--control-height-xl)', 'px-xs': 'var(--space-2)', 'px-sm': 'var(--space-2-5)', 'px-md': 'var(--space-3)', 'px-lg': 'var(--space-3-5)', 'px-xl': 'var(--space-4)', 'gap-xs': 'var(--space-0-5)', 'gap-sm': 'var(--space-0-5)', 'gap-md': 'var(--space-1)', 'gap-lg': 'var(--space-1-5)', 'gap-xl': 'var(--space-2)', 'segment-px-xs': 'var(--space-0-5)', 'segment-px-sm': 'var(--space-0-5)', 'segment-px-md': 'var(--space-1)', 'segment-px-lg': 'var(--space-1-5)', 'segment-px-xl': 'var(--space-2)', 'font-family': 'var(--font-ui)', 'font-size-xs': 'var(--font-size-xs)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'font-size-xl': 'var(--font-size-xl)', 'line-height': 'var(--leading-ui)', radius: 'var(--radius-md)', 'border-width': 'var(--border-width)', border: 'var(--color-border-default)', 'border-invalid': 'var(--color-risk-border)', bg: 'var(--color-surface-default)', color: 'var(--color-content-primary)', 'label-color': 'var(--color-content-secondary)', 'label-font-weight': 'var(--font-weight-regular)', 'placeholder-color': 'var(--color-content-muted)', 'literal-color': 'var(--color-content-muted)', 'focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'segment-min-width': '1.5ch', 'segment-height': 'calc(var(--_color-field-height) - var(--space-2))', 'segment-radius': 'var(--radius-sm)', 'segment-color': 'var(--color-content-primary)', 'segment-invalid-color': 'var(--color-risk-text)', 'segment-readonly-bg': 'var(--color-surface-overlay)', 'segment-readonly-color': 'var(--color-content-secondary)', 'segment-readonly-decoration': 'underline dotted var(--color-content-muted)', 'segment-focus-shadow': 'inset 0 0 0 var(--border-width) var(--_color-field-accent-border)', 'swatch-size-xs': 'calc(var(--control-height-xs) - var(--space-2))', 'swatch-size-sm': 'calc(var(--control-height-sm) - var(--space-2))', 'swatch-size-md': 'calc(var(--control-height-md) - var(--space-2))', 'swatch-size-lg': 'calc(var(--control-height-lg) - var(--space-2))', 'swatch-size-xl': 'calc(var(--control-height-xl) - var(--space-2))', 'format-select-color': 'var(--color-content-secondary)', 'format-select-bg': 'transparent', 'format-select-radius': 'var(--radius-sm)', 'format-select-px': 'var(--space-1)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)' }, 'color-picker': { // Popover content shell 'content-gap': 'var(--space-3)', 'content-padding-sm': 'var(--space-3)', 'content-padding-md': 'var(--space-3-5)', 'content-padding-lg': 'var(--space-4)', 'content-width-sm': '17rem', 'content-width-md': '19.5rem', 'content-width-lg': '22rem', // Trigger button (compact field-shaped pill with a swatch dot) 'trigger-height-sm': 'var(--control-height-sm)', 'trigger-height-md': 'var(--control-height-md)', 'trigger-height-lg': 'var(--control-height-lg)', 'trigger-px-sm': 'var(--space-2)', 'trigger-px-md': 'var(--space-2-5)', 'trigger-px-lg': 'var(--space-3)', 'trigger-gap': 'var(--space-2)', 'trigger-radius': 'var(--radius-md)', 'trigger-border-width': 'var(--border-width)', 'trigger-border': 'var(--color-border-default)', 'trigger-bg': 'var(--color-surface-default)', 'trigger-color': 'var(--color-content-primary)', 'trigger-hover-bg': 'var(--color-surface-overlay)', 'trigger-hover-border': 'var(--color-border-strong)', 'trigger-swatch-size-sm': 'calc(var(--control-height-sm) - var(--space-2))', 'trigger-swatch-size-md': 'calc(var(--control-height-md) - var(--space-2))', 'trigger-swatch-size-lg': 'calc(var(--control-height-lg) - var(--space-2))', 'trigger-swatch-radius': 'var(--radius-full)', 'trigger-swatch-border': 'var(--color-border-subtle)', 'trigger-focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', // 2D area 'area-height': '11rem', 'area-radius': 'var(--radius-md)', 'area-border-width': 'var(--border-width)', 'area-border': 'var(--color-border-subtle)', 'area-thumb-size': '16px', 'area-thumb-radius': 'var(--radius-full)', 'area-thumb-border-width': 'var(--border-width-medium)', 'area-thumb-border': 'var(--color-surface-default)', 'area-thumb-shadow': '0 0 0 1px color-mix(in srgb, var(--color-neutral-contrast) 45%, transparent), 0 1px 2px color-mix(in srgb, var(--color-neutral-contrast) 20%, transparent)', // Channel sliders consume the generic `--slider-*` recipe tokens. // Only the picker-specific decoration (gradient on track) lives // in the picker CSS; sizes, shadows and radii come from the // slider recipe so they stay in lockstep with the standalone // Slider and the time-picker sliders. // Transparency checker (alpha background) 'transparency-cell': 'var(--color-content-muted)', 'transparency-cell-alt': 'var(--color-surface-default)', // Swatches 'swatch-size-sm': '1.25rem', 'swatch-size-md': '1.5rem', 'swatch-size-lg': '1.75rem', 'swatch-radius': 'var(--radius-sm)', 'swatch-border': 'var(--color-border-subtle)', 'swatch-checked-ring': 'var(--color-primary-solid)', 'swatch-gap': 'var(--space-1-5)', // Eye-dropper button 'eye-dropper-size': 'var(--control-height-sm)', 'eye-dropper-radius': 'var(--radius-md)', 'eye-dropper-bg': 'transparent', 'eye-dropper-color': 'var(--color-content-secondary)', 'eye-dropper-hover-bg': 'var(--color-surface-overlay)', 'eye-dropper-hover-color': 'var(--color-content-primary)', // Hue spectrum — drives the hue ring + saturation overlay. These // sit in a sidecar file (color-picker-spectrum.css) so the raw // hsl literals stay out of the main recipe; declaring them here // keeps the recipe contract whole. 'hue-0': 'hsl(0, 100%, 50%)', 'hue-60': 'hsl(60, 100%, 50%)', 'hue-120': 'hsl(120, 100%, 50%)', 'hue-180': 'hsl(180, 100%, 50%)', 'hue-240': 'hsl(240, 100%, 50%)', 'hue-300': 'hsl(300, 100%, 50%)', 'hue-360': 'hsl(360, 100%, 50%)', 'saturation-floor': 'hsl(0, 0%, 50%)', // Misc 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)' }, button: { // Size tokens 'height-xs': 'var(--control-height-xs)', 'height-sm': 'var(--control-height-sm)', 'height-md': 'var(--control-height-md)', 'height-lg': 'var(--control-height-lg)', 'height-xl': 'var(--control-height-xl)', 'px-xs': 'var(--space-2)', 'px-sm': 'var(--space-3)', 'px-md': 'var(--space-4)', 'px-lg': 'var(--space-5)', 'px-xl': 'var(--space-6)', 'gap-xs': 'var(--space-1)', 'gap-sm': 'var(--space-1-5)', 'gap-md': 'var(--space-2)', 'gap-lg': 'var(--space-2-5)', 'gap-xl': 'var(--space-3)', 'font-family': 'var(--font-ui)', 'line-height': 'var(--leading-ui)', 'letter-spacing': 'var(--tracking-normal)', 'font-size-xs': 'var(--font-size-xs)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'font-size-xl': 'var(--font-size-xl)', 'font-weight-xs': 'var(--font-weight-medium)', 'font-weight-sm': 'var(--font-weight-medium)', 'font-weight-md': 'var(--font-weight-medium)', 'font-weight-lg': 'var(--font-weight-medium)', 'font-weight-xl': 'var(--font-weight-medium)', // Icon follows the button's font-size 1:1 (canonical icon↔type correlation): // the font now scales 1:1 with the size (no longer compact), so the icon // matches at the same step. The parallel icon scale preserves icon ≈ font+2 // in the body sizes (md: font 16 → icon 18). Density-scaled; never hardcoded px. 'icon-size-xs': 'var(--icon-size-xs)', 'icon-size-sm': 'var(--icon-size-sm)', 'icon-size-md': 'var(--icon-size-md)', 'icon-size-lg': 'var(--icon-size-lg)', 'icon-size-xl': 'var(--icon-size-xl)', 'radius-sm': 'var(--radius-sm)', 'radius-md': 'var(--radius-md)', 'radius-lg': 'var(--radius-lg)', 'radius-xl': 'var(--radius-xl)', 'border-width': 'var(--border-width)', shadow: 'none', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'spinner-duration': '720ms', 'disabled-opacity': 'var(--opacity-disabled)', // Per-color palettes — 7 slots per color, uniform across all 8: track / // element / border / solid / solid-hover / text / contrast. soft + surface // + outline variants read track/border, so every color must define them // (was only fulfill/loss — the others rendered with no bg/border). 'primary-track': 'var(--color-primary-track)', 'primary-element': 'var(--color-primary-element)', 'primary-border': 'var(--color-primary-border)', 'primary-solid': 'var(--color-primary-solid)', 'primary-solid-hover': 'var(--color-primary-solid-hover)', 'primary-text': 'var(--color-primary-text)', 'primary-contrast': 'var(--color-primary-contrast)', 'secondary-track': 'var(--color-secondary-track)', 'secondary-element': 'var(--color-secondary-element)', 'secondary-border': 'var(--color-secondary-border)', 'secondary-solid': 'var(--color-secondary-solid)', 'secondary-solid-hover': 'var(--color-secondary-solid-hover)', 'secondary-text': 'var(--color-secondary-text)', 'secondary-contrast': 'var(--color-secondary-contrast)', 'neutral-track': 'var(--color-neutral-track)', 'neutral-element': 'var(--color-neutral-element)', 'neutral-border': 'var(--color-neutral-border)', 'neutral-solid': 'var(--color-neutral-solid)', 'neutral-solid-hover': 'var(--color-neutral-solid-hover)', 'neutral-text': 'var(--color-neutral-text)', 'neutral-contrast': 'var(--color-neutral-contrast)', 'affirm-track': 'var(--color-affirm-track)', 'affirm-element': 'var(--color-affirm-element)', 'affirm-border': 'var(--color-affirm-border)', 'affirm-solid': 'var(--color-affirm-solid)', 'affirm-solid-hover': 'var(--color-affirm-solid-hover)', 'affirm-text': 'var(--color-affirm-text)', 'affirm-contrast': 'var(--color-affirm-contrast)', 'fulfill-track': 'var(--color-fulfill-track)', 'fulfill-element': 'var(--color-fulfill-element)', 'fulfill-border': 'var(--color-fulfill-border)', 'fulfill-solid': 'var(--color-fulfill-solid)', 'fulfill-solid-hover': 'var(--color-fulfill-solid-hover)', 'fulfill-text': 'var(--color-fulfill-text)', 'fulfill-contrast': 'var(--color-fulfill-contrast)', 'risk-track': 'var(--color-risk-track)', 'risk-element': 'var(--color-risk-element)', 'risk-border': 'var(--color-risk-border)', 'risk-solid': 'var(--color-risk-solid)', 'risk-solid-hover': 'var(--color-risk-solid-hover)', 'risk-text': 'var(--color-risk-text)', 'risk-contrast': 'var(--color-risk-contrast)', 'threat-track': 'var(--color-threat-track)', 'threat-element': 'var(--color-threat-element)', 'threat-border': 'var(--color-threat-border)', 'threat-solid': 'var(--color-threat-solid)', 'threat-solid-hover': 'var(--color-threat-solid-hover)', 'threat-text': 'var(--color-threat-text)', 'threat-contrast': 'var(--color-threat-contrast)', 'loss-track': 'var(--color-loss-track)', 'loss-element': 'var(--color-loss-element)', 'loss-border': 'var(--color-loss-border)', 'loss-solid': 'var(--color-loss-solid)', 'loss-solid-hover': 'var(--color-loss-solid-hover)', 'loss-text': 'var(--color-loss-text)', 'loss-contrast': 'var(--color-loss-contrast)', // Active palette — 8 custom properties, each declared with 8 // declarations (host default = primary, plus per-color overrides // for the 7 other supported values). Single source of truth via // TSC v2 `declarations[]`. Replaces the per-color blocks that // used to live in `button.css`. 'palette-track': { declarations: [ { value: 'var(--button-primary-track)', scope: 'host' }, { value: 'var(--button-secondary-track)', scope: 'color:secondary' }, { value: 'var(--button-neutral-track)', scope: 'color:neutral' }, { value: 'var(--button-affirm-track)', scope: 'color:affirm' }, { value: 'var(--button-fulfill-track)', scope: 'color:fulfill' }, { value: 'var(--button-risk-track)', scope: 'color:risk' }, { value: 'var(--button-threat-track)', scope: 'color:threat' }, { value: 'var(--button-loss-track)', scope: 'color:loss' } ] }, 'palette-element': { declarations: [ { value: 'var(--button-primary-element)', scope: 'host' }, { value: 'var(--button-secondary-element)', scope: 'color:secondary' }, { value: 'var(--button-neutral-element)', scope: 'color:neutral' }, { value: 'var(--button-affirm-element)', scope: 'color:affirm' }, { value: 'var(--button-fulfill-element)', scope: 'color:fulfill' }, { value: 'var(--button-risk-element)', scope: 'color:risk' }, { value: 'var(--button-threat-element)', scope: 'color:threat' }, { value: 'var(--button-loss-element)', scope: 'color:loss' } ] }, 'palette-border': { declarations: [ { value: 'var(--button-primary-border)', scope: 'host' }, { value: 'var(--button-secondary-border)', scope: 'color:secondary' }, { value: 'var(--button-neutral-border)', scope: 'color:neutral' }, { value: 'var(--button-affirm-border)', scope: 'color:affirm' }, { value: 'var(--button-fulfill-border)', scope: 'color:fulfill' }, { value: 'var(--button-risk-border)', scope: 'color:risk' }, { value: 'var(--button-threat-border)', scope: 'color:threat' }, { value: 'var(--button-loss-border)', scope: 'color:loss' } ] }, 'palette-solid': { declarations: [ { value: 'var(--button-primary-solid)', scope: 'host' }, { value: 'var(--button-secondary-solid)', scope: 'color:secondary' }, { value: 'var(--button-neutral-solid)', scope: 'color:neutral' }, { value: 'var(--button-affirm-solid)', scope: 'color:affirm' }, { value: 'var(--button-fulfill-solid)', scope: 'color:fulfill' }, { value: 'var(--button-risk-solid)', scope: 'color:risk' }, { value: 'var(--button-threat-solid)', scope: 'color:threat' }, { value: 'var(--button-loss-solid)', scope: 'color:loss' } ] }, 'palette-solid-hover': { declarations: [ { value: 'var(--button-primary-solid-hover)', scope: 'host' }, { value: 'var(--button-secondary-solid-hover)', scope: 'color:secondary' }, { value: 'var(--button-neutral-solid-hover)', scope: 'color:neutral' }, { value: 'var(--button-affirm-solid-hover)', scope: 'color:affirm' }, { value: 'var(--button-fulfill-solid-hover)', scope: 'color:fulfill' }, { value: 'var(--button-risk-solid-hover)', scope: 'color:risk' }, { value: 'var(--button-threat-solid-hover)', scope: 'color:threat' }, { value: 'var(--button-loss-solid-hover)', scope: 'color:loss' } ] }, 'palette-text': { declarations: [ { value: 'var(--button-primary-text)', scope: 'host' }, { value: 'var(--button-secondary-text)', scope: 'color:secondary' }, { value: 'var(--button-neutral-text)', scope: 'color:neutral' }, { value: 'var(--button-affirm-text)', scope: 'color:affirm' }, { value: 'var(--button-fulfill-text)', scope: 'color:fulfill' }, { value: 'var(--button-risk-text)', scope: 'color:risk' }, { value: 'var(--button-threat-text)', scope: 'color:threat' }, { value: 'var(--button-loss-text)', scope: 'color:loss' } ] }, 'palette-contrast': { declarations: [ { value: 'var(--button-primary-contrast)', scope: 'host' }, { value: 'var(--button-secondary-contrast)', scope: 'color:secondary' }, { value: 'var(--button-neutral-contrast)', scope: 'color:neutral' }, { value: 'var(--button-affirm-contrast)', scope: 'color:affirm' }, { value: 'var(--button-fulfill-contrast)', scope: 'color:fulfill' }, { value: 'var(--button-risk-contrast)', scope: 'color:risk' }, { value: 'var(--button-threat-contrast)', scope: 'color:threat' }, { value: 'var(--button-loss-contrast)', scope: 'color:loss' } ] } }, calendar: { gap: 'var(--space-3)', 'padding-xs': 'var(--space-2)', 'padding-sm': 'var(--space-3)', 'padding-md': 'var(--space-4)', 'padding-lg': 'var(--space-5)', radius: 'var(--radius-lg)', 'border-width': 'var(--border-width)', border: 'var(--color-border-subtle)', 'invalid-border': 'var(--color-risk-border)', bg: 'var(--color-surface-raised)', 'outline-bg': 'var(--color-surface-default)', 'outline-shadow': 'none', color: 'var(--color-content-primary)', shadow: 'var(--depth-raised-shadow), var(--depth-raised-halo)', 'font-family': 'var(--font-ui)', 'font-size-xs': 'var(--font-size-xs)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'line-height': 'var(--leading-ui)', 'header-gap': 'var(--space-2)', 'heading-color': 'var(--color-content-primary)', 'heading-font-size': 'var(--font-size-sm)', 'heading-font-weight': 'var(--font-weight-semibold)', 'control-size-xs': 'var(--control-height-xxs)', 'control-size-sm': 'var(--control-height-xs)', 'control-size-md': 'var(--control-height-sm)', 'control-size-lg': 'var(--control-height-md)', 'control-radius': 'var(--radius-md)', 'control-border-width': 'var(--border-width)', 'control-border': 'transparent', 'control-border-hover': 'var(--color-border-subtle)', 'control-bg': 'transparent', 'control-bg-hover': 'var(--color-surface-overlay)', 'control-color': 'var(--color-content-secondary)', 'control-color-hover': 'var(--color-content-primary)', 'select-min-width': '8ch', 'select-px': 'var(--space-2)', 'grid-gap': 'var(--space-0-5)', 'weekday-size': 'var(--space-5)', 'weekday-color': 'var(--color-content-muted)', 'weekday-font-size': 'var(--font-size-xs)', 'weekday-font-weight': 'var(--font-weight-medium)', 'day-size-xs': 'var(--control-height-xxs)', 'day-size-sm': 'var(--control-height-xs)', 'day-size-md': 'var(--control-height-sm)', 'day-size-lg': 'var(--control-height-md)', 'day-radius': 'var(--radius-md)', 'day-border-width': 'var(--border-width)', 'day-border': 'transparent', 'day-border-hover': 'var(--color-border-subtle)', 'day-bg': 'transparent', 'day-bg-hover': 'var(--color-surface-overlay)', 'day-color': 'var(--color-content-primary)', 'day-color-hover': 'var(--color-content-primary)', 'day-font-weight': 'var(--font-weight-regular)', 'day-selected-color': 'var(--color-content-on-solid)', 'day-today-border': 'var(--color-border-strong)', 'day-today-color': 'var(--color-content-primary)', 'day-today-font-weight': 'var(--font-weight-semibold)', 'day-outside-color': 'var(--color-content-muted)', 'day-outside-opacity': '0.62', 'day-weekend-color': 'var(--color-content-secondary)', 'day-holiday-shadow': 'inset 0 -2px 0 var(--_calendar-accent-border)', 'day-unavailable-decoration': 'var(--color-risk-border)', 'focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'event-shadow': '0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--_calendar-accent-border)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)' }, chronos: { // Component-semantic dimensions only. Spacing, typography and colors come // straight from the eidos primitives in chronos.css (no per-component // font/color tokens — those belong to the eidos foundation). 'cell-min-block-sm': 'calc(var(--control-height-md) * 2.6)', 'cell-min-block-md': 'calc(var(--control-height-md) * 3.2)', 'cell-min-block-lg': 'calc(var(--control-height-md) * 4)', 'num-row': 'var(--space-7)', 'lane-height-sm': 'var(--space-5)', 'lane-height-md': 'var(--space-6)', 'lane-height-lg': 'var(--space-7)', 'focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'disabled-opacity': 'var(--opacity-disabled)' }, pagination: { 'gap-xs': 'var(--space-0-5)', 'gap-sm': 'var(--space-1)', 'gap-md': 'var(--space-1-5)', 'gap-lg': 'var(--space-2)', 'control-size-xs': 'var(--control-height-xxs)', 'control-size-sm': 'var(--control-height-xs)', 'control-size-md': 'var(--control-height-sm)', 'control-size-lg': 'var(--control-height-md)', 'control-px-xs': 'var(--space-1-5)', 'control-px-sm': 'var(--space-2)', 'control-px-md': 'var(--space-2-5)', 'control-px-lg': 'var(--space-3)', 'font-family': 'var(--font-ui)', 'font-size-xs': 'var(--font-size-xs)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'line-height': 'var(--leading-ui)', 'control-radius': 'var(--radius-md)', 'control-border-width': 'var(--border-width)', 'control-border': 'transparent', 'control-border-hover': 'var(--color-border-subtle)', 'control-bg': 'transparent', 'control-bg-hover': 'var(--color-surface-raised)', 'control-color': 'var(--color-content-secondary)', 'control-color-hover': 'var(--color-content-primary)', 'selected-border': 'var(--color-primary-border)', 'selected-border-hover': 'var(--color-primary-border)', 'selected-bg': 'var(--color-primary-solid)', 'selected-bg-hover': 'var(--color-primary-solid-hover)', 'selected-color': 'var(--color-content-on-solid)', 'ellipsis-color': 'var(--color-content-muted)', 'focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)' }, popover: { 'content-z': '75', 'overlay-z': '60', 'overlay-bg': 'var(--color-overlay)', 'trigger-font-size': 'var(--font-size-sm)', gap: 'var(--space-3)', 'max-width': '32rem', 'min-width-sm': '14rem', 'min-width-md': '18rem', 'min-width-lg': '22rem', 'min-width-xl': '28rem', 'padding-y-sm': 'var(--space-2)', 'padding-x-sm': 'var(--space-2-5)', 'padding-y-md': 'var(--space-3)', 'padding-x-md': 'var(--space-3)', 'padding-y-lg': 'var(--space-3-5)', 'padding-x-lg': 'var(--space-4)', 'padding-y-xl': 'var(--space-4)', 'padding-x-xl': 'var(--space-5)', 'font-size': 'var(--font-size-sm)', 'font-family': 'var(--font-ui)', 'font-weight': 'var(--font-weight-regular)', 'line-height': 'var(--leading-text)', 'title-font-family': 'var(--font-heading)', 'title-font-size': 'var(--font-size-md)', 'title-font-weight': 'var(--font-weight-semibold)', 'title-line-height': 'var(--leading-heading)', 'title-color': 'var(--color-content-primary)', 'description-font-family': 'var(--font-ui)', 'description-font-size': 'var(--font-size-sm)', 'description-line-height': 'var(--leading-ui)', 'description-color': 'var(--color-content-secondary)', radius: 'var(--radius-lg)', 'border-width': 'var(--border-width)', bg: 'var(--color-surface-overlay)', color: 'var(--color-content-primary)', border: 'color-mix( in srgb, var(--color-border-default) 82%, var(--popover-bg) )', shadow: 'var(--depth-overlay-shadow), var(--depth-overlay-halo)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'close-size': 'var(--control-height-xs)', 'close-font-size': 'var(--font-size-sm)', 'close-radius': 'var(--radius-md)', 'close-border-width': 'var(--border-width)', 'close-bg': 'transparent', 'close-bg-hover': 'color-mix( in srgb, var(--color-neutral-track) 72%, var(--popover-bg) )', 'close-color': 'var(--color-content-secondary)', 'close-border': 'color-mix(in srgb, var(--color-border-default) 72%, transparent)', 'close-border-hover': 'var(--color-border-strong)' }, progress: { 'height-xs': '2px', 'height-sm': '4px', 'height-md': '6px', 'height-lg': '8px', 'height-xl': '12px', 'vertical-height': '10rem', 'radius-xs': 'var(--radius-full)', 'radius-sm': 'var(--radius-full)', 'radius-md': 'var(--radius-full)', 'radius-lg': 'var(--radius-full)', 'radius-xl': 'var(--radius-full)', 'ring-size-xs': '2rem', 'ring-size-sm': '2.5rem', 'ring-size-md': '3rem', 'ring-size-lg': '3.5rem', 'ring-size-xl': '4rem', 'ring-thickness-xs': '3px', 'ring-thickness-sm': '4px', 'ring-thickness-md': '6px', 'ring-thickness-lg': '8px', 'ring-thickness-xl': '10px', 'label-font-family': 'var(--font-ui)', 'label-font-size': 'var(--font-size-sm)', 'label-font-weight': 'var(--font-weight-medium)', 'label-line-height': 'var(--leading-ui)', 'label-color': 'var(--color-content-primary)', 'value-text-font-family': 'var(--font-ui)', 'value-text-font-size': 'var(--font-size-sm)', 'value-text-font-weight': 'var(--font-weight-regular)', 'value-text-line-height': 'var(--leading-ui)', 'value-text-color': 'var(--color-content-secondary)', 'track-bg': 'color-mix(in srgb, var(--color-content-primary) 12%, var(--color-surface-default))', 'ring-track-bg': 'color-mix(in srgb, var(--color-content-primary) 12%, var(--color-surface-default))', 'ring-center-bg': 'var(--color-surface-default)', 'indicator-bg': 'var(--color-primary-solid)', 'indicator-bg-loaded': 'var(--color-fulfill-solid)', 'transition-duration': 'var(--duration-normal)', 'transition-ease': 'var(--ease-default)', 'indeterminate-width': '35%', 'indeterminate-duration': '1.1s', 'indeterminate-ease': 'var(--ease-default)' }, 'radio-group': { 'gap-vertical': 'var(--space-3)', 'gap-horizontal': 'var(--space-4)', 'item-size-xs': '14px', 'item-size-sm': '16px', 'item-size-md': '18px', 'item-size-lg': '22px', 'item-size-xl': '26px', 'dot-size-xs': '5px', 'dot-size-sm': '6px', 'dot-size-md': '7px', 'dot-size-lg': '9px', 'dot-size-xl': '11px', 'item-gap': 'var(--space-3)', 'font-family': 'var(--font-ui)', 'font-size-xs': 'var(--font-size-xs)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'font-size-xl': 'var(--font-size-xl)', 'font-weight': 'var(--font-weight-medium)', 'line-height': 'var(--leading-ui)', 'item-label-color': 'var(--color-content-primary)', 'item-label-color-disabled': 'var(--color-content-disabled)', 'indicator-radius': 'var(--radius-full)', 'indicator-border-width': 'var(--border-width)', 'indicator-bg': 'var(--color-surface-default)', 'indicator-border': 'var(--color-border-default)', 'indicator-border-hover': 'var(--color-border-strong)', 'indicator-bg-disabled': 'color-mix( in srgb, var(--color-surface-overlay) 78%, var(--color-surface-default) )', 'indicator-border-disabled': 'color-mix( in srgb, var(--color-border-default) 72%, var(--color-border-subtle) )', 'indicator-bg-checked-disabled': 'color-mix( in srgb, var(--color-content-disabled) 40%, var(--color-surface-overlay) )', 'dot-color': 'var(--color-content-on-solid)', 'dot-color-disabled': 'color-mix( in srgb, var(--color-content-on-solid) 82%, var(--color-surface-default) )', 'focus-ring-offset': 'var(--focus-ring-offset)', 'focus-ring-width': 'var(--focus-ring-width)', 'focus-ring-color': 'var(--focus-ring-color)', 'focus-ring-surface': 'var(--color-surface-default)', 'focus-ring': '0 0 0 var(--radio-group-focus-ring-offset) var(--radio-group-focus-ring-surface), 0 0 0 calc(var(--radio-group-focus-ring-offset) + var(--radio-group-focus-ring-width)) var(--radio-group-focus-ring-color)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)', 'primary-solid': 'var(--color-primary-solid)', 'primary-solid-hover': 'var(--color-primary-solid-hover)', 'neutral-solid': 'var(--color-neutral-solid)', 'neutral-solid-hover': 'var(--color-neutral-solid-hover)', 'secondary-solid': 'var(--color-secondary-solid)', 'secondary-solid-hover': 'var(--color-secondary-solid-hover)', 'affirm-solid': 'var(--color-affirm-solid)', 'affirm-solid-hover': 'var(--color-affirm-solid-hover)', 'label-font-family': 'var(--font-ui)', 'label-font-size': 'var(--font-size-sm)', 'label-font-weight': 'var(--font-weight-medium)', 'label-line-height': 'var(--leading-ui)', 'label-color': 'var(--color-content-primary)', // Private palette (TSC v2.1). Declared on the [data-radio-group] // host, inherited by [data-radio-group-item] descendants via // CSS custom property inheritance. Migrated from per-color // blocks in radio-group.css. '_palette-solid': { declarations: [ { value: 'var(--radio-group-primary-solid)', scope: 'host' }, { value: 'var(--radio-group-secondary-solid)', scope: 'color:secondary' }, { value: 'var(--radio-group-neutral-solid)', scope: 'color:neutral' }, { value: 'var(--radio-group-affirm-solid)', scope: 'color:affirm' } ] }, '_palette-solid-hover': { declarations: [ { value: 'var(--radio-group-primary-solid-hover)', scope: 'host' }, { value: 'var(--radio-group-secondary-solid-hover)', scope: 'color:secondary' }, { value: 'var(--radio-group-neutral-solid-hover)', scope: 'color:neutral' }, { value: 'var(--radio-group-affirm-solid-hover)', scope: 'color:affirm' } ] }, '_palette-text': { value: 'var(--radio-group-dot-color)', scope: 'host' } }, // QrCode. Default fg/bg are FIXED-TONE (dark modules on a light backing), // not theme tokens: a QR must stay dark-on-light to scan — inverting it in // dark mode would break scanners. Theming goes through the `color` / // `background` props (consumer owns the contrast). 'qr-code': { fg: '#18181b', bg: '#ffffff', 'size-xs': '96px', 'size-sm': '128px', 'size-md': '160px', 'size-lg': '200px', 'size-xl': '256px', radius: 'var(--radius-md)', // White padding behind a center logo — FIXED-TONE for the same reason as // fg/bg above (the quiet zone around the logo must stay light to scan). 'overlay-bg': '#ffffff', 'overlay-radius': 'var(--radius-sm)' }, // RadioCards — card-style skin over RadioGroup. Reuses RadioGroup's // palette (`--_radio-group-palette-solid`, declared on the shared // [data-radio-group] host) and `--radio-group-focus-ring`; adds only the // card chrome (padding, radius, surface, title/description type). 'radio-cards': { gap: 'var(--space-3)', // Min card width in a horizontal row before wrapping (rem → scales with // root font-size / zoom). 'horizontal-basis': '12rem', 'padding-xs': 'var(--space-3)', 'padding-sm': 'var(--space-3)', 'padding-md': 'var(--space-4)', 'padding-lg': 'var(--space-4)', 'padding-xl': 'var(--space-5)', radius: 'var(--radius-lg)', 'border-width': 'var(--border-width)', border: 'var(--color-border-default)', 'border-hover': 'var(--color-border-strong)', bg: 'var(--color-surface-default)', 'bg-hover': 'var(--color-surface-raised)', 'content-gap': 'var(--space-3)', 'text-gap': 'var(--space-0-5)', 'title-font-family': 'var(--font-ui)', 'title-font-size-xs': 'var(--font-size-sm)', 'title-font-size-sm': 'var(--font-size-sm)', 'title-font-size-md': 'var(--font-size-md)', 'title-font-size-lg': 'var(--font-size-md)', 'title-font-size-xl': 'var(--font-size-lg)', 'title-font-weight': 'var(--font-weight-medium)', 'title-line-height': 'var(--leading-ui)', 'title-color': 'var(--color-content-primary)', 'description-font-size-xs': 'var(--font-size-xs)', 'description-font-size-sm': 'var(--font-size-xs)', 'description-font-size-md': 'var(--font-size-sm)', 'description-font-size-lg': 'var(--font-size-sm)', 'description-font-size-xl': 'var(--font-size-md)', 'description-line-height': 'var(--leading-normal)', 'description-color': 'var(--color-content-secondary)', // Icon follows the card's title font-size (canonical icon↔type correlation), // not an inflated standalone size. A bigger card icon comes from a bigger // title (the icon follows), never from inflating the icon by hand. 'icon-size-xs': 'var(--icon-size-sm)', 'icon-size-sm': 'var(--icon-size-sm)', 'icon-size-md': 'var(--icon-size-md)', 'icon-size-lg': 'var(--icon-size-md)', 'icon-size-xl': 'var(--icon-size-lg)', 'icon-color': 'var(--color-content-secondary)', // NOTE: the checked treatment (active border + faint tint + icon tint) // is NOT a token here. It references `--_radio-group-palette-solid`, // which is undefined at :root (declared only on [data-radio-group] // hosts) — a :root token referencing it is invalid-at-computed-value // and poisons down the tree. It's inlined in radio-cards.css instead, // applied on the card item where the palette IS in scope. 'focus-ring': 'var(--radio-group-focus-ring)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)' }, 'rating-group': { 'gap-xs': 'var(--space-0-5)', 'gap-sm': 'var(--space-1)', 'gap-md': 'var(--space-1-5)', 'gap-lg': 'var(--space-2)', 'gap-xl': 'var(--space-2-5)', 'item-size-xs': '14px', 'item-size-sm': '18px', 'item-size-md': '22px', 'item-size-lg': '28px', 'item-size-xl': '34px', 'font-family': 'var(--font-ui)', 'font-size-xs': 'var(--font-size-xs)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'font-size-xl': 'var(--font-size-xl)', 'line-height': 'var(--leading-ui)', 'item-color-inactive': 'var(--color-neutral-border)', 'item-color-active': 'var(--color-fulfill-solid)', 'item-color-partial': 'var(--color-fulfill-solid)', 'item-hover-offset': '-1px', 'focus-radius': 'var(--radius-md)', 'focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)' }, 'search-field': { 'height-xs': 'var(--control-height-xs)', 'height-sm': 'var(--control-height-sm)', 'height-md': 'var(--control-height-md)', 'height-lg': 'var(--control-height-lg)', 'height-xl': 'var(--control-height-xl)', 'px-xs': 'var(--space-2)', 'px-sm': 'var(--space-2-5)', 'px-md': 'var(--space-3)', 'px-lg': 'var(--space-3-5)', 'px-xl': 'var(--space-4)', 'gap-xs': 'var(--space-1)', 'gap-sm': 'var(--space-1-5)', 'gap-md': 'var(--space-2)', 'gap-lg': 'var(--space-2-5)', 'gap-xl': 'var(--space-3)', 'font-family': 'var(--font-ui)', 'font-size-xs': 'var(--font-size-xs)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'font-size-xl': 'var(--font-size-xl)', 'line-height': 'var(--leading-ui)', radius: 'var(--radius-md)', 'border-width': 'var(--border-width)', border: 'var(--color-border-default)', 'border-focus': 'var(--color-focus-ring)', 'border-invalid': 'var(--color-risk-border)', bg: 'var(--color-surface-default)', color: 'var(--color-content-primary)', 'placeholder-color': 'var(--color-content-muted)', 'focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'clear-hidden-opacity': '0', 'icon-size-xs': 'var(--icon-size-xs)', 'icon-size-sm': 'var(--icon-size-sm)', 'icon-size-md': 'var(--icon-size-md)', 'icon-size-lg': 'var(--icon-size-lg)', 'icon-size-xl': 'var(--icon-size-xl)', 'icon-color': 'var(--color-content-muted)', 'icon-margin-inline-end': 'var(--space-1-5)', 'loading-indicator-size-xs': 'var(--icon-size-xs)', 'loading-indicator-size-sm': 'var(--icon-size-sm)', 'loading-indicator-size-md': 'var(--icon-size-md)', 'loading-indicator-size-lg': 'var(--icon-size-md)', 'loading-indicator-size-xl': 'var(--icon-size-lg)', 'loading-indicator-color': 'var(--color-content-muted)', 'loading-indicator-track': 'var(--color-border-subtle)', 'loading-indicator-thickness': '2px', 'loading-indicator-duration': '900ms', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)' }, 'password-field': { 'height-xs': 'var(--control-height-xs)', 'height-sm': 'var(--control-height-sm)', 'height-md': 'var(--control-height-md)', 'height-lg': 'var(--control-height-lg)', 'height-xl': 'var(--control-height-xl)', 'px-xs': 'var(--space-2)', 'px-sm': 'var(--space-2-5)', 'px-md': 'var(--space-3)', 'px-lg': 'var(--space-3-5)', 'px-xl': 'var(--space-4)', 'gap-xs': 'var(--space-1)', 'gap-sm': 'var(--space-1-5)', 'gap-md': 'var(--space-2)', 'gap-lg': 'var(--space-2-5)', 'gap-xl': 'var(--space-3)', 'font-family': 'var(--font-ui)', 'font-size-xs': 'var(--font-size-xs)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'font-size-xl': 'var(--font-size-xl)', 'line-height': 'var(--leading-ui)', radius: 'var(--radius-md)', 'border-width': 'var(--border-width)', border: 'var(--color-border-default)', 'border-focus': 'var(--color-focus-ring)', 'border-invalid': 'var(--color-risk-border)', bg: 'var(--color-surface-default)', color: 'var(--color-content-primary)', 'placeholder-color': 'var(--color-content-muted)', 'focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'trigger-radius': 'var(--radius-full)', 'trigger-border-width': 'var(--border-width)', 'trigger-border': 'transparent', 'trigger-border-hover': 'var(--color-border-subtle)', 'trigger-bg': 'transparent', 'trigger-bg-hover': 'var(--color-surface-raised)', 'trigger-color': 'var(--color-content-secondary)', 'trigger-color-hover': 'var(--color-content-primary)', 'trigger-focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'icon-size-xs': 'var(--control-height-xs)', 'icon-size-sm': 'var(--control-height-xs)', 'icon-size-md': 'var(--control-height-sm)', 'icon-size-lg': 'var(--control-height-sm)', 'icon-size-xl': 'var(--control-height-md)', 'caps-color': 'var(--color-risk-text)', 'caps-bg': 'color-mix(in srgb, var(--color-risk-track) 50%, transparent)', 'caps-font-size-xs': 'var(--font-size-xs)', 'caps-font-size-sm': 'var(--font-size-xs)', 'caps-font-size-md': 'var(--font-size-xs)', 'caps-font-size-lg': 'var(--font-size-sm)', 'caps-font-size-xl': 'var(--font-size-sm)', 'strength-segment-bg': 'var(--color-border-default)', 'strength-segment-gap': '4px', 'strength-segment-height': '6px', 'strength-radius': 'var(--radius-sm)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)' }, select: { 'stack-gap': 'var(--space-2)', 'font-family': 'var(--font-ui)', 'font-size-xs': 'var(--font-size-xs)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'font-size-xl': 'var(--font-size-xl)', 'line-height': 'var(--leading-ui)', color: 'var(--color-content-primary)', // Per-color forwarders consumed only by the TSC v2.2 `_accent-*` // cascade below. The `solid` slot is intentionally omitted — // select.css doesn't read `_accent-solid`, so its forwarders // would be orphans (caught by the recipe-css-contract guard). 'primary-text': 'var(--color-primary-text)', 'secondary-text': 'var(--color-secondary-text)', 'neutral-text': 'var(--color-neutral-text)', 'affirm-text': 'var(--color-affirm-text)', 'fulfill-track': 'var(--color-fulfill-track)', 'fulfill-border': 'var(--color-fulfill-border)', 'fulfill-text': 'var(--color-fulfill-text)', 'risk-text': 'var(--color-risk-text)', 'threat-text': 'var(--color-threat-text)', 'loss-track': 'var(--color-loss-track)', 'loss-border': 'var(--color-loss-border)', 'loss-text': 'var(--color-loss-text)', 'trigger-height-xs': 'var(--control-height-xs)', 'trigger-height-sm': 'var(--control-height-sm)', 'trigger-height-md': 'var(--control-height-md)', 'trigger-height-lg': 'var(--control-height-lg)', 'trigger-height-xl': 'var(--control-height-xl)', 'trigger-px-xs': 'var(--space-2)', 'trigger-px-sm': 'var(--space-2-5)', 'trigger-px-md': 'var(--space-3)', 'trigger-px-lg': 'var(--space-3-5)', 'trigger-px-xl': 'var(--space-4)', 'trigger-gap-xs': 'var(--space-1)', 'trigger-gap-sm': 'var(--space-1-5)', 'trigger-gap-md': 'var(--space-2)', 'trigger-gap-lg': 'var(--space-2-5)', 'trigger-gap-xl': 'var(--space-3)', 'trigger-border-width': 'var(--border-width)', 'trigger-border': 'var(--color-border-default)', 'trigger-border-hover': 'var(--color-border-strong)', 'trigger-radius': 'var(--radius-md)', 'trigger-bg': 'var(--color-surface-default)', 'trigger-bg-hover': 'var(--color-surface-raised)', 'trigger-shadow': 'var(--shadow-subtle)', 'trigger-color': 'var(--color-content-primary)', 'trigger-indicator-color': 'var(--color-content-secondary)', 'trigger-indicator-size': 'var(--icon-size-sm)', 'placeholder-color': 'var(--color-content-muted)', 'focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'disabled-border': 'var(--color-border-subtle)', 'disabled-bg': 'var(--color-surface-raised)', 'disabled-color': 'var(--color-content-disabled)', 'content-z': '80', 'content-py-xs': 'var(--space-0-5)', 'content-py-sm': 'var(--space-1)', 'content-py-md': 'var(--space-1-5)', 'content-py-lg': 'var(--space-2)', 'content-py-xl': 'var(--space-2-5)', 'content-px-xs': 'var(--space-0-5)', 'content-px-sm': 'var(--space-1)', 'content-px-md': 'var(--space-1-5)', 'content-px-lg': 'var(--space-2)', 'content-px-xl': 'var(--space-2-5)', 'content-min-width': '12rem', 'content-max-width': '24rem', 'content-max-height': 'min(20rem, calc(100dvh - var(--space-6)))', 'content-border-width': 'var(--border-width)', 'content-border': 'var(--color-border-default)', 'content-radius': 'var(--radius-lg)', 'content-bg': 'var(--color-surface-overlay)', 'content-color': 'var(--color-content-primary)', 'content-shadow': 'var(--depth-overlay-shadow), var(--depth-overlay-halo)', 'content-outline-shadow': 'var(--depth-raised-shadow), var(--depth-raised-halo)', 'content-ghost-shadow': 'var(--depth-raised-shadow), var(--depth-raised-halo)', 'open-duration': 'var(--duration-normal)', 'close-duration': 'var(--duration-fast)', 'viewport-gap': 'var(--space-0-5)', 'viewport-padding': 'var(--space-0-5)', 'group-gap': 'var(--space-0-5)', 'group-py': 'var(--space-1)', 'group-heading-py': 'var(--space-1)', 'group-heading-px': 'var(--space-2)', 'group-heading-font-family': 'var(--font-ui)', 'group-heading-font-size': 'var(--font-size-xs)', 'group-heading-font-weight': 'var(--font-weight-semibold)', 'group-heading-letter-spacing': '0.04em', 'group-heading-color': 'var(--color-content-muted)', 'separator-size': 'var(--border-width)', 'separator-my': 'var(--space-1)', 'separator-bg': 'var(--color-border-subtle)', 'item-gap': 'var(--space-2)', 'item-min-height': 'var(--control-height-sm)', 'item-px': 'var(--space-2)', 'item-radius': 'var(--radius-md)', 'item-color': 'var(--color-content-primary)', 'item-bg-highlighted': 'var(--color-surface-raised)', 'item-color-highlighted': 'var(--color-content-primary)', 'item-indicator-size': 'var(--icon-size-sm)', 'item-focus-ring-width': 'var(--border-width-medium)', 'item-description-mt': '0.125rem', 'item-description-color': 'var(--color-content-muted)', 'item-description-font-size': '0.85em', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', // Restored after accidental sed-removal during switch migration. 'primary-track': 'var(--color-primary-track)', 'primary-border': 'var(--color-primary-border)', 'secondary-track': 'var(--color-secondary-track)', 'secondary-border': 'var(--color-secondary-border)', 'neutral-track': 'var(--color-neutral-track)', 'neutral-border': 'var(--color-neutral-border)', 'affirm-track': 'var(--color-affirm-track)', 'affirm-border': 'var(--color-affirm-border)', 'risk-track': 'var(--color-risk-track)', 'risk-border': 'var(--color-risk-border)', 'threat-track': 'var(--color-threat-track)', 'threat-border': 'var(--color-threat-border)', // TSC v2.2 — multi-part palette cascade. Select's `data-color` // attribute lives on the trigger AND content parts (NOT on the // root `[data-select]`), because content portals out of the // document tree and must carry the color independently. The // `parts: ['trigger', 'content']` field tells the generator to // emit each declaration as a comma-separated rule targeting both // `[data-select-trigger]` and `[data-select-content]`. // // 1 host default (primary) + 7 per-color cascades for each of the // 3 perceptual slots that select.css consumes (`track`, `border`, // `text`). The legacy CSS also declared `--_select-accent-solid` // but nothing in select.css read it; that orphan stayed out of // the TSC migration on purpose. '_accent-track': { parts: ['trigger', 'content'], declarations: [ { value: 'var(--select-primary-track)', scope: 'host' }, { value: 'var(--select-secondary-track)', scope: 'color:secondary' }, { value: 'var(--select-neutral-track)', scope: 'color:neutral' }, { value: 'var(--select-affirm-track)', scope: 'color:affirm' }, { value: 'var(--select-fulfill-track)', scope: 'color:fulfill' }, { value: 'var(--select-risk-track)', scope: 'color:risk' }, { value: 'var(--select-threat-track)', scope: 'color:threat' }, { value: 'var(--select-loss-track)', scope: 'color:loss' } ] }, '_accent-border': { parts: ['trigger', 'content'], declarations: [ { value: 'var(--select-primary-border)', scope: 'host' }, { value: 'var(--select-secondary-border)', scope: 'color:secondary' }, { value: 'var(--select-neutral-border)', scope: 'color:neutral' }, { value: 'var(--select-affirm-border)', scope: 'color:affirm' }, { value: 'var(--select-fulfill-border)', scope: 'color:fulfill' }, { value: 'var(--select-risk-border)', scope: 'color:risk' }, { value: 'var(--select-threat-border)', scope: 'color:threat' }, { value: 'var(--select-loss-border)', scope: 'color:loss' } ] }, '_accent-text': { parts: ['trigger', 'content'], declarations: [ { value: 'var(--select-primary-text)', scope: 'host' }, { value: 'var(--select-secondary-text)', scope: 'color:secondary' }, { value: 'var(--select-neutral-text)', scope: 'color:neutral' }, { value: 'var(--select-affirm-text)', scope: 'color:affirm' }, { value: 'var(--select-fulfill-text)', scope: 'color:fulfill' }, { value: 'var(--select-risk-text)', scope: 'color:risk' }, { value: 'var(--select-threat-text)', scope: 'color:threat' }, { value: 'var(--select-loss-text)', scope: 'color:loss' } ] } }, toolbar: { 'gap-xs': 'var(--space-0-5)', 'gap-sm': 'var(--space-1)', 'gap-md': 'var(--space-1-5)', 'gap-lg': 'var(--space-2)', 'padding-inline-xs': 'var(--space-0-5)', 'padding-inline-sm': 'var(--space-1)', 'padding-inline-md': 'var(--space-1-5)', 'padding-inline-lg': 'var(--space-2)', 'padding-block-xs': 'var(--space-0-5)', 'padding-block-sm': 'var(--space-1)', 'padding-block-md': 'var(--space-1)', 'padding-block-lg': 'var(--space-1-5)', 'control-height-xs': 'var(--control-height-xs)', 'control-height-sm': 'var(--control-height-sm)', 'control-height-md': 'var(--control-height-md)', 'control-height-lg': 'var(--control-height-lg)', 'control-px-xs': 'var(--space-1-5)', 'control-px-sm': 'var(--space-2)', 'control-px-md': 'var(--space-2-5)', 'control-px-lg': 'var(--space-3)', 'control-gap-xs': 'var(--space-0-5)', 'control-gap-sm': 'var(--space-1)', 'control-gap-md': 'var(--space-1-5)', 'control-gap-lg': 'var(--space-2)', 'font-family': 'var(--font-ui)', 'font-size-xs': 'var(--font-size-xs)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'line-height': 'var(--leading-ui)', radius: 'var(--radius-lg)', bg: 'var(--color-surface-raised)', border: 'var(--color-border-subtle)', 'border-width': 'var(--border-width)', shadow: 'var(--shadow-subtle)', color: 'var(--color-content-primary)', 'group-gap': 'var(--space-0-5)', 'control-radius': 'var(--radius-md)', 'control-border-width': 'var(--border-width)', 'control-border': 'transparent', 'control-border-hover': 'var(--color-border-subtle)', 'control-border-active': 'var(--color-primary-border)', 'control-bg': 'transparent', 'control-bg-hover': 'var(--color-surface-overlay)', 'control-bg-active': 'var(--color-primary-track)', 'control-color': 'var(--color-content-secondary)', 'control-color-hover': 'var(--color-content-primary)', 'control-color-active': 'var(--color-primary-text)', 'focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'separator-bg': 'var(--color-border-subtle)', 'separator-thickness': 'var(--border-width)', 'separator-length': 'var(--control-height-md)', 'separator-radius': 'var(--radius-full)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)' }, 'file-upload': { 'gap-sm': 'var(--space-2)', 'gap-md': 'var(--space-3)', 'gap-lg': 'var(--space-4)', 'padding-sm': 'var(--space-4)', 'padding-md': 'var(--space-5)', 'padding-lg': 'var(--space-6)', 'control-height-sm': 'var(--control-height-sm)', 'control-height-md': 'var(--control-height-md)', 'control-height-lg': 'var(--control-height-lg)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'preview-size-sm': '32px', 'preview-size-md': '40px', 'preview-size-lg': '48px', 'font-family': 'var(--font-ui)', 'line-height': 'var(--leading-ui)', color: 'var(--color-content-primary)', 'label-color': 'var(--color-content-secondary)', 'label-font-weight': 'var(--font-weight-medium)', 'dropzone-gap': 'var(--space-2)', 'dropzone-min-height': '9rem', 'dropzone-border-width': 'var(--border-width)', 'dropzone-border': 'var(--color-border-default)', 'dropzone-radius': 'var(--radius-lg)', 'dropzone-bg': 'var(--color-surface-raised)', 'dropzone-color': 'var(--color-content-secondary)', 'focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'button-gap': 'var(--space-1-5)', 'button-px': 'var(--space-3)', 'button-border-width': 'var(--border-width)', 'button-border': 'var(--color-border-subtle)', 'button-border-hover': 'var(--color-border-default)', 'button-radius': 'var(--radius-md)', 'button-bg': 'var(--color-surface-raised)', 'button-bg-hover': 'var(--color-surface-overlay)', 'button-color': 'var(--color-content-secondary)', 'button-color-hover': 'var(--color-content-primary)', 'button-solid-color': 'var(--color-content-on-solid)', 'list-gap': 'var(--space-2)', 'item-gap': 'var(--space-3)', 'item-padding': 'var(--space-2)', 'item-border-width': 'var(--border-width)', 'item-border': 'var(--color-border-subtle)', 'item-radius': 'var(--radius-md)', 'item-bg': 'var(--color-surface-raised)', 'item-shadow': 'var(--shadow-subtle)', 'preview-radius': 'var(--radius-sm)', 'preview-bg': 'var(--color-neutral-track)', 'preview-color': 'var(--color-neutral-text)', 'item-name-color': 'var(--color-content-primary)', 'item-name-font-weight': 'var(--font-weight-medium)', 'item-size-color': 'var(--color-content-muted)', 'item-size-font-size': 'var(--font-size-xs)', 'progress-height': '4px', 'progress-radius': 'var(--radius-full)', 'progress-track-bg': 'var(--color-neutral-track)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)', 'primary-solid': 'var(--color-primary-solid)', 'primary-solid-hover': 'var(--color-primary-solid-hover)', 'primary-text': 'var(--color-primary-text)', 'secondary-solid': 'var(--color-secondary-solid)', 'secondary-solid-hover': 'var(--color-secondary-solid-hover)', 'secondary-text': 'var(--color-secondary-text)', 'neutral-solid': 'var(--color-neutral-solid)', 'neutral-solid-hover': 'var(--color-neutral-solid-hover)', 'neutral-text': 'var(--color-neutral-text)', 'affirm-solid': 'var(--color-affirm-solid)', 'affirm-solid-hover': 'var(--color-affirm-solid-hover)', 'affirm-text': 'var(--color-affirm-text)', 'fulfill-solid': 'var(--color-fulfill-solid)', 'fulfill-solid-hover': 'var(--color-fulfill-solid-hover)', 'fulfill-track': 'var(--color-fulfill-track)', 'fulfill-border': 'var(--color-fulfill-border)', 'fulfill-text': 'var(--color-fulfill-text)', 'risk-solid': 'var(--color-risk-solid)', 'risk-solid-hover': 'var(--color-risk-solid-hover)', 'risk-text': 'var(--color-risk-text)', 'threat-solid': 'var(--color-threat-solid)', 'threat-solid-hover': 'var(--color-threat-solid-hover)', 'threat-text': 'var(--color-threat-text)', 'loss-solid': 'var(--color-loss-solid)', 'loss-solid-hover': 'var(--color-loss-solid-hover)', 'loss-track': 'var(--color-loss-track)', 'loss-border': 'var(--color-loss-border)', 'loss-text': 'var(--color-loss-text)', // Restored after accidental sed-removal during switch migration. 'primary-track': 'var(--color-primary-track)', 'primary-border': 'var(--color-primary-border)', 'secondary-track': 'var(--color-secondary-track)', 'secondary-border': 'var(--color-secondary-border)', 'neutral-track': 'var(--color-neutral-track)', 'neutral-border': 'var(--color-neutral-border)', 'affirm-track': 'var(--color-affirm-track)', 'affirm-border': 'var(--color-affirm-border)', 'risk-track': 'var(--color-risk-track)', 'risk-border': 'var(--color-risk-border)', 'threat-track': 'var(--color-threat-track)', 'threat-border': 'var(--color-threat-border)', // Private accent palette (TSC v2.1). 8 colors, 5 slots. '_accent-solid': { declarations: [ { value: 'var(--file-upload-primary-solid)', scope: 'host' }, { value: 'var(--file-upload-secondary-solid)', scope: 'color:secondary' }, { value: 'var(--file-upload-neutral-solid)', scope: 'color:neutral' }, { value: 'var(--file-upload-affirm-solid)', scope: 'color:affirm' }, { value: 'var(--file-upload-fulfill-solid)', scope: 'color:fulfill' }, { value: 'var(--file-upload-risk-solid)', scope: 'color:risk' }, { value: 'var(--file-upload-threat-solid)', scope: 'color:threat' }, { value: 'var(--file-upload-loss-solid)', scope: 'color:loss' } ] }, '_accent-solid-hover': { declarations: [ { value: 'var(--file-upload-primary-solid-hover)', scope: 'host' }, { value: 'var(--file-upload-secondary-solid-hover)', scope: 'color:secondary' }, { value: 'var(--file-upload-neutral-solid-hover)', scope: 'color:neutral' }, { value: 'var(--file-upload-affirm-solid-hover)', scope: 'color:affirm' }, { value: 'var(--file-upload-fulfill-solid-hover)', scope: 'color:fulfill' }, { value: 'var(--file-upload-risk-solid-hover)', scope: 'color:risk' }, { value: 'var(--file-upload-threat-solid-hover)', scope: 'color:threat' }, { value: 'var(--file-upload-loss-solid-hover)', scope: 'color:loss' } ] }, '_accent-track': { declarations: [ { value: 'var(--file-upload-primary-track)', scope: 'host' }, { value: 'var(--file-upload-secondary-track)', scope: 'color:secondary' }, { value: 'var(--file-upload-neutral-track)', scope: 'color:neutral' }, { value: 'var(--file-upload-affirm-track)', scope: 'color:affirm' }, { value: 'var(--file-upload-fulfill-track)', scope: 'color:fulfill' }, { value: 'var(--file-upload-risk-track)', scope: 'color:risk' }, { value: 'var(--file-upload-threat-track)', scope: 'color:threat' }, { value: 'var(--file-upload-loss-track)', scope: 'color:loss' } ] }, '_accent-border': { declarations: [ { value: 'var(--file-upload-primary-border)', scope: 'host' }, { value: 'var(--file-upload-secondary-border)', scope: 'color:secondary' }, { value: 'var(--file-upload-neutral-border)', scope: 'color:neutral' }, { value: 'var(--file-upload-affirm-border)', scope: 'color:affirm' }, { value: 'var(--file-upload-fulfill-border)', scope: 'color:fulfill' }, { value: 'var(--file-upload-risk-border)', scope: 'color:risk' }, { value: 'var(--file-upload-threat-border)', scope: 'color:threat' }, { value: 'var(--file-upload-loss-border)', scope: 'color:loss' } ] }, '_accent-text': { declarations: [ { value: 'var(--file-upload-primary-text)', scope: 'host' }, { value: 'var(--file-upload-secondary-text)', scope: 'color:secondary' }, { value: 'var(--file-upload-neutral-text)', scope: 'color:neutral' }, { value: 'var(--file-upload-affirm-text)', scope: 'color:affirm' }, { value: 'var(--file-upload-fulfill-text)', scope: 'color:fulfill' }, { value: 'var(--file-upload-risk-text)', scope: 'color:risk' }, { value: 'var(--file-upload-threat-text)', scope: 'color:threat' }, { value: 'var(--file-upload-loss-text)', scope: 'color:loss' } ] } }, 'tag-group': { 'gap-xs': 'var(--space-0-5)', 'gap-sm': 'var(--space-1)', 'gap-md': 'var(--space-1-5)', 'gap-lg': 'var(--space-2)', 'item-height-xs': 'var(--control-height-xs)', 'item-height-sm': 'var(--control-height-sm)', 'item-height-md': 'var(--control-height-md)', 'item-height-lg': 'var(--control-height-lg)', 'item-px-xs': 'var(--space-1-5)', 'item-px-sm': 'var(--space-2)', 'item-px-md': 'var(--space-2-5)', 'item-px-lg': 'var(--space-3)', 'item-gap-xs': 'var(--space-0-5)', 'item-gap-sm': 'var(--space-1)', 'item-gap-md': 'var(--space-1-5)', 'item-gap-lg': 'var(--space-2)', 'font-family': 'var(--font-ui)', 'font-size-xs': 'var(--font-size-xs)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'line-height': 'var(--leading-ui)', color: 'var(--color-content-primary)', 'label-color': 'var(--color-content-secondary)', 'label-font-weight': 'var(--font-weight-medium)', 'item-radius': 'var(--radius-full)', 'item-border-width': 'var(--border-width)', 'item-border': 'var(--color-border-subtle)', 'item-border-hover': 'var(--color-border-default)', 'item-bg': 'var(--color-surface-raised)', 'item-bg-hover': 'var(--color-surface-overlay)', 'item-shadow': 'var(--shadow-subtle)', 'item-color': 'var(--color-content-secondary)', 'item-color-hover': 'var(--color-content-primary)', 'focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'solid-fg': 'var(--color-content-on-solid)', 'remove-size': 'var(--control-height-xs)', 'remove-radius': 'var(--radius-full)', 'remove-border-width': 'var(--border-width)', 'remove-border': 'transparent', 'remove-border-hover': 'var(--color-border-subtle)', 'remove-bg': 'transparent', 'remove-bg-hover': 'color-mix(in srgb, currentColor 12%, transparent)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)', 'primary-solid-bg': 'var(--color-primary-solid)', 'primary-solid-bg-hover': 'var(--color-primary-solid-hover)', 'primary-soft-bg': 'var(--color-primary-surface)', 'primary-soft-bg-hover': 'var(--color-primary-surface-hover)', 'primary-soft-fg': 'var(--color-primary-text)', 'primary-outline-border': 'var(--color-primary-border)', 'primary-outline-fg': 'var(--color-primary-text)', 'secondary-solid-bg': 'var(--color-secondary-solid)', 'secondary-solid-bg-hover': 'var(--color-secondary-solid-hover)', 'secondary-soft-bg': 'var(--color-secondary-surface)', 'secondary-soft-bg-hover': 'var(--color-secondary-surface-hover)', 'secondary-soft-fg': 'var(--color-secondary-text)', 'secondary-outline-border': 'var(--color-secondary-border)', 'secondary-outline-fg': 'var(--color-secondary-text)', 'neutral-solid-bg': 'var(--color-neutral-solid)', 'neutral-solid-bg-hover': 'var(--color-neutral-solid-hover)', 'neutral-soft-bg': 'var(--color-neutral-surface)', 'neutral-soft-bg-hover': 'var(--color-neutral-surface-hover)', 'neutral-soft-fg': 'var(--color-neutral-text)', 'neutral-outline-border': 'var(--color-neutral-border)', 'neutral-outline-fg': 'var(--color-neutral-text)', 'affirm-solid-bg': 'var(--color-affirm-solid)', 'affirm-solid-bg-hover': 'var(--color-affirm-solid-hover)', 'affirm-soft-bg': 'var(--color-affirm-surface)', 'affirm-soft-bg-hover': 'var(--color-affirm-surface-hover)', 'affirm-soft-fg': 'var(--color-affirm-text)', 'affirm-outline-border': 'var(--color-affirm-border)', 'affirm-outline-fg': 'var(--color-affirm-text)', 'fulfill-solid-bg': 'var(--color-fulfill-solid)', 'fulfill-solid-bg-hover': 'var(--color-fulfill-solid-hover)', 'fulfill-soft-bg': 'var(--color-fulfill-surface)', 'fulfill-soft-bg-hover': 'var(--color-fulfill-surface-hover)', 'fulfill-soft-fg': 'var(--color-fulfill-text)', 'fulfill-outline-border': 'var(--color-fulfill-border)', 'fulfill-outline-fg': 'var(--color-fulfill-text)', 'risk-solid-bg': 'var(--color-risk-solid)', 'risk-solid-bg-hover': 'var(--color-risk-solid-hover)', 'risk-soft-bg': 'var(--color-risk-surface)', 'risk-soft-bg-hover': 'var(--color-risk-surface-hover)', 'risk-soft-fg': 'var(--color-risk-text)', 'risk-outline-border': 'var(--color-risk-border)', 'risk-outline-fg': 'var(--color-risk-text)', 'threat-solid-bg': 'var(--color-threat-solid)', 'threat-solid-bg-hover': 'var(--color-threat-solid-hover)', 'threat-soft-bg': 'var(--color-threat-surface)', 'threat-soft-bg-hover': 'var(--color-threat-surface-hover)', 'threat-soft-fg': 'var(--color-threat-text)', 'threat-outline-border': 'var(--color-threat-border)', 'threat-outline-fg': 'var(--color-threat-text)', 'loss-solid-bg': 'var(--color-loss-solid)', 'loss-solid-bg-hover': 'var(--color-loss-solid-hover)', 'loss-soft-bg': 'var(--color-loss-surface)', 'loss-soft-bg-hover': 'var(--color-loss-surface-hover)', 'loss-soft-fg': 'var(--color-loss-text)', 'loss-outline-border': 'var(--color-loss-border)', 'loss-outline-fg': 'var(--color-loss-text)', // Private selected palette (TSC v2.1). 8 colors, 7 slots // (solid-bg + solid-bg-hover for solid variant, soft-bg + // soft-bg-hover + soft-fg for soft variant, outline-border + // outline-fg for outline variant). All 3 variants share the // same per-color cascade keyed on `data-color`. '_selected-solid-bg': { declarations: [ { value: 'var(--tag-group-primary-solid-bg)', scope: 'host' }, { value: 'var(--tag-group-secondary-solid-bg)', scope: 'color:secondary' }, { value: 'var(--tag-group-neutral-solid-bg)', scope: 'color:neutral' }, { value: 'var(--tag-group-affirm-solid-bg)', scope: 'color:affirm' }, { value: 'var(--tag-group-fulfill-solid-bg)', scope: 'color:fulfill' }, { value: 'var(--tag-group-risk-solid-bg)', scope: 'color:risk' }, { value: 'var(--tag-group-threat-solid-bg)', scope: 'color:threat' }, { value: 'var(--tag-group-loss-solid-bg)', scope: 'color:loss' } ] }, '_selected-solid-bg-hover': { declarations: [ { value: 'var(--tag-group-primary-solid-bg-hover)', scope: 'host' }, { value: 'var(--tag-group-secondary-solid-bg-hover)', scope: 'color:secondary' }, { value: 'var(--tag-group-neutral-solid-bg-hover)', scope: 'color:neutral' }, { value: 'var(--tag-group-affirm-solid-bg-hover)', scope: 'color:affirm' }, { value: 'var(--tag-group-fulfill-solid-bg-hover)', scope: 'color:fulfill' }, { value: 'var(--tag-group-risk-solid-bg-hover)', scope: 'color:risk' }, { value: 'var(--tag-group-threat-solid-bg-hover)', scope: 'color:threat' }, { value: 'var(--tag-group-loss-solid-bg-hover)', scope: 'color:loss' } ] }, '_selected-soft-bg': { declarations: [ { value: 'var(--tag-group-primary-soft-bg)', scope: 'host' }, { value: 'var(--tag-group-secondary-soft-bg)', scope: 'color:secondary' }, { value: 'var(--tag-group-neutral-soft-bg)', scope: 'color:neutral' }, { value: 'var(--tag-group-affirm-soft-bg)', scope: 'color:affirm' }, { value: 'var(--tag-group-fulfill-soft-bg)', scope: 'color:fulfill' }, { value: 'var(--tag-group-risk-soft-bg)', scope: 'color:risk' }, { value: 'var(--tag-group-threat-soft-bg)', scope: 'color:threat' }, { value: 'var(--tag-group-loss-soft-bg)', scope: 'color:loss' } ] }, '_selected-soft-bg-hover': { declarations: [ { value: 'var(--tag-group-primary-soft-bg-hover)', scope: 'host' }, { value: 'var(--tag-group-secondary-soft-bg-hover)', scope: 'color:secondary' }, { value: 'var(--tag-group-neutral-soft-bg-hover)', scope: 'color:neutral' }, { value: 'var(--tag-group-affirm-soft-bg-hover)', scope: 'color:affirm' }, { value: 'var(--tag-group-fulfill-soft-bg-hover)', scope: 'color:fulfill' }, { value: 'var(--tag-group-risk-soft-bg-hover)', scope: 'color:risk' }, { value: 'var(--tag-group-threat-soft-bg-hover)', scope: 'color:threat' }, { value: 'var(--tag-group-loss-soft-bg-hover)', scope: 'color:loss' } ] }, '_selected-soft-fg': { declarations: [ { value: 'var(--tag-group-primary-soft-fg)', scope: 'host' }, { value: 'var(--tag-group-secondary-soft-fg)', scope: 'color:secondary' }, { value: 'var(--tag-group-neutral-soft-fg)', scope: 'color:neutral' }, { value: 'var(--tag-group-affirm-soft-fg)', scope: 'color:affirm' }, { value: 'var(--tag-group-fulfill-soft-fg)', scope: 'color:fulfill' }, { value: 'var(--tag-group-risk-soft-fg)', scope: 'color:risk' }, { value: 'var(--tag-group-threat-soft-fg)', scope: 'color:threat' }, { value: 'var(--tag-group-loss-soft-fg)', scope: 'color:loss' } ] }, '_selected-outline-border': { declarations: [ { value: 'var(--tag-group-primary-outline-border)', scope: 'host' }, { value: 'var(--tag-group-secondary-outline-border)', scope: 'color:secondary' }, { value: 'var(--tag-group-neutral-outline-border)', scope: 'color:neutral' }, { value: 'var(--tag-group-affirm-outline-border)', scope: 'color:affirm' }, { value: 'var(--tag-group-fulfill-outline-border)', scope: 'color:fulfill' }, { value: 'var(--tag-group-risk-outline-border)', scope: 'color:risk' }, { value: 'var(--tag-group-threat-outline-border)', scope: 'color:threat' }, { value: 'var(--tag-group-loss-outline-border)', scope: 'color:loss' } ] }, '_selected-outline-fg': { declarations: [ { value: 'var(--tag-group-primary-outline-fg)', scope: 'host' }, { value: 'var(--tag-group-secondary-outline-fg)', scope: 'color:secondary' }, { value: 'var(--tag-group-neutral-outline-fg)', scope: 'color:neutral' }, { value: 'var(--tag-group-affirm-outline-fg)', scope: 'color:affirm' }, { value: 'var(--tag-group-fulfill-outline-fg)', scope: 'color:fulfill' }, { value: 'var(--tag-group-risk-outline-fg)', scope: 'color:risk' }, { value: 'var(--tag-group-threat-outline-fg)', scope: 'color:threat' }, { value: 'var(--tag-group-loss-outline-fg)', scope: 'color:loss' } ] } }, editable: { 'gap-xs': 'var(--space-0-5)', 'gap-sm': 'var(--space-1)', 'gap-md': 'var(--space-1-5)', 'gap-lg': 'var(--space-2)', 'gap-xl': 'var(--space-2-5)', 'control-height-xs': 'var(--control-height-xs)', 'control-height-sm': 'var(--control-height-sm)', 'control-height-md': 'var(--control-height-md)', 'control-height-lg': 'var(--control-height-lg)', 'control-height-xl': 'var(--control-height-xl)', 'control-px-xs': 'var(--space-1-5)', 'control-px-sm': 'var(--space-2)', 'control-px-md': 'var(--space-2-5)', 'control-px-lg': 'var(--space-3)', 'control-px-xl': 'var(--space-3-5)', 'font-family': 'var(--font-ui)', 'font-size-xs': 'var(--font-size-xs)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'font-size-xl': 'var(--font-size-xl)', 'line-height': 'var(--leading-ui)', color: 'var(--color-content-primary)', 'area-min-inline-size': '12ch', 'control-radius': 'var(--radius-md)', 'control-border-width': 'var(--border-width)', 'control-border': 'var(--color-border-subtle)', 'control-border-hover': 'var(--color-border-default)', 'control-bg': 'var(--color-surface-default)', 'control-shadow': 'var(--shadow-subtle)', 'focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'placeholder-color': 'var(--color-content-muted)', 'trigger-gap': 'var(--space-1)', 'trigger-px': 'var(--space-2-5)', 'trigger-radius': 'var(--radius-md)', 'trigger-border-width': 'var(--border-width)', 'trigger-border': 'var(--color-border-subtle)', 'trigger-border-hover': 'var(--color-border-default)', 'trigger-bg': 'var(--color-surface-raised)', 'trigger-bg-hover': 'var(--color-surface-overlay)', 'trigger-color': 'var(--color-content-secondary)', 'trigger-color-hover': 'var(--color-content-primary)', 'submit-color': 'var(--color-content-on-solid)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)', 'primary-solid': 'var(--color-primary-solid)', 'secondary-solid': 'var(--color-secondary-solid)', 'neutral-solid': 'var(--color-neutral-solid)', 'affirm-solid': 'var(--color-affirm-solid)', 'risk-solid': 'var(--color-risk-solid)', 'threat-solid': 'var(--color-threat-solid)', // Restored after accidental sed-removal during switch migration. 'primary-border': 'var(--color-primary-border)', 'secondary-border': 'var(--color-secondary-border)', 'neutral-border': 'var(--color-neutral-border)', 'affirm-border': 'var(--color-affirm-border)', 'risk-border': 'var(--color-risk-border)', 'threat-border': 'var(--color-threat-border)', // Private accent palette (TSC v2.1). Only solid + border + // solid-hover are consumed; track/text declared pre-TSC but unused. '_accent-solid': { declarations: [ { value: 'var(--editable-primary-solid)', scope: 'host' }, { value: 'var(--editable-secondary-solid)', scope: 'color:secondary' }, { value: 'var(--editable-neutral-solid)', scope: 'color:neutral' }, { value: 'var(--editable-affirm-solid)', scope: 'color:affirm' }, { value: 'var(--editable-risk-solid)', scope: 'color:risk' }, { value: 'var(--editable-threat-solid)', scope: 'color:threat' } ] }, '_accent-border': { declarations: [ { value: 'var(--editable-primary-border)', scope: 'host' }, { value: 'var(--editable-secondary-border)', scope: 'color:secondary' }, { value: 'var(--editable-neutral-border)', scope: 'color:neutral' }, { value: 'var(--editable-affirm-border)', scope: 'color:affirm' }, { value: 'var(--editable-risk-border)', scope: 'color:risk' }, { value: 'var(--editable-threat-border)', scope: 'color:threat' } ] }, '_accent-solid-hover': { declarations: [ { value: 'var(--color-primary-solid-hover)', scope: 'host' }, { value: 'var(--color-secondary-solid-hover)', scope: 'color:secondary' }, { value: 'var(--color-neutral-solid-hover)', scope: 'color:neutral' }, { value: 'var(--color-affirm-solid-hover)', scope: 'color:affirm' }, { value: 'var(--color-risk-solid-hover)', scope: 'color:risk' }, { value: 'var(--color-threat-solid-hover)', scope: 'color:threat' } ] } }, words: { // xs is the small-control tier (inspector fields, swatches, chips, steppers): // one step under `sm`. Replaces the ad-hoc 4px / var(--radius-2,4px) / 3px / // var(--space-1) soup the inspector used for the same thing. 'radius-xs': 'var(--radius-sm)', 'radius-sm': 'var(--radius-md)', 'radius-md': 'var(--radius-lg)', 'radius-lg': 'var(--radius-xl)', 'border-width': 'var(--border-width)', border: 'var(--color-border-subtle)', 'border-hover': 'var(--color-border-default)', bg: 'var(--color-surface-raised)', shadow: 'var(--shadow-subtle)', color: 'var(--color-content-primary)', 'font-family': 'var(--font-ui)', 'font-size-sm': 'var(--font-size-xs)', 'font-size-md': 'var(--font-size-sm)', 'font-size-lg': 'var(--font-size-md)', 'focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'invalid-border': 'var(--color-risk-border)', 'disabled-opacity': 'var(--opacity-disabled)', // Smallest doc-chrome size (breadcrumb, cell labels) — one step under `sm`. 'font-size-xs': '0.6875rem', // Wash scale: ONE canonical set of color-mix opacities for the editor's // accent/role tints (header washes, hover fills, glows, focus rings). // Replaces the ad-hoc 4/8/12/14/16/22/30/35/40/45/50 % soup with 4 steps. // They are percentages, applied to whatever base color each surface mixes. 'wash-faint': '6%', 'wash-subtle': '16%', 'wash-soft': '30%', 'wash-strong': '44%', // Per-swatch hue, set inline by the bubble/inspector color grids; the // declared default is the surface bg (an unset swatch reads as empty). swatch: 'var(--words-bg)', // The CHROME typeface (toolbar · bubble · drawer · inspector · menus). Always a // UI sans, INDEPENDENT of `font-family` (the content/reading font, which a theme // may set to serif). Keeps every control + label in one face. 'chrome-font': 'var(--font-ui)', // The inline-control tier height — every control sitting on an inspector // row (number-field, colour trigger, ToggleGroup chip) shares ONE height // so a row of mixed controls aligns. 1.75rem (28px) was the number-field's // magic height; named here and applied uniformly to kill the 26/28/36 mix. 'control-height': '1.75rem', // Fixed width for the right-hand control in an inline inspector row so the // panel's right edge reads as a clean column (number-field was 6.75rem, // colour trigger 7.5rem — a ragged edge). 7.5rem fits the 8-char alpha hex. 'field-width': '7.5rem', 'command-gap': 'var(--space-1)', 'command-radius': 'var(--radius-md)', 'command-color': 'var(--color-content-secondary)', 'command-solid-color': 'var(--color-content-on-solid)', 'placeholder-color': 'var(--color-content-muted)', 'content-color': 'var(--color-content-primary)', 'content-py-sm': 'var(--space-2-5)', 'content-py-md': 'var(--space-3)', 'content-py-lg': 'var(--space-4)', 'content-min-block-size-sm': '10rem', 'content-min-block-size-md': '13rem', 'content-min-block-size-lg': '16rem', 'content-max-block-size-sm': '50vh', 'content-max-block-size-md': '60vh', 'content-max-block-size-lg': '70vh', // Document rhythm: airier than the default UI gap so blocks read // as paragraphs in a document, not stacked form rows. Headings // derive 1.5x of this for their top margin. 'block-gap': 'var(--space-3)', 'heading-color': 'var(--color-content-primary)', 'heading-h1-font-size': 'var(--font-size-xl)', 'heading-h2-font-size': 'calc(var(--font-size-lg) + 4px)', 'heading-h3-font-size': 'var(--font-size-lg)', 'heading-font-weight': 'var(--font-weight-semibold)', 'heading-line-height': 'var(--leading-heading)', 'strong-font-weight': 'var(--font-weight-semibold)', 'code-radius': 'var(--radius-sm)', 'code-bg': 'var(--color-surface-overlay)', 'code-color': 'var(--color-content-primary)', 'code-font-family': 'var(--font-mono)', 'code-py': 'var(--space-0-5)', 'code-px': 'var(--space-1)', 'quote-px': 'var(--space-3)', 'quote-border-width': 'var(--border-width-medium)', 'quote-color': 'var(--color-content-secondary)', 'list-padding-inline-start': 'var(--space-5)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'primary-solid': 'var(--color-primary-solid)', 'primary-text': 'var(--color-primary-text)', 'secondary-text': 'var(--color-secondary-text)', 'affirm-text': 'var(--color-affirm-text)', 'fulfill-solid': 'var(--color-fulfill-solid)', 'fulfill-track': 'var(--color-fulfill-track)', 'fulfill-border': 'var(--color-fulfill-border)', 'fulfill-text': 'var(--color-fulfill-text)', 'risk-text': 'var(--color-risk-text)', 'threat-solid': 'var(--color-threat-solid)', 'threat-text': 'var(--color-threat-text)', 'loss-track': 'var(--color-loss-track)', 'loss-border': 'var(--color-loss-border)', 'loss-text': 'var(--color-loss-text)', // Restored after accidental sed-removal during switch migration. // Consumed by words.css for code/link/blockquote color cues. 'primary-border': 'var(--color-primary-border)', 'neutral-track': 'var(--color-neutral-track)', 'neutral-border': 'var(--color-neutral-border)', 'affirm-track': 'var(--color-affirm-track)', 'affirm-border': 'var(--color-affirm-border)', 'risk-track': 'var(--color-risk-track)', 'risk-border': 'var(--color-risk-border)', 'threat-track': 'var(--color-threat-track)', 'threat-border': 'var(--color-threat-border)' }, 'tags-input': { 'gap-xs': 'var(--space-1)', 'gap-sm': 'var(--space-1-5)', 'gap-md': 'var(--space-2)', 'gap-lg': 'var(--space-2-5)', 'gap-xl': 'var(--space-3)', 'control-min-height-xs': 'var(--control-height-sm)', 'control-min-height-sm': 'var(--control-height-md)', 'control-min-height-md': 'var(--control-height-lg)', 'control-min-height-lg': 'calc(var(--control-height-lg) + var(--space-2))', 'control-min-height-xl': 'calc(var(--control-height-xl) + var(--space-2))', 'control-px-xs': 'var(--space-1-5)', 'control-px-sm': 'var(--space-2)', 'control-px-md': 'var(--space-2-5)', 'control-px-lg': 'var(--space-3)', 'control-px-xl': 'var(--space-3-5)', 'control-py-xs': 'var(--space-0-5)', 'control-py-sm': 'var(--space-1)', 'control-py-md': 'var(--space-1-5)', 'control-py-lg': 'var(--space-2)', 'control-py-xl': 'var(--space-2-5)', 'item-height-xs': 'var(--control-height-xs)', 'item-height-sm': 'var(--control-height-sm)', 'item-height-md': 'var(--control-height-md)', 'item-height-lg': 'var(--control-height-lg)', 'item-height-xl': 'var(--control-height-xl)', 'item-px-xs': 'var(--space-1-5)', 'item-px-sm': 'var(--space-2)', 'item-px-md': 'var(--space-2-5)', 'item-px-lg': 'var(--space-3)', 'item-px-xl': 'var(--space-3-5)', 'font-family': 'var(--font-ui)', 'font-size-xs': 'var(--font-size-xs)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'font-size-xl': 'var(--font-size-xl)', 'line-height': 'var(--leading-ui)', color: 'var(--color-content-primary)', 'item-gap': 'var(--space-1-5)', 'control-radius': 'var(--radius-lg)', 'control-border-width': 'var(--border-width)', 'control-border': 'var(--color-border-default)', 'control-border-hover': 'var(--color-border-strong)', 'control-bg': 'var(--color-surface-default)', 'control-shadow': 'var(--shadow-subtle)', 'focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'input-min-inline-size': '8ch', 'placeholder-color': 'var(--color-content-muted)', 'item-radius': 'var(--radius-full)', 'item-border-width': 'var(--border-width)', 'item-border': 'var(--color-border-subtle)', 'item-bg': 'var(--color-surface-overlay)', 'item-color': 'var(--color-content-primary)', 'action-gap': 'var(--space-1)', 'action-px': 'var(--space-2-5)', 'action-radius': 'var(--radius-md)', 'action-border-width': 'var(--border-width)', 'action-border': 'transparent', 'action-border-hover': 'var(--color-border-subtle)', 'action-bg': 'transparent', 'action-bg-hover': 'color-mix(in srgb, currentColor 10%, transparent)', 'action-color': 'var(--color-content-secondary)', 'action-color-hover': 'var(--color-content-primary)', 'delete-size': 'var(--control-height-xs)', 'delete-radius': 'var(--radius-full)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)', 'primary-text': 'var(--color-primary-text)', 'secondary-text': 'var(--color-secondary-text)', 'neutral-text': 'var(--color-neutral-text)', 'affirm-text': 'var(--color-affirm-text)', 'fulfill-track': 'var(--color-fulfill-track)', 'fulfill-border': 'var(--color-fulfill-border)', 'fulfill-text': 'var(--color-fulfill-text)', 'risk-text': 'var(--color-risk-text)', 'threat-text': 'var(--color-threat-text)', 'loss-track': 'var(--color-loss-track)', 'loss-border': 'var(--color-loss-border)', 'loss-text': 'var(--color-loss-text)', // Restored after accidental sed-removal during switch migration. // Consumed by tags-input.css for tag chip color cues per intent. 'primary-track': 'var(--color-primary-track)', 'primary-border': 'var(--color-primary-border)', 'secondary-track': 'var(--color-secondary-track)', 'secondary-border': 'var(--color-secondary-border)', 'neutral-track': 'var(--color-neutral-track)', 'neutral-border': 'var(--color-neutral-border)', 'affirm-track': 'var(--color-affirm-track)', 'affirm-border': 'var(--color-affirm-border)', 'risk-track': 'var(--color-risk-track)', 'risk-border': 'var(--color-risk-border)', 'threat-track': 'var(--color-threat-track)', 'threat-border': 'var(--color-threat-border)', // Private accent palette (TSC v2.1). 8 colors, 3 slots (track, // border, text). `solid` was declared pre-TSC but never consumed. '_accent-track': { declarations: [ { value: 'var(--tags-input-primary-track)', scope: 'host' }, { value: 'var(--tags-input-secondary-track)', scope: 'color:secondary' }, { value: 'var(--tags-input-neutral-track)', scope: 'color:neutral' }, { value: 'var(--tags-input-affirm-track)', scope: 'color:affirm' }, { value: 'var(--tags-input-fulfill-track)', scope: 'color:fulfill' }, { value: 'var(--tags-input-risk-track)', scope: 'color:risk' }, { value: 'var(--tags-input-threat-track)', scope: 'color:threat' }, { value: 'var(--tags-input-loss-track)', scope: 'color:loss' } ] }, '_accent-border': { declarations: [ { value: 'var(--tags-input-primary-border)', scope: 'host' }, { value: 'var(--tags-input-secondary-border)', scope: 'color:secondary' }, { value: 'var(--tags-input-neutral-border)', scope: 'color:neutral' }, { value: 'var(--tags-input-affirm-border)', scope: 'color:affirm' }, { value: 'var(--tags-input-fulfill-border)', scope: 'color:fulfill' }, { value: 'var(--tags-input-risk-border)', scope: 'color:risk' }, { value: 'var(--tags-input-threat-border)', scope: 'color:threat' }, { value: 'var(--tags-input-loss-border)', scope: 'color:loss' } ] }, '_accent-text': { declarations: [ { value: 'var(--tags-input-primary-text)', scope: 'host' }, { value: 'var(--tags-input-secondary-text)', scope: 'color:secondary' }, { value: 'var(--tags-input-neutral-text)', scope: 'color:neutral' }, { value: 'var(--tags-input-affirm-text)', scope: 'color:affirm' }, { value: 'var(--tags-input-fulfill-text)', scope: 'color:fulfill' }, { value: 'var(--tags-input-risk-text)', scope: 'color:risk' }, { value: 'var(--tags-input-threat-text)', scope: 'color:threat' }, { value: 'var(--tags-input-loss-text)', scope: 'color:loss' } ] } }, stepper: { 'gap-sm': 'var(--space-3)', 'gap-md': 'var(--space-4)', 'gap-lg': 'var(--space-5)', 'indicator-size-sm': 'var(--control-height-sm)', 'indicator-size-md': 'var(--control-height-md)', 'indicator-size-lg': 'var(--control-height-lg)', 'font-family': 'var(--font-ui)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'line-height': 'var(--leading-ui)', color: 'var(--color-content-primary)', 'list-gap': 'var(--space-1)', 'item-gap': 'var(--space-2)', 'trigger-gap': 'var(--space-2)', 'trigger-px': 'var(--space-2)', 'trigger-py': 'var(--space-1)', 'trigger-radius': 'var(--radius-md)', 'trigger-border-width': 'var(--border-width)', 'trigger-color': 'var(--color-content-secondary)', 'trigger-color-hover': 'var(--color-content-primary)', 'trigger-bg-hover': 'var(--color-surface-overlay)', 'indicator-radius': 'var(--radius-full)', 'indicator-border-width': 'var(--border-width)', 'indicator-border': 'var(--color-border-default)', 'indicator-bg': 'var(--color-surface-raised)', 'indicator-color': 'var(--color-content-secondary)', 'indicator-font-weight': 'var(--font-weight-semibold)', 'complete-color': 'var(--color-content-on-solid)', 'separator-min-size': '3rem', 'separator-thickness': 'var(--border-width-medium)', 'separator-radius': 'var(--radius-full)', 'separator-bg': 'var(--color-border-subtle)', 'content-padding': 'var(--space-4)', 'content-radius': 'var(--radius-lg)', 'content-border-width': 'var(--border-width)', 'content-border': 'var(--color-border-subtle)', 'content-bg': 'var(--color-surface-raised)', 'content-shadow': 'var(--shadow-subtle)', 'nav-height': 'var(--control-height-md)', 'nav-px': 'var(--space-3)', 'nav-radius': 'var(--radius-md)', 'nav-border-width': 'var(--border-width)', 'nav-border': 'var(--color-border-subtle)', 'nav-bg': 'var(--color-surface-raised)', 'nav-color': 'var(--color-content-primary)', 'nav-hover-brightness': '1.04', 'focus-shadow': 'inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)', 'primary-solid': 'var(--color-primary-solid)', 'primary-text': 'var(--color-primary-text)', 'secondary-solid': 'var(--color-secondary-solid)', 'secondary-text': 'var(--color-secondary-text)', 'neutral-solid': 'var(--color-neutral-solid)', 'neutral-text': 'var(--color-neutral-text)', 'affirm-solid': 'var(--color-affirm-solid)', 'affirm-text': 'var(--color-affirm-text)', 'fulfill-solid': 'var(--color-fulfill-solid)', 'fulfill-track': 'var(--color-fulfill-track)', 'fulfill-border': 'var(--color-fulfill-border)', 'fulfill-text': 'var(--color-fulfill-text)', 'primary-track': 'var(--color-primary-track)', 'primary-border': 'var(--color-primary-border)', 'secondary-track': 'var(--color-secondary-track)', 'secondary-border': 'var(--color-secondary-border)', 'neutral-track': 'var(--color-neutral-track)', 'neutral-border': 'var(--color-neutral-border)', 'affirm-track': 'var(--color-affirm-track)', 'affirm-border': 'var(--color-affirm-border)', // Private accent palette (TSC v2.1). Per-color cascade in config. '_accent-solid': { declarations: [ { value: 'var(--stepper-primary-solid)', scope: 'host' }, { value: 'var(--stepper-secondary-solid)', scope: 'color:secondary' }, { value: 'var(--stepper-neutral-solid)', scope: 'color:neutral' }, { value: 'var(--stepper-affirm-solid)', scope: 'color:affirm' }, { value: 'var(--stepper-fulfill-solid)', scope: 'color:fulfill' } ] }, '_accent-track': { declarations: [ { value: 'var(--stepper-primary-track)', scope: 'host' }, { value: 'var(--stepper-secondary-track)', scope: 'color:secondary' }, { value: 'var(--stepper-neutral-track)', scope: 'color:neutral' }, { value: 'var(--stepper-affirm-track)', scope: 'color:affirm' }, { value: 'var(--stepper-fulfill-track)', scope: 'color:fulfill' } ] }, '_accent-border': { declarations: [ { value: 'var(--stepper-primary-border)', scope: 'host' }, { value: 'var(--stepper-secondary-border)', scope: 'color:secondary' }, { value: 'var(--stepper-neutral-border)', scope: 'color:neutral' }, { value: 'var(--stepper-affirm-border)', scope: 'color:affirm' }, { value: 'var(--stepper-fulfill-border)', scope: 'color:fulfill' } ] }, '_accent-text': { declarations: [ { value: 'var(--stepper-primary-text)', scope: 'host' }, { value: 'var(--stepper-secondary-text)', scope: 'color:secondary' }, { value: 'var(--stepper-neutral-text)', scope: 'color:neutral' }, { value: 'var(--stepper-affirm-text)', scope: 'color:affirm' }, { value: 'var(--stepper-fulfill-text)', scope: 'color:fulfill' } ] } }, slider: { 'track-size-xs': '3px', 'track-size-sm': '4px', 'track-size-md': '6px', 'track-size-lg': '8px', 'track-size-xl': '10px', 'thumb-size-xs': '12px', 'thumb-size-sm': '16px', 'thumb-size-md': '20px', 'thumb-size-lg': '24px', 'thumb-size-xl': '28px', 'hit-size-xs': '24px', 'hit-size-sm': '28px', 'hit-size-md': '32px', 'hit-size-lg': '36px', 'hit-size-xl': '40px', 'tick-size-xs': '3px', 'tick-size-sm': '4px', 'tick-size-md': '5px', 'tick-size-lg': '6px', 'tick-size-xl': '7px', 'min-inline-size': '12rem', 'min-block-size': '10rem', 'track-radius': 'var(--radius-full)', // The unfilled groove. `--color-neutral-track` equals the surface in the // base theme (invisible against panels), so the track uses the same // visible-track mix as Progress: a light tint of content-primary on the // surface. Reads on white AND dark, and follows the theme. 'track-bg': 'color-mix(in srgb, var(--color-content-primary) 12%, var(--color-surface-default))', 'range-bg': 'var(--color-primary-solid)', 'thumb-radius': 'var(--radius-full)', 'thumb-border-width': 'var(--border-width)', 'thumb-border': 'var(--color-border-default)', 'thumb-bg': 'var(--color-surface-default)', 'thumb-shadow': 'var(--shadow-subtle)', // Pickup lift WHILE grabbed (pointer :active): the thumb scales toward the // viewer + rides a higher shadow — the draggable-surface lift doctrine // (THEMING §14), scaled up from the surface `--motion-scale-lift` (1.02) // because a ~20px thumb needs a larger multiplier to read as a lift. 'thumb-scale-active': '1.15', 'thumb-shadow-active': 'var(--shadow-3)', 'thumb-focus-shadow': '0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color), var(--slider-thumb-shadow)', 'tick-radius': 'var(--radius-full)', 'tick-bg': 'var(--color-neutral-border)', 'tick-bg-active': 'var(--color-primary-solid)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'disabled-opacity': 'var(--opacity-disabled)' }, switch: { 'size-xs-track-width': '26px', 'size-xs-track-height': '15px', 'size-xs-thumb-size': '11px', 'size-xs-thumb-translate': '12px', 'size-sm-track-width': '32px', 'size-sm-track-height': '18px', 'size-sm-thumb-size': '14px', 'size-sm-thumb-translate': '14px', 'size-md-track-width': '38px', 'size-md-track-height': '22px', 'size-md-thumb-size': '18px', 'size-md-thumb-translate': '16px', 'size-lg-track-width': '46px', 'size-lg-track-height': '28px', 'size-lg-thumb-size': '24px', 'size-lg-thumb-translate': '18px', 'size-xl-track-width': '54px', 'size-xl-track-height': '34px', 'size-xl-thumb-size': '30px', 'size-xl-thumb-translate': '20px', 'track-radius': 'var(--radius-full)', 'track-border-width': 'var(--border-width)', 'thumb-inset': '1px', 'thumb-radius': 'var(--radius-full)', 'thumb-border-width': 'var(--border-width)', 'thumb-shadow': '0 1px 2px rgb(17 14 10 / 0.12)', 'focus-ring-offset': 'var(--focus-ring-offset)', 'focus-ring-width': 'var(--focus-ring-width)', 'focus-ring-color': 'var(--focus-ring-color)', 'focus-ring-surface': 'var(--color-surface-default)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'track-bg-off': 'var(--color-surface-overlay)', 'track-bg-off-hover': 'color-mix( in srgb, var(--color-surface-overlay) 82%, var(--color-surface-raised) )', 'track-border-off': 'var(--color-border-default)', 'track-border-off-hover': 'var(--color-border-strong)', 'track-bg-disabled': 'color-mix( in srgb, var(--color-surface-overlay) 70%, var(--color-surface-default) )', 'track-border-disabled': 'color-mix( in srgb, var(--color-border-default) 70%, var(--color-border-subtle) )', 'thumb-bg-disabled': 'color-mix( in srgb, var(--color-surface-default) 88%, var(--color-surface-raised) )', 'thumb-border-disabled': 'color-mix( in srgb, var(--color-border-subtle) 88%, var(--color-surface-overlay) )', 'disabled-opacity': 'var(--opacity-disabled)', 'thumb-bg': 'var(--color-surface-default)', 'thumb-border': 'color-mix( in srgb, var(--color-border-default) 82%, var(--color-surface-overlay) )', 'thumb-icon-color': 'var(--color-content-muted)', 'primary-solid': 'var(--color-primary-solid)', 'primary-solid-hover': 'var(--color-primary-solid-hover)', 'neutral-solid': 'var(--color-neutral-solid)', 'neutral-solid-hover': 'var(--color-neutral-solid-hover)', 'risk-solid': 'var(--color-risk-solid)', 'risk-solid-hover': 'var(--color-risk-solid-hover)', 'threat-solid': 'var(--color-threat-solid)', 'threat-solid-hover': 'var(--color-threat-solid-hover)', 'secondary-solid': 'var(--color-secondary-solid)', 'secondary-solid-hover': 'var(--color-secondary-solid-hover)', 'affirm-solid': 'var(--color-affirm-solid)', 'affirm-solid-hover': 'var(--color-affirm-solid-hover)', // Private palette (TSC v2.1). Host default = neutral, plus // per-color overrides. Migrated from manual blocks in switch.css. // Only solid/solid-hover are actively consumed; track/border // existed in the pre-TSC defaults but were never referenced. '_palette-solid': { declarations: [ { value: 'var(--switch-neutral-solid)', scope: 'host' }, { value: 'var(--switch-primary-solid)', scope: 'color:primary' }, { value: 'var(--switch-secondary-solid)', scope: 'color:secondary' }, { value: 'var(--switch-affirm-solid)', scope: 'color:affirm' }, { value: 'var(--switch-risk-solid)', scope: 'color:risk' }, { value: 'var(--switch-threat-solid)', scope: 'color:threat' } ] }, '_palette-solid-hover': { declarations: [ { value: 'var(--switch-neutral-solid-hover)', scope: 'host' }, { value: 'var(--switch-primary-solid-hover)', scope: 'color:primary' }, { value: 'var(--switch-secondary-solid-hover)', scope: 'color:secondary' }, { value: 'var(--switch-affirm-solid-hover)', scope: 'color:affirm' }, { value: 'var(--switch-risk-solid-hover)', scope: 'color:risk' }, { value: 'var(--switch-threat-solid-hover)', scope: 'color:threat' } ] } }, tabs: { 'stack-gap': 'var(--space-4)', 'line-stack-gap': 'var(--space-3)', 'provider-radius': 'var(--radius-xl)', 'provider-border-width': 'var(--border-width)', 'provider-border': 'var(--color-border-default)', 'provider-bg': 'var(--color-surface-raised)', 'surface-provider-padding': 'var(--space-3)', 'surface-provider-shadow': 'var(--shadow-subtle)', 'list-gap': 'var(--space-1)', 'list-padding': 'var(--space-1)', 'list-radius': 'var(--radius-lg)', 'list-width': '220px', 'list-bg': 'transparent', 'list-border-width': 'var(--border-width)', 'list-border': 'var(--color-border-default)', 'line-list-padding-inline-end': 'var(--space-2)', 'surface-list-bg': 'color-mix(in srgb, var(--color-surface-default) 82%, transparent)', 'pills-list-bg': 'color-mix(in srgb, var(--color-surface-default) 90%, transparent)', 'trigger-height-xs': 'var(--control-height-xs)', 'trigger-height-sm': 'var(--control-height-sm)', 'trigger-height-md': 'var(--control-height-md)', 'trigger-height-lg': 'var(--control-height-lg)', 'trigger-px-xs': 'var(--space-2-5)', 'trigger-px-sm': 'var(--space-3)', 'trigger-px-md': 'var(--space-3-5)', 'trigger-px-lg': 'var(--space-4)', 'trigger-gap-xs': 'var(--space-1)', 'trigger-gap-sm': 'var(--space-1-5)', 'trigger-gap-md': 'var(--space-2)', 'trigger-gap-lg': 'var(--space-2)', 'trigger-radius': 'var(--radius-md)', 'trigger-border-width': 'var(--border-width)', 'trigger-font-family': 'var(--font-ui)', 'trigger-font-size': 'var(--font-size-sm)', 'trigger-font-weight': 'var(--font-weight-medium)', 'trigger-line-height': 'var(--leading-ui)', 'trigger-letter-spacing': 'var(--tracking-ui)', 'trigger-color': 'var(--color-content-secondary)', 'trigger-color-hover': 'var(--color-content-primary)', 'trigger-color-active': 'var(--color-content-primary)', 'trigger-bg': 'transparent', 'trigger-bg-hover': 'color-mix( in srgb, var(--color-surface-default) 84%, transparent )', 'trigger-bg-active': 'var(--color-surface-overlay)', 'trigger-border': 'transparent', 'trigger-border-active': 'var(--color-primary-border)', 'trigger-transition-duration': 'var(--duration-fast)', 'trigger-transition-ease': 'var(--ease-default)', 'trigger-focus-ring-offset': 'var(--focus-ring-offset)', 'trigger-focus-ring-width': 'var(--focus-ring-width)', 'trigger-focus-ring-color': 'var(--focus-ring-color)', 'surface-trigger-border-active': 'color-mix( in srgb, var(--tabs-trigger-border-active) 58%, transparent )', 'pills-trigger-radius': 'var(--radius-full)', 'pills-trigger-border-active': 'color-mix( in srgb, var(--tabs-trigger-border-active) 58%, transparent )', 'pills-trigger-shadow-active': 'var(--shadow-subtle)', 'content-padding-xs': 'var(--space-3)', 'content-padding-sm': 'var(--space-4)', 'content-padding-md': 'var(--space-5)', 'content-padding-lg': 'var(--space-6)', 'content-radius': 'var(--radius-lg)', 'content-bg': 'transparent', 'content-border-width': 'var(--border-width)', 'content-border': 'transparent', 'content-color': 'var(--color-content-primary)', 'surface-content-border': 'color-mix( in srgb, var(--tabs-provider-border) 84%, transparent )', 'surface-content-bg': 'color-mix( in srgb, var(--color-surface-overlay) 92%, transparent )', 'pills-content-padding-block-start': 'var(--space-2)', 'disabled-opacity': 'var(--opacity-disabled)', 'indicator-transition-duration': 'var(--duration-normal)', 'indicator-transition-ease': 'cubic-bezier(0.32, 0.72, 0, 1)', 'indicator-line-thickness': '2px', 'scrollable-fade': '16px' }, 's-text': { 'hint-color': 'var(--color-content-secondary)', 'hint-opacity': '0.8', 'hint-margin-top': 'var(--space-1)' }, 's-text-virtual-list': { 'line-height': 'var(--leading-prose)', color: 'var(--color-content-primary)', bg: 'var(--color-surface-default)', 'border-width': 'var(--border-width)', 'border-color': 'var(--color-border-subtle)', radius: 'var(--radius-md)', 'row-px': 'var(--space-3)', 'row-border-width': 'var(--border-width)', 'row-border-color': 'var(--color-border-subtle)' }, toast: { 'toaster-z': '1200', 'toaster-inset': 'var(--space-4)', 'toaster-gap': 'var(--space-3)', 'toaster-width': '420px', 'provider-min-width': '280px', 'provider-max-width': '420px', 'provider-gap': 'var(--space-3)', 'provider-stack-gap': 'var(--space-1)', 'provider-px': 'var(--space-4)', 'provider-py': 'var(--space-3)', 'provider-border-width': 'var(--border-width)', 'provider-radius': 'var(--radius-lg)', 'provider-shadow': 'var(--depth-overlay-shadow), var(--depth-overlay-halo)', 'accent-width': 'var(--border-width-thick)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', 'closed-offset': '10px', 'closed-scale': '0.98', 'status-size': '32px', 'status-radius': 'var(--radius-full)', 'title-font-family': 'var(--font-ui)', 'title-font-size': 'var(--font-size-sm)', 'title-font-weight': 'var(--font-weight-semibold)', 'title-line-height': 'var(--leading-ui)', 'title-color': 'var(--color-content-primary)', 'message-color': 'var(--color-content-primary)', 'description-font-family': 'var(--font-ui)', 'description-font-size': 'var(--font-size-xs)', 'description-line-height': 'var(--leading-prose)', 'description-color': 'var(--color-content-secondary)', 'action-gap': 'var(--space-1)', 'action-px': 'var(--space-2)', 'action-py': 'var(--space-1)', 'action-margin-top': 'var(--space-1)', 'action-border-width': 'var(--border-width)', 'action-radius': 'var(--radius-md)', 'action-font-family': 'var(--font-ui)', 'action-font-size': 'var(--font-size-xs)', 'action-font-weight': 'var(--font-weight-medium)', 'action-line-height': 'var(--leading-ui)', 'action-focus-ring-offset': 'var(--focus-ring-offset)', 'action-focus-ring-width': 'var(--focus-ring-width)', 'action-focus-ring-color': 'var(--focus-ring-color)', 'close-size': '28px', 'close-border-width': 'var(--border-width)', 'close-radius': 'var(--radius-full)', 'close-bg': 'transparent', 'close-border': 'transparent', 'close-color': 'var(--color-content-secondary)', 'close-hover-bg': 'var(--color-surface-raised)', 'close-hover-border': 'var(--color-border-subtle)', 'close-hover-color': 'var(--color-content-primary)', 'close-focus-ring-offset': 'var(--focus-ring-offset)', 'close-focus-ring-width': 'var(--focus-ring-width)', 'close-focus-ring-color': 'var(--focus-ring-color)', 'default-surface': 'color-mix( in srgb, var(--color-surface-overlay) 92%, var(--color-neutral-track) )', 'default-border': 'color-mix( in srgb, var(--color-neutral-border) 72%, var(--color-border-default) )', 'default-accent': 'var(--color-neutral-border)', 'default-status-bg': 'var(--color-neutral-track)', 'default-status-color': 'var(--color-neutral-text)', 'default-action-color': 'var(--color-neutral-text)', 'default-action-hover-bg': 'var(--color-neutral-track)', 'affirm-surface': 'color-mix( in srgb, var(--color-surface-overlay) 90%, var(--color-affirm-track) )', 'affirm-border': 'color-mix( in srgb, var(--color-affirm-border) 70%, var(--color-border-default) )', 'affirm-accent': 'var(--color-affirm-border)', 'affirm-status-bg': 'var(--color-affirm-track)', 'affirm-status-color': 'var(--color-affirm-text)', 'affirm-action-color': 'var(--color-affirm-text)', 'affirm-action-hover-bg': 'var(--color-affirm-track)', 'fulfill-surface': 'color-mix( in srgb, var(--color-surface-overlay) 90%, var(--color-fulfill-track) )', 'fulfill-border': 'color-mix( in srgb, var(--color-fulfill-border) 70%, var(--color-border-default) )', 'fulfill-accent': 'var(--color-fulfill-border)', 'fulfill-status-bg': 'var(--color-fulfill-track)', 'fulfill-status-color': 'var(--color-fulfill-text)', 'fulfill-action-color': 'var(--color-fulfill-text)', 'fulfill-action-hover-bg': 'var(--color-fulfill-track)', 'risk-surface': 'color-mix( in srgb, var(--color-surface-overlay) 90%, var(--color-risk-track) )', 'risk-border': 'color-mix( in srgb, var(--color-risk-border) 72%, var(--color-border-default) )', 'risk-accent': 'var(--color-risk-border)', 'risk-status-bg': 'var(--color-risk-track)', 'risk-status-color': 'var(--color-risk-text)', 'risk-action-color': 'var(--color-risk-text)', 'risk-action-hover-bg': 'var(--color-risk-track)', 'threat-surface': 'color-mix( in srgb, var(--color-surface-overlay) 90%, var(--color-threat-track) )', 'threat-border': 'color-mix( in srgb, var(--color-threat-border) 72%, var(--color-border-default) )', 'threat-accent': 'var(--color-threat-border)', 'threat-status-bg': 'var(--color-threat-track)', 'threat-status-color': 'var(--color-threat-text)', 'threat-action-color': 'var(--color-threat-text)', 'threat-action-hover-bg': 'var(--color-threat-track)', 'loss-surface': 'color-mix( in srgb, var(--color-surface-overlay) 90%, var(--color-loss-track) )', 'loss-border': 'color-mix( in srgb, var(--color-loss-border) 72%, var(--color-border-default) )', 'loss-accent': 'var(--color-loss-border)', 'loss-status-bg': 'var(--color-loss-track)', 'loss-status-color': 'var(--color-loss-text)', 'loss-action-color': 'var(--color-loss-text)', 'loss-action-hover-bg': 'var(--color-loss-track)' }, toggle: { 'height-xs': 'var(--control-height-xs)', 'height-sm': 'var(--control-height-sm)', 'height-md': 'var(--control-height-md)', 'height-lg': 'var(--control-height-lg)', 'height-xl': 'var(--control-height-xl)', 'px-xs': 'var(--space-2)', 'px-sm': 'var(--space-2-5)', 'px-md': 'var(--space-3-5)', 'px-lg': 'var(--space-4-5)', 'px-xl': 'var(--space-5)', 'gap-xs': 'var(--space-1)', 'gap-sm': 'var(--space-1-5)', 'gap-md': 'var(--space-1-5)', 'gap-lg': 'var(--space-2)', 'gap-xl': 'var(--space-2-5)', 'font-family': 'var(--font-ui)', 'line-height': 'var(--leading-ui)', 'letter-spacing': 'var(--tracking-normal)', 'font-size-xs': 'var(--font-size-xs)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'font-size-xl': 'var(--font-size-xl)', 'font-weight-xs': 'var(--font-weight-medium)', 'font-weight-sm': 'var(--font-weight-medium)', 'font-weight-md': 'var(--font-weight-medium)', 'font-weight-lg': 'var(--font-weight-medium)', 'font-weight-xl': 'var(--font-weight-medium)', 'radius-xs': 'var(--radius-sm)', 'radius-sm': 'var(--radius-sm)', 'radius-md': 'var(--radius-md)', 'radius-lg': 'var(--radius-md)', 'radius-xl': 'var(--radius-md)', 'border-width': 'var(--border-width)', shadow: 'none', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)', // Per-color forwarders consumed by the palette-* cascades below. // 8 slots per color (track / element / hover / border / solid / // solid-hover / text / contrast) matching the 8 palette-* tokens // the cascades target. Missing any forwarder makes the // corresponding palette-{slot} resolve to empty for that color, // which downstream collapses any derived token consuming it // (e.g. ghost-on-bg uses palette-track). 'primary-track': 'var(--color-primary-track)', 'primary-element': 'var(--color-primary-element)', 'primary-hover': 'var(--color-primary-hover)', 'primary-border': 'var(--color-primary-border)', 'primary-solid': 'var(--color-primary-solid)', 'primary-solid-hover': 'var(--color-primary-solid-hover)', 'primary-text': 'var(--color-primary-text)', 'primary-contrast': 'var(--color-primary-contrast)', 'neutral-track': 'var(--color-neutral-track)', 'neutral-element': 'var(--color-neutral-element)', 'neutral-hover': 'var(--color-neutral-hover)', 'neutral-border': 'var(--color-neutral-border)', 'neutral-solid': 'var(--color-neutral-solid)', 'neutral-solid-hover': 'var(--color-neutral-solid-hover)', 'neutral-text': 'var(--color-neutral-text)', 'neutral-contrast': 'var(--color-neutral-contrast)', 'risk-track': 'var(--color-risk-track)', 'risk-element': 'var(--color-risk-element)', 'risk-hover': 'var(--color-risk-hover)', 'risk-border': 'var(--color-risk-border)', 'risk-solid': 'var(--color-risk-solid)', 'risk-solid-hover': 'var(--color-risk-solid-hover)', 'risk-text': 'var(--color-risk-text)', 'risk-contrast': 'var(--color-risk-contrast)', 'threat-track': 'var(--color-threat-track)', 'threat-element': 'var(--color-threat-element)', 'threat-hover': 'var(--color-threat-hover)', 'threat-border': 'var(--color-threat-border)', 'threat-solid': 'var(--color-threat-solid)', 'threat-solid-hover': 'var(--color-threat-solid-hover)', 'threat-text': 'var(--color-threat-text)', 'threat-contrast': 'var(--color-threat-contrast)', 'secondary-track': 'var(--color-secondary-track)', 'secondary-element': 'var(--color-secondary-element)', 'secondary-hover': 'var(--color-secondary-hover)', 'secondary-border': 'var(--color-secondary-border)', 'secondary-solid': 'var(--color-secondary-solid)', 'secondary-solid-hover': 'var(--color-secondary-solid-hover)', 'secondary-text': 'var(--color-secondary-text)', 'secondary-contrast': 'var(--color-secondary-contrast)', 'affirm-track': 'var(--color-affirm-track)', 'affirm-element': 'var(--color-affirm-element)', 'affirm-hover': 'var(--color-affirm-hover)', 'affirm-border': 'var(--color-affirm-border)', 'affirm-solid': 'var(--color-affirm-solid)', 'affirm-solid-hover': 'var(--color-affirm-solid-hover)', 'affirm-text': 'var(--color-affirm-text)', 'affirm-contrast': 'var(--color-affirm-contrast)', // Palette tokens: 8 custom properties, each declared 7 times. // One default declaration at scope 'host' (the neutral color), plus // one override per supported color value (scope 'color:X'). The // generator emits them as a `[data-toggle]` block (default) plus // six `[data-toggle][data-color='X']` blocks (overrides). The CSS // cascade picks the most specific match per element. // // This replaces the per-color blocks that used to live in // `toggle.css` — the config now owns the entire palette cascade. 'palette-track': { declarations: [ { value: 'var(--toggle-neutral-track)', scope: 'host' }, { value: 'var(--toggle-primary-track)', scope: 'color:primary' }, { value: 'var(--toggle-secondary-track)', scope: 'color:secondary' }, { value: 'var(--toggle-affirm-track)', scope: 'color:affirm' }, { value: 'var(--toggle-risk-track)', scope: 'color:risk' }, { value: 'var(--toggle-threat-track)', scope: 'color:threat' } ] }, 'palette-element': { declarations: [ { value: 'var(--toggle-neutral-element)', scope: 'host' }, { value: 'var(--toggle-primary-element)', scope: 'color:primary' }, { value: 'var(--toggle-secondary-element)', scope: 'color:secondary' }, { value: 'var(--toggle-affirm-element)', scope: 'color:affirm' }, { value: 'var(--toggle-risk-element)', scope: 'color:risk' }, { value: 'var(--toggle-threat-element)', scope: 'color:threat' } ] }, 'palette-hover': { declarations: [ { value: 'var(--toggle-neutral-hover)', scope: 'host' }, { value: 'var(--toggle-primary-hover)', scope: 'color:primary' }, { value: 'var(--toggle-secondary-hover)', scope: 'color:secondary' }, { value: 'var(--toggle-affirm-hover)', scope: 'color:affirm' }, { value: 'var(--toggle-risk-hover)', scope: 'color:risk' }, { value: 'var(--toggle-threat-hover)', scope: 'color:threat' } ] }, 'palette-border': { declarations: [ { value: 'var(--toggle-neutral-border)', scope: 'host' }, { value: 'var(--toggle-primary-border)', scope: 'color:primary' }, { value: 'var(--toggle-secondary-border)', scope: 'color:secondary' }, { value: 'var(--toggle-affirm-border)', scope: 'color:affirm' }, { value: 'var(--toggle-risk-border)', scope: 'color:risk' }, { value: 'var(--toggle-threat-border)', scope: 'color:threat' } ] }, 'palette-solid': { declarations: [ { value: 'var(--toggle-neutral-solid)', scope: 'host' }, { value: 'var(--toggle-primary-solid)', scope: 'color:primary' }, { value: 'var(--toggle-secondary-solid)', scope: 'color:secondary' }, { value: 'var(--toggle-affirm-solid)', scope: 'color:affirm' }, { value: 'var(--toggle-risk-solid)', scope: 'color:risk' }, { value: 'var(--toggle-threat-solid)', scope: 'color:threat' } ] }, 'palette-solid-hover': { declarations: [ { value: 'var(--toggle-neutral-solid-hover)', scope: 'host' }, { value: 'var(--toggle-primary-solid-hover)', scope: 'color:primary' }, { value: 'var(--toggle-secondary-solid-hover)', scope: 'color:secondary' }, { value: 'var(--toggle-affirm-solid-hover)', scope: 'color:affirm' }, { value: 'var(--toggle-risk-solid-hover)', scope: 'color:risk' }, { value: 'var(--toggle-threat-solid-hover)', scope: 'color:threat' } ] }, 'palette-text': { declarations: [ { value: 'var(--toggle-neutral-text)', scope: 'host' }, { value: 'var(--toggle-primary-text)', scope: 'color:primary' }, { value: 'var(--toggle-secondary-text)', scope: 'color:secondary' }, { value: 'var(--toggle-affirm-text)', scope: 'color:affirm' }, { value: 'var(--toggle-risk-text)', scope: 'color:risk' }, { value: 'var(--toggle-threat-text)', scope: 'color:threat' } ] }, 'palette-contrast': { declarations: [ { value: 'var(--toggle-neutral-contrast)', scope: 'host' }, { value: 'var(--toggle-primary-contrast)', scope: 'color:primary' }, { value: 'var(--toggle-secondary-contrast)', scope: 'color:secondary' }, { value: 'var(--toggle-affirm-contrast)', scope: 'color:affirm' }, { value: 'var(--toggle-risk-contrast)', scope: 'color:risk' }, { value: 'var(--toggle-threat-contrast)', scope: 'color:threat' } ] }, // Variant tokens that depend on the runtime `--toggle-palette-*` // values are scoped to `host` so the var() reference resolves // against the toggle element (where the palette override lives), // not against `:root` (which would freeze them at neutral). // The generator infers the `depends` set automatically from the // `var(--toggle-palette-*)` references — no manual `depends` // arrays needed. See Token Scope Contract in `lib/config-types.ts`. 'solid-bg': 'var(--color-surface-raised)', 'solid-fg': 'var(--color-content-primary)', 'solid-border': 'var(--color-border-default)', 'solid-hover-bg': { value: 'color-mix( in srgb, var(--color-surface-overlay) 68%, var(--toggle-palette-track) )', scope: 'host' }, 'solid-hover-border': { value: 'color-mix( in srgb, var(--toggle-palette-border) 45%, var(--color-border-strong) )', scope: 'host' }, 'solid-on-bg': { value: 'var(--toggle-palette-solid)', scope: 'host' }, 'solid-on-fg': { value: 'var(--toggle-palette-contrast)', scope: 'host' }, 'solid-on-border': { value: 'var(--toggle-palette-solid)', scope: 'host' }, 'solid-on-hover-bg': { value: 'var(--toggle-palette-solid-hover)', scope: 'host' }, 'solid-on-hover-border': { value: 'var(--toggle-palette-solid-hover)', scope: 'host' }, 'outline-bg': 'transparent', 'outline-fg': { value: 'var(--toggle-palette-text)', scope: 'host' }, 'outline-border': { value: 'color-mix( in srgb, var(--toggle-palette-border) 88%, var(--color-border-default) )', scope: 'host' }, 'outline-hover-bg': { value: 'var(--toggle-palette-track)', scope: 'host' }, 'outline-hover-border': { value: 'color-mix( in srgb, var(--toggle-palette-border) 100%, var(--color-border-default) )', scope: 'host' }, 'outline-on-bg': { value: 'color-mix( in srgb, var(--toggle-palette-element) 100%, var(--color-surface-raised) )', scope: 'host' }, 'outline-on-fg': { value: 'var(--toggle-palette-text)', scope: 'host' }, 'outline-on-border': { value: 'var(--toggle-palette-border)', scope: 'host' }, 'outline-on-hover-bg': { value: 'var(--toggle-palette-hover)', scope: 'host' }, 'outline-on-hover-border': { value: 'var(--toggle-palette-border)', scope: 'host' }, 'ghost-bg': 'transparent', 'ghost-fg': { value: 'var(--toggle-palette-text)', scope: 'host' }, 'ghost-border': 'transparent', 'ghost-hover-bg': { value: 'color-mix(in srgb, var(--toggle-palette-track) 72%, transparent)', scope: 'host' }, 'ghost-hover-border': 'transparent', 'ghost-on-bg': { value: 'var(--toggle-palette-track)', scope: 'host' }, 'ghost-on-fg': { value: 'var(--toggle-palette-text)', scope: 'host' }, 'ghost-on-border': { value: 'color-mix( in srgb, var(--toggle-palette-border) 72%, transparent )', scope: 'host' }, 'ghost-on-hover-bg': { value: 'var(--toggle-palette-element)', scope: 'host' }, 'ghost-on-hover-border': { value: 'color-mix( in srgb, var(--toggle-palette-border) 88%, transparent )', scope: 'host' }, 'disabled-opacity': 'var(--opacity-disabled)' }, tooltip: { 'content-z': '76', 'max-width': '22rem', 'padding-y-sm': 'var(--space-1)', 'padding-x-sm': 'var(--space-2)', 'padding-y-md': 'var(--space-1-5)', 'padding-x-md': 'var(--space-2-5)', 'padding-y-lg': 'var(--space-2)', 'padding-x-lg': 'var(--space-3)', 'font-size-sm': 'var(--font-size-sm)', 'font-size-md': 'var(--font-size-md)', 'font-size-lg': 'var(--font-size-lg)', 'font-family': 'var(--font-ui)', 'font-weight': 'var(--font-weight-regular)', 'line-height': 'var(--leading-text)', radius: 'var(--radius-md)', 'border-width': 'var(--border-width)', bg: 'var(--color-surface-overlay)', color: 'var(--color-content-primary)', border: 'color-mix( in srgb, var(--color-border-default) 84%, var(--tooltip-bg) )', shadow: 'var(--depth-overlay-shadow), var(--depth-overlay-halo)' }, // ───────────────────────────────────────────────────────────────────── // Layout primitives. Box, Flex, Grid, Float and Group expose their CSS // variables as a pass-through channel: callers push per-instance values // inline via `pushStyleVar`, and the recipe simply mirrors the CSS // fallbacks so the contract sees each var as declared. `revert-layer` // means "fall back to the underlying tag's natural rule" — the right // default for unset Box props. // ───────────────────────────────────────────────────────────────────── box: { display: 'revert-layer', position: 'revert-layer', width: 'revert-layer', 'min-width': '0', 'max-width': 'revert-layer', height: 'revert-layer', 'min-height': 'revert-layer', 'max-height': 'revert-layer', padding: 'revert-layer', 'padding-block': 'revert-layer', 'padding-inline': 'revert-layer', 'padding-top': 'revert-layer', 'padding-right': 'revert-layer', 'padding-bottom': 'revert-layer', 'padding-left': 'revert-layer', margin: 'revert-layer', 'margin-block': 'revert-layer', 'margin-inline': 'revert-layer', 'margin-top': 'revert-layer', 'margin-right': 'revert-layer', 'margin-bottom': 'revert-layer', 'margin-left': 'revert-layer', gap: 'revert-layer', top: 'revert-layer', right: 'revert-layer', bottom: 'revert-layer', left: 'revert-layer', inset: 'revert-layer', 'inset-block': 'revert-layer', 'inset-inline': 'revert-layer', overflow: 'revert-layer', 'overflow-x': 'revert-layer', 'overflow-y': 'revert-layer', flex: 'revert-layer', grow: 'revert-layer', shrink: 'revert-layer', basis: 'revert-layer', order: 'revert-layer', 'align-self': 'revert-layer', 'justify-self': 'revert-layer', 'place-self': 'revert-layer', 'grid-column': 'revert-layer', 'grid-row': 'revert-layer', 'grid-area': 'revert-layer' }, flex: { direction: 'row', align: 'stretch', justify: 'flex-start', wrap: 'nowrap', 'align-content': 'normal', 'row-gap': 'var(--box-gap, revert-layer)', 'column-gap': 'var(--box-gap, revert-layer)' }, grid: { 'template-columns': 'none', 'template-rows': 'none', 'auto-columns': 'auto', 'auto-rows': 'auto', 'auto-flow': 'row', align: 'stretch', justify: 'start', 'align-content': 'normal', 'place-items': 'revert-layer', 'place-content': 'revert-layer', gap: 'revert-layer', 'row-gap': 'var(--grid-gap, revert-layer)', 'column-gap': 'var(--grid-gap, revert-layer)' }, float: { gap: 'var(--space-3)' }, group: { 'attached-overlap': '1px' }, // ───────────────────────────────────────────────────────────────────── // Banner — announcement strip. Public surface area is intentionally // small (gap + radius); the rest of the chrome resolves from // data-intent + data-variant. // ───────────────────────────────────────────────────────────────────── banner: { gap: 'var(--space-3)', radius: '0', // Per-intent palette forwarders → Banner is retintable via // `recipes.banner.{intent}-{slot}` like every other color component // (button/badge/toggle). banner.css reads these instead of the raw // foundation `--color-{intent}-*` tokens, so a per-component recipe // override actually reaches it. (audit P1-5) 'primary-solid': 'var(--color-primary-solid)', 'primary-contrast': 'var(--color-primary-contrast)', 'primary-track': 'var(--color-primary-track)', 'primary-border': 'var(--color-primary-border)', 'primary-text': 'var(--color-primary-text)', 'secondary-solid': 'var(--color-secondary-solid)', 'secondary-contrast': 'var(--color-secondary-contrast)', 'secondary-track': 'var(--color-secondary-track)', 'secondary-border': 'var(--color-secondary-border)', 'secondary-text': 'var(--color-secondary-text)', 'neutral-solid': 'var(--color-neutral-solid)', 'neutral-contrast': 'var(--color-neutral-contrast)', 'neutral-track': 'var(--color-neutral-track)', 'neutral-border': 'var(--color-neutral-border)', 'neutral-text': 'var(--color-neutral-text)', 'affirm-solid': 'var(--color-affirm-solid)', 'affirm-contrast': 'var(--color-affirm-contrast)', 'affirm-track': 'var(--color-affirm-track)', 'affirm-border': 'var(--color-affirm-border)', 'affirm-text': 'var(--color-affirm-text)', 'fulfill-solid': 'var(--color-fulfill-solid)', 'fulfill-contrast': 'var(--color-fulfill-contrast)', 'fulfill-track': 'var(--color-fulfill-track)', 'fulfill-border': 'var(--color-fulfill-border)', 'fulfill-text': 'var(--color-fulfill-text)', 'risk-solid': 'var(--color-risk-solid)', 'risk-contrast': 'var(--color-risk-contrast)', 'risk-track': 'var(--color-risk-track)', 'risk-border': 'var(--color-risk-border)', 'risk-text': 'var(--color-risk-text)', 'threat-solid': 'var(--color-threat-solid)', 'threat-contrast': 'var(--color-threat-contrast)', 'threat-track': 'var(--color-threat-track)', 'threat-border': 'var(--color-threat-border)', 'threat-text': 'var(--color-threat-text)', 'loss-solid': 'var(--color-loss-solid)', 'loss-contrast': 'var(--color-loss-contrast)', 'loss-track': 'var(--color-loss-track)', 'loss-border': 'var(--color-loss-border)', 'loss-text': 'var(--color-loss-text)' }, // ───────────────────────────────────────────────────────────────────── // Container — full-bleed wrapper that caps `max-width` at the xl // container token by default. Callers usually push `maxWidth` via Box, // but the recipe needs the var declared. // ───────────────────────────────────────────────────────────────────── container: { 'width-xl': 'var(--layout-container-width-xl, 80rem)' }, // ───────────────────────────────────────────────────────────────────── // Section — vertical rhythm scale. Sizes map to the spacing primitives. // ───────────────────────────────────────────────────────────────────── section: { 'padding-block-sm': 'var(--space-8)', 'padding-block-md': 'var(--space-12)', 'padding-block-lg': 'var(--space-16)', 'padding-block-xl': 'calc(var(--space-16) * 1.5)' }, // ───────────────────────────────────────────────────────────────────── // Separator — purely geometric divider. // ───────────────────────────────────────────────────────────────────── separator: { thickness: 'var(--border-width)', color: 'var(--color-border-default)', 'min-length': 'var(--space-4)' }, // ───────────────────────────────────────────────────────────────────── // ToggleGroup — gap is component-owned; the color cascade modifies // Toggle's `palette-*` tokens via TSC v2.2 cross-recipe composition // (see `composition` block below). // ───────────────────────────────────────────────────────────────────── 'toggle-group': { gap: 'var(--space-1)', // TSC v2.2 — cross-recipe composition. Items inside a toggle-group // ARE toggles, so the group's `data-color` cascade must override // Toggle's PUBLIC palette tokens (owned by Toggle's recipe — not by // toggle-group) ONLY when reached through a toggle-group ancestor. // // `targetSelector: '[data-toggle-group-item]'` reaches the foreign // part inside the host's cascade. The generator emits: // [data-toggle-group][data-color='X'] [data-toggle-group-item] { // --toggle-palette-{slot}: var(--toggle-X-{slot}); // } // // Replaces the 4 hand-written CSS blocks that used to live in // `toggle-group.css` (lines 264-308 in the legacy file). composition: { toggle: { targetSelector: '[data-toggle-group-item]', tokens: { 'palette-track': { declarations: [ { value: 'var(--toggle-primary-track)', scope: 'color:primary' }, { value: 'var(--toggle-affirm-track)', scope: 'color:affirm' }, { value: 'var(--toggle-risk-track)', scope: 'color:risk' }, { value: 'var(--toggle-threat-track)', scope: 'color:threat' } ] }, 'palette-element': { declarations: [ { value: 'var(--toggle-primary-element)', scope: 'color:primary' }, { value: 'var(--toggle-affirm-element)', scope: 'color:affirm' }, { value: 'var(--toggle-risk-element)', scope: 'color:risk' }, { value: 'var(--toggle-threat-element)', scope: 'color:threat' } ] }, 'palette-hover': { declarations: [ { value: 'var(--toggle-primary-hover)', scope: 'color:primary' }, { value: 'var(--toggle-affirm-hover)', scope: 'color:affirm' }, { value: 'var(--toggle-risk-hover)', scope: 'color:risk' }, { value: 'var(--toggle-threat-hover)', scope: 'color:threat' } ] }, 'palette-border': { declarations: [ { value: 'var(--toggle-primary-border)', scope: 'color:primary' }, { value: 'var(--toggle-affirm-border)', scope: 'color:affirm' }, { value: 'var(--toggle-risk-border)', scope: 'color:risk' }, { value: 'var(--toggle-threat-border)', scope: 'color:threat' } ] }, 'palette-solid': { declarations: [ { value: 'var(--toggle-primary-solid)', scope: 'color:primary' }, { value: 'var(--toggle-affirm-solid)', scope: 'color:affirm' }, { value: 'var(--toggle-risk-solid)', scope: 'color:risk' }, { value: 'var(--toggle-threat-solid)', scope: 'color:threat' } ] }, 'palette-solid-hover': { declarations: [ { value: 'var(--toggle-primary-solid-hover)', scope: 'color:primary' }, { value: 'var(--toggle-affirm-solid-hover)', scope: 'color:affirm' }, { value: 'var(--toggle-risk-solid-hover)', scope: 'color:risk' }, { value: 'var(--toggle-threat-solid-hover)', scope: 'color:threat' } ] }, 'palette-text': { declarations: [ { value: 'var(--toggle-primary-text)', scope: 'color:primary' }, { value: 'var(--toggle-affirm-text)', scope: 'color:affirm' }, { value: 'var(--toggle-risk-text)', scope: 'color:risk' }, { value: 'var(--toggle-threat-text)', scope: 'color:threat' } ] }, 'palette-contrast': { declarations: [ { value: 'var(--toggle-primary-contrast)', scope: 'color:primary' }, { value: 'var(--toggle-affirm-contrast)', scope: 'color:affirm' }, { value: 'var(--toggle-risk-contrast)', scope: 'color:risk' }, { value: 'var(--toggle-threat-contrast)', scope: 'color:threat' } ] } } } } }, // ───────────────────────────────────────────────────────────────────── // PinInput — one-time code cells. // ───────────────────────────────────────────────────────────────────── 'pin-input': { gap: 'var(--space-2)', 'disabled-opacity': 'var(--opacity-disabled)', 'cell-size-sm': '2rem', 'cell-size-md': '2.5rem', 'cell-size-lg': '3rem', 'cell-size-xl': '3.5rem', 'cell-font-size-sm': 'var(--font-size-md)', 'cell-font-size-md': 'var(--font-size-lg)', 'cell-font-size-lg': 'var(--font-size-xl)', 'cell-font-size-xl': 'var(--font-size-xxl)', 'cell-font-weight': '500', 'cell-radius': 'var(--radius-md)', 'cell-border-width': 'var(--border-width)', 'cell-border-color': 'var(--color-border-default)', 'cell-bg': 'var(--color-surface-default)', 'cell-filled-bg': 'var(--color-primary-element)', 'cell-filled-border': 'var(--color-primary-border)', 'cell-active-border': 'var(--color-primary-solid)', 'cell-invalid-border': 'var(--color-threat-solid)' }, // ───────────────────────────────────────────────────────────────────── // ScrollArea — overlay scrollbars (macOS-style). // ───────────────────────────────────────────────────────────────────── 'scroll-area': { bg: 'transparent', radius: 'var(--radius-md)', 'scrollbar-padding': 'var(--space-0-5)', 'scrollbar-size': 'var(--space-2-5)', 'track-bg': 'color-mix(in srgb, var(--color-neutral-track) 60%, transparent)', 'track-bg-hover': 'color-mix(in srgb, var(--color-neutral-track) 84%, transparent)', 'thumb-bg': 'var(--color-content-muted)', 'thumb-bg-hover': 'var(--color-content-secondary)', 'thumb-radius': 'var(--radius-full)', 'thumb-min-size': 'var(--space-3)', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)' }, // ───────────────────────────────────────────────────────────────────── // Splitter — resizable panels with a draggable handle + grip pill. // ───────────────────────────────────────────────────────────────────── splitter: { bg: 'var(--color-surface-default)', radius: 'var(--radius-md)', 'border-width': 'var(--border-width)', 'border-color': 'var(--color-border-default)', 'disabled-opacity': 'var(--opacity-disabled)', 'panel-bg': 'transparent', 'handle-size': 'var(--space-2)', 'handle-bg': 'var(--color-border-subtle)', 'handle-bg-hover': 'var(--color-border-default)', 'handle-bg-active': 'var(--color-primary-solid)', 'grip-radius': 'var(--radius-full)', 'grip-bg': 'var(--color-content-muted)', 'grip-main': 'var(--space-4)', 'grip-cross': '2px', 'transition-duration': 'var(--duration-fast)', 'transition-ease': 'var(--ease-default)' }, // ───────────────────────────────────────────────────────────────────── // NavigationMenu — soma writes the active-trigger rect into these // indicator vars; the recipe paints the underline. // ───────────────────────────────────────────────────────────────────── // Combobox — floating result list. Same overlay micro-band as `select` / // `dropdown-menu` (the soma floating layer mirrors this computed z-index onto // the positioner wrapper, so it must stay a low, themeable value — not the // global `--z-index-*` scale). combobox: { 'content-z': '80' }, // DragDrop — the drag preview/ghost that tracks the cursor. Floats above // local content during an active drag. 'drag-drop': { 'preview-z': '99' }, 'navigation-menu': { // Inline (non-portaled) dropdown panel: stacks above normal page flow. 'content-z': '50', 'indicator-w': '0px', 'indicator-x': '0px' }, // ───────────────────────────────────────────────────────────────────── // DropdownMenu — panel chrome + item rows. Mirror tokens to context-menu. // ───────────────────────────────────────────────────────────────────── 'dropdown-menu': { // Floating menu panel stacks in the top overlay band (matches // `select` — both are click-triggered list overlays). Without this // the portaled panel inherits `z-index: auto` and any positioned // page element with a positive z-index (e.g. a selected // `[data-toggle-group-item]`, z-index 1) paints THROUGH it. 'content-z': '80', 'content-min-width': '12rem', 'content-max-height': 'min(60vh, 22rem)', 'content-padding': 'var(--space-1)', 'content-border-width': 'var(--border-width)', 'content-border-color': 'var(--color-border-default)', 'content-radius': 'var(--radius-md)', 'content-bg': 'var(--color-surface-overlay)', 'content-shadow': 'var(--depth-overlay-shadow), var(--depth-overlay-halo)', 'content-font-size': 'var(--font-size-sm)', 'item-gap': 'var(--space-2)', 'item-height': '2rem', 'item-px': 'var(--space-2)', 'item-py': 'var(--space-1)', 'item-radius': 'var(--radius-sm)', 'item-bg-hover': 'var(--color-primary-element)', 'item-fg-hover': 'var(--color-content-primary)', 'item-disabled-opacity': '0.55', 'heading-px': 'var(--space-2)', 'heading-py': 'var(--space-1)', 'heading-font-size': 'var(--font-size-xs)', 'separator-bg': 'var(--color-border-subtle)', 'separator-my': 'var(--space-1)' }, // ───────────────────────────────────────────────────────────────────── // ContextMenu — same surface as DropdownMenu, with a span Trigger. // ───────────────────────────────────────────────────────────────────── 'context-menu': { 'content-min-width': '12rem', 'content-max-height': 'min(60vh, 22rem)', 'content-padding': 'var(--space-1)', 'content-border-width': 'var(--border-width)', 'content-border-color': 'var(--color-border-default)', 'content-radius': 'var(--radius-md)', 'content-bg': 'var(--color-surface-overlay)', 'content-shadow': 'var(--depth-overlay-shadow), var(--depth-overlay-halo)', 'content-font-size': 'var(--font-size-sm)', 'item-gap': 'var(--space-2)', 'item-height': '2rem', 'item-px': 'var(--space-2)', 'item-py': 'var(--space-1)', 'item-radius': 'var(--radius-sm)', 'item-bg-hover': 'var(--color-primary-element)', 'item-fg-hover': 'var(--color-content-primary)', 'item-disabled-opacity': '0.55', 'heading-px': 'var(--space-2)', 'heading-py': 'var(--space-1)', 'heading-font-size': 'var(--font-size-xs)', 'separator-bg': 'var(--color-border-subtle)', 'separator-my': 'var(--space-1)' }, // ───────────────────────────────────────────────────────────────────── // DateRangeField — layout only; chrome inherits from date-field. // ───────────────────────────────────────────────────────────────────── 'date-range-field': { 'row-gap': 'var(--space-3)', 'separator-color': 'var(--color-content-muted)', 'separator-glyph': "'—'" }, // ───────────────────────────────────────────────────────────────────── // TimeRangeField — layout only; chrome inherits from time-field. // ───────────────────────────────────────────────────────────────────── 'time-range-field': { 'row-gap': 'var(--space-3)', 'separator-color': 'var(--color-content-muted)', 'separator-glyph': "'—'" } } as const satisfies RecipeTokenSet;