;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/breadcrumb.json b/public/r/breadcrumb.json
index 97278f9b..961716bb 100644
--- a/public/r/breadcrumb.json
+++ b/public/r/breadcrumb.json
@@ -22,7 +22,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/button-group.json b/public/r/button-group.json
index 03e45d57..f3749b4d 100644
--- a/public/r/button-group.json
+++ b/public/r/button-group.json
@@ -22,7 +22,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/button.json b/public/r/button.json
index 76e0e43d..34a51abb 100644
--- a/public/r/button.json
+++ b/public/r/button.json
@@ -21,7 +21,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/calendar.json b/public/r/calendar.json
index 43f7c756..09e4b281 100644
--- a/public/r/calendar.json
+++ b/public/r/calendar.json
@@ -23,7 +23,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/card.json b/public/r/card.json
index 8c11340c..ad737f4c 100644
--- a/public/r/card.json
+++ b/public/r/card.json
@@ -20,7 +20,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/carousel.json b/public/r/carousel.json
index f153ab79..9e562f4b 100644
--- a/public/r/carousel.json
+++ b/public/r/carousel.json
@@ -22,7 +22,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/chart.json b/public/r/chart.json
index 743c9d40..ef6d35be 100644
--- a/public/r/chart.json
+++ b/public/r/chart.json
@@ -21,7 +21,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/checkbox.json b/public/r/checkbox.json
index a0cf6223..8660709b 100644
--- a/public/r/checkbox.json
+++ b/public/r/checkbox.json
@@ -22,7 +22,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/collapsible.json b/public/r/collapsible.json
index b628cbda..0f98c89d 100644
--- a/public/r/collapsible.json
+++ b/public/r/collapsible.json
@@ -21,7 +21,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/combobox.json b/public/r/combobox.json
index 912c1b23..aca826c5 100644
--- a/public/r/combobox.json
+++ b/public/r/combobox.json
@@ -24,7 +24,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/command.json b/public/r/command.json
index fca13ebc..c3e3e1d6 100644
--- a/public/r/command.json
+++ b/public/r/command.json
@@ -24,7 +24,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/context-menu.json b/public/r/context-menu.json
index ae83cee3..12631e19 100644
--- a/public/r/context-menu.json
+++ b/public/r/context-menu.json
@@ -22,7 +22,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/cropper.json b/public/r/cropper.json
index 67cb59f2..ce08d652 100644
--- a/public/r/cropper.json
+++ b/public/r/cropper.json
@@ -24,7 +24,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/date-picker-input.json b/public/r/date-picker-input.json
index 7a277e28..5db815de 100644
--- a/public/r/date-picker-input.json
+++ b/public/r/date-picker-input.json
@@ -26,7 +26,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/dialog.json b/public/r/dialog.json
index 1ad3ad4b..f3329c8d 100644
--- a/public/r/dialog.json
+++ b/public/r/dialog.json
@@ -23,7 +23,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/drawer.json b/public/r/drawer.json
index 59ae5461..f027d7ff 100644
--- a/public/r/drawer.json
+++ b/public/r/drawer.json
@@ -21,7 +21,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/dropdown-menu.json b/public/r/dropdown-menu.json
index 2a3b3825..9e18f100 100644
--- a/public/r/dropdown-menu.json
+++ b/public/r/dropdown-menu.json
@@ -22,7 +22,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/empty-state.json b/public/r/empty-state.json
index dd3f8993..c7db9438 100644
--- a/public/r/empty-state.json
+++ b/public/r/empty-state.json
@@ -20,7 +20,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/empty.json b/public/r/empty.json
index 2bfd2ccd..a67ff0c9 100644
--- a/public/r/empty.json
+++ b/public/r/empty.json
@@ -20,7 +20,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/field.json b/public/r/field.json
index eb90b0a3..b7412224 100644
--- a/public/r/field.json
+++ b/public/r/field.json
@@ -22,7 +22,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
"type": "registry:lib",
"target": "lib/material.ts"
},
diff --git a/public/r/gradient-background.json b/public/r/gradient-background.json
index 07bd254b..22c78e38 100644
--- a/public/r/gradient-background.json
+++ b/public/r/gradient-background.json
@@ -7,12 +7,13 @@
"registryDependencies": [
"@sistine/canvas-background-utils",
"@sistine/oklch-utils",
- "@sistine/theme"
+ "@sistine/theme",
+ "@sistine/use-glass-backdrop"
],
"files": [
{
"path": "components/gradient-background.tsx",
- "content": "\"use client\";\n\nimport { backdropPalette, useBackdropTint } from \"@/lib/canvas-background-utils\";\nimport {\n bandedFrescoStops,\n type GradientGeometry,\n type GradientShape,\n type RampGradientAxis,\n rampGradient,\n readableLightnessBand,\n wrapGradient,\n} from \"@/lib/oklch-utils\";\n\n/**\n * A ramp-driven gradient wallpaper. The gradient is one of our oklch ramps (hue / lightness / tonal\n * / chroma) centered on the live glass-tint color (so it recolors with the theme) with the center as a\n * slightly wider plateau, painted as a `linear`, `radial`, or `conic` gradient. Pure CSS — crisp at any DPI.\n */\nexport function GradientBackground({\n axis = \"tonal\",\n hue,\n angle = 90,\n shape = \"linear\",\n position,\n radialShape,\n radialSize,\n}: {\n axis?: RampGradientAxis;\n /** Hue override (deg). When set, drives the gradient color instead of the live --glass-tint-h. */\n hue?: number;\n angle?: number;\n shape?: GradientShape;\n} & GradientGeometry) {\n const tint = useBackdropTint();\n // Shared with CanvasBackground: theme-tracking base + fresco palette (the `hue` prop overrides both).\n const { base, frescoColors } = backdropPalette(tint, hue);\n /* The ramps span their FULL range by design — as a wallpaper that put pure black at one edge of the\n viewport and pure white at the other, so a single solved foreground could only be readable at one\n end. Fit the ramp into the band where text over it clears APCA 60 instead. Falls back to the whole\n range if the foreground has not resolved yet (first paint, before AutoForeground runs). */\n const band = tint.fg ? readableLightnessBand(tint.fg, base) : undefined;\n const gradient = frescoColors\n ? wrapGradient(shape, bandedFrescoStops(frescoColors, band, shape), {\n angle,\n position,\n radialShape,\n radialSize,\n })\n : rampGradient(axis, base, 5, {\n angle,\n band,\n gamut: tint.p3 ? \"p3\" : \"srgb\",\n shape,\n position,\n radialShape,\n radialSize,\n });\n\n return (\n \n {/* Subtle organic highlight/shadow for depth — plain alpha layers, NO mix-blend-mode: a\n blend-mode element on the page can disable backdrop-filter RENDERING in Chromium, killing\n every glass blur above it (computed styles stay correct, paint silently fails). */}\n
\n
\n );\n}\n",
+ "content": "\"use client\";\n\nimport { APP_BG_FROST_FILTER, usePublishAppBackground } from \"@/hooks/use-glass-backdrop\";\nimport { backdropPalette, useBackdropTint } from \"@/lib/canvas-background-utils\";\nimport {\n bandedFrescoStops,\n type GradientGeometry,\n type GradientShape,\n type RampGradientAxis,\n rampGradient,\n readableLightnessBand,\n wrapGradient,\n} from \"@/lib/oklch-utils\";\n\n/**\n * A ramp-driven gradient wallpaper. The gradient is one of our oklch ramps (hue / lightness / tonal\n * / chroma) centered on the live glass-tint color (so it recolors with the theme) with the center as a\n * slightly wider plateau, painted as a `linear`, `radial`, or `conic` gradient. Pure CSS — crisp at any DPI.\n *\n * The highlight veil is a background LAYER on this element, not a child: one background string is the\n * whole backdrop, and prebaked glass (`usePublishAppBackground`) samples that same string. A child\n * overlay would frost the gradient and leave the highlights out of every bubble's slice.\n */\nconst BACKDROP_HIGHLIGHTS =\n \"radial-gradient(circle at 20% 25%, oklch(var(--shadow-highlight) / 0.1) 0%, transparent 45%), radial-gradient(circle at 80% 75%, oklch(var(--shadow-ink) / 0.1) 0%, transparent 45%)\";\n\nexport function GradientBackground({\n axis = \"tonal\",\n hue,\n angle = 90,\n shape = \"linear\",\n position,\n radialShape,\n radialSize,\n}: {\n axis?: RampGradientAxis;\n /** Hue override (deg). When set, drives the gradient color instead of the live --glass-tint-h. */\n hue?: number;\n angle?: number;\n shape?: GradientShape;\n} & GradientGeometry) {\n const tint = useBackdropTint();\n // Shared with CanvasBackground: theme-tracking base + fresco palette (the `hue` prop overrides both).\n const { base, frescoColors } = backdropPalette(tint, hue);\n /* The ramps span their FULL range by design — as a wallpaper that put pure black at one edge of the\n viewport and pure white at the other, so a single solved foreground could only be readable at one\n end. Fit the ramp into the band where text over it clears APCA 60 instead. Falls back to the whole\n range if the foreground has not resolved yet (first paint, before AutoForeground runs). */\n const band = tint.fg ? readableLightnessBand(tint.fg, base) : undefined;\n const gradient = frescoColors\n ? wrapGradient(shape, bandedFrescoStops(frescoColors, band, shape), {\n angle,\n position,\n radialShape,\n radialSize,\n })\n : rampGradient(axis, base, 5, {\n angle,\n band,\n gamut: tint.p3 ? \"p3\" : \"srgb\",\n shape,\n position,\n radialShape,\n radialSize,\n });\n\n /* First layer paints on top. Same highlights the old child overlay drew, still plain alpha — no\n mix-blend-mode, which can disable backdrop-filter rendering in Chromium. */\n const stack = `${BACKDROP_HIGHLIGHTS}, ${gradient}`;\n usePublishAppBackground(stack, APP_BG_FROST_FILTER);\n\n return (\n \n );\n}\n",
"type": "registry:component",
"target": "components/gradient-background.tsx"
}
diff --git a/public/r/hover-card.json b/public/r/hover-card.json
index fd3fc42b..a59807ce 100644
--- a/public/r/hover-card.json
+++ b/public/r/hover-card.json
@@ -21,7 +21,7 @@
},
{
"path": "lib/material.ts",
- "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow, sheen)\n * over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record = {};\n if (v.tintH !== undefined) {\n s[\"--glass-tint-h\"] = String(v.tintH);\n }\n if (v.tintC !== undefined) {\n s[\"--glass-tint-c\"] = String(v.tintC);\n }\n if (v.tintA !== undefined) {\n s[\"--glass-tint-a\"] = String(v.tintA);\n }\n if (v.opacity !== undefined) {\n s[\"--glass-opacity\"] = String(v.opacity);\n }\n if (v.blur !== undefined) {\n s[\"--srf-blur\"] = typeof v.blur === \"number\" ? `${v.blur}px` : v.blur;\n }\n if (v.solidA !== undefined) {\n s[\"--glass-solid-a\"] = String(v.solidA);\n }\n return s as React.CSSProperties;\n}\n",
+ "content": "import type * as React from \"react\";\n\n/**\n * The Sistine material system — the single source of the material → markup mapping.\n *\n * FIVE materials (glass, frosted, crystal, chakra, opaque), each a `[data-material]` token set in\n * app/theme/materials.css, composed with orthogonal AXES (border + its colour, veil, size, gradient, glow,\n * sheen, prebaked) over the one structural `glass` utility. Components call `glassMaterial()` instead of hardcoding\n * recipe class strings (check-theme bans the legacy `glass-bg`/`glass-surface`/… classes).\n *\n * Semantics:\n * - `material` UNDEFINED = adaptive: no attribute is rendered; the surface follows the page's\n * [data-glass] style (the default everywhere).\n * - An explicit material PINS the element under any page style, and — because the token set is\n * inherited custom properties — also acts as a scoped default for adaptive glass descendants\n * (a dialog set to frosted re-skins the controls inside it; pin a child back with its own material).\n * - `\"none\"` = not a glass surface: the helper returns nothing and the component supplies its plain\n * (shadcn) classes.\n */\nexport type Material = \"glass\" | \"frosted\" | \"crystal\" | \"chakra\" | \"opaque\" | \"none\";\n\nexport interface MaterialProps {\n /** undefined = adaptive (follows the page style); \"none\" = the component's plain fallback. */\n material?: Material;\n /** Material border. Three weights: `true`/\"hairline\" = the material's edge (1px; 0.5px under\n * frosted), \"rim\" = 2px, \"frame\" = 4px. */\n border?: boolean | \"hairline\" | \"rim\" | \"frame\";\n /** The border's COLOUR. \"glass\" (the default) = the material's own edge, a near-white rim at the\n * material's alpha, which reads as glass but disappears on light themes at any weight. \"ink\" = the\n * page's text colour (--foreground, at --glass-border-ink-a), a visible line wherever text is legible.\n * Pairs with `border`; under the opaque page style it also colours the uniform panel edge. */\n borderColor?: \"glass\" | \"ink\";\n /** Element-composed legibility floor for read-through overlays (menus, tooltips, toasts). */\n veil?: boolean;\n /** Blur/elevation tier — INTERNAL: set by a component's ROLE (glass-sm/-lg), not a public prop\n * (\"size\" universally means a component's dimensions; the material tier must never shadow that). */\n size?: \"sm\" | \"lg\" | \"xl\";\n /** Readability blur FLOOR (>= --glass-diffuse, default 12px) for text-dense translucent surfaces;\n * inert under opaque. \"stained\" = the dyed mode: same floor, plus true stained-glass optics — the\n * backdrop renders as TONAL SHADES of the theme hue (grayscale luminance collapse — the tint supplies the color). */\n diffuse?: boolean | \"stained\";\n /** Brand-gradient accent layered over the material. */\n gradient?: boolean;\n /** Resting glow, or the intensified \"lg\" halo. */\n glow?: boolean | \"lg\";\n /** Opt-in hover shimmer (pseudo-element based — avoid on sticky/fixed surfaces). */\n sheen?: boolean;\n /** Fake the backdrop blur from a fixed background (`--app-bg-blurred`) instead of backdrop-filter.\n * Needs `useGlassBackdrop` on the scroll container. In-flow bubbles only — the class forces\n * `position: relative` and `overflow: hidden`, and it does not combine with `sheen`. */\n prebaked?: boolean;\n}\n\n/** The PUBLIC per-instance axis props a component spreads onto its type. Excludes `size` (the material\n * blur tier is a role-internal detail — a component's own `size` prop owns that name). */\nexport type MaterialAxisProps = Omit;\n\n/** The `rest` side of splitAxisProps. Distributes over union props (DayPicker's mode union, Radix\n * ToggleGroup's single/multiple) so a discriminated union survives the split instead of collapsing\n * under a bare Omit. */\nexport type SplitAxisRest = P extends unknown ? Omit
: never;\n\n/** Split the material axis props off a component's props in ONE place — components never enumerate\n * axis keys, so a NEW axis is zero-touch: extend MaterialProps + this destructure, done. `size` is\n * role-internal (not in MaterialAxisProps) and stays in `rest` for the component's own cva. */\nexport function splitAxisProps
(\n props: P,\n): [\n MaterialAxisProps,\n SplitAxisRest
,\n] {\n const { material, border, borderColor, veil, diffuse, gradient, glow, sheen, prebaked, ...rest } = props;\n return [\n {\n material,\n border,\n borderColor,\n veil,\n diffuse,\n gradient,\n glow,\n sheen,\n prebaked,\n },\n /* The conditional (distributive) rest type can't be proven for an unresolved P — safe by\n * construction: rest is exactly P minus the axis keys. */\n rest as SplitAxisRest
,\n ];\n}\n\nexport interface MaterialAttrs {\n /** Spread-ready: undefined for adaptive and \"none\". */\n \"data-material\"?: Exclude;\n /** \"\" when material === \"none\" (caller supplies its plain classes). */\n className: string;\n}\n\nexport function glassMaterial(props: MaterialProps = {}): MaterialAttrs {\n const { material, border, borderColor, veil, size, diffuse, gradient, glow, sheen, prebaked } = props;\n if (material === \"none\") {\n return {\n className: \"\",\n };\n }\n return {\n \"data-material\": material,\n className: [\n \"glass\",\n border && \"glass-border\",\n border === \"rim\" && \"glass-border-rim\",\n border === \"frame\" && \"glass-border-frame\",\n borderColor === \"ink\" && \"glass-border-ink\",\n veil && \"glass-veil\",\n size === \"sm\" && \"glass-sm\",\n size === \"lg\" && \"glass-lg\",\n size === \"xl\" && \"glass-xl\",\n diffuse && \"glass-diffuse\",\n diffuse === \"stained\" && \"glass-stained\",\n gradient && \"glass-gradient\",\n glow === \"lg\" ? \"glass-glow-lg\" : glow ? \"glass-glow\" : false,\n sheen && \"glass-sheen\",\n prebaked && \"glass-prebaked\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The component-facing resolver: merge a component's ROLE (its default axes for a given semantic\n * variant) with explicit per-instance material/axis props, and return the surface markup — or null\n * when the element is NOT a glass surface (role === null, or material === \"none\").\n *\n * Explicit props override the role per-axis; unspecified axes fall back to the role.\n */\nexport function materialSurface(role: MaterialProps | null, props: MaterialProps): MaterialAttrs | null {\n if (props.material === \"none\" || role === null) {\n return null;\n }\n return glassMaterial({\n material: props.material,\n border: props.border ?? role.border,\n borderColor: props.borderColor ?? role.borderColor,\n veil: props.veil ?? role.veil,\n size: props.size ?? role.size,\n diffuse: props.diffuse ?? role.diffuse,\n gradient: props.gradient ?? role.gradient,\n glow: props.glow ?? role.glow,\n sheen: props.sheen ?? role.sheen,\n prebaked: props.prebaked ?? role.prebaked,\n });\n}\n\n/**\n * Typed per-element knobs → CSS custom properties ONLY (the cascade-native successor to the old\n * `glass={{…}}` inline-style prop). Everything routes through the token system, so nothing here can\n * fight a material, a page style, or the theme.\n *\n * The tint* keys recolor engine-composed tokens, which re-resolve at grouped declarations — pair\n * them with a `data-glass-tint` attribute on the same element so the engine re-composes there.\n */\nexport interface GlassVars {\n /** → --glass-tint-h (surface hue) */\n tintH?: number;\n /** → --glass-tint-c (surface chroma — the colorfulness master) */\n tintC?: number;\n /** → --glass-tint-a (tint film alpha) */\n tintA?: number;\n /** → --glass-opacity (0..1 solidify dial; element-composed in `glass`) */\n opacity?: number;\n /** → --srf-blur (number → px; glass material only) */\n blur?: number | string;\n /** → --glass-solid-a (veil floor alpha; element-composed in `glass-veil`) */\n solidA?: number;\n}\n\nexport function glassVars(v: GlassVars = {}): React.CSSProperties {\n const s: Record