{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "glass-tooltip",
  "title": "Glass Tooltip",
  "description": "A small glass label that appears on hover and keyboard focus.",
  "dependencies": [
    "clsx",
    "@radix-ui/react-tooltip"
  ],
  "files": [
    {
      "path": "registry/glassyui/glass-provider.tsx",
      "content": "'use client';\n\nimport './styles/liquid.css';\n\nimport {\n  createContext,\n  useCallback,\n  useContext,\n  useEffect,\n  useMemo,\n  useState,\n  useSyncExternalStore,\n  type ReactNode,\n} from 'react';\nimport {\n  applyPreferences,\n  computeAutomaticSafeguards,\n  GLASS_THICKNESS,\n  loadPreferences,\n  persistPreferences,\n  type GlassyUiPreferences,\n  type GlassyUiTheme,\n} from './lib/preferences';\n\ntype PreferenceState = Required<GlassyUiPreferences>;\n\ntype SystemPreferenceState = Pick<\n  PreferenceState,\n  'theme' | 'quality' | 'reduceMotion' | 'reduceTransparency'\n>;\n\ntype PreferenceSources = {\n  explicit: GlassyUiPreferences;\n  system: SystemPreferenceState;\n};\n\ntype PreferenceContextValue = {\n  preferences: PreferenceState;\n  setPreferences: (prefs: Partial<GlassyUiPreferences>) => void;\n};\n\nconst DEFAULT_STATE: PreferenceState = {\n  theme: 'dark',\n  mode: 'clear',\n  reduceTransparency: false,\n  reduceMotion: false,\n  quality: 'high',\n  thickness: GLASS_THICKNESS.regular,\n};\n\nconst SERVER_SOURCES: PreferenceSources = {\n  explicit: {},\n  system: {\n    theme: DEFAULT_STATE.theme,\n    quality: DEFAULT_STATE.quality,\n    reduceMotion: DEFAULT_STATE.reduceMotion,\n    reduceTransparency: DEFAULT_STATE.reduceTransparency,\n  },\n};\n\nconst subscribeToHydration = () => () => {};\n\nconst transparencyQuery = '(prefers-reduced-transparency: reduce)';\n\nfunction subscribeToSystemTransparency(onChange: () => void) {\n  const query = window.matchMedia(transparencyQuery);\n  query.addEventListener('change', onChange);\n\n  return () => query.removeEventListener('change', onChange);\n}\n\nconst readSystemTransparency = () => window.matchMedia(transparencyQuery).matches;\n\nconst readServerTransparency = () => DEFAULT_STATE.reduceTransparency;\n\nconst PreferencesContext = createContext<PreferenceContextValue | null>(null);\n\nfunction warnPreferenceFailure(message: string, cause: unknown) {\n  console.warn(message, cause);\n}\n\nfunction mergePreferences(\n  base: PreferenceState,\n  next: Partial<GlassyUiPreferences>,\n): PreferenceState {\n  return {\n    ...base,\n    ...next,\n  };\n}\n\nfunction readSystemPreferences(): SystemPreferenceState {\n  if (typeof window === 'undefined') {\n    return {\n      theme: DEFAULT_STATE.theme,\n      quality: DEFAULT_STATE.quality,\n      reduceMotion: DEFAULT_STATE.reduceMotion,\n      reduceTransparency: DEFAULT_STATE.reduceTransparency,\n    };\n  }\n\n  const automatic = computeAutomaticSafeguards();\n\n  const systemPrefersLight =\n    window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches;\n\n  return {\n    theme: systemPrefersLight ? 'light' : DEFAULT_STATE.theme,\n    quality: automatic.quality,\n    reduceMotion: automatic.reduceMotion,\n    reduceTransparency: automatic.reduceTransparency,\n  };\n}\n\nfunction readInitialPreferenceSources(): PreferenceSources {\n  if (typeof window === 'undefined') {\n    return { explicit: {}, system: readSystemPreferences() };\n  }\n\n  let explicit: GlassyUiPreferences = {};\n\n  try {\n    explicit = loadPreferences();\n  } catch (error) {\n    warnPreferenceFailure('Failed to load Glassy UI preferences', error);\n  }\n\n  return { explicit, system: readSystemPreferences() };\n}\n\n/**\n * Holds the glass preferences and applies them to the document. `defaultTheme` is the theme a\n * visitor sees until they choose one, whatever their system prefers; leave it out to follow the\n * system setting.\n */\nexport function GlassProvider({\n  children,\n  defaultTheme,\n}: {\n  children: ReactNode;\n  defaultTheme?: GlassyUiTheme;\n}) {\n  const [sources, setSources] = useState<PreferenceSources>(readInitialPreferenceSources);\n\n  const hydrated = useSyncExternalStore(\n    subscribeToHydration,\n    () => true,\n    () => false,\n  );\n\n  const activeSources = hydrated ? sources : SERVER_SOURCES;\n\n  const preferences = useMemo(\n    () =>\n      mergePreferences(\n        mergePreferences(\n          DEFAULT_STATE,\n          defaultTheme ? { ...activeSources.system, theme: defaultTheme } : activeSources.system,\n        ),\n        activeSources.explicit,\n      ),\n    [activeSources, defaultTheme],\n  );\n\n  useEffect(() => {\n    if (!hydrated || typeof document === 'undefined') {\n      return;\n    }\n\n    applyPreferences(document, preferences);\n  }, [hydrated, preferences]);\n\n  const update = useCallback((next: Partial<GlassyUiPreferences>) => {\n    // The document changes before React renders whatever asked for the change, so a\n    // control's own flip runs under the setting it lands in. Turning Reduce Motion off\n    // from its own switch then animates instead of snapping under the old setting.\n    if (typeof document !== 'undefined') {\n      applyPreferences(document, next);\n    }\n\n    setSources((previous) => {\n      const explicit = { ...previous.explicit, ...next };\n\n      if (typeof window !== 'undefined') {\n        try {\n          persistPreferences(explicit);\n        } catch (error) {\n          warnPreferenceFailure('Failed to persist Glassy UI preferences', error);\n        }\n      }\n\n      return { ...previous, explicit };\n    });\n  }, []);\n\n  useEffect(() => {\n    if (typeof window === 'undefined') {\n      return;\n    }\n\n    const queries = [\n      '(prefers-color-scheme: light)',\n      '(prefers-reduced-motion: reduce)',\n      '(prefers-reduced-transparency: reduce)',\n      '(pointer: coarse)',\n    ].map((query) => window.matchMedia(query));\n\n    const handler = () => {\n      setSources((previous) => ({ ...previous, system: readSystemPreferences() }));\n    };\n\n    queries.forEach((query) => query.addEventListener('change', handler));\n\n    return () => queries.forEach((query) => query.removeEventListener('change', handler));\n  }, []);\n\n  const value = useMemo<PreferenceContextValue>(\n    () => ({\n      preferences,\n      setPreferences: update,\n    }),\n    [preferences, update],\n  );\n\n  return <PreferencesContext.Provider value={value}>{children}</PreferencesContext.Provider>;\n}\n\nexport const PreferencesProvider = GlassProvider;\n\nexport function useOptionalPreferences() {\n  const context = useContext(PreferencesContext);\n\n  const reduceTransparency = useSyncExternalStore(\n    context ? subscribeToHydration : subscribeToSystemTransparency,\n    context ? () => context.preferences.reduceTransparency : readSystemTransparency,\n    readServerTransparency,\n  );\n\n  return (\n    context ?? {\n      preferences: { ...DEFAULT_STATE, reduceTransparency },\n      setPreferences: () => {},\n    }\n  );\n}\n\nexport function usePreferences() {\n  const context = useContext(PreferencesContext);\n\n  if (!context) {\n    throw new Error('usePreferences must be used within PreferencesProvider');\n  }\n\n  return context;\n}\n",
      "type": "registry:ui",
      "target": "components/glassyui/glass-provider.tsx"
    },
    {
      "path": "registry/glassyui/liquid-filters.tsx",
      "content": "export function LiquidFilters() {\n  return (\n    <svg\n      aria-hidden=\"true\"\n      focusable=\"false\"\n      className=\"lg-svg-filters\"\n      style={{ position: 'absolute', width: 0, height: 0, overflow: 'hidden' }}\n    >\n      <defs>\n        {/*\n          Simplified high-performance refraction filter.\n          Uses userSpaceOnUse for pixel-accurate displacement.\n          Chromatic aberration via RGB channel separation + offset.\n        */}\n        <filter\n          id=\"lg-liquid-refraction\"\n          x=\"-10%\"\n          y=\"-10%\"\n          width=\"120%\"\n          height=\"120%\"\n          filterUnits=\"objectBoundingBox\"\n          primitiveUnits=\"userSpaceOnUse\"\n          colorInterpolationFilters=\"sRGB\"\n        >\n          {/* Load bowl-shaped displacement map */}\n          <feImage href={DISPLACEMENT_MAP} preserveAspectRatio=\"none\" result=\"dispMap\" />\n\n          {/* Blur the background for glass diffusion - single pass for performance */}\n          <feGaussianBlur in=\"BackgroundImage\" stdDeviation=\"12\" result=\"blurred\" />\n\n          {/* Apply displacement based on bowl map */}\n          <feDisplacementMap\n            in=\"blurred\"\n            in2=\"dispMap\"\n            scale=\"20\"\n            xChannelSelector=\"R\"\n            yChannelSelector=\"G\"\n            result=\"displaced\"\n          />\n\n          {/* Chromatic aberration: separate RGB channels */}\n          <feColorMatrix\n            in=\"displaced\"\n            type=\"matrix\"\n            values=\"1 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 1 0\"\n            result=\"redChannel\"\n          />\n          <feColorMatrix\n            in=\"displaced\"\n            type=\"matrix\"\n            values=\"0 0 0 0 0  0 1 0 0 0  0 0 0 0 0  0 0 0 1 0\"\n            result=\"greenChannel\"\n          />\n          <feColorMatrix\n            in=\"displaced\"\n            type=\"matrix\"\n            values=\"0 0 0 0 0  0 0 0 0 0  0 0 1 0 0  0 0 0 1 0\"\n            result=\"blueChannel\"\n          />\n\n          {/* Offset channels for chromatic dispersion (Cauchy: blue bends more) */}\n          <feOffset in=\"redChannel\" dx=\"-1.5\" dy=\"-1\" result=\"redShift\" />\n          <feOffset in=\"greenChannel\" dx=\"0\" dy=\"0\" result=\"greenShift\" />\n          <feOffset in=\"blueChannel\" dx=\"1.5\" dy=\"1\" result=\"blueShift\" />\n\n          {/* Recombine RGB channels */}\n          <feBlend in=\"redShift\" in2=\"greenShift\" mode=\"screen\" result=\"rgMix\" />\n          <feBlend in=\"rgMix\" in2=\"blueShift\" mode=\"screen\" result=\"chromatic\" />\n\n          {/* Boost saturation slightly for vibrancy */}\n          <feColorMatrix in=\"chromatic\" type=\"saturate\" values=\"1.15\" result=\"refracted\" />\n\n          {/* Composite with source (glass tint overlay) */}\n          <feBlend in=\"SourceGraphic\" in2=\"refracted\" mode=\"normal\" />\n        </filter>\n\n        {/* Light mode specific filter with stronger chromatic aberration */}\n        <filter\n          id=\"lg-liquid-refraction-light\"\n          x=\"-10%\"\n          y=\"-10%\"\n          width=\"120%\"\n          height=\"120%\"\n          filterUnits=\"objectBoundingBox\"\n          primitiveUnits=\"userSpaceOnUse\"\n          colorInterpolationFilters=\"sRGB\"\n        >\n          <feImage href={DISPLACEMENT_MAP} preserveAspectRatio=\"none\" result=\"dispMap\" />\n\n          {/* Less blur in light mode for sharper refractions */}\n          <feGaussianBlur in=\"BackgroundImage\" stdDeviation=\"8\" result=\"blurred\" />\n\n          <feDisplacementMap\n            in=\"blurred\"\n            in2=\"dispMap\"\n            scale=\"25\"\n            xChannelSelector=\"R\"\n            yChannelSelector=\"G\"\n            result=\"displaced\"\n          />\n\n          {/* Stronger chromatic separation for light mode */}\n          <feColorMatrix\n            in=\"displaced\"\n            type=\"matrix\"\n            values=\"1 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 1 0\"\n            result=\"redChannel\"\n          />\n          <feColorMatrix\n            in=\"displaced\"\n            type=\"matrix\"\n            values=\"0 0 0 0 0  0 1 0 0 0  0 0 0 0 0  0 0 0 1 0\"\n            result=\"greenChannel\"\n          />\n          <feColorMatrix\n            in=\"displaced\"\n            type=\"matrix\"\n            values=\"0 0 0 0 0  0 0 0 0 0  0 0 1 0 0  0 0 0 1 0\"\n            result=\"blueChannel\"\n          />\n\n          {/* Stronger offsets for visible chromatic aberration */}\n          <feOffset in=\"redChannel\" dx=\"-2\" dy=\"-1.5\" result=\"redShift\" />\n          <feOffset in=\"greenChannel\" dx=\"0\" dy=\"0\" result=\"greenShift\" />\n          <feOffset in=\"blueChannel\" dx=\"2\" dy=\"1.5\" result=\"blueShift\" />\n\n          <feBlend in=\"redShift\" in2=\"greenShift\" mode=\"screen\" result=\"rgMix\" />\n          <feBlend in=\"rgMix\" in2=\"blueShift\" mode=\"screen\" result=\"chromatic\" />\n\n          <feColorMatrix in=\"chromatic\" type=\"saturate\" values=\"1.2\" result=\"refracted\" />\n\n          <feBlend in=\"SourceGraphic\" in2=\"refracted\" mode=\"normal\" />\n        </filter>\n\n        {/* Lightweight turbulence-based distortion for CSS filter usage */}\n        <filter\n          id=\"lg-glass-distort\"\n          x=\"-20%\"\n          y=\"-20%\"\n          width=\"140%\"\n          height=\"140%\"\n          colorInterpolationFilters=\"sRGB\"\n          filterUnits=\"objectBoundingBox\"\n        >\n          <feTurbulence\n            type=\"fractalNoise\"\n            baseFrequency=\"0.012 0.018\"\n            numOctaves=\"2\"\n            seed=\"9\"\n            result=\"noise\"\n          />\n          <feGaussianBlur in=\"noise\" stdDeviation=\"1.8\" result=\"softNoise\" />\n          <feDisplacementMap\n            in=\"SourceGraphic\"\n            in2=\"softNoise\"\n            scale=\"18\"\n            xChannelSelector=\"R\"\n            yChannelSelector=\"G\"\n          />\n        </filter>\n\n        {/* Switcher-style displacement map (used with backdrop-filter) */}\n        <filter\n          id=\"lg-switcher\"\n          x=\"0%\"\n          y=\"0%\"\n          width=\"100%\"\n          height=\"100%\"\n          filterUnits=\"objectBoundingBox\"\n          primitiveUnits=\"objectBoundingBox\"\n          colorInterpolationFilters=\"sRGB\"\n        >\n          {/* Static packed normal-ish map to bend the backdrop */}\n          <feImage href={SWITCHER_MAP} result=\"map\" preserveAspectRatio=\"none\" />\n\n          {/* Mild blur of the backdrop for diffusion */}\n          <feGaussianBlur in=\"SourceGraphic\" stdDeviation=\"0.08\" result=\"blur\" />\n\n          <feDisplacementMap\n            in=\"blur\"\n            in2=\"map\"\n            scale=\"20\"\n            xChannelSelector=\"R\"\n            yChannelSelector=\"G\"\n          />\n        </filter>\n      </defs>\n    </svg>\n  );\n}\n\nconst DISPLACEMENT_MAP =\n  'data:image/png;base64,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';\n\nconst SWITCHER_MAP =\n  'data:image/webp;base64,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';\n",
      "type": "registry:ui",
      "target": "components/glassyui/liquid-filters.tsx"
    },
    {
      "path": "registry/glassyui/lib/preferences.ts",
      "content": "export type GlassyUiMode = 'clear' | 'tinted';\n\nexport type GlassyUiQuality = 'low' | 'medium' | 'high';\n\nexport type GlassyUiTheme = 'light' | 'dark';\n\nexport interface GlassyUiPreferences {\n  theme?: GlassyUiTheme;\n  mode?: GlassyUiMode;\n  reduceTransparency?: boolean;\n  reduceMotion?: boolean;\n  quality?: GlassyUiQuality;\n  /**\n   * How thick the glass is, as a multiple of regular: its rim widens, bends the\n   * backdrop further and splits more colour. Kept between 0.25 and 2.\n   */\n  thickness?: number;\n}\n\n/** The range of the thickness preference. 1 is regular glass. */\nexport const GLASS_THICKNESS = { min: 0.25, max: 2, regular: 1 } as const;\n\nconst THICKNESS_PROPERTY = '--lg-glass-thickness';\n\nfunction clampThickness(value: number) {\n  return Math.min(Math.max(value, GLASS_THICKNESS.min), GLASS_THICKNESS.max);\n}\n\ntype NavigatorWithMemory = Navigator & { deviceMemory?: number };\n\nconst DATA_KEYS = {\n  theme: 'data-lg-theme',\n  mode: 'data-lg-mode',\n  reduceTransparency: 'data-lg-reduce-transparency',\n  reduceMotion: 'data-lg-reduce-motion',\n  quality: 'data-lg-quality',\n} as const;\n\nconst STORAGE_KEY = 'glassy-ui-preferences';\n\nconst THEMES = ['light', 'dark'] as const satisfies readonly GlassyUiTheme[];\n\nconst MODES = ['clear', 'tinted'] as const satisfies readonly GlassyUiMode[];\n\nconst QUALITIES = ['low', 'medium', 'high'] as const satisfies readonly GlassyUiQuality[];\n\nconst FLAGS = [true, false] as const;\n\nexport function applyPreferences(target: Document, prefs: GlassyUiPreferences) {\n  const root = target.documentElement;\n\n  if (prefs.theme) {\n    root.setAttribute(DATA_KEYS.theme, prefs.theme);\n  }\n\n  if (prefs.mode) {\n    root.setAttribute(DATA_KEYS.mode, prefs.mode);\n  }\n\n  if (prefs.reduceTransparency !== undefined) {\n    root.setAttribute(DATA_KEYS.reduceTransparency, prefs.reduceTransparency ? '1' : '0');\n  }\n\n  if (prefs.reduceMotion !== undefined) {\n    root.setAttribute(DATA_KEYS.reduceMotion, prefs.reduceMotion ? '1' : '0');\n  }\n\n  if (prefs.quality) {\n    root.setAttribute(DATA_KEYS.quality, prefs.quality);\n  }\n\n  if (prefs.thickness !== undefined) {\n    root.style.setProperty(THICKNESS_PROPERTY, String(clampThickness(prefs.thickness)));\n  }\n}\n\nexport function readPreferences(source: Document): Required<GlassyUiPreferences> {\n  const root = source.documentElement;\n\n  const readOption = <T extends string>(name: string, options: readonly T[], fallback: T) => {\n    const value = root.getAttribute(name);\n\n    return options.find((option) => option === value) ?? fallback;\n  };\n\n  return {\n    theme: readOption(DATA_KEYS.theme, THEMES, 'dark'),\n    mode: readOption(DATA_KEYS.mode, MODES, 'clear'),\n    reduceTransparency: root.getAttribute(DATA_KEYS.reduceTransparency) === '1',\n    reduceMotion: root.getAttribute(DATA_KEYS.reduceMotion) === '1',\n    quality: readOption(DATA_KEYS.quality, QUALITIES, 'high'),\n    thickness: clampThickness(\n      Number.parseFloat(root.style.getPropertyValue(THICKNESS_PROPERTY)) || GLASS_THICKNESS.regular,\n    ),\n  };\n}\n\nexport function persistPreferences(\n  prefs: GlassyUiPreferences,\n  storage: Storage = window.localStorage,\n) {\n  const current = loadPreferences(storage);\n  const merged = { ...current, ...prefs } satisfies GlassyUiPreferences;\n  storage.setItem(STORAGE_KEY, JSON.stringify(merged));\n}\n\nexport function loadPreferences(\n  storage: Pick<Storage, 'getItem'> = window.localStorage,\n): GlassyUiPreferences {\n  const raw = storage.getItem(STORAGE_KEY);\n\n  if (!raw) {\n    return {};\n  }\n\n  try {\n    return decodePreferences(raw);\n  } catch (error) {\n    console.warn('Failed to parse Glassy UI preferences', error);\n\n    return {};\n  }\n}\n\n/** Keep the stored fields that hold a known value; drop stale or malformed entries. */\nfunction decodePreferences(raw: string): GlassyUiPreferences {\n  const stored: ReadonlyMap<string, unknown> = new Map(Object.entries(JSON.parse(raw)));\n  const prefs: GlassyUiPreferences = {};\n\n  const keep = <K extends keyof GlassyUiPreferences>(\n    key: K,\n    options: readonly NonNullable<GlassyUiPreferences[K]>[],\n  ) => {\n    const value = options.find((option) => option === stored.get(key));\n\n    if (value !== undefined) {\n      prefs[key] = value;\n    }\n  };\n\n  keep('theme', THEMES);\n  keep('mode', MODES);\n  keep('reduceTransparency', FLAGS);\n  keep('reduceMotion', FLAGS);\n  keep('quality', QUALITIES);\n\n  const thickness = Number(stored.get('thickness'));\n\n  if (Number.isFinite(thickness) && stored.has('thickness')) {\n    prefs.thickness = clampThickness(thickness);\n  }\n\n  return prefs;\n}\n\nexport { STORAGE_KEY as PREFERENCE_STORAGE_KEY };\n\nexport function computeAutomaticSafeguards(): Required<\n  Pick<GlassyUiPreferences, 'quality' | 'reduceMotion' | 'reduceTransparency'>\n> {\n  if (typeof window === 'undefined') {\n    return { quality: 'high', reduceMotion: false, reduceTransparency: false };\n  }\n\n  const supportsMatchMedia = 'matchMedia' in window;\n  const coarsePointer = supportsMatchMedia && window.matchMedia('(pointer: coarse)').matches;\n\n  const prefersReducedMotion =\n    supportsMatchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n  const prefersReducedTransparency =\n    supportsMatchMedia && window.matchMedia('(prefers-reduced-transparency: reduce)').matches;\n\n  // SAFETY: deviceMemory is a number where the Device Memory API exists and absent elsewhere.\n  const deviceMemory = (navigator as NavigatorWithMemory).deviceMemory;\n  const lowMemory = deviceMemory !== undefined && deviceMemory <= 4;\n\n  // Device heuristics only lower rendering quality. Opaque surfaces and stopped\n  // motion stay reserved for the user's own accessibility settings.\n  const quality: GlassyUiQuality =\n    prefersReducedTransparency || lowMemory\n      ? 'low'\n      : coarsePointer || prefersReducedMotion\n        ? 'medium'\n        : 'high';\n\n  return {\n    quality,\n    reduceMotion: Boolean(prefersReducedMotion),\n    reduceTransparency: Boolean(prefersReducedTransparency),\n  };\n}\n",
      "type": "registry:lib",
      "target": "components/glassyui/lib/preferences.ts"
    },
    {
      "path": "registry/glassyui/styles/liquid.css",
      "content": "/* Glassy UI styles live in the components layer, below Tailwind utilities, so\n   a className such as rounded-xl or p-8 overrides the library default. These\n   statements repeat Tailwind 4's own layer order, so it holds even when this\n   file loads before Tailwind. */\n@layer properties;\n@layer theme, base, components, utilities;\n\n@property --lg-fresnel {\n  syntax: '<number>';\n  initial-value: 0;\n  inherits: true;\n}\n\n@property --lg-specular {\n  syntax: '<number>';\n  initial-value: 0;\n  inherits: true;\n}\n\n@property --lg-refraction-scale {\n  syntax: '<number>';\n  initial-value: 0;\n  inherits: true;\n}\n\n@property --lg-refraction-blur {\n  syntax: '<number>';\n  initial-value: 0;\n  inherits: true;\n}\n\n@property --lg-refraction-scale-a {\n  syntax: '<number>';\n  initial-value: 0;\n  inherits: true;\n}\n\n@property --lg-refraction-scale-b {\n  syntax: '<number>';\n  initial-value: 0;\n  inherits: true;\n}\n\n@property --lg-refraction-blur-a {\n  syntax: '<number>';\n  initial-value: 0;\n  inherits: true;\n}\n\n@property --lg-refraction-blur-b {\n  syntax: '<number>';\n  initial-value: 0;\n  inherits: true;\n}\n\n@property --lg-refraction-dispersion {\n  syntax: '<number>';\n  initial-value: 0;\n  inherits: true;\n}\n\n@property --lg-rim-width-scale {\n  syntax: '<number>';\n  initial-value: 1;\n  inherits: true;\n}\n\n@property --lg-highlight-strength {\n  syntax: '<number>';\n  initial-value: 0;\n  inherits: true;\n}\n\n@property --lg-rim-micro-mask {\n  syntax: '<number>';\n  initial-value: 1;\n  inherits: true;\n}\n\n@property --lg-rim-corner-mask {\n  syntax: '<number>';\n  initial-value: 1;\n  inherits: true;\n}\n\n@property --lg-debug-micro-scale {\n  syntax: '<number>';\n  initial-value: 1;\n  inherits: true;\n}\n\n@property --lg-debug-corner-scale {\n  syntax: '<number>';\n  initial-value: 1;\n  inherits: true;\n}\n\n@property --lg-debug-ca-scale {\n  syntax: '<number>';\n  initial-value: 1;\n  inherits: true;\n}\n\n@property --lg-debug-ca-offset-scale {\n  syntax: '<number>';\n  initial-value: 1;\n  inherits: true;\n}\n\n@property --lg-debug-rim-thickness {\n  syntax: '<number>';\n  initial-value: 1;\n  inherits: true;\n}\n\n@property --lg-debug-rim-alpha-scale {\n  syntax: '<number>';\n  initial-value: 1;\n  inherits: true;\n}\n\n@property --lg-debug-tangent-scale {\n  syntax: '<number>';\n  initial-value: 1;\n  inherits: true;\n}\n\n@property --lg-debug-highlight-scale {\n  syntax: '<number>';\n  initial-value: 1;\n  inherits: true;\n}\n\n@property --lg-filter-scale {\n  syntax: '<number>';\n  initial-value: 0.98;\n  inherits: true;\n}\n\n@property --lg-bg {\n  syntax: '<color>';\n  initial-value: #1c1c1e;\n  inherits: true;\n}\n\n@property --lg-panel {\n  syntax: '<color>';\n  initial-value: rgba(255, 255, 255, 0.04);\n  inherits: true;\n}\n\n@property --lg-press {\n  syntax: '<number>';\n  initial-value: 0;\n  inherits: true;\n}\n\n/* How high a button's glass rests above the page: 1 at rest, lower under a\n   pointer, nearly down while pressed. Its shadow and the light it lets\n   through follow the height; the glass itself stays put. Registered so the\n   height eases instead of jumping. */\n@property --lg-button-rise {\n  syntax: '<number>';\n  initial-value: 1;\n  inherits: true;\n}\n\n/* Where the light on a prominent button comes from: 0deg straight overhead. A\n   pointer swings it over to the top left. Registered so the light eases\n   across instead of jumping. */\n@property --lg-button-light-angle {\n  syntax: '<angle>';\n  initial-value: 0deg;\n  inherits: true;\n}\n\n/* Glass scene material. Registered so the renderer reads resolved values and\n   tints can transition; engines without @property resolve them by probe. */\n@property --lg-scene-tint {\n  syntax: '<color>';\n  initial-value: transparent;\n  inherits: false;\n}\n\n@property --lg-scene-frost {\n  syntax: '<length>';\n  initial-value: 0px;\n  inherits: false;\n}\n\n@property --lg-scene-merge {\n  syntax: '<length>';\n  initial-value: 0px;\n  inherits: true;\n}\n\n@property --lg-scene-flow {\n  syntax: '<number>';\n  initial-value: 0;\n  inherits: false;\n}\n\n@property --lg-scene-ink {\n  syntax: '<color>';\n  initial-value: transparent;\n  inherits: false;\n}\n\n@layer base {\n  :where(.lg-glass-surface > *) {\n    position: relative;\n    z-index: 2;\n  }\n}\n\n@layer components {\n  :root {\n    /* Core Physics: the frost every glass layer reads. Controls, alerts, badges and\n       dock labels cap the blur at their own size and follow the rest. */\n    --lg-glass-blur: 20px;\n    --lg-glass-sat: 1.8;\n    --lg-glass-contrast: 0.9;\n    --lg-glass-brightness: 1;\n    --lg-glass-alpha: 0.02;\n    --lg-bg: #1c1c1e;\n    --lg-panel: rgba(255, 255, 255, 0.04);\n    --lg-foreground: #f5f5f7;\n    --lg-muted-foreground: #e5e5ea;\n    --lg-border: rgba(245, 245, 247, 0.22);\n    --lg-control-surface: rgba(245, 245, 247, 0.08);\n    --lg-control-surface-hover: rgba(245, 245, 247, 0.14);\n    --lg-opaque-surface: #2c2c2e;\n    /* Floating layers keep 4.5:1 text contrast over a pure white or black backdrop. */\n    --lg-overlay-surface: rgb(44 44 46 / 0.78);\n    --lg-scrim: rgb(0 0 0 / 0.45);\n    /* Slabs are clear glass. The page shows through, dimmed by brightness so\n       muted text keeps 4.5:1 over pure white. The lens rim is dimmed less, but\n       never above what holds that bar at the very edge. */\n    --lg-slab-tint: rgb(28 28 30 / 0.3);\n    --lg-slab-brightness: 0.38;\n    --lg-slab-rim-brightness: 0.46;\n    --lg-slab-blur: 3;\n    /* The header is a clearer slab. Its links sit clear of the rim, so the rim\n       lets the page through undimmed, bent and split into colour, while the top\n       keeps muted links at 4.5:1 over pure white. */\n    --lg-header-tint: rgb(28 28 30 / 0.35);\n    --lg-header-brightness: 0.55;\n    --lg-header-rim-brightness: 1;\n    /* Familiar blue for actions; Vermilion belongs to the brand and artwork. */\n    --lg-accent: #0067d9;\n    --lg-accent-foreground: #ffffff;\n    /* Prominent buttons are blue glass. The tint recolours whatever lies\n       behind them and caps how bright it can get, so white text keeps 4.5:1\n       over any backdrop. The fill stands in where there is no glass: reduced\n       transparency, forced colours and a GlassScene. */\n    --lg-prominent-fill: #0067d9;\n    --lg-prominent-tint: grayscale(1) contrast(0.4) brightness(0.55) sepia(1) hue-rotate(174deg)\n      saturate(6) brightness(1.12);\n    --lg-prominent-glow: 178 214 255;\n    --lg-prominent-shade: 4 33 65;\n    /* Focus stays neutral so it does not read as a blue selected state. */\n    --lg-focus-ring: #b8b8be;\n    --lg-invalid: #ff7a8e;\n    --lg-disabled-opacity: 0.45;\n    --lg-motion-duration: 200ms;\n    /* Springy settle for presses, toggles and moving indicators */\n    --lg-spring: cubic-bezier(0.34, 1.56, 0.64, 1);\n    --lg-ease-out: cubic-bezier(0.32, 0.72, 0, 1);\n    /* System controls: the resting track, the switch's on state and the white\n       knob that turns to clear glass under a finger */\n    --lg-track: rgb(118 118 128 / 0.36);\n    --lg-switch-on: #0067d9;\n    --lg-knob: #ffffff;\n    --lg-knob-shadow:\n      0 2px 6px rgb(28 28 30 / 0.16), 0 1px 2px rgb(28 28 30 / 0.1),\n      0 0 0 0.5px rgb(28 28 30 / 0.05);\n\n    /* The fixed light the CSS glass is lit by: where its highlight sits (0 to\n       1 across the glass), the direction it strikes the rims from, and its\n       strength. The glass never follows the pointer. */\n    --lg-light-x: 0.5;\n    --lg-light-y: 0.5;\n    --lg-light-dir-x: 0;\n    --lg-light-dir-y: 0;\n    --lg-light-level: 0;\n\n    /* Theme Colors */\n    --lg-ink-dark: #ffffff;\n    --lg-ink-light: #000000;\n    --lg-fresnel: 0;\n    --lg-specular: 0;\n    --lg-refraction-scale: 24;\n    --lg-refraction-blur: 16;\n\n    /* Edge reflex: strength of the lit bevel and of the shaded inner edge */\n    --lg-reflex-light: 0.42;\n    --lg-reflex-dark: 1.4;\n    --lg-button-reflex-light: 0.7;\n    --lg-sheen-alpha: 0.05;\n\n    /* Specular edge: a hairline ring brightest where the light enters (top\n       left), with a softer counter highlight on the far edge. The glow is the\n       light caught inside the glass thickness. */\n    --lg-rim-width: 1px;\n    --lg-specular-peak: 0.45;\n    --lg-specular-counter: 0.22;\n    --lg-specular-floor: 0.07;\n    --lg-glow-alpha: 0.06;\n\n    /* Lighting & Depth: outer shadows only, the glass edge lives in --lg-glass-rim */\n    --lg-shadow: 0 1px 2px rgb(0 0 0 / 0.18), 0 8px 24px -4px rgb(0 0 0 / 0.28);\n    --lg-shadow-raised: 0 2px 6px rgb(0 0 0 / 0.2), 0 30px 60px -18px rgb(0 0 0 / 0.55);\n    --lg-input-shadow: inset 0 1px 2px rgb(0 0 0 / 0.24), inset 0 -1px 0 rgb(255 255 255 / 0.06);\n\n    /* Chromium edge lens, read as plain numbers by useLensFilter:\n       depth scales the edge bend, blur is the frost radius in px. */\n    --lg-lens-depth: 1;\n    --lg-lens-blur: 6;\n    --lg-lens-saturation: 1.5;\n    --lg-lens-bevel: 0;\n    --lg-lens-thickness: 0;\n    --lg-lens-ior: 1.5;\n    --lg-lens-dispersion: 0.16;\n    --lg-lens-body-brightness: 1;\n    --lg-lens-rim-brightness: 1;\n    --lg-glass-thickness: 1;\n\n    --lg-noise-alpha: 0.03;\n\n    --lg-radius-md: 16px;\n    --lg-radius-lg: 24px;\n\n    /* Glass scene: shadow and highlight strength, and extra white in the tint. */\n    --lg-scene-shadow: 0.34;\n    --lg-scene-highlight: 1;\n    --lg-scene-tint-boost: 0;\n\n    --lg-noise-image: url('data:image/svg+xml,%3Csvg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 120 120\"%3E%3Cfilter id=\"grain\"%3E%3CfeTurbulence type=\"fractalNoise\" baseFrequency=\"0.8\" numOctaves=\"3\" stitchTiles=\"stitch\"/%3E%3CfeColorMatrix type=\"saturate\" values=\"0\"/%3E%3C/filter%3E%3Crect width=\"120\" height=\"120\" filter=\"url(%23grain)\" opacity=\"0.5\"/%3E%3C/svg%3E');\n  }\n\n  [data-lg-theme='dark'] {\n    color-scheme: dark;\n  }\n\n  /* Light theme */\n  [data-lg-theme='light'] {\n    color-scheme: light;\n    --lg-bg: #faf9f7;\n    --lg-panel: rgba(255, 255, 255, 0.5);\n    --lg-glass-alpha: 0.15;\n    --lg-glass-blur: 16px;\n    --lg-glass-contrast: 1;\n    --lg-glass-sat: 1.6;\n    --lg-glass-brightness: 1.06;\n    --lg-ink-dark: #222224;\n    --lg-ink-light: #222224;\n    --lg-ink: var(--lg-ink-dark);\n    --lg-foreground: #222224;\n    --lg-muted-foreground: #505055;\n    --lg-border: rgba(0, 0, 0, 0.14);\n    --lg-control-surface: rgba(255, 255, 255, 0.72);\n    --lg-control-surface-hover: rgba(255, 255, 255, 0.95);\n    --lg-opaque-surface: #ffffff;\n    --lg-overlay-surface: rgb(255 255 255 / 0.82);\n    --lg-scrim: rgb(0 0 0 / 0.16);\n    --lg-slab-tint: rgb(255 255 255 / 0.8);\n    --lg-slab-brightness: 1;\n    --lg-slab-rim-brightness: 1;\n    --lg-slab-blur: 3;\n    /* The tint alone keeps muted header links at 4.5:1 over pure black. */\n    --lg-header-tint: rgb(255 255 255 / 0.77);\n    --lg-header-brightness: 1;\n    --lg-header-rim-brightness: 1;\n    --lg-accent: #0067d9;\n    --lg-prominent-tint: grayscale(1) contrast(0.5) brightness(0.35) sepia(1) hue-rotate(172deg)\n      saturate(6) brightness(1.4);\n    --lg-focus-ring: #66666a;\n    --lg-invalid: #c4153f;\n    --lg-track: rgb(118 118 128 / 0.2);\n    --lg-switch-on: #0067d9;\n    --lg-noise-alpha: 0.02;\n    --lg-reflex-light: 1;\n    --lg-reflex-dark: 0.8;\n    --lg-button-reflex-light: 1;\n    --lg-sheen-alpha: 0.08;\n    --lg-specular-peak: 0.7;\n    --lg-specular-counter: 0.55;\n    --lg-specular-floor: 0.35;\n    --lg-glow-alpha: 0.14;\n    --lg-shadow: 0 1px 2px rgb(0 0 0 / 0.06), 0 8px 24px -6px rgb(0 0 0 / 0.14);\n    --lg-shadow-raised: 0 2px 6px rgb(0 0 0 / 0.06), 0 28px 56px -18px rgb(0 0 0 / 0.26);\n    --lg-input-shadow: inset 0 1px 2px rgb(0 0 0 / 0.08), inset 0 -1px 0 rgb(255 255 255 / 0.8);\n\n    --lg-refraction-scale: 24;\n    --lg-refraction-blur: 20;\n    --lg-fresnel: 0.1;\n    --lg-specular: 0.05;\n    --lg-highlight-strength: 0.1;\n\n    /* The light sits a little above centre and catches the top rims. */\n    --lg-light-y: 0.3;\n    --lg-light-dir-y: -0.35;\n    --lg-light-level: 0.15;\n\n    --lg-scene-shadow: 0.16;\n    --lg-scene-tint-boost: 0.06;\n  }\n\n  [data-lg-theme='dark'][data-lg-mode='clear'] {\n    --lg-glass-alpha: 0.02;\n    --lg-glass-sat: 1.8;\n    --lg-glass-contrast: 0.9;\n  }\n\n  [data-lg-theme='dark'][data-lg-mode='tinted'] {\n    --lg-glass-alpha: 0.12;\n    --lg-glass-sat: 1.5;\n    --lg-glass-contrast: 0.9;\n  }\n\n  [data-lg-theme='light'][data-lg-mode='clear'] {\n    --lg-glass-alpha: 0.08;\n    --lg-glass-sat: 1.8;\n    --lg-glass-contrast: 1.02;\n    --lg-glass-blur: 20px;\n  }\n\n  [data-lg-theme='light'][data-lg-mode='tinted'] {\n    --lg-glass-alpha: 0.25;\n    --lg-glass-sat: 1.4;\n    --lg-glass-contrast: 1;\n    --lg-glass-blur: 14px;\n  }\n\n  /* Tinted slabs frost harder and hold a denser tint; the rim still lets more\n     light through. The header matches the other slabs. */\n  [data-lg-theme='dark'][data-lg-mode='tinted'] {\n    --lg-slab-tint: rgb(28 28 30 / 0.55);\n    --lg-slab-brightness: 0.55;\n    --lg-slab-rim-brightness: 0.65;\n    --lg-slab-blur: 14;\n    --lg-header-tint: rgb(28 28 30 / 0.55);\n    --lg-header-brightness: 0.55;\n    --lg-header-rim-brightness: 0.65;\n  }\n\n  [data-lg-theme='light'][data-lg-mode='tinted'] {\n    --lg-slab-tint: rgb(255 255 255 / 0.9);\n    --lg-slab-blur: 14;\n    --lg-header-tint: rgb(255 255 255 / 0.9);\n  }\n\n  [data-lg-mode='tinted'] {\n    --lg-glass-alpha: 0.72;\n    --lg-glass-blur: 32px;\n    --lg-glass-sat: 1.4;\n    --lg-glass-contrast: 0.9;\n    --lg-lens-blur: 10;\n  }\n\n  /* Increased contrast keeps the glass and makes it predominantly black or\n     white, as the system's own glass does: dark glass dims what lies behind it\n     and light glass frosts denser, so text keeps 7:1 over any backdrop, and\n     muted text gets full contrast. Dark glass adds no white of its own, and\n     its Chromium lens dims as its frost does. Toasts and tooltips darken. A\n     ring in the text colour edges the glass (see Increased contrast below).\n     The dimming outranks the quality settings, which still lighten the frost. */\n  @media (prefers-contrast: more) {\n    [data-lg-theme='dark'],\n    [data-lg-theme='dark'][data-lg-mode],\n    [data-lg-theme='dark'][data-lg-mode][data-lg-quality] {\n      --lg-muted-foreground: var(--lg-foreground);\n      --lg-glass-alpha: 0.02;\n      --lg-glass-brightness: 0.22;\n      --lg-glass-contrast: 1;\n      --lg-sheen-alpha: 0;\n      --lg-lens-body-brightness: var(--lg-glass-brightness);\n      --lg-lens-rim-brightness: var(--lg-glass-brightness);\n      --lg-overlay-surface: rgb(28 28 30 / 0.88);\n      --lg-slab-tint: rgb(28 28 30 / 0.55);\n      --lg-slab-brightness: 0.5;\n      --lg-slab-rim-brightness: 0.65;\n      --lg-slab-blur: 14;\n      --lg-header-tint: rgb(28 28 30 / 0.55);\n      --lg-header-brightness: 0.5;\n      --lg-header-rim-brightness: 0.65;\n    }\n\n    [data-lg-theme='light'],\n    [data-lg-theme='light'][data-lg-mode] {\n      --lg-muted-foreground: var(--lg-foreground);\n      --lg-glass-alpha: 0.7;\n      --lg-slab-tint: rgb(255 255 255 / 0.9);\n      --lg-slab-blur: 14;\n      --lg-header-tint: rgb(255 255 255 / 0.9);\n    }\n  }\n\n  :root[data-lg-quality='low'] {\n    --lg-scene-highlight: 0.6;\n    --lg-glass-blur: 6px;\n    --lg-glass-sat: 1.05;\n    --lg-glass-contrast: 1;\n    --lg-glass-brightness: 1;\n    --lg-refraction-scale: 0;\n    --lg-refraction-blur: 0;\n    --lg-highlight-strength: 0;\n    --lg-lens-depth: 0;\n  }\n\n  /* Touch devices and reduced-motion settings land here. The colour split costs six\n     more filter passes a frame on every lens in view, so it is left out. */\n  :root[data-lg-quality='medium'] {\n    --lg-lens-dispersion: 0;\n    --lg-glass-blur: 12px;\n    --lg-glass-sat: 1.4;\n    --lg-glass-contrast: 0.96;\n    --lg-refraction-scale: 10;\n    --lg-refraction-blur: 8;\n  }\n\n  :root[data-lg-quality='high'] {\n    --lg-refraction-scale: 16;\n    --lg-refraction-blur: 10;\n  }\n\n  :root[data-lg-reduce-transparency='1'] {\n    --lg-glass-blur: 0px;\n    --lg-glass-alpha: 0.95;\n    --lg-noise-alpha: 0.01;\n    --lg-glass-contrast: 1;\n    --lg-glass-sat: 1;\n    --lg-glass-brightness: 1;\n    --lg-refraction-scale: 0;\n    --lg-lens-depth: 0;\n  }\n\n  [data-lg-theme='dark'][data-lg-reduce-transparency='1'] {\n    --lg-opaque-surface: #2c2c2e;\n    --lg-control-surface: #3a3a3c;\n    --lg-control-surface-hover: #48484a;\n    --lg-track: #48484a;\n  }\n\n  [data-lg-theme='light'][data-lg-reduce-transparency='1'] {\n    --lg-opaque-surface: #ffffff;\n    --lg-control-surface: #f0f0f2;\n    --lg-control-surface-hover: #e3e3e7;\n    --lg-track: #e6e6e9;\n  }\n\n  [data-lg-reduce-motion='1'] {\n    --lg-motion-duration: 0ms;\n  }\n\n  [data-lg-reduce-motion='1'] *,\n  [data-lg-reduce-motion='1'] *::before,\n  [data-lg-reduce-motion='1'] *::after {\n    animation-duration: 0ms !important;\n    transition-duration: 0ms !important;\n  }\n\n  /* A switch still shows its own change, in a short plain slide and a colour\n     fade: no spring, swell or glass. Everything else holds still. */\n  [data-lg-reduce-motion='1'] .lg-switch {\n    transition-duration: 160ms !important;\n  }\n\n  [data-lg-reduce-motion='1'] :is(.lg-switch-thumb, .lg-switch-lens-scene, .lg-switch-lens-track) {\n    transition-duration: 160ms !important;\n    transition-property: translate !important;\n    transition-timing-function: ease-out !important;\n  }\n\n  [data-lg-reduce-motion='1'] .lg-glass-surface::after {\n    transform: none !important;\n    transition: none !important;\n  }\n\n  [data-lg-reduce-motion='1'] .lg-button {\n    transform: none !important;\n    transition: none !important;\n  }\n\n  [data-lg-reduce-motion='1'] .lg-button__bloom {\n    display: none;\n  }\n\n  @media (prefers-reduced-motion: reduce) {\n    :root {\n      --lg-motion-duration: 0ms;\n    }\n\n    .lg-glass-surface,\n    .lg-glass-surface::after,\n    .lg-button,\n    .lg-button__distortion,\n    .lg-button__shine,\n    .lg-input,\n    .lg-dialog-overlay,\n    .lg-dialog-content,\n    .lg-popover-content,\n    .lg-tabs-trigger,\n    .lg-accordion-trigger,\n    .lg-accordion-chevron,\n    .lg-refraction-background,\n    .lg-noise,\n    .lg-switch,\n    .lg-switch-thumb,\n    .lg-slider-thumb,\n    .lg-checkbox,\n    .lg-radio,\n    .lg-check-tick,\n    .lg-check-dash,\n    .lg-radio-dot,\n    .lg-select-chevron,\n    .lg-progress-fill,\n    .lg-spinner-ring,\n    .lg-toast,\n    .lg-toast-root,\n    .lg-toast-close,\n    .lg-toast-action,\n    .lg-tooltip-content,\n    .lg-accordion-content,\n    .lg-avatar-image,\n    .lg-alert,\n    .lg-alert-fold,\n    .lg-skeleton::after,\n    .lg-command-list,\n    .lg-command-search,\n    .lg-page,\n    .lg-alert-close,\n    .lg-segmented-item,\n    .lg-segmented-indicator,\n    .lg-tabs-indicator,\n    .lg-dock-item,\n    .lg-dock-label,\n    .lg-sheet-content,\n    .lg-menu-content,\n    .lg-select-content,\n    .lg-lens,\n    .lg-scene-drop {\n      animation-duration: 0ms !important;\n      transition-duration: 0ms !important;\n    }\n\n    .lg-switch {\n      transition-duration: 160ms !important;\n    }\n\n    .lg-switch-thumb,\n    .lg-switch-lens-scene,\n    .lg-switch-lens-track {\n      transition-duration: 160ms !important;\n      transition-property: translate !important;\n      transition-timing-function: ease-out !important;\n    }\n\n    .lg-glass-surface::after,\n    .lg-button__distortion,\n    .lg-refraction-background,\n    .lg-button {\n      transform: none !important;\n    }\n\n    .lg-button__bloom {\n      display: none;\n    }\n  }\n\n  @keyframes lg-grain {\n    0% {\n      transform: translate3d(0, 0, 0);\n    }\n    20% {\n      transform: translate3d(-2%, 2%, 0);\n    }\n    40% {\n      transform: translate3d(-2%, -2%, 0);\n    }\n    60% {\n      transform: translate3d(2%, -2%, 0);\n    }\n    80% {\n      transform: translate3d(2%, 2%, 0);\n    }\n    100% {\n      transform: translate3d(0, 0, 0);\n    }\n  }\n\n  /* ============================================\n     Glass edge\n     Two layers make every glass edge. The bevel is an inset shadow stack: the\n     light caught in the glass thickness, a bright bevel on the lit top-left, a\n     softer counter-bevel, a shaded inner reflex, a faint chromatic fringe and\n     a highlight cast by the fixed light. The specular ring is a masked\n     hairline lit from the top left, with a glint where that light sits. Custom\n     properties resolve on the declaring element, so surfaces and buttons feed\n     both their own tokens.\n     ============================================ */\n\n  .lg-glass-surface,\n  .lg-button {\n    --lg-rim-gain: calc(\n      var(--lg-rim-tangent-alpha, 1) * var(--lg-debug-tangent-scale, 1) *\n        var(--lg-rim-micro-mask, 1) * var(--lg-debug-micro-scale, 1) *\n        var(--lg-rim-corner-mask, 1) * var(--lg-debug-corner-scale, 1) *\n        var(--lg-debug-rim-alpha-scale, 1)\n    );\n    --lg-glass-rim:\n      inset 0 0 calc(12px * var(--lg-rim-scale)) calc(-4px * var(--lg-rim-scale))\n        rgb(255 255 255 / calc(var(--lg-glow-alpha) * var(--lg-rim-gain))),\n      inset calc(1.5px * var(--lg-rim-scale)) calc(2.5px * var(--lg-rim-scale))\n        calc(1px * var(--lg-rim-scale)) -2px rgb(255 255 255 / calc(var(--lg-rim-light) * 0.7)),\n      inset calc(-1.5px * var(--lg-rim-scale)) calc(-2px * var(--lg-rim-scale))\n        calc(1px * var(--lg-rim-scale)) -2px rgb(255 255 255 / calc(var(--lg-rim-light) * 0.55)),\n      inset -0.3px -1px 4px 0 rgb(0 0 0 / calc(var(--lg-rim-dark) * 0.1)),\n      inset -1.5px 2.5px 0 -2px rgb(0 0 0 / calc(var(--lg-rim-dark) * 0.14)),\n      inset 0 3px 4px -2px rgb(0 0 0 / calc(var(--lg-rim-dark) * 0.14)),\n      inset var(--lg-rim-ca-offset) 0 3px -1px rgb(80 160 255 / var(--lg-rim-ca-alpha)),\n      inset calc(-1 * var(--lg-rim-ca-offset)) 0 3px -1px rgb(255 90 150 / var(--lg-rim-ca-alpha)),\n      inset var(--lg-rim-offset-x) var(--lg-rim-offset-y) 3px rgb(255 255 255 / var(--lg-rim-alpha));\n    /* to bottom right keeps both highlights on the corners at any aspect\n       ratio; a fixed angle would smear them along a wide pill. */\n    --lg-specular-ring:\n      radial-gradient(\n        circle at calc(var(--lg-light-x) * 100%) calc(var(--lg-light-y) * 100%),\n        rgb(255 255 255 / calc(var(--lg-light-level) * 0.85)),\n        transparent 42%\n      ),\n      linear-gradient(\n        to bottom right,\n        rgb(255 255 255 / calc(var(--lg-specular-peak) * var(--lg-rim-gain))) 0%,\n        rgb(255 255 255 / calc(var(--lg-specular-floor) * var(--lg-rim-gain))) 32%,\n        rgb(255 255 255 / calc(var(--lg-specular-floor) * var(--lg-rim-gain))) 68%,\n        rgb(255 255 255 / calc(var(--lg-specular-counter) * var(--lg-rim-gain))) 100%\n      );\n  }\n\n  /* Glass Surface - Global Refraction */\n  .lg-glass-surface {\n    --lg-thickness: calc(1 + var(--lg-light-strength) * 0.35);\n    --lg-surface-blur-base: calc(var(--lg-glass-blur) * var(--lg-thickness));\n    --lg-surface-blur: var(--lg-surface-blur-base);\n    --lg-surface-alpha: var(--lg-glass-alpha);\n    --lg-surface-lift: 0;\n    --lg-light-strength: calc(var(--lg-light-level) * 0.45);\n    /* Bevel thickness (scaled by distance-aware factor) */\n    --lg-rim-scale: calc(var(--lg-rim-width-scale, 1) * var(--lg-debug-rim-thickness, 1));\n    --lg-rim-offset-max: 4.5px;\n    --lg-rim-offset-max-scaled: calc(var(--lg-rim-offset-max) * var(--lg-rim-scale));\n    --lg-rim-tangent-alpha: 1;\n    --lg-rim-micro-mask: 1;\n    --lg-rim-corner-mask: 1;\n    --lg-rim-ca-offset: calc(2px * var(--lg-debug-ca-offset-scale, 1));\n    --lg-rim-ca-alpha: calc(0.06 * var(--lg-debug-ca-scale, 1));\n    --lg-rim-offset-x: clamp(\n      calc(-1 * var(--lg-rim-offset-max-scaled)),\n      calc(\n        var(--lg-light-dir-x) * -1 * var(--lg-rim-offset-max-scaled) *\n          (0.6 + var(--lg-light-strength))\n      ),\n      var(--lg-rim-offset-max-scaled)\n    );\n    --lg-rim-offset-y: clamp(\n      calc(-1 * var(--lg-rim-offset-max-scaled)),\n      calc(\n        var(--lg-light-dir-y) * -1 * var(--lg-rim-offset-max-scaled) *\n          (0.6 + var(--lg-light-strength))\n      ),\n      var(--lg-rim-offset-max-scaled)\n    );\n    --lg-rim-light: calc(var(--lg-reflex-light) * var(--lg-rim-gain));\n    --lg-rim-dark: var(--lg-reflex-dark);\n    --lg-rim-alpha: calc(\n      (0.05 + var(--lg-light-strength) * 0.12 + var(--lg-fresnel, 0) * 0.35 + var(--lg-specular) *\n          0.32) *\n        var(--lg-rim-gain)\n    );\n\n    position: relative;\n    border-radius: var(--lg-panel-radius, var(--lg-radius-lg));\n    isolation: isolate;\n    background: transparent;\n    color: var(--lg-foreground);\n    transition:\n      box-shadow var(--lg-motion-duration) ease,\n      transform var(--lg-motion-duration) ease;\n    box-shadow: var(--lg-panel-elevation-shadow, var(--lg-shadow));\n    overflow: hidden;\n    contain: layout paint style;\n  }\n\n  .lg-glass-surface[data-lg-preset='subtle'] {\n    --lg-surface-blur: min(var(--lg-surface-blur-base), 8px);\n    --lg-surface-alpha: max(var(--lg-glass-alpha), 0.06);\n    --lg-rim-offset-max: 1.5px;\n  }\n\n  .lg-glass-surface[data-lg-preset='standard'] {\n    --lg-surface-blur: min(var(--lg-surface-blur-base), 14px);\n    --lg-surface-alpha: max(var(--lg-glass-alpha), 0.08);\n  }\n\n  .lg-glass-surface[data-lg-preset='prominent'] {\n    --lg-surface-blur: min(var(--lg-surface-blur-base), 18px);\n    --lg-surface-alpha: max(var(--lg-glass-alpha), 0.12);\n  }\n\n  .lg-glass-surface[data-lg-preset='control'] {\n    --lg-surface-blur: min(var(--lg-surface-blur-base), 10px);\n    --lg-surface-alpha: max(var(--lg-glass-alpha), 0.08);\n    --lg-rim-offset-max: 1.25px;\n  }\n\n  .lg-glass-surface[data-lg-preset='showcase'] {\n    --lg-surface-blur: min(var(--lg-surface-blur-base), 24px);\n  }\n\n  /* An interactive surface brightens a touch on hover, wherever the pointer\n     rests on it. */\n  .lg-glass-surface[data-lg-interactive='true']:hover {\n    --lg-surface-lift: 0.04;\n  }\n\n  /* The lift eases in and out. Other frost has no transition, so it changes\n     with a theme or preference switch at once. */\n  .lg-glass-surface[data-lg-interactive='true']::before {\n    transition: background-color var(--lg-motion-duration) ease;\n  }\n\n  /* Panel shapes and spacing. Component defaults live here rather than in\n     className utilities, so a consumer's p-4 or rounded-none always wins. */\n  .lg-panel--panel {\n    --lg-panel-radius: var(--lg-radius-lg);\n    padding: 1.5rem;\n  }\n\n  .lg-panel--card {\n    --lg-panel-radius: var(--lg-radius-md);\n    padding: 1.25rem;\n  }\n\n  .lg-panel--pill {\n    --lg-panel-radius: 9999px;\n    padding: 0.75rem 1.25rem;\n  }\n\n  .lg-panel--raised {\n    --lg-panel-elevation-shadow: var(--lg-shadow-raised);\n  }\n\n  .lg-refraction-filter {\n    position: absolute;\n    width: 0;\n    height: 0;\n    overflow: hidden;\n    pointer-events: none;\n  }\n\n  /* The generated scene sits under the frost layer, which then drops its\n     backdrop blur and lays only its tint, bevel and sheen over the scene.\n     WebKit draws a filtered layer from its overflow origin, so a viewport\n     scene hanging off the top or left edge would land shifted. Clipping\n     keeps both origins at the surface corner. */\n  .lg-glass-surface > .lg-refraction-background {\n    position: absolute;\n    inset: 0;\n    z-index: -1;\n    overflow: hidden;\n    border-radius: inherit;\n    pointer-events: none;\n    transform: translateZ(0);\n  }\n\n  .lg-refraction-background > .lg-refraction-scene {\n    position: absolute;\n    inset: 0;\n  }\n\n  .lg-refraction-scene > * {\n    min-width: 100%;\n    min-height: 100%;\n  }\n\n  /* Position the scene without a transform: WebKit shifts transformed input\n     when the SVG filter combines refracted colour channels. Chromium filters\n     composited layers, so a scroll-driven animation on translate still carries\n     the scene through the scroll, and left/top hold what scrolling leaves unchanged. */\n  .lg-glass-surface[data-lg-refraction-background-space='viewport']\n    > .lg-refraction-background\n    > .lg-refraction-scene {\n    inset: 0 auto auto 0;\n    top: var(--lg-refraction-scene-y, 0px);\n    left: var(--lg-refraction-scene-x, 0px);\n    width: var(--lg-refraction-scene-width, 100vw);\n    height: var(--lg-refraction-scene-height, 100dvh);\n  }\n\n  .lg-glass-surface[data-lg-refraction='soft'] {\n    --lg-surface-blur: calc(var(--lg-surface-blur-base) * 0.9);\n  }\n\n  .lg-glass-surface[data-lg-refraction='strong'] {\n    --lg-surface-blur: calc(var(--lg-surface-blur-base) * 1.12);\n  }\n\n  /* Frost, bevel and sheen. Keep blend modes, masks, filters and opacity off\n     every ancestor of this layer: in Chromium each of them isolates the\n     backdrop and silently turns the blur into a no-op. The layer carries its\n     own rounded shape: Chromium drops the host's rounded clip from a backdrop\n     blur that sits inside another rounded overflow clip, such as a card. The\n     tint is background-color alone, so a consumer's before:bg-* utility\n     recolors the glass and keeps the sheen. */\n  .lg-glass-surface::before {\n    content: '';\n    position: absolute;\n    inset: 0;\n    z-index: 0;\n    border-radius: inherit;\n    pointer-events: none;\n\n    background-color: rgb(255 255 255 / calc(var(--lg-surface-alpha) + var(--lg-surface-lift)));\n    background-image:\n      radial-gradient(\n        circle at calc(var(--lg-light-x) * 100%) calc(var(--lg-light-y) * 100%),\n        rgb(\n          255 255 255 /\n            calc(\n              (var(--lg-light-strength) * 0.1 + var(--lg-highlight-strength) * 0.12) *\n                var(--lg-debug-highlight-scale, 1)\n            )\n        ),\n        transparent 65%\n      ),\n      linear-gradient(180deg, rgb(255 255 255 / var(--lg-sheen-alpha)), transparent 45%);\n    box-shadow: var(--lg-glass-rim);\n\n    -webkit-backdrop-filter: blur(var(--lg-surface-blur)) brightness(var(--lg-glass-brightness))\n      contrast(var(--lg-glass-contrast)) saturate(var(--lg-glass-sat));\n    backdrop-filter: blur(var(--lg-surface-blur)) brightness(var(--lg-glass-brightness))\n      contrast(var(--lg-glass-contrast)) saturate(var(--lg-glass-sat));\n  }\n\n  .lg-glass-surface[data-lg-generated-refraction='true']::before {\n    -webkit-backdrop-filter: none;\n    backdrop-filter: none;\n  }\n\n  /* Specular ring. The mask lives on this sibling of the frost layer, never\n     on an ancestor, so it cannot flatten the blur. */\n  .lg-glass-surface::after {\n    content: '';\n    position: absolute;\n    inset: 0;\n    z-index: 1;\n    padding: var(--lg-rim-width);\n    border-radius: inherit;\n    pointer-events: none;\n    background: var(--lg-specular-ring);\n    -webkit-mask:\n      linear-gradient(#000 0 0) content-box,\n      linear-gradient(#000 0 0);\n    -webkit-mask-composite: xor;\n    mask:\n      linear-gradient(#000 0 0) content-box,\n      linear-gradient(#000 0 0);\n    mask-composite: exclude;\n  }\n\n  /* Chromium edge lens: one SVG filter frosts, bends and saturates the\n     backdrop. Its displacement map is measured from the padding box the\n     frost layer fills. */\n  .lg-glass-surface[data-lg-lens='active']::before {\n    backdrop-filter: var(--lg-lens-filter);\n  }\n\n  /* Glass inside glass samples a backdrop the outer layer already saturated,\n     so it adds no saturation of its own. */\n  .lg-glass-surface .lg-glass-surface {\n    --lg-glass-sat: 1;\n    --lg-lens-saturation: 1;\n  }\n\n  .lg-noise {\n    position: absolute;\n    inset: 0;\n    z-index: 1;\n    border-radius: inherit;\n    pointer-events: none;\n    background-image: var(--lg-noise-image);\n    background-size: 128px 128px;\n    opacity: var(--lg-noise-alpha);\n    /* Static by default to avoid per-frame repaints; opt-in with data-lg-animate-noise=\"1\" on <html>. */\n    animation: none;\n    will-change: auto;\n  }\n\n  [data-lg-animate-noise='1'] .lg-noise {\n    animation: lg-grain 4s steps(10) infinite;\n  }\n\n  [data-lg-reduce-motion='1'] .lg-noise {\n    animation: none !important;\n  }\n\n  /* Light mode glass surface - emphasize refraction, minimize dynamic lighting */\n  [data-lg-theme='light'] .lg-glass-surface {\n    --lg-rim-offset-max: 2px;\n    --lg-rim-ca-alpha: calc(0.05 * var(--lg-debug-ca-scale, 1));\n  }\n\n  /* ============================================\n     Floating layers\n     Dialogs, popovers, toasts and tooltips frost on the element itself, so the\n     material survives their scrolling and their opacity animations. Their\n     denser tint keeps text readable over any backdrop.\n     ============================================ */\n\n  .lg-dialog-content,\n  .lg-popover-content,\n  .lg-toast-root,\n  .lg-tooltip-content,\n  .lg-sheet-content,\n  .lg-menu-content,\n  .lg-select-content {\n    background: var(--lg-overlay-surface);\n    -webkit-backdrop-filter: blur(var(--lg-surface-blur)) saturate(var(--lg-glass-sat));\n    backdrop-filter: blur(var(--lg-surface-blur)) saturate(var(--lg-glass-sat));\n  }\n\n  .lg-dialog-content::before,\n  .lg-popover-content::before,\n  .lg-toast-root::before,\n  .lg-tooltip-content::before,\n  .lg-sheet-content::before,\n  .lg-menu-content::before,\n  .lg-select-content::before {\n    background-color: transparent;\n    -webkit-backdrop-filter: none;\n    backdrop-filter: none;\n  }\n\n  /* Dialogs, popovers, sheets and menus are slabs of glass: the page shows\n     through, dimmed or lifted just enough to keep their text legible, and where\n     Chromium can run the lens their rim bends it. */\n  .lg-dialog-content,\n  .lg-popover-content,\n  .lg-sheet-content,\n  .lg-menu-content,\n  .lg-select-content {\n    --lg-lens-blur: var(--lg-slab-blur);\n    --lg-lens-body-brightness: var(--lg-slab-brightness);\n    --lg-lens-rim-brightness: var(--lg-slab-rim-brightness);\n\n    background: var(--lg-slab-tint);\n    -webkit-backdrop-filter: blur(calc(var(--lg-slab-blur) * 1px)) saturate(var(--lg-glass-sat))\n      brightness(var(--lg-slab-brightness));\n    backdrop-filter: blur(calc(var(--lg-slab-blur) * 1px)) saturate(var(--lg-glass-sat))\n      brightness(var(--lg-slab-brightness));\n  }\n\n  .lg-dialog-content[data-lg-lens='active'],\n  .lg-popover-content[data-lg-lens='active'],\n  .lg-sheet-content[data-lg-lens='active'],\n  .lg-menu-content[data-lg-lens='active'],\n  .lg-select-content[data-lg-lens='active'] {\n    -webkit-backdrop-filter: var(--lg-lens-filter);\n    backdrop-filter: var(--lg-lens-filter);\n  }\n\n  .lg-dialog-content[data-lg-lens='active']::before,\n  .lg-popover-content[data-lg-lens='active']::before,\n  .lg-sheet-content[data-lg-lens='active']::before,\n  .lg-menu-content[data-lg-lens='active']::before,\n  .lg-select-content[data-lg-lens='active']::before {\n    -webkit-backdrop-filter: none;\n    backdrop-filter: none;\n  }\n\n  .lg-dialog-content {\n    position: fixed;\n    top: 50%;\n    left: 50%;\n    z-index: 50;\n    width: calc(100vw - 2rem);\n    max-width: 520px;\n    max-height: calc(100dvh - 2rem);\n    translate: -50% -50%;\n    overflow-x: hidden;\n    overflow-y: auto;\n  }\n\n  @media (width >= 40rem) {\n    .lg-dialog-content {\n      padding: 2rem;\n    }\n  }\n\n  .lg-popover-content {\n    z-index: 50;\n    width: min(22rem, calc(100vw - 2rem));\n    max-height: calc(100dvh - 2rem);\n    overflow-x: hidden;\n    overflow-y: auto;\n    font-size: 0.875rem;\n    line-height: calc(1.25 / 0.875);\n  }\n\n  .lg-dialog-content:focus,\n  .lg-popover-content:focus {\n    outline: none;\n  }\n\n  .lg-tooltip-content {\n    z-index: 50;\n    max-width: calc(100vw - 2rem);\n    padding: 0.375rem 0.75rem;\n    font-size: 0.75rem;\n    line-height: calc(1 / 0.75);\n    font-weight: 500;\n  }\n\n  .lg-dialog-overlay {\n    position: fixed;\n    inset: 0;\n    z-index: 40;\n    background: var(--lg-scrim);\n    -webkit-backdrop-filter: blur(1.5px);\n    backdrop-filter: blur(1.5px);\n  }\n\n  /* Toasts stack in the top-right corner; each glass card keeps its own frost. */\n  .lg-toast-viewport {\n    position: fixed;\n    top: 1rem;\n    right: 1rem;\n    z-index: 100;\n    display: flex;\n    flex-direction: column;\n    gap: 0.75rem;\n    width: min(22rem, calc(100vw - 2rem));\n    max-width: calc(100vw - 2rem);\n    margin: 0;\n    padding: 0;\n    list-style: none;\n    pointer-events: none;\n  }\n\n  /* Radix turns selection off inline for the swipe, without the -webkit- prefix Safari needs. */\n  .lg-toast {\n    position: relative;\n    width: 100%;\n    list-style: none;\n    outline: none;\n    pointer-events: auto;\n    user-select: none;\n  }\n\n  .lg-toast-root {\n    display: grid;\n    grid-template-columns: minmax(0, 1fr) auto;\n    width: 100%;\n    font-size: 0.875rem;\n    line-height: calc(1.25 / 0.875);\n  }\n\n  .lg-toast-root > * {\n    grid-column: 1;\n  }\n\n  /* The dismiss button stands beside the words, not over them. */\n  .lg-toast-root > .lg-toast-close {\n    grid-column: 2;\n    grid-row: 1 / span 2;\n    align-self: start;\n  }\n\n  .lg-toast-close {\n    display: inline-flex;\n    flex: none;\n    align-items: center;\n    justify-content: center;\n    width: 1.75rem;\n    height: 1.75rem;\n    margin-block: -0.25rem 0;\n    margin-inline: 0.75rem -0.375rem;\n    padding: 0;\n    border: 0;\n    border-radius: 9999px;\n    background: transparent;\n    color: var(--lg-muted-foreground);\n    cursor: pointer;\n    transition:\n      background-color 180ms ease,\n      color 180ms ease;\n  }\n\n  .lg-toast-close:hover {\n    background: rgb(255 255 255 / 0.14);\n    color: var(--lg-foreground);\n  }\n\n  [data-lg-theme='light'] .lg-toast-close:hover {\n    background: rgb(0 0 0 / 0.07);\n  }\n\n  .lg-toast-close:focus-visible {\n    outline: 2px solid var(--lg-focus-ring);\n    outline-offset: 1px;\n    color: var(--lg-foreground);\n  }\n\n  .lg-toast-close > svg {\n    width: 1rem;\n    height: 1rem;\n  }\n\n  .lg-toast-action {\n    grid-column: 1;\n    justify-self: start;\n    height: 1.875rem;\n    margin-top: 0.625rem;\n    padding: 0 0.875rem;\n    border: 0;\n    border-radius: 9999px;\n    background: var(--lg-control-surface-hover);\n    box-shadow: inset 0 0 0 1px var(--lg-border);\n    color: var(--lg-foreground);\n    cursor: pointer;\n    font: inherit;\n    font-size: 0.8125rem;\n    font-weight: 600;\n    transition:\n      background-color 180ms ease,\n      scale 320ms var(--lg-spring);\n  }\n\n  .lg-toast-action:active {\n    scale: 0.94;\n  }\n\n  .lg-toast-action:focus-visible {\n    outline: 2px solid var(--lg-focus-ring);\n    outline-offset: 2px;\n  }\n\n  .lg-toast-title {\n    color: var(--lg-foreground);\n    font-size: 1rem;\n    line-height: 1.5;\n    font-weight: 600;\n  }\n\n  .lg-toast-description {\n    margin-top: 0.25rem;\n    color: var(--lg-muted-foreground);\n    font-size: 0.875rem;\n    line-height: calc(1.25 / 0.875);\n  }\n\n  /* ============================================\n     Reduced transparency\n     ============================================ */\n\n  /* Preference guards are !important because consumer utilities outrank every\n     other library default. Restyle them through --lg-opaque-surface and\n     --lg-control-surface, never by undoing the guard. */\n  [data-lg-reduce-transparency='1'] .lg-glass-surface::before {\n    -webkit-backdrop-filter: none !important;\n    backdrop-filter: none !important;\n    background: var(--lg-opaque-surface) !important;\n    box-shadow: none !important;\n    transform: none;\n  }\n\n  /* The ring keeps its mask and turns into a plain hairline border. */\n  [data-lg-reduce-transparency='1'] .lg-glass-surface::after,\n  [data-lg-reduce-transparency='1'] .lg-tabs-trigger[data-state='active']::after {\n    background: var(--lg-border);\n  }\n\n  /* The button draws the same hairline as an inset ring. A masked fill would\n     read to contrast checkers as a veil over the label. */\n  [data-lg-reduce-transparency='1'] .lg-button__rim {\n    background: none;\n    box-shadow: inset 0 0 0 var(--lg-rim-width) var(--lg-border);\n  }\n\n  [data-lg-reduce-transparency='1']\n    :is(\n      .lg-dialog-content,\n      .lg-popover-content,\n      .lg-toast-root,\n      .lg-tooltip-content,\n      .lg-sheet-content,\n      .lg-menu-content,\n      .lg-select-content,\n      .lg-dock-label\n    ) {\n    background: var(--lg-opaque-surface) !important;\n    -webkit-backdrop-filter: none !important;\n    backdrop-filter: none !important;\n  }\n\n  [data-lg-reduce-transparency='1']\n    :is(\n      .lg-button__distortion,\n      .lg-input,\n      .lg-accordion-trigger,\n      .lg-dialog-overlay,\n      .lg-badge,\n      .lg-alert\n    ) {\n    -webkit-backdrop-filter: none !important;\n    backdrop-filter: none !important;\n  }\n\n  /* Prominent glass has no fill of its own, so without the glass it is the\n     plain fill. */\n  [data-lg-reduce-transparency='1']\n    .lg-button--prominent\n    > .lg-button__layers\n    > .lg-button__distortion {\n    background: var(--lg-prominent-fill) !important;\n  }\n\n  [data-lg-reduce-transparency='1'] .lg-button__layers > .lg-button__light {\n    display: none !important;\n  }\n\n  /* Knobs stay solid white instead of turning to clear glass. */\n  [data-lg-reduce-transparency='1'] :is(.lg-switch-thumb, .lg-slider-thumb) {\n    background: var(--lg-knob) !important;\n  }\n\n  [data-lg-reduce-transparency='1'] .lg-switch-lens,\n  [data-lg-reduce-transparency='1'] .lg-switch-thumb::after {\n    display: none;\n  }\n\n  [data-lg-reduce-transparency='1'] .lg-button__shine,\n  [data-lg-reduce-transparency='1'] .lg-button__tint {\n    opacity: 0;\n  }\n\n  [data-lg-reduce-transparency='1'] .lg-button__bloom {\n    display: none;\n  }\n\n  [data-lg-reduce-transparency='1'] .lg-refraction-background {\n    display: none;\n  }\n\n  /* ============================================\n     Increased contrast: glass dimmed or frosted denser (see the tokens above),\n     edged by a ring in the text colour. The ring is the specular layer, which\n     paints above the frost, so every engine shows it.\n     Forced colors: solid surfaces, real outlines.\n     Both: buttons and fields drop their blur, and controls get outlines in the\n     text colour.\n     ============================================ */\n\n  @media (prefers-contrast: more) {\n    /* A guard like the transparency ones, so their hairline cannot replace it. */\n    .lg-glass-surface::after {\n      background: var(--lg-foreground) !important;\n    }\n\n    /* Dark glass adds no white of its own: presets and hover keep the base veil. */\n    [data-lg-theme='dark'] .lg-glass-surface {\n      --lg-surface-alpha: var(--lg-glass-alpha) !important;\n      --lg-surface-lift: 0 !important;\n    }\n\n    /* Light segmented tracks frost like the other glass, not as a slate well. */\n    [data-lg-theme='light']:not([data-lg-reduce-transparency='1']) .lg-segmented::before {\n      background-color: rgb(255 255 255 / var(--lg-glass-alpha));\n    }\n\n    /* A generated refraction shows its backdrop undimmed, so the pane frosts\n       and dims the page behind it instead. */\n    .lg-refraction-background {\n      display: none;\n    }\n\n    .lg-glass-surface[data-lg-generated-refraction='true']::before {\n      -webkit-backdrop-filter: blur(var(--lg-surface-blur)) brightness(var(--lg-glass-brightness))\n        contrast(var(--lg-glass-contrast)) saturate(var(--lg-glass-sat));\n      backdrop-filter: blur(var(--lg-surface-blur)) brightness(var(--lg-glass-brightness))\n        contrast(var(--lg-glass-contrast)) saturate(var(--lg-glass-sat));\n    }\n\n    /* Badges and alerts keep the solid fill their tone colours are set on. */\n    .lg-badge,\n    .lg-alert {\n      -webkit-backdrop-filter: none !important;\n      backdrop-filter: none !important;\n      background: var(--lg-opaque-surface) !important;\n    }\n\n    /* Overlays scroll their content, and their ring layer with it, so they\n       carry the ring as an outline that stays on their edge, focused or not. */\n    :is(\n      .lg-dialog-content,\n      .lg-popover-content,\n      .lg-sheet-content,\n      .lg-menu-content,\n      .lg-select-content\n    ) {\n      outline: 1px solid var(--lg-foreground) !important;\n      outline-offset: -1px !important;\n    }\n\n    :is(\n      .lg-dialog-content,\n      .lg-popover-content,\n      .lg-sheet-content,\n      .lg-menu-content,\n      .lg-select-content\n    )::after {\n      display: none;\n    }\n  }\n\n  @media (forced-colors: active) {\n    .lg-glass-surface {\n      outline: 1px solid CanvasText !important;\n      outline-offset: -1px !important;\n    }\n\n    .lg-glass-surface::before,\n    .lg-dialog-content,\n    .lg-popover-content,\n    .lg-toast-root,\n    .lg-tooltip-content,\n    .lg-sheet-content,\n    .lg-menu-content,\n    .lg-select-content,\n    .lg-dock-label,\n    .lg-badge,\n    .lg-alert {\n      -webkit-backdrop-filter: none !important;\n      backdrop-filter: none !important;\n      background: var(--lg-opaque-surface) !important;\n    }\n\n    .lg-glass-surface::before {\n      box-shadow: none !important;\n    }\n\n    /* The 1px outline replaces the specular ring. */\n    .lg-glass-surface::after {\n      display: none;\n    }\n\n    .lg-refraction-background {\n      display: none;\n    }\n  }\n\n  @media (prefers-contrast: more), (forced-colors: active) {\n    .lg-badge,\n    .lg-alert,\n    .lg-kbd,\n    .lg-progress-track,\n    .lg-dock-label,\n    .lg-switch,\n    .lg-slider-track,\n    .lg-segmented-indicator,\n    .lg-tabs-indicator {\n      outline: 1px solid CanvasText;\n      outline-offset: -1px;\n    }\n\n    .lg-segmented-indicator::after,\n    .lg-tabs-indicator::after,\n    .lg-lens::after,\n    .lg-button__bloom,\n    .lg-switch-lens,\n    .lg-switch-thumb::after {\n      display: none;\n    }\n\n    /* The switch's knob stays solid instead of turning to clear glass; forced\n       colours paint it with system colours below. */\n    .lg-switch-thumb {\n      background: var(--lg-knob) !important;\n    }\n\n    .lg-lens {\n      outline: 2px solid CanvasText;\n    }\n\n    .lg-tabs-trigger[data-state='active']::after {\n      display: none;\n    }\n\n    .lg-button:not(.lg-button--ghost, .lg-button--prominent) {\n      --lg-button-fill: var(--lg-opaque-surface) !important;\n      --lg-button-fill-hover: var(--lg-opaque-surface) !important;\n    }\n\n    .lg-button--prominent > .lg-button__layers > .lg-button__distortion {\n      background: var(--lg-prominent-fill) !important;\n    }\n\n    .lg-button__layers > .lg-button__light {\n      display: none !important;\n    }\n\n    .lg-button__distortion,\n    .lg-input,\n    .lg-accordion-trigger,\n    .lg-dialog-overlay {\n      -webkit-backdrop-filter: none !important;\n      backdrop-filter: none !important;\n    }\n\n    .lg-button .lg-button__rim {\n      padding: 0;\n      border: 1px solid CanvasText;\n      background: none;\n      -webkit-mask: none;\n      mask: none;\n    }\n\n    .lg-input,\n    .lg-checkbox,\n    .lg-radio,\n    .lg-accordion-trigger {\n      border-color: CanvasText !important;\n    }\n\n    /* Focusable surfaces such as tab panels need a ring distinct from the\n       1px surface outline. */\n    .lg-button:focus-visible,\n    .lg-input:focus,\n    .lg-checkbox:focus-visible,\n    .lg-radio:focus-visible,\n    .lg-glass-surface:focus-visible {\n      outline: 2px solid CanvasText !important;\n      outline-offset: 2px !important;\n    }\n  }\n\n  /* Forced colors repaint every author color, so the controls whose state is\n     their color opt out and use system colors directly. */\n  @media (forced-colors: active) {\n    .lg-switch,\n    .lg-switch-thumb,\n    .lg-slider-range,\n    .lg-slider-thumb,\n    .lg-segmented-indicator,\n    .lg-tabs-indicator,\n    .lg-checkbox,\n    .lg-radio,\n    .lg-progress-fill,\n    .lg-menu-item,\n    .lg-command-item {\n      forced-color-adjust: none;\n    }\n\n    .lg-progress-fill {\n      background: Highlight;\n      box-shadow: none;\n    }\n\n    .lg-page[data-current] {\n      background: Highlight;\n      color: HighlightText;\n      forced-color-adjust: none;\n    }\n\n    .lg-switch {\n      background: Canvas;\n    }\n\n    .lg-checkbox,\n    .lg-radio {\n      border-color: CanvasText;\n      background: Canvas;\n      box-shadow: none;\n      color: HighlightText;\n    }\n\n    .lg-checkbox[data-state='checked'],\n    .lg-checkbox[data-state='indeterminate'],\n    .lg-radio[data-state='checked'] {\n      border-color: Highlight;\n      background: Highlight;\n    }\n\n    .lg-radio-dot {\n      background: HighlightText;\n      box-shadow: none;\n    }\n\n    /* Forced colours strip the fill that gives an avatar its shape. */\n    .lg-avatar-face {\n      border: 1px solid CanvasText;\n      box-sizing: border-box;\n    }\n\n    .lg-switch[data-state='checked'],\n    .lg-slider-range,\n    .lg-menu-item[data-highlighted],\n    .lg-command-item[data-selected='true'] {\n      background: Highlight;\n      color: HighlightText;\n    }\n\n    /* A guard, like the transparency ones: the bubbles' glass rules are more\n       specific. */\n    .lg-segmented-indicator,\n    .lg-tabs-indicator {\n      background: Highlight !important;\n    }\n\n    /* The list prefix outranks the controls' own later state colors. */\n    .lg-tabs-list .lg-tabs-trigger[data-state='active'] {\n      color: HighlightText;\n      forced-color-adjust: none;\n    }\n\n    .lg-tabs-list:not([data-lg-indicator='ready']) .lg-tabs-trigger[data-state='active'] {\n      background: Highlight;\n    }\n\n    .lg-switch-thumb,\n    .lg-slider-thumb {\n      background: CanvasText !important;\n      box-shadow: none;\n    }\n\n    .lg-switch[data-state='checked'] .lg-switch-thumb {\n      background: HighlightText !important;\n    }\n\n    .lg-segmented .lg-segmented-item[data-state='checked'] {\n      color: HighlightText;\n      forced-color-adjust: none;\n    }\n\n    .lg-menu-item,\n    .lg-command-item,\n    .lg-toast-close {\n      color: CanvasText;\n    }\n  }\n\n  /* --- Buttons --- */\n\n  .lg-button {\n    --lg-radius: 999px;\n    --lg-surface-blur: min(var(--lg-glass-blur), 16px);\n    --lg-ink: var(--lg-foreground);\n    --lg-button-fill: rgb(255 255 255 / 0.07);\n    --lg-button-fill-hover: rgb(255 255 255 / 0.11);\n    --lg-button-sheen: 0.1;\n    --lg-button-glow: 0.14;\n    --lg-button-glow-pressed: 0.26;\n    --lg-button-shine: var(--lg-button-glow);\n    /* The fill highlight sits between the light and the centre. */\n    --lg-fill-x: calc(0.5 + (var(--lg-light-x) - 0.5) * 0.35);\n    --lg-fill-y: calc(0.5 + (var(--lg-light-y) - 0.5) * 0.35);\n    --lg-rim-scale: var(--lg-debug-rim-thickness, 1);\n    --lg-rim-offset-max: 1.1px;\n    --lg-rim-tangent-alpha: 1;\n    --lg-rim-micro-mask: 1;\n    --lg-rim-corner-mask: 1;\n    --lg-rim-offset-x: clamp(\n      calc(-1 * var(--lg-rim-offset-max)),\n      calc(var(--lg-light-dir-x) * -1 * var(--lg-rim-offset-max) * (0.7 + var(--lg-light-level))),\n      var(--lg-rim-offset-max)\n    );\n    --lg-rim-offset-y: clamp(\n      calc(-1 * var(--lg-rim-offset-max)),\n      calc(var(--lg-light-dir-y) * -1 * var(--lg-rim-offset-max) * (0.7 + var(--lg-light-level))),\n      var(--lg-rim-offset-max)\n    );\n    --lg-rim-light: calc(var(--lg-button-reflex-light) * var(--lg-rim-gain));\n    --lg-rim-dark: var(--lg-reflex-dark);\n    --lg-rim-alpha: calc((0.08 + var(--lg-light-level) * 0.12) * var(--lg-rim-gain));\n    --lg-rim-ca-offset: calc(1.5px * var(--lg-debug-ca-offset-scale, 1));\n    --lg-rim-ca-alpha: calc(0.06 * var(--lg-debug-ca-scale, 1));\n\n    position: relative;\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    gap: 0.5rem;\n    padding: 0.75rem 1.5rem;\n\n    border-radius: var(--lg-radius);\n    border: none;\n    background: transparent;\n    color: var(--lg-ink);\n    text-decoration: none;\n\n    font-weight: 500;\n    letter-spacing: -0.01em;\n    isolation: isolate;\n    cursor: pointer;\n    contain: layout paint style;\n\n    /* Each button is a slab of glass resting just above the page, lit from\n       above. A pointer lowers it halfway and a press sets it down, so its\n       shadow draws in under it; the glass itself stays put. */\n    --lg-button-rise: 1;\n    --lg-button-rise-time: calc(var(--lg-motion-duration) * 1.6);\n    --lg-button-shade: 0 0 0;\n    --lg-button-shade-near: 0.32;\n    --lg-button-shade-far: 0.36;\n    transition: --lg-button-rise var(--lg-button-rise-time) var(--lg-ease-out);\n  }\n\n  @media (hover: hover) {\n    .lg-button:not(:disabled, [aria-disabled='true']):hover {\n      --lg-button-rise: 0.5;\n    }\n  }\n\n  .lg-button[data-pressed='true']:not(:disabled, [aria-disabled='true']) {\n    --lg-button-rise: 0.2;\n    --lg-button-rise-time: calc(var(--lg-motion-duration) * 0.6);\n  }\n\n  .lg-button[data-lg-preset='control'] {\n    --lg-surface-blur: min(var(--lg-glass-blur), 10px);\n  }\n\n  .lg-button[data-lg-preset='showcase'] {\n    --lg-surface-blur: min(var(--lg-glass-blur), 16px);\n  }\n\n  .lg-button:focus-visible {\n    outline: 2px solid var(--lg-focus-ring);\n    outline-offset: 2px;\n  }\n\n  /* Disabled buttons dim their content, never the host: opacity on an ancestor\n     of the frost layer isolates its backdrop and flattens the glass. */\n  .lg-button:disabled,\n  .lg-button[aria-disabled='true'] {\n    cursor: not-allowed;\n    transform: none;\n  }\n\n  .lg-button:disabled :is(.lg-button__label, .lg-button__tint, .lg-button__rim),\n  .lg-button[aria-disabled='true'] :is(.lg-button__label, .lg-button__tint, .lg-button__rim) {\n    opacity: var(--lg-disabled-opacity);\n  }\n\n  .lg-button__layers {\n    position: absolute;\n    inset: 0;\n    border-radius: inherit;\n    pointer-events: none;\n    z-index: 0;\n    overflow: hidden;\n  }\n\n  /* Icons and text sit in one row, spaced by the button's own gap. */\n  .lg-button__label {\n    position: relative;\n    z-index: 1;\n    display: inline-flex;\n    align-items: center;\n    gap: inherit;\n  }\n\n  .lg-button__layers > span {\n    position: absolute;\n    inset: 0;\n    border-radius: inherit;\n  }\n\n  /* 0. The light the glass lets through, under it. Tinted glass shows it. */\n  .lg-button__layers > .lg-button__light {\n    display: none;\n  }\n\n  /* 1. Frost: the only backdrop layer */\n  .lg-button__distortion {\n    background: var(--lg-button-fill);\n    -webkit-backdrop-filter: blur(var(--lg-surface-blur)) saturate(var(--lg-glass-sat));\n    backdrop-filter: blur(var(--lg-surface-blur)) saturate(var(--lg-glass-sat));\n    transition: background-color var(--lg-motion-duration) ease;\n  }\n\n  .lg-button[data-lg-lens='active'] > .lg-button__layers > .lg-button__distortion {\n    backdrop-filter: var(--lg-lens-filter);\n  }\n\n  .lg-button:not(:disabled, [aria-disabled='true']):hover .lg-button__distortion {\n    background: var(--lg-button-fill-hover);\n  }\n\n  /* 2. Sheen and bevel: top-lit gradient, a gentle fixed highlight and the\n     shared glass bevel */\n  .lg-button__tint {\n    background:\n      radial-gradient(\n        circle at calc(var(--lg-fill-x) * 100%) calc(var(--lg-fill-y) * 100%),\n        rgb(255 255 255 / calc(var(--lg-light-level) * 0.08)),\n        transparent 70%\n      ),\n      linear-gradient(180deg, rgb(255 255 255 / var(--lg-button-sheen)), transparent 60%);\n    box-shadow: var(--lg-glass-rim);\n  }\n\n  /* 3. Shine: hover glow that lights up from within while pressed */\n  .lg-button__shine {\n    background: radial-gradient(\n      circle at calc(var(--lg-fill-x) * 100%) calc(var(--lg-fill-y) * 100%),\n      rgb(255 255 255 / var(--lg-button-shine)),\n      transparent 60%\n    );\n    opacity: 0;\n    transition: opacity var(--lg-motion-duration) ease;\n  }\n\n  .lg-button:not(:disabled, [aria-disabled='true']):hover .lg-button__shine,\n  .lg-button[data-pressed='true']:not(:disabled, [aria-disabled='true']) .lg-button__shine {\n    opacity: 1;\n  }\n\n  .lg-button[data-pressed='true'] {\n    --lg-button-shine: var(--lg-button-glow-pressed);\n  }\n\n  /* 4. Bloom: a press lights the glass from the fingertip outward. Script\n     places it at the press point and plays it once per press. It stays\n     faint: the slab setting down carries the press, and the light only\n     marks where it landed. */\n  .lg-button__layers > .lg-button__bloom {\n    inset: auto;\n    top: var(--lg-bloom-y, 50%);\n    left: var(--lg-bloom-x, 50%);\n    width: var(--lg-bloom-size, 0px);\n    height: var(--lg-bloom-size, 0px);\n    border-radius: 50%;\n    background: radial-gradient(\n      closest-side,\n      rgb(255 255 255 / 0.18),\n      rgb(255 255 255 / 0.05) 60%,\n      transparent\n    );\n    opacity: 0;\n    translate: -50% -50%;\n  }\n\n  /* 5. Rim: the shared specular ring */\n  .lg-button__rim {\n    padding: var(--lg-rim-width);\n    background: var(--lg-specular-ring);\n    -webkit-mask:\n      linear-gradient(#000 0 0) content-box,\n      linear-gradient(#000 0 0);\n    -webkit-mask-composite: xor;\n    mask:\n      linear-gradient(#000 0 0) content-box,\n      linear-gradient(#000 0 0);\n    mask-composite: exclude;\n  }\n\n  /* Button Variants. A slab's shadow falls straight down from it and draws in\n     as it lowers: a near, sharp contact shadow and a soft one further out. */\n  .lg-button--primary,\n  .lg-button--soft {\n    box-shadow:\n      0 calc(var(--lg-button-rise) * 1.8px) calc(var(--lg-button-rise) * 2px)\n        calc(var(--lg-button-rise) * -1px) rgb(var(--lg-button-shade) / var(--lg-button-shade-near)),\n      0 calc(var(--lg-button-rise) * 6.7px) calc(var(--lg-button-rise) * 10px)\n        calc(var(--lg-button-rise) * -5px) rgb(var(--lg-button-shade) / var(--lg-button-shade-far));\n  }\n\n  .lg-button--soft {\n    --lg-button-fill: rgb(255 255 255 / 0.04);\n    --lg-button-fill-hover: rgb(255 255 255 / 0.08);\n    --lg-button-shade-near: 0.2;\n    --lg-button-shade-far: 0.18;\n  }\n\n  .lg-button--ghost {\n    --lg-button-fill: transparent;\n    --lg-button-fill-hover: rgb(255 255 255 / 0.06);\n    box-shadow: none;\n  }\n\n  .lg-button--ghost .lg-button__distortion {\n    -webkit-backdrop-filter: none;\n    backdrop-filter: none;\n  }\n\n  .lg-button--ghost :is(.lg-button__rim, .lg-button__tint) {\n    display: none;\n  }\n\n  /* Sizes */\n  .lg-button--sm {\n    font-size: 0.8rem;\n    padding: 0.4rem 0.8rem;\n  }\n  .lg-button--md {\n    font-size: 0.95rem;\n    padding: 0.7rem 1.4rem;\n  }\n  .lg-button--lg {\n    font-size: 1.1rem;\n    padding: 1rem 2rem;\n  }\n\n  /* ============================================\n     LIGHT THEME - Button Overrides\n     ============================================ */\n\n  [data-lg-theme='light'] .lg-button {\n    --lg-button-fill: rgb(255 255 255 / 0.45);\n    --lg-button-fill-hover: rgb(255 255 255 / 0.6);\n    --lg-button-sheen: 0.35;\n    --lg-button-glow: 0.45;\n    --lg-button-glow-pressed: 0.75;\n    --lg-button-shade: 52 62 84;\n    --lg-button-shade-near: 0.18;\n    --lg-button-shade-far: 0.2;\n  }\n\n  [data-lg-theme='light'] .lg-button--soft {\n    --lg-button-shade-near: 0.12;\n    --lg-button-shade-far: 0.12;\n  }\n\n  [data-lg-theme='light'] .lg-button--soft {\n    --lg-button-fill: rgb(255 255 255 / 0.3);\n    --lg-button-fill-hover: rgb(255 255 255 / 0.45);\n  }\n\n  [data-lg-theme='light'] .lg-button--ghost {\n    --lg-button-fill: transparent;\n    --lg-button-fill-hover: rgb(0 0 0 / 0.04);\n  }\n\n  /* Prominent: a slab of blue glass. It passes on the light of whatever\n     lies behind it, tinted blue, so the page, the light it lets through and\n     the shadow under it all show in it. The tint caps how bright that light\n     can get, which keeps white text legible over any backdrop. Two classes\n     outrank the light-theme overrides above. */\n  .lg-button.lg-button--prominent {\n    --lg-ink: var(--lg-accent-foreground);\n    --lg-button-fill: var(--lg-prominent-fill);\n    --lg-button-fill-hover: var(--lg-prominent-fill);\n    --lg-button-sheen: 0;\n    --lg-button-glow: 0;\n    --lg-button-glow-pressed: 0;\n    /* The rays of the light cross the glass along x and y. */\n    --lg-button-ray-x: calc(sin(var(--lg-button-light-angle)) * -1);\n    --lg-button-ray-y: cos(var(--lg-button-light-angle));\n    /* The light eases over, gently at both ends, and returns briskly. */\n    --lg-button-rise-time: calc(var(--lg-motion-duration) * 1.5);\n    --lg-button-light-time: calc(var(--lg-motion-duration) * 1.75);\n    --lg-button-light-ease: cubic-bezier(0.25, 0.8, 0.3, 1);\n    /* The shadow stays under the slab and draws in as it lowers; only the\n       light along the rim follows the light. */\n    box-shadow:\n      0 calc(var(--lg-button-rise) * 1.8px) calc(var(--lg-button-rise) * 2px)\n        calc(var(--lg-button-rise) * -1px) rgb(var(--lg-prominent-shade) / 0.4),\n      0 calc(var(--lg-button-rise) * 6.7px) calc(var(--lg-button-rise) * 10px)\n        calc(var(--lg-button-rise) * -5px) rgb(var(--lg-prominent-shade) / 0.4);\n    transition:\n      --lg-button-rise var(--lg-button-rise-time) cubic-bezier(0.25, 0.8, 0.3, 1),\n      --lg-button-light-angle var(--lg-button-light-time) var(--lg-button-light-ease);\n  }\n\n  /* A pointer lowers the slab like any button and swings its light 50deg over\n     to the top left. */\n  @media (hover: hover) {\n    .lg-button.lg-button--prominent:not(:disabled, [aria-disabled='true']):hover {\n      --lg-button-light-angle: -50deg;\n      --lg-button-light-time: calc(var(--lg-motion-duration) * 2.75);\n      --lg-button-light-ease: cubic-bezier(0.45, 0, 0.55, 1);\n    }\n  }\n\n  /* Under the glass lies the light it lets through: a dim pool, a dark line\n     where the rounded edge turns the light aside and a bright one just inside\n     it where the edge gathers it. It sits a little below the glass, further\n     the higher the glass rests, so a press all but hides it. The pool is dense\n     enough that, should an ancestor cut the glass off from the page (opacity,\n     a filter or a mask), it alone keeps the white label at 4.5:1 over white. */\n  .lg-button--prominent > .lg-button__layers > .lg-button__light {\n    --lg-rise-cubed: calc(var(--lg-button-rise) * var(--lg-button-rise) * var(--lg-button-rise));\n\n    display: block;\n    /* Light coming in at a slant crosses the glass at a slant, so the pool\n       moves away from it. */\n    translate: calc(var(--lg-button-ray-x) * 1.2px) calc(var(--lg-rise-cubed) * 2px);\n    background: rgb(var(--lg-prominent-shade) / 0.6);\n    box-shadow:\n      inset 0 0 0 calc(1px + var(--lg-rise-cubed) * 1.6px) rgb(var(--lg-prominent-shade) / 0.5),\n      inset 0 0 0 calc(2px + var(--lg-rise-cubed) * 2.2px) rgb(var(--lg-prominent-glow) / 0.75);\n    filter: blur(calc(0.2px + var(--lg-button-rise) * 0.4px));\n  }\n\n  /* The face is that light, tinted. Its faint sheen turns with the light. */\n  .lg-button--prominent > .lg-button__layers > .lg-button__distortion {\n    -webkit-backdrop-filter: blur(0.6px) var(--lg-prominent-tint);\n    backdrop-filter: blur(0.6px) var(--lg-prominent-tint);\n    /* The solid fill replaces the tint and light together. Fading only the\n       fill exposes the untinted backdrop while those layers switch. */\n    transition: none;\n  }\n\n  .lg-button--prominent > .lg-button__layers > .lg-button__distortion,\n  .lg-button--prominent:not(:disabled, [aria-disabled='true']):hover\n    > .lg-button__layers\n    > .lg-button__distortion {\n    background: linear-gradient(\n      calc(180deg + var(--lg-button-light-angle)),\n      rgb(255 255 255 / 0.07),\n      transparent 45%\n    );\n  }\n\n  /* In Chromium the edge lens bends the light at the rim, then it is tinted. */\n  .lg-button--prominent[data-lg-lens='active'] > .lg-button__layers > .lg-button__distortion {\n    backdrop-filter: var(--lg-lens-filter) var(--lg-prominent-tint);\n  }\n\n  /* The rim: a dark line at the very edge, where it turns the light aside, a\n     soft sheen under the top, where it faces the light, and a glow along the\n     bottom, where the light the slab carried across leaves it. Set down, the\n     glass gathers more of that light and glows all round. All of it turns\n     with the light: the sheen moves round to the edge facing it and the glow\n     round to the far edge. */\n  .lg-button--prominent > .lg-button__layers > .lg-button__tint {\n    --lg-button-sunk: calc(1 - var(--lg-button-rise));\n\n    background: none;\n    box-shadow:\n      inset 0 0 0 1px rgb(var(--lg-prominent-shade) / 0.32),\n      inset calc(var(--lg-button-ray-x) * -5px) calc(var(--lg-button-ray-y) * -5px) 7px -4px\n        rgb(var(--lg-prominent-glow) / calc(0.5 + var(--lg-button-sunk) * 0.35)),\n      inset 0 0 calc(4px + var(--lg-button-sunk) * 10px) 0\n        rgb(var(--lg-prominent-glow) / calc(var(--lg-button-sunk) * 0.32)),\n      inset calc(var(--lg-button-ray-x) * 7px) calc(var(--lg-button-ray-y) * 7px) 8px -7px\n        rgb(255 255 255 / 0.22),\n      inset calc(var(--lg-button-ray-x) * 3px) calc(var(--lg-button-ray-y) * 3px) 4px -2px\n        rgb(0 0 0 / 0.08);\n  }\n\n  /* Just inside the dark line, a bright one where the edge gathers the\n     light: strongest along the top, faint at the sides, blue below. It turns\n     with the light, so the bright line moves round to the end facing it and\n     the blue one to the far end. */\n  .lg-button--prominent > .lg-button__layers > .lg-button__rim {\n    inset: 1px;\n    padding: 1px;\n    background: linear-gradient(\n      calc(180deg + var(--lg-button-light-angle)),\n      rgb(255 255 255 / 0.78),\n      rgb(255 255 255 / 0.12) 36% 64%,\n      rgb(var(--lg-prominent-glow) / 0.62)\n    );\n  }\n\n  /* Over a pale page the bright line brightens as the light swings over, so\n     it reads as clearly as it does against a dark one. */\n  [data-lg-theme='light'] .lg-button--prominent > .lg-button__layers > .lg-button__rim {\n    background: linear-gradient(\n      calc(180deg + var(--lg-button-light-angle)),\n      rgb(255 255 255 / calc(0.78 + max(0, var(--lg-button-ray-x)) * 0.2)),\n      rgb(255 255 255 / 0.12) 36% 64%,\n      rgb(var(--lg-prominent-glow) / 0.62)\n    );\n  }\n\n  /* Without a backdrop filter the face is the plain fill. */\n  @supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {\n    .lg-button--prominent > .lg-button__layers > .lg-button__distortion {\n      background: var(--lg-prominent-fill);\n    }\n  }\n\n  [data-lg-reduce-transparency='1'] .lg-button:not(.lg-button--ghost, .lg-button--prominent) {\n    --lg-button-fill: var(--lg-control-surface) !important;\n    --lg-button-fill-hover: var(--lg-control-surface-hover) !important;\n  }\n\n  /* Input Fields: a recessed glass well */\n  .lg-input {\n    width: 100%;\n    padding: 0.875rem 1.25rem;\n    border-radius: 16px;\n    border: 1px solid var(--lg-border);\n    background: var(--lg-control-surface);\n    color: var(--lg-foreground);\n    font-size: 1rem;\n    outline: none;\n    transition:\n      background var(--lg-motion-duration) ease,\n      border-color var(--lg-motion-duration) ease,\n      box-shadow var(--lg-motion-duration) ease;\n    -webkit-backdrop-filter: blur(min(var(--lg-glass-blur), 16px))\n      brightness(var(--lg-glass-brightness)) contrast(var(--lg-glass-contrast))\n      saturate(var(--lg-glass-sat));\n    backdrop-filter: blur(min(var(--lg-glass-blur), 16px)) brightness(var(--lg-glass-brightness))\n      contrast(var(--lg-glass-contrast)) saturate(var(--lg-glass-sat));\n    box-shadow: var(--lg-input-shadow);\n  }\n\n  .lg-input:focus {\n    background: var(--lg-control-surface-hover);\n    border-color: var(--lg-focus-ring);\n    box-shadow: 0 0 0 1px var(--lg-focus-ring);\n  }\n\n  .lg-input:focus-visible {\n    outline: 2px solid var(--lg-focus-ring);\n    outline-offset: 2px;\n  }\n\n  .lg-input::placeholder {\n    color: var(--lg-muted-foreground);\n    opacity: 0.72;\n  }\n\n  .lg-input[aria-invalid='true'] {\n    border-color: var(--lg-invalid);\n    box-shadow: 0 0 0 1px var(--lg-invalid);\n  }\n\n  .lg-input:disabled {\n    cursor: not-allowed;\n    opacity: var(--lg-disabled-opacity);\n  }\n\n  /* ============================================\n     Checkbox and radio: a small glass well that fills with the accent, with a\n     mark that draws itself in and back out, so clearing a choice moves as\n     smoothly as making it. Every transition sits on the base rule, never on\n     the checked one, so both directions animate.\n     ============================================ */\n\n  .lg-check-field {\n    display: flex;\n    align-items: flex-start;\n    gap: 0.75rem;\n    color: var(--lg-foreground);\n    font-size: 0.9375rem;\n    line-height: 1.4;\n  }\n\n  .lg-check-text {\n    display: flex;\n    min-width: 0;\n    flex-direction: column;\n    padding-top: 0.0625rem;\n  }\n\n  /* Clicking the label toggles the box, so a quick second click must not select its text. The\n     description below it stays selectable. */\n  .lg-check-text > label {\n    cursor: pointer;\n    user-select: none;\n  }\n\n  .lg-check-text > span {\n    color: var(--lg-muted-foreground);\n    font-size: 0.8125rem;\n    line-height: 1.35;\n  }\n\n  .lg-check-field[data-size='sm'] {\n    gap: 0.625rem;\n    font-size: 0.875rem;\n  }\n\n  .lg-check-field[data-disabled] {\n    opacity: var(--lg-disabled-opacity);\n  }\n\n  .lg-check-field[data-disabled] .lg-check-text > label {\n    cursor: not-allowed;\n  }\n\n  .lg-radio-group {\n    display: grid;\n    gap: 0.75rem;\n  }\n\n  .lg-checkbox,\n  .lg-radio {\n    --lg-check-size: 1.25rem;\n    /* The edge of an empty box is what says it can be ticked, so it holds 3:1 over the\n       glass it sits on, which the hairline border of a text field does not. */\n    --lg-check-edge: rgb(244 245 249 / 0.78);\n\n    position: relative;\n    display: inline-grid;\n    flex: none;\n    place-items: center;\n    box-sizing: border-box;\n    width: var(--lg-check-size);\n    height: var(--lg-check-size);\n    margin: 0;\n    padding: 0;\n    border: 1.5px solid var(--lg-check-edge);\n    background: var(--lg-control-surface);\n    box-shadow: var(--lg-input-shadow);\n    color: #fff;\n    cursor: pointer;\n    -webkit-tap-highlight-color: transparent;\n    transition:\n      background-color 220ms ease,\n      border-color 220ms ease,\n      box-shadow 220ms ease,\n      scale 320ms var(--lg-spring);\n  }\n\n  [data-lg-theme='light'] .lg-checkbox,\n  [data-lg-theme='light'] .lg-radio {\n    --lg-check-edge: rgb(27 29 36 / 0.6);\n  }\n\n  .lg-checkbox {\n    border-radius: 0.4375rem;\n  }\n\n  .lg-radio {\n    border-radius: 9999px;\n  }\n\n  .lg-checkbox[data-size='sm'],\n  .lg-check-field[data-size='sm'] .lg-checkbox {\n    --lg-check-size: 1rem;\n\n    border-radius: 0.3125rem;\n  }\n\n  .lg-checkbox[data-state='unchecked']:hover:not([data-disabled]),\n  .lg-radio[data-state='unchecked']:hover:not([data-disabled]) {\n    background: var(--lg-control-surface-hover);\n  }\n\n  .lg-checkbox:active:not([data-disabled]),\n  .lg-radio:active:not([data-disabled]) {\n    scale: 0.9;\n  }\n\n  .lg-checkbox:focus-visible,\n  .lg-radio:focus-visible {\n    outline: 2px solid var(--lg-focus-ring);\n    outline-offset: 2px;\n  }\n\n  .lg-checkbox[aria-invalid='true'],\n  .lg-radio[aria-invalid='true'] {\n    border-color: var(--lg-invalid);\n  }\n\n  .lg-checkbox[data-disabled],\n  .lg-radio[data-disabled] {\n    cursor: not-allowed;\n    opacity: var(--lg-disabled-opacity);\n  }\n\n  .lg-checkbox[data-state='checked'],\n  .lg-checkbox[data-state='indeterminate'],\n  .lg-radio[data-state='checked'] {\n    border-color: transparent;\n    background:\n      linear-gradient(180deg, rgb(255 255 255 / 0.24), rgb(255 255 255 / 0) 62%), var(--lg-accent);\n    box-shadow:\n      inset 0 1px 0 rgb(255 255 255 / 0.4),\n      inset 0 -1px 0 rgb(0 0 0 / 0.14),\n      0 1px 3px rgb(0 0 0 / 0.28);\n  }\n\n  .lg-check-indicator {\n    display: grid;\n    width: 100%;\n    height: 100%;\n    place-items: center;\n    pointer-events: none;\n  }\n\n  .lg-check-mark {\n    width: 84%;\n    height: 84%;\n    fill: none;\n    stroke: currentColor;\n    stroke-width: 2.1;\n    stroke-linecap: round;\n    stroke-linejoin: round;\n  }\n\n  .lg-check-tick,\n  .lg-check-dash {\n    stroke-dasharray: 1;\n    stroke-dashoffset: 1;\n    transition: stroke-dashoffset 300ms var(--lg-ease-out);\n  }\n\n  .lg-checkbox[data-state='checked'] .lg-check-tick,\n  .lg-checkbox[data-state='indeterminate'] .lg-check-dash {\n    stroke-dashoffset: 0;\n  }\n\n  .lg-radio-dot {\n    width: 42%;\n    height: 42%;\n    border-radius: 9999px;\n    background: #fff;\n    box-shadow: 0 1px 2px rgb(0 0 0 / 0.3);\n    scale: 0;\n    transition: scale 160ms cubic-bezier(0.4, 0, 1, 1);\n  }\n\n  /* The dot springs in and shrinks straight out: the spring would swing it\n     through zero on the way back. */\n  .lg-radio[data-state='checked'] .lg-radio-dot {\n    scale: 1;\n    transition: scale 340ms var(--lg-spring);\n  }\n\n  /* ============================================\n     Textarea and select: the Input's recessed glass field\n     ============================================ */\n\n  .lg-textarea {\n    display: block;\n    min-height: 5.5rem;\n    line-height: 1.5;\n    resize: vertical;\n  }\n\n  .lg-textarea[data-resize='auto'] {\n    resize: none;\n    overflow-y: hidden;\n  }\n\n  .lg-select-trigger {\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    gap: 0.75rem;\n    text-align: start;\n    cursor: pointer;\n    user-select: none;\n  }\n\n  .lg-select-trigger > span:first-child {\n    min-width: 0;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n  }\n\n  .lg-select-trigger[data-placeholder] {\n    color: var(--lg-muted-foreground);\n  }\n\n  .lg-select-chevron {\n    display: inline-flex;\n    flex: none;\n    color: var(--lg-muted-foreground);\n    transition: rotate 260ms var(--lg-spring);\n  }\n\n  .lg-select-chevron > svg {\n    width: 1rem;\n    height: 1rem;\n  }\n\n  .lg-select-trigger[data-state='open'] .lg-select-chevron {\n    rotate: 180deg;\n  }\n\n  .lg-select-content {\n    --lg-panel-radius: 1.25rem;\n\n    z-index: 60;\n    box-sizing: border-box;\n    min-width: var(--radix-select-trigger-width);\n    max-width: calc(100vw - 1rem);\n    max-height: var(--radix-select-content-available-height, 24rem);\n    padding: 0.375rem;\n    font-size: 0.9375rem;\n    line-height: 1.4;\n    transform-origin: var(--radix-select-content-transform-origin);\n  }\n\n  .lg-select-content:focus {\n    outline: none;\n  }\n\n  .lg-select-viewport {\n    max-height: inherit;\n    overflow-y: auto;\n    overscroll-behavior: contain;\n    scrollbar-width: none;\n  }\n\n  .lg-select-viewport::-webkit-scrollbar {\n    display: none;\n  }\n\n  .lg-select-scroll {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    height: 1.5rem;\n    color: var(--lg-muted-foreground);\n    cursor: default;\n  }\n\n  .lg-select-scroll > svg {\n    width: 1rem;\n    height: 1rem;\n  }\n\n  /* ============================================\n     Progress, spinner and skeleton: waiting, told quietly\n     ============================================ */\n\n  .lg-visually-hidden {\n    position: absolute;\n    width: 1px;\n    height: 1px;\n    margin: -1px;\n    padding: 0;\n    overflow: hidden;\n    border: 0;\n    clip-path: inset(50%);\n    white-space: nowrap;\n  }\n\n  .lg-progress {\n    --lg-progress-height: 0.5rem;\n\n    display: grid;\n    gap: 0.5rem;\n    width: 100%;\n    color: var(--lg-foreground);\n    font-size: 0.875rem;\n    line-height: 1.25rem;\n  }\n\n  .lg-progress[data-size='sm'] {\n    --lg-progress-height: 0.25rem;\n  }\n\n  .lg-progress[data-size='lg'] {\n    --lg-progress-height: 0.75rem;\n  }\n\n  .lg-progress-header {\n    display: flex;\n    align-items: baseline;\n    justify-content: space-between;\n    gap: 1rem;\n  }\n\n  .lg-progress-value {\n    color: var(--lg-muted-foreground);\n    font-variant-numeric: tabular-nums;\n  }\n\n  .lg-progress-track {\n    position: relative;\n    height: var(--lg-progress-height);\n    overflow: hidden;\n    border-radius: 9999px;\n    background: var(--lg-track);\n    box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.18);\n  }\n\n  /* The whole pill slides in from the left, so its leading end stays round. */\n  .lg-progress-fill {\n    width: 100%;\n    height: 100%;\n    border-radius: inherit;\n    background-color: var(--lg-accent);\n    background-image: linear-gradient(180deg, rgb(255 255 255 / 0.34), rgb(255 255 255 / 0) 60%);\n    box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.4);\n    translate: calc((var(--lg-progress, 0) - 100) * 1%) 0;\n    transition: translate 640ms var(--lg-ease-out);\n  }\n\n  .lg-progress[data-state='indeterminate'] .lg-progress-fill {\n    width: 40%;\n    translate: 75% 0;\n    transition: none;\n    /* Stepped at 30 frames a second: a loader that runs for a while does not need a frame\n       every 8 ms, and the GPU is spared most of them. */\n    animation: lg-progress-sweep 1.6s steps(48) infinite;\n  }\n\n  @keyframes lg-progress-sweep {\n    from {\n      translate: -100% 0;\n    }\n\n    to {\n      translate: 250% 0;\n    }\n  }\n\n  .lg-spinner {\n    --lg-spinner-size: 1.5rem;\n    --lg-spinner-width: 2px;\n\n    display: inline-flex;\n    flex: none;\n    width: var(--lg-spinner-size);\n    height: var(--lg-spinner-size);\n    border-radius: 9999px;\n    box-shadow: inset 0 0 0 var(--lg-spinner-width)\n      color-mix(in srgb, currentColor 20%, transparent);\n    color: var(--lg-foreground);\n    vertical-align: middle;\n  }\n\n  .lg-spinner[data-size='sm'] {\n    --lg-spinner-size: 1rem;\n    --lg-spinner-width: 1.5px;\n  }\n\n  .lg-spinner[data-size='lg'] {\n    --lg-spinner-size: 2.25rem;\n    --lg-spinner-width: 3px;\n  }\n\n  .lg-spinner-ring {\n    width: 100%;\n    height: 100%;\n    border-radius: inherit;\n    background: conic-gradient(from 0deg, transparent, currentColor);\n    -webkit-mask: radial-gradient(\n      farthest-side,\n      transparent calc(100% - var(--lg-spinner-width) - 0.5px),\n      #000 calc(100% - var(--lg-spinner-width))\n    );\n    mask: radial-gradient(\n      farthest-side,\n      transparent calc(100% - var(--lg-spinner-width) - 0.5px),\n      #000 calc(100% - var(--lg-spinner-width))\n    );\n    animation: lg-spinner-turn 0.9s linear infinite;\n  }\n\n  @keyframes lg-spinner-turn {\n    to {\n      rotate: 360deg;\n    }\n  }\n\n  .lg-skeleton {\n    position: relative;\n    display: block;\n    min-height: 1rem;\n    overflow: hidden;\n    border-radius: 0.625rem;\n    background: var(--lg-control-surface);\n  }\n\n  .lg-skeleton[data-variant='circle'] {\n    width: 2.5rem;\n    min-height: 0;\n    aspect-ratio: 1;\n    border-radius: 9999px;\n  }\n\n  .lg-skeleton[data-variant='line'] {\n    min-height: 0;\n    height: 0.875rem;\n    border-radius: 9999px;\n  }\n\n  .lg-skeleton::after {\n    content: '';\n    position: absolute;\n    inset: 0;\n    background: linear-gradient(\n      100deg,\n      transparent 20%,\n      rgb(255 255 255 / 0.14) 50%,\n      transparent 80%\n    );\n    translate: -100% 0;\n    /* Stepped at 30 frames a second, like the progress sweep. */\n    animation: lg-skeleton-sheen 1.8s steps(54) infinite;\n  }\n\n  [data-lg-theme='light'] .lg-skeleton::after {\n    background: linear-gradient(\n      100deg,\n      transparent 20%,\n      rgb(255 255 255 / 0.75) 50%,\n      transparent 80%\n    );\n  }\n\n  @keyframes lg-skeleton-sheen {\n    to {\n      translate: 100% 0;\n    }\n  }\n\n  .lg-skeleton-text {\n    display: grid;\n    gap: 0.625rem;\n    width: 100%;\n  }\n\n  .lg-skeleton-text > .lg-skeleton:last-child:not(:only-child) {\n    width: 62%;\n  }\n\n  /* ============================================\n     Alert: tinted glass with the badge's tones. Every tone keeps 4.5:1 text\n     contrast over a pure black or pure white backdrop in both themes.\n     ============================================ */\n\n  .lg-alert {\n    --lg-alert-fill: 13 44 82;\n    --lg-alert-ink: #b2d6ff;\n    --lg-alert-tint: 0 103 217;\n    --lg-alert-highlight: rgb(255 255 255 / 0.12);\n\n    display: flex;\n    align-items: flex-start;\n    gap: 0.75rem;\n    box-sizing: border-box;\n    width: 100%;\n    padding: 0.875rem 1rem;\n    border-radius: 1.125rem;\n    background: rgb(var(--lg-alert-fill) / 0.88);\n    box-shadow:\n      inset 0 1px 0 var(--lg-alert-highlight),\n      inset 0 0 0 0.5px rgb(var(--lg-alert-tint) / 0.45);\n    color: var(--lg-foreground);\n    font-size: 0.9375rem;\n    line-height: 1.4;\n    -webkit-backdrop-filter: blur(min(var(--lg-glass-blur), 16px))\n      brightness(var(--lg-glass-brightness)) contrast(var(--lg-glass-contrast))\n      saturate(var(--lg-glass-sat));\n    backdrop-filter: blur(min(var(--lg-glass-blur), 16px)) brightness(var(--lg-glass-brightness))\n      contrast(var(--lg-glass-contrast)) saturate(var(--lg-glass-sat));\n  }\n\n  .lg-alert[data-tone='success'] {\n    --lg-alert-fill: 22 60 48;\n    --lg-alert-ink: #7cebc0;\n    --lg-alert-tint: 51 214 159;\n  }\n\n  .lg-alert[data-tone='warning'] {\n    --lg-alert-fill: 70 54 22;\n    --lg-alert-ink: #ffd27a;\n    --lg-alert-tint: 255 189 56;\n  }\n\n  .lg-alert[data-tone='danger'] {\n    --lg-alert-fill: 76 30 44;\n    --lg-alert-ink: #ffa6b7;\n    --lg-alert-tint: 255 92 122;\n  }\n\n  [data-lg-theme='light'] .lg-alert {\n    --lg-alert-fill: 229 241 255;\n    --lg-alert-ink: #0054b3;\n    --lg-alert-tint: 0 103 217;\n    --lg-alert-highlight: rgb(255 255 255 / 0.9);\n  }\n\n  [data-lg-theme='light'] .lg-alert[data-tone='success'] {\n    --lg-alert-fill: 224 247 238;\n    --lg-alert-ink: #08603f;\n    --lg-alert-tint: 20 168 116;\n  }\n\n  [data-lg-theme='light'] .lg-alert[data-tone='warning'] {\n    --lg-alert-fill: 255 243 219;\n    --lg-alert-ink: #824c00;\n    --lg-alert-tint: 232 150 12;\n  }\n\n  [data-lg-theme='light'] .lg-alert[data-tone='danger'] {\n    --lg-alert-fill: 255 229 236;\n    --lg-alert-ink: #a8113a;\n    --lg-alert-tint: 232 52 90;\n  }\n\n  /* Dismissing folds the alert to nothing. The alert sits in a one-row grid, and the row shrinks\n     from its content to zero, so its padding and margin go with it and nothing is measured. */\n  .lg-alert-fold {\n    display: grid;\n    grid-template-rows: 1fr;\n  }\n\n  .lg-alert-fold-inner {\n    min-height: 0;\n  }\n\n  .lg-alert-fold[data-state='folding'] {\n    grid-template-rows: 0fr;\n    transition: grid-template-rows 240ms var(--lg-ease-out);\n  }\n\n  .lg-alert-fold[data-state='folding'] > .lg-alert-fold-inner {\n    overflow: hidden;\n  }\n\n  .lg-alert-fold[data-state='folding'] .lg-alert {\n    opacity: 0;\n    pointer-events: none;\n    transition: opacity 160ms ease-in;\n  }\n\n  .lg-alert-icon {\n    display: inline-flex;\n    flex: none;\n    width: 1.25rem;\n    height: 1.25rem;\n    margin-top: 0.0625rem;\n    color: var(--lg-alert-ink);\n  }\n\n  .lg-alert-icon > svg {\n    display: block;\n    width: 100%;\n    height: 100%;\n  }\n\n  .lg-alert-body {\n    display: grid;\n    flex: 1;\n    gap: 0.125rem;\n    min-width: 0;\n  }\n\n  .lg-alert-title {\n    margin: 0;\n    font-weight: 600;\n  }\n\n  .lg-alert-description {\n    opacity: 0.82;\n  }\n\n  .lg-alert-close {\n    display: inline-flex;\n    flex: none;\n    align-items: center;\n    justify-content: center;\n    width: 1.75rem;\n    height: 1.75rem;\n    margin: -0.25rem -0.375rem -0.25rem 0;\n    padding: 0;\n    border: 0;\n    border-radius: 9999px;\n    background: transparent;\n    color: var(--lg-foreground);\n    cursor: pointer;\n    opacity: 0.7;\n    transition:\n      background-color 180ms ease,\n      opacity 180ms ease;\n  }\n\n  .lg-alert-close:hover {\n    background: rgb(255 255 255 / 0.14);\n    opacity: 1;\n  }\n\n  [data-lg-theme='light'] .lg-alert-close:hover {\n    background: rgb(0 0 0 / 0.07);\n  }\n\n  .lg-alert-close:focus-visible {\n    outline: 2px solid var(--lg-focus-ring);\n    outline-offset: 1px;\n    opacity: 1;\n  }\n\n  .lg-alert-close > svg {\n    width: 1rem;\n    height: 1rem;\n  }\n\n  /* ============================================\n     Avatar: a round photo or coloured initials. A dot or a neighbour cuts\n     the circle away instead of ringing it, so it works on any backdrop.\n     ============================================ */\n\n  .lg-avatar {\n    --lg-avatar-size: 2.5rem;\n    --lg-avatar-dot: 0.625rem;\n\n    position: relative;\n    display: inline-flex;\n    flex: none;\n    width: var(--lg-avatar-size);\n    height: var(--lg-avatar-size);\n    font-size: calc(var(--lg-avatar-size) * 0.38);\n    vertical-align: middle;\n  }\n\n  .lg-avatar[data-size='xs'] {\n    --lg-avatar-size: 1.5rem;\n    --lg-avatar-dot: 0.4375rem;\n  }\n\n  .lg-avatar[data-size='sm'] {\n    --lg-avatar-size: 2rem;\n    --lg-avatar-dot: 0.5rem;\n  }\n\n  .lg-avatar[data-size='lg'] {\n    --lg-avatar-size: 3.5rem;\n    --lg-avatar-dot: 0.875rem;\n  }\n\n  .lg-avatar[data-size='xl'] {\n    --lg-avatar-size: 5rem;\n    --lg-avatar-dot: 1.125rem;\n  }\n\n  .lg-avatar-face {\n    position: relative;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: 100%;\n    height: 100%;\n    overflow: hidden;\n    border-radius: 9999px;\n    background: var(--lg-control-surface);\n    color: #fff;\n    font-weight: 600;\n    line-height: 1;\n    user-select: none;\n  }\n\n  .lg-avatar-face::after {\n    content: '';\n    position: absolute;\n    inset: 0;\n    border-radius: inherit;\n    box-shadow:\n      inset 0 0 0 1px rgb(255 255 255 / 0.18),\n      inset 0 1px 0 rgb(255 255 255 / 0.22);\n    pointer-events: none;\n  }\n\n  [data-lg-theme='light'] .lg-avatar-face::after {\n    box-shadow:\n      inset 0 0 0 1px rgb(0 0 0 / 0.1),\n      inset 0 1px 0 rgb(255 255 255 / 0.3);\n  }\n\n  .lg-avatar-image {\n    display: block;\n    width: 100%;\n    height: 100%;\n    object-fit: cover;\n  }\n\n  .lg-avatar-fallback {\n    --lg-avatar-from: #747479;\n    --lg-avatar-to: #535359;\n\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: 100%;\n    height: 100%;\n    background: linear-gradient(145deg, var(--lg-avatar-from), var(--lg-avatar-to));\n    text-shadow: 0 1px 1px rgb(0 0 0 / 0.22);\n  }\n\n  .lg-avatar-fallback[data-tone='0'] {\n    --lg-avatar-from: #2d6de9;\n    --lg-avatar-to: #1a4fc7;\n  }\n\n  .lg-avatar-fallback[data-tone='1'] {\n    --lg-avatar-from: #b93f24;\n    --lg-avatar-to: #882c1a;\n  }\n\n  .lg-avatar-fallback[data-tone='2'] {\n    --lg-avatar-from: #707075;\n    --lg-avatar-to: #56565b;\n  }\n\n  .lg-avatar-fallback[data-tone='3'] {\n    --lg-avatar-from: #d0386f;\n    --lg-avatar-to: #a82458;\n  }\n\n  .lg-avatar-fallback[data-tone='4'] {\n    --lg-avatar-from: #b9540f;\n    --lg-avatar-to: #9c4308;\n  }\n\n  .lg-avatar-fallback[data-tone='5'] {\n    --lg-avatar-from: #1f8150;\n    --lg-avatar-to: #146c3c;\n  }\n\n  .lg-avatar-fallback[data-tone='6'] {\n    --lg-avatar-from: #0e7d8b;\n    --lg-avatar-to: #0a6674;\n  }\n\n  .lg-avatar-fallback[data-tone='7'] {\n    --lg-avatar-from: #747479;\n    --lg-avatar-to: #535359;\n  }\n\n  .lg-avatar-status {\n    --lg-status: #8e8e93;\n\n    position: absolute;\n    top: calc(var(--lg-avatar-size) * 0.8536 - var(--lg-avatar-dot) / 2);\n    left: calc(var(--lg-avatar-size) * 0.8536 - var(--lg-avatar-dot) / 2);\n    width: var(--lg-avatar-dot);\n    height: var(--lg-avatar-dot);\n    border-radius: 9999px;\n    background: var(--lg-status);\n  }\n\n  .lg-avatar[data-status='online'] > .lg-avatar-status {\n    --lg-status: #33d69f;\n  }\n\n  .lg-avatar[data-status='away'] > .lg-avatar-status {\n    --lg-status: #ffbd38;\n  }\n\n  .lg-avatar[data-status='busy'] > .lg-avatar-status {\n    --lg-status: #ff5c7a;\n  }\n\n  [data-lg-theme='light'] .lg-avatar[data-status='online'] > .lg-avatar-status {\n    --lg-status: #14a874;\n  }\n\n  [data-lg-theme='light'] .lg-avatar[data-status='away'] > .lg-avatar-status {\n    --lg-status: #e8960c;\n  }\n\n  [data-lg-theme='light'] .lg-avatar[data-status='busy'] > .lg-avatar-status {\n    --lg-status: #e8345a;\n  }\n\n  .lg-avatar[data-status] > .lg-avatar-face {\n    --lg-cut-status: radial-gradient(\n      circle at calc(var(--lg-avatar-size) * 0.8536) calc(var(--lg-avatar-size) * 0.8536),\n      transparent calc(var(--lg-avatar-dot) / 2 + 2px),\n      #000 calc(var(--lg-avatar-dot) / 2 + 2.5px)\n    );\n\n    -webkit-mask-image: var(--lg-cut-status), var(--lg-cut-next, linear-gradient(#000, #000));\n    mask-image: var(--lg-cut-status), var(--lg-cut-next, linear-gradient(#000, #000));\n    -webkit-mask-composite: source-in;\n    mask-composite: intersect;\n  }\n\n  .lg-avatar-group {\n    display: inline-flex;\n    align-items: center;\n    isolation: isolate;\n  }\n\n  .lg-avatar-group[data-size='xs'] .lg-avatar {\n    --lg-avatar-size: 1.5rem;\n    --lg-avatar-dot: 0.4375rem;\n  }\n\n  .lg-avatar-group[data-size='sm'] .lg-avatar {\n    --lg-avatar-size: 2rem;\n    --lg-avatar-dot: 0.5rem;\n  }\n\n  .lg-avatar-group[data-size='md'] .lg-avatar {\n    --lg-avatar-size: 2.5rem;\n    --lg-avatar-dot: 0.625rem;\n  }\n\n  .lg-avatar-group[data-size='lg'] .lg-avatar {\n    --lg-avatar-size: 3.5rem;\n    --lg-avatar-dot: 0.875rem;\n  }\n\n  .lg-avatar-group[data-size='xl'] .lg-avatar {\n    --lg-avatar-size: 5rem;\n    --lg-avatar-dot: 1.125rem;\n  }\n\n  .lg-avatar-group > .lg-avatar + .lg-avatar {\n    margin-inline-start: calc(var(--lg-avatar-size) * -0.2);\n  }\n\n  .lg-avatar-group > .lg-avatar:not(:last-child) > .lg-avatar-face {\n    --lg-cut-next: radial-gradient(\n      circle at calc(var(--lg-avatar-size) * 1.3) 50%,\n      transparent calc(var(--lg-avatar-size) / 2 + 2px),\n      #000 calc(var(--lg-avatar-size) / 2 + 2.5px)\n    );\n\n    -webkit-mask-image: var(--lg-cut-status, linear-gradient(#000, #000)), var(--lg-cut-next);\n    mask-image: var(--lg-cut-status, linear-gradient(#000, #000)), var(--lg-cut-next);\n    -webkit-mask-composite: source-in;\n    mask-composite: intersect;\n  }\n\n  [dir='rtl'] .lg-avatar-group > .lg-avatar:not(:last-child) > .lg-avatar-face {\n    --lg-cut-next: radial-gradient(\n      circle at calc(var(--lg-avatar-size) * -0.3) 50%,\n      transparent calc(var(--lg-avatar-size) / 2 + 2px),\n      #000 calc(var(--lg-avatar-size) / 2 + 2.5px)\n    );\n  }\n\n  .lg-avatar-more {\n    background: var(--lg-control-surface-hover);\n    color: var(--lg-foreground);\n    font-size: calc(var(--lg-avatar-size) * 0.32);\n  }\n\n  /* ============================================\n     Kbd: a keycap with a lit top edge and a dark lip\n     ============================================ */\n\n  .lg-kbd {\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    box-sizing: border-box;\n    min-width: 1.5rem;\n    height: 1.5rem;\n    padding: 0 0.4375rem;\n    border-radius: 0.4375rem;\n    background: var(--lg-control-surface);\n    box-shadow:\n      inset 0 1px 0 rgb(255 255 255 / 0.18),\n      inset 0 0 0 1px var(--lg-border),\n      0 1px 0 rgb(0 0 0 / 0.35);\n    color: var(--lg-foreground);\n    font: inherit;\n    font-size: 0.75rem;\n    font-weight: 600;\n    letter-spacing: 0.02em;\n    line-height: 1;\n  }\n\n  [data-lg-theme='light'] .lg-kbd {\n    box-shadow:\n      inset 0 1px 0 rgb(255 255 255 / 0.9),\n      inset 0 0 0 1px var(--lg-border),\n      0 1px 0 rgb(0 0 0 / 0.16);\n  }\n\n  .lg-kbd-group {\n    display: inline-flex;\n    align-items: center;\n    gap: 0.25rem;\n  }\n\n  /* ============================================\n     Scroll area: native scrolling with a thin glass scrollbar over its edge.\n     The bar shows while the pointer is over the area or it scrolls, rests\n     narrow, and widens under the pointer.\n     ============================================ */\n\n  .lg-scroll-area {\n    position: relative;\n    overflow: hidden;\n  }\n\n  /* A max-height on the area bounds the viewport as well as a height does. */\n  .lg-scroll-area-viewport {\n    width: 100%;\n    height: 100%;\n    max-height: inherit;\n    border-radius: inherit;\n  }\n\n  .lg-scroll-area-viewport:focus-visible {\n    outline: 2px solid var(--lg-focus-ring);\n    outline-offset: -2px;\n  }\n\n  .lg-scrollbar {\n    z-index: 1;\n    display: flex;\n    box-sizing: border-box;\n    padding: 3px;\n    touch-action: none;\n    user-select: none;\n    transition: padding 160ms var(--lg-ease-out);\n  }\n\n  .lg-scrollbar[data-orientation='vertical'] {\n    width: 10px;\n  }\n\n  .lg-scrollbar[data-orientation='horizontal'] {\n    flex-direction: column;\n    height: 10px;\n  }\n\n  .lg-scrollbar:hover {\n    padding: 2px;\n  }\n\n  .lg-scrollbar[data-state='visible'] {\n    animation: lg-scrollbar-in 160ms var(--lg-ease-out);\n  }\n\n  .lg-scrollbar[data-state='hidden'] {\n    animation: lg-scrollbar-out 240ms ease-in forwards;\n  }\n\n  /* A sliver of clear glass: a faint tint of the text colour, a lit rim and a\n     blur of what scrolls beneath it. */\n  .lg-scrollbar-thumb {\n    position: relative;\n    flex: 1;\n    border-radius: 999px;\n    background: color-mix(in srgb, var(--lg-foreground) 24%, transparent);\n    box-shadow: inset 0 0 0 0.5px rgb(255 255 255 / 0.24);\n    -webkit-backdrop-filter: blur(6px) saturate(1.6);\n    backdrop-filter: blur(6px) saturate(1.6);\n    transition: background-color 160ms var(--lg-ease-out);\n  }\n\n  [data-lg-theme='light'] .lg-scrollbar-thumb {\n    box-shadow:\n      inset 0 0 0 0.5px rgb(255 255 255 / 0.7),\n      0 0 0 0.5px rgb(0 0 0 / 0.06);\n  }\n\n  /* The pointer can catch more than the sliver it sees. */\n  .lg-scrollbar-thumb::before {\n    content: '';\n    position: absolute;\n    top: 50%;\n    left: 50%;\n    width: 100%;\n    height: 100%;\n    min-width: 24px;\n    min-height: 24px;\n    transform: translate(-50%, -50%);\n  }\n\n  .lg-scrollbar:hover .lg-scrollbar-thumb {\n    background: color-mix(in srgb, var(--lg-foreground) 40%, transparent);\n  }\n\n  @keyframes lg-scrollbar-in {\n    from {\n      opacity: 0;\n    }\n  }\n\n  @keyframes lg-scrollbar-out {\n    to {\n      opacity: 0;\n    }\n  }\n\n  [data-lg-reduce-transparency='1'] .lg-scrollbar-thumb {\n    -webkit-backdrop-filter: none;\n    backdrop-filter: none;\n    background: color-mix(in srgb, var(--lg-foreground) 55%, var(--lg-bg));\n  }\n\n  @media (prefers-contrast: more) {\n    .lg-scrollbar-thumb {\n      background: color-mix(in srgb, var(--lg-foreground) 70%, transparent);\n    }\n  }\n\n  @media (forced-colors: active) {\n    .lg-scrollbar-thumb {\n      forced-color-adjust: none;\n      background: CanvasText;\n      box-shadow: none;\n    }\n  }\n\n  /* ============================================\n     Command: a search field over a list that filters as you type. The\n     highlighted row is the menu's, and the list resizes with its results.\n     ============================================ */\n\n  .lg-command {\n    display: flex;\n    flex-direction: column;\n    width: 100%;\n    overflow: hidden;\n    border-radius: inherit;\n    color: var(--lg-foreground);\n    font-size: 0.9375rem;\n    line-height: 1.4;\n  }\n\n  .lg-command-dialog {\n    --lg-panel-radius: 1.5rem;\n\n    top: min(18vh, 9rem);\n    max-width: 40rem;\n    padding: 0;\n    translate: -50% 0;\n    overflow: hidden;\n  }\n\n  .lg-command-search {\n    display: flex;\n    flex: none;\n    align-items: center;\n    gap: 0.75rem;\n    height: 3.25rem;\n    padding: 0 1.125rem;\n    border-bottom: 1px solid var(--lg-border);\n    color: var(--lg-muted-foreground);\n    transition: box-shadow 200ms ease;\n  }\n\n  .lg-command-search:focus-within {\n    box-shadow: inset 0 -1px 0 color-mix(in srgb, var(--lg-focus-ring) 60%, transparent);\n  }\n\n  .lg-command-search > svg {\n    flex: none;\n    width: 1.125rem;\n    height: 1.125rem;\n  }\n\n  .lg-command-input {\n    flex: 1;\n    min-width: 0;\n    height: 100%;\n    padding: 0;\n    border: 0;\n    background: transparent;\n    color: var(--lg-foreground);\n    font: inherit;\n    font-size: 1rem;\n    outline: none;\n  }\n\n  .lg-command-input::placeholder {\n    color: var(--lg-muted-foreground);\n    opacity: 0.72;\n  }\n\n  .lg-command-list {\n    box-sizing: border-box;\n    height: min(calc(var(--cmdk-list-height, 22rem) + 0.75rem), 22rem);\n    max-height: min(22rem, 60dvh);\n    padding: 0.375rem;\n    overflow-x: hidden;\n    overflow-y: auto;\n    overscroll-behavior: contain;\n    scroll-padding-block: 0.375rem;\n    transition: height 160ms var(--lg-ease-out);\n  }\n\n  .lg-command-group [cmdk-group-heading] {\n    padding: 0.5rem 0.75rem 0.25rem;\n    color: var(--lg-muted-foreground);\n    font-size: 0.75rem;\n    font-weight: 600;\n    line-height: 1rem;\n    user-select: none;\n  }\n\n  .lg-command-item {\n    display: flex;\n    align-items: center;\n    gap: 0.625rem;\n    box-sizing: border-box;\n    min-height: 2.5rem;\n    padding: 0.5rem 0.75rem;\n    border-radius: 0.75rem;\n    color: var(--lg-foreground);\n    cursor: default;\n    outline: none;\n    user-select: none;\n  }\n\n  .lg-command-item > svg {\n    flex: none;\n    width: 1.125rem;\n    height: 1.125rem;\n    color: var(--lg-muted-foreground);\n  }\n\n  .lg-command-item[data-selected='true'] {\n    background: rgb(255 255 255 / 0.14);\n  }\n\n  [data-lg-theme='light'] .lg-command-item[data-selected='true'] {\n    background: rgb(0 0 0 / 0.06);\n  }\n\n  .lg-command-item[data-disabled='true'] {\n    opacity: var(--lg-disabled-opacity);\n    pointer-events: none;\n  }\n\n  .lg-command-empty {\n    padding: 2rem 1rem;\n    color: var(--lg-muted-foreground);\n    text-align: center;\n  }\n\n  .lg-command-separator {\n    height: 1px;\n    margin: 0.375rem 0.625rem;\n    background: var(--lg-border);\n  }\n\n  .lg-command-shortcut {\n    display: inline-flex;\n    align-items: center;\n    margin-inline-start: auto;\n    padding-inline-start: 1.5rem;\n    color: var(--lg-muted-foreground);\n    font-size: 0.75rem;\n    letter-spacing: 0.06em;\n  }\n\n  /* ============================================\n     Breadcrumb and pagination: where you are, and the way on\n     ============================================ */\n\n  .lg-breadcrumb {\n    color: var(--lg-muted-foreground);\n    font-size: 0.9375rem;\n    line-height: 1.4;\n  }\n\n  .lg-breadcrumb-list {\n    display: flex;\n    flex-wrap: wrap;\n    align-items: center;\n    gap: 0.125rem;\n    margin: 0;\n    padding: 0;\n    list-style: none;\n  }\n\n  .lg-breadcrumb-item {\n    display: inline-flex;\n    align-items: center;\n    gap: 0.125rem;\n    min-width: 0;\n  }\n\n  .lg-breadcrumb-link,\n  .lg-breadcrumb-ellipsis,\n  .lg-breadcrumb-page {\n    display: inline-flex;\n    align-items: center;\n    box-sizing: border-box;\n    min-height: 1.875rem;\n    padding: 0 0.625rem;\n    border-radius: 9999px;\n  }\n\n  .lg-breadcrumb-link,\n  .lg-breadcrumb-ellipsis {\n    border: 0;\n    background: transparent;\n    color: var(--lg-muted-foreground);\n    cursor: pointer;\n    font: inherit;\n    text-decoration: none;\n    transition:\n      background-color 180ms ease,\n      color 180ms ease;\n  }\n\n  .lg-breadcrumb-link:hover,\n  .lg-breadcrumb-ellipsis:hover,\n  .lg-breadcrumb-ellipsis[data-state='open'] {\n    background: rgb(255 255 255 / 0.1);\n    color: var(--lg-foreground);\n  }\n\n  [data-lg-theme='light'] .lg-breadcrumb-link:hover,\n  [data-lg-theme='light'] .lg-breadcrumb-ellipsis:hover,\n  [data-lg-theme='light'] .lg-breadcrumb-ellipsis[data-state='open'] {\n    background: rgb(0 0 0 / 0.06);\n  }\n\n  .lg-breadcrumb-link:focus-visible,\n  .lg-breadcrumb-ellipsis:focus-visible {\n    outline: 2px solid var(--lg-focus-ring);\n    outline-offset: 1px;\n  }\n\n  .lg-breadcrumb-ellipsis {\n    padding: 0 0.375rem;\n  }\n\n  .lg-breadcrumb-ellipsis > svg {\n    width: 1.25rem;\n    height: 1.25rem;\n  }\n\n  .lg-breadcrumb-page {\n    color: var(--lg-foreground);\n    font-weight: 600;\n  }\n\n  .lg-breadcrumb-separator {\n    display: inline-flex;\n    color: var(--lg-muted-foreground);\n    opacity: 0.65;\n  }\n\n  .lg-breadcrumb-separator > svg {\n    width: 1rem;\n    height: 1rem;\n  }\n\n  [dir='rtl'] .lg-breadcrumb-separator {\n    scale: -1 1;\n  }\n\n  .lg-breadcrumb-item:last-child > .lg-breadcrumb-separator {\n    display: none;\n  }\n\n  .lg-pagination-list {\n    display: flex;\n    flex-wrap: wrap;\n    align-items: center;\n    gap: 0.25rem;\n    margin: 0;\n    padding: 0;\n    list-style: none;\n  }\n\n  .lg-page {\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    box-sizing: border-box;\n    min-width: 2.25rem;\n    height: 2.25rem;\n    padding: 0 0.625rem;\n    border: 0;\n    border-radius: 9999px;\n    background: transparent;\n    box-shadow: inset 0 0 0 1px transparent;\n    color: var(--lg-foreground);\n    cursor: pointer;\n    font: inherit;\n    font-size: 0.9375rem;\n    font-variant-numeric: tabular-nums;\n    -webkit-tap-highlight-color: transparent;\n    transition:\n      background-color 200ms ease,\n      box-shadow 200ms ease,\n      scale 320ms var(--lg-spring);\n  }\n\n  .lg-page > svg {\n    width: 1.125rem;\n    height: 1.125rem;\n  }\n\n  .lg-page:hover:not(:disabled, [data-current]) {\n    background: var(--lg-control-surface-hover);\n  }\n\n  .lg-page:active:not(:disabled) {\n    scale: 0.92;\n  }\n\n  .lg-page:focus-visible {\n    outline: 2px solid var(--lg-focus-ring);\n    outline-offset: 2px;\n  }\n\n  .lg-page:disabled {\n    cursor: not-allowed;\n    opacity: var(--lg-disabled-opacity);\n  }\n\n  .lg-page[data-current] {\n    background: rgb(255 255 255 / 0.16);\n    box-shadow:\n      inset 0 1px 0 rgb(255 255 255 / 0.28),\n      inset 0 0 0 1px rgb(255 255 255 / 0.12);\n    font-weight: 600;\n  }\n\n  [data-lg-theme='light'] .lg-page[data-current] {\n    background: rgb(0 0 0 / 0.08);\n    box-shadow:\n      inset 0 1px 0 rgb(255 255 255 / 0.9),\n      inset 0 0 0 1px rgb(0 0 0 / 0.06);\n  }\n\n  .lg-page-gap {\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    min-width: 1.5rem;\n    color: var(--lg-muted-foreground);\n    user-select: none;\n  }\n\n  /* Tabs */\n  .lg-tabs-list {\n    display: flex;\n    width: 100%;\n    max-width: 100%;\n    gap: 0.25rem;\n    padding: 0.25rem;\n    font-size: 0.875rem;\n    line-height: calc(1.25 / 0.875);\n  }\n\n  .lg-tabs-trigger {\n    position: relative;\n    display: flex;\n    flex: 1 1 0%;\n    min-width: 0;\n    align-items: center;\n    justify-content: center;\n    border-radius: 9999px;\n    padding: 0.5rem 0.75rem;\n    color: var(--lg-muted-foreground);\n    transition:\n      color var(--lg-motion-duration) ease,\n      background-color var(--lg-motion-duration) ease,\n      box-shadow var(--lg-motion-duration) ease;\n  }\n\n  .lg-tabs-trigger:focus-visible {\n    outline: 2px solid var(--lg-focus-ring);\n    outline-offset: 2px;\n  }\n\n  .lg-tabs-trigger:disabled {\n    pointer-events: none;\n    opacity: var(--lg-disabled-opacity);\n  }\n\n  .lg-tabs-content {\n    margin-top: 0.75rem;\n    font-size: 0.875rem;\n    line-height: calc(1.25 / 0.875);\n  }\n\n  /* The active trigger is a small raised glass bubble */\n  .lg-tabs-trigger[data-state='active'] {\n    color: var(--lg-foreground);\n    background: rgb(255 255 255 / 0.12);\n    box-shadow:\n      inset 0 1px 0 rgb(255 255 255 / 0.22),\n      inset 0 -1px 0 rgb(0 0 0 / 0.12),\n      0 1px 3px rgb(0 0 0 / 0.24),\n      0 4px 12px -4px rgb(0 0 0 / 0.4);\n  }\n\n  [data-lg-theme='light'] .lg-tabs-trigger[data-state='active'] {\n    background: rgb(255 255 255 / 0.82);\n    box-shadow:\n      inset 0 1px 0 rgb(255 255 255 / 0.9),\n      0 1px 3px rgb(0 0 0 / 0.1),\n      0 4px 12px -4px rgb(0 0 0 / 0.16);\n  }\n\n  /* The bubble catches the same specular light as the glass around it. */\n  .lg-tabs-trigger[data-state='active']::after,\n  .lg-tabs-indicator::after {\n    content: '';\n    position: absolute;\n    inset: 0;\n    padding: var(--lg-rim-width);\n    border-radius: inherit;\n    pointer-events: none;\n    background: linear-gradient(\n      to bottom right,\n      rgb(255 255 255 / var(--lg-specular-peak)),\n      rgb(255 255 255 / var(--lg-specular-floor)) 38% 62%,\n      rgb(255 255 255 / var(--lg-specular-counter))\n    );\n    -webkit-mask:\n      linear-gradient(#000 0 0) content-box,\n      linear-gradient(#000 0 0);\n    -webkit-mask-composite: xor;\n    mask:\n      linear-gradient(#000 0 0) content-box,\n      linear-gradient(#000 0 0);\n    mask-composite: exclude;\n  }\n\n  /* Once scripts run, one bubble for the whole list moves between triggers\n     and the active trigger stops drawing its own. */\n  .lg-tabs-indicator {\n    display: none;\n  }\n\n  .lg-tabs-list[data-lg-indicator='ready'] > .lg-tabs-indicator {\n    --lg-bubble-alpha: 0.12;\n\n    position: absolute;\n    z-index: 1;\n    display: block;\n    border-radius: 9999px;\n    pointer-events: none;\n  }\n\n  [data-lg-theme='light'] .lg-tabs-list[data-lg-indicator='ready'] > .lg-tabs-indicator {\n    --lg-bubble-alpha: 0.82;\n  }\n\n  .lg-tabs-list[data-lg-indicator='ready'] .lg-tabs-trigger[data-state='active'] {\n    background: transparent;\n    box-shadow: none;\n    transition: color var(--lg-motion-duration) ease;\n  }\n\n  .lg-tabs-list[data-lg-indicator='ready'] .lg-tabs-trigger[data-state='active']::after {\n    display: none;\n  }\n\n  /* Accordion: the trigger shares the content card's corner radius */\n  .lg-accordion-trigger {\n    display: flex;\n    width: 100%;\n    justify-content: space-between;\n    border: 1px solid var(--lg-border);\n    border-radius: var(--lg-radius-md);\n    padding: 0.75rem 1rem;\n    background: var(--lg-control-surface);\n    box-shadow: none;\n    color: var(--lg-foreground);\n    font-size: 1rem;\n    line-height: 1.5;\n    font-weight: 500;\n    text-align: left;\n    -webkit-backdrop-filter: blur(min(var(--lg-glass-blur), 12px))\n      brightness(var(--lg-glass-brightness)) contrast(var(--lg-glass-contrast))\n      saturate(var(--lg-glass-sat));\n    backdrop-filter: blur(min(var(--lg-glass-blur), 12px)) brightness(var(--lg-glass-brightness))\n      contrast(var(--lg-glass-contrast)) saturate(var(--lg-glass-sat));\n    transition:\n      transform var(--lg-motion-duration) cubic-bezier(0.2, 0, 0, 1),\n      background-color var(--lg-motion-duration) ease;\n  }\n\n  .lg-accordion-trigger:hover {\n    background: var(--lg-control-surface-hover);\n  }\n\n  .lg-accordion-trigger:disabled {\n    pointer-events: none;\n    opacity: var(--lg-disabled-opacity);\n  }\n\n  .lg-accordion-content {\n    margin-top: 0.5rem;\n    overflow: hidden;\n    font-size: 0.875rem;\n    line-height: calc(1.25 / 0.875);\n  }\n\n  .lg-accordion-chevron {\n    flex: none;\n    transition: transform var(--lg-motion-duration) ease;\n  }\n\n  .lg-accordion-trigger[data-state='open'] .lg-accordion-chevron {\n    transform: rotate(180deg);\n  }\n\n  /* ============================================\n     Enter and exit motion. Radix keeps a closing layer mounted until its exit\n     animation ends; the reduced motion guards above cut both to zero. The\n     keyframes move scale and translate, never transform, so they compose\n     with positioning and with a sheet's drag offset.\n     ============================================ */\n\n  @keyframes lg-fade-in {\n    from {\n      opacity: 0;\n    }\n  }\n\n  @keyframes lg-fade-out {\n    to {\n      opacity: 0;\n    }\n  }\n\n  /* A layer grows out of whatever opened it. --lg-pop-x and --lg-pop-y hold the last few pixels\n     of its travel, away from its trigger; a dialog keeps its own centring in them and rises. */\n  @keyframes lg-pop-in {\n    from {\n      opacity: 0;\n      scale: 0.96;\n      translate: var(--lg-pop-x, 0) var(--lg-pop-y, 0);\n    }\n  }\n\n  @keyframes lg-pop-out {\n    to {\n      opacity: 0;\n      scale: 0.96;\n      translate: var(--lg-pop-x, 0) var(--lg-pop-y, 0);\n    }\n  }\n\n  .lg-dialog-content {\n    --lg-pop-x: -50%;\n    --lg-pop-y: calc(-50% + 0.5rem);\n  }\n\n  .lg-popover-content[data-side='bottom'],\n  .lg-menu-content[data-side='bottom'],\n  .lg-select-content[data-side='bottom'],\n  .lg-tooltip-content[data-side='bottom'] {\n    --lg-pop-y: -0.25rem;\n  }\n\n  .lg-popover-content[data-side='top'],\n  .lg-menu-content[data-side='top'],\n  .lg-select-content[data-side='top'],\n  .lg-tooltip-content[data-side='top'] {\n    --lg-pop-y: 0.25rem;\n  }\n\n  .lg-popover-content[data-side='right'],\n  .lg-menu-content[data-side='right'],\n  .lg-select-content[data-side='right'],\n  .lg-tooltip-content[data-side='right'] {\n    --lg-pop-x: -0.25rem;\n  }\n\n  .lg-popover-content[data-side='left'],\n  .lg-menu-content[data-side='left'],\n  .lg-select-content[data-side='left'],\n  .lg-tooltip-content[data-side='left'] {\n    --lg-pop-x: 0.25rem;\n  }\n\n  .lg-dialog-overlay[data-state='open'] {\n    animation: lg-fade-in 320ms var(--lg-ease-out);\n  }\n\n  .lg-dialog-overlay[data-state='closed'] {\n    animation: lg-fade-out 220ms ease-in forwards;\n  }\n\n  .lg-dialog-content[data-state='open'],\n  .lg-popover-content[data-state='open'],\n  .lg-menu-content[data-state='open'],\n  .lg-select-content[data-state='open'] {\n    animation: lg-pop-in 240ms var(--lg-ease-out);\n  }\n\n  .lg-dialog-content[data-state='closed'],\n  .lg-popover-content[data-state='closed'],\n  .lg-menu-content[data-state='closed'],\n  .lg-select-content[data-state='closed'] {\n    animation: lg-pop-out 160ms ease-in forwards;\n  }\n\n  .lg-popover-content {\n    transform-origin: var(--radix-popover-content-transform-origin);\n  }\n\n  .lg-menu-content {\n    transform-origin: var(--radix-dropdown-menu-content-transform-origin);\n  }\n\n  .lg-select-content {\n    transform-origin: var(--radix-select-content-transform-origin);\n  }\n\n  /* A tip settles in from the side it opens toward and fades on the way out. Moving from one\n     trigger to the next skips the entrance, so the tip follows the pointer instead of restarting. */\n  .lg-tooltip-content {\n    transform-origin: var(--radix-tooltip-content-transform-origin);\n  }\n\n  .lg-tooltip-content[data-state='delayed-open'] {\n    animation: lg-pop-in 140ms var(--lg-ease-out);\n  }\n\n  .lg-tooltip-content[data-state='instant-open'] {\n    animation: lg-fade-in 90ms ease-out;\n  }\n\n  .lg-tooltip-content[data-state='closed'] {\n    animation: lg-pop-out 100ms ease-in forwards;\n  }\n\n  /* A toast slides in from the side it will leave toward and back out when it goes: the side of\n     its swipe direction, the right unless the provider says otherwise. The slide is on the list\n     item and the fade on the glass itself: opacity on an ancestor of the frost would turn its blur\n     off until the animation ended. A swipe drags it and a fling sends it on its way. */\n  .lg-toast {\n    --lg-toast-shift-x: 2rem;\n    --lg-toast-shift-y: 0px;\n    --lg-toast-fly-x: calc(100% + 2rem);\n    --lg-toast-fly-y: 0px;\n  }\n\n  .lg-toast[data-swipe-direction='left'] {\n    --lg-toast-shift-x: -2rem;\n    --lg-toast-fly-x: calc(-100% - 2rem);\n  }\n\n  .lg-toast[data-swipe-direction='up'] {\n    --lg-toast-shift-x: 0px;\n    --lg-toast-shift-y: -2rem;\n    --lg-toast-fly-x: 0px;\n    --lg-toast-fly-y: calc(-100% - 2rem);\n  }\n\n  .lg-toast[data-swipe-direction='down'] {\n    --lg-toast-shift-x: 0px;\n    --lg-toast-shift-y: 2rem;\n    --lg-toast-fly-x: 0px;\n    --lg-toast-fly-y: calc(100% + 2rem);\n  }\n\n  @keyframes lg-toast-slide-in {\n    from {\n      translate: var(--lg-toast-shift-x) var(--lg-toast-shift-y);\n    }\n  }\n\n  @keyframes lg-toast-slide-out {\n    to {\n      translate: var(--lg-toast-shift-x) var(--lg-toast-shift-y);\n    }\n  }\n\n  @keyframes lg-toast-swipe-out {\n    from {\n      translate: var(--radix-toast-swipe-end-x, 0px) var(--radix-toast-swipe-end-y, 0px);\n    }\n\n    to {\n      translate: var(--lg-toast-fly-x) var(--lg-toast-fly-y);\n    }\n  }\n\n  .lg-toast[data-state='open'] {\n    animation: lg-toast-slide-in 420ms var(--lg-ease-out);\n  }\n\n  .lg-toast[data-state='open'] > .lg-toast-root {\n    animation: lg-fade-in 300ms ease-out;\n  }\n\n  .lg-toast[data-state='closed'] {\n    animation: lg-toast-slide-out 220ms ease-in forwards;\n  }\n\n  .lg-toast[data-state='closed'] > .lg-toast-root {\n    animation: lg-fade-out 200ms ease-in forwards;\n  }\n\n  .lg-toast[data-swipe='move'] {\n    translate: var(--radix-toast-swipe-move-x, 0px) var(--radix-toast-swipe-move-y, 0px);\n  }\n\n  .lg-toast[data-swipe='cancel'] {\n    translate: 0 0;\n    transition: translate 260ms var(--lg-spring);\n  }\n\n  .lg-toast[data-swipe='end'] {\n    animation: lg-toast-swipe-out 160ms ease-out forwards;\n  }\n\n  /* The card opens and closes like a curtain. Height and padding move, opacity does not, for\n     the same reason as the toast: the card's frost sits in a child layer. */\n  @keyframes lg-accordion-down {\n    from {\n      height: 0;\n      margin-top: 0;\n      padding-block: 0;\n    }\n\n    to {\n      height: var(--radix-accordion-content-height);\n    }\n  }\n\n  @keyframes lg-accordion-up {\n    from {\n      height: var(--radix-accordion-content-height);\n    }\n\n    to {\n      height: 0;\n      margin-top: 0;\n      padding-block: 0;\n    }\n  }\n\n  .lg-accordion-content[data-state='open'] {\n    animation: lg-accordion-down 300ms var(--lg-ease-out);\n  }\n\n  .lg-accordion-content[data-state='closed'] {\n    animation: lg-accordion-up 220ms ease-in forwards;\n  }\n\n  @keyframes lg-avatar-in {\n    from {\n      opacity: 0;\n      scale: 1.06;\n    }\n  }\n\n  .lg-avatar-image {\n    animation: lg-avatar-in 260ms var(--lg-ease-out);\n  }\n\n  /* ============================================\n     Switch: a pill track and a white knob that turns to clear glass while it\n     is held, the way the system toggle does\n     ============================================ */\n\n  .lg-switch {\n    --lg-switch-width: 3.75rem;\n    --lg-switch-height: 1.75rem;\n    --lg-switch-thumb-width: 2.25rem;\n    --lg-switch-thumb-height: 1.5rem;\n    --lg-switch-inset: 0.125rem;\n    --lg-switch-direction: 1;\n    /* Held, the knob swells past the track, and the lens shows what lies under it at\n       this share of its size. */\n    --lg-switch-swell: 1.57;\n    --lg-switch-minify: 0.85;\n    /* The colour of the track under the knob, which its rim and glow pick up. */\n    --lg-switch-lens-tint: var(--lg-track);\n\n    position: relative;\n    display: inline-flex;\n    flex: none;\n    align-items: center;\n    box-sizing: border-box;\n    width: var(--lg-switch-width);\n    height: var(--lg-switch-height);\n    margin: 0;\n    padding: 0 var(--lg-switch-inset);\n    border: none;\n    border-radius: 9999px;\n    background: var(--lg-track);\n    box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.1);\n    cursor: pointer;\n    -webkit-tap-highlight-color: transparent;\n    transition: background-color 250ms ease;\n  }\n\n  .lg-switch[data-size='sm'] {\n    --lg-switch-width: 2.875rem;\n    --lg-switch-height: 1.5rem;\n    --lg-switch-thumb-width: 1.75rem;\n    --lg-switch-thumb-height: 1.25rem;\n  }\n\n  [dir='rtl'] .lg-switch,\n  .lg-switch[dir='rtl'] {\n    --lg-switch-direction: -1;\n  }\n\n  .lg-switch[data-state='checked'] {\n    --lg-switch-lens-tint: var(--lg-switch-on);\n\n    background: var(--lg-switch-on);\n  }\n\n  .lg-switch:focus-visible {\n    outline: 2px solid var(--lg-focus-ring);\n    outline-offset: 2px;\n  }\n\n  .lg-switch[data-disabled] {\n    cursor: not-allowed;\n    opacity: var(--lg-disabled-opacity);\n  }\n\n  .lg-switch-thumb {\n    position: relative;\n    display: block;\n    flex: none;\n    width: var(--lg-switch-thumb-width);\n    height: var(--lg-switch-thumb-height);\n    border-radius: 9999px;\n    background: var(--lg-knob);\n    box-shadow: var(--lg-knob-shadow);\n    pointer-events: none;\n    translate: 0 0;\n    transition:\n      translate 420ms var(--lg-spring),\n      scale 320ms var(--lg-spring),\n      background-color 180ms ease,\n      box-shadow 180ms ease;\n  }\n\n  .lg-switch[data-state='checked'] .lg-switch-thumb {\n    translate: calc(\n        (var(--lg-switch-width) - var(--lg-switch-thumb-width) - var(--lg-switch-inset) * 2) *\n          var(--lg-switch-direction)\n      )\n      0;\n  }\n\n  /* Held, the knob swells past the track into a lens of clear glass. Through it the\n     track and what lies around it show a little smaller, and they bend at the rim. Lit\n     from the top left, the rim takes the track's colour, heavier along the bottom and\n     right where the light leaves the glass, and glints on the left. A soft glow in the\n     same colour lies around it. After a flip it stays this size and glass while it\n     slides, and only then shrinks back. */\n  .lg-switch:is(:active, [data-lg-moving]):not([data-disabled]) .lg-switch-thumb {\n    background: rgb(255 255 255 / 0);\n    box-shadow:\n      0.4px 0.8px 0.8px rgb(0 0 0 / 0.14),\n      0 2px 5px rgb(0 0 0 / 0.06),\n      0 0 12px 3px color-mix(in srgb, var(--lg-switch-lens-tint) 18%, transparent);\n    scale: var(--lg-switch-swell);\n  }\n\n  .lg-switch-thumb::after {\n    content: '';\n    position: absolute;\n    inset: 0;\n    z-index: 1;\n    border-radius: inherit;\n    pointer-events: none;\n    opacity: 0;\n    /* Gradients and unblurred shadows only: WebKit draws a blurred inset shadow at low\n       resolution, which the swell would show as blocks. */\n    background:\n      radial-gradient(19% 7% at 15% 20%, rgb(255 255 255 / 0.95), rgb(255 255 255 / 0)),\n      radial-gradient(19% 7% at 15% 80%, rgb(255 255 255 / 0.85), rgb(255 255 255 / 0)),\n      linear-gradient(\n        to top,\n        color-mix(in srgb, var(--lg-switch-lens-tint) 18%, transparent),\n        transparent 32%\n      ),\n      linear-gradient(rgb(0 0 0 / 0.05), transparent 14%),\n      linear-gradient(rgb(255 255 255 / 0.07), rgb(255 255 255 / 0.02));\n    box-shadow:\n      inset 0.35px 0.6px color-mix(in srgb, var(--lg-switch-lens-tint) 80%, black),\n      inset 0 0 0 0.4px var(--lg-switch-lens-tint),\n      inset -0.6px -1.4px oklch(from var(--lg-switch-lens-tint) calc(l + 0.1) c h),\n      inset -0.9px -2.2px\n        color-mix(\n          in srgb,\n          oklch(from var(--lg-switch-lens-tint) calc(l + 0.18) c h) 45%,\n          transparent\n        );\n    transition:\n      opacity 180ms ease,\n      box-shadow 250ms ease;\n  }\n\n  .lg-switch:is(:active, [data-lg-moving]):not([data-disabled]) .lg-switch-thumb::after {\n    opacity: 1;\n  }\n\n  /* The lens reaches a margin past the knob so its rim has track to bend in, and cuts the\n     filtered view back to the knob, half a pixel inside so the rim's highlight covers the\n     copy's edge. A clip on the filtered element itself would let Chromium draw the\n     filter's margin outside it. It is hidden at rest, so the filter only runs while the\n     knob is glass. */\n  .lg-switch-lens {\n    position: absolute;\n    top: calc(var(--lg-switch-lens-margin, 0px) * -1);\n    left: calc(var(--lg-switch-lens-margin, 0px) * -1);\n    width: calc(var(--lg-switch-thumb-width) + var(--lg-switch-lens-margin, 0px) * 2);\n    height: calc(var(--lg-switch-thumb-height) + var(--lg-switch-lens-margin, 0px) * 2);\n    clip-path: inset(calc(var(--lg-switch-lens-margin, 0px) + 0.5px) round 9999px);\n    pointer-events: none;\n    opacity: 0;\n    visibility: hidden;\n    transition:\n      opacity 180ms ease,\n      visibility 0s linear 180ms;\n  }\n\n  /* The view is laid out at --lg-switch-lens-scale times the lens and scaled back down on\n     its own layer, so engines that filter at layout resolution bend it smoothly too.\n     WebKit draws a filtered layer from its overflow origin, so the view clips its own\n     overflow on a composited layer. It is filled with the colour behind the switch,\n     which the component reads when the knob is pressed, so the real track under the\n     knob stays hidden. */\n  .lg-switch-lens-view {\n    position: absolute;\n    top: 0;\n    left: 0;\n    width: calc(100% * var(--lg-switch-lens-scale, 1));\n    height: calc(100% * var(--lg-switch-lens-scale, 1));\n    overflow: hidden;\n    background: var(--lg-switch-lens-backdrop, var(--lg-bg));\n    transform-origin: 0 0;\n    transform: translateZ(0) scale(calc(1 / var(--lg-switch-lens-scale, 1)));\n  }\n\n  .lg-switch:is(:active, [data-lg-moving]):not([data-disabled]) .lg-switch-lens {\n    opacity: 1;\n    visibility: visible;\n    transition-delay: 0s;\n  }\n\n  /* The scene under the lens, around the knob's centre. It undoes the knob's swell with\n     the same timing, and shows what lies under the knob at --lg-switch-minify of its\n     size. */\n  .lg-switch-lens-scene {\n    position: absolute;\n    inset: 0;\n    scale: var(--lg-switch-minify);\n    transition: scale 320ms var(--lg-spring);\n  }\n\n  .lg-switch:is(:active, [data-lg-moving]):not([data-disabled]) .lg-switch-lens-scene {\n    scale: calc(var(--lg-switch-minify) / var(--lg-switch-swell));\n  }\n\n  /* The track as it lies under the knob, at the lens's scale: the knob's slide is undone\n     with the same timing, so the copy stays put while the knob passes over it. */\n  .lg-switch-lens-track {\n    position: absolute;\n    inset-inline-start: calc(\n      (var(--lg-switch-lens-margin, 0px) - var(--lg-switch-inset)) * var(--lg-switch-lens-scale, 1)\n    );\n    top: calc(\n      (var(--lg-switch-lens-margin, 0px) -\n          (var(--lg-switch-height) - var(--lg-switch-thumb-height)) / 2) *\n        var(--lg-switch-lens-scale, 1)\n    );\n    width: calc(var(--lg-switch-width) * var(--lg-switch-lens-scale, 1));\n    height: calc(var(--lg-switch-height) * var(--lg-switch-lens-scale, 1));\n    border-radius: 9999px;\n    background: var(--lg-track);\n    box-shadow: inset 0 calc(var(--lg-switch-lens-scale, 1) * 1px)\n      calc(var(--lg-switch-lens-scale, 1) * 2px) rgb(0 0 0 / 0.1);\n    translate: 0 0;\n    transition:\n      translate 420ms var(--lg-spring),\n      background-color 250ms ease;\n  }\n\n  .lg-switch[data-state='checked'] .lg-switch-lens-track {\n    background: var(--lg-switch-on);\n    translate: calc(\n        (var(--lg-switch-width) - var(--lg-switch-thumb-width) - var(--lg-switch-inset) * 2) *\n          var(--lg-switch-direction) * var(--lg-switch-lens-scale, 1) * -1\n      )\n      0;\n  }\n\n  /* ============================================\n     Slider: a thin track, an accent fill and the same capsule knob\n     ============================================ */\n\n  .lg-slider {\n    --lg-slider-thumb-width: 2.375rem;\n    --lg-slider-thumb-height: 1.5rem;\n    --lg-slider-track-size: 0.375rem;\n\n    position: relative;\n    display: flex;\n    align-items: center;\n    width: 100%;\n    height: var(--lg-slider-thumb-height);\n    touch-action: none;\n    user-select: none;\n    -webkit-tap-highlight-color: transparent;\n  }\n\n  .lg-slider[data-orientation='vertical'] {\n    flex-direction: column;\n    width: var(--lg-slider-thumb-height);\n    height: 100%;\n    min-height: 8rem;\n  }\n\n  .lg-slider[data-disabled] {\n    opacity: var(--lg-disabled-opacity);\n  }\n\n  .lg-slider-track {\n    position: relative;\n    flex-grow: 1;\n    overflow: hidden;\n    border-radius: 9999px;\n    background: var(--lg-track);\n  }\n\n  .lg-slider-track[data-orientation='horizontal'] {\n    height: var(--lg-slider-track-size);\n  }\n\n  .lg-slider-track[data-orientation='vertical'] {\n    width: var(--lg-slider-track-size);\n  }\n\n  .lg-slider-range {\n    position: absolute;\n    border-radius: inherit;\n    background: var(--lg-accent);\n  }\n\n  .lg-slider-range[data-orientation='horizontal'] {\n    height: 100%;\n  }\n\n  .lg-slider-range[data-orientation='vertical'] {\n    width: 100%;\n  }\n\n  .lg-slider-thumb {\n    display: block;\n    width: var(--lg-slider-thumb-width);\n    height: var(--lg-slider-thumb-height);\n    border-radius: 9999px;\n    background: var(--lg-knob);\n    box-shadow: var(--lg-knob-shadow);\n    cursor: grab;\n    /* Script stretches a dragged knob along the track with its speed. */\n    transform: scale(var(--lg-stretch-x, 1), var(--lg-stretch-y, 1));\n    transition:\n      scale 320ms var(--lg-spring),\n      background-color 180ms ease,\n      box-shadow 180ms ease;\n  }\n\n  .lg-slider[data-orientation='vertical'] .lg-slider-thumb {\n    width: var(--lg-slider-thumb-height);\n    height: var(--lg-slider-thumb-width);\n  }\n\n  .lg-slider-thumb:focus-visible {\n    outline: 2px solid var(--lg-focus-ring);\n    outline-offset: 2px;\n  }\n\n  .lg-slider[data-disabled] .lg-slider-thumb {\n    cursor: not-allowed;\n  }\n\n  /* Radix focuses the thumb it drags, so only that one turns to glass. */\n  .lg-slider:not([data-disabled]):active .lg-slider-thumb:focus {\n    background: rgb(255 255 255 / 0.16);\n    box-shadow:\n      inset 0 0 0 0.5px rgb(255 255 255 / 0.55),\n      inset 1.5px 2px 1px -1px rgb(255 255 255 / 0.9),\n      inset -1.5px -2px 1px -1px rgb(255 255 255 / 0.55),\n      inset 0 0 8px rgb(255 255 255 / 0.28),\n      0 4px 14px rgb(0 0 0 / 0.2);\n    cursor: grabbing;\n    scale: 1.3 1.4;\n  }\n\n  /* ============================================\n     Segmented control: one raised bubble slides between equal segments.\n     :has() counts the segments and finds the checked one, so the bubble is\n     placed before any script runs. Up to six segments.\n     ============================================ */\n\n  .lg-segmented {\n    --lg-segmented-pad: 0.1875rem;\n\n    display: grid;\n    grid-auto-columns: minmax(0, 1fr);\n    grid-auto-flow: column;\n    width: 100%;\n    padding: var(--lg-segmented-pad);\n    font-size: 0.875rem;\n    line-height: calc(1.25 / 0.875);\n  }\n\n  .lg-segmented:has(> button:nth-of-type(2):last-of-type) {\n    --lg-segmented-count: 2;\n  }\n\n  .lg-segmented:has(> button:nth-of-type(3):last-of-type) {\n    --lg-segmented-count: 3;\n  }\n\n  .lg-segmented:has(> button:nth-of-type(4):last-of-type) {\n    --lg-segmented-count: 4;\n  }\n\n  .lg-segmented:has(> button:nth-of-type(5):last-of-type) {\n    --lg-segmented-count: 5;\n  }\n\n  .lg-segmented:has(> button:nth-of-type(6):last-of-type) {\n    --lg-segmented-count: 6;\n  }\n\n  .lg-segmented:has(> button:nth-of-type(2)[data-state='checked']) {\n    --lg-segmented-index: 1;\n  }\n\n  .lg-segmented:has(> button:nth-of-type(3)[data-state='checked']) {\n    --lg-segmented-index: 2;\n  }\n\n  .lg-segmented:has(> button:nth-of-type(4)[data-state='checked']) {\n    --lg-segmented-index: 3;\n  }\n\n  .lg-segmented:has(> button:nth-of-type(5)[data-state='checked']) {\n    --lg-segmented-index: 4;\n  }\n\n  .lg-segmented:has(> button:nth-of-type(6)[data-state='checked']) {\n    --lg-segmented-index: 5;\n  }\n\n  .lg-segmented > .lg-segmented-indicator {\n    position: absolute;\n    top: var(--lg-segmented-pad);\n    bottom: var(--lg-segmented-pad);\n    left: var(--lg-segmented-pad);\n    z-index: 1;\n    width: calc((100% - var(--lg-segmented-pad) * 2) / var(--lg-segmented-count, 1));\n    border-radius: 9999px;\n    background: rgb(255 255 255 / 0.14);\n    box-shadow:\n      inset 0 1px 0 rgb(255 255 255 / 0.22),\n      inset 0 -1px 0 rgb(0 0 0 / 0.12),\n      0 1px 3px rgb(0 0 0 / 0.24),\n      0 4px 12px -4px rgb(0 0 0 / 0.4);\n    pointer-events: none;\n    translate: calc(var(--lg-segmented-index, 0) * 100%) 0;\n    transition:\n      translate 460ms var(--lg-spring),\n      opacity 200ms ease;\n  }\n\n  [dir='rtl'] .lg-segmented > .lg-segmented-indicator {\n    right: var(--lg-segmented-pad);\n    left: auto;\n    translate: calc(var(--lg-segmented-index, 0) * -100%) 0;\n  }\n\n  .lg-segmented:not(:has(> button[data-state='checked'])) > .lg-segmented-indicator {\n    opacity: 0;\n  }\n\n  /* Light glass on a white page would hide the white bubble, so the track\n     sinks into a faint slate well. */\n  [data-lg-theme='light']:not([data-lg-reduce-transparency='1']) .lg-segmented::before {\n    background-color: rgb(100 108 140 / 0.12);\n  }\n\n  [data-lg-theme='light'] .lg-segmented > .lg-segmented-indicator {\n    background: rgb(255 255 255 / 0.9);\n    box-shadow:\n      inset 0 1px 0 rgb(255 255 255 / 0.9),\n      0 1px 3px rgb(0 0 0 / 0.1),\n      0 4px 12px -4px rgb(0 0 0 / 0.16);\n  }\n\n  /* Once measured, script owns the bubble. It springs each edge toward the\n     selected item and writes --lg-lift while the bubble travels or is held,\n     which turns it into clearer glass that floats higher. */\n  .lg-segmented[data-lg-indicator='ready'] {\n    touch-action: pan-y;\n  }\n\n  .lg-segmented[data-lg-indicator='ready'] > .lg-segmented-indicator {\n    --lg-bubble-alpha: 0.14;\n  }\n\n  [data-lg-theme='light'] .lg-segmented[data-lg-indicator='ready'] > .lg-segmented-indicator {\n    --lg-bubble-alpha: 0.9;\n  }\n\n  .lg-segmented[data-lg-indicator='ready'] > .lg-segmented-indicator,\n  .lg-tabs-list[data-lg-indicator='ready'] > .lg-tabs-indicator {\n    --lg-bubble-shadow:\n      inset 0 1px 0 rgb(255 255 255 / 0.22), inset 0 -1px 0 rgb(0 0 0 / 0.12),\n      0 1px 3px rgb(0 0 0 / 0.24), 0 4px 12px -4px rgb(0 0 0 / 0.4);\n\n    top: 0;\n    right: auto;\n    bottom: auto;\n    left: 0;\n    /* A bead of glass: lit from above, clearer while it is lifted, and it\n       brightens and sharpens what lies under it. */\n    background: linear-gradient(\n      180deg,\n      rgb(255 255 255 / calc((var(--lg-bubble-alpha) + 0.08) * (1 - var(--lg-lift, 0) * 0.55))),\n      rgb(255 255 255 / calc(var(--lg-bubble-alpha) * (1 - var(--lg-lift, 0) * 0.55)))\n    );\n    -webkit-backdrop-filter: blur(2px) saturate(1.5)\n      brightness(calc(1.08 + var(--lg-lift, 0) * 0.14));\n    backdrop-filter: blur(2px) saturate(1.5) brightness(calc(1.08 + var(--lg-lift, 0) * 0.14));\n    box-shadow:\n      inset 0 0 0 calc(var(--lg-lift, 0) * 0.75px) rgb(255 255 255 / calc(var(--lg-lift, 0) * 0.5)),\n      inset 0 0 calc(var(--lg-lift, 0) * 12px) rgb(255 255 255 / calc(var(--lg-lift, 0) * 0.2)),\n      0 calc(var(--lg-lift, 0) * 8px) calc(var(--lg-lift, 0) * 22px)\n        rgb(0 0 0 / calc(var(--lg-lift, 0) * 0.25)),\n      var(--lg-bubble-shadow);\n    transition: opacity 200ms ease;\n  }\n\n  [data-lg-theme='light'] .lg-segmented[data-lg-indicator='ready'] > .lg-segmented-indicator,\n  [data-lg-theme='light'] .lg-tabs-list[data-lg-indicator='ready'] > .lg-tabs-indicator {\n    --lg-bubble-shadow:\n      inset 0 1px 0 rgb(255 255 255 / 0.9), 0 1px 3px rgb(0 0 0 / 0.1),\n      0 4px 12px -4px rgb(0 0 0 / 0.16);\n  }\n\n  :is(.lg-segmented-indicator, .lg-tabs-indicator)[data-lg-empty] {\n    opacity: 0;\n  }\n\n  .lg-segmented[data-lg-dragging] {\n    cursor: grabbing;\n    -webkit-user-select: none;\n    user-select: none;\n  }\n\n  .lg-segmented-indicator::after {\n    content: '';\n    position: absolute;\n    inset: 0;\n    padding: var(--lg-rim-width);\n    border-radius: inherit;\n    pointer-events: none;\n    background: linear-gradient(\n      to bottom right,\n      rgb(255 255 255 / var(--lg-specular-peak)),\n      rgb(255 255 255 / var(--lg-specular-floor)) 38% 62%,\n      rgb(255 255 255 / var(--lg-specular-counter))\n    );\n    -webkit-mask:\n      linear-gradient(#000 0 0) content-box,\n      linear-gradient(#000 0 0);\n    -webkit-mask-composite: xor;\n    mask:\n      linear-gradient(#000 0 0) content-box,\n      linear-gradient(#000 0 0);\n    mask-composite: exclude;\n  }\n\n  [data-lg-reduce-transparency='1'] :is(.lg-segmented-indicator, .lg-tabs-indicator)::after {\n    background: var(--lg-border);\n  }\n\n  [data-lg-reduce-transparency='1'] .lg-segmented > .lg-segmented-indicator,\n  [data-lg-reduce-transparency='1']\n    :is(.lg-segmented, .lg-tabs-list)[data-lg-indicator='ready']\n    > :is(.lg-segmented-indicator, .lg-tabs-indicator) {\n    background: var(--lg-control-surface-hover);\n  }\n\n  .lg-segmented-item {\n    position: relative;\n    z-index: 2;\n    display: flex;\n    min-width: 0;\n    align-items: center;\n    justify-content: center;\n    gap: 0.375rem;\n    margin: 0;\n    padding: 0.4375rem 0.875rem;\n    border: none;\n    border-radius: 9999px;\n    background: transparent;\n    color: var(--lg-muted-foreground);\n    font: inherit;\n    font-weight: 500;\n    white-space: nowrap;\n    cursor: pointer;\n    -webkit-tap-highlight-color: transparent;\n    transition: color var(--lg-motion-duration) ease;\n  }\n\n  .lg-segmented-item:hover:not([data-disabled]),\n  .lg-segmented-item[data-state='checked'] {\n    color: var(--lg-foreground);\n  }\n\n  .lg-segmented-item:focus-visible {\n    outline: 2px solid var(--lg-focus-ring);\n    outline-offset: -2px;\n  }\n\n  .lg-segmented-item[data-disabled] {\n    cursor: not-allowed;\n    opacity: var(--lg-disabled-opacity);\n  }\n\n  /* ============================================\n     Badge: a small frosted capsule. Every tone keeps 4.5:1 text contrast\n     over a pure black or pure white backdrop in both themes.\n     ============================================ */\n\n  .lg-badge {\n    --lg-badge-fill: 44 44 46;\n    --lg-badge-ink: #f5f5f7;\n    --lg-badge-tint: 142 142 147;\n    --lg-badge-highlight: rgb(255 255 255 / 0.12);\n\n    display: inline-flex;\n    align-items: center;\n    gap: 0.375rem;\n    box-sizing: border-box;\n    padding: 0.1875rem 0.625rem;\n    border-radius: 9999px;\n    background: rgb(var(--lg-badge-fill) / 0.88);\n    box-shadow:\n      inset 0 1px 0 var(--lg-badge-highlight),\n      inset 0 0 0 0.5px rgb(var(--lg-badge-tint) / 0.4);\n    color: var(--lg-badge-ink);\n    font-size: 0.75rem;\n    line-height: 1rem;\n    font-weight: 600;\n    white-space: nowrap;\n    -webkit-backdrop-filter: blur(min(var(--lg-glass-blur), 12px))\n      brightness(var(--lg-glass-brightness)) contrast(var(--lg-glass-contrast))\n      saturate(var(--lg-glass-sat));\n    backdrop-filter: blur(min(var(--lg-glass-blur), 12px)) brightness(var(--lg-glass-brightness))\n      contrast(var(--lg-glass-contrast)) saturate(var(--lg-glass-sat));\n  }\n\n  .lg-badge[data-tone='blue'] {\n    --lg-badge-fill: 13 44 82;\n    --lg-badge-ink: #b2d6ff;\n    --lg-badge-tint: 0 103 217;\n  }\n\n  .lg-badge[data-tone='green'] {\n    --lg-badge-fill: 22 60 48;\n    --lg-badge-ink: #7cebc0;\n    --lg-badge-tint: 51 214 159;\n  }\n\n  .lg-badge[data-tone='orange'] {\n    --lg-badge-fill: 70 54 22;\n    --lg-badge-ink: #ffd27a;\n    --lg-badge-tint: 255 189 56;\n  }\n\n  .lg-badge[data-tone='red'] {\n    --lg-badge-fill: 76 30 44;\n    --lg-badge-ink: #ffa6b7;\n    --lg-badge-tint: 255 92 122;\n  }\n\n  .lg-badge[data-tone='purple'] {\n    --lg-badge-fill: 44 36 92;\n    --lg-badge-ink: #c7b8ff;\n    --lg-badge-tint: 155 128 255;\n  }\n\n  [data-lg-theme='light'] .lg-badge {\n    --lg-badge-fill: 242 242 244;\n    --lg-badge-ink: #222224;\n    --lg-badge-highlight: rgb(255 255 255 / 0.9);\n  }\n\n  [data-lg-theme='light'] .lg-badge[data-tone='blue'] {\n    --lg-badge-fill: 229 241 255;\n    --lg-badge-ink: #0054b3;\n    --lg-badge-tint: 0 103 217;\n  }\n\n  [data-lg-theme='light'] .lg-badge[data-tone='green'] {\n    --lg-badge-fill: 224 247 238;\n    --lg-badge-ink: #08603f;\n    --lg-badge-tint: 20 168 116;\n  }\n\n  [data-lg-theme='light'] .lg-badge[data-tone='orange'] {\n    --lg-badge-fill: 255 243 219;\n    --lg-badge-ink: #824c00;\n    --lg-badge-tint: 232 150 12;\n  }\n\n  [data-lg-theme='light'] .lg-badge[data-tone='red'] {\n    --lg-badge-fill: 255 229 236;\n    --lg-badge-ink: #a8113a;\n    --lg-badge-tint: 232 52 90;\n  }\n\n  [data-lg-theme='light'] .lg-badge[data-tone='purple'] {\n    --lg-badge-fill: 237 232 255;\n    --lg-badge-ink: #5532d0;\n    --lg-badge-tint: 106 76 240;\n  }\n\n  .lg-badge-dot {\n    flex: none;\n    width: 0.375rem;\n    height: 0.375rem;\n    border-radius: 9999px;\n    background: rgb(var(--lg-badge-tint));\n  }\n\n  /* ============================================\n     Dock: a glass shelf under a row of icons that name themselves on hover\n     ============================================ */\n\n  .lg-dock {\n    --lg-dock-size: 3rem;\n    --lg-dock-gap: 0.5rem;\n    --lg-dock-pad: 0.625rem;\n\n    position: relative;\n    display: inline-flex;\n    align-items: center;\n    gap: var(--lg-dock-gap);\n    box-sizing: border-box;\n    height: calc(var(--lg-dock-size) + var(--lg-dock-pad) * 2);\n    padding: var(--lg-dock-pad) calc(var(--lg-dock-pad) + 0.125rem);\n    isolation: isolate;\n  }\n\n  .lg-dock > .lg-dock-shelf {\n    --lg-panel-radius: calc(var(--lg-dock-size) * 0.24 + var(--lg-dock-pad));\n\n    position: absolute;\n    inset: 0;\n    z-index: 0;\n    pointer-events: none;\n  }\n\n  .lg-dock-item {\n    position: relative;\n    z-index: 1;\n    display: flex;\n    flex: none;\n    align-items: center;\n    justify-content: center;\n    box-sizing: border-box;\n    width: calc(var(--lg-dock-size) * var(--lg-dock-scale, 1));\n    height: calc(var(--lg-dock-size) * var(--lg-dock-scale, 1));\n    margin: 0;\n    padding: 0;\n    border: none;\n    border-radius: 22.5%;\n    /* Nothing is painted behind the artwork, so an icon that bounces or has clear edges shows the\n       shelf. */\n    background: none;\n    color: inherit;\n    cursor: pointer;\n    /* The hover label sits outside the button, where a double click would otherwise select it\n       even while it is hidden. */\n    user-select: none;\n    -webkit-tap-highlight-color: transparent;\n  }\n\n  /* A consumer's icon dimensions take precedence over the full-size app artwork. */\n  .lg-dock-item > :where(:not(.lg-dock-label, .lg-dock-dot)) {\n    width: 100%;\n    height: 100%;\n  }\n\n  .lg-dock-item:focus-visible {\n    outline: 2px solid var(--lg-focus-ring);\n    outline-offset: 3px;\n  }\n\n  .lg-dock-label {\n    position: absolute;\n    bottom: calc(100% + 0.625rem);\n    left: 50%;\n    z-index: 2;\n    padding: 0.375rem 0.625rem;\n    border-radius: 0.625rem;\n    background: var(--lg-overlay-surface);\n    box-shadow:\n      inset 0 0 0 0.5px var(--lg-border),\n      var(--lg-shadow);\n    color: var(--lg-foreground);\n    font-size: 0.8125rem;\n    line-height: 1.125rem;\n    font-weight: 500;\n    white-space: nowrap;\n    pointer-events: none;\n    opacity: 0;\n    translate: -50% 0.25rem;\n    transition:\n      opacity 150ms ease,\n      translate 220ms var(--lg-ease-out);\n    -webkit-backdrop-filter: blur(min(var(--lg-glass-blur), 16px))\n      brightness(var(--lg-glass-brightness)) contrast(var(--lg-glass-contrast))\n      saturate(var(--lg-glass-sat));\n    backdrop-filter: blur(min(var(--lg-glass-blur), 16px)) brightness(var(--lg-glass-brightness))\n      contrast(var(--lg-glass-contrast)) saturate(var(--lg-glass-sat));\n  }\n\n  .lg-dock-item:hover > .lg-dock-label,\n  .lg-dock-item:focus-visible > .lg-dock-label {\n    opacity: 1;\n    translate: -50% 0;\n  }\n\n  .lg-dock-dot {\n    position: absolute;\n    bottom: calc(var(--lg-dock-pad) * -1 + 0.1875rem);\n    left: 50%;\n    width: 0.25rem;\n    height: 0.25rem;\n    border-radius: 9999px;\n    background: var(--lg-foreground);\n    opacity: 0;\n    translate: -50% 0;\n    transition: opacity 200ms ease;\n  }\n\n  .lg-dock-item[data-active='true'] > .lg-dock-dot {\n    opacity: 0.75;\n  }\n\n  .lg-dock-separator {\n    position: relative;\n    z-index: 1;\n    flex: none;\n    align-self: stretch;\n    width: 1px;\n    margin: 0.375rem 0.25rem;\n    background: var(--lg-border);\n  }\n\n  /* ============================================\n     Sheet: a glass card that slides in from an edge. A bottom sheet can be\n     dragged down by its grabber to dismiss it.\n     ============================================ */\n\n  @keyframes lg-sheet-in-bottom {\n    from {\n      translate: 0 calc(100% + 1rem);\n    }\n  }\n\n  @keyframes lg-sheet-out-bottom {\n    to {\n      translate: 0 calc(100% + 1rem);\n    }\n  }\n\n  @keyframes lg-sheet-in-top {\n    from {\n      translate: 0 calc(-100% - 1rem);\n    }\n  }\n\n  @keyframes lg-sheet-out-top {\n    to {\n      translate: 0 calc(-100% - 1rem);\n    }\n  }\n\n  @keyframes lg-sheet-in-left {\n    from {\n      translate: calc(-100% - 1rem) 0;\n    }\n  }\n\n  @keyframes lg-sheet-out-left {\n    to {\n      translate: calc(-100% - 1rem) 0;\n    }\n  }\n\n  @keyframes lg-sheet-in-right {\n    from {\n      translate: calc(100% + 1rem) 0;\n    }\n  }\n\n  @keyframes lg-sheet-out-right {\n    to {\n      translate: calc(100% + 1rem) 0;\n    }\n  }\n\n  .lg-sheet-content {\n    --lg-panel-radius: 2.5rem;\n\n    position: fixed;\n    z-index: 50;\n    display: flex;\n    flex-direction: column;\n    box-sizing: border-box;\n    overflow-x: hidden;\n    overflow-y: auto;\n    overscroll-behavior: contain;\n  }\n\n  .lg-sheet-content:focus {\n    outline: none;\n  }\n\n  .lg-sheet-content[data-side='bottom'],\n  .lg-sheet-content[data-side='top'] {\n    right: 0.5rem;\n    left: 0.5rem;\n    max-width: 40rem;\n    max-height: calc(100dvh - 3rem);\n    margin-inline: auto;\n  }\n\n  .lg-sheet-content[data-side='bottom'] {\n    bottom: 0.5rem;\n  }\n\n  .lg-sheet-content[data-side='top'] {\n    top: 0.5rem;\n  }\n\n  .lg-sheet-content[data-side='left'],\n  .lg-sheet-content[data-side='right'] {\n    top: 0.5rem;\n    bottom: 0.5rem;\n    width: min(24rem, calc(100vw - 1rem));\n  }\n\n  .lg-sheet-content[data-side='left'] {\n    left: 0.5rem;\n  }\n\n  .lg-sheet-content[data-side='right'] {\n    right: 0.5rem;\n  }\n\n  .lg-sheet-content[data-side='bottom'][data-state='open'] {\n    animation: lg-sheet-in-bottom 500ms var(--lg-ease-out);\n  }\n\n  .lg-sheet-content[data-side='bottom'][data-state='closed'] {\n    animation: lg-sheet-out-bottom 300ms var(--lg-ease-out) forwards;\n  }\n\n  .lg-sheet-content[data-side='top'][data-state='open'] {\n    animation: lg-sheet-in-top 500ms var(--lg-ease-out);\n  }\n\n  .lg-sheet-content[data-side='top'][data-state='closed'] {\n    animation: lg-sheet-out-top 300ms var(--lg-ease-out) forwards;\n  }\n\n  .lg-sheet-content[data-side='left'][data-state='open'] {\n    animation: lg-sheet-in-left 500ms var(--lg-ease-out);\n  }\n\n  .lg-sheet-content[data-side='left'][data-state='closed'] {\n    animation: lg-sheet-out-left 300ms var(--lg-ease-out) forwards;\n  }\n\n  .lg-sheet-content[data-side='right'][data-state='open'] {\n    animation: lg-sheet-in-right 500ms var(--lg-ease-out);\n  }\n\n  .lg-sheet-content[data-side='right'][data-state='closed'] {\n    animation: lg-sheet-out-right 300ms var(--lg-ease-out) forwards;\n  }\n\n  .lg-sheet-handle {\n    display: flex;\n    flex: none;\n    justify-content: center;\n    margin: -1rem -1.5rem 0.25rem;\n    padding: 0.625rem 0 0.75rem;\n    cursor: grab;\n    touch-action: none;\n  }\n\n  .lg-sheet-handle:active {\n    cursor: grabbing;\n  }\n\n  .lg-sheet-handle::before {\n    content: '';\n    width: 2.25rem;\n    height: 0.3125rem;\n    border-radius: 9999px;\n    background: var(--lg-muted-foreground);\n    opacity: 0.5;\n  }\n\n  /* ============================================\n     Menu: a frosted list with a soft lozenge under the highlighted row\n     ============================================ */\n\n  .lg-menu-content {\n    --lg-panel-radius: 1.125rem;\n\n    z-index: 50;\n    box-sizing: border-box;\n    min-width: 14rem;\n    max-width: calc(100vw - 1rem);\n    max-height: var(--radix-dropdown-menu-content-available-height, 100dvh);\n    overflow-x: hidden;\n    overflow-y: auto;\n    padding: 0.375rem;\n    font-size: 0.875rem;\n    line-height: calc(1.25 / 0.875);\n    transform-origin: var(--radix-dropdown-menu-content-transform-origin);\n  }\n\n  .lg-menu-content:focus {\n    outline: none;\n  }\n\n  .lg-menu-item {\n    position: relative;\n    display: flex;\n    align-items: center;\n    gap: 0.625rem;\n    min-height: 2.25rem;\n    box-sizing: border-box;\n    padding: 0.4375rem 0.75rem;\n    border-radius: 0.75rem;\n    color: var(--lg-foreground);\n    cursor: default;\n    outline: none;\n    user-select: none;\n  }\n\n  .lg-menu-item > svg {\n    flex: none;\n    width: 1rem;\n    height: 1rem;\n  }\n\n  .lg-menu-item[data-highlighted],\n  .lg-menu-item[data-state='open'] {\n    background: rgb(255 255 255 / 0.14);\n  }\n\n  [data-lg-theme='light'] .lg-menu-item[data-highlighted],\n  [data-lg-theme='light'] .lg-menu-item[data-state='open'] {\n    background: rgb(0 0 0 / 0.06);\n  }\n\n  .lg-menu-item[data-disabled] {\n    opacity: var(--lg-disabled-opacity);\n    pointer-events: none;\n  }\n\n  .lg-menu-item[data-tone='destructive'] {\n    color: var(--lg-invalid);\n  }\n\n  .lg-menu-item--inset {\n    padding-inline-start: 2rem;\n  }\n\n  .lg-menu-indicator {\n    position: absolute;\n    inset-inline-start: 0.5rem;\n    display: inline-flex;\n    width: 1rem;\n    align-items: center;\n    justify-content: center;\n  }\n\n  .lg-menu-indicator > svg {\n    width: 1rem;\n    height: 1rem;\n  }\n\n  .lg-menu-label {\n    padding: 0.375rem 0.75rem 0.25rem;\n    color: var(--lg-muted-foreground);\n    font-size: 0.75rem;\n    line-height: 1rem;\n    font-weight: 600;\n    user-select: none;\n  }\n\n  .lg-menu-separator {\n    height: 1px;\n    margin: 0.375rem 0.625rem;\n    background: var(--lg-border);\n  }\n\n  .lg-menu-shortcut {\n    margin-inline-start: auto;\n    padding-inline-start: 1.5rem;\n    color: var(--lg-muted-foreground);\n    font-size: 0.75rem;\n    letter-spacing: 0.06em;\n  }\n\n  .lg-menu-chevron {\n    margin-inline-start: auto;\n    color: var(--lg-muted-foreground);\n  }\n\n  [dir='rtl'] .lg-menu-chevron {\n    scale: -1 1;\n  }\n\n  /* ============================================\n     Lens: a draggable magnifier. Its view repeats the stage content, zoomed\n     around the lens center and bent at the rim by the generated refraction\n     filter where the engine supports it.\n     ============================================ */\n\n  .lg-lens-stage {\n    position: relative;\n    /* Focus must not scroll the padded lens view and shift the content beneath it. */\n    overflow: clip;\n    isolation: isolate;\n  }\n\n  .lg-lens {\n    --lg-lens-size: 10rem;\n    --lg-lens-zoom: 1.6;\n    --lg-lens-fill: var(--lg-bg);\n    --lg-lens-margin: 0px;\n\n    position: absolute;\n    top: 0;\n    left: 0;\n    z-index: 2;\n    width: var(--lg-lens-size);\n    height: var(--lg-lens-size);\n    border-radius: 50%;\n    box-shadow:\n      0 14px 34px -10px rgb(0 0 0 / 0.5),\n      0 2px 8px rgb(0 0 0 / 0.22);\n    cursor: grab;\n    touch-action: none;\n    -webkit-tap-highlight-color: transparent;\n    translate: calc(var(--lg-lens-x, 0px) - var(--lg-lens-size) / 2)\n      calc(var(--lg-lens-y, 0px) - var(--lg-lens-size) / 2);\n    transition:\n      scale 320ms var(--lg-spring),\n      box-shadow 200ms ease;\n  }\n\n  .lg-lens:active {\n    box-shadow:\n      0 22px 44px -12px rgb(0 0 0 / 0.55),\n      0 4px 12px rgb(0 0 0 / 0.24);\n    cursor: grabbing;\n    scale: 1.04;\n  }\n\n  .lg-lens:focus-visible {\n    outline: 2px solid var(--lg-focus-ring);\n    outline-offset: 3px;\n  }\n\n  /* The view reaches a margin past the lens so the rim filter has content to bend in.\n     WebKit draws a filtered layer from its overflow origin, so the view clips its own\n     overflow on a composited layer and is cut back to the lens by clip-path. */\n  .lg-lens-view {\n    position: absolute;\n    inset: calc(var(--lg-lens-margin) * -1);\n    overflow: hidden;\n    background: var(--lg-lens-fill);\n    clip-path: circle(calc(var(--lg-lens-size) / 2));\n    pointer-events: none;\n    transform: translateZ(0);\n  }\n\n  .lg-lens-scene {\n    position: absolute;\n    top: var(--lg-lens-margin);\n    left: var(--lg-lens-margin);\n    width: var(--lg-lens-stage-width, 100%);\n    height: var(--lg-lens-stage-height, 100%);\n    transform-origin: 0 0;\n    translate: calc(var(--lg-lens-size) / 2 - var(--lg-lens-x, 0px) * var(--lg-lens-zoom))\n      calc(var(--lg-lens-size) / 2 - var(--lg-lens-y, 0px) * var(--lg-lens-zoom));\n    scale: var(--lg-lens-zoom);\n  }\n\n  /* Bevel and sheen over the view, then the specular ring on top. */\n  .lg-lens::before {\n    content: '';\n    position: absolute;\n    inset: 0;\n    z-index: 1;\n    border-radius: inherit;\n    pointer-events: none;\n    background:\n      radial-gradient(circle at 32% 24%, rgb(255 255 255 / 0.22), transparent 42%),\n      linear-gradient(180deg, rgb(255 255 255 / 0.08), transparent 50%);\n    box-shadow:\n      inset 0 0 22px -6px rgb(255 255 255 / 0.5),\n      inset 2px 3px 1px -2px rgb(255 255 255 / 0.9),\n      inset -2px -3px 1px -2px rgb(255 255 255 / 0.55),\n      inset 0 -10px 18px -10px rgb(0 0 0 / 0.3);\n  }\n\n  .lg-lens::after {\n    content: '';\n    position: absolute;\n    inset: 0;\n    z-index: 2;\n    padding: 1px;\n    border-radius: inherit;\n    pointer-events: none;\n    background: linear-gradient(\n      to bottom right,\n      rgb(255 255 255 / 0.9),\n      rgb(255 255 255 / 0.16) 36% 64%,\n      rgb(255 255 255 / 0.5)\n    );\n    -webkit-mask:\n      linear-gradient(#000 0 0) content-box,\n      linear-gradient(#000 0 0);\n    -webkit-mask-composite: xor;\n    mask:\n      linear-gradient(#000 0 0) content-box,\n      linear-gradient(#000 0 0);\n    mask-composite: exclude;\n  }\n\n  /* ============================================\n     GLASS SCENE\n     One WebGL canvas draws every registered glass element in the scene as a\n     single refracting body. The canvas shows only once it has drawn; before\n     that, and whenever WebGL2 is missing, lost or switched off, every element\n     keeps its CSS glass. data-lg-scene=\"active\" marks an element whose\n     material the canvas has taken over.\n     ============================================ */\n\n  .lg-scene {\n    position: relative;\n    isolation: isolate;\n  }\n\n  /* The backdrop and the canvas sit below the scene's children. Their wrapper\n     adds no box, so they stack as before, except over a viewport backdrop\n     (below). */\n  .lg-scene-layers {\n    display: contents;\n    border-radius: inherit;\n  }\n\n  .lg-scene-backdrop,\n  .lg-scene-canvas {\n    position: absolute;\n    inset: 0;\n    z-index: -1;\n    border-radius: inherit;\n    pointer-events: none;\n  }\n\n  .lg-scene-backdrop {\n    display: block;\n    background: var(--lg-scene-backdrop, var(--lg-scene-image, none)) center / cover no-repeat;\n  }\n\n  /* A viewport backdrop holds still while the page scrolls the glass across\n     it, as background-attachment: fixed does. clip-path keeps it inside the\n     scene without becoming its containing block, and the canvas reads where\n     the layer sits, so the glass bends the backdrop that shows beside it. */\n  .lg-scene[data-lg-backdrop-space='viewport'] {\n    clip-path: inset(0);\n  }\n\n  /* The two layers share one box below the children, so the fixed backdrop\n     itself keeps a z-index of auto: over a fixed backdrop with a negative\n     z-index, iOS Safari paints the status bar solid and cuts the page off in a\n     hard line beneath it. */\n  .lg-scene[data-lg-backdrop-space='viewport'] > .lg-scene-layers {\n    display: block;\n    position: absolute;\n    inset: 0;\n    z-index: -1;\n    pointer-events: none;\n  }\n\n  .lg-scene[data-lg-backdrop-space='viewport']\n    > .lg-scene-layers\n    > :is(.lg-scene-backdrop, .lg-scene-canvas) {\n    z-index: auto;\n  }\n\n  .lg-scene[data-lg-backdrop-space='viewport'] > .lg-scene-layers > .lg-scene-backdrop {\n    position: fixed;\n    border-radius: 0;\n  }\n\n  .lg-scene-canvas {\n    display: none;\n    width: 100%;\n    height: 100%;\n  }\n\n  .lg-scene[data-lg-scene-renderer='webgl'] > .lg-scene-layers > .lg-scene-canvas {\n    display: block;\n  }\n\n  /* Each element hands the canvas the same material its CSS glass shows,\n     and the faintest colour of its text, which the face keeps legible. The\n     canvas frosts over a disk, which spreads light as far as a blur of half\n     its radius. A tenth of the surface blur keeps the shapes behind the glass\n     sharp, so its rim has something to bend. Milk-white frost hides them and\n     the glass reads as acrylic. */\n  .lg-scene .lg-glass-surface {\n    --lg-scene-tint: rgb(\n      255 255 255 /\n        calc(var(--lg-surface-alpha) + var(--lg-scene-tint-boost) + var(--lg-surface-lift))\n    );\n    --lg-scene-frost: calc(var(--lg-surface-blur) * 0.1);\n    --lg-scene-ink: var(--lg-muted-foreground);\n    transition:\n      box-shadow var(--lg-motion-duration) ease,\n      transform var(--lg-motion-duration) ease,\n      --lg-scene-tint var(--lg-motion-duration) ease;\n  }\n\n  /* The dock shelf carries no text, so it keeps its full colour. */\n  .lg-scene .lg-glass-surface.lg-dock-shelf {\n    --lg-scene-ink: transparent;\n  }\n\n  .lg-scene .lg-button {\n    --lg-scene-tint: var(--lg-button-fill);\n    --lg-scene-frost: calc(var(--lg-surface-blur) * 0.4);\n    --lg-scene-ink: var(--lg-ink);\n    transition:\n      transform calc(var(--lg-motion-duration) * 1.9) var(--lg-spring),\n      box-shadow var(--lg-motion-duration) ease,\n      --lg-scene-tint var(--lg-motion-duration) ease;\n  }\n\n  .lg-scene .lg-button:not(:disabled, [aria-disabled='true']):hover {\n    --lg-scene-tint: var(--lg-button-fill-hover);\n  }\n\n  .lg-scene .lg-glass-surface[data-lg-scene='active'],\n  .lg-scene .lg-button[data-lg-scene='active'] {\n    box-shadow: none !important;\n  }\n\n  .lg-scene .lg-glass-surface[data-lg-scene='active']::before,\n  .lg-scene .lg-glass-surface[data-lg-scene='active']::after,\n  .lg-scene .lg-glass-surface[data-lg-scene='active'] > .lg-noise,\n  .lg-scene\n    .lg-button[data-lg-scene='active']\n    > .lg-button__layers\n    > :is(\n      .lg-button__light,\n      .lg-button__distortion,\n      .lg-button__tint,\n      .lg-button__shine,\n      .lg-button__rim\n    ) {\n    display: none;\n  }\n\n  /* A button on a pane the canvas draws sits on glass already. It keeps its\n     frost but neither bends nor saturates that face again, which would undo\n     the face's legible range. */\n  .lg-scene\n    [data-lg-scene='active']\n    .lg-button:not(.lg-button--ghost)\n    > .lg-button__layers\n    > .lg-button__distortion {\n    -webkit-backdrop-filter: blur(var(--lg-surface-blur));\n    backdrop-filter: blur(var(--lg-surface-blur));\n  }\n\n  /* Glass nested in a scene's glass, like a segmented track, keeps its frost\n     and edges but casts no shadow, and its tint moves away from the pane's\n     text: darker under light text, lighter under dark text. On the canvas,\n     text on it keeps at least the contrast the face promised; the CSS glass\n     looks the same, so nothing changes when the canvas takes over. */\n  .lg-scene :is(.lg-glass-surface, [data-lg-scene='active']) .lg-glass-surface {\n    box-shadow: none;\n  }\n\n  .lg-scene :is(.lg-glass-surface, [data-lg-scene='active']) .lg-glass-surface::before {\n    background: rgb(0 0 0 / 0.14);\n    -webkit-backdrop-filter: blur(var(--lg-surface-blur));\n    backdrop-filter: blur(var(--lg-surface-blur));\n  }\n\n  [data-lg-theme='light']\n    .lg-scene\n    :is(.lg-glass-surface, [data-lg-scene='active'])\n    .lg-glass-surface::before {\n    background: rgb(255 255 255 / 0.22);\n  }\n\n  /* A plain piece of glass for scenes: a droplet, lens or pebble. Outside a\n     scene, or before the canvas draws, it shows as frosted CSS glass. */\n  .lg-scene-drop {\n    --lg-scene-tint: rgb(255 255 255 / calc(0.1 + var(--lg-scene-tint-boost)));\n    --lg-scene-frost: 3px;\n    --lg-scene-flow: 1;\n    border-radius: var(--lg-radius-lg);\n    background: rgb(255 255 255 / 0.08);\n    box-shadow:\n      inset 0 1px 0 rgb(255 255 255 / 0.35),\n      inset 0 0 0 1px rgb(255 255 255 / 0.14),\n      0 8px 24px rgb(0 0 0 / 0.18);\n    -webkit-backdrop-filter: blur(min(var(--lg-glass-blur), 8px))\n      brightness(var(--lg-glass-brightness)) contrast(var(--lg-glass-contrast))\n      saturate(var(--lg-glass-sat));\n    backdrop-filter: blur(min(var(--lg-glass-blur), 8px)) brightness(var(--lg-glass-brightness))\n      contrast(var(--lg-glass-contrast)) saturate(var(--lg-glass-sat));\n  }\n\n  .lg-scene-drop[data-lg-scene='active'] {\n    background: none !important;\n    box-shadow: none !important;\n    -webkit-backdrop-filter: none !important;\n    backdrop-filter: none !important;\n  }\n\n  :root[data-lg-reduce-transparency='1'] .lg-scene-drop {\n    background: var(--lg-opaque-surface);\n    -webkit-backdrop-filter: none;\n    backdrop-filter: none;\n  }\n\n  /* The system setting also protects components installed without a provider,\n     including their first paint. An explicit provider choice takes precedence. */\n  @media (prefers-reduced-transparency: reduce) {\n    :root:not([data-lg-reduce-transparency='0']) {\n      --lg-glass-blur: 0px;\n      --lg-glass-alpha: 0.95;\n      --lg-noise-alpha: 0.01;\n      --lg-glass-contrast: 1;\n      --lg-glass-sat: 1;\n      --lg-glass-brightness: 1;\n      --lg-refraction-scale: 0;\n      --lg-lens-depth: 0;\n      --lg-opaque-surface: #2c2c2e;\n      --lg-control-surface: #3a3a3c;\n      --lg-control-surface-hover: #48484a;\n      --lg-track: #48484a;\n    }\n\n    :root[data-lg-theme='light']:not([data-lg-reduce-transparency='0']) {\n      --lg-opaque-surface: #ffffff;\n      --lg-control-surface: #f0f0f2;\n      --lg-control-surface-hover: #e3e3e7;\n      --lg-track: #e6e6e9;\n    }\n\n    :root:not([data-lg-reduce-transparency='0']) .lg-glass-surface::before {\n      -webkit-backdrop-filter: none !important;\n      backdrop-filter: none !important;\n      background: var(--lg-opaque-surface) !important;\n      box-shadow: none !important;\n      transform: none;\n    }\n\n    :root:not([data-lg-reduce-transparency='0'])\n      :is(.lg-glass-surface, .lg-tabs-trigger[data-state='active'])::after,\n    :root:not([data-lg-reduce-transparency='0'])\n      :is(.lg-segmented-indicator, .lg-tabs-indicator)::after {\n      background: var(--lg-border);\n    }\n\n    :root:not([data-lg-reduce-transparency='0']) .lg-button__rim {\n      background: none;\n      box-shadow: inset 0 0 0 var(--lg-rim-width) var(--lg-border);\n    }\n\n    :root:not([data-lg-reduce-transparency='0'])\n      :is(\n        .lg-dialog-content,\n        .lg-popover-content,\n        .lg-toast-root,\n        .lg-tooltip-content,\n        .lg-sheet-content,\n        .lg-menu-content,\n        .lg-select-content,\n        .lg-dock-label\n      ) {\n      background: var(--lg-opaque-surface) !important;\n      -webkit-backdrop-filter: none !important;\n      backdrop-filter: none !important;\n    }\n\n    :root:not([data-lg-reduce-transparency='0'])\n      :is(\n        .lg-button__distortion,\n        .lg-input,\n        .lg-accordion-trigger,\n        .lg-dialog-overlay,\n        .lg-badge,\n        .lg-alert\n      ) {\n      -webkit-backdrop-filter: none !important;\n      backdrop-filter: none !important;\n    }\n\n    :root:not([data-lg-reduce-transparency='0'])\n      .lg-button--prominent\n      > .lg-button__layers\n      > .lg-button__distortion {\n      background: var(--lg-prominent-fill) !important;\n    }\n\n    :root:not([data-lg-reduce-transparency='0'])\n      .lg-button:not(.lg-button--ghost, .lg-button--prominent) {\n      --lg-button-fill: var(--lg-control-surface) !important;\n      --lg-button-fill-hover: var(--lg-control-surface-hover) !important;\n    }\n\n    :root:not([data-lg-reduce-transparency='0']) .lg-button__layers > .lg-button__light {\n      display: none !important;\n    }\n\n    :root:not([data-lg-reduce-transparency='0']) :is(.lg-switch-thumb, .lg-slider-thumb) {\n      background: var(--lg-knob) !important;\n    }\n\n    :root:not([data-lg-reduce-transparency='0']) :is(.lg-button__shine, .lg-button__tint) {\n      opacity: 0;\n    }\n\n    :root:not([data-lg-reduce-transparency='0']) :is(.lg-button__bloom, .lg-refraction-background) {\n      display: none;\n    }\n\n    :root:not([data-lg-reduce-transparency='0']) .lg-segmented > .lg-segmented-indicator,\n    :root:not([data-lg-reduce-transparency='0'])\n      :is(.lg-segmented, .lg-tabs-list)[data-lg-indicator='ready']\n      > :is(.lg-segmented-indicator, .lg-tabs-indicator) {\n      background: var(--lg-control-surface-hover);\n    }\n\n    :root:not([data-lg-reduce-transparency='0']) .lg-scene-drop {\n      background: var(--lg-opaque-surface);\n      -webkit-backdrop-filter: none;\n      backdrop-filter: none;\n    }\n  }\n}\n",
      "type": "registry:file",
      "target": "components/glassyui/styles/liquid.css"
    },
    {
      "path": "registry/glassyui/glass-surface.tsx",
      "content": "'use client';\n\nimport clsx from 'clsx';\nimport { Children, forwardRef, useMemo, useRef, useSyncExternalStore } from 'react';\nimport type { CSSProperties, HTMLAttributes, ReactNode } from 'react';\nimport { mergeRefs } from './lib/merge-refs';\nimport { useGlassScenePane } from './lib/scene-context';\nimport { useLensFilter, useRefractionFilter } from './lib/use-refraction-filter';\nimport { useOptionalPreferences } from './glass-provider';\n\nexport type SurfaceRefraction = 'none' | 'soft' | 'strong';\n\nexport type RefractionBackgroundSpace = 'local' | 'viewport';\n\nexport type SurfacePreset = 'subtle' | 'standard' | 'prominent' | 'control' | 'showcase';\n\nexport type GlassSurfaceProps = HTMLAttributes<HTMLDivElement> & {\n  /** Brightens the surface a touch on hover. */\n  interactive?: boolean;\n  /** Chromium edge lens over the frost. On by default for control and showcase presets. */\n  lens?: boolean;\n  preset?: SurfacePreset;\n  refraction?: SurfaceRefraction;\n  refractionBackground?: ReactNode;\n  refractionBackgroundSpace?: RefractionBackgroundSpace;\n  refractionDisplacement?: number;\n  /**\n   * How thick this glass is, as a multiple of regular. A thicker slab has a\n   * wider rim that bends the backdrop further and splits more colour. Defaults\n   * to the site's thickness preference. Works with a supplied backdrop in every\n   * browser, or with the Chromium lens over live content.\n   */\n  thickness?: number;\n};\n\n// Increased contrast dims the lens through its tokens, which the lens reads only when it measures.\nconst contrastQuery = '(prefers-contrast: more)';\n\nconst subscribeToContrast = (onChange: () => void) => {\n  const query = window.matchMedia(contrastQuery);\n  query.addEventListener('change', onChange);\n\n  return () => query.removeEventListener('change', onChange);\n};\n\nconst readContrast = () => window.matchMedia(contrastQuery).matches;\n\nconst readServerContrast = () => false;\n\nexport const GlassSurface = forwardRef<HTMLDivElement, GlassSurfaceProps>(\n  (\n    {\n      className,\n      children,\n      interactive = false,\n      preset = 'standard',\n      lens = preset === 'control' || preset === 'showcase',\n      refraction = preset === 'showcase' ? 'strong' : 'none',\n      refractionBackground,\n      refractionBackgroundSpace = 'local',\n      refractionDisplacement,\n      style,\n      thickness,\n      ...rest\n    },\n    forwardedRef,\n  ) => {\n    const { preferences } = useOptionalPreferences();\n    const reduceMotion = Boolean(preferences?.reduceMotion);\n    const reduceTransparency = Boolean(preferences?.reduceTransparency);\n    const surfaceRef = useRef<HTMLDivElement | null>(null);\n    const ref = useMemo(() => mergeRefs(surfaceRef, forwardedRef), [forwardedRef]);\n\n    const generatedRefractionEnabled =\n      refraction !== 'none' &&\n      Boolean(refractionBackground) &&\n      !reduceMotion &&\n      !reduceTransparency;\n\n    const { active, filterElement, filterStyle, sceneRef } = useRefractionFilter(surfaceRef, {\n      displacement: refractionDisplacement,\n      enabled: generatedRefractionEnabled,\n      reduceTransparency,\n      strength: refraction === 'none' ? 'soft' : refraction,\n      thickness: thickness ?? preferences?.thickness,\n      viewportAligned: refractionBackgroundSpace === 'viewport',\n    });\n\n    const moreContrast = useSyncExternalStore(\n      subscribeToContrast,\n      readContrast,\n      readServerContrast,\n    );\n\n    // One refraction technique at a time: a generated background scene covers the frost.\n    const lensFilter = useLensFilter(surfaceRef, {\n      enabled: lens && !generatedRefractionEnabled && !reduceTransparency,\n      signature: `${preferences?.theme}:${preferences?.mode}:${preferences?.quality}:${thickness ?? preferences?.thickness}:${moreContrast}`,\n    });\n\n    // Inside a GlassScene the canvas draws this glass; a generated refraction\n    // scene is its own backdrop and keeps its CSS material.\n    useGlassScenePane(surfaceRef, !generatedRefractionEnabled);\n\n    return (\n      <div\n        ref={ref}\n        data-lg-generated-refraction={active ? 'true' : 'false'}\n        data-lg-interactive={interactive ? 'true' : 'false'}\n        data-lg-lens={lensFilter.active ? 'active' : undefined}\n        data-lg-preset={preset}\n        data-lg-refraction={refraction}\n        data-lg-refraction-background-space={refractionBackgroundSpace}\n        className={clsx('lg-glass-surface', className)}\n        style={\n          // SAFETY: CSSProperties has no custom-property index; these add string-valued properties.\n          lensFilter.filterStyle || thickness !== undefined\n            ? ({\n                ...style,\n                ...(thickness === undefined ? null : { '--lg-glass-thickness': thickness }),\n                ...(lensFilter.filterStyle ? { '--lg-lens-filter': lensFilter.filterStyle } : null),\n              } as CSSProperties)\n            : style\n        }\n        {...rest}\n      >\n        {filterElement}\n        {lensFilter.filterElement}\n        {active ? (\n          <div\n            className=\"lg-refraction-background\"\n            aria-hidden=\"true\"\n            style={{ filter: filterStyle }}\n          >\n            <div ref={sceneRef} className=\"lg-refraction-scene\">\n              {refractionBackground}\n            </div>\n          </div>\n        ) : null}\n        <span className=\"lg-noise\" aria-hidden />\n        {Children.map(children, (child) =>\n          // Children.map yields null, elements, portals or text; wrap only the text.\n          child === null || child instanceof Object ? (\n            child\n          ) : (\n            <span className=\"lg-glass-text\">{child}</span>\n          ),\n        )}\n      </div>\n    );\n  },\n);\n\nGlassSurface.displayName = 'GlassSurface';\n",
      "type": "registry:ui",
      "target": "components/glassyui/glass-surface.tsx"
    },
    {
      "path": "registry/glassyui/lib/merge-refs.ts",
      "content": "import type { Ref } from 'react';\n\nexport function mergeRefs<T>(...refs: Array<Ref<T> | undefined>) {\n  return (node: T) => {\n    for (const ref of refs) {\n      if (!ref) continue;\n\n      if ('current' in ref) {\n        try {\n          ref.current = node;\n        } catch {\n          // Read-only refs cannot be assigned.\n        }\n      } else {\n        ref(node);\n      }\n    }\n  };\n}\n",
      "type": "registry:lib",
      "target": "components/glassyui/lib/merge-refs.ts"
    },
    {
      "path": "registry/glassyui/lib/refraction-map.ts",
      "content": "import { SLAB_AIR_GAP, SLAB_MAX_SLOPE, SLAB_MIN_RISE, SLAB_RISE_SPAN } from './slab-optics';\n\nexport type GeneratedRefractionStrength = 'soft' | 'strong';\n\ntype RefractionPreset = {\n  centerNeutralRatio: number;\n  defaultDisplacement: number;\n  edgeBandRatio: number;\n  edgeWidth: number;\n  /** Rim pull at the default displacement, as a share of the edge band. */\n  rimPull: number;\n};\n\nexport type RefractionMapOptions = {\n  devicePixelRatio?: number;\n  displacement?: number;\n  height: number;\n  radius: number;\n  strength: GeneratedRefractionStrength;\n  thickness?: number;\n  width: number;\n};\n\nexport type RefractionMapMetrics = {\n  cacheKey: string;\n  dispersion: number;\n  edgeBand: number;\n  /** Corner radius of the bend field, never tighter than the edge band. */\n  fieldRadius: number;\n  filterBlur: number;\n  filterPadding: number;\n  filterScale: number;\n  height: number;\n  mapHeight: number;\n  mapPixels: number;\n  mapWidth: number;\n  paddedHeight: number;\n  paddedWidth: number;\n  /** Inward offset at the rim, in CSS pixels. */\n  pull: number;\n  radius: number;\n  width: number;\n};\n\nexport type RefractionMapBuildResult = {\n  href: string;\n  metrics: RefractionMapMetrics;\n};\n\nexport const MAX_REFRACTION_MAP_PIXELS = 160000;\n\nconst REFRACTION_PRESETS: Record<GeneratedRefractionStrength, RefractionPreset> = {\n  soft: {\n    centerNeutralRatio: 0.68,\n    defaultDisplacement: 72,\n    edgeBandRatio: 0.18,\n    edgeWidth: 1.08,\n    rimPull: 0.22,\n  },\n  strong: {\n    centerNeutralRatio: 0.58,\n    defaultDisplacement: 112,\n    edgeBandRatio: 0.2,\n    edgeWidth: 1.22,\n    rimPull: 0.34,\n  },\n};\n\n/**\n * Scene blur under the rim, in CSS pixels. Chromium and Firefox sample the bend\n * nearest-neighbour, so the magnified rim would stair-step at 1x pixel density. The\n * map's blue channel keeps the blur off the flat centre.\n */\nconst RIM_BLUR = 0.8;\n\n/**\n * The bend falls off as (1 - t)^2 across the edge band, steepest at the rim. Any pull\n * under half the band keeps each sample further in than its outer neighbour, so the rim\n * compresses the view like thick glass and never mirrors it. The base pull is 0.34;\n * even the furthest colour stays below 0.4 to leave room for the map's 8-bit rounding.\n */\nconst MAX_RIM_PULL = 0.34;\n\nconst MAX_CHROMATIC_RIM_PULL = 0.4;\n\nconst refractionMapCache = new Map<string, string>();\n\nconst maxCachedRefractionMaps = 48;\n\nexport function clamp(value: number, min: number, max: number) {\n  return Math.min(max, Math.max(min, value));\n}\n\nfunction smoothstep(edge0: number, edge1: number, value: number) {\n  const t = clamp((value - edge0) / Math.max(edge1 - edge0, 0.0001), 0, 1);\n\n  return t * t * (3 - 2 * t);\n}\n\ntype Edge = { distance: number; normalX: number; normalY: number };\n\n// Distance to a rounded rectangle plus its outward unit normal.\nfunction roundedRectEdge(\n  x: number,\n  y: number,\n  width: number,\n  height: number,\n  radius: number,\n  edge: Edge,\n) {\n  const px = x - width / 2;\n  const py = y - height / 2;\n  const qx = Math.abs(px) - (width / 2 - radius);\n  const qy = Math.abs(py) - (height / 2 - radius);\n  const signX = px < 0 ? -1 : 1;\n  const signY = py < 0 ? -1 : 1;\n\n  if (qx > 0 && qy > 0) {\n    const length = Math.hypot(qx, qy);\n\n    edge.distance = length - radius;\n    edge.normalX = (signX * qx) / length;\n    edge.normalY = (signY * qy) / length;\n  } else if (qx > qy) {\n    edge.distance = qx - radius;\n    edge.normalX = signX;\n    edge.normalY = 0;\n  } else {\n    edge.distance = qy - radius;\n    edge.normalX = 0;\n    edge.normalY = signY;\n  }\n\n  return edge;\n}\n\nfunction fitMapSize(width: number, height: number, pixelRatio: number) {\n  let mapWidth = clamp(Math.round(width * pixelRatio), 32, 1800);\n  let mapHeight = clamp(Math.round(height * pixelRatio), 32, 1200);\n\n  const pixels = mapWidth * mapHeight;\n\n  if (pixels <= MAX_REFRACTION_MAP_PIXELS) {\n    return { mapWidth, mapHeight };\n  }\n\n  const ratio = Math.sqrt(MAX_REFRACTION_MAP_PIXELS / pixels);\n  mapWidth = Math.max(32, Math.floor(mapWidth * ratio));\n  mapHeight = Math.max(32, Math.floor(mapHeight * ratio));\n\n  while (mapWidth * mapHeight > MAX_REFRACTION_MAP_PIXELS) {\n    if (mapWidth >= mapHeight) {\n      mapWidth -= 1;\n    } else {\n      mapHeight -= 1;\n    }\n  }\n\n  return { mapWidth, mapHeight };\n}\n\nexport function computeRefractionMapMetrics(options: RefractionMapOptions): RefractionMapMetrics {\n  const preset = REFRACTION_PRESETS[options.strength];\n  const width = Math.max(0, options.width);\n  const height = Math.max(0, options.height);\n  const minDimension = Math.min(width, height);\n  const radius = clamp(options.radius, 0, minDimension / 2);\n  const displacement = clamp(options.displacement ?? preset.defaultDisplacement, 0, 196);\n  const thickness = clamp(options.thickness ?? 1, 0.1, 4);\n  const rimWidth = 0.6 + 0.4 * thickness;\n  const dispersion = clamp((thickness - 1) * 0.2, 0, 0.6);\n  const blueFactor = 1 + dispersion / 2;\n  const neutralInset = (minDimension * (1 - preset.centerNeutralRatio)) / 2;\n\n  const edgeBand = clamp(\n    Math.min(minDimension * preset.edgeBandRatio, neutralInset) * preset.edgeWidth * rimWidth,\n    6,\n    Math.min(72 * rimWidth, (radius || 56) * 1.15 * rimWidth, minDimension * 0.48),\n  );\n\n  // Inside a tighter corner the inset contours would turn sharp and pinch the bend.\n  const fieldRadius = clamp(Math.max(radius, edgeBand), 0, minDimension / 2);\n\n  const pull =\n    edgeBand *\n    Math.min(\n      MAX_RIM_PULL,\n      MAX_CHROMATIC_RIM_PULL / blueFactor,\n      (preset.rimPull * displacement) / preset.defaultDisplacement,\n    );\n\n  // WebKit shifts a clipped, filtered scene unless the filter region reaches past the\n  // box as far as the primitives read: the blue pull plus three blur deviations.\n  const filterPadding = Math.ceil(pull * blueFactor + RIM_BLUR * 3) + 2;\n  const paddedWidth = width + filterPadding * 2;\n  const paddedHeight = height + filterPadding * 2;\n  const targetRatio = clamp((options.devicePixelRatio ?? 1) * 1.12, 1.15, 2.1);\n  const targetPixels = paddedWidth * paddedHeight * targetRatio * targetRatio;\n\n  const pixelRatio =\n    targetPixels > MAX_REFRACTION_MAP_PIXELS\n      ? Math.max(1, targetRatio * Math.sqrt(MAX_REFRACTION_MAP_PIXELS / targetPixels))\n      : targetRatio;\n\n  const { mapWidth, mapHeight } = fitMapSize(paddedWidth, paddedHeight, pixelRatio);\n\n  const cacheKey = [\n    mapWidth,\n    mapHeight,\n    Math.round(width),\n    Math.round(height),\n    Math.round(fieldRadius * 10),\n    Math.round(edgeBand * 10),\n    filterPadding,\n  ].join(':');\n\n  return {\n    cacheKey,\n    dispersion,\n    edgeBand,\n    fieldRadius,\n    filterBlur: RIM_BLUR,\n    filterPadding,\n    // Map channels hold a unit offset; the scale turns it into CSS pixels.\n    filterScale: Math.round(pull * 2 * 100) / 100,\n    height,\n    mapHeight,\n    mapPixels: mapWidth * mapHeight,\n    mapWidth,\n    paddedHeight,\n    paddedWidth,\n    pull,\n    radius,\n    width,\n  };\n}\n\n/**\n * Encodes a unit rim field: R/G = 0.5 + 0.5 * inward offset. Past the field's edge the\n * rim offset carries on unchanged, so the map stays smooth across the clipped border.\n * B is the share of softened scene: full through the outer half of the band, which\n * holds every point the steep rim samples, and gone by the flat centre.\n */\nexport async function buildRefractionMapDataUrl(\n  options: RefractionMapOptions,\n): Promise<RefractionMapBuildResult> {\n  const metrics = computeRefractionMapMetrics(options);\n  const cached = refractionMapCache.get(metrics.cacheKey);\n\n  if (cached) return { href: cached, metrics };\n\n  if (typeof document === 'undefined') {\n    throw new Error('Refraction maps require a browser document');\n  }\n\n  const canvas = document.createElement('canvas');\n  canvas.width = metrics.mapWidth;\n  canvas.height = metrics.mapHeight;\n\n  const ctx = canvas.getContext('2d');\n\n  if (!ctx) {\n    throw new Error('Canvas 2D context unavailable');\n  }\n\n  const {\n    edgeBand,\n    fieldRadius,\n    filterPadding,\n    height,\n    mapHeight,\n    mapWidth,\n    paddedHeight,\n    paddedWidth,\n    width,\n  } = metrics;\n\n  const data = new Uint8ClampedArray(mapWidth * mapHeight * 4);\n  const edge: Edge = { distance: 0, normalX: 0, normalY: 0 };\n\n  for (let yIndex = 0; yIndex < mapHeight; yIndex += 1) {\n    const y = ((yIndex + 0.5) / mapHeight) * paddedHeight - filterPadding;\n\n    for (let xIndex = 0; xIndex < mapWidth; xIndex += 1) {\n      const x = ((xIndex + 0.5) / mapWidth) * paddedWidth - filterPadding;\n      const index = (yIndex * mapWidth + xIndex) * 4;\n      roundedRectEdge(x, y, width, height, fieldRadius, edge);\n      const depth = clamp(-edge.distance / edgeBand, 0, 1);\n      const falloff = (1 - depth) ** 2;\n      const offsetX = -edge.normalX * falloff;\n      const offsetY = -edge.normalY * falloff;\n\n      data[index] = Math.round((0.5 + offsetX / 2) * 255);\n      data[index + 1] = Math.round((0.5 + offsetY / 2) * 255);\n      data[index + 2] = Math.round((1 - smoothstep(0.5, 1, depth)) * 255);\n      data[index + 3] = 255;\n    }\n  }\n\n  ctx.putImageData(new ImageData(data, mapWidth, mapHeight), 0, 0);\n  const href = canvas.toDataURL('image/png');\n  refractionMapCache.set(metrics.cacheKey, href);\n\n  if (refractionMapCache.size > maxCachedRefractionMaps) {\n    const oldestKey = refractionMapCache.keys().next().value;\n\n    if (oldestKey) refractionMapCache.delete(oldestKey);\n  }\n\n  return { href, metrics };\n}\n\n/** Corner radii in CSS pixels, clockwise from the top left. */\nexport type LensRadii = readonly [number, number, number, number];\n\nexport type LensMapOptions = {\n  /** Width of the curved rim in CSS pixels. */\n  bevel: number;\n  /** Multiplies how far the rim bends the backdrop. 0 leaves it flat. */\n  depth: number;\n  devicePixelRatio?: number;\n  height: number;\n  /** Refractive index of the glass. */\n  ior: number;\n  radii: LensRadii;\n  /** Height of the slab in CSS pixels. Thicker glass bends further. */\n  thickness: number;\n  width: number;\n};\n\nexport type LensMapMetrics = {\n  bevel: number;\n  cacheKey: string;\n  height: number;\n  mapHeight: number;\n  mapWidth: number;\n  /** The furthest the rim reads the backdrop from, in CSS pixels. */\n  reach: number;\n  width: number;\n};\n\nexport type LensMapBuildResult = {\n  href: string;\n  metrics: LensMapMetrics;\n};\n\nconst MAX_LENS_MAP_PIXELS = 420000;\n\nexport const MAX_LENS_SURFACE_AREA = 720000;\n\n// The rim reads the backdrop from no further than this share of its width, and\n// the point it reads from advances by at least a quarter of every pixel across\n// the rim, so the view compresses toward the edge and never folds back on itself.\nconst LENS_REACH = 0.7;\n\nconst LENS_FOLD = 0.75;\n\nconst LENS_PROFILE_STEPS = 512;\n\n// The rim and the flat top are the same frosted glass, but smoked glass lets more\n// light through its rim. Blue holds the share of the rim's light: all of it near\n// the edge, none past four fifths of the rim or a sixth of the surface, whichever\n// comes first, so small pieces keep the top's shade in the middle.\nconst LENS_RIM_LIGHT = 0.8;\n\nconst LENS_RIM_LIGHT_SURFACE = 0.16;\n\nconst LENS_RIM_LIGHT_FALLOFF = 0.45;\n\nconst lensMapCache = new Map<string, LensMapBuildResult>();\n\nconst maxCachedLensMaps = 32;\n\n// Native byte order keeps the neutral RGBA pixel identical on every platform.\nconst FLAT_LENS_PIXEL = new Uint32Array(new Uint8Array([128, 128, 0, 255]).buffer)[0];\n\n/**\n * How far inward a view ray lands on the backdrop after it crosses a slab of glass\n * whose top curves down into a rim, s pixels in from the edge. The top follows\n * (1 - (1 - u)^4)^(1/4) across the rim, Snell's law bends the ray into the glass and\n * again out of its flat underside, and it crosses an air gap to the backdrop. This is\n * the WebGL scene's `through()`, for a ray straight down.\n */\nfunction slabOffset(s: number, bevel: number, thickness: number, ior: number) {\n  const u = s / bevel;\n  const v = 1 - Math.max(u, 0.002);\n  let rise = 1;\n  let steepness = 0;\n\n  if (u < 1) {\n    const v4 = v ** 4;\n\n    rise = (1 - v4) ** 0.25;\n    steepness = v ** 3 * Math.max(1 - v4, 1e-6) ** -0.75;\n  }\n\n  const slope = Math.min(((SLAB_RISE_SPAN * thickness) / bevel) * steepness, SLAB_MAX_SLOPE);\n  const height = thickness * (SLAB_MIN_RISE + SLAB_RISE_SPAN * rise);\n  const tilt = Math.hypot(slope, 1);\n  const sinTilt = slope / tilt;\n  const cosTilt = 1 / tilt;\n  const eta = 1 / ior;\n  const root = Math.sqrt(Math.max(1 - eta * eta * sinTilt * sinTilt, 0));\n  const bend = eta * cosTilt - root;\n  const along = bend * sinTilt;\n  const down = Math.max(eta - bend * cosTilt, 0.05);\n  const sinOut = ior * Math.abs(along);\n  const cosOut = Math.sqrt(Math.max(1 - sinOut * sinOut, 0));\n  const leaving = (ior * along) / Math.max(sinOut, 1);\n\n  return -(along * (height / down) + leaving * (SLAB_AIR_GAP / Math.max(cosOut, 0.1)));\n}\n\n/**\n * The inward offset across the rim, from the edge to its inner boundary. The physical\n * offset is softly capped, then limited so it never falls faster than the pixels it\n * crosses, which would fold the view back on itself.\n */\nfunction lensProfile(bevel: number, thickness: number, ior: number, depth: number) {\n  const cap = LENS_REACH * bevel;\n  const step = bevel / LENS_PROFILE_STEPS;\n  const offsets = new Float32Array(LENS_PROFILE_STEPS + 1);\n\n  for (let index = 0; index < LENS_PROFILE_STEPS; index += 1) {\n    offsets[index] =\n      cap * Math.tanh((depth * slabOffset(index * step, bevel, thickness, ior)) / cap);\n  }\n\n  for (let index = LENS_PROFILE_STEPS - 1; index >= 0; index -= 1) {\n    offsets[index] = Math.min(offsets[index], offsets[index + 1] + LENS_FOLD * step);\n  }\n\n  return { offsets, reach: Math.max(...offsets, 0.01) };\n}\n\n// Distance to a rounded rectangle with its own radius in every corner, plus its outward unit normal.\nfunction roundedBoxEdge(\n  x: number,\n  y: number,\n  width: number,\n  height: number,\n  radii: LensRadii,\n  edge: Edge,\n) {\n  const px = x - width / 2;\n  const py = y - height / 2;\n  const radius = px < 0 ? (py < 0 ? radii[0] : radii[3]) : py < 0 ? radii[1] : radii[2];\n  const qx = Math.abs(px) - (width / 2 - radius);\n  const qy = Math.abs(py) - (height / 2 - radius);\n  const signX = px < 0 ? -1 : 1;\n  const signY = py < 0 ? -1 : 1;\n\n  if (qx > 0 && qy > 0) {\n    const length = Math.hypot(qx, qy);\n\n    edge.distance = length - radius;\n    edge.normalX = (signX * qx) / length;\n    edge.normalY = (signY * qy) / length;\n  } else if (qx > qy) {\n    edge.distance = qx - radius;\n    edge.normalX = signX;\n    edge.normalY = 0;\n  } else {\n    edge.distance = qy - radius;\n    edge.normalX = 0;\n    edge.normalY = signY;\n  }\n\n  return edge;\n}\n\nfunction computeLensMapMetrics(options: LensMapOptions) {\n  const width = Math.max(1, options.width);\n  const height = Math.max(1, options.height);\n  const bevel = clamp(options.bevel, 1, Math.min(width, height) / 2);\n  const pixelRatio = clamp(options.devicePixelRatio ?? 1, 1, 2);\n  let mapWidth = clamp(Math.round(width * pixelRatio), 32, 1800);\n  let mapHeight = clamp(Math.round(height * pixelRatio), 32, 1200);\n\n  if (mapWidth * mapHeight > MAX_LENS_MAP_PIXELS) {\n    const ratio = Math.sqrt(MAX_LENS_MAP_PIXELS / (mapWidth * mapHeight));\n\n    mapWidth = Math.max(32, Math.floor(mapWidth * ratio));\n    mapHeight = Math.max(32, Math.floor(mapHeight * ratio));\n  }\n\n  const cacheKey = [\n    mapWidth,\n    mapHeight,\n    Math.round(width),\n    Math.round(height),\n    ...options.radii.map((radius) => Math.round(radius * 10)),\n    Math.round(bevel * 10),\n    Math.round(options.thickness * 10),\n    Math.round(options.ior * 100),\n    Math.round(options.depth * 100),\n  ].join(':');\n\n  return { bevel, cacheKey, height, mapHeight, mapWidth, width };\n}\n\n/**\n * Encodes the rim of a slab of glass as a displacement field: R/G = 0.5 + 0.5 * the\n * offset the backdrop is read from, as a share of `reach`. The SVG feDisplacementMap\n * scale of twice `reach` turns it back into CSS pixels. B is the share of the rim's\n * light, which smoked glass dims less than its top. The field is flat past the rim.\n */\nexport function buildLensMapDataUrl(options: LensMapOptions): LensMapBuildResult {\n  const base = computeLensMapMetrics(options);\n  const cached = lensMapCache.get(base.cacheKey);\n\n  if (cached) {\n    lensMapCache.delete(base.cacheKey);\n    lensMapCache.set(base.cacheKey, cached);\n\n    return cached;\n  }\n\n  if (typeof document === 'undefined') {\n    throw new Error('Lens maps require a browser document');\n  }\n\n  const canvas = document.createElement('canvas');\n  canvas.width = base.mapWidth;\n  canvas.height = base.mapHeight;\n\n  const ctx = canvas.getContext('2d');\n\n  if (!ctx) {\n    throw new Error('Canvas 2D context unavailable');\n  }\n\n  const { bevel, height, mapHeight, mapWidth, width } = base;\n  const { offsets, reach } = lensProfile(bevel, options.thickness, options.ior, options.depth);\n\n  const litTo = Math.min(\n    LENS_RIM_LIGHT,\n    (LENS_RIM_LIGHT_SURFACE * Math.min(width, height)) / bevel,\n  );\n\n  const litFrom = litTo * LENS_RIM_LIGHT_FALLOFF;\n  const data = new Uint8ClampedArray(mapWidth * mapHeight * 4);\n  const pixels = new Uint32Array(data.buffer);\n  const edge: Edge = { distance: 0, normalX: 0, normalY: 0 };\n  // Beyond every corner and the bevel, the map is exactly neutral. Keep a full\n  // texel inside that rectangle so fractional dimensions cannot round a rim in.\n  const flatInset = Math.max(bevel, ...options.radii);\n  const flatLeft = Math.min(mapWidth, Math.ceil((flatInset / width) * mapWidth + 0.5));\n  const flatRight = Math.max(flatLeft, Math.floor(((width - flatInset) / width) * mapWidth - 0.5));\n  const flatTop = Math.ceil((bevel / height) * mapHeight + 0.5);\n  const flatBottom = Math.floor(((height - bevel) / height) * mapHeight - 0.5);\n\n  for (let yIndex = 0; yIndex < mapHeight; yIndex += 1) {\n    const y = ((yIndex + 0.5) / mapHeight) * height;\n    const flatRow = yIndex >= flatTop && yIndex < flatBottom;\n\n    for (let xIndex = 0; xIndex < mapWidth; xIndex += 1) {\n      if (flatRow && xIndex === flatLeft && flatRight > flatLeft) {\n        pixels.fill(FLAT_LENS_PIXEL, yIndex * mapWidth + flatLeft, yIndex * mapWidth + flatRight);\n        xIndex = flatRight - 1;\n\n        continue;\n      }\n\n      const x = ((xIndex + 0.5) / mapWidth) * width;\n      const index = (yIndex * mapWidth + xIndex) * 4;\n      roundedBoxEdge(x, y, width, height, options.radii, edge);\n      const inset = Math.max(-edge.distance, 0);\n      let offset = 0;\n\n      if (inset < bevel) {\n        const position = (inset / bevel) * LENS_PROFILE_STEPS;\n        const lower = Math.floor(position);\n        const fraction = position - lower;\n\n        offset = offsets[lower] * (1 - fraction) + offsets[lower + 1] * fraction;\n      }\n\n      data[index] = Math.round(clamp(0.5 - (offset * edge.normalX) / (2 * reach), 0, 1) * 255);\n      data[index + 1] = Math.round(clamp(0.5 - (offset * edge.normalY) / (2 * reach), 0, 1) * 255);\n      data[index + 2] = Math.round((1 - smoothstep(litFrom, litTo, inset / bevel)) * 255);\n      data[index + 3] = 255;\n    }\n  }\n\n  ctx.putImageData(new ImageData(data, mapWidth, mapHeight), 0, 0);\n\n  const result = {\n    href: canvas.toDataURL('image/png'),\n    metrics: { ...base, reach },\n  };\n\n  lensMapCache.set(base.cacheKey, result);\n\n  if (lensMapCache.size > maxCachedLensMaps) {\n    const oldestKey = lensMapCache.keys().next().value;\n\n    if (oldestKey) lensMapCache.delete(oldestKey);\n  }\n\n  return result;\n}\n\nexport type MagnifierMapOptions = {\n  devicePixelRatio?: number;\n  size: number;\n};\n\nexport type MagnifierMapMetrics = {\n  /** Width of the ring that bends, in CSS pixels. */\n  band: number;\n  cacheKey: string;\n  /** Outward offset at the rim, in CSS pixels. */\n  depth: number;\n  mapSize: number;\n  size: number;\n};\n\nexport type MagnifierMapBuildResult = {\n  href: string;\n  metrics: MagnifierMapMetrics;\n};\n\nconst magnifierMapCache = new Map<string, string>();\n\nconst maxCachedMagnifierMaps = 8;\n\nexport function computeMagnifierMapMetrics(options: MagnifierMapOptions): MagnifierMapMetrics {\n  const size = Math.max(1, options.size);\n  const radius = size / 2;\n  const mapSize = clamp(Math.round(size * clamp(options.devicePixelRatio ?? 1, 1, 2)), 32, 400);\n\n  return {\n    band: radius * 0.46,\n    cacheKey: [mapSize, Math.round(size * 10)].join(':'),\n    depth: radius * 0.5,\n    mapSize,\n    size,\n  };\n}\n\n/**\n * Encodes an outward offset that grows toward the rim of a circle:\n * R/G = 0.5 + 0.5 * offset / depth. Each pixel samples a little further out than its\n * inner neighbour, so the view compresses into the rim like thick glass and never folds\n * back on itself, even over sharp text.\n */\nexport function buildMagnifierMapDataUrl(options: MagnifierMapOptions): MagnifierMapBuildResult {\n  const metrics = computeMagnifierMapMetrics(options);\n  const cached = magnifierMapCache.get(metrics.cacheKey);\n\n  if (cached) return { href: cached, metrics };\n\n  if (typeof document === 'undefined') {\n    throw new Error('Magnifier maps require a browser document');\n  }\n\n  const canvas = document.createElement('canvas');\n  canvas.width = metrics.mapSize;\n  canvas.height = metrics.mapSize;\n\n  const ctx = canvas.getContext('2d');\n\n  if (!ctx) {\n    throw new Error('Canvas 2D context unavailable');\n  }\n\n  const { band, mapSize, size } = metrics;\n  const radius = size / 2;\n  const data = new Uint8ClampedArray(mapSize * mapSize * 4);\n\n  for (let yIndex = 0; yIndex < mapSize; yIndex += 1) {\n    const dy = ((yIndex + 0.5) / mapSize) * size - radius;\n\n    for (let xIndex = 0; xIndex < mapSize; xIndex += 1) {\n      const dx = ((xIndex + 0.5) / mapSize) * size - radius;\n      const index = (yIndex * mapSize + xIndex) * 4;\n      const distance = Math.hypot(dx, dy) || 1;\n      // Flat in the centre, cubic through the ring so the bend starts without a crease.\n      const rim = clamp((distance - (radius - band)) / band, 0, 1) ** 3;\n\n      data[index] = Math.round((0.5 + (0.5 * rim * dx) / distance) * 255);\n      data[index + 1] = Math.round((0.5 + (0.5 * rim * dy) / distance) * 255);\n      data[index + 2] = 128;\n      data[index + 3] = 255;\n    }\n  }\n\n  ctx.putImageData(new ImageData(data, mapSize, mapSize), 0, 0);\n  const href = canvas.toDataURL('image/png');\n  magnifierMapCache.set(metrics.cacheKey, href);\n\n  if (magnifierMapCache.size > maxCachedMagnifierMaps) {\n    const oldestKey = magnifierMapCache.keys().next().value;\n\n    if (oldestKey) magnifierMapCache.delete(oldestKey);\n  }\n\n  return { href, metrics };\n}\n\nexport type CapsuleLensMapOptions = {\n  devicePixelRatio?: number;\n  height: number;\n  /** Multiple of regular glass: a thicker capsule bends further at its rim. */\n  thickness?: number;\n  width: number;\n};\n\ntype CapsuleLensMapMetrics = {\n  /** Width of the band inside the rim that bends, in CSS pixels. */\n  band: number;\n  cacheKey: string;\n  /** Outward offset at the rim, in CSS pixels. */\n  depth: number;\n  height: number;\n  mapHeight: number;\n  mapWidth: number;\n  width: number;\n};\n\nexport type CapsuleLensMapBuildResult = {\n  href: string;\n  metrics: CapsuleLensMapMetrics;\n};\n\n// The lens itself shows its scene evenly, a little smaller; only a thin band at the rim bends.\nconst CAPSULE_BAND = 0.3;\n\nconst CAPSULE_DEPTH = 0.25;\n\nconst capsuleLensMapCache = new Map<string, string>();\n\nconst maxCachedCapsuleLensMaps = 8;\n\nfunction computeCapsuleLensMapMetrics(options: CapsuleLensMapOptions): CapsuleLensMapMetrics {\n  const width = Math.max(1, options.width);\n  const height = Math.max(1, options.height);\n  const radius = Math.min(width, height) / 2;\n  const thickness = clamp(options.thickness ?? 1, 0.1, 4);\n  // The map is drawn at twice the device scale, so the bend stays smooth on a small knob.\n  const scale = clamp(options.devicePixelRatio ?? 1, 1, 2) * 2;\n  const mapWidth = clamp(Math.round(width * scale), 32, 400);\n  const mapHeight = clamp(Math.round(height * scale), 32, 400);\n  const band = radius * CAPSULE_BAND;\n  const depth = radius * CAPSULE_DEPTH * thickness;\n\n  return {\n    band,\n    cacheKey: [mapWidth, mapHeight, Math.round(width * 10), Math.round(height * 10)].join(':'),\n    depth,\n    height,\n    mapHeight,\n    mapWidth,\n    width,\n  };\n}\n\n/**\n * The rim's field for a capsule lens, such as a switch knob: R/G = 0.5 + 0.5 * the outward\n * offset as a share of `depth`, along the outward normal of the nearest rim. It is flat in\n * the middle and grows cubically through a thin band, so each pixel there samples a little\n * further out than its inner neighbour: the view compresses into the rim like thick glass\n * and never folds back on itself. The ends and the straight sides meet without a crease.\n * B rises through the band, so the filter softens only the scene the rim bends and the\n * middle stays sharp.\n */\nexport function buildCapsuleLensMapDataUrl(\n  options: CapsuleLensMapOptions,\n): CapsuleLensMapBuildResult {\n  const metrics = computeCapsuleLensMapMetrics(options);\n  const cached = capsuleLensMapCache.get(metrics.cacheKey);\n\n  if (cached) return { href: cached, metrics };\n\n  if (typeof document === 'undefined') {\n    throw new Error('Lens maps require a browser document');\n  }\n\n  const canvas = document.createElement('canvas');\n  canvas.width = metrics.mapWidth;\n  canvas.height = metrics.mapHeight;\n\n  const ctx = canvas.getContext('2d');\n\n  if (!ctx) {\n    throw new Error('Canvas 2D context unavailable');\n  }\n\n  const { band, height, mapHeight, mapWidth, width } = metrics;\n  const radius = Math.min(width, height) / 2;\n  const radii: LensRadii = [radius, radius, radius, radius];\n  const data = new Uint8ClampedArray(mapWidth * mapHeight * 4);\n  const edge: Edge = { distance: 0, normalX: 0, normalY: 0 };\n\n  for (let yIndex = 0; yIndex < mapHeight; yIndex += 1) {\n    const y = ((yIndex + 0.5) / mapHeight) * height;\n\n    for (let xIndex = 0; xIndex < mapWidth; xIndex += 1) {\n      const x = ((xIndex + 0.5) / mapWidth) * width;\n      const index = (yIndex * mapWidth + xIndex) * 4;\n      roundedBoxEdge(x, y, width, height, radii, edge);\n      const inBand = clamp((band + edge.distance) / band, 0, 1);\n      const rim = inBand ** 3;\n\n      data[index] = Math.round((0.5 + 0.5 * rim * edge.normalX) * 255);\n      data[index + 1] = Math.round((0.5 + 0.5 * rim * edge.normalY) * 255);\n      data[index + 2] = Math.round(inBand * 255);\n      data[index + 3] = 255;\n    }\n  }\n\n  ctx.putImageData(new ImageData(data, mapWidth, mapHeight), 0, 0);\n  const href = canvas.toDataURL('image/png');\n  capsuleLensMapCache.set(metrics.cacheKey, href);\n\n  if (capsuleLensMapCache.size > maxCachedCapsuleLensMaps) {\n    const oldestKey = capsuleLensMapCache.keys().next().value;\n\n    if (oldestKey) capsuleLensMapCache.delete(oldestKey);\n  }\n\n  return { href, metrics };\n}\n",
      "type": "registry:lib",
      "target": "components/glassyui/lib/refraction-map.ts"
    },
    {
      "path": "registry/glassyui/lib/slab-optics.ts",
      "content": "// The glass floats this far above its backdrop, in CSS pixels.\nexport const SLAB_AIR_GAP = 8;\n\n// Fractions of full slab thickness at the rim and added across its curved top.\nexport const SLAB_MIN_RISE = 0.3;\n\nexport const SLAB_RISE_SPAN = 0.7;\n\nexport const SLAB_MAX_SLOPE = 12;\n",
      "type": "registry:lib",
      "target": "components/glassyui/lib/slab-optics.ts"
    },
    {
      "path": "registry/glassyui/lib/use-refraction-filter.tsx",
      "content": "'use client';\n\nimport { useCallback, useEffect, useId, useMemo, useRef, useState, type RefObject } from 'react';\nimport {\n  buildCapsuleLensMapDataUrl,\n  buildLensMapDataUrl,\n  buildMagnifierMapDataUrl,\n  buildRefractionMapDataUrl,\n  clamp,\n  computeMagnifierMapMetrics,\n  MAX_LENS_SURFACE_AREA,\n  type CapsuleLensMapBuildResult,\n  type GeneratedRefractionStrength,\n  type LensMapMetrics,\n  type LensRadii,\n  type MagnifierMapBuildResult,\n  type RefractionMapMetrics,\n} from './refraction-map';\n\ntype RefractionFilterOptions = {\n  displacement?: number;\n  enabled: boolean;\n  reduceTransparency?: boolean;\n  strength: GeneratedRefractionStrength;\n  thickness?: number;\n  viewportAligned?: boolean;\n};\n\ntype RefractionFilterState = {\n  href: string | null;\n  metrics: RefractionMapMetrics | null;\n};\n\nfunction isProductionRuntime() {\n  // SAFETY: only Node and bundler shims define `process`, so every step of the probe stays optional.\n  const runtime = globalThis as typeof globalThis & {\n    process?: { env?: { NODE_ENV?: string } };\n  };\n\n  return runtime.process?.env?.NODE_ENV === 'production';\n}\n\nfunction parseRadiusValue(value: string, width: number, height: number) {\n  const [first] = value.trim().split(/\\s+/);\n  const maxRadius = Math.min(width, height) / 2;\n\n  const parsed = Number.parseFloat(first);\n\n  if (first.endsWith('%')) {\n    return clamp((parsed / 100) * Math.min(width, height), 0, maxRadius);\n  }\n\n  return clamp(Number.isFinite(parsed) ? parsed : maxRadius, 0, maxRadius);\n}\n\nfunction readUniformRadius(el: HTMLElement, width: number, height: number) {\n  const style = window.getComputedStyle(el);\n\n  const rawRadii = [\n    style.borderTopLeftRadius,\n    style.borderTopRightRadius,\n    style.borderBottomRightRadius,\n    style.borderBottomLeftRadius,\n  ];\n\n  const radii = rawRadii.map((value) => parseRadiusValue(value, width, height));\n  const first = radii[0];\n  const mixed = radii.some((radius) => Math.abs(radius - first) > 0.5);\n\n  return mixed ? null : first;\n}\n\nfunction readCornerRadii(style: CSSStyleDeclaration, width: number, height: number): LensRadii {\n  return [\n    parseRadiusValue(style.borderTopLeftRadius, width, height),\n    parseRadiusValue(style.borderTopRightRadius, width, height),\n    parseRadiusValue(style.borderBottomRightRadius, width, height),\n    parseRadiusValue(style.borderBottomLeftRadius, width, height),\n  ];\n}\n\n/**\n * A scroll event reaches script a frame after the compositor has scrolled, so a scene moved from\n * script trails the page. Chromium filters a composited layer on its compositor, which lets a\n * scroll-driven animation carry the scene in step with the scroll and still bend it. WebKit leaves\n * a scene on its own compositing layer out of the SVG filter and Gecko has no scroll timelines, so\n * both keep moving the scene from script. Only Chromium has userAgentData.\n */\nfunction supportsCompositedSceneScroll() {\n  return (\n    typeof ViewTimeline !== 'undefined' &&\n    typeof navigator !== 'undefined' &&\n    'userAgentData' in navigator\n  );\n}\n\n// Across the timeline the scene moves down exactly as far as the scroll carries the surface up.\nconst sceneScrollKeyframes = (span: number): Keyframe[] => [\n  { translate: '0px 0px' },\n  { translate: `0px ${span}px` },\n];\n\n/**\n * A view timeline places its subject where it would sit if nothing were fixed or stuck, so it runs\n * on while such a surface stands still. Those surfaces keep following the scroll from script.\n */\nfunction standsStillWhileScrolling(el: Element, source: Element) {\n  for (let node: Element | null = el; node && node !== source; node = node.parentElement) {\n    const { position } = window.getComputedStyle(node);\n\n    if (position === 'fixed' || position === 'sticky') {\n      return true;\n    }\n  }\n\n  return false;\n}\n\nexport function useRefractionFilter(\n  surfaceRef: RefObject<HTMLElement | null>,\n  {\n    displacement,\n    enabled,\n    reduceTransparency = false,\n    strength,\n    thickness,\n    viewportAligned = false,\n  }: RefractionFilterOptions,\n) {\n  const rawId = useId().replaceAll(':', '');\n  const filterId = `lg-refraction-${rawId}`;\n  const generationRef = useRef(0);\n  const warnedMixedRadiusRef = useRef(false);\n  const [state, setState] = useState<RefractionFilterState>({ href: null, metrics: null });\n  const sceneRef = useRef<HTMLDivElement | null>(null);\n  // Set while the scene is kept aligned, so a scene that mounts is aligned before it first paints.\n  const alignSceneNowRef = useRef<(() => void) | null>(null);\n\n  const setScene = useCallback((node: HTMLDivElement | null) => {\n    sceneRef.current = node;\n    alignSceneNowRef.current?.();\n  }, []);\n\n  useEffect(() => {\n    if (!enabled || reduceTransparency || !viewportAligned) {\n      return;\n    }\n\n    const el = surfaceRef.current;\n\n    if (!el) {\n      return;\n    }\n\n    let alignmentFrame = 0;\n    let disposed = false;\n    // Aligning a scene that no one can see only costs a layout, a style pass and a repaint on\n    // every scroll frame, so it waits until the surface is within a quarter screen of the viewport.\n    let nearViewport = true;\n\n    const timeline = supportsCompositedSceneScroll()\n      ? new ViewTimeline({ axis: 'block', subject: el })\n      : null;\n\n    let sceneScroll: Animation | null = null;\n    let sceneScrollSpan = Number.NaN;\n\n    // Keeps the scene's scroll-driven animation spanning the timeline and returns how far along\n    // the block axis it has carried the scene, which the offset below then leaves out. Past\n    // either end of the timeline the animation holds still, but the unclamped distance keeps the\n    // offset constant, so plain scrolling rewrites nothing and the scene never waits on script.\n    const followScroll = () => {\n      const scene = sceneRef.current;\n      const source = timeline?.source ?? null;\n\n      if (\n        !timeline ||\n        !scene ||\n        !source ||\n        timeline.currentTime === null ||\n        standsStillWhileScrolling(el, source)\n      ) {\n        sceneScroll?.cancel();\n        sceneScroll = null;\n\n        return 0;\n      }\n\n      const start = timeline.startOffset.to('px').value;\n      const span = timeline.endOffset.to('px').value - start;\n\n      if (sceneScroll?.effect instanceof KeyframeEffect && sceneScroll.effect.target === scene) {\n        if (span !== sceneScrollSpan) {\n          sceneScroll.effect.setKeyframes(sceneScrollKeyframes(span));\n        }\n      } else {\n        sceneScroll?.cancel();\n        sceneScroll = scene.animate(sceneScrollKeyframes(span), { fill: 'both', timeline });\n      }\n\n      sceneScrollSpan = span;\n\n      return source.scrollTop - start;\n    };\n\n    const writeProperty = (property: string, value: string) => {\n      if (el.style.getPropertyValue(property) !== value) {\n        el.style.setProperty(property, value);\n      }\n    };\n\n    const alignScene = () => {\n      alignmentFrame = 0;\n\n      if (disposed) {\n        return;\n      }\n\n      const followed = followScroll();\n      const rect = el.getBoundingClientRect();\n      writeProperty('--lg-refraction-scene-x', `${-(rect.left + el.clientLeft)}px`);\n      writeProperty('--lg-refraction-scene-y', `${-(rect.top + el.clientTop) - followed}px`);\n      writeProperty('--lg-refraction-scene-width', `${document.documentElement.clientWidth}px`);\n      writeProperty('--lg-refraction-scene-height', `${document.documentElement.clientHeight}px`);\n    };\n\n    const scheduleAlignment = () => {\n      if (nearViewport && !alignmentFrame) {\n        alignmentFrame = requestAnimationFrame(alignScene);\n      }\n    };\n\n    alignSceneNowRef.current = () => {\n      cancelAnimationFrame(alignmentFrame);\n      alignScene();\n    };\n\n    const visibilityObserver =\n      typeof IntersectionObserver === 'undefined'\n        ? null\n        : new IntersectionObserver(\n            (entries) => {\n              const wasNear = nearViewport;\n              nearViewport = entries[entries.length - 1]?.isIntersecting ?? true;\n\n              // Coming into range aligns at once, in this task. A frame asked for from here would run\n              // after whatever the page queued for the next frame, and that could read the scene\n              // where it still was.\n              if (nearViewport && !wasNear) {\n                cancelAnimationFrame(alignmentFrame);\n                alignScene();\n              }\n            },\n            { rootMargin: '25% 0px' },\n          );\n\n    visibilityObserver?.observe(el);\n\n    const resizeObserver =\n      typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(scheduleAlignment);\n\n    for (let ancestor: HTMLElement | null = el; ancestor; ancestor = ancestor.parentElement) {\n      resizeObserver?.observe(ancestor);\n    }\n\n    const readExternalStyleSignature = () => {\n      const declarations: string[] = [];\n\n      for (let index = 0; index < el.style.length; index += 1) {\n        const property = el.style.item(index);\n\n        if (property.startsWith('--lg-refraction-scene-')) {\n          continue;\n        }\n\n        declarations.push(\n          `${property}:${el.style.getPropertyValue(property)}:${el.style.getPropertyPriority(property)}`,\n        );\n      }\n\n      return declarations.sort().join(';');\n    };\n\n    let externalStyleSignature = readExternalStyleSignature();\n\n    const mutationObserver =\n      typeof MutationObserver === 'undefined'\n        ? null\n        : new MutationObserver((records) => {\n            const hasExternalMutation = records.some((record) => {\n              if (\n                record.type === 'attributes' &&\n                record.target === el &&\n                record.attributeName === 'style'\n              ) {\n                const nextExternalStyleSignature = readExternalStyleSignature();\n\n                if (nextExternalStyleSignature === externalStyleSignature) {\n                  return false;\n                }\n\n                externalStyleSignature = nextExternalStyleSignature;\n              }\n\n              return true;\n            });\n\n            if (hasExternalMutation) {\n              scheduleAlignment();\n            }\n          });\n\n    mutationObserver?.observe(document.body, {\n      attributeFilter: ['class', 'hidden', 'open', 'style'],\n      attributes: true,\n      characterData: true,\n      childList: true,\n      subtree: true,\n    });\n    document.addEventListener('scroll', scheduleAlignment, {\n      capture: true,\n      passive: true,\n    });\n    document.addEventListener('load', scheduleAlignment, {\n      capture: true,\n      passive: true,\n    });\n    document.fonts?.addEventListener('loadingdone', scheduleAlignment);\n    window.addEventListener('resize', scheduleAlignment, { passive: true });\n    window.visualViewport?.addEventListener('resize', scheduleAlignment, { passive: true });\n    window.visualViewport?.addEventListener('scroll', scheduleAlignment, { passive: true });\n    scheduleAlignment();\n\n    return () => {\n      disposed = true;\n      alignSceneNowRef.current = null;\n      cancelAnimationFrame(alignmentFrame);\n      sceneScroll?.cancel();\n      resizeObserver?.disconnect();\n      mutationObserver?.disconnect();\n      visibilityObserver?.disconnect();\n      document.removeEventListener('scroll', scheduleAlignment, { capture: true });\n      document.removeEventListener('load', scheduleAlignment, { capture: true });\n      document.fonts?.removeEventListener('loadingdone', scheduleAlignment);\n      window.removeEventListener('resize', scheduleAlignment);\n      window.visualViewport?.removeEventListener('resize', scheduleAlignment);\n      window.visualViewport?.removeEventListener('scroll', scheduleAlignment);\n      el.style.removeProperty('--lg-refraction-scene-height');\n      el.style.removeProperty('--lg-refraction-scene-width');\n      el.style.removeProperty('--lg-refraction-scene-x');\n      el.style.removeProperty('--lg-refraction-scene-y');\n    };\n  }, [enabled, reduceTransparency, surfaceRef, viewportAligned]);\n\n  useEffect(() => {\n    generationRef.current += 1;\n    const generation = generationRef.current;\n\n    if (!enabled || reduceTransparency || typeof ResizeObserver === 'undefined') {\n      queueMicrotask(() => {\n        if (generationRef.current === generation) {\n          setState({ href: null, metrics: null });\n        }\n      });\n\n      return;\n    }\n\n    const el = surfaceRef.current;\n\n    if (!el) {\n      queueMicrotask(() => {\n        if (generationRef.current === generation) {\n          setState({ href: null, metrics: null });\n        }\n      });\n\n      return;\n    }\n\n    let raf = 0;\n    let disposed = false;\n\n    const clear = () => {\n      if (generationRef.current === generation) {\n        setState({ href: null, metrics: null });\n      }\n    };\n\n    const schedule = () => {\n      cancelAnimationFrame(raf);\n      raf = requestAnimationFrame(() => {\n        const rect = el.getBoundingClientRect();\n        const width = Math.max(0, rect.width);\n        const height = Math.max(0, rect.height);\n\n        if (!width || !height) {\n          clear();\n\n          return;\n        }\n\n        const radius = readUniformRadius(el, width, height);\n\n        if (radius === null) {\n          if (!isProductionRuntime() && !warnedMixedRadiusRef.current) {\n            console.warn(\n              'Glassy UI supplied-background refraction currently supports uniform rounded rectangles only.',\n            );\n            warnedMixedRadiusRef.current = true;\n          }\n\n          clear();\n\n          return;\n        }\n\n        void buildRefractionMapDataUrl({\n          devicePixelRatio: window.devicePixelRatio || 1,\n          displacement,\n          height,\n          radius,\n          strength,\n          thickness,\n          width,\n        })\n          .then((result) => {\n            if (!disposed && generationRef.current === generation) {\n              setState({ href: result.href, metrics: result.metrics });\n            }\n          })\n          .catch(() => {\n            if (!disposed) {\n              clear();\n            }\n          });\n      });\n    };\n\n    const observer = new ResizeObserver(schedule);\n    observer.observe(el);\n    schedule();\n\n    return () => {\n      disposed = true;\n      cancelAnimationFrame(raf);\n      observer.disconnect();\n    };\n  }, [displacement, enabled, reduceTransparency, strength, surfaceRef, thickness]);\n\n  const filterElement = useMemo(() => {\n    if (!state.href || !state.metrics) return null;\n\n    const {\n      dispersion,\n      filterBlur,\n      filterPadding,\n      filterScale,\n      height,\n      paddedHeight,\n      paddedWidth,\n      width,\n    } = state.metrics;\n\n    // Every colour follows the same two-axis rim normal, so the sides split as much as the ends.\n    const channel = (name: string, matrix: string, factor: number) => (\n      <>\n        <feDisplacementMap\n          in=\"scene\"\n          in2=\"map\"\n          scale={Math.round(filterScale * factor * 100) / 100}\n          xChannelSelector=\"R\"\n          yChannelSelector=\"G\"\n          result={`${name}-scene`}\n        />\n        <feColorMatrix in={`${name}-scene`} type=\"matrix\" values={matrix} result={`${name}-bent`} />\n      </>\n    );\n\n    return (\n      <svg aria-hidden=\"true\" className=\"lg-refraction-filter\" focusable=\"false\" viewBox=\"0 0 0 0\">\n        <defs>\n          <filter\n            id={filterId}\n            x={-filterPadding}\n            y={-filterPadding}\n            width={paddedWidth}\n            height={paddedHeight}\n            filterUnits=\"userSpaceOnUse\"\n            primitiveUnits=\"userSpaceOnUse\"\n            colorInterpolationFilters=\"sRGB\"\n          >\n            <feGaussianBlur in=\"SourceGraphic\" stdDeviation={filterBlur} result=\"blurred\" />\n            <feImage\n              href={state.href}\n              x={-filterPadding}\n              y={-filterPadding}\n              width={width + filterPadding * 2}\n              height={height + filterPadding * 2}\n              preserveAspectRatio=\"none\"\n              result=\"map\"\n            />\n            {/* The map's blue channel softens only the scene the rim magnifies. */}\n            <feColorMatrix\n              in=\"map\"\n              type=\"matrix\"\n              values=\"0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 1 0 0\"\n              result=\"rim\"\n            />\n            <feComposite in=\"blurred\" in2=\"rim\" operator=\"in\" result=\"softRim\" />\n            <feComposite in=\"softRim\" in2=\"SourceGraphic\" operator=\"over\" result=\"scene\" />\n            {dispersion > 0 ? (\n              <>\n                {channel('red', '1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1', 1 - dispersion / 2)}\n                {channel('green', '0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1', 1)}\n                {channel('blue', '0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1', 1 + dispersion / 2)}\n                <feBlend in=\"red-bent\" in2=\"green-bent\" mode=\"screen\" result=\"red-green\" />\n                <feBlend in=\"red-green\" in2=\"blue-bent\" mode=\"screen\" result=\"rgb\" />\n                {/* Combine opaque colour, then restore coverage once so translucent scenes stay translucent. */}\n                <feComposite in=\"rgb\" in2=\"green-scene\" operator=\"in\" />\n              </>\n            ) : (\n              <feDisplacementMap\n                in=\"scene\"\n                in2=\"map\"\n                scale={filterScale}\n                xChannelSelector=\"R\"\n                yChannelSelector=\"G\"\n              />\n            )}\n          </filter>\n        </defs>\n      </svg>\n    );\n  }, [filterId, state.href, state.metrics]);\n\n  return {\n    active: Boolean(state.href && state.metrics),\n    filterElement,\n    filterStyle: state.href ? `url(#${filterId})` : undefined,\n    sceneRef: setScene,\n  };\n}\n\ntype LensFilterOptions = {\n  enabled: boolean;\n  /** Changes whenever theme, mode, quality or variant tokens may have changed. */\n  signature?: string;\n};\n\ntype LensFilterState = {\n  blur: number;\n  bodyBrightness: number;\n  dispersion: number;\n  href: string;\n  metrics: LensMapMetrics;\n  rimBrightness: number;\n  saturation: number;\n};\n\n/**\n * Only Chromium renders SVG references inside backdrop-filter. WebKit and\n * Gecko drop the whole declaration when url() is present, and CSS.supports()\n * reports true everywhere, so the engine is detected explicitly.\n */\nfunction supportsBackdropLens() {\n  return (\n    typeof navigator !== 'undefined' &&\n    'userAgentData' in navigator &&\n    typeof ResizeObserver !== 'undefined'\n  );\n}\n\nfunction readNumberToken(style: CSSStyleDeclaration, name: string) {\n  const value = Number.parseFloat(style.getPropertyValue(name));\n\n  return Number.isFinite(value) ? value : 0;\n}\n\nfunction readTokenOr(style: CSSStyleDeclaration, name: string, fallback: number) {\n  const value = Number.parseFloat(style.getPropertyValue(name));\n\n  return Number.isFinite(value) ? value : fallback;\n}\n\nfunction sameLens(previous: LensFilterState | null, next: LensFilterState) {\n  return (\n    previous !== null &&\n    previous.href === next.href &&\n    previous.blur === next.blur &&\n    previous.bodyBrightness === next.bodyBrightness &&\n    previous.dispersion === next.dispersion &&\n    previous.rimBrightness === next.rimBrightness &&\n    previous.saturation === next.saturation\n  );\n}\n\n// A rim as wide as the corners are round, up to a little wider than the WebGL scene's default.\nconst LENS_BEVEL = 36;\n\n// Slab height per pixel of rim, as in the scene (40 px of glass under a 28 px rim).\nconst LENS_THICKNESS_RATIO = 1.4;\n\n// The least frost the lens reads through, so bent edges never stair-step.\nconst MIN_FROST = 0.5;\n\n// Each colour follows the same rim normal: red bends least and blue most.\n// Both live-backdrop glass and the magnifier use this material pass.\nfunction refractColours(source: string, map: string, scale: number, dispersion: number) {\n  if (dispersion <= 0.005) {\n    return (\n      <feDisplacementMap\n        in={source}\n        in2={map}\n        scale={scale}\n        xChannelSelector=\"R\"\n        yChannelSelector=\"G\"\n        result=\"bent\"\n      />\n    );\n  }\n\n  const channel = (name: string, matrix: string, factor: number) => (\n    <>\n      <feDisplacementMap\n        in={source}\n        in2={map}\n        scale={Math.round(scale * factor * 100) / 100}\n        xChannelSelector=\"R\"\n        yChannelSelector=\"G\"\n        result={`${name}-scene`}\n      />\n      <feColorMatrix in={`${name}-scene`} type=\"matrix\" values={matrix} result={`${name}-bent`} />\n    </>\n  );\n\n  return (\n    <>\n      {channel('red', '1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1', 1 - dispersion / 2)}\n      {channel('green', '0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1', 1)}\n      {channel('blue', '0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1', 1 + dispersion / 2)}\n      <feBlend in=\"red-bent\" in2=\"green-bent\" mode=\"screen\" result=\"red-green\" />\n      <feBlend in=\"red-green\" in2=\"blue-bent\" mode=\"screen\" result=\"rgb\" />\n      {/* Combine opaque colour, then restore the reference channel's coverage once. */}\n      <feComposite in=\"rgb\" in2=\"green-scene\" operator=\"in\" result=\"bent\" />\n    </>\n  );\n}\n\n/**\n * Chromium-only lens for glass over live content. The backdrop is frosted, then read\n * through a slab of glass whose top curves down into a rounded rim, so content bends\n * and splits into colour along the edge and lies flat everywhere else. The\n * --lg-lens-* tokens shape it: depth, bevel, thickness, ior, dispersion, blur and\n * saturation, and --lg-glass-thickness scales the whole slab at once. Other engines,\n * zero depth and oversized surfaces keep the CSS glass.\n */\nexport function useLensFilter(\n  surfaceRef: RefObject<HTMLElement | null>,\n  { enabled, signature }: LensFilterOptions,\n) {\n  const rawId = useId().replaceAll(':', '');\n  const filterId = `lg-lens-${rawId}`;\n  const generationRef = useRef(0);\n  const [state, setState] = useState<LensFilterState | null>(null);\n\n  useEffect(() => {\n    generationRef.current += 1;\n    const generation = generationRef.current;\n    const el = surfaceRef.current;\n\n    if (!enabled || !el || !supportsBackdropLens()) {\n      queueMicrotask(() => {\n        if (generationRef.current === generation) {\n          setState(null);\n        }\n      });\n\n      return;\n    }\n\n    let frame = 0;\n    let disposed = false;\n\n    const measure = () => {\n      frame = 0;\n\n      if (disposed || generationRef.current !== generation) {\n        return;\n      }\n\n      // The lens layer fills the padding box, so borders and scrollbars stay out of the map.\n      const width = el.clientWidth;\n      const height = el.clientHeight;\n      const style = window.getComputedStyle(el);\n      const depth = readNumberToken(style, '--lg-lens-depth');\n\n      if (depth <= 0 || !width || !height || width * height > MAX_LENS_SURFACE_AREA) {\n        setState(null);\n\n        return;\n      }\n\n      const radii = readCornerRadii(style, width, height);\n      const roundest = Math.max(...radii);\n      const multiplier = clamp(readTokenOr(style, '--lg-glass-thickness', 1), 0.1, 4);\n      const bevelToken = readNumberToken(style, '--lg-lens-bevel');\n      const thicknessToken = readNumberToken(style, '--lg-lens-thickness');\n      const baseBevel = bevelToken > 0 ? bevelToken : clamp(roundest, 6, LENS_BEVEL);\n      // A thicker slab also has a wider rim, though not in proportion.\n      const bevel = clamp(baseBevel * (0.6 + 0.4 * multiplier), 4, Math.min(width, height) / 2);\n\n      const thickness =\n        (thicknessToken > 0 ? thicknessToken : baseBevel * LENS_THICKNESS_RATIO) * multiplier;\n\n      const { href, metrics } = buildLensMapDataUrl({\n        bevel,\n        depth,\n        devicePixelRatio: window.devicePixelRatio || 1,\n        height,\n        ior: Math.max(1, readTokenOr(style, '--lg-lens-ior', 1.5)),\n        radii,\n        thickness,\n        width,\n      });\n\n      const next = {\n        blur: Math.max(0, readNumberToken(style, '--lg-lens-blur')),\n        bodyBrightness: clamp(readTokenOr(style, '--lg-lens-body-brightness', 1), 0, 1),\n        dispersion: clamp(readNumberToken(style, '--lg-lens-dispersion') * multiplier, 0, 1),\n        href,\n        metrics,\n        rimBrightness: clamp(readTokenOr(style, '--lg-lens-rim-brightness', 1), 0, 1),\n        saturation: readNumberToken(style, '--lg-lens-saturation') || 1,\n      };\n\n      setState((previous) => (sameLens(previous, next) ? previous : next));\n    };\n\n    const schedule = () => {\n      if (!frame) {\n        frame = requestAnimationFrame(measure);\n      }\n    };\n\n    const observer = new ResizeObserver(schedule);\n    observer.observe(el);\n    schedule();\n\n    return () => {\n      disposed = true;\n      cancelAnimationFrame(frame);\n      observer.disconnect();\n    };\n  }, [enabled, signature, surfaceRef]);\n\n  const filterElement = useMemo(() => {\n    if (!state) return null;\n\n    const { blur, bodyBrightness, dispersion, href, metrics, rimBrightness, saturation } = state;\n    // The rim is the same frosted glass as the flat top: it bends and splits what the frost\n    // leaves and is never clearer, so content does not show through a sharp band at the edge.\n    const frost = Math.max(blur, MIN_FROST);\n    const padding = Math.ceil(frost * 3) + 2;\n    // Map channels hold a unit offset; the scale turns it into CSS pixels.\n    const scale = Math.round(2 * metrics.reach * 100) / 100;\n\n    // Smoked glass darkens the flat top more than its rim, which lets the light through. A\n    // primitive is added only where it changes something: each one is another pass on the GPU.\n    const dim = (input: string, brightness: number, result: string) =>\n      brightness < 1 ? (\n        <feComponentTransfer in={input} result={result}>\n          <feFuncR type=\"linear\" slope={brightness} />\n          <feFuncG type=\"linear\" slope={brightness} />\n          <feFuncB type=\"linear\" slope={brightness} />\n        </feComponentTransfer>\n      ) : null;\n\n    // The map's blue channel weights the rim's light over the top's. Where both let the same\n    // light through, the bent frost alone is the glass.\n    const shaded = rimBrightness !== bodyBrightness;\n    const rimSource = rimBrightness < 1 ? 'rim-lit' : 'bent';\n    const topSource = bodyBrightness < 1 ? 'top-lit' : 'bent';\n    const glass = shaded ? 'mixed' : topSource;\n\n    return (\n      <svg aria-hidden=\"true\" className=\"lg-refraction-filter\" focusable=\"false\" viewBox=\"0 0 0 0\">\n        <defs>\n          <filter\n            id={filterId}\n            x={-padding}\n            y={-padding}\n            width={metrics.width + padding * 2}\n            height={metrics.height + padding * 2}\n            filterUnits=\"userSpaceOnUse\"\n            primitiveUnits=\"userSpaceOnUse\"\n            colorInterpolationFilters=\"sRGB\"\n          >\n            <feGaussianBlur in=\"SourceGraphic\" stdDeviation={frost} result=\"frost\" />\n            <feImage\n              href={href}\n              x={0}\n              y={0}\n              width={metrics.width}\n              height={metrics.height}\n              preserveAspectRatio=\"none\"\n              result=\"lens\"\n            />\n            {refractColours('frost', 'lens', scale, dispersion)}\n            {shaded ? (\n              <>\n                <feColorMatrix\n                  in=\"lens\"\n                  type=\"matrix\"\n                  values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0\"\n                  result=\"rim\"\n                />\n                {dim('bent', rimBrightness, 'rim-lit')}\n                {dim('bent', bodyBrightness, 'top-lit')}\n                <feComposite in={rimSource} in2=\"rim\" operator=\"in\" result=\"rim-glass\" />\n                {/* The rim, weighted by its mask, over the top, which is opaque: the mask's\n                    complement is implied, so the top needs no mask of its own. */}\n                <feComposite in=\"rim-glass\" in2={topSource} operator=\"over\" result=\"mixed\" />\n              </>\n            ) : (\n              dim('bent', bodyBrightness, 'top-lit')\n            )}\n            {saturation === 1 ? null : (\n              <feColorMatrix in={glass} type=\"saturate\" values={String(saturation)} />\n            )}\n          </filter>\n        </defs>\n      </svg>\n    );\n  }, [filterId, state]);\n\n  return {\n    active: state !== null,\n    filterElement,\n    filterStyle: state ? `url(#${filterId})` : undefined,\n  };\n}\n\ntype MagnifierFilterOptions = LensFilterOptions & {\n  /** Diameter of the round lens in CSS pixels. */\n  size: number;\n};\n\n// Softens the compressed rim just enough to keep sharp edges from stair-stepping.\nconst MAGNIFIER_BLUR = 0.35;\n\n/**\n * Rim refraction for the round magnifier, applied with `filter` to its zoomed view, which\n * every engine with SVG filters on HTML supports. Near the rim each pixel samples content\n * from further out, so the view bends into the edge like a glass bead.\n *\n * The view extends `margin` past the lens on every side so the rim has content to sample.\n * WebKit only lines the filtered view up with the map when the view clips its own overflow\n * and the filter region reaches past it by as far as the primitives can read, so the\n * region is the view plus another margin and the map sits one margin in.\n */\nexport function useMagnifierFilter(\n  surfaceRef: RefObject<HTMLElement | null>,\n  { enabled, signature, size }: MagnifierFilterOptions,\n) {\n  const rawId = useId().replaceAll(':', '');\n  const filterId = `lg-magnifier-${rawId}`;\n  const [map, setMap] = useState<(MagnifierMapBuildResult & { dispersion: number }) | null>(null);\n\n  // Blue reaches furthest; leave enough scene beyond the rim for it and the blur.\n  const margin =\n    Math.ceil(\n      computeMagnifierMapMetrics({ size }).depth * (1 + (map?.dispersion ?? 0) / 2) +\n        MAGNIFIER_BLUR * 3,\n    ) + 2;\n\n  useEffect(() => {\n    let disposed = false;\n\n    // The map is drawn on a canvas, so it can only be built in the browser.\n    queueMicrotask(() => {\n      if (disposed) return;\n\n      const surface = surfaceRef.current;\n\n      if (!enabled || !surface) {\n        setMap(null);\n\n        return;\n      }\n\n      const style = window.getComputedStyle(surface);\n      const thickness = clamp(readTokenOr(style, '--lg-glass-thickness', 1), 0.1, 4);\n      setMap({\n        ...buildMagnifierMapDataUrl({ devicePixelRatio: window.devicePixelRatio || 1, size }),\n        dispersion: clamp(readNumberToken(style, '--lg-lens-dispersion') * thickness, 0, 1),\n      });\n    });\n\n    return () => {\n      disposed = true;\n    };\n  }, [enabled, signature, size, surfaceRef]);\n\n  const filterElement = useMemo(() => {\n    if (!map) return null;\n\n    const {\n      dispersion,\n      metrics: { depth, size: mapCssSize },\n    } = map;\n\n    return (\n      <svg aria-hidden=\"true\" className=\"lg-refraction-filter\" focusable=\"false\" viewBox=\"0 0 0 0\">\n        <defs>\n          <filter\n            id={filterId}\n            x={-margin}\n            y={-margin}\n            width={mapCssSize + margin * 4}\n            height={mapCssSize + margin * 4}\n            filterUnits=\"userSpaceOnUse\"\n            primitiveUnits=\"userSpaceOnUse\"\n            colorInterpolationFilters=\"sRGB\"\n          >\n            <feGaussianBlur in=\"SourceGraphic\" stdDeviation={MAGNIFIER_BLUR} result=\"soft\" />\n            <feImage\n              href={map.href}\n              x={margin}\n              y={margin}\n              width={mapCssSize}\n              height={mapCssSize}\n              preserveAspectRatio=\"none\"\n              result=\"bend\"\n            />\n            {refractColours('soft', 'bend', depth * 2, dispersion)}\n          </filter>\n        </defs>\n      </svg>\n    );\n  }, [filterId, map, margin]);\n\n  return {\n    active: map !== null,\n    filterElement,\n    filterStyle: map ? `url(#${filterId})` : undefined,\n    margin,\n  };\n}\n\ntype CapsuleLensFilterOptions = LensFilterOptions & {\n  /** Colour split at the rim for regular glass; --lg-glass-thickness scales it. */\n  dispersion: number;\n  /**\n   * How many times the capsule's size the filtered copy is laid out at before it is scaled\n   * back down. WebKit filters at layout resolution, so a small lens bends in steps without it.\n   */\n  supersample?: number;\n};\n\ntype CapsuleLensState = CapsuleLensMapBuildResult & { dispersion: number };\n\n/**\n * Rim refraction for a capsule lens, such as a switch knob, applied with `filter` to a copy\n * of what lies under it. Every engine with SVG filters on HTML runs it. Near the rim each\n * pixel samples the copy from further out, so it bends into the edge like a bead of glass\n * and splits into colour there; --lg-glass-thickness deepens both. The copy must reach\n * `margin` past the capsule on every side so the rim has content to sample, and the filter\n * region reaches one margin further, as the round magnifier's does.\n */\nexport function useCapsuleLensFilter(\n  surfaceRef: RefObject<HTMLElement | null>,\n  { dispersion, enabled, signature, supersample = 1 }: CapsuleLensFilterOptions,\n) {\n  const rawId = useId().replaceAll(':', '');\n  const filterId = `lg-capsule-${rawId}`;\n  const [map, setMap] = useState<CapsuleLensState | null>(null);\n\n  useEffect(() => {\n    const el = surfaceRef.current;\n\n    if (!enabled || !el) {\n      queueMicrotask(() => setMap(null));\n\n      return;\n    }\n\n    let frame = 0;\n    let disposed = false;\n\n    const measure = () => {\n      frame = 0;\n\n      if (disposed) return;\n\n      const width = el.clientWidth;\n      const height = el.clientHeight;\n\n      if (!width || !height) {\n        setMap(null);\n\n        return;\n      }\n\n      const thickness = clamp(\n        readTokenOr(window.getComputedStyle(el), '--lg-glass-thickness', 1),\n        0.1,\n        4,\n      );\n\n      const next = {\n        // A supersampled copy already has the resolution the map needs.\n        ...buildCapsuleLensMapDataUrl({\n          devicePixelRatio: supersample > 1 ? 1 : window.devicePixelRatio || 1,\n          height: height * supersample,\n          thickness,\n          width: width * supersample,\n        }),\n        dispersion: clamp(dispersion * thickness, 0, 1),\n      };\n\n      setMap((previous) =>\n        previous &&\n        previous.href === next.href &&\n        previous.metrics.depth === next.metrics.depth &&\n        previous.dispersion === next.dispersion\n          ? previous\n          : next,\n      );\n    };\n\n    const schedule = () => {\n      if (!frame) frame = requestAnimationFrame(measure);\n    };\n\n    const observer = new ResizeObserver(schedule);\n    observer.observe(el);\n    schedule();\n\n    return () => {\n      disposed = true;\n      cancelAnimationFrame(frame);\n      observer.disconnect();\n    };\n  }, [dispersion, enabled, signature, supersample, surfaceRef]);\n\n  // Blue reaches furthest; leave enough content beyond the rim for it and the blur. The\n  // filter works in the copy's supersampled pixels; the margin is returned in CSS pixels,\n  // rounded up to a whole one so the scaled copy lands on the knob without a sliver.\n  const blur = MAGNIFIER_BLUR * supersample;\n\n  const scaledMargin = map\n    ? Math.ceil(\n        (map.metrics.depth * (1 + map.dispersion / 2) + blur * 3 + 2 * supersample) / supersample,\n      ) * supersample\n    : 0;\n\n  const filterElement = useMemo(() => {\n    if (!map) return null;\n\n    const { depth, height, width } = map.metrics;\n    const margin = scaledMargin;\n\n    return (\n      <svg aria-hidden=\"true\" className=\"lg-refraction-filter\" focusable=\"false\" viewBox=\"0 0 0 0\">\n        <defs>\n          <filter\n            id={filterId}\n            x={-margin}\n            y={-margin}\n            width={width + margin * 4}\n            height={height + margin * 4}\n            filterUnits=\"userSpaceOnUse\"\n            primitiveUnits=\"userSpaceOnUse\"\n            colorInterpolationFilters=\"sRGB\"\n          >\n            <feGaussianBlur in=\"SourceGraphic\" stdDeviation={blur} result=\"blurred\" />\n            <feImage\n              href={map.href}\n              x={margin}\n              y={margin}\n              width={width}\n              height={height}\n              preserveAspectRatio=\"none\"\n              result=\"bend\"\n            />\n            {/* The map's blue channel softens only the scene the rim bends. */}\n            <feColorMatrix\n              in=\"bend\"\n              type=\"matrix\"\n              values=\"0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 1 0 0\"\n              result=\"rim\"\n            />\n            <feComposite in=\"blurred\" in2=\"rim\" operator=\"in\" result=\"softRim\" />\n            <feComposite in=\"softRim\" in2=\"SourceGraphic\" operator=\"over\" result=\"soft\" />\n            {refractColours('soft', 'bend', depth * 2, map.dispersion)}\n          </filter>\n        </defs>\n      </svg>\n    );\n  }, [blur, filterId, map, scaledMargin]);\n\n  return {\n    active: map !== null,\n    filterElement,\n    filterStyle: map ? `url(#${filterId})` : undefined,\n    margin: scaledMargin / supersample,\n    supersample,\n  };\n}\n",
      "type": "registry:hook",
      "target": "components/glassyui/lib/use-refraction-filter.tsx"
    },
    {
      "path": "registry/glassyui/lib/scene-context.ts",
      "content": "'use client';\n\nimport { createContext, useContext, useLayoutEffect } from 'react';\nimport type { RefObject } from 'react';\n\nexport type GlassSceneRegistry = {\n  elements: ReadonlySet<HTMLElement>;\n  register: (element: HTMLElement) => () => void;\n  subscribe: (listener: () => void) => () => void;\n};\n\n// The registry exists before any effect runs, because children register in\n// their effects and those run before the scene's own effect.\nexport function createGlassSceneRegistry(): GlassSceneRegistry {\n  const elements = new Set<HTMLElement>();\n  const listeners = new Set<() => void>();\n  const notify = () => listeners.forEach((listener) => listener());\n\n  return {\n    elements,\n    register(element) {\n      elements.add(element);\n      notify();\n\n      return () => {\n        elements.delete(element);\n        notify();\n      };\n    },\n    subscribe(listener) {\n      listeners.add(listener);\n\n      return () => {\n        listeners.delete(listener);\n      };\n    },\n  };\n}\n\nexport const GlassSceneContext = createContext<GlassSceneRegistry | null>(null);\n\n/**\n * Lets a glass element hand its material to the nearest GlassScene. Outside a\n * scene it does nothing. It registers before paint, so glass that mounts into\n * a live scene never shows its CSS material first.\n */\nexport function useGlassScenePane(ref: RefObject<HTMLElement | null>, enabled = true) {\n  const registry = useContext(GlassSceneContext);\n\n  useLayoutEffect(() => {\n    const element = ref.current;\n\n    if (!registry || !enabled || !element) return;\n\n    return registry.register(element);\n  }, [enabled, ref, registry]);\n}\n",
      "type": "registry:lib",
      "target": "components/glassyui/lib/scene-context.ts"
    },
    {
      "path": "registry/glassyui/glass-panel.tsx",
      "content": "'use client';\n\nimport clsx from 'clsx';\nimport { forwardRef } from 'react';\nimport type { HTMLAttributes, ReactNode } from 'react';\nimport { GlassSurface } from './glass-surface';\nimport type { RefractionBackgroundSpace } from './glass-surface';\n\ntype PanelVariant = 'panel' | 'card' | 'pill';\n\ntype PanelElevation = 'base' | 'raised';\n\ntype PanelRefraction = 'none' | 'soft' | 'strong';\n\ntype PanelPreset = 'subtle' | 'standard' | 'prominent' | 'control' | 'showcase';\n\nexport type GlassPanelProps = HTMLAttributes<HTMLDivElement> & {\n  variant?: PanelVariant;\n  elevation?: PanelElevation;\n  /** Brightens the surface a touch on hover. */\n  interactive?: boolean;\n  /** Chromium edge lens over the frost. On by default for control and showcase presets. */\n  lens?: boolean;\n  preset?: PanelPreset;\n  refraction?: PanelRefraction;\n  refractionBackground?: ReactNode;\n  refractionBackgroundSpace?: RefractionBackgroundSpace;\n  refractionDisplacement?: number;\n  /** How thick the glass is, as a multiple of regular. See GlassSurface. */\n  thickness?: number;\n};\n\n// Shape, spacing and elevation live in liquid.css, below Tailwind utilities.\nconst VARIANT_CLASS: Record<PanelVariant, string> = {\n  panel: 'lg-panel--panel',\n  card: 'lg-panel--card',\n  pill: 'lg-panel--pill',\n};\n\nexport const GlassPanel = forwardRef<HTMLDivElement, GlassPanelProps>(\n  (\n    {\n      className,\n      variant = 'panel',\n      elevation = 'base',\n      interactive = false,\n      lens,\n      preset = variant === 'pill' ? 'control' : 'standard',\n      refraction = preset === 'showcase' ? 'strong' : 'none',\n      refractionBackground,\n      refractionBackgroundSpace,\n      refractionDisplacement,\n      ...rest\n    },\n    forwardedRef,\n  ) => {\n    return (\n      <GlassSurface\n        ref={forwardedRef}\n        interactive={interactive}\n        lens={lens}\n        preset={preset}\n        refraction={refraction}\n        refractionBackground={refractionBackground}\n        refractionBackgroundSpace={refractionBackgroundSpace}\n        refractionDisplacement={refractionDisplacement}\n        className={clsx(\n          VARIANT_CLASS[variant],\n          elevation === 'raised' && 'lg-panel--raised',\n          className,\n        )}\n        {...rest}\n      />\n    );\n  },\n);\n\nGlassPanel.displayName = 'GlassPanel';\n",
      "type": "registry:ui",
      "target": "components/glassyui/glass-panel.tsx"
    },
    {
      "path": "registry/glassyui/glass-tooltip.tsx",
      "content": "'use client';\n\nimport * as TooltipPrimitive from '@radix-ui/react-tooltip';\nimport clsx from 'clsx';\nimport { GlassPanel } from './glass-panel';\n\nconst radixSlotProps = { asChild: true };\n\nexport const GlassTooltipProvider = TooltipPrimitive.Provider;\n\nexport const GlassTooltip = TooltipPrimitive.Root;\n\nexport const GlassTooltipTrigger = TooltipPrimitive.Trigger;\n\nexport function GlassTooltipContent(\n  props: React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>,\n) {\n  const { className, sideOffset = 6, ...rest } = props;\n\n  return (\n    <TooltipPrimitive.Portal>\n      <TooltipPrimitive.Content sideOffset={sideOffset} {...rest} {...radixSlotProps}>\n        <GlassPanel\n          variant=\"card\"\n          elevation=\"raised\"\n          refraction=\"none\"\n          className={clsx('lg-tooltip-content', className)}\n        >\n          {props.children}\n        </GlassPanel>\n      </TooltipPrimitive.Content>\n    </TooltipPrimitive.Portal>\n  );\n}\n",
      "type": "registry:ui",
      "target": "components/glassyui/glass-tooltip.tsx"
    }
  ],
  "meta": {
    "sourceModules": [
      "tooltip"
    ]
  },
  "type": "registry:ui"
}