{"version":3,"file":"refine.cjs","names":["e","e","#entries","#listeners","#eventListeners","#disposed","#max","#setEntries","#emit","#entry","#update","#scheduleTimer","#clearTimer"],"sources":["../src/_dev.ts","../src/content/icon/icon.css?inline","../src/content/icon/icon.ts","../src/shared/prop-bundles.ts","../src/shared/size-presets.ts","../src/styles/mixins/accessibility.css.ts","../src/styles/mixins/animation.css.ts","../src/styles/mixins/field-variants.css.ts","../src/styles/mixins/shape.css.ts","../src/styles/mixins/states.css.ts","../src/styles/mixins/table-base.css.ts","../src/styles/mixins/theme.css.ts","../src/styles/mixins/variants.css.ts","../src/content/avatar/avatar.css?inline","../src/content/avatar/avatar.ts","../src/content/avatar/avatar-group.css?inline","../src/content/avatar/avatar-group.ts","../src/content/breadcrumb/breadcrumb.css?inline","../src/content/breadcrumb/breadcrumb-item.css?inline","../src/content/breadcrumb/breadcrumb.ts","../src/core/announcer.ts","../src/core/aria-reflection.ts","../src/core/auto-resize.ts","../src/core/field-base.ts","../src/core/keyboard.ts","../src/core/signals.ts","../src/core/checkable.ts","../src/core/choice-field.ts","../src/core/composer.ts","../src/core/date-picker.ts","../src/core/focus.ts","../src/core/light-dom.ts","../src/core/numbers.ts","../src/core/ore.ts","../src/core/overlay.ts","../src/core/ref-callback.ts","../../arsenal/dist/math/clamp.js","../src/core/slider.ts","../src/core/spinner.ts","../src/core/text-field.ts","../src/core/direction.ts","../src/core/nav.ts","../src/errors.ts","../src/core/positioner.ts","../src/core/option-list.ts","../src/core/parse.ts","../src/content/card/card.css?inline","../src/content/card/card.ts","../src/feedback/progress/progress.css?inline","../src/feedback/progress/progress.ts","../src/content/carousel/carousel.css?inline","../src/content/carousel/carousel-slide.css?inline","../src/content/carousel/carousel-slide.ts","../src/content/carousel/carousel.ts","../src/content/chat-message/chat-message.css?inline","../src/content/chat-message/chat-message.ts","../src/content/code-window/code-window.css?inline","../src/content/code-window/code-window.ts","../src/content/copy-command/copy-command.css?inline","../src/content/copy-command/copy-command.ts","../src/content/list/list.css?inline","../src/content/list/list.ts","../src/content/list/_list-item-reveal.ts","../src/content/list/list-item.css?inline","../src/content/list/list-item.ts","../src/utils/css.ts","../src/utils/link.ts","../src/inputs/button-group/button-group.css?inline","../src/inputs/button-group/button-group.ts","../src/inputs/shared/field-binding.ts","../src/inputs/shared/templates.ts","../src/inputs/shared/use-form-action.ts","../src/inputs/button/button.css?inline","../src/inputs/button/button.ts","../src/content/marquee/marquee.css?inline","../src/content/marquee/marquee.ts","../src/content/pagination/pagination.css?inline","../src/content/pagination/pagination.ts","../src/content/separator/separator.css?inline","../src/content/separator/separator.ts","../src/content/stepper/_is-step-navigable.ts","../src/content/stepper/step.css?inline","../src/content/stepper/stepper.css?inline","../src/content/stepper/stepper.ts","../src/content/stepper/step.ts","../src/content/table/table.css?inline","../src/content/table/table.ts","../src/content/text/text.css?inline","../src/content/text/text.ts","../src/content/index.ts","../src/disclosure/accordion/accordion.css?inline","../src/disclosure/accordion/accordion.ts","../src/disclosure/accordion-item/accordion-item.css?inline","../src/disclosure/accordion-item/accordion-item.ts","../src/disclosure/tabs/tabs.css?inline","../src/disclosure/tabs/tabs.ts","../src/disclosure/tab-item/tab-item.css?inline","../src/disclosure/tab-item/tab-item.ts","../src/disclosure/tab-panel/tab-panel.css?inline","../src/disclosure/tab-panel/tab-panel.ts","../src/disclosure/index.ts","../src/overlay/shared/await-exit.ts","../src/feedback/alert/alert.css?inline","../src/feedback/alert/alert.ts","../src/feedback/async/async.css?inline","../src/feedback/async/async.ts","../src/feedback/badge/badge.css?inline","../src/feedback/badge/badge.ts","../src/feedback/chip/chip.css?inline","../src/feedback/chip/chip.ts","../src/feedback/password-strength/password-strength.css?inline","../src/feedback/password-strength/password-strength.ts","../src/feedback/skeleton/skeleton.css?inline","../src/feedback/skeleton/skeleton.ts","../../arsenal/dist/random/uuid.js","../src/feedback/toast/toast.css?inline","../src/feedback/toast/toast.ts","../src/feedback/typing-indicator/typing-indicator.css?inline","../src/feedback/typing-indicator/typing-indicator.ts","../src/feedback/index.ts","../src/inputs/calendar/calendar.css?inline","../src/inputs/calendar/calendar.ts","../src/inputs/checkbox-group/checkbox-group.css?inline","../src/inputs/checkbox-group/checkbox-group.ts","../src/inputs/shared/native-field-event.ts","../src/inputs/checkbox/checkbox.css?inline","../src/inputs/checkbox/checkbox.ts","../src/inputs/combobox/combobox-options.ts","../src/inputs/input/input.css?inline","../src/inputs/input/input.ts","../src/inputs/combobox/combobox.css?inline","../src/inputs/combobox/combobox.ts","../../arsenal/dist/function/debounce.js","../src/inputs/select/select.css?inline","../src/inputs/select/select.ts","../src/overlay/shared/use-floating-trigger.ts","../src/overlay/popover/popover.css?inline","../src/overlay/popover/popover.ts","../src/inputs/datagrid/datagrid.css?inline","../src/inputs/datagrid/datagrid-column.ts","../src/inputs/datagrid/datagrid-model.ts","../src/inputs/datagrid/datagrid-nav.ts","../src/inputs/datagrid/datagrid.ts","../src/inputs/date-picker/date-picker.css?inline","../src/inputs/date-picker/date-picker.ts","../src/inputs/file-input/file-input.css?inline","../src/inputs/file-input/file-input-upload.ts","../src/inputs/file-input/file-input.ts","../src/inputs/message-composer/message-composer.css?inline","../src/inputs/message-composer/message-composer.ts","../src/inputs/number-input/number-input.css?inline","../src/inputs/number-input/number-input.ts","../src/inputs/otp-input/otp-input.css?inline","../src/inputs/otp-input/otp-input.ts","../src/inputs/radio-group/radio-group.css?inline","../src/inputs/radio-group/radio-group.ts","../src/inputs/radio/radio.css?inline","../src/inputs/radio/radio.ts","../src/inputs/rating/rating.css?inline","../src/inputs/rating/rating.ts","../src/inputs/slider/slider.css?inline","../src/inputs/slider/slider.ts","../src/inputs/switch/switch.css?inline","../src/inputs/switch/switch.ts","../src/inputs/textarea/textarea.css?inline","../src/inputs/textarea/textarea.ts","../src/inputs/time-picker/time-picker.css?inline","../src/inputs/time-picker/time-picker.ts","../src/inputs/index.ts","../src/layout/box/box.css?inline","../src/layout/box/box.ts","../src/layout/grid/grid.css?inline","../src/layout/grid/grid.ts","../src/layout/grid-item/grid-item.css?inline","../src/layout/grid-item/grid-item.ts","../src/layout/navbar/navbar.css?inline","../src/layout/navbar/navbar.ts","../src/layout/sidebar/sidebar.css?inline","../src/layout/sidebar/sidebar-group.css?inline","../src/layout/sidebar/sidebar-item.css?inline","../src/layout/sidebar/sidebar.ts","../src/layout/index.ts","../src/overlay/shared/background-lock.ts","../src/overlay/shared/use-dialog.ts","../src/overlay/command-palette/command-palette-items.ts","../src/overlay/command-palette/command-palette.css?inline","../src/overlay/command-palette/command-palette.ts","../src/overlay/dialog/dialog.css?inline","../src/overlay/dialog/dialog.ts","../src/overlay/drawer/drawer.css?inline","../src/overlay/drawer/drawer.ts","../src/overlay/menu/menu.css?inline","../src/overlay/menu/menu-item.css?inline","../src/overlay/menu/menu-separator.css?inline","../src/overlay/menu/menu.ts","../src/overlay/navigation-menu/navigation-menu.css?inline","../src/overlay/navigation-menu/navigation-menu-item.css?inline","../src/overlay/navigation-menu/navigation-menu-panel.css?inline","../src/overlay/navigation-menu/navigation-menu.ts","../src/overlay/tooltip/tooltip.css?inline","../src/overlay/tooltip/tooltip.ts","../src/overlay/index.ts","../src/register.ts"],"sourcesContent":["const isDev = !(globalThis as { __REFINE_PROD__?: boolean }).__REFINE_PROD__;\n\n/**\n * Emits a `console.warn` in development builds only.\n * @internal\n * @security Messages may include user-supplied attribute values or element content.\n * Never pass PII or secrets as component attributes.\n */\nexport function warn(msg: string): void {\n  if (isDev) console.warn(`[@vielzeug/refine] ${msg}`);\n}\n","@layer refine.base {\n  :host {\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    line-height: 0;\n    vertical-align: middle;\n    color: inherit;\n  }\n\n  :host([hidden]) {\n    display: none;\n  }\n\n  svg {\n    display: block;\n    width: 100%;\n    height: 100%;\n  }\n}\n\n/* Unlayered: always wins over any @layer rule, including refine.overrides */\n:host {\n  width: var(--ore-icon-size, var(--_size-px));\n  height: var(--ore-icon-size, var(--_size-px));\n}\n","import { bind, define, html, prop, ref, watchEffect, when } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport * as lucideModule from 'lucide';\n\nimport { warn } from '../../_dev';\nimport styles from './icon.css?inline';\n\nexport type IconNode = Array<[string, Record<string, string | number | undefined>]>;\n\nconst DEFAULT_SIZE = 16;\nconst DEFAULT_STROKE_WIDTH = 2;\nconst LUCIDE_VIEWBOX_SIZE = 24;\nconst SVG_NS = 'http://www.w3.org/2000/svg';\n\n/**\n * Allowlisted SVG shape/structure element names. Only these tags are permitted\n * when building the SVG DOM from an IconNode, preventing arbitrary element\n * injection (e.g. <script>, event-handler-bearing elements).\n */\nconst ALLOWED_SVG_TAGS = new Set([\n  'circle',\n  'clipPath',\n  'defs',\n  'ellipse',\n  'g',\n  'line',\n  'linearGradient',\n  'mask',\n  'path',\n  'polygon',\n  'polyline',\n  'radialGradient',\n  'rect',\n  'stop',\n  'symbol',\n  'use',\n]);\n\n/**\n * Allowlisted SVG presentation / structural attribute names.\n * Event handler attributes (on*) and \"xlink:href\" are excluded.\n */\nconst ATTR_KEY_RE = /^[a-zA-Z][a-zA-Z0-9:_-]*$/;\nconst BLOCKED_ATTR_RE = /^(on|xlink:|xml:|href$)/i;\n\n// Sync registry seeded from lucide at module load; extend at any time via registerIcons()\nconst registry = new Map<string, IconNode>(\n  Object.entries((lucideModule as unknown as { icons: Record<string, IconNode> }).icons),\n);\n\n/**\n * Register additional icons (or override existing ones) by name.\n * Keys may be kebab-case or PascalCase — both are accepted by `ore-icon`.\n */\nexport function registerIcons(icons: Record<string, IconNode>): void {\n  for (const [name, node] of Object.entries(icons)) {\n    registry.set(name, node);\n  }\n}\n\nconst toPascalCase = (value: string): string =>\n  value\n    .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n    .split(/[^a-zA-Z0-9]+/)\n    .filter(Boolean)\n    .map((p) => p.charAt(0).toUpperCase() + p.slice(1).toLowerCase())\n    .join('');\n\nconst parseSize = (value: string | null): number | string => {\n  if (value == null || value === '') return DEFAULT_SIZE;\n\n  const n = Number(value);\n\n  return Number.isFinite(n) && n > 0 && /^\\d+(\\.\\d+)?$/.test(value.trim()) ? n : value;\n};\n\nconst resolveIcon = (name: string): IconNode | undefined => registry.get(name) ?? registry.get(toPascalCase(name));\n\n/**\n * Builds an allowlisted SVG child element via `createElementNS` — real DOM construction, not\n * HTML-string parsing, so this never touches Ore's `unsafeHtml()` directive (and its \"unsanitized\n * HTML\" dev warning) at all. `iconNode` entries come from the bundled Lucide icon set or\n * `registerIcons()` (a developer/build-time API, never runtime user input), but the tag/attr\n * allowlist stays as defense in depth regardless of where the data originated.\n */\nconst createSvgChild = (tag: string, attrs: Record<string, string | number | undefined>): SVGElement | null => {\n  if (!ALLOWED_SVG_TAGS.has(tag)) return null;\n\n  const el = document.createElementNS(SVG_NS, tag);\n\n  for (const [key, value] of Object.entries(attrs)) {\n    if (value === undefined) continue;\n\n    if (!ATTR_KEY_RE.test(key) || BLOCKED_ATTR_RE.test(key)) continue;\n\n    el.setAttribute(key, String(value));\n  }\n\n  return el;\n};\n\n/** Icon component properties */\nexport type OreIconProps = {\n  /** Keep stroke width visually consistent when icon size changes */\n  absoluteStrokeWidth?: boolean;\n  /** Accessible text label. Decorative icons should omit this. */\n  label?: string;\n  /** Lucide icon name, e.g. `search` or `chevron-right` */\n  name?: string;\n  /** Icon width/height in px by default. Accepts CSS lengths. */\n  size?: number | string;\n  /** Render as a filled/solid shape instead of a stroked outline */\n  solid?: boolean;\n  /** SVG stroke width */\n  strokeWidth?: number;\n};\n\n/**\n * Icon wrapper for consistent Lucide rendering across Block.\n *\n * @element ore-icon\n *\n * @attr {string} name - Lucide icon name, e.g. `search` or `chevron-right`\n * @attr {number|string} size - Width/height (default: 16)\n * @attr {number} stroke-width - SVG stroke width (default: 2)\n * @attr {boolean} absolute-stroke-width - Keep stroke width visually stable across icon sizes\n * @attr {boolean} solid - Render as filled shape instead of stroked outline\n * @attr {string} label - Accessible label; when omitted the icon is decorative\n *\n * @csspart svg - Internal SVG element\n *\n * @example\n * ```html\n * <ore-icon name=\"search\"></ore-icon>\n * <ore-icon name=\"chevron-right\" size=\"18\"></ore-icon>\n * <ore-icon name=\"trash-2\" label=\"Delete\"></ore-icon>\n * <ore-icon name=\"star\" solid></ore-icon>\n * ```\n */\nexport const ICON_TAG = 'ore-icon' as const;\ndefine<OreIconProps>(ICON_TAG, {\n  props: {\n    absoluteStrokeWidth: prop.bool(),\n    label: prop.string(),\n    name: prop.string(),\n    size: { default: DEFAULT_SIZE as number | string, parse: parseSize, reflect: false },\n    solid: prop.bool(),\n    strokeWidth: prop.number(DEFAULT_STROKE_WIDTH),\n  },\n  setup(props) {\n    bind({\n      attr: {\n        'aria-hidden': () => ((props.label.value ?? '').trim() ? null : 'true'),\n        'aria-label': () => (props.label.value ?? '').trim() || null,\n        role: () => ((props.label.value ?? '').trim() ? 'img' : null),\n      },\n      style: {\n        '--_size-px': () => {\n          const s = props.size.value;\n\n          return typeof s === 'number' ? `${s}px` : String(s);\n        },\n      },\n    });\n\n    const svgRef = ref<SVGSVGElement>();\n\n    // Memoized so an unknown icon name only warns once per change, not once per reactive read.\n    const iconNode = computed(() => {\n      const name = (props.name.value ?? '').trim();\n\n      if (!name) return undefined;\n\n      const node = resolveIcon(name);\n\n      if (!node) warn(`ore-icon: icon not found: \"${name.slice(0, 64)}\"`);\n\n      return node;\n    });\n\n    // Real DOM construction (createElementNS), not the unsafeHtml() directive — see createSvgChild's\n    // doc comment. Rebuilds the <svg>'s attributes and children whenever the icon name, size,\n    // or presentation props change, or when `svgRef` first attaches (a fresh element mounts\n    // every time `when()`'s branch below flips truthy).\n    watchEffect(() => {\n      const svg = svgRef.value;\n      const node = iconNode.value;\n\n      if (!svg || !node) return;\n\n      const size = props.size.value;\n      const numericSize = typeof size === 'number' ? size : LUCIDE_VIEWBOX_SIZE;\n      const strokeWidth =\n        props.absoluteStrokeWidth.value && !props.solid.value\n          ? props.strokeWidth.value! * (LUCIDE_VIEWBOX_SIZE / numericSize)\n          : props.strokeWidth.value!;\n\n      svg.setAttribute('fill', props.solid.value ? 'currentColor' : 'none');\n      svg.setAttribute('stroke', props.solid.value ? 'none' : 'currentColor');\n      svg.setAttribute('stroke-linecap', 'round');\n      svg.setAttribute('stroke-linejoin', 'round');\n      svg.setAttribute('stroke-width', String(props.solid.value ? 0 : strokeWidth));\n      svg.setAttribute('viewBox', '0 0 24 24');\n\n      const children = node.map(([tag, attrs]) => createSvgChild(tag, attrs)).filter((el): el is SVGElement => !!el);\n\n      svg.replaceChildren(...children);\n    });\n\n    return html`\n      ${when(\n        () => !!iconNode.value,\n        () => html`\n          <svg ref=\"${svgRef}\" part=\"svg\" style=\"width:100%;height:100%\"></svg>\n        `,\n      )}\n    `;\n  },\n  styles: [styles],\n});\n","import { prop } from '@vielzeug/ore';\n\nimport type { ComponentSize, ElevationLevel, RoundedSize, ThemeColor } from './types';\n\n/** Prop bundle for components that support a theme colour. */\nexport const themableBundle = {\n  color: prop.string<ThemeColor>(),\n};\n\n/** Prop bundle for components with discrete size variants. */\nexport const sizableBundle = {\n  size: prop.string<ComponentSize>(),\n};\n\n/** Prop bundle for interactive components that can be disabled. */\nexport const disablableBundle = {\n  disabled: prop.bool(false),\n};\n\n/** Prop bundle for components with a loading / busy state. */\nexport const loadableBundle = {\n  loading: prop.bool(false),\n};\n\n/** Prop bundle for components with configurable border-radius. */\nexport const roundableBundle = {\n  rounded: prop.string<RoundedSize>(),\n};\n\n/** Prop bundle for components with an elevation / box-shadow. */\nexport const elevatableBundle = {\n  elevation: prop.number<ElevationLevel>(),\n};\n\n/**\n * Convenience bundle combining the five most common interactive-component props:\n * `color`, `size`, `disabled`, `loading`, and `rounded`.\n *\n * Use this single spread instead of five separate bundle spreads when a\n * component needs all of them.\n *\n * @example\n * ```ts\n * props: { ...commonProps, href: prop.string() }\n * ```\n */\nexport const commonProps = {\n  ...themableBundle,\n  ...sizableBundle,\n  ...disablableBundle,\n  ...loadableBundle,\n  ...roundableBundle,\n};\n","import type { SizeConfig } from '../styles/mixins/shape.css';\nimport type { ComponentSize } from './types';\n\n/** A preset with an entry for every ComponentSize key. */\ntype FullSizePreset = Record<ComponentSize, SizeConfig>;\n\n/** A preset that may omit some ComponentSize keys (sizeVariantMixin fills the gaps with its defaults). */\ntype PartialSizePreset = Partial<Record<ComponentSize, SizeConfig>>;\n\nexport const FIELD_SIZE_PRESET = {\n  lg: {\n    '--_field-height': 'var(--size-12)',\n    '--_padding': 'var(--size-2-5) var(--size-3-5)',\n    fontSize: 'var(--text-base)',\n    gap: 'var(--size-2-5)',\n  },\n  md: {\n    '--_field-height': 'var(--size-10)',\n    '--_padding': 'var(--size-1-5) var(--size-3)',\n    fontSize: 'var(--text-sm)',\n    gap: 'var(--size-2)',\n  },\n  sm: {\n    '--_field-height': 'var(--size-8)',\n    '--_padding': 'var(--size-1) var(--size-2)',\n    fontSize: 'var(--text-xs)',\n    gap: 'var(--size-1-5)',\n  },\n} satisfies FullSizePreset;\n\nexport const TEXTAREA_SIZE_PRESET = {\n  lg: {\n    '--_padding': 'var(--size-2-5) var(--size-3-5)',\n    fontSize: 'var(--text-base)',\n    gap: 'var(--size-2-5)',\n  },\n  md: {\n    '--_padding': 'var(--size-1-5) var(--size-3)',\n    fontSize: 'var(--text-sm)',\n    gap: 'var(--size-2)',\n  },\n  sm: {\n    '--_padding': 'var(--size-1) var(--size-2)',\n    fontSize: 'var(--text-xs)',\n    gap: 'var(--size-1-5)',\n  },\n} satisfies FullSizePreset;\n\n/** Shared size preset for checkbox and radio (icon + label layout). */\nexport const CONTROL_SIZE_PRESET = {\n  lg: {\n    fontSize: 'var(--text-base)',\n    gap: 'var(--size-2-5)',\n    size: 'var(--size-6)',\n  },\n  sm: {\n    fontSize: 'var(--text-xs)',\n    gap: 'var(--size-1-5)',\n    size: 'var(--size-4)',\n  },\n} satisfies PartialSizePreset;\n\n/** Shared size preset for the switch toggle control. */\nexport const SWITCH_SIZE_PRESET = {\n  lg: {\n    fontSize: 'var(--text-base)',\n    gap: 'var(--size-3)',\n    height: 'var(--size-7)',\n    thumbSize: 'var(--size-6)',\n    width: 'var(--size-14)',\n  },\n  sm: {\n    fontSize: 'var(--text-xs)',\n    gap: 'var(--size-2)',\n    height: 'var(--size-5)',\n    thumbSize: 'var(--size-4)',\n    width: 'var(--size-9)',\n  },\n} satisfies PartialSizePreset;\n\n/** Shared size preset for the slider track/thumb. */\nexport const SLIDER_SIZE_PRESET = {\n  lg: {\n    '--_thumb-inset': 'var(--slider-thumb-inset, var(--size-3))',\n    fontSize: 'var(--text-base)',\n    height: 'calc(var(--size-5) - var(--size-1))',\n    size: 'var(--size-6)',\n  },\n  md: {\n    '--_thumb-inset': 'var(--slider-thumb-inset, var(--size-2-5))',\n    fontSize: 'var(--text-base)',\n    height: 'var(--size-3)',\n    size: 'var(--size-5)',\n  },\n  sm: {\n    '--_thumb-inset': 'var(--slider-thumb-inset, var(--size-2))',\n    fontSize: 'var(--text-xs)',\n    height: 'var(--size-2)',\n    size: 'var(--size-4)',\n  },\n} satisfies FullSizePreset;\n\n/**\n * Size preset for the message composer card. Padding is symmetric (unlike\n * `TEXTAREA_SIZE_PRESET`'s field-shaped padding) since this scales a card that wraps a field\n * *and* a toolbar row, not a bare field — `md`'s padding matches the value the card used before\n * `size` scaled anything, so the default look is unchanged.\n */\nexport const MESSAGE_COMPOSER_SIZE_PRESET = {\n  lg: {\n    '--_padding': 'var(--size-4)',\n    fontSize: 'var(--text-base)',\n    gap: 'var(--size-2-5)',\n  },\n  md: {\n    '--_padding': 'var(--size-3)',\n    fontSize: 'var(--text-sm)',\n    gap: 'var(--size-2)',\n  },\n  sm: {\n    '--_padding': 'var(--size-2)',\n    fontSize: 'var(--text-xs)',\n    gap: 'var(--size-1-5)',\n  },\n} satisfies FullSizePreset;\n\n/**\n * Size preset for `ore-menu`'s floating panel, `ore-menu-item`'s row, and `ore-menu-separator`'s\n * margin. `--_panel-padding`, `--_item-padding`, and `--_separator-margin` are custom pass-through\n * keys (not one of `SizeConfig`'s named slots) since the panel, its items, and its separators each\n * need independently-scaling spacing; `md`'s values match what `menu.css`/`menu-item.css`/\n * `menu-separator.css` hardcoded before `size` was wired up, so the default look is unchanged.\n * `--_font-size`/`--_gap` are inherited by `ore-menu-item` from `ore-menu`'s own host — custom\n * properties cascade down through light-DOM children the same way they cascade into a shadow root.\n */\nexport const MENU_SIZE_PRESET = {\n  lg: {\n    '--_item-padding': 'var(--size-2) var(--size-3-5)',\n    '--_panel-padding': 'var(--size-1-5)',\n    '--_separator-margin': 'var(--size-1-5)',\n    fontSize: 'var(--text-base)',\n    gap: 'var(--size-2-5)',\n  },\n  md: {\n    '--_item-padding': 'var(--size-1-5) var(--size-3)',\n    '--_panel-padding': 'var(--size-1)',\n    '--_separator-margin': 'var(--size-1)',\n    fontSize: 'var(--text-sm)',\n    gap: 'var(--size-2)',\n  },\n  sm: {\n    '--_item-padding': 'var(--size-1) var(--size-2-5)',\n    '--_panel-padding': 'var(--size-0-5)',\n    '--_separator-margin': 'var(--size-0-5)',\n    fontSize: 'var(--text-xs)',\n    gap: 'var(--size-1-5)',\n  },\n} satisfies FullSizePreset;\n\n/**\n * Size preset for `ore-list`'s own host. `ore-list-item` has no `sizeVariantMixin` call of its\n * own — it reads `--_gap`/`--_padding`/`--_padding-inline-end`/`--_font-size`/`--_min-height`/\n * `--_min-height-two-line` inherited straight from its parent `ore-list`'s shadow host (custom\n * properties cascade through light-DOM children the same way `MENU_SIZE_PRESET` cascades from\n * `ore-menu` into `ore-menu-item`), with fallback defaults for standalone use outside an\n * `ore-list`.\n *\n * Follows Material 3's list-item spacing at `md`/`lg`: 16dp between leading/content/trailing\n * (`gap`), 16dp inline-start (`padding`), 24dp inline-end (`--_padding-inline-end` — the trailing\n * edge sits 8dp further out than the other three sides in the M3 spec), 56dp one-line / 72dp\n * two-line row height (`--_min-height`/`--_min-height-two-line`, applied in `list-item.css`).\n * `sm` keeps the same asymmetry and the M3/WCAG 48dp touch-target floor proportionally, for a\n * denser list that still reads as \"M3-like\" rather than hitting the exact dp values M3 doesn't\n * itself define an alternate density for.\n */\nexport const LIST_SIZE_PRESET = {\n  lg: {\n    '--_min-height': 'var(--size-14)',\n    '--_min-height-two-line': 'calc(var(--size-16) + var(--size-2))',\n    '--_padding-inline-end': 'var(--size-6)',\n    fontSize: 'var(--text-base)',\n    gap: 'var(--size-4)',\n    padding: 'var(--size-3) var(--size-4)',\n  },\n  md: {\n    '--_min-height': 'var(--size-14)',\n    '--_min-height-two-line': 'calc(var(--size-16) + var(--size-2))',\n    '--_padding-inline-end': 'var(--size-6)',\n    fontSize: 'var(--text-sm)',\n    gap: 'var(--size-4)',\n    padding: 'var(--size-2-5) var(--size-4)',\n  },\n  sm: {\n    '--_min-height': 'var(--size-12)',\n    '--_min-height-two-line': 'var(--size-16)',\n    '--_padding-inline-end': 'var(--size-4)',\n    fontSize: 'var(--text-xs)',\n    gap: 'var(--size-2)',\n    padding: 'var(--size-1-5) var(--size-2)',\n  },\n} satisfies FullSizePreset;\n\n/** Shared size preset for the file-input dropzone. */\nexport const FILE_INPUT_SIZE_PRESET = {\n  lg: {\n    '--_min-height': 'var(--size-40)',\n    fontSize: 'var(--text-base)',\n  },\n  md: {\n    '--_min-height': 'var(--size-32)',\n    fontSize: 'var(--text-sm)',\n  },\n  sm: {\n    '--_min-height': 'var(--size-28)',\n    fontSize: 'var(--text-xs)',\n  },\n} satisfies FullSizePreset;\n","import { css } from '@vielzeug/ore';\n\n/**\n * Visually-Hidden (\"sr-only\") Style\n *\n * Single source of truth for the standard visually-hidden-but-accessible\n * clipping technique — hides content visually while keeping it in the\n * accessibility tree (screen readers, `aria-live` regions).\n *\n * Two forms are exported from the same declarations so component stylesheets\n * and JS-created DOM elements never drift out of sync:\n * - `srOnlyMixin` — a `.sr-only` class for component `styles: [...]` arrays.\n * - `SR_ONLY_INLINE_STYLE` — the equivalent `cssText` string for elements\n *   created outside any component's shadow root (e.g. a live region appended\n *   directly to `document.body`).\n *\n * @example\n * ```ts\n * // Component stylesheet\n * import { srOnlyMixin } from '../../styles';\n * return { styles: [srOnlyMixin, componentStyles], template: html`<span class=\"sr-only\">...</span>` };\n *\n * // JS-created element outside a shadow root\n * import { SR_ONLY_INLINE_STYLE } from '../../styles';\n * el.style.cssText = SR_ONLY_INLINE_STYLE;\n * ```\n */\nexport const SR_ONLY_INLINE_STYLE =\n  'position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;' +\n  'white-space:nowrap;border-width:0;clip-path:inset(50%);';\n\nexport const srOnlyMixin = css`\n  .sr-only {\n    position: absolute;\n    width: 1px;\n    height: 1px;\n    padding: 0;\n    margin: -1px;\n    overflow: hidden;\n    white-space: nowrap;\n    border-width: 0;\n    clip-path: inset(50%);\n  }\n`;\n\n/**\n * Coarse Pointer Mixin\n *\n * Under `@media (pointer: coarse)`, promotes the full component one size tier\n * so padding, gap, font-size, height, and icon-size all grow proportionally\n * with the WCAG 44 px touch target — not just the minimum height in isolation:\n *\n * - default / `size=\"md\"` → lg-scale tokens + `--_touch-target: var(--size-11)`\n * - `size=\"sm\"` → md-scale tokens + `--_touch-target: var(--size-11)`\n * - `size=\"lg\"` → touch target only (already at max scale)\n *\n * Interactive elements inside the component that need a guaranteed tap target\n * should still reference `--_touch-target`:\n *\n * ```css\n * .close { min-height: var(--_touch-target); min-width: var(--_touch-target); }\n * ```\n *\n * @example\n * ```ts\n * import { coarsePointerMixin } from '../../styles';\n *\n * return {\n *   styles: [coarsePointerMixin, componentStyles],\n *   template: html`...`\n * };\n * ```\n */\nexport const coarsePointerMixin = css`\n  @media (pointer: coarse) {\n    /* Default / md size: promote all scale tokens one tier up (md → lg) */\n    :host,\n    :host([size='md']) {\n      --_touch-target: var(--size-11);\n      --_font-size: var(--text-base);\n      --_gap: var(--size-2-5);\n      --_height: var(--size-12);\n      --_size: var(--size-6);\n      --_icon-size: var(--size-6);\n      --_padding: var(--size-2-5) var(--size-5);\n    }\n\n    /* sm size: promote to md scale */\n    :host([size='sm']) {\n      --_touch-target: var(--size-11);\n      --_font-size: var(--text-sm);\n      --_gap: var(--size-2);\n      --_height: var(--size-10);\n      --_size: var(--size-5);\n      --_icon-size: var(--size-5);\n      --_padding: var(--size-2) var(--size-4);\n    }\n\n    /* lg size: already max, just enforce touch target */\n    :host([size='lg']) {\n      --_touch-target: var(--size-11);\n    }\n  }\n`;\n\n/**\n * Reduced Motion Mixin\n *\n * Defines `--_motion-transition: none` and `--_motion-animation: none` on\n * `:host` under `@media (prefers-reduced-motion: reduce)`.\n * Component CSS opts in via CSS variable fallbacks:\n *\n * ```css\n * .panel { transition: var(--_motion-transition, opacity 300ms ease); }\n * .loader { animation: var(--_motion-animation, spin 0.6s linear infinite); }\n * ```\n *\n * @example\n * ```ts\n * import { reducedMotionMixin } from '../../styles';\n *\n * return {\n *   styles: [reducedMotionMixin, componentStyles],\n *   template: html`...`\n * };\n * ```\n */\nexport const reducedMotionMixin = css`\n  @media (prefers-reduced-motion: reduce) {\n    :host {\n      --_motion-transition: none;\n      --_motion-animation: none;\n    }\n  }\n`;\n","import { css } from '@vielzeug/ore';\n\n/**\n * Register the --rainbow-angle CSS custom property so browsers can\n * interpolate it inside conic-gradient().\n * Called automatically by rainbowEffectMixin on first use.\n */\nlet rainbowRegistered = false;\n\nexport function registerRainbowProperty() {\n  if (rainbowRegistered) return;\n\n  if (typeof CSS !== 'undefined' && CSS.registerProperty) {\n    try {\n      CSS.registerProperty({\n        inherits: false,\n        initialValue: '0deg',\n        name: '--rainbow-angle',\n        syntax: '<angle>',\n      });\n    } catch {\n      // Already registered — safe to ignore\n    }\n  }\n\n  rainbowRegistered = true;\n}\n\n/**\n * Register the --shine-angle CSS custom property so browsers can\n * interpolate it inside conic-gradient().\n * Called automatically by shineEffectMixin on first use.\n */\nlet shineRegistered = false;\n\nexport function registerShineProperty() {\n  if (shineRegistered) return;\n\n  if (typeof CSS !== 'undefined' && CSS.registerProperty) {\n    try {\n      CSS.registerProperty({\n        inherits: false,\n        initialValue: '0deg',\n        name: '--shine-angle',\n        syntax: '<angle>',\n      });\n    } catch {\n      // Already registered — safe to ignore\n    }\n  }\n\n  shineRegistered = true;\n}\n\n/**\n * Rainbow Border Effect Mixin\n *\n * Animated rainbow border with glow effect.\n * Perfect for highlighting call-to-action elements or special features.\n *\n * @param selector - CSS selector for the element carrying the border, matched\n *   against the component's actual shadow DOM markup — a bare word like\n *   'button' is a TYPE selector (matches a literal `<button>` tag), not a\n *   part/class selector. Use the selector that actually matches your root\n *   element, e.g. `'.box'` for a `<div class=\"box\">`, or `'[part=\"button\"]'`\n *   for a `<span part=\"button\">`/`<a part=\"button\">` (ore-button's actual\n *   markup — it never renders a `<button>` tag).\n * @returns CSSResult with rainbow border animation\n *\n * @example\n * ```ts\n * import { rainbowEffectMixin } from '../../styles/effects/rainbow.css';\n *\n * return {\n *   styles: [rainbowEffectMixin('[part=\"button\"]'), componentStyles],\n *   template: html`...`\n * };\n * ```\n */\nexport const rainbowEffectMixin = (selector: string) => {\n  registerRainbowProperty();\n\n  return css`\n    /* ========================================\n       Rainbow Border Effect\n       ======================================== */\n\n    :host([effect='rainbow']) ${selector} {\n      position: relative;\n      border: var(--border-2) solid transparent !important;\n      overflow: visible;\n    }\n\n    /* Rainbow border and glow layers */\n    :host([effect='rainbow']) ${selector}::before, :host([effect='rainbow']) ${selector}::after {\n      content: '';\n      position: absolute;\n      inset: calc(-1 * var(--border-2));\n      border: inherit;\n      border-radius: inherit;\n\n      /* Reserve no-clip space for glow */\n      box-shadow: 0 0 calc(3 * var(--blur-xl)) rgba(0 0 0 / 0.001);\n\n      /* Rainbow gradient — Okabe-Ito colorblind-safe palette */\n      background: conic-gradient(\n          from var(--rainbow-angle),\n          #56b4e9,\n          /* Sky Blue       */ #0072b2,\n          /* Deep Blue      */ #009e73,\n          /* Bluish Green   */ #f0e442,\n          /* Yellow         */ #e69f00,\n          /* Orange         */ #d55e00,\n          /* Vermillion     */ #cc79a7,\n          /* Reddish Purple */ #56b4e9 /* Back to Sky Blue */\n        )\n        border-box;\n\n      /* Make everything inside padding-box transparent\n       by subtracting padding-box from no-clip box */\n      -webkit-mask:\n        conic-gradient(red 0 0) no-clip subtract,\n        conic-gradient(red 0 0) padding-box;\n      mask:\n        conic-gradient(red 0 0) no-clip subtract,\n        conic-gradient(red 0 0) padding-box;\n\n      pointer-events: none;\n      animation: rainbow-rotate 4s linear infinite;\n    }\n\n    /* Turn one pseudo layer into glow halo */\n    :host([effect='rainbow']) ${selector}::after {\n      filter: blur(var(--blur-xl));\n    }\n\n    /* ========================================\n       Animation\n       ======================================== */\n\n    @keyframes rainbow-rotate {\n      to {\n        --rainbow-angle: 1turn;\n      }\n    }\n\n    @media (prefers-reduced-motion: reduce) {\n      :host([effect='rainbow']) ${selector}::before, :host([effect='rainbow']) ${selector}::after {\n        animation: none;\n      }\n    }\n  `;\n};\n\n/**\n * Shine Border Effect Mixin\n *\n * Animated color-aware border shine. A tight arc of the component's own\n * theme color rotates around the border, producing the glossy \"shimmer\"\n * look seen in modern card and button designs.\n *\n * Respects the `color` attribute via `--_theme-*` tokens — no extra\n * configuration needed. Falls back to the neutral theme when no color\n * is set.\n *\n * @param selector - CSS selector for the inner element, matched against the\n *   component's actual shadow DOM markup — see rainbowEffectMixin's\n *   `selector` doc above for why a bare word like 'button' is usually wrong.\n * @returns CSSResult with shine border animation\n *\n * @example\n * ```ts\n * styles: [shineEffectMixin('[part=\"button\"]'), componentStyles]\n * ```\n */\nexport const shineEffectMixin = (selector: string) => {\n  registerShineProperty();\n\n  return css`\n    /* ========================================\n       Shine Border Effect\n       ======================================== */\n\n    :host([effect='shine']) ${selector} {\n      position: relative;\n      overflow: visible;\n      --_shine-color: light-dark(\n        oklch(from var(--_theme-focus) 0.6 calc(c * 1.2) h),\n        oklch(from var(--_theme-focus) 0.85 calc(c * 1.2) h)\n      );\n    }\n\n    /* Shine border — single pseudo, glow via box-shadow (follows border-radius, no artifacts) */\n    :host([effect='shine']) ${selector}::before {\n      content: '';\n      position: absolute;\n      inset: calc(-1 * var(--border-2));\n      border: var(--border-2) solid transparent;\n      border-radius: calc(var(--_radius, 0px) + var(--border-2));\n\n      /* Two comet tails 180deg apart, same shape rotating together */\n      background:\n        conic-gradient(from var(--shine-angle), transparent 0%, transparent 75%, var(--_shine-color) 100%) border-box,\n        conic-gradient(\n            from calc(var(--shine-angle) + 180deg),\n            transparent 0%,\n            transparent 75%,\n            var(--_shine-color) 100%\n          )\n          border-box;\n\n      -webkit-mask:\n        conic-gradient(red 0 0) no-clip subtract,\n        conic-gradient(red 0 0) padding-box;\n      mask:\n        conic-gradient(red 0 0) no-clip subtract,\n        conic-gradient(red 0 0) padding-box;\n\n      pointer-events: none;\n      animation: shine-rotate 2.5s linear infinite;\n    }\n\n    /* ========================================\n       Animation\n       ======================================== */\n\n    @keyframes shine-rotate {\n      to {\n        --shine-angle: 1turn;\n      }\n    }\n\n    @media (prefers-reduced-motion: reduce) {\n      :host([effect='shine']) ${selector}::before {\n        animation: none;\n      }\n    }\n  `;\n};\n","import { css } from '@vielzeug/ore';\n\nexport type FieldVariantMixinOptions = {\n  /**\n   * The theme accent custom property `flat`/`bordered` mix into their border color. Defaults to\n   * `--_theme-focus` (from `colorThemeMixin`). Override for a component with its own distinct\n   * focus/accent concept instead of the shared theme token (`ore-otp-input`'s `--_cell-focus-\n   * border`, which isn't theme-color-driven the same way).\n   */\n  accentVar?: string;\n  /** Selector for the element that gets the variant's background/border/shadow — the visual \"box\". */\n  container: string;\n  /**\n   * Selector for the text-bearing element the `bordered` variant tints to the theme color.\n   * Defaults to `container` for components where the box and the text-bearing element are the\n   * same node (`ore-input`/`ore-textarea`'s `.field`). Pass a distinct selector when they're\n   * split (`ore-message-composer`'s `.composer` card vs its bare `.field` textarea).\n   */\n  text?: string;\n  /** CSS custom-property namespace, e.g. `'input'` → `--input-bg`, `--input-hover-bg`, ... */\n  tokenPrefix: string;\n};\n\n/**\n * The `solid`/`flat`/`bordered`/`outline`/`ghost` variant switch shared by every text-entry\n * field component (`ore-input`, `ore-textarea`, `ore-message-composer`, `ore-otp-input`) —\n * previously hand-duplicated across them, mostly identically but not quite: this version also\n * uniformly adds a `:not([disabled])` guard to the `flat` variant's hover/focus rules (only\n * `ore-message-composer` had it) and the `bordered` variant's text/placeholder/caret tint\n * (`ore-input`/`ore-otp-input` were missing pieces of it) — clearly-unintentional per-component\n * gaps, not deliberate differences, so this mixin converges on the more complete behavior for\n * every consumer rather than picking one component's version arbitrarily.\n *\n * Deliberately does **not** touch `:focus-within` box-shadow for `solid`/`outline`/`ghost` —\n * every current consumer already covers that with its own single `:host(:not([disabled],\n * [variant='flat'], ...)) ${container}:focus-within` catch-all in its *own* base layer, so a\n * copy here would be pure redundancy for them, and actively wrong for `ore-otp-input`: its\n * `.cell` is the focusable element itself (not a wrapper), so `:focus-within` matches on every\n * keystroke, and it already renders its own bespoke ring (colored by `accentVar`, not\n * `--_theme-shadow`) uniformly across all variants in its base layer — this mixin adding a\n * second, generic one would fight it depending on layer/rule order.\n *\n * Each component keeps its own `:host(:not([variant], ...)) ${container}:hover/:focus-within`\n * base-state rules and any variant beyond this shared set (e.g. `ore-input`'s extra `'text'`\n * variant) in its own stylesheet — this mixin only covers the five variants every consumer has\n * in common.\n *\n * @example\n * ```ts\n * // ore-textarea / ore-input (box and text-bearing element are the same `.field`)\n * styles: [..., fieldVariantMixin({ container: '.field', tokenPrefix: 'textarea' }), componentStyles]\n *\n * // ore-message-composer (card `.composer` vs its own bare `.field` textarea)\n * styles: [\n *   ...,\n *   fieldVariantMixin({ container: '.composer', text: '.field', tokenPrefix: 'message-composer' }),\n *   componentStyles,\n * ]\n *\n * // ore-otp-input (own per-cell accent instead of the shared theme-focus token)\n * styles: [\n *   ...,\n *   fieldVariantMixin({ accentVar: '--_cell-focus-border', container: '.cell', tokenPrefix: 'otp-cell' }),\n *   componentStyles,\n * ]\n * ```\n */\nexport const fieldVariantMixin = ({\n  accentVar = '--_theme-focus',\n  container,\n  text = container,\n  tokenPrefix,\n}: FieldVariantMixinOptions) => css`\n  @layer refine.variants {\n    /* Solid (default) */\n    :host(:not([variant])),\n    :host([variant='solid']) {\n      --_bg: var(--${tokenPrefix}-bg, var(--color-contrast-50));\n      --_border-color: var(--${tokenPrefix}-border-color, var(--color-contrast-300));\n    }\n\n    :host(:not([variant])) ${container}, :host([variant='solid']) ${container} {\n      box-shadow: var(--shadow-2xs);\n    }\n\n    /* Flat */\n    :host([variant='flat']) {\n      --_bg: var(--${tokenPrefix}-bg, var(--color-contrast-100));\n      --_border-color: var(--${tokenPrefix}-border-color, color-mix(in oklch, var(${accentVar}) 20%, transparent));\n    }\n\n    :host([variant='flat']) ${container} {\n      box-shadow: var(--inset-shadow-2xs);\n    }\n\n    :host([variant='flat']:not([disabled])) ${container}:hover {\n      background: var(--${tokenPrefix}-hover-bg, color-mix(in oklch, var(--_theme-base) 6%, var(--color-contrast-100)));\n      border-color: var(\n        --${tokenPrefix}-hover-border-color,\n        color-mix(in oklch, var(--_theme-base) 35%, var(--color-contrast-300))\n      );\n    }\n\n    :host([variant='flat']:not([disabled])) ${container}:focus-within {\n      background: var(--${tokenPrefix}-focus-bg, color-mix(in oklch, var(--_theme-base) 8%, var(--color-canvas)));\n      border-color: var(--${tokenPrefix}-focus-border-color, color-mix(in oklch, var(${accentVar}) 60%, transparent));\n      box-shadow: var(--_theme-shadow);\n    }\n\n    /* Bordered */\n    :host([variant='bordered']) {\n      --_bg: var(--${tokenPrefix}-bg, var(--_theme-backdrop));\n      --_border-color: var(--${tokenPrefix}-border-color, color-mix(in oklch, var(${accentVar}) 70%, transparent));\n    }\n\n    :host([variant='bordered']:not([disabled])) ${container}:hover {\n      border-color: var(--${tokenPrefix}-hover-border-color, var(${accentVar}));\n    }\n\n    :host([variant='bordered']) ${text} {\n      color: var(--_theme-base);\n      caret-color: var(--_theme-base);\n    }\n\n    :host([variant='bordered']) ${text}::placeholder {\n      color: var(--${tokenPrefix}-placeholder-color, color-mix(in oklch, var(--_theme-base) 45%, transparent));\n    }\n\n    /* Outline — border always visible, so unlike the other variants it can't lean on a\n       per-component \\`:host{}\\` base fallback for \\`--_border-color\\` that may or may not exist\n       (\\`ore-message-composer\\` has none — every other rule here sets both custom properties, so\n       its base layer omits a default on the assumption that always holds). Set explicitly. */\n    :host([variant='outline']) {\n      --_bg: var(--${tokenPrefix}-bg, transparent);\n      --_border-color: var(--${tokenPrefix}-border-color, var(--color-contrast-300));\n    }\n\n    :host([variant='outline']) ${container} {\n      box-shadow: none;\n    }\n\n    /* Ghost */\n    :host([variant='ghost']) {\n      --_bg: var(--${tokenPrefix}-bg, transparent);\n      --_border-color: var(--${tokenPrefix}-border-color, transparent);\n    }\n\n    :host([variant='ghost']) ${container} {\n      box-shadow: none;\n    }\n\n    :host([variant='ghost']:not([disabled])) ${container}:hover {\n      background: var(--${tokenPrefix}-hover-bg, var(--color-contrast-100));\n    }\n  }\n`;\n","import { css } from '@vielzeug/ore';\n\n// ── Padding ───────────────────────────────────────────────────────────────────\n\n/**\n * Padding Variant Mixin\n *\n * Provides padding size variants (none, sm, md, lg, xl) via CSS custom properties.\n * Sets the --_padding variable based on padding attribute.\n *\n * @example\n * ```ts\n * import { paddingMixin } from '../../styles';\n *\n * return {\n *   styles: [paddingMixin, componentStyles],\n *   template: html`...`\n * };\n * ```\n */\nexport const paddingMixin = css`\n  /* ========================================\n     Padding Variants\n     ======================================== */\n\n  :host([padding='none']) {\n    --_padding: var(--size-0);\n  }\n\n  :host([padding='sm']) {\n    --_padding: var(--size-3);\n  }\n\n  :host([padding='md']) {\n    --_padding: var(--size-4);\n  }\n\n  :host([padding='lg']) {\n    --_padding: var(--size-6);\n  }\n\n  :host([padding='xl']) {\n    --_padding: var(--size-8);\n  }\n`;\n\n// ── Rounded ───────────────────────────────────────────────────────────────────\n\n/**\n * Rounded Variant Mixin\n *\n * Shared border-radius variant styles for components.\n * Maps rounded attribute values to theme border radius tokens.\n *\n * @example\n * ```ts\n * import { roundedVariantMixin } from '../../styles';\n *\n * return {\n *   styles: [roundedVariantMixin, componentStyles],\n *   template: html`...`\n * };\n * ```\n */\nexport const roundedVariantMixin = css`\n  :host([rounded='none']) {\n    --_radius: var(--rounded-none);\n  }\n  :host([rounded='sm']) {\n    --_radius: var(--rounded-sm);\n  }\n  :host([rounded='md']) {\n    --_radius: var(--rounded-md);\n  }\n  :host([rounded='lg']) {\n    --_radius: var(--rounded-lg);\n  }\n  :host([rounded='xl']) {\n    --_radius: var(--rounded-xl);\n  }\n  :host([rounded='2xl']) {\n    --_radius: var(--rounded-2xl);\n  }\n  :host([rounded='3xl']) {\n    --_radius: var(--rounded-3xl);\n  }\n  :host([rounded='full']),\n  :host([rounded='']) {\n    --_radius: var(--rounded-full);\n  }\n`;\n\n// ── Size Variants ─────────────────────────────────────────────────────────────\n\n/**\n * Size Variant Mixin\n *\n * Injects the three standard size tiers (sm / md / lg) as CSS custom property\n * blocks on `:host([size=\"…\"])`. Per-component overrides are supplied as a raw\n * CSS string for each tier and are appended after the shared defaults.\n *\n * All property names use the `--_` internal convention already established by\n * other mixins. The mapping is:\n *\n * | Config key   | CSS custom property  |\n * |------------- |----------------------|\n * | fontSize     | --_font-size         |\n * | gap          | --_gap               |\n * | height       | --_height            |\n * | iconSize     | --_icon-size         |\n * | lineHeight   | --_line-height       |\n * | padding      | --_padding           |\n * | size         | --_size              |\n * | thumbSize    | --_thumb-size        |\n * | width        | --_width             |\n * | --foo        | --foo (pass-through) |\n *\n * @example\n * ```ts\n * styles: [\n *   sizeVariantMixin({\n *     sm: { height: 'var(--size-8)', padding: 'var(--size-1-5) var(--size-3)' },\n *     lg: { height: 'var(--size-12)', padding: 'var(--size-2-5) var(--size-5)' },\n *   }),\n *   componentStyles,\n * ]\n * ```\n */\nexport type SizeConfig = {\n  /** Arbitrary CSS custom properties (must start with --) */\n  [key: `--${string}`]: string | undefined;\n  /** Font size — maps to --_font-size */\n  fontSize?: string;\n  /** Gap between elements — maps to --_gap */\n  gap?: string;\n  /** Element height — maps to --_height */\n  height?: string;\n  /** Icon size — maps to --_icon-size */\n  iconSize?: string;\n  /** Line height — maps to --_line-height */\n  lineHeight?: string;\n  /** Internal padding — maps to --_padding */\n  padding?: string;\n  /** Element size (width/height) — maps to --_size */\n  size?: string;\n  /** Thumb size (e.g. toggle/switch thumb) — maps to --_thumb-size */\n  thumbSize?: string;\n  /** Element width — maps to --_width */\n  width?: string;\n};\n\nconst PROP_MAP: Record<string, string> = {\n  fontSize: '--_font-size',\n  gap: '--_gap',\n  height: '--_height',\n  iconSize: '--_icon-size',\n  lineHeight: '--_line-height',\n  padding: '--_padding',\n  size: '--_size',\n  thumbSize: '--_thumb-size',\n  width: '--_width',\n};\n\nconst configToBlock = (config: SizeConfig): string =>\n  Object.entries(config)\n    .filter(([, v]) => v !== undefined)\n    .map(([k, v]) => `${k.startsWith('--') ? k : (PROP_MAP[k] ?? `--_${k}`)}: ${v};`)\n    .join('\\n        ');\n\nexport const sizeVariantMixin = (config?: { lg?: SizeConfig; md?: SizeConfig; sm?: SizeConfig }) => {\n  const sm = configToBlock({\n    fontSize: 'var(--text-xs)',\n    gap: 'var(--size-1-5)',\n    size: 'var(--size-4)',\n    ...config?.sm,\n  });\n  const md = configToBlock({\n    fontSize: 'var(--text-sm)',\n    gap: 'var(--size-2)',\n    size: 'var(--size-5)',\n    ...config?.md,\n  });\n  const lg = configToBlock({\n    fontSize: 'var(--text-base)',\n    gap: 'var(--size-2-5)',\n    size: 'var(--size-6)',\n    ...config?.lg,\n  });\n\n  return css`\n    :host {\n      ${md}\n    }\n    :host([size='sm']) {\n      ${sm}\n    }\n    :host([size='md']) {\n      ${md}\n    }\n    :host([size='lg']) {\n      ${lg}\n    }\n  `;\n};\n","import { css } from '@vielzeug/ore';\n\n/**\n * Disabled State Mixin\n *\n * Reduces opacity and shows `not-allowed` cursor on the host.\n * `pointer-events: none` is placed on the inner slot so the host stays\n * hoverable (e.g. for tooltips that explain why the control is disabled).\n */\nexport const disabledStateMixin = css`\n  :host([disabled]) {\n    opacity: 0.5;\n    cursor: not-allowed;\n  }\n\n  :host([disabled]) ::slotted(*),\n  :host([disabled]) > :not(slot) {\n    pointer-events: none;\n  }\n`;\n\n/**\n * Loading State Mixin\n *\n * Shows `wait` cursor on the host; blocks pointer events on inner content.\n */\nexport const loadingStateMixin = css`\n  :host([loading]) {\n    opacity: 0.5;\n    cursor: wait;\n  }\n\n  :host([loading]) ::slotted(*),\n  :host([loading]) > :not(slot) {\n    pointer-events: none;\n  }\n`;\n\n/**\n * Combined Disabled & Loading State Mixin\n *\n * Convenience mixin combining both disabled and loading host states.\n * Use for most interactive components that support both attributes.\n *\n * - Host receives the correct cursor (not-allowed / wait) and remains\n *   hoverable so external tooltip wrappers can still fire pointer events.\n * - Inner shadow-DOM children have pointer-events disabled so they refuse\n *   clicks while the host cursor signal is still visible.\n */\nexport const disabledLoadingMixin = css`\n  :host([disabled]),\n  :host([loading]) {\n    opacity: 0.5;\n    cursor: not-allowed;\n  }\n\n  :host([loading]) {\n    cursor: wait;\n  }\n\n  :host([disabled]) > :not(slot),\n  :host([loading]) > :not(slot) {\n    pointer-events: none;\n  }\n`;\n","import { css } from '@vielzeug/ore';\n\n/**\n * Table Base Mixin\n *\n * Shared structural foundation for table-like components (`ore-table`, `ore-datagrid`).\n * Covers only the `:host` shell, `.scroll-container`, and the bare `table` element.\n * Each consumer component owns all cell, row, head, and footer styles itself.\n *\n * Token naming:\n *  - `--_accent`   Primary interactive accent (sort icons, selection borders, focus rings).\n *                  Defaults to `--color-primary-focus`. Override via `--{prefix}-accent`.\n *\n * @param prefix  CSS custom-property namespace, e.g. `'table'` or `'datagrid'`\n *\n * @example\n * ```ts\n * // ore-table\n * styles: [tableBaseMixin('table'), componentStyles]\n *\n * // ore-datagrid\n * styles: [tableBaseMixin('datagrid'), componentStyles]\n * ```\n */\nexport const tableBaseMixin = (prefix: string) => css`\n  @layer refine.base {\n    :host {\n      /* ── Public token API ─────────────────────────────────────────────── */\n      --_bg: var(--${prefix}-bg, var(--color-canvas));\n      --_border-color: var(--${prefix}-border-color, var(--color-contrast-200));\n      --_radius: var(--${prefix}-radius, var(--rounded-xl));\n      --_header-bg: var(--${prefix}-header-bg, var(--color-contrast-50));\n      --_accent: var(--${prefix}-accent, var(--color-neutral-focus));\n      --_row-hover-bg: var(--${prefix}-row-hover-bg, color-mix(in oklch, var(--_accent) 6%, transparent));\n      --_stripe-bg: var(--${prefix}-stripe-bg, color-mix(in oklch, var(--color-contrast-900) 3%, transparent));\n      --_cell-padding-x: var(--${prefix}-cell-padding-x, var(--size-3));\n      --_cell-padding-y: var(--${prefix}-cell-padding-y, var(--size-2-5));\n      --_font-size: var(--${prefix}-font-size, var(--text-sm));\n\n      display: block;\n      overflow: hidden;\n      background: var(--_bg);\n      border: var(--border) solid var(--_border-color);\n      border-radius: var(--_radius);\n      box-shadow: var(--${prefix}-shadow, var(--shadow-sm));\n    }\n\n    /* ── Scroll wrapper ─────────────────────────────────────────────────── */\n\n    .scroll-container {\n      overflow: auto;\n      max-height: var(--${prefix}-max-height, none);\n    }\n\n    /* ── Native table ───────────────────────────────────────────────────── */\n\n    table {\n      width: 100%;\n      font-size: var(--_font-size);\n      table-layout: auto;\n      border-collapse: collapse;\n      background: var(--_bg);\n    }\n\n    /* ── Loading state ──────────────────────────────────────────────────── */\n\n    :host([loading]) .scroll-container {\n      opacity: 0.5;\n      pointer-events: none;\n      cursor: wait;\n    }\n  }\n\n  @layer refine.variants {\n    /* Bordered */\n    :host([bordered]) {\n      overflow: hidden;\n      border: var(--border) solid var(--_border-color);\n      border-radius: var(--_radius);\n      box-shadow: var(--shadow-xs);\n    }\n\n    :host([bordered]) .scroll-container {\n      border-radius: inherit;\n      clip-path: inset(0 round var(--_radius));\n    }\n\n    /* Sticky header */\n    :host([sticky]) .scroll-container {\n      max-height: var(--${prefix}-sticky-max-height, 24rem);\n      overflow-y: auto;\n    }\n  }\n\n  @layer refine.density {\n    :host([density='compact']) {\n      --_cell-padding-x: var(--size-2);\n      --_cell-padding-y: var(--size-1-5);\n    }\n\n    :host([density='cozy']) {\n      --_cell-padding-x: var(--size-3);\n      --_cell-padding-y: var(--size-2-5);\n    }\n\n    :host([density='comfortable']) {\n      --_cell-padding-x: var(--size-4);\n      --_cell-padding-y: var(--size-3-5);\n    }\n  }\n\n  @layer refine.overrides {\n    :host([fullwidth]) {\n      width: 100%;\n    }\n  }\n`;\n","import { css } from '@vielzeug/ore';\n\n// ── Color Theme ───────────────────────────────────────────────────────────────\n\nconst THEME_COLORS = ['primary', 'secondary', 'info', 'success', 'warning', 'error'] as const;\n\ntype ThemeColorName = (typeof THEME_COLORS)[number];\n\n// Standard token suffix for each --_theme-* variable. The 'shadow' slot maps\n// to --color-*-focus-shadow (not --color-*-shadow) and 'halo' maps to --halo-shadow-*.\nconst TOKEN_SUFFIX: Record<string, (color: ThemeColorName) => string> = {\n  backdrop: (c) => `var(--color-${c}-backdrop)`,\n  base: (c) => `var(--color-${c})`,\n  border: (c) => `var(--color-${c}-border)`,\n  content: (c) => `var(--color-${c}-content)`,\n  contrast: (c) => `var(--color-${c}-contrast)`,\n  focus: (c) => `var(--color-${c}-focus)`,\n  halo: (c) => `var(--halo-shadow-${c})`,\n  shadow: (c) => `var(--color-${c}-focus-shadow)`,\n};\n\nconst colorBlock = (color: ThemeColorName): string =>\n  `:host([color='${color}']) {\\n${Object.entries(TOKEN_SUFFIX)\n    .map(([slot, fn]) => `  --_theme-${slot}: ${fn(color)};`)\n    .join('\\n')}\\n}`;\n\nexport const colorThemeMixin = css`\n  :host {\n    --_theme-base: var(--color-neutral);\n    --_theme-content: var(--color-neutral-content);\n    --_theme-contrast: var(--color-neutral-contrast);\n    --_theme-focus: var(--color-neutral-focus);\n    --_theme-backdrop: var(--color-neutral-backdrop);\n    --_theme-border: var(--color-neutral-border);\n    --_theme-shadow: var(--color-neutral-focus-shadow);\n    --_theme-halo: var(--halo-shadow-neutral);\n  }\n\n  ${THEME_COLORS.map(colorBlock).join('\\n\\n  ')}\n`;\n\n// ── Elevation ─────────────────────────────────────────────────────────────────\n\n/**\n * Elevation Mixin\n *\n * Provides elevation shadow levels (0-5) via CSS custom properties.\n * Sets the --_shadow variable based on elevation attribute.\n *\n * @example\n * ```ts\n * import { elevationMixin } from '../../styles';\n *\n * return {\n *   styles: [elevationMixin, componentStyles],\n *   template: html`...`\n * };\n * ```\n */\nexport const elevationMixin = css`\n  /* ========================================\n     Elevation Levels (0-5)\n     ======================================== */\n\n  :host([elevation='0']) {\n    --_shadow: none;\n  }\n\n  :host([elevation='1']) {\n    --_shadow: var(--shadow-sm);\n  }\n\n  :host([elevation='2']) {\n    --_shadow: var(--shadow-md);\n  }\n\n  :host([elevation='3']) {\n    --_shadow: var(--shadow-lg);\n  }\n\n  :host([elevation='4']) {\n    --_shadow: var(--shadow-xl);\n  }\n\n  :host([elevation='5']) {\n    --_shadow: var(--shadow-2xl);\n  }\n`;\n\n// ── Forced Colors ─────────────────────────────────────────────────────────────\n\n/**\n * Forced Colors Mixin\n *\n * Ensures components are visually distinct in Windows High Contrast / forced-colors mode.\n * The browser already overrides `color`, `background-color`, and `border-color` to system\n * color keywords, but components that rely solely on `background` for visual identity\n * (no border) or that use `box-shadow` for focus rings need explicit fallbacks.\n *\n * Usage: apply to any component that has a background but no natural border.\n *\n * @example\n * ```ts\n * import { forcedColorsMixin } from '../../styles';\n *\n * return {\n *   styles: [forcedColorsMixin, componentStyles],\n *   template: html`...`\n * };\n * ```\n */\nexport const forcedColorsMixin = css`\n  @media (forced-colors: active) {\n    :host {\n      border: 1px solid ButtonText;\n    }\n  }\n`;\n\n/**\n * Forced Colors Focus Ring Mixin\n *\n * Replaces box-shadow focus rings (which are removed in forced-colors mode)\n * with a proper system-color outline.\n *\n * @param selector - CSS selector for the focusable element inside the host\n *\n * @example\n * ```ts\n * import { forcedColorsFocusMixin } from '../../styles';\n *\n * return {\n *   styles: [forcedColorsFocusMixin('button'), componentStyles],\n *   template: html`...`\n * };\n * ```\n */\nexport const forcedColorsFocusMixin = (selector: string) => css`\n  @media (forced-colors: active) {\n    ${selector}:focus-visible {\n      outline: 2px solid Highlight;\n      outline-offset: 2px;\n      box-shadow: none;\n    }\n  }\n`;\n\n/**\n * Forced Colors Form Control Mixin\n *\n * For custom form controls (checkbox, radio, switch, slider) that paint their\n * own visual state. Maps checked/active state to system colors so they remain\n * distinguishable in forced-colors mode.\n *\n * @example\n * ```ts\n * import { forcedColorsFormControlMixin } from '../../styles';\n *\n * return {\n *   styles: [forcedColorsFormControlMixin, componentStyles],\n *   template: html`...`\n * };\n * ```\n */\nexport const forcedColorsFormControlMixin = css`\n  @media (forced-colors: active) {\n    :host {\n      forced-color-adjust: none;\n      color: ButtonText;\n      background: ButtonFace;\n      border: 1px solid ButtonText;\n    }\n\n    :host([checked]) {\n      background: Highlight;\n      color: HighlightText;\n      border-color: Highlight;\n    }\n\n    :host([disabled]) {\n      color: GrayText;\n      border-color: GrayText;\n    }\n  }\n`;\n","import { css } from '@vielzeug/ore';\n\n/**\n * Frost Variant Mixin\n *\n * Shared frost variant styles for components.\n * Provides consistent frosted glass effect with backdrop blur,\n * theme-aware colors, halo shadows, and elevation support.\n *\n * @param selector - CSS selector for the element, matched against the\n *   component's actual shadow DOM markup (e.g., '.card', '.field') — a bare\n *   word like 'button' is a TYPE selector for a literal `<button>` tag, not\n *   a part/class selector. Use `'[part=\"button\"]'` for components whose root\n *   is a `<span part=\"button\">`/`<a part=\"button\">` (e.g. ore-button, which\n *   never renders a `<button>` tag).\n * @returns CSSResult with complete frost variant implementation\n *\n * @example\n * ```ts\n * import { frostVariantMixin } from '../../styles/mixins/frost.css';\n *\n * return {\n *   styles: [frostVariantMixin('[part=\"button\"]'), componentStyles],\n *   template: html`...`\n * };\n * ```\n */\nexport const frostVariantMixin = (selector: string) => css`\n  :host([variant='frost']) ${selector} {\n    backdrop-filter: blur(var(--blur-xl)) saturate(200%) brightness(1.1);\n    -webkit-backdrop-filter: blur(var(--blur-xl)) saturate(200%) brightness(1.1);\n  }\n\n  :host([variant='frost']:not([color])) ${selector} {\n    background: color-mix(in oklch, var(--color-canvas) 55%, transparent);\n    color: var(--color-contrast);\n    text-shadow: var(--text-shadow-xs);\n    border: var(--border) solid color-mix(in oklch, var(--color-contrast-400) 45%, transparent);\n  }\n\n  /* Frost neutral without elevation: use halo shadow */\n  :host([variant='frost']:not([color]):not([elevation])) ${selector} {\n    box-shadow: var(--halo-shadow-neutral);\n  }\n\n  /* Frost neutral with elevation: combine halo with elevation shadow */\n  :host([variant='frost']:not([color])[elevation]) ${selector} {\n    box-shadow: var(--halo-shadow-neutral), var(--_shadow);\n  }\n\n  :host([variant='frost'][color]) ${selector} {\n    background: color-mix(in oklch, var(--_theme-base), transparent);\n    border-color: color-mix(in oklch, var(--_theme-border) 45%, transparent);\n    color: var(--_theme-content);\n    border: var(--border) solid color-mix(in oklch, var(--_theme-border) 45%, transparent);\n    backdrop-filter: blur(var(--blur-2xl)) saturate(220%) brightness(1.15);\n    -webkit-backdrop-filter: blur(var(--blur-2xl)) saturate(220%) brightness(1.15);\n    text-shadow: var(--text-shadow-xs);\n    filter: brightness(1.05);\n  }\n\n  /* Frost color without elevation: use halo shadow */\n  :host([variant='frost'][color]:not([elevation])) ${selector} {\n    box-shadow: var(--_theme-halo);\n  }\n\n  /* Frost color with elevation: combine halo with elevation shadow */\n  :host([variant='frost'][color][elevation]) ${selector} {\n    box-shadow: var(--_theme-halo), var(--_shadow);\n  }\n\n  :host([variant='frost']:not([color])) ${selector}:hover {\n    backdrop-filter: blur(var(--blur-2xl)) saturate(220%) brightness(1.15);\n    -webkit-backdrop-filter: blur(var(--blur-2xl)) saturate(220%) brightness(1.15);\n  }\n\n  :host([variant='frost'][color]) ${selector}:hover {\n    backdrop-filter: blur(var(--blur-3xl)) saturate(240%) brightness(1.2);\n    -webkit-backdrop-filter: blur(var(--blur-3xl)) saturate(240%) brightness(1.2);\n  }\n`;\n","@layer refine.base {\n  :host {\n    --_bg: var(--avatar-bg, var(--_theme-backdrop, var(--color-contrast-200)));\n    --_color: var(--avatar-color, var(--_theme-base, var(--color-contrast-700)));\n    --_radius: var(--avatar-radius, var(--rounded-full));\n    --_font-weight: var(--avatar-font-weight, var(--font-semibold));\n    --_border: var(--avatar-border, none);\n    --_border-color: var(--avatar-border-color, var(--color-canvas));\n    --_size: var(--avatar-size, var(--size-10));\n    --_font-size: var(--avatar-font-size, var(--text-sm));\n\n    position: relative;\n    display: inline-flex;\n    flex-shrink: 0;\n  }\n\n  .avatar {\n    box-sizing: border-box;\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    width: var(--_size);\n    height: var(--_size);\n    overflow: hidden;\n    font-size: var(--_font-size);\n    font-weight: var(--_font-weight);\n    line-height: 1;\n    color: var(--_color);\n    text-transform: uppercase;\n    user-select: none;\n    background: var(--_bg);\n    border: var(--_border);\n    border-color: var(--_border-color);\n    border-radius: var(--_radius);\n  }\n\n  img {\n    display: block;\n    width: 100%;\n    height: 100%;\n    object-fit: cover;\n  }\n\n  img[hidden] {\n    display: none;\n  }\n\n  .initials {\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    width: 100%;\n    height: 100%;\n  }\n\n  .icon-fallback {\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    width: 100%;\n    height: 100%;\n    color: var(--_color);\n    opacity: 0.6;\n  }\n\n  .status {\n    position: absolute;\n    inset-inline-end: 0;\n    bottom: 0;\n    width: 0.75em;\n    height: 0.75em;\n    border: 2px solid var(--_border-color, var(--color-canvas));\n    border-radius: var(--rounded-full);\n  }\n\n  .status[data-status='online'] {\n    background: var(--color-success);\n  }\n\n  .status[data-status='offline'] {\n    background: var(--color-contrast-400);\n  }\n\n  .status[data-status='busy'] {\n    background: var(--color-error);\n  }\n\n  .status[data-status='away'] {\n    background: var(--color-warning);\n  }\n}\n\n/* forcedColorsMixin targets :host; avatar needs the border on .avatar (different geometry),\n     so forced-color rules are kept inline and unlayered to match mixin convention. */\n@media (forced-colors: active) {\n  .avatar {\n    forced-color-adjust: none;\n    border: 1px solid ButtonText;\n  }\n\n  .status {\n    background: Highlight;\n    border: 2px solid ButtonText;\n  }\n}\n","import { define, html, prop } from '@vielzeug/ore';\nimport { computed, signal, watch } from '@vielzeug/ripple';\n\nimport type { ComponentSize, RoundedSize, ThemeColor } from '../../types';\n\nimport '../icon/icon';\nimport { roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, roundedVariantMixin, sizeVariantMixin } from '../../styles';\nimport componentStyles from './avatar.css?inline';\n\nexport type AvatarStatus = 'online' | 'offline' | 'busy' | 'away';\n\nconst STATUS_LABELS: Record<AvatarStatus, string> = {\n  away: 'Away',\n  busy: 'Busy',\n  offline: 'Offline',\n  online: 'Online',\n};\n\n/** Avatar component properties */\nexport type OreAvatarProps = {\n  /** Alt text for the image; also used to derive initials when no `initials` prop is given */\n  alt?: string;\n  /** Theme color (used for initials background) */\n  color?: ThemeColor;\n  /** Explicit initials to display when no image is available (e.g. \"JD\") */\n  initials?: string;\n  /** Border radius */\n  rounded?: RoundedSize | '';\n  /** Component size */\n  size?: ComponentSize;\n  /** Image source URL */\n  src?: string;\n  /** Online presence indicator */\n  status?: AvatarStatus;\n};\n\n/**\n * Displays a user avatar: image → initials → generic fallback icon, in that priority order.\n *\n * @element ore-avatar\n *\n * @attr {string} src - Image source URL\n * @attr {string} alt - Image alt text (also used to derive initials)\n * @attr {string} initials - Explicit initials (up to 2 chars)\n * @attr {string} color - Theme color for initials background: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {string} status - 'online' | 'offline' | 'busy' | 'away'\n *\n * @slot - Fallback content shown when image and initials are unavailable.\n * @cssprop --avatar-size - Diameter of the avatar\n * @cssprop --avatar-bg - Background color\n * @cssprop --avatar-color - Text/icon color\n * @cssprop --avatar-radius - Border radius\n * @cssprop --avatar-border - Border shorthand\n * @cssprop --avatar-border-color - Border color (also controls status dot border)\n *\n * @part avatar - Avatar root container.\n * @part img - Image element.\n * @part initials - Initials fallback element.\n * @part fallback - Shadow part for the `fallback` element.\n * @part status - Status indicator element.\n * @part overflow - Overflow indicator element.\n * @example\n * ```html\n * <ore-avatar src=\"/jane.jpg\" alt=\"Jane Doe\"></ore-avatar>\n * <ore-avatar initials=\"JD\" color=\"primary\"></ore-avatar>\n * <ore-avatar alt=\"John Smith\" status=\"online\"></ore-avatar>\n * ```\n */\nexport const AVATAR_TAG = 'ore-avatar' as const;\ndefine<OreAvatarProps>(AVATAR_TAG, {\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...roundableBundle,\n    alt: prop.string(),\n    initials: prop.string(),\n    src: prop.string(),\n    status: prop.string<AvatarStatus>(),\n  },\n  setup(props) {\n    const imgFailed = signal(false);\n\n    // Reset stale error state whenever src changes\n    watch(props.src, () => {\n      imgFailed.value = false;\n    });\n\n    // Attach load/error listeners reactively when the img element mounts\n    const attachImgListeners = (el: HTMLImageElement | null) => {\n      if (!el) return;\n\n      el.addEventListener('error', () => {\n        imgFailed.value = true;\n      });\n      el.addEventListener('load', () => {\n        imgFailed.value = false;\n      });\n    };\n    const derivedInitials = computed(() => {\n      if (props.initials.value) return props.initials.value.slice(0, 2);\n\n      const alt = props.alt.value;\n\n      if (!alt) return '';\n\n      const parts = alt.trim().split(/\\s+/);\n\n      if (parts.length >= 2) return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();\n\n      return parts[0].slice(0, 2).toUpperCase();\n    });\n    const showImage = computed(() => !!props.src.value && !imgFailed.value);\n    const showInitials = computed(() => !showImage.value && !!derivedInitials.value);\n    const showFallback = computed(() => !showImage.value && !showInitials.value);\n    const avatarLabel = () => {\n      const name = (props.alt.value as string | undefined) || null;\n      const statusKey = props.status.value as AvatarStatus | undefined;\n      const status = statusKey ? STATUS_LABELS[statusKey] : null;\n\n      if (!name && !status) return null;\n\n      if (!name) return `Status: ${status}`;\n\n      if (!status) return name;\n\n      return `${name}, ${status}`;\n    };\n    const avatarRole = () => (avatarLabel() ? 'img' : null);\n\n    return html`\n      <span class=\"avatar\" part=\"avatar\" aria-label=\"${avatarLabel}\" role=\"${avatarRole}\">\n        ${() =>\n          props.src.value\n            ? html`\n                <img\n                  ref=\"${attachImgListeners}\"\n                  part=\"img\"\n                  src=\"${props.src}\"\n                  alt=\"${props.alt}\"\n                  ?hidden=\"${() => !showImage.value}\"\n                  aria-hidden=\"true\" />\n              `\n            : ''}\n        ${() =>\n          showInitials.value\n            ? html`\n                <span class=\"initials\" part=\"initials\" aria-hidden=\"true\">${derivedInitials}</span>\n              `\n            : ''}\n        ${() =>\n          showFallback.value\n            ? html`\n                <ore-icon class=\"icon-fallback\" part=\"fallback\" name=\"user\" size=\"50%\"></ore-icon>\n              `\n            : ''}\n      </span>\n      ${() =>\n        props.status.value\n          ? html`\n              <span class=\"status\" part=\"status\" data-status=\"${props.status}\" aria-hidden=\"true\"></span>\n            `\n          : ''}\n    `;\n  },\n  styles: [\n    colorThemeMixin,\n    roundedVariantMixin,\n    sizeVariantMixin({\n      lg: { fontSize: 'var(--avatar-font-size, var(--text-base))', size: 'var(--avatar-size, var(--size-14))' },\n      md: { fontSize: 'var(--avatar-font-size, var(--text-sm))', size: 'var(--avatar-size, var(--size-10))' },\n      sm: { fontSize: 'var(--avatar-font-size, var(--text-xs))', size: 'var(--avatar-size, var(--size-7))' },\n    }),\n    componentStyles,\n  ],\n});\n","@layer refine.base {\n  :host {\n    display: inline-flex;\n    flex-direction: row;\n  }\n\n  /* Overlap avatars, latest first */\n  ::slotted(ore-avatar) {\n    --avatar-border: var(--border-2) solid var(--color-canvas);\n\n    margin-left: calc(var(--avatar-group-overlap, -0.75rem));\n  }\n\n  ::slotted(ore-avatar:first-child) {\n    margin-left: 0;\n  }\n\n  :host([dir='rtl']) ::slotted(ore-avatar),\n  :host(:dir(rtl)) ::slotted(ore-avatar) {\n    margin-right: calc(var(--avatar-group-overlap, -0.75rem));\n    margin-left: 0;\n  }\n\n  :host([dir='rtl']) ::slotted(ore-avatar:first-child),\n  :host(:dir(rtl)) ::slotted(ore-avatar:first-child) {\n    margin-right: 0;\n  }\n\n  ::slotted(ore-avatar[data-avatar-group-hidden]) {\n    display: none;\n  }\n\n  .overflow-badge {\n    --_size: var(--avatar-size, var(--size-10));\n\n    box-sizing: border-box;\n    display: inline-flex;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    width: var(--_size);\n    height: var(--_size);\n    margin-left: calc(var(--avatar-group-overlap, -0.75rem));\n    font-size: var(--text-xs);\n    font-weight: var(--font-semibold);\n    color: var(--color-contrast-700);\n    user-select: none;\n    background: var(--color-contrast-200);\n    border: var(--border-2) solid var(--color-canvas);\n    border-radius: var(--rounded-full);\n  }\n\n  :host([dir='rtl']) .overflow-badge,\n  :host(:dir(rtl)) .overflow-badge {\n    margin-right: calc(var(--avatar-group-overlap, -0.75rem));\n    margin-left: 0;\n  }\n}\n","import { define, getHost, html, prop, useSlots, watchEffect } from '@vielzeug/ore';\nimport { signal } from '@vielzeug/ripple';\n\nimport componentStyles from './avatar-group.css?inline';\n\n/** AvatarGroup component properties */\nexport type OreAvatarGroupProps = {\n  /** Maximum number of avatars to show before showing a +N badge */\n  max?: number;\n  /** Total count shown in the overflow badge (defaults to the actual hidden count) */\n  total?: number;\n};\n\n/**\n * Groups multiple `ore-avatar` elements in a stacked, overlapping row.\n *\n * @element ore-avatar-group\n *\n * @attr {number} max - Max visible avatars before overflow badge (default: 5)\n * @attr {number} total - Override the total count displayed in the badge\n *\n * @slot - `ore-avatar` elements\n *\n * @cssprop --avatar-group-overlap - Negative margin creating the overlap (default: -0.75rem)\n *\n * @part overflow - Overflow count badge shown when avatars exceed `max`.\n *\n * @example\n * ```html\n * <ore-avatar-group max=\"3\">\n *   <ore-avatar src=\"/a.jpg\" alt=\"Alice\"></ore-avatar>\n *   <ore-avatar src=\"/b.jpg\" alt=\"Bob\"></ore-avatar>\n *   <ore-avatar src=\"/c.jpg\" alt=\"Carol\"></ore-avatar>\n *   <ore-avatar src=\"/d.jpg\" alt=\"Dave\"></ore-avatar>\n * </ore-avatar-group>\n * ```\n */\nexport const AVATAR_GROUP_TAG = 'ore-avatar-group' as const;\ndefine<OreAvatarGroupProps>(AVATAR_GROUP_TAG, {\n  props: {\n    max: prop.number(5),\n    total: prop.number(),\n  },\n  setup(props) {\n    const el = getHost();\n    const slots = useSlots();\n    const watch = watchEffect;\n\n    const overflowCount = signal(0);\n\n    const updateVisibility = () => {\n      const avatars = [...el.querySelectorAll('ore-avatar')];\n      const max = Number(props.max.value) || 5;\n      const hidden = Math.max(0, avatars.length - max);\n\n      overflowCount.value = props.total.value != null ? Number(props.total.value) - max : hidden;\n      avatars.forEach((a, i) => {\n        if (i >= max) a.setAttribute('data-avatar-group-hidden', '');\n        else a.removeAttribute('data-avatar-group-hidden');\n      });\n    };\n\n    watch(() => {\n      void slots.elements().value;\n      updateVisibility();\n    });\n\n    const overflowLabel = () => `+${overflowCount.value} more`;\n    const overflowText = () => `+${overflowCount.value}`;\n\n    return html`\n      <slot></slot>\n      ${() =>\n        overflowCount.value > 0\n          ? html`\n              <span class=\"overflow-badge\" part=\"overflow\" aria-label=\"${overflowLabel}\">${overflowText}</span>\n            `\n          : ''}\n    `;\n  },\n  styles: [componentStyles],\n});\n","@layer refine.base {\n  :host {\n    display: block;\n  }\n\n  nav {\n    display: block;\n  }\n\n  ol {\n    display: flex;\n    flex-wrap: wrap;\n    gap: 0;\n    align-items: center;\n    padding: 0;\n    margin: 0;\n    list-style: none;\n  }\n}\n","@layer refine.base {\n  :host {\n    display: inline-flex;\n    align-items: center;\n  }\n\n  .item {\n    display: inline-flex;\n    align-items: center;\n  }\n\n  .separator {\n    display: none;\n    padding-inline: var(--size-2);\n    font-size: var(--text-sm);\n    font-weight: var(--font-normal);\n    color: var(--color-contrast-400);\n  }\n\n  :host([data-show-separator]) .separator {\n    display: inline-block;\n  }\n\n  .link {\n    display: inline-flex;\n    gap: var(--size-1);\n    align-items: center;\n    font-size: var(--text-sm);\n    font-weight: var(--font-medium);\n    color: var(--color-contrast-600);\n    text-decoration: none;\n    outline-offset: 2px;\n    border-radius: var(--rounded-lg);\n    transition: color var(--transition-fast);\n  }\n\n  .link:hover {\n    color: var(--color-contrast-900);\n    text-decoration: underline;\n  }\n\n  .link:focus-visible {\n    outline: var(--border-2) solid currentcolor;\n    outline-offset: var(--border-2);\n  }\n\n  :host([active]) .link {\n    font-weight: var(--font-semibold);\n    color: var(--color-contrast-900);\n    text-decoration: none;\n    pointer-events: none;\n  }\n\n  /* Icon slot */\n  .icon {\n    display: contents;\n  }\n\n  .label {\n    min-width: 0;\n    max-width: var(--breadcrumb-item-max-width, 20ch);\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n  }\n}\n","import { define, getHost, html, prop, useSlots, watchEffect } from '@vielzeug/ore';\nimport componentStyles from './breadcrumb.css?inline';\nimport itemStyles from './breadcrumb-item.css?inline';\n\nexport type OreBreadcrumbProps = {\n  label?: string;\n  separator?: string;\n};\n\nexport type OreBreadcrumbItemProps = {\n  active?: boolean;\n  href?: string;\n  separator?: string;\n};\n\n/**\n * A single breadcrumb entry rendered inside `<ore-breadcrumb>`.\n *\n * @element ore-breadcrumb-item\n *\n * @attr {boolean} active - Marks this item as the current page (`aria-current=\"page\"`)\n * @attr {string} href - Link target for this breadcrumb item\n * @attr {string} separator - Separator text shown before the item (except first item)\n *\n * @slot - Item label/content\n * @slot icon - Optional leading icon for the crumb\n *\n * @part separator - Separator element before the item label\n * @part link - The interactive anchor element\n *\n * @example\n * ```html\n * <ore-breadcrumb-item href=\"/\">Home</ore-breadcrumb-item>\n * <ore-breadcrumb-item active>Current Page</ore-breadcrumb-item>\n * ```\n */\nexport const BREADCRUMB_ITEM_TAG = 'ore-breadcrumb-item' as const;\ndefine<OreBreadcrumbItemProps>(BREADCRUMB_ITEM_TAG, {\n  props: {\n    active: prop.bool(),\n    href: prop.string(),\n    separator: prop.string('/'),\n  },\n  setup(props) {\n    return html`\n      <li class=\"item\" role=\"listitem\">\n        <span class=\"separator\" part=\"separator\" aria-hidden=\"true\">${props.separator}</span>\n        <a\n          class=\"link\"\n          href=\"${props.href}\"\n          aria-current=\"${() => (props.active.value ? 'page' : null)}\"\n          tabindex=\"${() => (props.active.value ? '-1' : null)}\"\n          part=\"link\">\n          <span class=\"icon\"><slot name=\"icon\"></slot></span>\n          <span class=\"label\"><slot></slot></span>\n        </a>\n      </li>\n    `;\n  },\n  styles: [itemStyles],\n});\n\n// ============================================\n// Breadcrumb Component\n// ============================================\n\n/**\n * Accessible breadcrumb navigation container.\n *\n * @element ore-breadcrumb\n *\n * @attr {string} label - Accessible label for the internal `<nav>` landmark\n * @attr {string} separator - Separator text propagated to child `<ore-breadcrumb-item>` elements\n *\n * @slot - One or more `<ore-breadcrumb-item>` children\n *\n * @part nav - Internal navigation landmark element\n * @part list - Internal ordered list container\n *\n * @cssprop --breadcrumb-separator - Optional custom separator text synced to child items\n *\n * @example\n * ```html\n * <ore-breadcrumb label=\"Page breadcrumb\">\n *   <ore-breadcrumb-item href=\"/\">Home</ore-breadcrumb-item>\n *   <ore-breadcrumb-item href=\"/blog\">Blog</ore-breadcrumb-item>\n *   <ore-breadcrumb-item active>My Post</ore-breadcrumb-item>\n * </ore-breadcrumb>\n * ```\n */\nexport const BREADCRUMB_TAG = 'ore-breadcrumb' as const;\ndefine<OreBreadcrumbProps>(BREADCRUMB_TAG, {\n  props: {\n    label: prop.string('Breadcrumb'),\n    separator: prop.string(),\n  },\n  setup(props) {\n    const el = getHost();\n    const slots = useSlots();\n    const watch = watchEffect;\n\n    // ────────────────────────────────────────────────────────────────\n    // Item & Separator Synchronization\n    // ────────────────────────────────────────────────────────────────\n\n    const getItems = (): HTMLElement[] => Array.from(el.getElementsByTagName('ore-breadcrumb-item'));\n\n    const syncItems = () => {\n      const sep = props.separator.value || '/';\n      const items = getItems();\n\n      for (let i = 0; i < items.length; i++) {\n        items[i].setAttribute('separator', sep);\n        items[i].toggleAttribute('data-show-separator', i > 0);\n      }\n\n      // Sync CSS variable for CSS-based separator (if used)\n      if (sep) el.style.setProperty('--breadcrumb-separator', `'${sep}'`);\n      else el.style.removeProperty('--breadcrumb-separator');\n    };\n\n    // ────────────────────────────────────────────────────────────────\n    // Lifecycle\n    // ────────────────────────────────────────────────────────────────\n\n    watch(() => {\n      void slots.elements().value;\n      syncItems();\n    });\n\n    return html`\n      <nav part=\"nav\" aria-label=\"${props.label}\">\n        <ol role=\"list\" part=\"list\">\n          <slot></slot>\n        </ol>\n      </nav>\n    `;\n  },\n  styles: [componentStyles],\n});\n","// ── Live-Region Announcer ─────────────────────────────────────────────────────\n// Programmatic announcements to screen readers without requiring a visible\n// DOM element. Used for status messages, selection feedback, and count updates\n// that live in components where the visible element is hidden or absent.\n//\n// Two visually-hidden live regions are lazily created in `<body>` — one polite,\n// one assertive. The clear-then-set pattern forces AT to re-read even identical\n// consecutive messages.\n//\n// Usage:\n// ```ts\n// import { announce } from './announcer';\n// announce(`${selectedCount} items selected`);\n// announce('Error: field is required', { politeness: 'assertive' });\n// ```\n\nimport { SR_ONLY_INLINE_STYLE } from '../styles';\n\n// ── Visually-hidden style ─────────────────────────────────────────────────────\n// Shared with the CSS-side `.sr-only` mixin — see `src/styles/mixins/accessibility.css.ts`.\n\n// ── Per-document live regions (WeakMap for automatic GC + test isolation) ────\n\ntype DocumentRegions = { assertive?: HTMLElement; polite?: HTMLElement };\n\nconst _regions = new WeakMap<Document, DocumentRegions>();\nconst _timers = new WeakMap<HTMLElement, ReturnType<typeof setTimeout>>();\n\n/** Creates and mounts a visually-hidden live region with the given politeness. */\nconst createRegion = (politeness: 'assertive' | 'polite', doc: Document): HTMLElement => {\n  const el = doc.createElement('div');\n\n  el.setAttribute('aria-live', politeness);\n  el.setAttribute('aria-atomic', 'true');\n  el.setAttribute('data-block-announcer', politeness);\n  el.style.cssText = SR_ONLY_INLINE_STYLE;\n\n  doc.body.appendChild(el);\n\n  return el;\n};\n\n/**\n * Returns the live region for the requested politeness in the given document,\n * creating it on first access. Returns `null` outside a browser context.\n */\nconst getRegion = (politeness: 'assertive' | 'polite', doc: Document): HTMLElement | null => {\n  let regions = _regions.get(doc);\n\n  // Re-create if this specific region was removed from the DOM (e.g. by test teardown).\n  if (regions?.[politeness] && !doc.body.contains(regions[politeness])) {\n    regions[politeness] = undefined;\n  }\n\n  if (!regions?.[politeness]) {\n    if (!regions) {\n      regions = {};\n      _regions.set(doc, regions);\n    }\n\n    regions[politeness] = createRegion(politeness, doc);\n  }\n\n  return regions[politeness] ?? null;\n};\n\n// ── Public API ────────────────────────────────────────────────────────────────\n\nexport type AnnouncePoliteness = 'assertive' | 'polite';\n\nexport type AnnounceOptions = {\n  /**\n   * `'polite'` — queues the announcement; does not interrupt ongoing speech.\n   * `'assertive'` — interrupts immediately. Use sparingly; reserve for errors.\n   *\n   * Default: `'polite'`.\n   */\n  politeness?: AnnouncePoliteness;\n};\n\n/**\n * Announces a message to screen readers via a singleton visually-hidden\n * live region. Safe to call outside a component lifecycle (no cleanup needed).\n *\n * The clear-then-set pattern (50 ms delay) forces AT to re-read even when the\n * message text hasn't changed.\n *\n * @example\n * ```ts\n * announce('3 results found');\n * announce('Session expired', { politeness: 'assertive' });\n * ```\n */\nexport const announce = (message: string, options: AnnounceOptions = {}): void => {\n  if (typeof document === 'undefined') return;\n\n  const politeness = options.politeness ?? 'polite';\n  const region = getRegion(politeness, document);\n\n  if (!region) return;\n\n  // Clear immediately so AT registers a content change, then set after a short\n  // delay. The 50 ms window is the established minimum for most AT/browser combos.\n  region.textContent = '';\n\n  // Use a per-element timer so concurrent polite + assertive announcements don't\n  // clobber each other's pending writes.\n  const existing = _timers.get(region);\n\n  if (existing !== undefined) clearTimeout(existing);\n\n  const timer = setTimeout(() => {\n    region.textContent = message;\n    _timers.delete(region);\n  }, 50);\n\n  _timers.set(region, timer);\n};\n","/**\n * Cross-shadow-root ARIA relationship helper.\n *\n * Plain IDREF attributes (`aria-controls`, `aria-describedby`, `aria-labelledby`, …) cannot\n * resolve across shadow-tree boundaries — the browser only looks up an `id` within the same\n * root as the referencing element, so `<div id=\"x\">` inside one component's shadow root is\n * invisible to `aria-controls=\"x\"` set inside another component's shadow root, even when both\n * custom elements are siblings in the light DOM. This is a platform limitation, not a bug —\n * see the WICG \"reference target\" explainer for the full rationale.\n *\n * Modern browsers instead expose element-reflection IDL properties\n * (`ariaControlsElements`, `ariaDescribedByElements`, `ariaLabelledByElements`, …) that accept\n * live `Element` references directly, sidestepping ID lookup entirely — these work across\n * shadow roots by design. Where unsupported, this falls back to the plain IDREF attribute,\n * which is still correct for same-root pairings and degrades gracefully (no relationship)\n * for cross-root ones instead of throwing.\n */\n\nexport type AriaReflectionProperty = 'ariaControlsElements' | 'ariaDescribedByElements' | 'ariaLabelledByElements';\n\nconst ATTR_BY_PROPERTY: Record<AriaReflectionProperty, string> = {\n  ariaControlsElements: 'aria-controls',\n  ariaDescribedByElements: 'aria-describedby',\n  ariaLabelledByElements: 'aria-labelledby',\n};\n\n/**\n * Associates `el` with `targets` via the given ARIA relationship. Prefers the\n * cross-shadow-root-safe element-reflection property; falls back to a plain IDREF attribute\n * built from `targets`' own `id`s when the browser doesn't support element reflection yet.\n *\n * Pass an empty array to clear the relationship.\n */\nexport function setAriaReflection(el: Element, property: AriaReflectionProperty, targets: readonly Element[]): void {\n  if (property in el) {\n    (el as unknown as Record<AriaReflectionProperty, readonly Element[] | null>)[property] =\n      targets.length > 0 ? targets : null;\n\n    return;\n  }\n\n  const attr = ATTR_BY_PROPERTY[property];\n  const ids = targets.map((target) => target.id).filter(Boolean);\n\n  if (ids.length === 0) el.removeAttribute(attr);\n  else el.setAttribute(attr, ids.join(' '));\n}\n","import type { Readable } from '@vielzeug/ripple';\n\nexport type AutoResizeOptions = {\n  /** Gates growth; omit for an always-on composer field, or pass a signal for a toggleable `auto-resize` attribute. */\n  enabled?: Readable<boolean | undefined>;\n};\n\nexport type AutoResizeControl = {\n  /** Recomputes height from the wired element's current content. No-ops when `enabled` is false or nothing is wired. */\n  recompute: () => void;\n  /** Wire onto the raw `<textarea>` when it mounts. Returns a detach function to call on unmount. */\n  wire: (el: HTMLTextAreaElement) => () => void;\n};\n\n/**\n * Grows a `<textarea>`'s height to fit its content, shared by every component that offers\n * auto-resize (`ore-textarea`, `ore-message-composer`) instead of each reimplementing it.\n *\n * Owns only height — manual-resize cursor/direction is a per-component styling concern, not\n * shared behavior, so it stays local to whichever component renders a resize handle.\n *\n * @example\n * ```ts\n * const autoResize = createAutoResize({ enabled: props['auto-resize'] });\n *\n * onElement(textareaRef, (el) => autoResize.wire(el));\n * // after a programmatic value change that doesn't fire a native `input` event:\n * autoResize.recompute();\n * ```\n */\nexport const createAutoResize = (options: AutoResizeOptions = {}): AutoResizeControl => {\n  let wiredEl: HTMLTextAreaElement | null = null;\n\n  const recompute = (): void => {\n    if (!wiredEl || options.enabled?.value === false) return;\n\n    wiredEl.style.height = 'auto';\n    wiredEl.style.height = `${wiredEl.scrollHeight}px`;\n  };\n\n  const wire = (el: HTMLTextAreaElement): (() => void) => {\n    wiredEl = el;\n    el.addEventListener('input', recompute);\n\n    // Deferred a frame: right after mount, the browser hasn't necessarily finished laying out\n    // the textarea yet, so a synchronous `scrollHeight` read here can be stale — often reading\n    // as 0 and collapsing the field until the next real `input` event happens to correct it.\n    // `ore-textarea` has always worked around this locally with its own extra `requestAnimationFrame`\n    // call; folding the deferral into `wire()` itself means every consumer gets it for free.\n    requestAnimationFrame(recompute);\n\n    return () => {\n      el.removeEventListener('input', recompute);\n\n      if (wiredEl === el) wiredEl = null;\n    };\n  };\n\n  return { recompute, wire };\n};\n","import { createStableId } from '@vielzeug/ore';\nimport { computed, type Readable } from '@vielzeug/ripple';\n\nimport { warn } from '../_dev';\n\n// ── Validation / context types ────────────────────────────────────────────────\n\nexport type ValidationTrigger = 'blur' | 'change' | 'input' | 'submit';\nexport type ControlValidationMode = ValidationTrigger | undefined;\n\n// ── Error/helper assistive state ──────────────────────────────────────────────\n\nexport type ErrorHelperState = {\n  errorText: string;\n  helperText: string;\n};\n\nexport type ErrorHelperOptions = {\n  error?: Readable<string | undefined>;\n  helper?: Readable<string | undefined>;\n};\n\nexport const createErrorHelperState = (options: ErrorHelperOptions): Readable<ErrorHelperState> =>\n  computed(() => ({\n    errorText: options.error?.value ?? '',\n    helperText: options.helper?.value ?? '',\n  }));\n\n// ── Counter state (opt-in) ─────────────────────────────────────────────────────\n\n/** Counter state for text fields with `maxLength`. */\nexport type CounterState = {\n  counterAtLimit: boolean;\n  counterNearLimit: boolean;\n  counterText: string;\n};\n\nexport type CounterOptions = {\n  maxLength?: Readable<number | undefined>;\n  value: Readable<string | undefined>;\n};\n\n/**\n * Creates a reactive counter state signal for text fields with `maxLength`.\n * Only call this when `maxLength` may be set — the state is genuinely opt-in.\n *\n * @example\n * ```ts\n * const counter = createCounterState({ value: tf.value, maxLength: props.maxlength });\n * ```\n */\nexport const createCounterState = (options: CounterOptions): Readable<CounterState> =>\n  computed<CounterState>(() => {\n    const value = options.value?.value ?? '';\n    const maxLength = options.maxLength?.value;\n    const parsedMaxLength = Number(maxLength);\n    const validMaxLength = Number.isFinite(parsedMaxLength) && parsedMaxLength > 0 ? parsedMaxLength : null;\n    const hasCounter = validMaxLength !== null;\n    const counterText = hasCounter ? `${value.length} / ${validMaxLength}` : '';\n    const ratio = hasCounter ? value.length / validMaxLength : 0;\n\n    return {\n      counterAtLimit: hasCounter ? ratio >= 1 : false,\n      counterNearLimit: hasCounter ? ratio >= 0.9 && ratio < 1 : false,\n      counterText,\n    };\n  });\n\n/**\n * The single implementation of \"which modifier class does this counter state map to\" —\n * every field with a character counter (`ore-input`, `ore-textarea`, `ore-message-composer`)\n * renders the identical near-limit/at-limit styling, so this is the one place that decides it.\n *\n * @example\n * ```ts\n * html`<span class=\"${() => counterClassName(counter?.value)}\">...</span>`\n * ```\n */\nexport const counterClassName = (counter: CounterState | undefined, base = 'counter'): string => {\n  if (!counter) return base;\n\n  if (counter.counterAtLimit) return `${base} at-limit`;\n\n  if (counter.counterNearLimit) return `${base} near-limit`;\n\n  return base;\n};\n\n// ── Dirty tracking (two-state reset) ───────────────────────────────────────────\n\n/**\n * Tracks whether a control's value has ever been changed by user interaction.\n *\n * Backs the \"two-state reset()\" pattern used by `createCheckable` (`checked`/\n * `indeterminate`) and `createChoiceField` (`selectedValues`): before the first\n * interaction, the live prop is still a reliable \"current default\" to resync from\n * (e.g. an async-loaded value arriving after mount); after it, the prop is\n * contaminated by interaction-driven attribute reflection, so only a snapshot taken\n * at creation still represents \"the default\" in the native sense. `reset()` callers\n * check `isDirty` to decide which source to revert to, then call `clear()`.\n */\nexport type DirtyTracker = {\n  clear: () => void;\n  readonly isDirty: boolean;\n  markDirty: () => void;\n};\n\nexport function createDirtyTracker(): DirtyTracker {\n  let dirty = false;\n\n  return {\n    clear: () => {\n      dirty = false;\n    },\n    get isDirty() {\n      return dirty;\n    },\n    markDirty: () => {\n      dirty = true;\n    },\n  };\n}\n\n// ── Label placement ───────────────────────────────────────────────────────────\n\nexport type LabelPlacement = 'inset' | 'outside' | undefined;\n\n// ── Assistive state (error/helper text, describedby/errormessage/invalid) ─────\n\n/**\n * A field's error/helper/disabled/validation-trigger state — everything an input\n * needs *except* a visible `<label>`. Split out from label state (below) because\n * not every field has one: `ore-message-composer` names itself via `aria-label`\n * (a chat composer's accessible name conventionally comes from context/placeholder,\n * not a floating `<label>`), so it composes this directly instead of pulling in\n * label plumbing it can't use. `createField()` composes both for fields that do\n * render a `<label>`.\n */\nexport type AssistiveStateHandle = {\n  /** `aria-describedby` value. Non-null when helper or error text is present. */\n  ariaDescribedBy: Readable<string | null>;\n  /** `aria-errormessage` value. Non-null when error text is present. */\n  ariaErrorMessage: Readable<string | null>;\n  /** `aria-invalid` value. `'true'` when error text is present, otherwise `null`. */\n  ariaInvalid: Readable<'true' | null>;\n  /**\n   * The stable `id` used for `aria-describedby` on the input. Points at the\n   * assistive-text region (covers both helper text and error text per WAI-ARIA).\n   */\n  assistiveId: string;\n  /**\n   * Registers the real form field handle (the return value of `useField()`) so that\n   * `triggerValidation()` can call its `reportValidity()`. See `TextFieldHandle.attachFormField`\n   * for why this is a post-hoc call instead of a constructor option — the same forward\n   * reference applies here for choice fields.\n   */\n  attachFormField: (formField: { reportValidity(): void }) => void;\n  disabled: Readable<boolean>;\n  /** Stable `id` for the inline error message element (`aria-errormessage`). */\n  errorId: string;\n  /** Reactive error text. Empty string when no error is set. */\n  errorText: Readable<string>;\n  /** Reactive helper text. Empty string when no helper is set. */\n  helperText: Readable<string>;\n  triggerValidation: (on: Extract<ValidationTrigger, 'blur' | 'change'>) => void;\n};\n\nexport type AssistiveStateOptions = {\n  disabled?: Readable<boolean | undefined>;\n  error?: Readable<string | undefined>;\n  helper?: Readable<string | undefined>;\n  validateOn?: Readable<ControlValidationMode>;\n};\n\nexport const createAssistiveState = (options: AssistiveStateOptions): AssistiveStateHandle => {\n  const disabled = computed(() => Boolean(options.disabled?.value));\n  const assistiveId = createStableId('helper');\n  const errorId = createStableId('error');\n  const resolvedAssistive = createErrorHelperState({ error: options.error, helper: options.helper });\n\n  const ariaDescribedBy = computed(() =>\n    resolvedAssistive.value.errorText || resolvedAssistive.value.helperText ? assistiveId : null,\n  );\n  const ariaErrorMessage = computed(() => (resolvedAssistive.value.errorText ? errorId : null));\n  const ariaInvalid = computed<'true' | null>(() => (resolvedAssistive.value.errorText ? 'true' : null));\n\n  let formField: { reportValidity(): void } | null = null;\n  const attachFormField = (nextFormField: { reportValidity(): void }): void => {\n    formField = nextFormField;\n  };\n\n  const triggerValidation = (on: Extract<ValidationTrigger, 'blur' | 'change'>): void => {\n    if (options.validateOn?.value !== on) return;\n\n    if (!formField) {\n      // Not user-facing — this only fires when a component author wired `validateOn` but\n      // forgot the matching `attachFormField(useField(...))` call, so validation silently\n      // never runs instead of erroring where the mistake actually is.\n      warn(\n        \"triggerValidation() called before attachFormField() — validation will not run. See createTextField()/createChoiceField()/createCheckable()'s attachFormField doc comment.\",\n      );\n\n      return;\n    }\n\n    formField.reportValidity();\n  };\n\n  return {\n    ariaDescribedBy,\n    ariaErrorMessage,\n    ariaInvalid,\n    assistiveId,\n    attachFormField,\n    disabled,\n    errorId,\n    errorText: computed(() => resolvedAssistive.value.errorText),\n    helperText: computed(() => resolvedAssistive.value.helperText),\n    triggerValidation,\n  };\n};\n\n// ── Label state (visible `<label>` + `aria-labelledby`) ────────────────────────\n\nexport type LabelStateHandle = {\n  /** `aria-labelledby` value. Non-null when a label is visible. */\n  ariaLabelledBy: Readable<string | null>;\n  /** Stable `id` for the underlying form control — the `<label for=\"...\">` target. */\n  fieldId: string;\n  /** Stable `id` for the label element. Stamp this on your `<label id=\"...\">`. */\n  labelId: string;\n  /** Whether the label should be visible. Use to toggle `hidden` on the `<label>`. */\n  labelVisible: Readable<boolean>;\n};\n\nexport type LabelStateOptions = {\n  /**\n   * Override for label visibility that takes precedence over deriving it from\n   * the `label` text signal. Pass a computed signal that checks both prop and\n   * slot presence to enable slot-first composition.\n   *\n   * @example\n   * ```ts\n   * const hasLabel = computed(() => !!props.label.value || slots.has('label').value);\n   * const label = createLabelState({ ...options, hasLabel });\n   * ```\n   */\n  hasLabel?: Readable<boolean>;\n  /**\n   * When provided, used directly as `fieldId` instead of generating one via\n   * `createStableId`. Useful in tests for deterministic ID assertions.\n   */\n  id?: string;\n  /**\n   * Label text signal. When provided, `labelVisible` and `ariaLabelledBy` are\n   * computed reactively from this value (see `hasLabel` for the slot-first override).\n   */\n  label?: Readable<string | undefined>;\n  /**\n   * Label placement signal. Defaults to `'inset'`.\n   *\n   * Not consumed by `createLabelState()` itself — visibility is driven solely by\n   * `hasLabel`/`label`. Threaded through so component authors can apply\n   * placement-specific styling (`label-placement` attribute) without a second\n   * option; if placement-dependent visibility is ever needed, wire it into\n   * `labelVisible` here instead of adding a new option.\n   */\n  labelPlacement?: Readable<LabelPlacement>;\n  prefix?: string;\n};\n\nexport const createLabelState = (options: LabelStateOptions): LabelStateHandle => {\n  const fieldId = options.id ?? createStableId(options.prefix ?? 'field');\n  const labelId = createStableId('label');\n  const label$ = options.label ?? computed(() => undefined);\n\n  // Slot-first composition: if the caller provides `hasLabel`, use it instead\n  // of deriving visibility purely from the label text signal. This allows\n  // components with a `<slot name=\"label\">` to stay visible even when the\n  // `label` prop is empty but a slotted label element is present.\n  const labelVisible = options.hasLabel ?? computed(() => Boolean(label$.value));\n  const ariaLabelledBy = computed(() => (labelVisible.value ? labelId : null));\n\n  return { ariaLabelledBy, fieldId, labelId, labelVisible };\n};\n\n// ── Field handle (assistive + label, composed) ──────────────────────────────\n\n/**\n * Common handle returned by `createField` — the base for both `TextFieldHandle`\n * and `ChoiceFieldHandle`. Composes `createAssistiveState` + `createLabelState`;\n * call those directly instead if a field has no visible `<label>` (see\n * `createAssistiveState`'s doc comment).\n *\n * ARIA signals and label state are flat on the handle — no nested `aria` or\n * `label` sub-objects. `labelId`/`labelVisible`/`ariaLabelledBy` are always\n * present but only meaningful when `label`/`hasLabel` was passed — omit both\n * and they resolve to an always-hidden, unreferenced label.\n *\n * @example\n * ```html\n * <label id=\"${labelId}\" ?hidden=\"${() => !labelVisible.value}\">...</label>\n * <input\n *   aria-labelledby=\"${ariaLabelledBy}\"\n *   aria-describedby=\"${ariaDescribedBy}\"\n *   aria-invalid=\"${ariaInvalid}\" />\n * ```\n */\nexport type FieldHandle = AssistiveStateHandle & LabelStateHandle;\n\n/** Options shared by both `createTextField` and `createChoiceField`. */\nexport type FieldOptions = AssistiveStateOptions & LabelStateOptions;\n\nexport const createField = (options: FieldOptions): FieldHandle => ({\n  ...createAssistiveState(options),\n  ...createLabelState(options),\n});\n","import type { Readable } from '@vielzeug/ripple';\n\n// ── Keyboard dispatch ─────────────────────────────────────────────────────────\n\nexport type KeyboardDispatchOptions = {\n  disabled?: Readable<boolean | undefined>;\n  keymap: Record<string, (event: KeyboardEvent) => boolean | void>;\n  preventDefault?: 'after' | 'before' | false;\n};\n\nexport const dispatchKeyboardAction = (event: KeyboardEvent, options: KeyboardDispatchOptions): boolean => {\n  if (options.disabled?.value) return false;\n\n  // `event.key` is attacker-influenceable on a synthetic KeyboardEvent (e.g. `new\n  // KeyboardEvent('keydown', { key: '__proto__' })`). Guard with `Object.hasOwn` so a\n  // crafted key name can never resolve to an inherited `Object.prototype` member\n  // (`__proto__`, `constructor`, `toString`, …) instead of `undefined`.\n  const action = Object.hasOwn(options.keymap, event.key) ? options.keymap[event.key] : undefined;\n\n  if (!action) return false;\n\n  const preventDefaultMode = options.preventDefault ?? 'before';\n\n  if (preventDefaultMode === 'before') event.preventDefault();\n\n  const handled = action(event) !== false;\n\n  if (preventDefaultMode === 'after' && handled) event.preventDefault();\n\n  return handled;\n};\n\n// ── Press control / Interaction ───────────────────────────────────────────────\n\nexport type PressTrigger = 'keyboard' | 'pointer';\n\n/**\n * Options for `createInteraction` — a unified press + focus/blur interaction\n * handler for accessible interactive elements.\n */\nexport type InteractionOptions = {\n  /** `true` when the element is disabled. All handlers become no-ops. */\n  disabled?: Readable<boolean | undefined>;\n  /** Keys that trigger a press. Defaults to `['Enter', ' ']`. */\n  keys?: string[];\n  /** Called when the element loses focus. */\n  onBlur?: (event: FocusEvent) => void;\n  /** Called when the element receives focus. */\n  onFocus?: (event: FocusEvent) => void;\n  /** Called when the element is pressed via keyboard or pointer. */\n  onPress?: (event: KeyboardEvent | MouseEvent, trigger: PressTrigger) => void;\n};\n\nexport type Interaction = {\n  handleBlur: (event: FocusEvent) => void;\n  handleClick: (event: MouseEvent) => boolean;\n  handleFocus: (event: FocusEvent) => void;\n  handleKeydown: (event: KeyboardEvent) => boolean;\n};\n\n/**\n * Creates a set of event handlers for an interactive element that responds to\n * keyboard and pointer presses, and optionally focus/blur events.\n *\n * @example\n * ```ts\n * const interaction = createInteraction({\n *   disabled: props.disabled,\n *   onPress: (event, trigger) => toggle(event),\n *   onFocus: (event) => setFocused(true),\n *   onBlur: (event) => setFocused(false),\n * });\n *\n * // In template:\n * // @click=\"${interaction.handleClick}\"\n * // @keydown=\"${interaction.handleKeydown}\"\n * // @focus=\"${interaction.handleFocus}\"\n * // @blur=\"${interaction.handleBlur}\"\n * ```\n */\nexport const createInteraction = (options: InteractionOptions): Interaction => {\n  const isDisabled = (): boolean => Boolean(options.disabled?.value);\n  const keyboardKeys = options.keys ?? ['Enter', ' '];\n  const keymap = Object.fromEntries(\n    keyboardKeys.map((key) => [key, (keyboardEvent: KeyboardEvent) => options.onPress?.(keyboardEvent, 'keyboard')]),\n  );\n\n  return {\n    handleBlur: (event: FocusEvent): void => {\n      if (!isDisabled()) options.onBlur?.(event);\n    },\n    handleClick: (event: MouseEvent): boolean => {\n      if (isDisabled()) return false;\n\n      options.onPress?.(event, 'pointer');\n\n      return true;\n    },\n    handleFocus: (event: FocusEvent): void => {\n      if (!isDisabled()) options.onFocus?.(event);\n    },\n    handleKeydown: (event: KeyboardEvent): boolean =>\n      dispatchKeyboardAction(event, { disabled: options.disabled, keymap }),\n  };\n};\n","import { type Readable, type Signal, signal, untrack, watch } from '@vielzeug/ripple';\n\n// ── syncedSignal ──────────────────────────────────────────────────────────────\n\n/**\n * Creates a local writable `Signal<T>` that stays in sync with an external\n * `Reactive<T>`. When `abortSignal` is provided the watcher subscription\n * is disposed automatically on abort; otherwise the caller is responsible for\n * disposal.\n *\n * Initialised synchronously via `untrack` so the first render never reads a\n * stale value. The optional `transform` coerces each incoming value (e.g.\n * `Boolean`, `String`).\n *\n * @example\n * ```ts\n * const value = syncedSignal(options.value, options.signal, (v) => String(v ?? ''));\n * // Without lifecycle signal (test / non-component context):\n * const value = syncedSignal(source);\n * ```\n */\nexport const syncedSignal = <TIn, TOut = TIn>(\n  source: Readable<TIn>,\n  abortSignal?: AbortSignal,\n  transform: (value: TIn) => TOut = (v) => v as unknown as TOut,\n): Signal<TOut> => {\n  const local = signal<TOut>(untrack(() => transform(source.value)));\n  const sub = watch(source, (v) => {\n    local.value = transform(v);\n  });\n\n  if (abortSignal) {\n    abortSignal.addEventListener('abort', () => sub.dispose(), { once: true });\n  }\n\n  return local;\n};\n","import { computed, type Readable, type Signal, signal } from '@vielzeug/ripple';\n\nimport { type ControlValidationMode, createDirtyTracker, createField, type FieldHandle } from './field-base';\nimport { createInteraction } from './keyboard';\nimport { syncedSignal } from './signals';\n\n// ── Checkable control ─────────────────────────────────────────────────────────\n\nexport type CheckableChangePayload = {\n  checked: boolean;\n  originalEvent?: Event;\n  value: string;\n};\n\nexport type CheckableOptions = {\n  checked: Readable<boolean | undefined>;\n  clearIndeterminateFirst?: boolean;\n  disabled?: Readable<boolean | undefined>;\n  error?: Readable<string | undefined>;\n  group?: { toggle: (value: string, originalEvent?: Event) => void };\n  helper?: Readable<string | undefined>;\n  indeterminate?: Readable<boolean | undefined>;\n  onToggle?: (payload: CheckableChangePayload) => void;\n  prefix?: string;\n  /** Marks an unchecked control invalid — feeds `validity`/`validationMessage` (see below). */\n  required?: Readable<boolean | undefined>;\n  /** Message for the unchecked+required case. Defaults to `'This field is required.'`. */\n  requiredMessage?: Readable<string | undefined>;\n  /** `AbortSignal` from the component lifecycle. All reactive subscriptions are torn down on abort. */\n  signal: AbortSignal;\n  validateOn?: Readable<ControlValidationMode>;\n  value: Readable<string | undefined>;\n};\n\nexport type CheckableHandle = FieldHandle & {\n  /** The form submission value: null when unchecked/indeterminate, the value string when checked. */\n  checkableFormValue: Readable<string | null>;\n  checked: Signal<boolean>;\n  handleClick: (event: MouseEvent) => boolean;\n  handleKeydown: (event: KeyboardEvent) => boolean;\n  indeterminate: Signal<boolean>;\n  /**\n   * Restores `checked`/`indeterminate` to their native \"default\" value. See `DirtyTracker`\n   * for the two-state rationale. Wire into `useField({ onReset: checkable.reset })`.\n   */\n  reset: () => void;\n  toggle: (event: Event) => void;\n  /** Reactive validation message paired with `validity`. Empty string when valid. */\n  validationMessage: Readable<string>;\n  /**\n   * Reactive `ValidityStateFlags` — `{ valueMissing: true }` while `required` and unchecked\n   * (indeterminate counts as unchecked), `null` (valid) otherwise. Pass straight to\n   * `useField({ validity: checkable.validity })`.\n   */\n  validity: Readable<ValidityStateFlags | null>;\n};\n\nexport const createCheckable = (options: CheckableOptions): CheckableHandle => {\n  const checked = syncedSignal(options.checked, options.signal, Boolean);\n  const indeterminate = options.indeterminate\n    ? syncedSignal(options.indeterminate, options.signal, Boolean)\n    : signal(false);\n  const initialChecked = checked.value;\n  const initialIndeterminate = indeterminate.value;\n  const dirtyTracker = createDirtyTracker();\n\n  const checkableFormValue = computed<string | null>(() =>\n    indeterminate.value ? null : checked.value ? (options.value.value ?? '') : null,\n  );\n\n  const field = createField(options);\n\n  const validity = computed<ValidityStateFlags | null>(() =>\n    options.required?.value && (!checked.value || indeterminate.value) ? { valueMissing: true } : null,\n  );\n  const validationMessage = computed(() =>\n    validity.value ? options.requiredMessage?.value || 'This field is required.' : '',\n  );\n\n  const reset = (): void => {\n    checked.value = dirtyTracker.isDirty ? initialChecked : Boolean(options.checked.value);\n    indeterminate.value = dirtyTracker.isDirty ? initialIndeterminate : Boolean(options.indeterminate?.value);\n    dirtyTracker.clear();\n    field.triggerValidation('change');\n  };\n\n  const createPayload = (event: Event): CheckableChangePayload => ({\n    checked: checked.value,\n    originalEvent: event,\n    value: options.value.value ?? '',\n  });\n\n  const toggle = (event: Event): void => {\n    if (field.disabled.value) return;\n\n    dirtyTracker.markDirty();\n\n    if (options.group) {\n      indeterminate.value = false;\n      options.group.toggle(options.value.value ?? '', event);\n      options.onToggle?.(createPayload(event));\n\n      return;\n    }\n\n    if (options.clearIndeterminateFirst && indeterminate.value) {\n      indeterminate.value = false;\n    } else {\n      checked.value = !checked.value;\n      indeterminate.value = false;\n    }\n\n    options.onToggle?.(createPayload(event));\n  };\n\n  const interaction = createInteraction({\n    disabled: field.disabled,\n    onPress: (event) => toggle(event),\n  });\n\n  return {\n    ...field,\n    checkableFormValue,\n    checked,\n    handleClick: interaction.handleClick,\n    handleKeydown: interaction.handleKeydown,\n    indeterminate,\n    reset,\n    toggle,\n    validationMessage,\n    validity,\n  };\n};\n","import { computed, type Readable, watch } from '@vielzeug/ripple';\n\nimport { createDirtyTracker, createField, type FieldHandle, type FieldOptions } from './field-base';\nimport { syncedSignal } from './signals';\n\n// ── Choice change event payload ──────────────────────────────────────────────────────────────\n\nexport type ChoiceChangeDetail = {\n  labels: string[];\n  originalEvent?: Event;\n  values: string[];\n};\n\n// ── Choice field ──────────────────────────────────────────────────────────────────────\n\nexport type ChoiceFieldOptions = FieldOptions & {\n  multiple?: Readable<boolean | undefined>;\n  /** Marks an empty selection invalid — feeds `validity`/`validationMessage` (see below). */\n  required?: Readable<boolean | undefined>;\n  /** Message for the empty-selection+required case. Defaults to `'Please make a selection.'`. */\n  requiredMessage?: Readable<string | undefined>;\n  /** `AbortSignal` from the component lifecycle. All internal subscriptions are disposed on abort. */\n  signal: AbortSignal;\n  /**\n   * Current selection value(s). Accepts a comma-separated string\n   * (legacy/single-select form serialisation) or a `string[]` array.\n   * The field normalises both formats internally via `parseChoiceValues`.\n   */\n  value: Readable<string | string[] | undefined>;\n};\n\nexport type ChoiceFieldHandle = FieldHandle & {\n  clear: () => void;\n  formValue: Readable<string>;\n  removeValue: (value: string) => void;\n  /**\n   * Restores the selection to its native \"default\". See `DirtyTracker` for the two-state\n   * rationale.\n   */\n  reset: () => void;\n  selectedValue: Readable<string | undefined>;\n  selectedValues: Readable<string[]>;\n  selectValue: (value: string) => void;\n  setValues: (values: string[]) => void;\n  /**\n   * Toggles `value` in the selection.\n   * - **Multiple mode**: adds if absent, removes if present.\n   * - **Single mode**: always selects `value` (acts like `selectValue` — cannot\n   *   deselect; use `clear()` to reset a single-select field).\n   */\n  toggleValue: (value: string) => void;\n  /** Reactive validation message paired with `validity`. Empty string when valid. */\n  validationMessage: Readable<string>;\n  /**\n   * Reactive `ValidityStateFlags` — `{ valueMissing: true }` while `required` and no option is\n   * selected, `null` (valid) otherwise. Pass straight to `useField({ validity: choice.validity })`.\n   */\n  validity: Readable<ValidityStateFlags | null>;\n};\n\nconst parseChoiceValues = (raw: string | string[] | undefined): string[] => {\n  if (!raw) return [];\n\n  if (Array.isArray(raw)) return raw.filter(Boolean);\n\n  return raw\n    .split(',')\n    .map((entry) => entry.trim())\n    .filter(Boolean);\n};\n\nexport const createChoiceField = (options: ChoiceFieldOptions): ChoiceFieldHandle => {\n  const isMultiple = computed(() => Boolean(options.multiple?.value));\n\n  const normalizeValues = (values: string[]): string[] => {\n    const normalized = isMultiple.value ? values : values.slice(0, 1);\n\n    return [...new Set(normalized.filter(Boolean))];\n  };\n\n  // Kept in sync with `options.value` via the shared helper (see `checkable.ts`/`text-field.ts`\n  // for the same pattern) rather than a hand-rolled signal + watch pair.\n  const selectedValues = syncedSignal(options.value, options.signal, (raw) => normalizeValues(parseChoiceValues(raw)));\n  const formValue = computed(() =>\n    isMultiple.value ? selectedValues.value.join(',') : (selectedValues.value[0] ?? ''),\n  );\n\n  const dirtyTracker = createDirtyTracker();\n\n  // The actual state setter, shared by every mutation path. Deliberately *not* where the dirty\n  // tracker gets marked — `syncFromProp` (below) calls this directly to stay exempt from it,\n  // since mirroring an external prop change is never \"the user changed the selection\".\n  const applyValues = (values: string[]): void => {\n    selectedValues.value = normalizeValues(values);\n  };\n\n  const setValues = (values: string[]): void => {\n    dirtyTracker.markDirty();\n    applyValues(values);\n  };\n  const clear = (): void => setValues([]);\n  const removeValue = (value: string): void => {\n    dirtyTracker.markDirty();\n    selectedValues.value = selectedValues.value.filter((v) => v !== value);\n  };\n\n  const selectValue = (value: string): void => {\n    if (isMultiple.value) {\n      if (!selectedValues.value.includes(value)) setValues([...selectedValues.value, value]);\n\n      return;\n    }\n\n    setValues([value]);\n  };\n\n  const toggleValue = (value: string): void => {\n    if (isMultiple.value) {\n      if (selectedValues.value.includes(value)) removeValue(value);\n      else selectValue(value);\n    } else {\n      selectValue(value);\n    }\n  };\n\n  const syncFromProp = (nextValue: string | string[] | undefined): void => {\n    applyValues(parseChoiceValues(nextValue));\n  };\n\n  const field = createField(options);\n\n  const validity = computed<ValidityStateFlags | null>(() =>\n    options.required?.value && selectedValues.value.length === 0 ? { valueMissing: true } : null,\n  );\n  const validationMessage = computed(() =>\n    validity.value ? options.requiredMessage?.value || 'Please make a selection.' : '',\n  );\n\n  if (options.multiple) {\n    const multipleSub = watch(options.multiple, () => syncFromProp(options.value.value));\n\n    options.signal.addEventListener('abort', () => multipleSub.dispose(), { once: true });\n  }\n\n  const initialValues = selectedValues.value;\n  const reset = (): void => {\n    applyValues(dirtyTracker.isDirty ? initialValues : parseChoiceValues(options.value.value));\n    dirtyTracker.clear();\n    field.triggerValidation('change');\n  };\n\n  return {\n    ...field,\n    clear,\n    formValue,\n    removeValue,\n    reset,\n    selectedValue: computed(() => selectedValues.value[0]),\n    selectedValues,\n    selectValue,\n    setValues,\n    toggleValue,\n    validationMessage,\n    validity,\n  };\n};\n","import type { Readable } from '@vielzeug/ripple';\n\nimport { computed } from '@vielzeug/ripple';\n\n/**\n * Keyboard shortcut that triggers a send:\n * - `'enter'` (default) — Enter sends, Shift+Enter inserts a newline.\n * - `'mod+enter'` — Enter always inserts a newline; Ctrl/Cmd+Enter sends.\n */\nexport type SendShortcut = 'enter' | 'mod+enter';\n\nexport type ComposerControlOptions = {\n  disabled?: Readable<boolean | undefined>;\n  /** Blocks further sends (e.g. a send is already in flight) without disabling editing. */\n  loading?: Readable<boolean | undefined>;\n  /** Called for a send attempt that passed the `canSend` guard. */\n  onSend: (event: KeyboardEvent | MouseEvent) => void;\n  sendShortcut?: Readable<SendShortcut | undefined>;\n  value: Readable<string | undefined>;\n};\n\nexport type ComposerControl = {\n  /** Whether the current value is non-blank and the control isn't disabled/loading. */\n  canSend: Readable<boolean>;\n  /** Wire onto the raw `<textarea>`'s `keydown` — intercepts the resolved send shortcut. */\n  handleKeydown: (event: KeyboardEvent) => void;\n  /** `aria-keyshortcuts` value describing the resolved shortcut. */\n  keyShortcutsHint: Readable<string>;\n  /** Attempts a send; no-ops when `canSend` is false. Wire onto the send button's `click`. */\n  send: (event: KeyboardEvent | MouseEvent) => void;\n};\n\nconst isBlank = (value: string | undefined): boolean => !value || value.trim() === '';\n\n/**\n * Send-gesture logic for a message/comment composer — decides *when* a send is allowed\n * and *whether* a given keydown counts as one. Owns no DOM, value state, or event dispatch;\n * the component wires `handleKeydown`/`send` and decides what a send actually does.\n *\n * @example\n * ```ts\n * const composer = createComposerControl({\n *   onSend: (event) => attemptSend(event),\n *   sendShortcut: props['send-shortcut'],\n *   value,\n * });\n * // <textarea @keydown=\"${composer.handleKeydown}\" aria-keyshortcuts=\"${composer.keyShortcutsHint}\">\n * // <button ?disabled=\"${() => !composer.canSend.value}\" @click=\"${composer.send}\">\n * ```\n */\nexport const createComposerControl = (options: ComposerControlOptions): ComposerControl => {\n  const canSend = computed(() => !isBlank(options.value.value) && !options.disabled?.value && !options.loading?.value);\n\n  const send = (event: KeyboardEvent | MouseEvent): void => {\n    if (!canSend.value) return;\n\n    options.onSend(event);\n  };\n\n  const handleKeydown = (event: KeyboardEvent): void => {\n    // A composing IME candidate selection also fires `Enter` — never treat that as a send.\n    if (event.key !== 'Enter' || event.isComposing) return;\n\n    const mode = options.sendShortcut?.value ?? 'enter';\n    const hasModifier = event.metaKey || event.ctrlKey;\n\n    if (mode === 'mod+enter' ? !hasModifier : event.shiftKey) return;\n\n    event.preventDefault();\n    send(event);\n  };\n\n  const keyShortcutsHint = computed(() =>\n    (options.sendShortcut?.value ?? 'enter') === 'mod+enter' ? 'Control+Enter Meta+Enter' : 'Enter',\n  );\n\n  return { canSend, handleKeydown, keyShortcutsHint, send };\n};\n","import { format, parse, Temporal } from '@vielzeug/tempo';\n\n// ── Public ISO helpers (single source of truth for both components) ───────────\n\n/**\n * Parses an ISO 8601 date string (`yyyy-MM-dd`) into a `Temporal.PlainDate`.\n * Returns `null` for any invalid / empty input — never throws.\n */\nexport function parseIso(iso: string | undefined | null): Temporal.PlainDate | null {\n  if (!iso) return null;\n\n  try {\n    return parse(iso, { as: 'plainDate' });\n  } catch {\n    return null;\n  }\n}\n\n/**\n * Serialises a `Temporal.PlainDate` (or `null`) to an ISO 8601 string (`yyyy-MM-dd`).\n * Returns `null` when the input is `null`.\n */\nexport function toIsoString(date: Temporal.PlainDate | null): string | null {\n  return date ? date.toString() : null;\n}\n\n/**\n * Formats a `Temporal.PlainDate` for display in a given locale.\n * e.g. \"15 Jun 2025\" (default medium pattern).\n */\nexport function formatDisplayDate(date: Temporal.PlainDate, locale: string): string {\n  return format(date, { intl: { day: 'numeric', month: 'short', year: 'numeric' }, locale, timeZone: 'UTC' });\n}\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type DatePickerView = 'day' | 'month' | 'year';\n\nexport type DateCell = {\n  /** Day-of-month number (1–31) */\n  day: number;\n  isDisabled: boolean;\n  /** ISO date string yyyy-MM-dd — stable key for rendering */\n  iso: string;\n  isOutsideMonth: boolean;\n  isSelected: boolean;\n  isToday: boolean;\n  plain: Temporal.PlainDate;\n};\n\nexport type MonthCell = {\n  isDisabled: boolean;\n  isSelected: boolean;\n  label: string;\n  /** 1-based month number (Temporal convention: 1 = January … 12 = December) */\n  month: number;\n  shortLabel: string;\n};\n\nexport type YearCell = {\n  isDisabled: boolean;\n  isSelected: boolean;\n  year: number;\n};\n\nexport type DatePickerControlOptions = {\n  /** Locale for day/month names, defaults to `navigator.language` or `'en'` */\n  locale?: string;\n  /** Maximum selectable date (inclusive) */\n  max?: Temporal.PlainDate | null;\n  /** Minimum selectable date (inclusive) */\n  min?: Temporal.PlainDate | null;\n  /** Called when a date is committed by the user */\n  onChange: (date: Temporal.PlainDate | null) => void;\n  /** Currently selected date */\n  value?: Temporal.PlainDate | null;\n  /**\n   * Which days of the week to disable (0 = Sunday … 6 = Saturday).\n   * @example [0, 6] disables weekends\n   */\n  weekendDays?: number[];\n};\n\nexport type DatePickerControl = {\n  /** Ordered day cells for the visible month grid (includes leading/trailing days) */\n  dayCells(): DateCell[];\n  /** Month currently shown in the header (1-indexed, Temporal convention) */\n  displayMonth(): number;\n  /** Year currently shown in the header */\n  displayYear(): number;\n  /** Jump to a specific display month/year without selecting */\n  goTo(year: number, month: number): void;\n  /** All 12 month cells */\n  monthCells(): MonthCell[];\n  /** Move display month forward by one */\n  nextMonth(): void;\n  /** Move display year forward by one */\n  nextYear(): void;\n  /** Move display month backward by one */\n  prevMonth(): void;\n  /** Move display year backward by one */\n  prevYear(): void;\n  /** Select a date. Pass null to clear. */\n  select(date: Temporal.PlainDate | null): void;\n  /** The currently selected date, or null */\n  selected(): Temporal.PlainDate | null;\n  /** Switch the calendar view */\n  setView(view: DatePickerView): void;\n  /** Currently rendered calendar view */\n  view(): DatePickerView;\n  /** Short week-day labels in locale order e.g. [\"Su\",\"Mo\",…] */\n  weekdayLabels(): string[];\n  /** Year cells for the visible decade window */\n  yearCells(): YearCell[];\n};\n\n// ── Internal helpers ──────────────────────────────────────────────────────────\n\n/**\n * Returns today as a `Temporal.PlainDate` in the ISO calendar.\n * @internal\n */\nfunction todayPlain(): Temporal.PlainDate {\n  return Temporal.Now.plainDateISO();\n}\n\n/**\n * Converts a `Temporal.PlainDate.dayOfWeek` value (1=Mon…7=Sun) to the\n * 0-based weekday index (0=Sun…6=Sat) used in the `weekendDays` prop.\n * @internal\n */\nfunction temporalDowToIndex(dow: number): number {\n  // Temporal: 1=Mon, 2=Tue, …, 7=Sun  →  0=Sun, 1=Mon, …, 6=Sat\n  return dow % 7;\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\n/**\n * Pure, framework-agnostic date-picker state machine backed by `Temporal.PlainDate`.\n *\n * All state is held in plain mutable variables — suitable for wrapping in any\n * reactive layer (ore `signal`, Vue ref, etc.). The factory returns a stable\n * handle object; callers are responsible for reactivity.\n *\n * Options with getter-based live bindings (e.g. `get min() { ... }`) are read\n * on every call so the control always reflects the latest reactive state.\n *\n * @example\n * ```ts\n * const ctrl = createDatePickerControl({\n *   value: Temporal.PlainDate.from('2025-06-15'),\n *   locale: 'en-US',\n *   onChange: (date) => console.log(date?.toString()),\n * });\n *\n * ctrl.nextMonth();\n * ctrl.select(Temporal.PlainDate.from('2025-07-04'));\n * ```\n */\nexport function createDatePickerControl(options: DatePickerControlOptions): DatePickerControl {\n  // ── Mutable state ─────────────────────────────────────────────────────────\n\n  let _selected: Temporal.PlainDate | null = options.value ?? null;\n  let _view: DatePickerView = 'day';\n\n  const initial = _selected ?? todayPlain();\n\n  let _displayYear = initial.year;\n  let _displayMonth = initial.month; // 1-indexed (Temporal convention)\n\n  // ── Live option accessors (always read from options for reactive compat) ───\n\n  function locale(): string {\n    return options.locale ?? (typeof navigator !== 'undefined' ? navigator.language : 'en');\n  }\n\n  function weekendDays(): number[] {\n    return options.weekendDays ?? [];\n  }\n\n  // ── Range / disabled helpers ───────────────────────────────────────────────\n\n  function isOutOfRange(date: Temporal.PlainDate): boolean {\n    if (options.min && Temporal.PlainDate.compare(date, options.min) < 0) return true;\n\n    if (options.max && Temporal.PlainDate.compare(date, options.max) > 0) return true;\n\n    return false;\n  }\n\n  function isDayDisabled(date: Temporal.PlainDate): boolean {\n    if (isOutOfRange(date)) return true;\n\n    if (weekendDays().includes(temporalDowToIndex(date.dayOfWeek))) return true;\n\n    return false;\n  }\n\n  // ── Grid builders ─────────────────────────────────────────────────────────\n\n  function buildDayCells(): DateCell[] {\n    const todayDate = todayPlain();\n    const firstOfMonth = Temporal.PlainDate.from({ day: 1, month: _displayMonth, year: _displayYear });\n\n    // Sunday-start grid: Temporal dayOfWeek is 1=Mon…7=Sun, convert to 0=Sun offset\n    const startOffset = temporalDowToIndex(firstOfMonth.dayOfWeek);\n    const cells: DateCell[] = [];\n\n    // Leading days from previous month\n    for (let i = startOffset - 1; i >= 0; i--) {\n      const d = firstOfMonth.subtract({ days: i + 1 });\n\n      cells.push({\n        day: d.day,\n        isDisabled: isDayDisabled(d),\n        isOutsideMonth: true,\n        iso: d.toString(),\n        isSelected: _selected !== null && Temporal.PlainDate.compare(d, _selected) === 0,\n        isToday: Temporal.PlainDate.compare(d, todayDate) === 0,\n        plain: d,\n      });\n    }\n\n    // Days in current month\n    const daysInMonth = firstOfMonth.daysInMonth;\n\n    for (let day = 1; day <= daysInMonth; day++) {\n      const d = Temporal.PlainDate.from({ day, month: _displayMonth, year: _displayYear });\n\n      cells.push({\n        day,\n        isDisabled: isDayDisabled(d),\n        isOutsideMonth: false,\n        iso: d.toString(),\n        isSelected: _selected !== null && Temporal.PlainDate.compare(d, _selected) === 0,\n        isToday: Temporal.PlainDate.compare(d, todayDate) === 0,\n        plain: d,\n      });\n    }\n\n    // Trailing days to fill last row (always end at multiple of 7)\n    const remaining = (7 - (cells.length % 7)) % 7;\n    const firstOfNext = firstOfMonth.add({ months: 1 });\n\n    for (let i = 0; i < remaining; i++) {\n      const d = firstOfNext.add({ days: i });\n\n      cells.push({\n        day: d.day,\n        isDisabled: isDayDisabled(d),\n        isOutsideMonth: true,\n        iso: d.toString(),\n        isSelected: _selected !== null && Temporal.PlainDate.compare(d, _selected) === 0,\n        isToday: Temporal.PlainDate.compare(d, todayDate) === 0,\n        plain: d,\n      });\n    }\n\n    return cells;\n  }\n\n  function buildMonthCells(): MonthCell[] {\n    const cells: MonthCell[] = [];\n    const loc = locale();\n\n    for (let m = 1; m <= 12; m++) {\n      const plain = Temporal.PlainDate.from({ day: 1, month: m, year: _displayYear });\n      const lastOfMonth = plain.with({ day: plain.daysInMonth });\n\n      const isDisabled =\n        (options.min !== null && options.min !== undefined\n          ? Temporal.PlainDate.compare(lastOfMonth, options.min) < 0\n          : false) ||\n        (options.max !== null && options.max !== undefined\n          ? Temporal.PlainDate.compare(plain, options.max) > 0\n          : false);\n\n      cells.push({\n        isDisabled,\n        isSelected: _selected !== null && _selected.year === _displayYear && _selected.month === m,\n        label: format(plain, { intl: { month: 'long' }, locale: loc, timeZone: 'UTC' }),\n        month: m,\n        shortLabel: format(plain, { intl: { month: 'short' }, locale: loc, timeZone: 'UTC' }),\n      });\n    }\n\n    return cells;\n  }\n\n  function buildYearCells(): YearCell[] {\n    const decadeStart = Math.floor(_displayYear / 10) * 10;\n    const cells: YearCell[] = [];\n\n    for (let y = decadeStart; y < decadeStart + 12; y++) {\n      const firstOfYear = Temporal.PlainDate.from({ day: 1, month: 1, year: y });\n      const lastOfYear = Temporal.PlainDate.from({ day: 31, month: 12, year: y });\n\n      const isDisabled =\n        (options.min !== null && options.min !== undefined\n          ? Temporal.PlainDate.compare(lastOfYear, options.min) < 0\n          : false) ||\n        (options.max !== null && options.max !== undefined\n          ? Temporal.PlainDate.compare(firstOfYear, options.max) > 0\n          : false);\n\n      cells.push({\n        isDisabled,\n        isSelected: _selected !== null && _selected.year === y,\n        year: y,\n      });\n    }\n\n    return cells;\n  }\n\n  function buildWeekdayLabels(): string[] {\n    // 2024-01-07 is a Sunday — use it as the Sunday anchor\n    const sunday = parse('2024-01-07', { as: 'plainDate' });\n    const loc = locale();\n\n    return Array.from({ length: 7 }, (_, i) =>\n      format(sunday.add({ days: i }), { intl: { weekday: 'short' }, locale: loc, timeZone: 'UTC' }),\n    );\n  }\n\n  // ── Handle ────────────────────────────────────────────────────────────────\n\n  return {\n    dayCells: buildDayCells,\n    displayMonth: () => _displayMonth,\n    displayYear: () => _displayYear,\n\n    goTo(year: number, month: number): void {\n      if (!Number.isFinite(year)) return;\n\n      _displayYear = year;\n      _displayMonth = Math.max(1, Math.min(12, month));\n    },\n\n    monthCells: buildMonthCells,\n\n    nextMonth(): void {\n      if (_displayMonth === 12) {\n        _displayMonth = 1;\n        _displayYear++;\n      } else {\n        _displayMonth++;\n      }\n    },\n\n    nextYear(): void {\n      _displayYear++;\n    },\n\n    prevMonth(): void {\n      if (_displayMonth === 1) {\n        _displayMonth = 12;\n        _displayYear--;\n      } else {\n        _displayMonth--;\n      }\n    },\n\n    prevYear(): void {\n      _displayYear--;\n    },\n\n    select(date: Temporal.PlainDate | null): void {\n      if (date !== null && isDayDisabled(date)) return;\n\n      _selected = date;\n\n      if (_selected) {\n        _displayYear = _selected.year;\n        _displayMonth = _selected.month;\n      }\n\n      options.onChange(_selected);\n    },\n\n    selected: () => _selected,\n\n    setView(view: DatePickerView): void {\n      _view = view;\n    },\n\n    view: () => _view,\n\n    weekdayLabels: buildWeekdayLabels,\n\n    yearCells: buildYearCells,\n  };\n}\n","import { captureFocus, type FocusRestorer } from '@vielzeug/focus';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type FocusManagerOptions = {\n  /**\n   * Returns the CSS selector for the element that should receive focus on open.\n   *\n   * **Security note:** this value is passed directly to `querySelector`. It must\n   * come from trusted developer-controlled configuration, never from raw user input.\n   */\n  getInitialFocusSelector: () => string | undefined;\n  /**\n   * Returns whether focus should be restored to the previously focused element\n   * on close. `undefined` or `true` means restore; `false` means skip.\n   */\n  getReturnFocus: () => boolean | undefined;\n  /** Host element used for `querySelector` when resolving the initial focus target. */\n  host: HTMLElement;\n  /**\n   * `AbortSignal` from the component lifecycle. Cancels a pending `applyInitialFocus()`\n   * animation frame automatically on abort — prevents a stray `.focus()` call landing on an\n   * element that's been disconnected in the meantime (e.g. the dialog closes and unmounts\n   * before the deferred focus frame runs).\n   */\n  signal?: AbortSignal;\n};\n\nexport type FocusManager = {\n  [Symbol.dispose](): void;\n  /** Move focus to the element matching `getInitialFocusSelector` (deferred one frame). */\n  applyInitialFocus: () => void;\n  /** Cancel a pending `applyInitialFocus` rAF, if any. */\n  cancelInitialFocus: () => void;\n  /** Capture the currently focused element so it can be restored later. */\n  captureReturnFocus: () => void;\n  /** Cancels any pending initial-focus frame and clears captured return-focus state. */\n  dispose(): void;\n  /** `true` after `dispose()` has been called. */\n  readonly disposed: boolean;\n  /** Restore focus to the element captured by `captureReturnFocus`. */\n  restoreFocus: () => void;\n};\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\n/**\n * Encapsulates the three-step focus lifecycle used by dialogs and drawers:\n * 1. Capture the element that triggered the open.\n * 2. Move focus inside the overlay (optionally to a specific element).\n * 3. Restore focus when the overlay closes.\n */\nexport function createFocusManager(options: FocusManagerOptions): FocusManager {\n  let restoreReturnFocus: FocusRestorer | null = null;\n  let rafHandle: ReturnType<typeof requestAnimationFrame> | null = null;\n  let disposed = false;\n\n  const cancelInitialFocus = (): void => {\n    if (rafHandle !== null) {\n      cancelAnimationFrame(rafHandle);\n      rafHandle = null;\n    }\n  };\n\n  const dispose = (): void => {\n    if (disposed) return;\n\n    disposed = true;\n    cancelInitialFocus();\n    restoreReturnFocus = null;\n  };\n\n  options.signal?.addEventListener('abort', dispose, { once: true });\n\n  return {\n    applyInitialFocus() {\n      cancelInitialFocus();\n\n      const selector = options.getInitialFocusSelector();\n\n      if (selector) {\n        // Query the shadow root first (all refine components render into Shadow DOM),\n        // falling back to the host's light-DOM tree for non-Shadow contexts.\n        const root = options.host.shadowRoot ?? options.host;\n\n        let target: HTMLElement | null = null;\n\n        try {\n          target = root.querySelector<HTMLElement>(selector);\n        } catch {\n          // Malformed selector (SyntaxError) — skip initial focus rather than throw.\n          return;\n        }\n\n        if (target) {\n          rafHandle = requestAnimationFrame(() => {\n            rafHandle = null;\n            target.focus();\n          });\n        }\n      }\n    },\n    cancelInitialFocus,\n\n    captureReturnFocus() {\n      restoreReturnFocus = captureFocus();\n    },\n\n    dispose,\n\n    get disposed() {\n      return disposed;\n    },\n\n    restoreFocus() {\n      if (options.getReturnFocus() !== false) restoreReturnFocus?.();\n\n      restoreReturnFocus = null;\n    },\n\n    [Symbol.dispose]: dispose,\n  };\n}\n","// ── Slot / light-DOM query helpers ────────────────────────────────────────────\n// Utilities for querying slotted light-DOM children and resolving labels from\n// option elements. Used by group components (checkbox-group, radio-group) and\n// choice-field components (select, combobox).\n\n/**\n * Returns all light-DOM descendants matching `tag` inside `host`.\n * Uses `getElementsByTagName` on the host's light DOM \\u2014 not Shadow DOM slot assignment.\n */\nexport const getLightChildrenByTag = (host: HTMLElement, tag: string): HTMLElement[] =>\n  Array.from(host.getElementsByTagName(tag)) as HTMLElement[];\n\n/**\n * Returns the `textContent` of the item whose `value` attribute matches `value`,\n * falling back to `value` itself when no match is found.\n * Used by choice-field components to derive labels for emitted change events.\n */\nexport const getChoiceLabel = (items: HTMLElement[], value: string): string => {\n  const item = items.find((el) => (el.getAttribute('value') ?? '') === value);\n\n  return item?.textContent?.replace(/\\s+/g, ' ').trim() || value;\n};\n","// ── Number helpers ────────────────────────────────────────────────────────────\n\n/**\n * Coerces `value` via `Number()` and returns it when finite, `undefined` otherwise.\n *\n * Caveat: `null` and `''` both coerce to `0` in JavaScript (`Number(null) === 0`,\n * `Number('') === 0`) and are therefore returned as the finite number `0`, not\n * `undefined` — this function does not treat \"absent\" values specially. Only\n * genuinely non-numeric input (`undefined`, `NaN`, non-numeric strings) yields\n * `undefined`. Callers that mean \"no bound set\" should pass `undefined`\n * explicitly rather than `null` or `''`.\n */\nexport const toFiniteNumber = (value: unknown): number | undefined => {\n  const parsed = Number(value);\n\n  return Number.isFinite(parsed) ? parsed : undefined;\n};\n\nexport const toFiniteNumberOr = (value: unknown, fallback: number): number => {\n  return toFiniteNumber(value) ?? fallback;\n};\n\nexport const toPositiveStep = (value: unknown, fallback: number): number => {\n  return Math.abs(toFiniteNumberOr(value, fallback)) || fallback;\n};\n","// ── Ore adapter ─────────────────────────────────────────────────────────────\n// Utilities that bridge Ore's component lifecycle with Refine's core\n// primitives' `AbortSignal`-based lifecycle contract.\n\n/**\n * Creates an `AbortSignal` tied to the component's Ore lifecycle.\n *\n * Call once at the top of a `setup()` function and pass the resulting signal\n * as the required `signal` option to any stateful core primitive\n * (`createTextField`, `createCheckable`, `createListboxDropdown`, etc.).\n *\n * When Ore disconnects the component, `onCleanup` fires, aborting the\n * signal and triggering cleanup in every primitive that received it.\n *\n * @example\n * ```ts\n * setup(props, { el }) {\n *   const signal = lifecycleSignal(onCleanup);\n *   const tf = createTextField({ ..., signal });\n * }\n * ```\n */\nexport const lifecycleSignal = (onCleanup: (fn: () => void) => void): AbortSignal => {\n  const controller = new AbortController();\n\n  onCleanup(() => controller.abort());\n\n  return controller.signal;\n};\n","/**\n * Why an overlay was opened.\n * - `'click'`       — user clicked the trigger element\n * - `'focus'`       — focus entered the trigger (tooltip, popover)\n * - `'hover'`       — pointer entered the trigger (tooltip)\n * - `'keyboard'`    — keyboard shortcut or Enter/Space on a trigger\n * - `'programmatic'` — opened via the JS API without a user gesture\n * - `'trigger'`     — opened via the Invoker Commands API (`command=\"show-modal\"`)\n */\nexport type OverlayOpenReason = 'click' | 'focus' | 'hover' | 'keyboard' | 'programmatic' | 'trigger';\n\n/** Close reasons valid for modal dialogs (includes 'swipe' for drawer). */\nexport type DialogCloseReason = 'escape' | 'outsideClick' | 'programmatic' | 'swipe' | 'trigger';\n/** Close reasons valid for dropdown overlays (no swipe). */\nexport type DropdownCloseReason = Exclude<DialogCloseReason, 'swipe'> | 'select';\n\n/** Detail shape for overlay open events emitted by components. */\nexport type OverlayOpenDetail = { reason: OverlayOpenReason };\n/** Detail shape for overlay close events emitted by components. */\nexport type OverlayCloseDetail = { reason: DialogCloseReason };\n/** Detail shape for state changes emitted by overlay components. */\nexport type OverlayOpenChangeDetail = {\n  open: boolean;\n  reason: DialogCloseReason | DropdownCloseReason | OverlayOpenReason;\n};\n\nexport type OutsidePointerDismissalOptions = {\n  getTargets: () => Array<Element | null | undefined>;\n  isActive: () => boolean;\n  onDismiss: () => void;\n  signal: AbortSignal;\n};\n\n/**\n * Dismisses an active floating surface when a pointer begins outside all of its\n * supplied boundary elements. Components retain ownership of their open state.\n */\nexport const createOutsidePointerDismissal = (options: OutsidePointerDismissalOptions): (() => void) => {\n  const onPointerDown = (event: PointerEvent): void => {\n    if (!options.isActive()) return;\n\n    const path = event.composedPath();\n    const target = path[0] instanceof Node ? path[0] : event.target instanceof Node ? event.target : null;\n    const inside = options.getTargets().some((element) => {\n      return (\n        element !== null &&\n        element !== undefined &&\n        (path.includes(element) || Boolean(target && element.contains(target)))\n      );\n    });\n\n    if (!inside) options.onDismiss();\n  };\n\n  const dispose = (): void => {\n    document.removeEventListener('pointerdown', onPointerDown, { capture: true });\n  };\n\n  document.addEventListener('pointerdown', onPointerDown, { capture: true });\n  options.signal.addEventListener('abort', dispose, { once: true });\n\n  return dispose;\n};\n","import type { Readable } from '@vielzeug/ripple';\nimport { watch } from '@vielzeug/ripple';\n\n/** Shape every `ref` prop in this package uses — a JS-only escape hatch to the live element. */\nexport type RefCallback<T> = ((el: T | null) => void) | null | undefined;\n\n/**\n * Forwards a mounted element to a JS-only `ref` callback prop, and keeps forwarding to a\n * *new* callback if the prop is set again after mount (e.g. a parent sets it via a ref\n * callback after render, rather than at initial mount). Every text-entry-style component\n * with a `ref` escape-hatch prop (`ore-input`, `ore-textarea`, `ore-message-composer`,\n * `ore-file-input`) wires this identically — call it once from inside `onElement()`, alongside\n * whatever else that element needs wired.\n *\n * @example\n * ```ts\n * onElement(fieldRef, (el) => {\n *   const unwireField = tf.wire(el);\n *   const unwireRef = bindRefCallback(props.ref, el);\n *\n *   return () => {\n *     unwireField();\n *     unwireRef();\n *   };\n * });\n * ```\n */\nexport const bindRefCallback = <T extends Element>(ref: Readable<RefCallback<T>>, el: T): (() => void) => {\n  // Immediate fire for when the prop is already set on mount.\n  ref.value?.(el);\n\n  const sub = watch(ref, (cb) => cb?.(el));\n\n  return () => {\n    sub.dispose();\n    ref.value?.(null);\n  };\n};\n","//#region src/math/clamp.ts\nfunction e(e, t, n) {\n\treturn t != null && e < t ? t : n != null && e > n ? n : e;\n}\n//#endregion\nexport { e as clamp };\n\n//# sourceMappingURL=clamp.js.map","import { clamp as clampRange } from '@vielzeug/arsenal/math';\nimport type { Readable } from '@vielzeug/ripple';\n\nimport { toFiniteNumberOr, toPositiveStep } from './numbers';\n\n// ── Slider control ────────────────────────────────────────────────────────────\n\nexport type SliderControlOptions = {\n  disabled?: Readable<boolean | undefined>;\n  max?: Readable<number | string | undefined>;\n  min?: Readable<number | string | undefined>;\n  readonly?: Readable<boolean | undefined>;\n  step?: Readable<number | string | undefined>;\n};\n\nexport type SliderControl = {\n  clamp: (value: number) => number;\n  fromClientX: (clientX: number, rect: { left: number; width: number }) => number;\n  /**\n   * Handles keyboard navigation for a slider input.\n   * When the slider is disabled or readonly, the event is ignored and `false` is returned.\n   * @returns `true` when the event was handled and `onCommit` was called, `false` otherwise.\n   */\n  handleKeydown: (event: KeyboardEvent, currentValue: number, onCommit: (value: number) => void) => boolean;\n  max: () => number;\n  min: () => number;\n  nextFromKey: (key: string, current: number) => number | null;\n  snap: (value: number) => number;\n  toPercent: (value: number) => number;\n};\n\nexport const createSliderControl = (options: SliderControlOptions): SliderControl => {\n  const min = (): number => toFiniteNumberOr(options.min?.value, 0);\n  const max = (): number => toFiniteNumberOr(options.max?.value, 100);\n  const step = (): number => toPositiveStep(options.step?.value, 1);\n\n  const clamp = (value: number): number => {\n    const minValue = min();\n    const maxValue = max();\n\n    return clampRange(toFiniteNumberOr(value, minValue), minValue, maxValue);\n  };\n\n  const snap = (value: number): number => {\n    const minValue = min();\n\n    return clamp(Math.round(toFiniteNumberOr(value, minValue) / step()) * step());\n  };\n\n  const toPercent = (value: number): number => {\n    const minValue = min();\n    const maxValue = max();\n    const normalized = toFiniteNumberOr(value, minValue);\n\n    if (maxValue <= minValue) return 0;\n\n    return ((normalized - minValue) / (maxValue - minValue)) * 100;\n  };\n\n  const fromClientX = (clientX: number, rect: { left: number; width: number }): number => {\n    if (rect.width <= 0) return snap(min());\n\n    const pct = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));\n    const minValue = min();\n    const maxValue = max();\n\n    return snap(minValue + pct * (maxValue - minValue));\n  };\n\n  const nextFromKey = (key: string, current: number): number | null => {\n    const normalized = toFiniteNumberOr(current, min());\n\n    if (key === 'ArrowRight' || key === 'ArrowUp') return clamp(normalized + step());\n\n    if (key === 'ArrowLeft' || key === 'ArrowDown') return clamp(normalized - step());\n\n    if (key === 'Home') return min();\n\n    if (key === 'End') return max();\n\n    return null;\n  };\n\n  const handleKeydown = (event: KeyboardEvent, currentValue: number, onCommit: (value: number) => void): boolean => {\n    if (options.disabled?.value || options.readonly?.value) return false;\n\n    const next = nextFromKey(event.key, currentValue);\n\n    if (next === null) return false;\n\n    event.preventDefault();\n    onCommit(next);\n\n    return true;\n  };\n\n  return { clamp, fromClientX, handleKeydown, max, min, nextFromKey, snap, toPercent };\n};\n","import { clamp as clampRange } from '@vielzeug/arsenal/math';\nimport type { Readable } from '@vielzeug/ripple';\n\nimport { dispatchKeyboardAction } from './keyboard';\nimport { toFiniteNumber, toPositiveStep } from './numbers';\n\nexport type SpinnerControlOptions = {\n  commit: (value: number | null, originalEvent?: Event) => void;\n  disabled?: Readable<boolean | undefined>;\n  largeStep?: Readable<number | string | undefined>;\n  max?: Readable<number | string | undefined>;\n  min?: Readable<number | string | undefined>;\n  parse: () => number | null;\n  readonly?: Readable<boolean | undefined>;\n  step?: Readable<number | string | undefined>;\n};\n\nexport type SpinnerControl = {\n  atMax: () => boolean;\n  atMin: () => boolean;\n  handleKeydown: (event: KeyboardEvent) => boolean;\n  incrementBy: (delta: number, originalEvent?: Event) => void;\n};\n\nexport const createSpinnerControl = (options: SpinnerControlOptions): SpinnerControl => {\n  const isBlocked = (): boolean => Boolean(options.disabled?.value) || Boolean(options.readonly?.value);\n\n  const min = (): number | undefined => {\n    return toFiniteNumber(options.min?.value);\n  };\n\n  const max = (): number | undefined => {\n    return toFiniteNumber(options.max?.value);\n  };\n\n  const clamp = (value: number): number => {\n    return clampRange(value, min(), max());\n  };\n\n  const step = (): number => toPositiveStep(options.step?.value, 1);\n\n  const largeStep = (): number => {\n    const s = step();\n\n    return toPositiveStep(options.largeStep?.value, s * 10);\n  };\n\n  const currentOrFallback = (): number => {\n    const parsed = options.parse();\n\n    if (parsed != null) return parsed;\n\n    const minValue = min();\n\n    if (minValue != null) return minValue;\n\n    return 0;\n  };\n\n  const commit = (value: number | null, originalEvent?: Event): void => {\n    if (value == null) {\n      options.commit(null, originalEvent);\n\n      return;\n    }\n\n    options.commit(clamp(value), originalEvent);\n  };\n\n  const incrementBy = (delta: number, originalEvent?: Event): void => {\n    if (isBlocked()) return;\n\n    commit(currentOrFallback() + delta, originalEvent);\n  };\n\n  const atMin = (): boolean => {\n    const parsed = options.parse();\n    const minValue = min();\n\n    return parsed != null && minValue != null && parsed <= minValue;\n  };\n\n  const atMax = (): boolean => {\n    const parsed = options.parse();\n    const maxValue = max();\n\n    return parsed != null && maxValue != null && parsed >= maxValue;\n  };\n\n  const handleKeydown = (event: KeyboardEvent): boolean => {\n    if (isBlocked()) return false;\n\n    return dispatchKeyboardAction(event, {\n      keymap: {\n        ArrowDown: () => incrementBy(-step(), event),\n        ArrowUp: () => incrementBy(step(), event),\n        End: () => {\n          const maxValue = max();\n\n          if (maxValue == null) return false;\n\n          commit(maxValue, event);\n        },\n        Home: () => {\n          const minValue = min();\n\n          if (minValue == null) return false;\n\n          commit(minValue, event);\n        },\n        PageDown: () => incrementBy(-largeStep(), event),\n        PageUp: () => incrementBy(largeStep(), event),\n      },\n      preventDefault: 'after',\n    });\n  };\n\n  return {\n    atMax,\n    atMin,\n    handleKeydown,\n    incrementBy,\n  };\n};\n","import { computed, type Readable, type Signal } from '@vielzeug/ripple';\n\nimport { type CounterState, createCounterState, createField, type FieldHandle, type FieldOptions } from './field-base';\nimport { syncedSignal } from './signals';\n\n// ── Text field ────────────────────────────────────────────────────────────────\n\n/** Detach function returned by `wire()`. Call to remove element listeners. */\nexport type TextFieldDetach = () => void;\n\nexport type TextFieldOptions = FieldOptions & {\n  maxLength?: Readable<number | undefined>;\n  /**\n   * Called synchronously before value extraction on every input event.\n   * Use only for DOM side-effects (e.g. auto-resize measurement) that must\n   * run before the reactive value is updated.\n   */\n  onBeforeInput?: (event: Event) => void;\n  onBlur?: (event: FocusEvent) => void;\n  onChange?: (event: Event, value: string) => void;\n  onFocus?: (event: FocusEvent) => void;\n  onInput?: (event: Event, value: string) => void;\n  /**\n   * Bars the field from constraint validation while true — matches the native HTML rule that a\n   * `readonly` field is never a candidate for constraint validation (a `readonly required`\n   * field is always valid, per spec), so `validity`/`validationMessage` don't feed a false\n   * `valueMissing` into `useField()` just because a read-only field happens to be blank.\n   */\n  readonly?: Readable<boolean | undefined>;\n  /** Marks a blank value invalid — feeds `validity`/`validationMessage` (see below). */\n  required?: Readable<boolean | undefined>;\n  /** Message for the blank+required case. Defaults to `'This field is required.'`. */\n  requiredMessage?: Readable<string | undefined>;\n  /** `AbortSignal` from the component lifecycle. The internal value-sync watcher is disposed on abort. */\n  signal: AbortSignal;\n  value: Readable<string | undefined>;\n};\n\nexport type TextFieldHandle = FieldHandle & {\n  /**\n   * Registers the real form field handle (the return value of `useField()`) so that\n   * `triggerValidation()` — called internally on blur/change — can call its\n   * `reportValidity()`. `useField()` itself needs `value` (below) to exist first, so this\n   * is a two-step wiring rather than a constructor option:\n   *\n   * ```ts\n   * const tf = createTextField({ value: props.value, ... });\n   * const formField = useField({ value: tf.value, ... });\n   * tf.attachFormField(formField);\n   * ```\n   */\n  attachFormField: (formField: { reportValidity(): void }) => void;\n  /** Clears the field value and fires synthetic input/change events. */\n  clear: (event?: Event) => void;\n  /**\n   * Reactive counter state. Non-null when `maxLength` was provided; `null` otherwise.\n   * Components should only render a counter element when this is non-null.\n   */\n  counter: Readable<CounterState> | null;\n  /**\n   * Restores the value to whatever the `value` option currently holds (native form\n   * `reset()` semantics: a `<input>` reverts to its *current* `value` content attribute,\n   * not a frozen snapshot from element creation — so setting the attribute programmatically\n   * after mount changes what a later reset reverts to). Wire into `useField({ onReset: tf.reset })`.\n   */\n  reset: () => void;\n  /** Reactive validation message paired with `validity`. Empty string when valid. */\n  validationMessage: Readable<string>;\n  /**\n   * Reactive `ValidityStateFlags` — `{ valueMissing: true }` while `required` and blank,\n   * `null` (valid) otherwise. Pass straight to `useField({ validity: tf.validity })`.\n   */\n  validity: Readable<ValidityStateFlags | null>;\n  /** The local mutable field value (two-way bound to the input element via `wire()`). */\n  value: Signal<string>;\n  /**\n   * Attaches event listeners to the underlying input or textarea element.\n   *\n   * When `signal` is provided, the listeners are detached automatically when\n   * the signal's controller calls `abort()`. Without a signal the returned\n   * `TextFieldDetach` must be called manually.\n   *\n   * Safe to call multiple times — each call attaches a fresh set of listeners\n   * and returns a distinct detach function. Calling detach multiple times is\n   * a no-op (guarded internally).\n   */\n  wire: (el: HTMLInputElement | HTMLTextAreaElement, signal?: AbortSignal) => TextFieldDetach;\n};\n\nconst isBlank = (value: string): boolean => value.trim() === '';\nconst toFieldValue = (v: string | undefined): string => String(v ?? '');\n\nexport const createTextField = (options: TextFieldOptions): TextFieldHandle => {\n  const value = syncedSignal(options.value, options.signal, toFieldValue);\n\n  const field = createField(options);\n  const counter = options.maxLength ? createCounterState({ maxLength: options.maxLength, value }) : null;\n\n  const validity = computed<ValidityStateFlags | null>(() =>\n    !options.readonly?.value && options.required?.value && isBlank(value.value) ? { valueMissing: true } : null,\n  );\n  const validationMessage = computed(() =>\n    validity.value ? options.requiredMessage?.value || 'This field is required.' : '',\n  );\n\n  const reset = (): void => {\n    value.value = toFieldValue(options.value.value);\n    field.triggerValidation('change');\n  };\n\n  const clear = (event?: Event): void => {\n    event?.preventDefault?.();\n    value.value = '';\n    options.onInput?.(event ?? new InputEvent('input', { bubbles: true }), '');\n    options.onChange?.(event ?? new Event('change', { bubbles: true }), '');\n    field.triggerValidation('change');\n  };\n\n  const wire = (element: HTMLInputElement | HTMLTextAreaElement, signal?: AbortSignal): TextFieldDetach => {\n    const cleanups: Array<() => void> = [];\n    const on = (type: string, handler: EventListener): void => {\n      element.addEventListener(type, handler);\n      cleanups.push(() => element.removeEventListener(type, handler));\n    };\n\n    if (options.onFocus) {\n      on('focus', (e) => options.onFocus?.(e as FocusEvent));\n    }\n\n    on('input', (e) => {\n      e.stopPropagation();\n      options.onBeforeInput?.(e);\n      value.value = element.value;\n      options.onInput?.(e, element.value);\n    });\n\n    on('change', (e) => {\n      e.stopPropagation();\n      value.value = element.value;\n      options.onChange?.(e, element.value);\n      field.triggerValidation('change');\n    });\n\n    on('blur', (e) => {\n      options.onBlur?.(e as FocusEvent);\n      field.triggerValidation('blur');\n    });\n\n    let detached = false;\n    const detach = (): void => {\n      if (detached) return;\n\n      detached = true;\n      for (const dispose of cleanups) dispose();\n    };\n\n    signal?.addEventListener('abort', detach, { once: true });\n\n    return detach;\n  };\n\n  return { ...field, clear, counter, reset, validationMessage, validity, value, wire };\n};\n","/**\n * Resolves the effective text direction for an element.\n *\n * The closest ancestor with an explicit `dir=\"ltr\"` or `dir=\"rtl\"` attribute wins — this\n * supports locally-scoped RTL sections (e.g. a single `dir=\"rtl\"` panel inside an otherwise\n * LTR page). When no explicit `dir` attribute is found up the tree, falls back to the\n * computed `direction` CSS property (e.g. set via a `direction: rtl` style rule with no\n * `dir` attribute). Defaults to `'ltr'` when `el` is `null`.\n */\nexport function elementDirection(el: Element | null): 'ltr' | 'rtl' {\n  let node: Element | null = el;\n\n  while (node) {\n    const dir = node.getAttribute('dir');\n\n    if (dir === 'rtl' || dir === 'ltr') return dir;\n\n    node = node.parentElement;\n  }\n\n  return el !== null && getComputedStyle(el).direction === 'rtl' ? 'rtl' : 'ltr';\n}\n","import {\n  createListNavigation,\n  type ListNavigationOptions as FocusListNavigationOptions,\n  type ListKeyAction,\n  type ListNavigation,\n  type ListNavigationAction,\n  type ListNavigationChange,\n  type ListNavigationTypeaheadOptions,\n} from '@vielzeug/focus';\nimport { type Readable, signal } from '@vielzeug/ripple';\n\nexport type ListNavigationOptions<T> = Omit<FocusListNavigationOptions<T>, 'disabled'> & {\n  disabled?: Readable<boolean | undefined>;\n};\n\nexport type ListControl<T> = {\n  [Symbol.dispose](): void;\n  dispose(): void;\n  readonly disposed: boolean;\n  readonly focusedIndex: Readable<number>;\n  getActiveItem(): T | undefined;\n  handleKeydown(event: KeyboardEvent): boolean;\n  navigate(action: ListNavigationAction): number;\n  reset(): void;\n  set(index: number): number;\n};\n\nexport type { ListKeyAction, ListNavigationAction, ListNavigationChange, ListNavigationTypeaheadOptions };\n\nexport const createListControl = <T>(options: ListNavigationOptions<T>): ListControl<T> => {\n  const focusedIndex = signal(-1);\n  let removeAbortListener: (() => void) | undefined;\n  const navigation: ListNavigation<T> = createListNavigation<T>({\n    direction: options.direction,\n    disabled: () => Boolean(options.disabled?.value),\n    getItems: options.getItems,\n    isItemDisabled: options.isItemDisabled,\n    keys: options.keys,\n    loop: options.loop,\n    onNavigate: (change) => {\n      focusedIndex.value = change.index;\n      options.onNavigate?.(change);\n    },\n    orientation: options.orientation,\n    typeahead: options.typeahead,\n  });\n\n  const syncIndex = (): void => {\n    focusedIndex.value = navigation.getIndex();\n  };\n\n  const set = (index: number): number => {\n    const next = navigation.set(index);\n\n    syncIndex();\n\n    return next;\n  };\n\n  const navigate = (action: ListNavigationAction): number => {\n    const next = navigation.navigate(action);\n\n    syncIndex();\n\n    return next;\n  };\n\n  const reset = (): void => {\n    navigation.reset();\n    syncIndex();\n  };\n\n  const handleKeydown = (event: KeyboardEvent): boolean => {\n    const handled = navigation.handleKeydown(event);\n\n    syncIndex();\n\n    return handled;\n  };\n\n  const dispose = (): void => {\n    navigation.dispose();\n    syncIndex();\n    removeAbortListener?.();\n    removeAbortListener = undefined;\n  };\n\n  if (options.signal?.aborted) {\n    dispose();\n  } else if (options.signal) {\n    options.signal?.addEventListener('abort', dispose, { once: true });\n    removeAbortListener = () => options.signal?.removeEventListener('abort', dispose);\n  }\n\n  return {\n    dispose,\n    get disposed() {\n      return navigation.disposed;\n    },\n    focusedIndex,\n    getActiveItem: () => navigation.getActiveItem(),\n    handleKeydown,\n    navigate,\n    reset,\n    set,\n    [Symbol.dispose]: dispose,\n  };\n};\n","/** Base class for all refine errors. Use `instanceof RefineError` to catch any refine-originated error. */\nexport class RefineError extends Error {\n  constructor(message: string, opts?: ErrorOptions) {\n    super(message, opts);\n    this.name = new.target.name;\n    Object.setPrototypeOf(this, new.target.prototype);\n  }\n\n  static is(err: unknown): err is RefineError {\n    return err instanceof RefineError;\n  }\n}\n\n/** Thrown when a refine component receives an invalid or unsupported configuration. */\nexport class RefineConfigError extends RefineError {}\n","import {\n  autoUpdate,\n  computePosition,\n  flip,\n  getClippingAncestorRect,\n  offset,\n  type Placement,\n  type Rect,\n  shift,\n  size,\n} from '@vielzeug/orbit';\n\nimport { elementDirection } from './direction';\n\n// ── Overlay positioner contract ──────────────────────────────────────────────\n\nexport type OverlayPositioner = {\n  floating: () => HTMLElement | null;\n  reference: () => HTMLElement | null;\n  /** Start continuous position auto-updates. Returns a stop function. */\n  startAutoUpdate?: () => () => void;\n  update: () => void;\n};\n\n// ── Dropdown positioner ───────────────────────────────────────────────────────\n\nexport type DropdownPositionerOptions = {\n  /**\n   * Clipping boundary for flip/shift/size — the edges the dropdown must stay within.\n   * Defaults to the nearest ancestor that actually clips content (`overflow:\n   * hidden|auto|scroll|clip`, e.g. a dialog panel), auto-detected per update via\n   * `getClippingAncestorRect()`, intersected with the viewport. Without this, flip/shift only\n   * avoid the full page viewport — a dropdown can be \"in view\" by that measure while still\n   * visibly overhanging a much smaller container it's actually nested in. Pass an explicit\n   * boundary to override auto-detection.\n   */\n  boundary?: Element | Rect;\n  /**\n   * Returns the text direction used for placement mirroring. Defaults to the resolved\n   * direction of the reference element (nearest `dir=\"ltr\"|\"rtl\"` ancestor, falling back to\n   * computed style) — most callers never need to pass this explicitly.\n   */\n  getDir?: () => 'ltr' | 'rtl';\n  /** Getter for the floating (dropdown panel) element. */\n  getFloating: () => HTMLElement | null;\n  /** Getter for the current placement. Defaults to 'bottom-start' (RTL-aware: flips to 'bottom-end'). */\n  getPlacement?: () => Placement;\n  /** Getter for the reference (trigger) element. */\n  getReference: () => HTMLElement | null;\n  /** Whether to match the floating element width to the reference. Default: true */\n  matchWidth?: boolean;\n  /** Additional offset in pixels between reference and floating element. Default: 0 */\n  offsetPx?: number;\n  /** Padding (px) used by flip, shift, and size middleware. Default: 6 */\n  padding?: number;\n  /**\n   * Whether to constrain placement to a clipping ancestor when `boundary` is unset. Default:\n   * true. Disable for native Popover API panels, which render in the top layer.\n   */\n  useClippingAncestor?: boolean;\n};\n\n/** Mirrors a start/end placement for RTL layouts. */\nconst rtlPlacement = (p: Placement): Placement => {\n  if (p.endsWith('-start')) return p.replace('-start', '-end') as Placement;\n\n  if (p.endsWith('-end')) return p.replace('-end', '-start') as Placement;\n\n  return p;\n};\n\n/**\n * Creates an Orbit-powered positioner for dropdown overlays (select, combobox, menu).\n *\n * Uses flip + shift + optional width-matching middleware. Supports continuous\n * auto-update for repositioning on scroll or resize.\n *\n * RTL-aware: start/end placements are automatically mirrored so dropdowns open on the\n * correct side, based on `getDir` (or the reference element's resolved direction when\n * `getDir` is omitted).\n */\nexport function createDropdownPositioner({\n  boundary,\n  getDir,\n  getFloating,\n  getPlacement,\n  getReference,\n  matchWidth = true,\n  offsetPx = 0,\n  padding = 6,\n  useClippingAncestor = true,\n}: DropdownPositionerOptions): OverlayPositioner {\n  function resolvedPlacement(): Placement {\n    const base = getPlacement?.() ?? 'bottom-start';\n    const dir = getDir?.() ?? elementDirection(getReference());\n\n    return dir === 'rtl' ? rtlPlacement(base) : base;\n  }\n\n  function updatePosition(): void {\n    const ref = getReference();\n    const floating = getFloating();\n\n    if (!ref || !floating) return;\n\n    const placement = resolvedPlacement();\n    // Defaults to `undefined` (meaning \"auto-detect\"), not the detected value itself —\n    // re-running the detection on every update (rather than once, at positioner-creation time)\n    // matters because the dialog/scroll-container an instance is rendered into can change\n    // across opens (e.g. the same `<ore-select>` reused in different dialogs), and the detected\n    // ancestor's own rect can change between opens even when it's the same element (a resized\n    // dialog).\n    const resolvedBoundary = boundary ?? (useClippingAncestor ? getClippingAncestorRect(floating) : undefined);\n\n    const result = computePosition(ref, floating, {\n      boundary: resolvedBoundary,\n      middleware: [\n        ...(offsetPx ? [offset(offsetPx)] : []),\n        flip({ padding }),\n        shift({ padding }),\n        ...(matchWidth ? [size({ padding })] : []),\n      ],\n      placement,\n    });\n\n    floating.style.left = `${result.x}px`;\n    floating.style.top = `${result.y}px`;\n\n    // `computePosition()` assumes `left`/`top` resolve relative to the viewport (correct for\n    // `position: fixed`) — true almost always, but not when some ancestor establishes a\n    // containing block for fixed descendants (a non-`none` `transform`, even a visually-identity\n    // one left over from an entrance transition that never resets to `none` at rest is a real,\n    // easy-to-hit case — a modal dialog's panel, say). Analytically detecting *that* ancestor via\n    // `getContainingBlock()` and pre-subtracting its rect turned out to be unreliable in\n    // practice: browsers don't apply the \"ancestor transform traps fixed descendants\" rule\n    // uniformly across every element nested under it in every case we tested — some floating\n    // elements in the exact same subtree needed the correction and some didn't, for reasons we\n    // couldn't fully pin down. Measuring what actually happened after writing `left`/`top`\n    // and correcting only the observed gap sidesteps that: it's a no-op when the browser already\n    // put the element where asked, and it fixes the same class of bug the moment there's a real\n    // mismatch, regardless of which specific ancestor (if any) turns out to be responsible.\n    //\n    // The measurement itself must not be fooled by the floating element's *own* transform,\n    // though: dropdowns/popovers here all use a `transform: translateY(...)` entrance transition\n    // driven by a `[data-open]` attribute + `@starting-style` — right at open, before the\n    // transition has visibly progressed, `getBoundingClientRect()` can still reflect that\n    // starting offset (a handful of px, matching `--overlay-enter-translate-y`), which this\n    // correction would otherwise misread as a permanent ancestor-driven mismatch and bake in\n    // forever. Temporarily neutralizing the floating element's own transform for the measurement\n    // (and restoring it before anything paints, so there's no visible flash) isolates the\n    // correction to ancestor-driven offsets only, which is the only thing it's meant to fix.\n    const prevTransition = floating.style.transition;\n    const prevTransform = floating.style.transform;\n\n    floating.style.transition = 'none';\n    floating.style.transform = 'none';\n\n    const actual = floating.getBoundingClientRect();\n    const deltaX = result.x - actual.left;\n    const deltaY = result.y - actual.top;\n\n    floating.style.transition = prevTransition;\n    floating.style.transform = prevTransform;\n\n    if (deltaX !== 0 || deltaY !== 0) {\n      floating.style.left = `${result.x + deltaX}px`;\n      floating.style.top = `${result.y + deltaY}px`;\n    }\n\n    if (matchWidth) {\n      floating.style.width = `${ref.getBoundingClientRect().width}px`;\n    }\n  }\n\n  function startAutoUpdate(): () => void {\n    const ref = getReference();\n    const floating = getFloating();\n\n    if (!ref || !floating) return () => {};\n\n    return autoUpdate(ref, floating, updatePosition);\n  }\n\n  return { floating: getFloating, reference: getReference, startAutoUpdate, update: updatePosition };\n}\n","import { restoreFocus } from '@vielzeug/focus';\nimport { computed, type Readable, signal } from '@vielzeug/ripple';\n\nimport { RefineConfigError } from '../errors';\nimport {\n  createListControl,\n  type ListNavigationAction,\n  type ListNavigationChange,\n  type ListNavigationTypeaheadOptions,\n} from './nav';\nimport { createOutsidePointerDismissal, type DropdownCloseReason, type OverlayOpenReason } from './overlay';\nimport { createDropdownPositioner, type DropdownPositionerOptions } from './positioner';\n\nexport type ListboxItem = object;\n\n/** Placement-only options for the listbox dropdown positioner. */\nexport type ListboxDropdownPlacementOptions = Omit<DropdownPositionerOptions, 'getFloating' | 'getReference'>;\n\nexport type ListboxDropdownOptions<T extends ListboxItem> = {\n  getBoundary: () => HTMLElement | null;\n  getFocusedOptionElement?: () => HTMLElement | null;\n  getItems: () => readonly T[];\n  getOptionId?: (index: number) => string;\n  getPanel: () => HTMLElement | null;\n  getReference: () => HTMLElement | null;\n  getTrigger?: () => HTMLElement | null;\n  isDisabled?: () => boolean;\n  isItemDisabled?: (item: T, index: number) => boolean;\n  keys?: Partial<Record<ListNavigationAction, readonly string[]>>;\n  loop?: boolean;\n  onClose?: (reason: DropdownCloseReason) => void;\n  onNavigate?: (change: ListNavigationChange<T>) => void;\n  onOpen?: (reason: OverlayOpenReason) => void;\n  orientation?: 'both' | 'horizontal' | 'vertical';\n  positioning?: ListboxDropdownPlacementOptions;\n  restoreFocus?: boolean | (() => boolean);\n  signal: AbortSignal;\n  typeahead?: ListNavigationTypeaheadOptions<T>;\n};\n\nexport type ListboxDropdown<T extends ListboxItem> = {\n  [Symbol.dispose](): void;\n  readonly ariaActiveDescendant: Readable<string | null>;\n  readonly ariaExpanded: Readable<string>;\n  close(reason?: DropdownCloseReason): void;\n  /** Closes the dropdown (without restoring focus) and disposes list navigation state. */\n  dispose(): void;\n  /** `true` after `dispose()` has been called. */\n  readonly disposed: boolean;\n  readonly focusedIndex: Readable<number>;\n  getActiveItem(): T | undefined;\n  handleKeydown(event: KeyboardEvent): boolean;\n  readonly isOpen: Readable<boolean>;\n  navigate(action: ListNavigationAction): number;\n  open(reason?: OverlayOpenReason): void;\n  scrollFocusedIntoView(): void;\n  set(index: number): number;\n  toggle(openReason?: OverlayOpenReason, closeReason?: DropdownCloseReason): void;\n  updatePosition(): void;\n};\n\n/**\n * Internal listbox dropdown behavior for select and combobox. It owns only\n * listbox interactions; menu and other overlay families keep their own logic.\n */\nexport const createListboxDropdown = <T extends ListboxItem>(\n  options: ListboxDropdownOptions<T>,\n): ListboxDropdown<T> => {\n  if (typeof options.getBoundary !== 'function') {\n    throw new RefineConfigError('createListboxDropdown: getBoundary is required');\n  }\n\n  if (typeof options.getPanel !== 'function') {\n    throw new RefineConfigError('createListboxDropdown: getPanel is required');\n  }\n\n  if (typeof options.getReference !== 'function') {\n    throw new RefineConfigError('createListboxDropdown: getReference is required');\n  }\n\n  const isOpen = signal(false);\n  const ariaExpanded = computed(() => String(isOpen.value));\n  let stopPositioning: (() => void) | null = null;\n\n  const positioner = createDropdownPositioner({\n    ...options.positioning,\n    getFloating: options.getPanel,\n    getReference: options.getReference,\n  });\n\n  const scrollFocusedIntoView = (): void => {\n    options.getFocusedOptionElement?.()?.scrollIntoView({ block: 'nearest' });\n  };\n\n  const list = createListControl<T>({\n    disabled: computed(() => !isOpen.value),\n    getItems: options.getItems,\n    isItemDisabled: options.isItemDisabled,\n    keys: options.keys,\n    loop: options.loop ?? true,\n    onNavigate: (change) => {\n      scrollFocusedIntoView();\n      options.onNavigate?.(change);\n    },\n    orientation: options.orientation,\n    signal: options.signal,\n    typeahead: options.typeahead,\n  });\n\n  const ariaActiveDescendant = computed<string | null>(() => {\n    const index = list.focusedIndex.value;\n\n    return options.getOptionId && isOpen.value && index >= 0 ? options.getOptionId(index) : null;\n  });\n\n  const shouldRestoreFocus = (): boolean => {\n    return typeof options.restoreFocus === 'function' ? options.restoreFocus() : (options.restoreFocus ?? true);\n  };\n\n  const close = (reason: DropdownCloseReason = 'programmatic', shouldRestore = true): void => {\n    if (!isOpen.value) return;\n\n    isOpen.value = false;\n    list.reset();\n    stopPositioning?.();\n    stopPositioning = null;\n\n    if (shouldRestore && shouldRestoreFocus() && options.getTrigger) restoreFocus(options.getTrigger);\n\n    options.onClose?.(reason);\n  };\n\n  const open = (reason: OverlayOpenReason = 'programmatic'): void => {\n    if (options.isDisabled?.() || isOpen.value) return;\n\n    isOpen.value = true;\n    positioner.update();\n    stopPositioning = positioner.startAutoUpdate?.() ?? null;\n    options.onOpen?.(reason);\n  };\n\n  const toggle = (openReason: OverlayOpenReason = 'click', closeReason: DropdownCloseReason = 'trigger'): void => {\n    if (isOpen.value) close(closeReason);\n    else open(openReason);\n  };\n\n  createOutsidePointerDismissal({\n    getTargets: () => [options.getBoundary(), options.getPanel()],\n    isActive: () => isOpen.value,\n    onDismiss: () => close('outsideClick'),\n    signal: options.signal,\n  });\n\n  let disposed = false;\n\n  const dispose = (): void => {\n    if (disposed) return;\n\n    disposed = true;\n\n    if (isOpen.value) {\n      isOpen.value = false;\n      list.reset();\n      stopPositioning?.();\n      stopPositioning = null;\n    }\n  };\n\n  options.signal.addEventListener('abort', dispose, { once: true });\n\n  const handleKeydown = (event: KeyboardEvent): boolean => {\n    if (!isOpen.value) return false;\n\n    if (event.key === 'Escape') {\n      event.preventDefault();\n      close('escape');\n\n      return true;\n    }\n\n    return list.handleKeydown(event);\n  };\n\n  return {\n    ariaActiveDescendant,\n    ariaExpanded,\n    close,\n    dispose,\n    get disposed() {\n      return disposed;\n    },\n    focusedIndex: list.focusedIndex,\n    getActiveItem: list.getActiveItem,\n    handleKeydown,\n    isOpen,\n    navigate: list.navigate,\n    open,\n    scrollFocusedIntoView,\n    set: list.set,\n    [Symbol.dispose]: dispose,\n    toggle,\n    updatePosition: positioner.update,\n  };\n};\n","// ── Trigger string parser ─────────────────────────────────────────────────────\n\n/**\n * Parses a comma-separated trigger string into a typed array, filtering against\n * a valid set and falling back to `defaults` when the input is empty or invalid.\n *\n * Used by tooltip and popover to normalise their `trigger` prop values.\n *\n * @example\n * ```ts\n * const VALID = new Set(['click', 'hover', 'focus'] as const);\n * parseStringTriggers('hover,focus', VALID, ['click']); // → ['hover', 'focus']\n * parseStringTriggers('',            VALID, ['click']); // → ['click']\n * ```\n */\nexport const parseStringTriggers = <T extends string>(\n  value: string | null | undefined,\n  valid: ReadonlySet<T>,\n  defaults: T[],\n): T[] => {\n  const parsed = String(value ?? '')\n    .split(',')\n    .map((t) => t.trim())\n    .filter((t): t is T => valid.has(t as T));\n\n  return parsed.length > 0 ? parsed : [...defaults];\n};\n","@layer refine.base {\n  :host {\n    --_bg: var(--card-bg, var(--color-canvas));\n    --_color: var(--card-color, var(--color-contrast-900));\n    --_border: var(--card-border, var(--border));\n    --_border-color: var(--card-border-color, var(--color-divider));\n    --_radius: var(--card-radius, var(--rounded-lg));\n    --_padding: var(--card-padding, var(--size-4));\n    --_shadow: var(--card-shadow, var(--shadow-sm));\n    --_hover-shadow: var(--card-hover-shadow, var(--shadow-md));\n\n    position: relative;\n    display: flex;\n    flex-direction: column;\n  }\n\n  .card {\n    position: relative;\n    display: flex;\n    flex: 1;\n    flex-direction: column;\n    overflow: hidden;\n    color: var(--_color);\n    background: var(--_bg);\n    border-radius: var(--_radius);\n    backdrop-filter: blur(var(--blur-md));\n    transition:\n      box-shadow var(--transition-normal),\n      transform var(--transition-normal),\n      background var(--transition-normal),\n      border-color var(--transition-normal);\n  }\n\n  /* ── Card Structure ───────────────────────── */\n\n  .card-media {\n    flex-shrink: 0;\n    overflow: hidden;\n  }\n\n  .card-media img {\n    display: block;\n    width: 100%;\n    height: auto;\n    object-fit: cover;\n  }\n\n  .card-body {\n    display: flex;\n    flex: 1;\n    flex-direction: column;\n    min-height: 0;\n  }\n\n  .card-header,\n  .card-content,\n  .card-footer {\n    padding: var(--_padding);\n  }\n\n  .card-header {\n    padding-bottom: calc(var(--_padding) / 2);\n  }\n\n  .card-footer {\n    padding-top: calc(var(--_padding) / 2);\n  }\n\n  .card-content {\n    flex: 1;\n  }\n\n  .card-actions {\n    display: flex;\n    flex-wrap: wrap;\n    gap: var(--size-2);\n    align-items: center;\n    padding: var(--_padding);\n    padding-top: calc(var(--_padding) / 2);\n  }\n\n  [hidden] {\n    display: none;\n  }\n}\n\n@layer refine.variants {\n  /* Default — bordered card with shadow */\n  :host(:not([variant], [color])) {\n    --_shadow: var(--card-shadow, var(--shadow-sm));\n  }\n\n  :host(:not([variant], [color])) .card {\n    border: var(--_border) solid var(--_border-color);\n    box-shadow: var(--_shadow);\n  }\n\n  /* Default + color — tinted backdrop */\n  :host(:not([variant])[color]) {\n    --_bg: var(--card-bg, var(--_theme-backdrop));\n    --_border-color: var(--card-border-color, var(--_theme-border));\n  }\n\n  :host(:not([variant])[color]) .card {\n    border: var(--_border) solid var(--_border-color);\n  }\n\n  :host(:not([variant])[color]:hover) {\n    --_bg: var(--card-bg, color-mix(in oklch, var(--_theme-base) 16%, var(--color-contrast-50)));\n    --_border-color: var(--card-border-color, var(--_theme-focus));\n  }\n\n  /* Solid — fully filled with theme color */\n  :host([variant='solid']) {\n    --_bg: var(--card-bg, var(--_theme-base));\n    --_color: var(--card-color, var(--_theme-contrast));\n    --_border-color: var(--card-border-color, var(--_theme-base));\n    --_shadow: var(--card-shadow, var(--shadow-sm));\n  }\n\n  :host([variant='solid']) .card {\n    border: var(--_border) solid var(--_border-color);\n    box-shadow: var(--_shadow);\n  }\n\n  /* Flat — tinted backdrop, subtle border */\n  :host([variant='flat']) {\n    --_border-color: var(--card-border-color, color-mix(in oklch, var(--_theme-border) 50%, transparent));\n  }\n\n  :host([variant='flat']) .card {\n    border: var(--_border) solid var(--_border-color);\n  }\n\n  /* Glass — frosted blur panel */\n  :host([variant='glass']) .card {\n    text-shadow: var(--text-shadow-xs);\n    border: var(--_border) solid var(--_border-color);\n    box-shadow: var(--card-shadow, var(--shadow-md)), var(--inset-shadow-xs);\n    backdrop-filter: blur(var(--blur-lg)) saturate(180%) brightness(1.05);\n  }\n\n  :host([variant='glass']:hover) .card {\n    box-shadow: var(--card-hover-shadow, var(--shadow-xl)), var(--inset-shadow-sm);\n    backdrop-filter: blur(var(--blur-xl)) saturate(200%) brightness(1.1);\n  }\n\n  :host([variant='glass'][interactive]:hover) .card {\n    box-shadow: var(--card-hover-shadow, var(--shadow-2xl)), var(--inset-shadow-sm);\n  }\n}\n\n@layer refine.overrides {\n  /* ── Loading bar ──────────────────────────── */\n\n  /* Bar lives inside .card which already has overflow:hidden,\n       so translateX can sweep freely without any overflow. */\n  .loading-bar {\n    position: absolute;\n    inset-inline-start: 0;\n    top: 0;\n    display: none;\n    width: 65%;\n    height: 3px;\n    background: linear-gradient(90deg, transparent 0%, var(--_theme-base, var(--color-primary)) 50%, transparent 100%);\n  }\n\n  :host([loading]) .loading-bar {\n    display: block;\n    animation: var(--_motion-animation, loading-bar 1.4s linear infinite);\n  }\n\n  /* In RTL the loading bar sweeps right-to-left */\n  :host(:dir(rtl)[loading]) .loading-bar {\n    animation-direction: reverse;\n  }\n\n  /* ── Disabled ─────────────────────────────── */\n\n  :host([disabled]) {\n    pointer-events: none;\n    opacity: 0.6;\n  }\n\n  :host([disabled][interactive]) .card {\n    cursor: not-allowed;\n  }\n\n  /* ── Interactive hover/active ─────────────── */\n\n  :host([interactive]:not([disabled]):hover) .card {\n    box-shadow: var(--_hover-shadow);\n    transform: translateY(-2px) scale(1.01);\n  }\n\n  :host([interactive]) .card {\n    cursor: pointer;\n    will-change: transform;\n  }\n\n  /* `:active` bubbles to every ancestor of whatever element is actually being pressed, so\n     without the `:not(:has(...))` guard, pressing a nested interactive descendant (a swatch\n     button, a slotted `<ore-button>`, a link, etc. — kept in sync with card.ts's\n     `INTERACTIVE_DESCENDANT_SELECTOR`) would *also* visually \"press\" the whole card even though\n     `handleClick` already ignores the click for activation purposes. `:host(:has(...))`\n     (`:has()` as `:host()`'s functional argument) is invalid — `:host()` only accepts a compound\n     selector and doesn't accept `:has()` inside it, so the bare `:host` pseudo-class chained\n     directly with the rest (no parentheses around it) is used instead — same reasoning as\n     list-item.css's identical `:host:has(...)` rules. */\n  :host[interactive]:not([disabled]):active:not(\n    :has(\n      button:active,\n      a[href]:active,\n      input:active,\n      select:active,\n      textarea:active,\n      summary:active,\n      [role='button']:active,\n      [role='link']:active\n    )\n  ) .card {\n    box-shadow: var(--_shadow);\n    transform: translateY(0) scale(0.99);\n    transition:\n      box-shadow var(--transition-fast),\n      transform 120ms var(--ease-spring);\n  }\n\n  :host([interactive]:focus-visible) .card {\n    outline: var(--border-2) solid var(--_theme-focus, var(--color-primary));\n    outline-offset: var(--border-2);\n  }\n\n  /* ── Horizontal orientation ───────────────── */\n\n  :host([orientation='horizontal']) .card {\n    flex-direction: row;\n  }\n\n  :host([orientation='horizontal']) .card-media {\n    width: 30%;\n    min-width: 192px;\n    max-width: 320px;\n  }\n\n  :host([orientation='horizontal']) .card-media img {\n    width: 100%;\n    height: 100%;\n    object-fit: cover;\n  }\n\n  :host([orientation='horizontal']) .card-body {\n    flex: 1;\n  }\n}\n\n@keyframes loading-bar {\n  0% {\n    transform: translateX(-100%);\n  }\n\n  100% {\n    transform: translateX(200%);\n  }\n}\n","import { bind, define, getHost, html, prop, useEmit, useSlots, watchEffect } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport { createInteraction } from '../../core';\nimport { disablableBundle, loadableBundle, themableBundle } from '../../shared';\nimport {\n  colorThemeMixin,\n  elevationMixin,\n  frostVariantMixin,\n  paddingMixin,\n  reducedMotionMixin,\n  roundedVariantMixin,\n} from '../../styles';\nimport type { ElevationLevel, PaddingSize, ThemeColor } from '../../types';\nimport componentStyles from './card.css?inline';\n\nconst INTERACTIVE_DESCENDANT_SELECTOR =\n  'button, a[href], input, select, textarea, summary, [role=\"button\"], [role=\"link\"], [contenteditable=\"\"], [contenteditable=\"true\"]';\n\nfunction isNestedInteractiveTarget(host: HTMLElement, event: Event): boolean {\n  for (const node of event.composedPath()) {\n    if (!(node instanceof HTMLElement)) continue;\n\n    if (node === host) return false;\n\n    if (node.matches(INTERACTIVE_DESCENDANT_SELECTOR) || node.closest(INTERACTIVE_DESCENDANT_SELECTOR)) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\n/** Card component properties */\n\nexport type OreCardEvents = {\n  activate: { originalEvent: MouseEvent | KeyboardEvent; trigger: 'pointer' | 'keyboard' };\n};\n\nexport type OreCardProps = {\n  /** Theme color */\n  color?: ThemeColor;\n  /** Disable interaction */\n  disabled?: boolean;\n  /** Shadow elevation level (0-5) */\n  elevation?: ElevationLevel;\n  /** Make the card interactive (role=button, keyboard nav, emits activate) */\n  interactive?: boolean;\n  /** Show a loading progress bar */\n  loading?: boolean;\n  /** Card orientation */\n  orientation?: 'horizontal';\n  /** Internal padding size */\n  padding?: PaddingSize;\n  /** Visual style variant */\n  variant?: 'solid' | 'flat' | 'glass' | 'frost';\n};\n\n/**\n * A versatile card container with semantic slots for media, header, body, footer, and actions.\n *\n * @element ore-card\n *\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'glass' | 'frost'\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} padding - Internal padding: 'none' | 'sm' | 'md' | 'lg' | 'xl'\n * @attr {string} elevation - Shadow elevation: '0' | '1' | '2' | '3' | '4' | '5'\n * @attr {string} orientation - Card layout: 'horizontal'\n * @attr {boolean} interactive - Enable pointer/keyboard activation\n * @attr {boolean} disabled - Disable card interaction\n * @attr {boolean} loading - Show loading progress bar\n *\n * @fires activate - Emitted when an interactive card is activated. detail: { originalEvent: MouseEvent | KeyboardEvent; trigger: 'pointer' | 'keyboard' }\n *\n * @slot media - Media content displayed at top/left\n * @slot header - Card header (title, subtitle)\n * @slot - Main card content\n * @slot footer - Card footer content\n * @slot actions - Action buttons or links\n *\n * @cssprop --card-bg - Background color\n * @cssprop --card-color - Text color\n * @cssprop --card-border - Border width\n * @cssprop --card-border-color - Border color\n * @cssprop --card-radius - Border radius\n * @cssprop --card-padding - Internal padding\n * @cssprop --card-shadow - Box shadow\n * @cssprop --card-hover-shadow - Shadow on hover\n *\n * @part card - Card root container.\n * @part loading-bar - Loading progress bar.\n * @part media - Media slot container.\n * @part body - Body content container.\n * @part header - Header container.\n * @part content - Content container.\n * @part footer - Footer container.\n * @part actions - Actions slot container.\n * @example\n * ```html\n * <ore-card elevation=\"2\"><h3 slot=\"header\">Title</h3><p>Content</p></ore-card>\n * <ore-card interactive color=\"primary\"><h3 slot=\"header\">Click me</h3></ore-card>\n * <ore-card variant=\"frost\" color=\"secondary\">Frosted card</ore-card>\n * ```\n */\nexport const CARD_TAG = 'ore-card' as const;\ndefine<OreCardProps>(CARD_TAG, {\n  props: {\n    ...themableBundle,\n    ...disablableBundle,\n    ...loadableBundle,\n    elevation: prop.number<ElevationLevel>(),\n    interactive: prop.bool(false),\n    orientation: prop.string<'horizontal'>(),\n    padding: prop.string<PaddingSize>(),\n    variant: prop.string<'solid' | 'flat' | 'glass' | 'frost'>(),\n  },\n\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreCardEvents>();\n    const slots = useSlots();\n    const watch = watchEffect;\n\n    bind({\n      attr: {\n        ariaBusy: () => (props.loading.value ? 'true' : 'false'),\n        ariaDisabled: () => (props.interactive.value ? String(props.disabled.value) : null),\n        role: () => (props.interactive.value ? 'button' : null),\n      },\n    });\n\n    watch(() => {\n      if (props.interactive.value) {\n        el.setAttribute('tabindex', props.disabled.value ? '-1' : '0');\n      } else {\n        el.removeAttribute('tabindex');\n      }\n    });\n\n    // ────────────────────────────────────────────────────────────────\n    // Event Handlers\n    // ────────────────────────────────────────────────────────────────\n\n    const pressControl = createInteraction({\n      disabled: computed(() => !props.interactive.value || Boolean(props.disabled.value)),\n      onPress: (originalEvent, trigger) => {\n        emit('activate', { originalEvent, trigger });\n      },\n    });\n\n    const handleClick = (e: MouseEvent) => {\n      if (!props.interactive.value || props.disabled.value) return;\n\n      if (isNestedInteractiveTarget(el, e)) return;\n\n      pressControl.handleClick(e);\n    };\n\n    const handleKeydown = (e: KeyboardEvent) => {\n      pressControl.handleKeydown(e);\n    };\n\n    bind({\n      on: {\n        click: (e: MouseEvent) => handleClick(e),\n        keydown: (e: KeyboardEvent) => handleKeydown(e),\n      },\n    });\n\n    // ────────────────────────────────────────────────────────────────\n    // Template\n    // ────────────────────────────────────────────────────────────────\n\n    return html`\n      <div class=\"card\" part=\"card\">\n        <div class=\"loading-bar\" part=\"loading-bar\"></div>\n        <div class=\"card-media\" part=\"media\" ?hidden=\"${() => !slots.has('media').value}\">\n          <slot name=\"media\"></slot>\n        </div>\n        <div class=\"card-body\" part=\"body\">\n          <div class=\"card-header\" part=\"header\" ?hidden=\"${() => !slots.has('header').value}\">\n            <slot name=\"header\"></slot>\n          </div>\n          <div class=\"card-content\" part=\"content\" ?hidden=\"${() => !slots.has().value}\">\n            <slot></slot>\n          </div>\n          <div class=\"card-footer\" part=\"footer\" ?hidden=\"${() => !slots.has('footer').value}\">\n            <slot name=\"footer\"></slot>\n          </div>\n          <div class=\"card-actions\" part=\"actions\" ?hidden=\"${() => !slots.has('actions').value}\">\n            <slot name=\"actions\"></slot>\n          </div>\n        </div>\n      </div>\n    `;\n  },\n\n  styles: [\n    colorThemeMixin,\n    elevationMixin,\n    paddingMixin,\n    roundedVariantMixin,\n    frostVariantMixin('.card'),\n    reducedMotionMixin,\n    componentStyles,\n  ],\n});\n","@layer refine.base {\n  :host {\n    --_height: var(--progress-height, var(--size-2, 0.5rem));\n    --_radius: var(--progress-radius, var(--rounded-lg));\n    --_circle-size: var(--progress-circle-size, 6rem);\n    --_circular-label-size: var(--progress-circular-label-size, var(--text-xl, 1.25rem));\n    --_circular-title-size: var(--progress-circular-title-size, var(--text-xs, 0.75rem));\n\n    display: block;\n\n    /* Stretch to fill the parent container (matches native <progress> behaviour).\n         The host's width is set against its parent, so % widths inside shadow DOM\n         (.track, .fill) resolve correctly in any flex/grid/block context. */\n    width: 100%;\n  }\n\n  /* ========================================\n       Linear Bar\n       ======================================== */\n\n  .track {\n    width: 100%;\n    height: var(--_height);\n    overflow: hidden;\n\n    /* contrast-300 (88% lightness) gives a visible groove in light mode */\n    background: var(--progress-track-bg, var(--color-contrast-300, #ddd));\n    border-radius: var(--_radius);\n  }\n\n  .fill {\n    width: var(--_percent, 0%);\n    height: 100%;\n    background: var(--progress-fill, var(--_theme-base, #3b82f6));\n    border-radius: inherit;\n    transform-origin: left;\n    transition: var(--_motion-transition, width var(--transition-normal));\n  }\n\n  /* In RTL the fill grows from the inline-end (physical right) side */\n  :host(:dir(rtl)) .fill {\n    transform-origin: right;\n  }\n\n  /* Indeterminate: sliding bar */\n  @keyframes ore-progress-slide {\n    0% {\n      transform: translateX(-150%) scaleX(0.6);\n    }\n\n    50% {\n      transform: translateX(50%) scaleX(1);\n    }\n\n    100% {\n      transform: translateX(300%) scaleX(0.6);\n    }\n  }\n\n  :host([indeterminate]) .fill {\n    width: 40%;\n    animation: var(--_motion-animation, ore-progress-slide var(--duration-1500) var(--ease-linear) infinite);\n  }\n\n  /* In RTL the indeterminate bar sweeps right-to-left */\n  :host(:dir(rtl)[indeterminate]) .fill {\n    animation-direction: reverse;\n  }\n\n  /* ========================================\n       Vertical Bar\n       ======================================== */\n\n  :host([type='vertical']) {\n    --_width: var(--progress-width, var(--size-2, 0.5rem));\n\n    display: inline-flex;\n    width: auto;\n  }\n\n  :host([type='vertical']) .wrapper {\n    flex-direction: row;\n    gap: var(--progress-label-gap, var(--space-1, 0.25rem));\n    width: auto;\n    height: 100%;\n  }\n\n  :host([type='vertical']) .track {\n    width: var(--_width);\n    height: 100%;\n    overflow: hidden;\n  }\n\n  :host([type='vertical']) .fill {\n    width: 100%;\n    height: var(--_percent, 0%);\n    transform-origin: bottom;\n    transition: var(--_motion-transition, height var(--transition-normal));\n  }\n\n  :host([type='vertical'][indeterminate]) .fill {\n    height: 40%;\n    animation: var(--_motion-animation, ore-progress-slide-v var(--duration-1500) var(--ease-linear) infinite);\n  }\n\n  @keyframes ore-progress-slide-v {\n    0% {\n      transform: translateY(150%) scaleY(0.6);\n    }\n\n    50% {\n      transform: translateY(-50%) scaleY(1);\n    }\n\n    100% {\n      transform: translateY(-300%) scaleY(0.6);\n    }\n  }\n\n  .bar-row-vertical {\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    height: 100%;\n  }\n\n  :host([type='vertical']) .track-outer {\n    display: flex;\n    flex: 1 1 0%;\n    align-items: stretch;\n    justify-content: center;\n    width: auto;\n    height: 100%;\n  }\n\n  /* ========================================\n       Wrapper / Label / Title / Floating label\n       ======================================== */\n\n  /* Flex-column shell for the linear variant */\n  .wrapper {\n    display: flex;\n    flex-direction: column;\n    gap: var(--progress-label-gap, var(--space-1, 0.25rem));\n    width: 100%;\n  }\n\n  /* Header row ─ visible only when [title] is present */\n  .header {\n    display: none;\n    gap: var(--space-2, 0.5rem);\n    align-items: baseline;\n    justify-content: space-between;\n  }\n\n  :host([title]) .header {\n    display: flex;\n  }\n\n  .progress-title {\n    font-size: var(--text-sm, 0.875rem);\n    font-weight: var(--font-weight-medium, 500);\n    line-height: 1.25;\n    color: var(--progress-title-color, currentColor);\n  }\n\n  /* Label inside the header ─ only when both [title] and [label] are set */\n  .header-label {\n    display: none;\n  }\n\n  :host([title][label]) .header-label {\n    display: inline;\n  }\n\n  /* Bar row ─ transparent wrapper by default; becomes a flex row when\n       [label] is present without [title] so the label sits beside the bar */\n  .bar-row {\n    display: contents;\n  }\n\n  :host([label]:not([title])) .bar-row {\n    display: flex;\n    gap: var(--progress-label-gap, var(--space-2, 0.5rem));\n    align-items: center;\n    width: 100%;\n  }\n\n  /* Outer track container ─ always position:relative for floating-label */\n  .track-outer {\n    position: relative;\n    width: 100%;\n  }\n\n  :host([label]:not([title])) .track-outer {\n    flex: 1 1 0%;\n    width: auto;\n    min-width: 0;\n  }\n\n  /* Shared label typography */\n  .end-label {\n    flex-shrink: 0;\n    font-size: var(--text-sm, 0.875rem);\n    line-height: 1.25;\n    color: var(--progress-label-color, currentColor);\n    white-space: nowrap;\n  }\n\n  /* Trailing end label ─ shown only when [label] is present without [title] */\n  .row-label {\n    display: none;\n  }\n\n  :host([label]:not([title])) .row-label {\n    display: inline;\n  }\n\n  /* Floating label chip ─────────────────────────────────────────────────\n       Positioned above the fill endpoint.\n       Formula: left = X% (fill width) − Y (half chip width)\n       Implemented as: left: var(--_percent); transform: translateX(-50%)     */\n  .floating-label {\n    position: absolute;\n    bottom: calc(100% + var(--space-1, 0.25rem));\n    left: var(--_percent, 0%);\n    display: none;\n    padding: var(--space-0-5, 0.125rem) var(--space-2, 0.5rem);\n    font-size: var(--text-xs, 0.75rem);\n    font-weight: var(--font-weight-medium, 500);\n    line-height: 1;\n    color: var(--color-white, #fff);\n    white-space: nowrap;\n    pointer-events: none;\n    user-select: none;\n    background: var(--progress-fill, var(--_theme-base, #3b82f6));\n    border-radius: var(--rounded-md, 0.375rem);\n    transform: translateX(-50%);\n  }\n\n  :host([floating-label]:not([indeterminate])) .floating-label {\n    display: block;\n  }\n\n  /* Reserve vertical space above the track so the chip does not clip */\n  :host([floating-label]:not([indeterminate])) .wrapper {\n    padding-top: calc(var(--text-xs, 0.75rem) + var(--space-1, 0.25rem) * 3);\n  }\n\n  /* ========================================\n       Circular variant\n       ======================================== */\n\n  .circular-track {\n    position: relative; /* anchor the inner text overlay */\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    width: var(--_circle-size);\n    height: var(--_circle-size);\n  }\n\n  .circular-track svg {\n    width: 100%;\n    height: 100%;\n    overflow: visible;\n    transform: rotate(-90deg);\n  }\n\n  /* Inner overlay — label + title stacked and centered inside the ring */\n  .circular-inner {\n    position: absolute;\n    inset: 0;\n    display: flex;\n    flex-direction: column;\n    gap: var(--space-0-5, 0.125rem);\n    align-items: center;\n    justify-content: center;\n\n    /* Inset from the stroke edge so text stays clear of the ring */\n    padding: calc(8% + var(--_height));\n    overflow: hidden;\n    text-align: center;\n    pointer-events: none;\n  }\n\n  .circular-label {\n    max-width: 100%;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    font-size: var(--_circular-label-size);\n    font-weight: var(--font-weight-semibold, 600);\n    line-height: 1;\n    color: var(--progress-label-color, currentColor);\n    white-space: nowrap;\n  }\n\n  .circular-title {\n    max-width: 100%;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    font-size: var(--_circular-title-size);\n    line-height: 1.25;\n    color: var(--progress-title-color, var(--color-contrast-500, #6b7280));\n    white-space: nowrap;\n  }\n\n  /* Hide empty inner text nodes so flexbox gap doesn't create phantom space */\n  .circular-label:empty,\n  .circular-title:empty {\n    display: none;\n  }\n\n  .circle-bg {\n    fill: none;\n    stroke: var(--progress-track-bg, var(--color-contrast-300, #ddd));\n    stroke-width: var(--progress-stroke-width, calc(var(--_height) * 1.2));\n  }\n\n  .circle-fill {\n    fill: none;\n    stroke: var(--progress-fill, var(--_theme-base, #3b82f6));\n    stroke-width: var(--progress-stroke-width, calc(var(--_height) * 1.2));\n    stroke-linecap: round;\n    transition: var(--_motion-transition, stroke-dashoffset var(--transition-normal));\n  }\n\n  @keyframes ore-progress-spin {\n    from {\n      transform: rotate(-90deg);\n    }\n\n    to {\n      transform: rotate(270deg);\n    }\n  }\n\n  @keyframes ore-progress-dash {\n    0% {\n      stroke-dasharray: 1px var(--_circ);\n      stroke-dashoffset: var(--_circ);\n    }\n\n    40% {\n      stroke-dasharray: calc(var(--_circ) * 0.75) var(--_circ);\n      stroke-dashoffset: calc(var(--_circ) * -0.1);\n    }\n\n    60% {\n      stroke-dasharray: calc(var(--_circ) * 0.75) var(--_circ);\n      stroke-dashoffset: calc(var(--_circ) * -0.1);\n    }\n\n    100% {\n      stroke-dasharray: 1px var(--_circ);\n      stroke-dashoffset: calc(var(--_circ) * -0.9);\n    }\n  }\n\n  :host([indeterminate]) .circular-track svg {\n    animation: var(--_motion-animation, ore-progress-spin var(--duration-1400) var(--ease-linear) infinite);\n  }\n\n  :host([indeterminate]) .circle-fill {\n    animation: var(--_motion-animation, ore-progress-dash var(--duration-1400) var(--ease-in-out) infinite);\n  }\n}\n\n@layer refine.utilities {\n  :host([size='sm']) {\n    --_height: var(--size-1, 0.25rem);\n    --_circle-size: 4rem;\n    --_circular-label-size: var(--text-sm, 0.875rem);\n    --_circular-title-size: var(--text-2xs, 0.625rem);\n  }\n\n  :host([size='md']) {\n    --_height: var(--size-2, 0.5rem);\n    --_circle-size: 6rem;\n  }\n\n  :host([size='lg']) {\n    --_height: var(--size-3-5, 0.875rem);\n    --_circle-size: 9rem;\n    --_circular-label-size: var(--text-3xl);\n    --_circular-title-size: var(--text-sm, 0.875rem);\n  }\n}\n\n/* Extra indeterminate state overrides — cannot be expressed via CSS variables alone */\n@media (prefers-reduced-motion: reduce) {\n  :host([indeterminate]) .fill {\n    width: 100%;\n    opacity: 0.6;\n  }\n\n  :host([indeterminate]) .circle-fill {\n    stroke-dasharray: none;\n  }\n\n  :host([type='vertical'][indeterminate]) .fill {\n    height: 100%;\n    opacity: 0.6;\n  }\n}\n","import { define, getHost, html, prop, styleMap, watchEffect } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport { sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, forcedColorsMixin, reducedMotionMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport componentStyles from './progress.css?inline';\n\n/** Progress bar component properties */\nexport type OreProgressProps = {\n  /** Theme color for the fill bar */\n  color?: ThemeColor;\n  /** Floating chip centered above the fill endpoint (linear only). Hidden in indeterminate mode. Position formula: left = fill% − half chip width (CSS: left:X%; transform:translateX(−50%)). */\n  'floating-label'?: string;\n  /** When true, shows an infinite animation — use when progress is unknown. */\n  indeterminate?: boolean;\n  /** Accessible name AND visible text label.\n   * - Linear without `title`: rendered at the end of the bar.\n   * - Linear with `title`: moved into the header row above the bar.\n   * - Circular: large text centered inside the ring. */\n  label?: string;\n  /** Maximum value. Defaults to 100. */\n  max?: number;\n  /** Size variant controlling bar height */\n  size?: ComponentSize;\n  /** Title text.\n   * - Linear: displayed as a header above the bar; moves `label` into the header row.\n   * - Circular: smaller text displayed below the `label` inside the ring. */\n  title?: string;\n  /** 'linear' (default), 'circular', or 'vertical' */\n  type?: 'linear' | 'circular' | 'vertical';\n  /** Current progress value (0 to `max`). Ignored when `indeterminate`. */\n  value?: number;\n  /** Human-readable value text for screen readers (e.g. \"Step 2 of 5\", \"75%\"). Overrides the raw aria-valuenow when set. */\n  'value-text'?: string;\n};\n\n/**\n * A linear progress bar for conveying operation progress.\n * Supports determinate (known value) and indeterminate (unknown duration) modes.\n *\n * @element ore-progress\n *\n * @attr {number} value   - Current value (0–max). Defaults to 0.\n * @attr {number} max     - Maximum value. Defaults to 100.\n * @attr {boolean} indeterminate - Show infinite animation (ignores value/max).\n * @attr {string} color   - Theme color: 'primary' | 'success' | 'warning' | 'error' | …\n * @attr {string} size    - Bar height/width: 'sm' | 'md' | 'lg'\n * @attr {string} type   - 'linear' (default) | 'circular' | 'vertical'\n *\n * @cssprop --progress-width  - Bar width override (vertical only)\n * @attr {string} label          - Visible text label + accessible name. Linear: at bar end (or header row with title). Circular: large text centered inside the ring.\n * @attr {string} title          - Title text. Linear: header above the bar (moves label to header row). Circular: smaller text below the label inside the ring.\n * @attr {string} floating-label - Floating chip centered above the fill endpoint (linear only); hidden when indeterminate.\n *\n * @cssprop --progress-height               - Bar height override\n * @cssprop --progress-track-bg             - Track background color\n * @cssprop --progress-fill                 - Fill bar color\n * @cssprop --progress-radius               - Border radius\n * @cssprop --progress-label-gap            - Gap between header/bar row and between bar and trailing label (default 0.25 rem)\n * @cssprop --progress-title-color          - Title text color (defaults to currentColor)\n * @cssprop --progress-label-color          - Label text color (defaults to currentColor)\n * @cssprop --progress-circle-size          - Circular indicator diameter (default 6rem)\n * @cssprop --progress-circular-label-size  - Font size of the label inside the ring (default --text-xl)\n * @cssprop --progress-circular-title-size  - Font size of the title inside the ring (default --text-xs)\n *\n * @part fill - Progress fill element.\n * @example\n * ```html\n * <ore-progress value=\"45\"></ore-progress>\n * <ore-progress value=\"75\" max=\"100\" color=\"success\" size=\"lg\"></ore-progress>\n * <ore-progress indeterminate color=\"primary\" label=\"Loading…\"></ore-progress>\n * ```\n */\nexport const PROGRESS_TAG = 'ore-progress' as const;\ndefine<OreProgressProps>(PROGRESS_TAG, {\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    'floating-label': prop.string(),\n    indeterminate: prop.bool(false),\n    label: prop.string(),\n    max: prop.number(100),\n    title: prop.string(),\n    type: prop.oneOf(['linear', 'circular', 'vertical'] as const, 'linear'),\n    value: prop.number(0),\n    'value-text': prop.string(),\n  },\n\n  setup(props) {\n    const el = getHost();\n    const watch = watchEffect;\n\n    // The SVG circle circumference for a radius of 45 (viewBox 0 0 100 100)\n    const RADIUS = 45;\n    const CIRC = 2 * Math.PI * RADIUS; // ~282.7\n\n    const percent = computed(() => {\n      const v = Math.max(0, Math.min(Number(props.value.value), Number(props.max.value)));\n      const m = Math.max(1, Number(props.max.value));\n\n      return `${(v / m) * 100}%`;\n    });\n\n    const dashoffset = computed(() => {\n      const v = Math.max(0, Math.min(Number(props.value.value), Number(props.max.value)));\n      const m = Math.max(1, Number(props.max.value));\n\n      return CIRC - (v / m) * CIRC;\n    });\n\n    const ariaValueNow = () => (props.indeterminate.value ? null : String(props.value.value));\n    const ariaLabel = () => props.label.value ?? props.title.value ?? 'Progress';\n    const circularStyle = styleMap({ '--_circ': `${CIRC}px` });\n    const strokeDasharray = () => (props.indeterminate.value ? undefined : `${CIRC}px`);\n    const strokeDashoffset = () => (props.indeterminate.value ? undefined : `${dashoffset.value}px`);\n    const isVertical = computed(() => props.type.value === 'vertical');\n    const linearFillStyle = styleMap({\n      height: () => (!props.indeterminate.value && isVertical.value ? percent.value : null),\n      width: () => (!props.indeterminate.value && !isVertical.value ? percent.value : null),\n    });\n\n    watch(() => {\n      el.style.setProperty('--_percent', props.indeterminate.value ? '0%' : percent.value);\n    });\n\n    const circularTemplate = () => html`\n      <div\n        class=\"circular-track\"\n        role=\"progressbar\"\n        aria-valuenow=\"${ariaValueNow}\"\n        aria-valuemin=\"0\"\n        aria-valuemax=\"${props.max}\"\n        aria-label=\"${ariaLabel}\"\n        aria-valuetext=\"${props['value-text']}\"\n        style=\"${circularStyle}\">\n        <svg viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">\n          <circle class=\"circle-bg\" cx=\"50\" cy=\"50\" r=\"${RADIUS}\"></circle>\n          <circle\n            class=\"circle-fill\"\n            cx=\"50\"\n            cy=\"50\"\n            r=\"${RADIUS}\"\n            stroke-dasharray=\"${strokeDasharray}\"\n            stroke-dashoffset=\"${strokeDashoffset}\"></circle>\n        </svg>\n        <div class=\"circular-inner\">\n          <span class=\"circular-label\">${() => props.label.value ?? ''}</span>\n          <span class=\"circular-title\">${() => props.title.value ?? ''}</span>\n        </div>\n      </div>\n    `;\n\n    const barTemplate = () => html`\n      <div class=\"wrapper\">\n        <div class=\"header\">\n          <span class=\"progress-title\">${() => props.title.value ?? ''}</span>\n          <span class=\"end-label header-label\">${() => props.label.value ?? ''}</span>\n        </div>\n        <div class=${() => `bar-row${isVertical.value ? ' bar-row-vertical' : ''}`}>\n          <div class=\"track-outer\">\n            <div\n              class=\"track\"\n              role=\"progressbar\"\n              aria-valuenow=\"${ariaValueNow}\"\n              aria-valuemin=\"0\"\n              aria-valuemax=\"${props.max}\"\n              aria-label=\"${ariaLabel}\"\n              aria-valuetext=\"${props['value-text']}\">\n              <div class=\"fill\" part=\"fill\" style=\"${linearFillStyle}\"></div>\n            </div>\n            ${() =>\n              !isVertical.value\n                ? html`\n                    <span class=\"floating-label\">${props['floating-label']}</span>\n                  `\n                : null}\n          </div>\n          <span class=\"end-label row-label\">${() => props.label.value ?? ''}</span>\n        </div>\n      </div>\n    `;\n\n    return html`\n      ${() => (props.type.value === 'circular' ? circularTemplate() : barTemplate())}\n    `;\n  },\n\n  styles: [colorThemeMixin, forcedColorsMixin, reducedMotionMixin, componentStyles],\n});\n","@layer refine.base {\n  :host {\n    --_bg: var(--carousel-bg, var(--color-canvas));\n    --_radius: var(--carousel-radius, var(--rounded-xl));\n    --_dot-bg: var(--carousel-dot-bg, var(--color-contrast-300));\n    --_dot-active-bg: var(--carousel-dot-active-bg, var(--color-contrast-700));\n\n    position: relative;\n    display: flex;\n    flex-direction: column;\n    width: 100%;\n    min-height: var(--carousel-min-height, 240px);\n    overflow: hidden;\n    touch-action: auto;\n    outline: none;\n    background: var(--_bg);\n    border-radius: var(--_radius);\n  }\n\n  /* ── Track ──────────────────────────────────────────────────────── */\n\n  .track {\n    position: relative;\n    flex: 1 1 auto;\n    width: 100%;\n    min-height: 0;\n  }\n\n  /* ── Controls (prev / next) ────────────────────────────────────────────── */\n\n  /* Controls live inside the bottom nav bar, right-aligned via margin-inline-start: auto. */\n\n  .controls {\n    display: flex;\n    gap: var(--size-0-5);\n    align-items: center;\n    margin-inline-start: auto;\n    pointer-events: none;\n  }\n\n  /* Controls rendered standalone (no indicators bar) — needs own positioning + backdrop. */\n  :host > .controls {\n    position: absolute;\n    inset-block-end: var(--size-3);\n    inset-inline-end: var(--size-3);\n    padding: var(--size-1-5) var(--size-2);\n    margin-inline-start: 0;\n    background: color-mix(in oklch, var(--color-canvas) 55%, transparent);\n    border-radius: var(--rounded-full);\n    backdrop-filter: blur(6px);\n  }\n\n  .nav-btn {\n    pointer-events: auto;\n  }\n\n  /* ── Variant-specific track styles ────────────────────────────────────── */\n\n  /* Gallery: flex row, fills host, shows active + two thumbnails */\n  :host([variant='gallery']) .track {\n    position: absolute;\n    inset: 0;\n    display: flex;\n    flex-direction: row;\n    gap: var(--carousel-gallery-gap, var(--size-2));\n    align-items: stretch;\n    overflow: hidden;\n  }\n\n  :host([variant='gallery'][orientation='vertical']) .track {\n    flex-direction: column;\n    align-items: stretch;\n  }\n\n  /* Filmstrip: flex row/column with absolute positioning to fill host */\n  :host([variant='filmstrip']) .track {\n    position: absolute;\n    inset: 0;\n    display: flex;\n    flex-direction: row;\n    gap: var(--carousel-filmstrip-gap, var(--size-2));\n    align-items: stretch;\n    overflow: hidden;\n  }\n\n  :host([variant='filmstrip'][orientation='vertical']) .track {\n    flex-direction: column;\n    width: 100%;\n  }\n\n  /* ── Vertical orientation ──────────────────────────────────────────────── */\n\n  :host([orientation='vertical']) {\n    --_slide-translate-before: translateY(-100%);\n    --_slide-translate-after: translateY(100%);\n  }\n\n  :host([orientation='vertical']) .indicators {\n    inset-block: 50% auto;\n    inset-inline: var(--size-3) auto;\n    flex-direction: column;\n    width: auto;\n    height: max-content;\n    padding-block: var(--size-6) var(--size-2);\n    padding-inline: var(--size-1-5);\n    border-radius: var(--rounded-full);\n    transform: translateX(0) translateY(-50%);\n  }\n\n  :host([orientation='vertical']) .controls {\n    flex-direction: column;\n    margin-block-start: auto;\n    margin-inline-start: 0;\n  }\n\n  :host([orientation='vertical']) > .controls {\n    inset-block-end: var(--size-3);\n    inset-inline-end: var(--size-3);\n    margin-block-start: 0;\n  }\n\n  :host([orientation='vertical']) .indicator:not(.indicator-active) {\n    width: var(--size-2);\n    height: var(--size-2);\n  }\n\n  :host([orientation='vertical']) .indicator-active {\n    width: var(--size-1-5);\n    height: var(--size-8);\n  }\n\n  /* animation properties are inherited from .indicator-active ore-progress::part(fill) below */\n\n  /* ── Bottom nav bar: indicators + controls ───────────────────────────── */\n\n  /* Floats above the bottom edge, shrinks to content width, centered.\n     A frosted backdrop keeps it legible over any image. */\n\n  .indicators {\n    position: absolute;\n    inset-block-end: var(--size-3);\n    inset-inline: 50%;\n    display: flex;\n    flex-direction: row;\n    gap: var(--size-1-5);\n    align-items: center;\n    width: max-content;\n    padding: var(--size-1-5) var(--size-2) var(--size-1-5) var(--size-6);\n    pointer-events: none;\n    background: color-mix(in oklch, var(--color-canvas) 55%, transparent);\n    border-radius: var(--rounded-full);\n    backdrop-filter: blur(6px);\n    transform: translateX(-50%);\n  }\n\n  .indicator {\n    display: block;\n    flex-shrink: 0;\n    padding: 0;\n    pointer-events: auto;\n    cursor: pointer;\n    background: none;\n    border: none;\n    transition: opacity var(--transition-fast);\n  }\n\n  .indicator > ore-progress {\n    display: block;\n    width: 100%;\n    height: 100%;\n    pointer-events: none;\n  }\n\n  /* Inactive indicator: small circle */\n  .indicator:not(.indicator-active) {\n    width: var(--size-2);\n    height: var(--size-2);\n    overflow: hidden;\n    border-radius: var(--rounded-full);\n  }\n\n  /* Active indicator: wider pill (progress bar) */\n  .indicator-active {\n    --progress-track-bg: color-mix(in oklch, var(--_dot-bg) 60%, transparent);\n    width: var(--size-8);\n  }\n\n  .indicator:focus-visible {\n    outline: var(--border) solid currentcolor;\n    outline-offset: 2px;\n  }\n\n  .indicator:hover {\n    opacity: 0.8;\n  }\n\n  .indicator ore-progress::part(fill) {\n    transition: width var(--transition-normal);\n  }\n\n  .indicator-active ore-progress::part(fill) {\n    animation-name: var(--carousel-animation-name, none);\n    animation-duration: calc(var(--carousel-timeout, 4000) * 1ms);\n    animation-timing-function: var(--ease-linear);\n    animation-fill-mode: forwards;\n  }\n}\n\n@media (prefers-reduced-motion: reduce) {\n  :host {\n    --carousel-transition-duration: 0s;\n  }\n}\n\n@keyframes carousel-fill {\n  from {\n    width: 0%;\n  }\n\n  to {\n    width: 100%;\n  }\n}\n\n@keyframes carousel-fill-v {\n  from {\n    height: 0%;\n  }\n\n  to {\n    height: 100%;\n  }\n}\n","/* ── Default: translate in/out ───────────────────────────────────────────── */\n:host {\n  position: absolute;\n  inset: 0;\n  display: block;\n  width: 100%;\n  height: 100%;\n  overflow: hidden;\n  pointer-events: none;\n  opacity: 0;\n  transform: var(--_slide-translate-after, translateX(100%));\n  transition:\n    transform var(--carousel-transition-duration, 0.35s) var(--ease-move),\n    opacity var(--carousel-transition-duration, 0.35s) var(--ease-move);\n}\n\n:host([data-before]) {\n  transform: var(--_slide-translate-before, translateX(-100%));\n}\n\n:host([data-active]) {\n  pointer-events: auto;\n  opacity: 1;\n  transform: translate(0, 0);\n}\n\n/* ── Fade variant ────────────────────────────────────────────────────────── */\n:host([data-variant='fade']) {\n  transform: none;\n  transition: opacity var(--carousel-transition-duration, 0.35s) var(--ease-move);\n}\n\n/* ── Filmstrip variant — shared ──────────────────────────────────────────── */\n:host([data-variant='filmstrip']) {\n  position: relative;\n  inset: auto;\n  flex-shrink: 0;\n  align-self: stretch;\n  pointer-events: auto;\n  border-radius: var(--carousel-radius, var(--rounded-xl));\n  opacity: 1;\n  transform: none;\n  transition:\n    flex var(--carousel-transition-duration, 0.35s) var(--ease-move),\n    opacity var(--carousel-transition-duration, 0.35s) var(--ease-move);\n}\n\n/* ── Filmstrip variant (horizontal) ──────────────────────────────────────── */\n:host([data-variant='filmstrip'][data-orientation='horizontal']) {\n  flex: 0 0 var(--carousel-filmstrip-inactive, var(--size-16));\n  width: auto;\n  min-width: var(--carousel-filmstrip-inactive, var(--size-16));\n  height: 100%;\n}\n\n:host([data-variant='filmstrip'][data-orientation='horizontal'][data-active]) {\n  flex: 1 1 0;\n}\n\n/* ── Filmstrip variant (vertical) ────────────────────────────────────────── */\n:host([data-variant='filmstrip'][data-orientation='vertical']) {\n  flex: 0 0 var(--carousel-filmstrip-inactive, var(--size-10));\n  width: 100%;\n  height: auto;\n  min-height: var(--carousel-filmstrip-inactive, var(--size-10));\n}\n\n:host([data-variant='filmstrip'][data-orientation='vertical'][data-active]) {\n  flex: 1 1 0;\n}\n\n/* ── Gallery variant — shared base ───────────────────────────────────────── */\n:host([data-variant='gallery']) {\n  display: none;\n}\n\n:host([data-variant='gallery'][data-gallery-visible]) {\n  position: relative;\n  inset: auto;\n  display: block;\n  align-self: stretch;\n  overflow: hidden;\n  pointer-events: auto;\n  border-radius: var(--carousel-radius, var(--rounded-xl));\n  opacity: 0.5;\n  transform: none;\n  transition:\n    flex var(--carousel-transition-duration, 0.35s) var(--ease-move),\n    opacity var(--carousel-transition-duration, 0.35s) var(--ease-move);\n}\n\n:host([data-variant='gallery'][data-gallery-visible][data-active]) {\n  opacity: 1;\n}\n\n/* ── Gallery variant (horizontal) ────────────────────────────────────────── */\n:host([data-variant='gallery'][data-orientation='horizontal'][data-gallery-visible]) {\n  flex: 0 0 var(--carousel-gallery-thumbnail, var(--size-24));\n  flex-shrink: 0;\n  width: auto;\n  min-width: var(--carousel-gallery-thumbnail, var(--size-24));\n  height: 100%;\n}\n\n:host([data-variant='gallery'][data-orientation='horizontal'][data-gallery-visible][data-active]) {\n  flex: 1 1 0;\n}\n\n/* ── Gallery variant (vertical) ──────────────────────────────────────────── */\n:host([data-variant='gallery'][data-orientation='vertical'][data-gallery-visible]) {\n  flex: 1 1 0;\n  width: 100%;\n  height: auto;\n}\n\n:host([data-variant='gallery'][data-orientation='vertical'][data-gallery-visible][data-active]) {\n  flex: 4 1 0;\n}\n\n::slotted(*) {\n  max-width: 100%;\n}\n","import { bind, define, html } from '@vielzeug/ore';\n\nimport slideStyles from './carousel-slide.css?inline';\n\nexport const CAROUSEL_SLIDE_TAG = 'ore-carousel-slide' as const;\n\ndefine(CAROUSEL_SLIDE_TAG, {\n  props: {},\n  setup(_props) {\n    bind({\n      attr: {\n        'aria-roledescription': () => 'slide',\n        role: () => 'group',\n      },\n    });\n\n    return html`\n      <slot></slot>\n    `;\n  },\n  styles: [slideStyles],\n});\n","import { createPanGesture } from '@vielzeug/gesture';\nimport { bind, define, getHost, html, onCleanup, onMounted, prop, useEmit } from '@vielzeug/ore';\nimport { computed, signal, watch } from '@vielzeug/ripple';\n\nimport type { ThemeColor } from '../../types';\n\nimport '../../content/icon/icon';\nimport '../../feedback/progress/progress';\nimport { announce, createListControl, lifecycleSignal } from '../../core';\nimport componentStyles from './carousel.css?inline';\nimport './carousel-slide';\n\nexport { CAROUSEL_SLIDE_TAG } from './carousel-slide';\n\n// ── Types ──────────────────────────────────────────────────────────────────────\n\nexport type CarouselOrientation = 'horizontal' | 'vertical';\nexport type CarouselVariant = 'default' | 'fade' | 'filmstrip' | 'gallery';\n\nexport type OreCarouselEvents = {\n  /** Fired when the active slide changes. */\n  change: { index: number };\n};\n\nexport type OreCarouselProps = {\n  /**\n   * Whether to advance slides automatically. Defaults to `false`.\n   * Opt in explicitly — autoplay on by default is a WCAG 2.1 SC 2.2.2 violation for many use cases.\n   */\n  autoplay?: boolean;\n  /** Interval in milliseconds between automatic slide advances. Defaults to `5000`. */\n  'autoplay-interval'?: number;\n  /** Theme color passed to the prev/next navigation buttons. */\n  color?: ThemeColor;\n  /** Accessible label for the carousel region. */\n  label?: string;\n  /** Whether the carousel loops from the last slide back to the first. Defaults to `true`. */\n  loop?: boolean;\n  /** Carousel orientation. Defaults to `'horizontal'`. */\n  orientation?: CarouselOrientation;\n  /** Show next/prev navigation buttons. Defaults to `true`. */\n  'show-controls'?: boolean;\n  /** Show dot/indicator navigation. Defaults to `true`. */\n  'show-indicators'?: boolean;\n  /** Index of the currently active slide (zero-based). Defaults to `0`. */\n  'slide-index'?: number;\n  /**\n   * Layout variant.\n   * - `'default'`   — slides translate in/out (default)\n   * - `'fade'`      — slides crossfade; no movement\n   * - `'filmstrip'` — all slides visible side-by-side; active expands\n   * - `'gallery'`   — active slide fills the majority; adjacent slides show as thumbnails\n   */\n  variant?: CarouselVariant;\n};\n\n/**\n * An accessible, keyboard-navigable carousel / slideshow with optional\n * autoplay, swipe support, and indicator dots.\n *\n * Place `<ore-carousel-slide>` elements as direct children.\n *\n * @element ore-carousel\n * @element ore-carousel-slide - Child element for individual slides\n *\n * @attr {string}  color             - Theme color for navigation buttons: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {boolean} autoplay          - Advance slides automatically (default false)\n * @attr {number}  autoplay-interval - Milliseconds between automatic advances (default 5000)\n * @attr {string}  label             - Accessible label for the carousel region\n * @attr {boolean} loop              - Loop from last slide to first (default true)\n * @attr {string}  orientation       - 'horizontal' (default) | 'vertical'\n * @attr {string}  variant           - 'default' | 'fade' | 'filmstrip' | 'gallery'\n * @attr {boolean} show-controls     - Show prev/next buttons (default true)\n * @attr {boolean} show-indicators   - Show indicator dots (default true)\n * @attr {number}  slide-index       - Active slide index (zero-based, default 0)\n *\n * @fires change - Fires when the active slide changes. detail: { index: number }\n *\n * @slot - Place `<ore-carousel-slide>` elements here\n *\n * @cssprop --carousel-bg                  - Slide area background\n * @cssprop --carousel-radius              - Border radius of the carousel\n * @cssprop --carousel-dot-bg              - Inactive indicator color (default: var(--color-contrast-300))\n * @cssprop --carousel-dot-active-bg       - Active indicator / fill color (default: var(--color-contrast-700))\n * @cssprop --carousel-transition-duration - Slide transition duration (default 0.35s; 0s under prefers-reduced-motion).\n * @cssprop --carousel-min-height          - Minimum height when no explicit height is set (default 240px)\n * @cssprop --carousel-filmstrip-inactive  - Width (horizontal) or height (vertical) of inactive slides in filmstrip mode\n * @cssprop --carousel-filmstrip-gap       - Gap between slides in filmstrip mode\n * @cssprop --carousel-gallery-thumbnail   - Width (horizontal) or height (vertical) of thumbnail slides in gallery mode (default var(--size-24))\n * @cssprop --carousel-gallery-gap         - Gap between slides in gallery mode (default var(--size-2))\n *\n * @part track      - The scrolling slide track element\n * @part controls   - The prev/next button container\n * @part indicators - The indicator dots container\n * @part prev-btn   - The previous-slide button\n * @part next-btn   - The next-slide button\n *\n * @example\n * ```html\n * <ore-carousel label=\"Product highlights\" loop>\n *   <ore-carousel-slide>Slide 1</ore-carousel-slide>\n *   <ore-carousel-slide>Slide 2</ore-carousel-slide>\n *   <ore-carousel-slide>Slide 3</ore-carousel-slide>\n * </ore-carousel>\n * ```\n */\nexport const CAROUSEL_TAG = 'ore-carousel' as const;\n\n// ── Slide-state sync helpers ──────────────────────────────────────────────────\n// Each function handles exactly one variant's attribute bookkeeping.\n// Called from a dispatch table in syncActiveState.\n\nconst syncDefaultSlides = (slides: HTMLElement[], current: number): void => {\n  const count = slides.length;\n\n  slides.forEach((slide, i) => {\n    const active = i === current;\n\n    slide.toggleAttribute('data-active', active);\n    slide.setAttribute('aria-hidden', String(!active));\n    slide.setAttribute('aria-label', slide.getAttribute('aria-label') ?? `Slide ${i + 1} of ${count}`);\n    slide.removeAttribute('data-gallery-visible');\n    slide.toggleAttribute('data-before', i < current);\n    slide.toggleAttribute('data-after', i > current);\n  });\n};\n\nconst syncFilmstripSlides = (slides: HTMLElement[], current: number): void => {\n  const count = slides.length;\n\n  slides.forEach((slide, i) => {\n    const active = i === current;\n\n    slide.toggleAttribute('data-active', active);\n    slide.setAttribute('aria-hidden', String(!active));\n    slide.setAttribute('aria-label', slide.getAttribute('aria-label') ?? `Slide ${i + 1} of ${count}`);\n    slide.removeAttribute('data-gallery-visible');\n    slide.removeAttribute('data-before');\n    slide.removeAttribute('data-after');\n  });\n};\n\nconst syncGallerySlides = (slides: HTMLElement[], current: number): void => {\n  const count = slides.length;\n\n  slides.forEach((slide, i) => {\n    const active = i === current;\n    const isPrev = current > 0 && i === current - 1;\n    const isNext = current < count - 1 && i === current + 1;\n\n    slide.toggleAttribute('data-active', active);\n    slide.setAttribute('aria-hidden', String(!active));\n    slide.setAttribute('aria-label', slide.getAttribute('aria-label') ?? `Slide ${i + 1} of ${count}`);\n    slide.removeAttribute('data-before');\n    slide.removeAttribute('data-after');\n    slide.toggleAttribute('data-gallery-visible', active || isPrev || isNext);\n  });\n};\n\n// ── ore-carousel ──────────────────────────────────────────────────────────────\n\ndefine<OreCarouselProps>(CAROUSEL_TAG, {\n  props: {\n    autoplay: prop.bool(false),\n    'autoplay-interval': prop.number(5000),\n    color: prop.string<ThemeColor>(),\n    label: prop.string('Carousel'),\n    loop: prop.bool(true),\n    orientation: prop.string<CarouselOrientation>('horizontal'),\n    'show-controls': prop.bool(true),\n    'show-indicators': prop.bool(true),\n    'slide-index': prop.number(0),\n    variant: prop.string<CarouselVariant>('default'),\n  },\n\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreCarouselEvents>();\n\n    // ── State ────────────────────────────────────────────────────────────────\n\n    const activeIndex = signal<number>(props['slide-index'].value ?? 0);\n    let autoplayTimer: ReturnType<typeof setInterval> | null = null;\n\n    // Slide cache — populated immediately, refreshed on slotchange.\n    let slides: HTMLElement[] = Array.from(el.querySelectorAll<HTMLElement>(':scope > ore-carousel-slide'));\n    const slideCount = signal(slides.length);\n\n    const refreshSlides = (): void => {\n      slides = Array.from(el.querySelectorAll<HTMLElement>(':scope > ore-carousel-slide'));\n      slideCount.value = slides.length;\n    };\n\n    const isHorizontal = computed(() => props.orientation.value !== 'vertical');\n    const looping = computed(() => props.loop.value !== false);\n    const showControls = computed(() => props['show-controls'].value !== false);\n    const showIndicators = computed(() => props['show-indicators'].value !== false);\n\n    const canGoPrev = computed(() => looping.value || activeIndex.value > 0);\n    const canGoNext = computed(() => looping.value || activeIndex.value < slideCount.value - 1);\n\n    // ── Navigation ───────────────────────────────────────────────────────────\n\n    const goTo = (index: number, announce_: boolean = true): void => {\n      const count = slideCount.value;\n\n      if (count === 0) return;\n\n      const next = looping.value ? ((index % count) + count) % count : Math.max(0, Math.min(index, count - 1));\n\n      if (next === activeIndex.value) return;\n\n      activeIndex.value = next;\n      el.setAttribute('slide-index', String(next));\n      emit('change', { index: next });\n\n      if (announce_) {\n        announce(slides[next]?.getAttribute('aria-label') ?? `Slide ${next + 1} of ${count}`);\n      }\n    };\n\n    const prev = (): void => goTo(activeIndex.value - 1);\n    const next = (): void => goTo(activeIndex.value + 1);\n\n    // ── Sync prop → state ────────────────────────────────────────────────────\n\n    watch(props['slide-index'], (v) => {\n      if (typeof v === 'number' && v !== activeIndex.value) goTo(v, false);\n    });\n\n    // ── Sync variant + orientation → slides ──────────────────────────────────\n\n    const syncSlideVariants = (): void => {\n      const variant = props.variant.value ?? 'default';\n      const orientation = props.orientation.value ?? 'horizontal';\n\n      slides.forEach((slide) => {\n        slide.setAttribute('data-variant', variant);\n        slide.setAttribute('data-orientation', orientation);\n      });\n    };\n\n    watch(\n      computed(() => ({ orientation: props.orientation.value, variant: props.variant.value })),\n      syncSlideVariants,\n      { immediate: true },\n    );\n\n    // ── Sync active index → slides — dispatch table ───────────────────────────\n\n    const syncTable: Record<CarouselVariant, (slides: HTMLElement[], current: number) => void> = {\n      default: syncDefaultSlides,\n      fade: syncDefaultSlides,\n      filmstrip: syncFilmstripSlides,\n      gallery: syncGallerySlides,\n    };\n\n    const syncActiveState = (): void => {\n      const variant = (props.variant.value ?? 'default') as CarouselVariant;\n\n      syncTable[variant](slides, activeIndex.value);\n    };\n\n    watch(activeIndex, syncActiveState, { immediate: true });\n\n    // ── Autoplay ─────────────────────────────────────────────────────────────\n\n    const startAutoplay = (): void => {\n      if (autoplayTimer !== null) return;\n\n      autoplayTimer = setInterval(next, props['autoplay-interval'].value ?? 5000);\n    };\n\n    const stopAutoplay = (): void => {\n      if (autoplayTimer !== null) {\n        clearInterval(autoplayTimer);\n        autoplayTimer = null;\n      }\n    };\n\n    watch(\n      computed(() => ({ enabled: props.autoplay.value, interval: props['autoplay-interval'].value })),\n      ({ enabled }) => {\n        stopAutoplay();\n\n        if (enabled) startAutoplay();\n      },\n    );\n\n    // ── Keyboard navigation ──────────────────────────────────────────────────\n\n    const handleKeydown = (e: KeyboardEvent): void => {\n      const isH = isHorizontal.value;\n      const prevKey = isH ? 'ArrowLeft' : 'ArrowUp';\n      const nextKey = isH ? 'ArrowRight' : 'ArrowDown';\n\n      if (e.key === prevKey) {\n        e.preventDefault();\n        prev();\n      } else if (e.key === nextKey) {\n        e.preventDefault();\n        next();\n      } else if (e.key === 'Home') {\n        e.preventDefault();\n        goTo(0);\n      } else if (e.key === 'End') {\n        e.preventDefault();\n        goTo(slideCount.value - 1);\n      }\n    };\n\n    const indicatorNav = createListControl<number>({\n      getItems: () => Array.from({ length: slideCount.value }, (_, index) => index),\n      loop: true,\n      onNavigate: ({ index }) => {\n        goTo(index);\n        const dot = el.shadowRoot?.querySelector<HTMLElement>(`.indicator[data-index=\"${index}\"]`);\n\n        dot?.focus();\n      },\n      orientation: () => (isHorizontal.value ? 'horizontal' : 'vertical'),\n      signal: lifecycleSignal(onCleanup),\n    });\n\n    // ── Host bindings ────────────────────────────────────────────────────────\n\n    bind({\n      attr: {\n        'aria-label': () => props.label.value ?? 'Carousel',\n        'aria-roledescription': () => 'carousel',\n        orientation: () => props.orientation.value ?? 'horizontal',\n        role: () => 'region',\n        style: () => `touch-action:${isHorizontal.value ? 'pan-y' : 'pan-x'}`,\n        variant: () => props.variant.value ?? 'default',\n      },\n      on: {\n        focusin: () => {\n          stopAutoplay();\n        },\n        focusout: () => {\n          if (props.autoplay.value) startAutoplay();\n        },\n        keydown: handleKeydown,\n        pointerenter: () => {\n          stopAutoplay();\n        },\n        pointerleave: () => {\n          if (props.autoplay.value) startAutoplay();\n        },\n      },\n    });\n\n    // ── Lifecycle ────────────────────────────────────────────────────────────\n\n    onMounted(() => {\n      const pan = createPanGesture(el, {\n        axis: () => (isHorizontal.value ? 'x' : 'y'),\n        onEnd: ({ distance, reason }) => {\n          if (reason !== 'release' || Math.abs(distance) < 48) return;\n\n          if (distance < 0) next();\n          else prev();\n        },\n        shouldStart: (event) => {\n          const path = event.composedPath();\n\n          return !path.some(\n            (node) =>\n              node instanceof HTMLElement &&\n              (node.tagName === 'BUTTON' || node.tagName === 'ORE-BUTTON' || node.tagName === 'ORE-PROGRESS'),\n          );\n        },\n      });\n      const shadowRoot = el.shadowRoot!;\n      const slot = shadowRoot.querySelector<HTMLSlotElement>('slot')!;\n\n      // slotchange replaces MutationObserver — fires exactly when assigned\n      // nodes change, scoped to this component's slot, no polling overhead.\n      const onSlotChange = (): void => {\n        refreshSlides();\n        syncSlideVariants();\n        syncActiveState();\n      };\n\n      slot.addEventListener('slotchange', onSlotChange);\n\n      if (props.autoplay.value) {\n        startAutoplay();\n      }\n\n      return () => {\n        pan.dispose();\n        stopAutoplay();\n        slot.removeEventListener('slotchange', onSlotChange);\n      };\n    });\n\n    // ── Template ─────────────────────────────────────────────────────────────\n\n    const renderControls = () =>\n      showControls.value\n        ? html`\n            <div class=\"controls\" part=\"controls\">\n              <ore-button\n                class=\"nav-btn prev-btn\"\n                part=\"prev-btn\"\n                variant=\"ghost\"\n                color=${() => props.color.value}\n                rounded\n                icon-only\n                aria-label=\"Previous slide\"\n                disabled=${() => (!canGoPrev.value ? true : undefined)}\n                @click=${(e: Event) => {\n                  e.stopPropagation();\n                  prev();\n                }}>\n                <ore-icon\n                  name=${() => (isHorizontal.value ? 'chevron-left' : 'chevron-up')}\n                  size=\"16\"\n                  stroke-width=\"2\"\n                  aria-hidden=\"true\"></ore-icon>\n              </ore-button>\n              <ore-button\n                class=\"nav-btn next-btn\"\n                part=\"next-btn\"\n                variant=\"ghost\"\n                color=${() => props.color.value}\n                rounded\n                icon-only\n                aria-label=\"Next slide\"\n                disabled=${() => (!canGoNext.value ? true : undefined)}\n                @click=${(e: Event) => {\n                  e.stopPropagation();\n                  next();\n                }}>\n                <ore-icon\n                  name=${() => (isHorizontal.value ? 'chevron-right' : 'chevron-down')}\n                  size=\"16\"\n                  stroke-width=\"2\"\n                  aria-hidden=\"true\"></ore-icon>\n              </ore-button>\n            </div>\n          `\n        : html``;\n\n    return html`\n      <div class=\"track\" part=\"track\" aria-live=${() => (props.autoplay.value ? 'off' : 'polite')}>\n        <slot></slot>\n      </div>\n\n      ${() =>\n        showIndicators.value && slideCount.value > 1\n          ? html`\n              <div class=\"indicators\" part=\"indicators\" role=\"tablist\" aria-label=\"Slide indicators\">\n                ${() =>\n                  Array.from(\n                    { length: slideCount.value },\n                    (_, i) => html`\n                      <button\n                        type=\"button\"\n                        role=\"tab\"\n                        data-index=\"${i}\"\n                        class=${() => `indicator${i === activeIndex.value ? ' indicator-active' : ''}`}\n                        aria-selected=${() => String(i === activeIndex.value)}\n                        tabindex=${() => (i === activeIndex.value ? '0' : '-1')}\n                        aria-label=\"${`Go to slide ${i + 1}`}\"\n                        @focus=${() => indicatorNav.set(i)}\n                        @click=${() => goTo(i)}\n                        @keydown=${(e: KeyboardEvent) => {\n                          const target = e.currentTarget;\n\n                          if (target instanceof HTMLElement) {\n                            const index = Number(target.dataset.index);\n\n                            if (Number.isInteger(index)) indicatorNav.set(index);\n                          }\n\n                          indicatorNav.handleKeydown(e);\n                        }}>\n                        <ore-progress\n                          aria-hidden=\"true\"\n                          tabindex=\"-1\"\n                          color=${() => props.color.value}\n                          type=${() => (isHorizontal.value ? 'linear' : 'vertical')}\n                          value=${() => (i === activeIndex.value ? 100 : 0)}\n                          style=${() => {\n                            const fillAnim = isHorizontal.value ? 'carousel-fill' : 'carousel-fill-v';\n\n                            return `--carousel-timeout:${props['autoplay-interval'].value ?? 5000};--carousel-animation-name:${i === activeIndex.value && props.autoplay.value ? fillAnim : 'none'}`;\n                          }}></ore-progress>\n                      </button>\n                    `,\n                  )}\n                ${renderControls}\n              </div>\n            `\n          : html`\n              ${renderControls}\n            `}\n    `;\n  },\n  styles: [componentStyles],\n});\n","@layer refine.base {\n  :host {\n    --_bg: var(--chat-message-bg, var(--color-contrast-100));\n    --_color: var(--chat-message-color, var(--color-contrast-900));\n    --_user-bg: var(--chat-message-user-bg, var(--color-primary));\n    --_user-color: var(--chat-message-user-color, var(--color-primary-content));\n    --_radius: var(--chat-message-radius, var(--rounded-lg));\n    --_max-width: var(--chat-message-max-width, 36rem);\n\n    display: block;\n  }\n\n  .row {\n    display: flex;\n    gap: var(--size-2-5);\n    align-items: flex-start;\n  }\n\n  :host([sender='user']) .row {\n    flex-direction: row-reverse;\n  }\n\n  .avatar {\n    display: flex;\n    flex-shrink: 0;\n  }\n\n  .avatar[hidden] {\n    display: none;\n  }\n\n  .column {\n    display: flex;\n    flex: 1;\n    flex-direction: column;\n    gap: var(--size-1);\n    align-items: flex-start;\n    min-width: 0;\n  }\n\n  :host([sender='user']) .column {\n    align-items: flex-end;\n  }\n\n  .name {\n    /* Match `.bubble`'s inline padding so the name lines up with the bubble's own text\n       instead of the bubble's outer box. */\n    padding-inline: var(--size-3-5);\n    font-size: var(--text-xs);\n    font-weight: var(--font-medium);\n    color: var(--color-contrast-500);\n  }\n\n  .name[hidden] {\n    display: none;\n  }\n\n  /* =====================\n       Bubble\n       ===================== */\n\n  .bubble {\n    box-sizing: border-box;\n    width: fit-content;\n    max-width: var(--_max-width);\n    padding: var(--size-2-5) var(--size-3-5);\n    color: var(--_color);\n    background: var(--_bg);\n    border-radius: var(--_radius);\n  }\n\n  :host([sender='user']) .bubble {\n    color: var(--_user-color);\n    background: var(--_user-bg);\n  }\n\n  .content {\n    font-size: var(--text-sm);\n    line-height: var(--leading-relaxed);\n  }\n\n  /*\n   * `white-space`/`overflow-wrap` live on the slot itself, not `.content` — both are\n   * inherited properties, and slotted nodes inherit from their point of use (the `<slot>`)\n   * per the CSS Scoping spec, so this still reaches the projected text. Scoping it here\n   * (instead of the parent `.content`) keeps `.content`'s own whitespace-only text nodes —\n   * the newline + indentation between `<slot>` and the cursor `<span>` in this template —\n   * under normal collapsing rules, so they don't render as extra blank lines. Putting\n   * `pre-wrap` on `.content` directly did exactly that: real bug, caught by measuring\n   * rendered box height in a real browser.\n   */\n  .content-slot {\n    overflow-wrap: anywhere;\n    white-space: pre-wrap;\n  }\n\n  /* =====================\n       Streaming cursor\n       ===================== */\n\n  .cursor {\n    display: inline-block;\n    width: 0.5em;\n    height: 1em;\n    margin-inline-start: var(--size-0-5);\n    vertical-align: text-bottom;\n    background: currentcolor;\n    animation: var(--_motion-animation, chat-message-blink 1s step-end infinite);\n  }\n\n  .cursor[hidden] {\n    display: none;\n  }\n\n  @keyframes chat-message-blink {\n    50% {\n      opacity: 0;\n    }\n  }\n\n  /* =====================\n       Meta row (timestamp / status / error / retry)\n       ===================== */\n\n  .meta {\n    display: flex;\n    gap: var(--size-1-5);\n    align-items: center;\n\n    /* Match `.bubble`'s inline padding — see `.name` above. */\n    padding-inline: var(--size-3-5);\n    font-size: var(--text-xs);\n    color: var(--color-contrast-400);\n  }\n\n  .meta[hidden] {\n    display: none;\n  }\n\n  .timestamp[hidden] {\n    display: none;\n  }\n\n  .status {\n    display: inline-flex;\n    align-items: center;\n  }\n\n  .status[hidden] {\n    display: none;\n  }\n\n  .status[data-status='sent'] {\n    color: var(--color-success);\n  }\n\n  .status[data-status='error'] {\n    color: var(--color-error);\n  }\n\n  .spinner {\n    display: inline-block;\n    width: 0.75em;\n    height: 0.75em;\n    border: 2px solid var(--color-contrast-300);\n    border-inline-end-color: transparent;\n    border-radius: 50%;\n    animation: var(--_motion-animation, chat-message-spin var(--transition-loader) infinite);\n  }\n\n  @keyframes chat-message-spin {\n    to {\n      transform: rotate(360deg);\n    }\n  }\n\n  .error-text {\n    color: var(--color-error);\n  }\n\n  .error-text[hidden] {\n    display: none;\n  }\n\n  .retry {\n    padding: 0;\n    font: inherit;\n    font-size: var(--text-xs);\n    font-weight: var(--font-medium);\n    color: var(--color-primary);\n    text-decoration: underline;\n    text-underline-offset: 2px;\n    cursor: pointer;\n    background: none;\n    border: none;\n  }\n\n  .retry[hidden] {\n    display: none;\n  }\n\n  .retry:focus-visible {\n    outline: var(--border-2) solid var(--color-focus);\n    outline-offset: var(--border-2);\n  }\n\n  /* =====================\n       Actions\n       ===================== */\n\n  .actions {\n    display: flex;\n    gap: var(--size-1);\n\n    /* Match `.bubble`'s inline padding — see `.name` above. */\n    padding-inline: var(--size-3-5);\n  }\n\n  .actions[hidden] {\n    display: none;\n  }\n}\n","import { define, html, onEvent, onMounted, prop, ref, useEmit, useSlots } from '@vielzeug/ore';\nimport { computed, watch } from '@vielzeug/ripple';\n\nimport { announce } from '../../core';\nimport { reducedMotionMixin } from '../../styles';\nimport '../icon/icon';\nimport componentStyles from './chat-message.css?inline';\n\nexport type ChatMessageSender = 'assistant' | 'system' | 'user';\nexport type ChatMessageStatus = 'error' | 'sending' | 'sent';\n\nconst SENDER_LABELS: Record<ChatMessageSender, string> = {\n  assistant: 'Assistant',\n  system: 'System',\n  user: 'You',\n};\n\n/** Events emitted by the chat-message component */\nexport type OreChatMessageEvents = {\n  /** Fired when the retry action is activated on a `status=\"error\"` message */\n  retry: { originalEvent?: Event };\n};\n\n/** Chat message component properties */\nexport type OreChatMessageProps = {\n  /** Error detail shown beneath the bubble; only visible when `status=\"error\"` */\n  error?: string;\n  /** Display name shown above the bubble (falls back to a generic label per `sender`) */\n  name?: string;\n  /** Who sent the message — controls alignment and bubble styling */\n  sender?: ChatMessageSender;\n  /** Delivery status for outgoing messages — shows an inline indicator and, for `\"error\"`, a retry action */\n  status?: ChatMessageStatus;\n  /** Append a blinking cursor after the content, for a message still streaming in */\n  streaming?: boolean;\n  /** ISO 8601 timestamp; rendered as a localized short time in a semantic `<time>` element */\n  timestamp?: string;\n};\n\n/**\n * A single message bubble for chat/conversation UIs — sender-aware alignment, an optional\n * avatar slot, delivery status (sending/sent/error with retry), and a streaming cursor for\n * assistant messages still generating. Content is provided via the default slot, so any\n * markdown-to-HTML rendering stays the consumer's choice.\n *\n * The default slot's leading/trailing whitespace-only text nodes are trimmed in place once\n * per slot assignment (mount, and again on `slotchange`) — pretty-printed HTML's\n * indentation would otherwise render as blank lines, since the bubble preserves line breaks\n * (`white-space: pre-wrap`) for genuine multi-paragraph replies. This mutates those specific\n * text nodes' `textContent` directly; it never touches nodes appended afterward (e.g. by\n * `el.textContent += token` while streaming), only the ones present at assignment time.\n *\n * @element ore-chat-message\n *\n * @attr {string} sender - Who sent the message: 'user' | 'assistant' | 'system' (default 'assistant')\n * @attr {string} name - Display name shown above the bubble\n * @attr {string} timestamp - ISO 8601 timestamp, rendered as a localized short time\n * @attr {string} status - Delivery status: 'sending' | 'sent' | 'error'\n * @attr {string} error - Error detail shown beneath the bubble when status=\"error\"\n * @attr {boolean} streaming - Append a blinking cursor after the content\n *\n * @fires retry - Fired when the retry action is activated. detail: { originalEvent }\n *\n * @slot - Message content\n * @slot avatar - Avatar element (e.g. `<ore-avatar>`)\n * @slot actions - Action buttons shown beneath the message (copy, regenerate, feedback, …)\n *\n * @cssprop --chat-message-bg - Bubble background color (assistant/system)\n * @cssprop --chat-message-color - Bubble text color (assistant/system)\n * @cssprop --chat-message-user-bg - Bubble background color (user)\n * @cssprop --chat-message-user-color - Bubble text color (user)\n * @cssprop --chat-message-radius - Bubble border radius\n * @cssprop --chat-message-max-width - Maximum bubble width\n *\n * @part row - Root row container (avatar + column)\n * @part avatar - Avatar slot container\n * @part column - Column containing name, bubble, meta, and actions\n * @part name - Sender display name\n * @part bubble - Message bubble container\n * @part content - Content container inside the bubble\n * @part cursor - Blinking streaming cursor\n * @part meta - Row of timestamp, status, and error text below the bubble\n * @part timestamp - Timestamp `<time>` element\n * @part status - Status indicator\n * @part error - Error text\n * @part retry - Retry button (status=\"error\" only)\n * @part actions - Actions slot container\n *\n * @example\n * ```html\n * <ore-chat-message sender=\"user\" timestamp=\"2024-01-01T12:00:00Z\" status=\"sent\">\n *   What's the weather like today?\n * </ore-chat-message>\n *\n * <ore-chat-message sender=\"assistant\" name=\"Assistant\" streaming>\n *   Let me check that for you\n * </ore-chat-message>\n * ```\n */\nexport const CHAT_MESSAGE_TAG = 'ore-chat-message' as const;\ndefine<OreChatMessageProps>(CHAT_MESSAGE_TAG, {\n  props: {\n    error: prop.string(),\n    name: prop.string(),\n    sender: prop.oneOf(['user', 'assistant', 'system'] as const, 'assistant'),\n    status: prop.string<ChatMessageStatus>(),\n    streaming: prop.bool(false),\n    timestamp: prop.string(),\n  },\n  setup(props) {\n    const emit = useEmit<OreChatMessageEvents>();\n    const slots = useSlots();\n\n    const senderLabel = () => SENDER_LABELS[props.sender.value ?? 'assistant'];\n\n    const bubbleLabel = computed(() => `Message from ${props.name.value || senderLabel()}`);\n\n    const formattedTime = computed(() => {\n      const raw = props.timestamp.value;\n\n      if (!raw) return '';\n\n      const date = new Date(raw);\n\n      if (Number.isNaN(date.getTime())) return '';\n\n      return new Intl.DateTimeFormat(undefined, { hour: 'numeric', minute: '2-digit' }).format(date);\n    });\n\n    const hasMeta = computed(\n      () => Boolean(formattedTime.value) || Boolean(props.status.value) || Boolean(props.error.value),\n    );\n\n    // Announce delivery failures — the visible retry button and error text are always present\n    // for sighted users, but a failed send is exactly the kind of state change a screen\n    // reader user could otherwise miss entirely. Keyed on `error` text too (not just\n    // `status`) so a retry that fails again with a *different* reason re-announces even\n    // though `status` never left `\"error\"` in between; a second failure with the identical\n    // message doesn't re-fire, since the source value hasn't actually changed.\n    watch(\n      () => (props.status.value === 'error' ? (props.error.value ?? '') : null),\n      (errorText) => {\n        if (errorText !== null) {\n          announce(`Message failed to send${errorText ? `: ${errorText}` : ''}`, { politeness: 'assertive' });\n        }\n      },\n    );\n\n    function handleRetry(e: Event): void {\n      emit('retry', { originalEvent: e });\n    }\n\n    // ── Trim author-time indentation whitespace from the default slot ──\n    // `.content` uses `white-space: pre-wrap` so genuine multi-paragraph replies keep their\n    // line breaks — but that also preserves the leading/trailing newline + indentation from\n    // pretty-printed HTML (`<ore-chat-message>\\n  Hello\\n</ore-chat-message>`), rendering as\n    // visible blank lines around the text. Trim only the outermost edges once per slot\n    // assignment; appending tokens to an existing text node for streaming doesn't re-fire\n    // `slotchange`, so this never interferes with in-progress streaming updates.\n    //\n    // A named-slotted sibling (e.g. `<ore-avatar slot=\"avatar\">` between the opening tag and\n    // the message text) splits the default slot's light-DOM text into *multiple* text nodes\n    // — text nodes can't target a named slot, so each run on either side of the element is\n    // assigned separately. The \"real\" content can start on a later node than index 0 (it's\n    // still preceded by its own leading indentation), so this walks inward from each end,\n    // fully clearing whitespace-only nodes and stopping at the first node with real content\n    // on each side — rather than only touching the very first/last assigned node.\n    const contentSlotRef = ref<HTMLSlotElement>();\n\n    function trimSlotEdgeWhitespace(): void {\n      const nodes = contentSlotRef.value?.assignedNodes({ flatten: true });\n\n      if (!nodes || nodes.length === 0) return;\n\n      for (const node of nodes) {\n        if (node.nodeType !== Node.TEXT_NODE) break;\n\n        const trimmed = (node.textContent ?? '').replace(/^\\s+/, '');\n\n        node.textContent = trimmed;\n\n        if (trimmed !== '') break;\n      }\n\n      for (let i = nodes.length - 1; i >= 0; i--) {\n        const node = nodes[i];\n\n        if (node.nodeType !== Node.TEXT_NODE) break;\n\n        const trimmed = (node.textContent ?? '').replace(/\\s+$/, '');\n\n        node.textContent = trimmed;\n\n        if (trimmed !== '') break;\n      }\n    }\n\n    onMounted(() => {\n      trimSlotEdgeWhitespace();\n\n      const slotEl = contentSlotRef.value;\n\n      if (slotEl) onEvent(slotEl, 'slotchange', trimSlotEdgeWhitespace);\n    });\n\n    return html`\n      <div class=\"row\" part=\"row\">\n        <span class=\"avatar\" part=\"avatar\" ?hidden=\"${() => !slots.has('avatar').value}\">\n          <slot name=\"avatar\"></slot>\n        </span>\n        <div class=\"column\" part=\"column\">\n          <span class=\"name\" part=\"name\" ?hidden=\"${() => !props.name.value}\">${props.name}</span>\n          <div class=\"bubble\" part=\"bubble\" role=\"article\" aria-label=\"${bubbleLabel}\">\n            <div class=\"content\" part=\"content\">\n              <slot class=\"content-slot\" ref=\"${contentSlotRef}\"></slot>\n              <span class=\"cursor\" part=\"cursor\" aria-hidden=\"true\" ?hidden=\"${() => !props.streaming.value}\"></span>\n            </div>\n          </div>\n          <div class=\"meta\" part=\"meta\" ?hidden=\"${() => !hasMeta.value}\">\n            <time\n              class=\"timestamp\"\n              part=\"timestamp\"\n              datetime=\"${props.timestamp}\"\n              ?hidden=\"${() => !formattedTime.value}\">\n              ${formattedTime}\n            </time>\n            <span class=\"status\" part=\"status\" data-status=\"${props.status}\" ?hidden=\"${() => !props.status.value}\">\n              ${() => {\n                switch (props.status.value) {\n                  case 'error':\n                    return html`\n                      <ore-icon name=\"alert-circle\" size=\"12\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n                    `;\n                  case 'sending':\n                    return html`\n                      <span class=\"spinner\" aria-hidden=\"true\"></span>\n                    `;\n                  case 'sent':\n                    return html`\n                      <ore-icon name=\"check\" size=\"12\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n                    `;\n                  default:\n                    return '';\n                }\n              }}\n            </span>\n            <span class=\"error-text\" part=\"error\" role=\"alert\" ?hidden=\"${() => !props.error.value}\">\n              ${props.error}\n            </span>\n            <button\n              class=\"retry\"\n              part=\"retry\"\n              type=\"button\"\n              ?hidden=\"${() => props.status.value !== 'error'}\"\n              @click=\"${handleRetry}\">\n              Retry\n            </button>\n          </div>\n          <div class=\"actions\" part=\"actions\" ?hidden=\"${() => !slots.has('actions').value}\">\n            <slot name=\"actions\"></slot>\n          </div>\n        </div>\n      </div>\n    `;\n  },\n  styles: [reducedMotionMixin, componentStyles],\n});\n","@layer refine.base {\n  :host {\n    --_bg: var(--code-window-bg, var(--color-canvas));\n    --_header-bg: var(--code-window-header-bg, var(--color-contrast-100));\n    --_border-color: var(--code-window-border-color, var(--color-contrast-300));\n    --_radius: var(--code-window-radius, var(--rounded-lg));\n    --_shadow: var(--code-window-shadow, var(--shadow-sm));\n    --_body-padding: var(--code-window-body-padding, var(--size-5) var(--size-6));\n\n    display: block;\n  }\n\n  .window {\n    overflow: hidden;\n    background: var(--_bg);\n    border: var(--border) solid var(--_border-color);\n    border-radius: var(--_radius);\n    box-shadow: var(--_shadow);\n    transition:\n      border-color var(--transition-normal),\n      box-shadow var(--transition-normal);\n  }\n\n  .header {\n    display: flex;\n    gap: var(--size-1-5);\n    align-items: center;\n    padding: var(--size-3) var(--size-5);\n    overflow: hidden;\n    background: var(--_header-bg);\n    border-bottom: var(--border) solid var(--_border-color);\n    transition: background var(--transition-normal);\n  }\n\n  /* ── code variant ─────────────────────────────────────────── */\n\n  .lang {\n    flex-shrink: 0;\n    padding: 2px var(--size-1-5);\n    font-family: var(--font-mono);\n    font-size: var(--text-2xs);\n    font-weight: var(--font-semibold);\n    color: var(--color-primary);\n    letter-spacing: 0.03em;\n    background: var(--color-primary-backdrop);\n    border: var(--border) solid oklch(70% 0.12 293deg / 20%);\n    border-radius: var(--rounded-sm);\n  }\n\n  .filename {\n    min-width: 0;\n    margin-inline-start: var(--size-2);\n    overflow: hidden;\n    text-overflow: ellipsis;\n    font-family: var(--font-mono);\n    font-size: var(--text-xs);\n    color: var(--text-color-secondary);\n    white-space: nowrap;\n  }\n\n  /* ── chat variant ─────────────────────────────────────────── */\n\n  .dots {\n    display: flex;\n    flex-shrink: 0;\n    gap: var(--size-1-5);\n    align-items: center;\n    padding-inline-end: var(--size-3);\n    margin-inline-end: var(--size-1-5);\n    border-inline-end: var(--border) solid var(--_border-color);\n  }\n\n  /* Authentic macOS traffic-light palette — muted so they don't fight the content */\n  .dots span {\n    display: block;\n    width: var(--size-3);\n    height: var(--size-3);\n    border-radius: var(--rounded-full);\n  }\n\n  .dots span:nth-child(1) {\n    background: oklch(65% 0.18 25deg);\n  }\n\n  .dots span:nth-child(2) {\n    background: oklch(72% 0.18 80deg);\n  }\n\n  .dots span:nth-child(3) {\n    background: oklch(62% 0.18 145deg);\n  }\n\n  .title {\n    font-family: var(--font-mono);\n    font-size: var(--text-xs);\n    color: var(--text-color-secondary);\n    letter-spacing: 0.02em;\n  }\n\n  /* ── header-end spacer ────────────────────────────────────── */\n\n  .header-spacer {\n    flex: 1;\n  }\n\n  ::slotted([slot='header-end']) {\n    flex-shrink: 0;\n  }\n\n  /* ── body ─────────────────────────────────────────────────── */\n\n  .body {\n    padding: var(--_body-padding);\n    overflow-x: auto;\n  }\n}\n","import { define, html, prop, when } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\n\nimport componentStyles from './code-window.css?inline';\n\n/** `ore-code-window` variant */\nexport type CodeWindowVariant = 'code' | 'chat';\n\n/** `ore-code-window` component properties */\nexport type OreCodeWindowProps = {\n  /** Filename label shown after the language badge (`variant=\"code\"` only) */\n  filename?: string;\n  /** Language badge text, e.g. `\"ts\"`, `\"sh\"` (`variant=\"code\"` only) */\n  lang?: string;\n  /** Title string shown beside the traffic-light dots (`variant=\"chat\"` only) */\n  title?: string;\n  /**\n   * `\"code\"` (default) — header shows a language badge + filename.\n   * `\"chat\"` — header shows traffic-light dots + a title.\n   */\n  variant?: CodeWindowVariant;\n};\n\n/**\n * A styled window chrome for code blocks and AI/MCP conversation flows.\n *\n * Two variants:\n * - `variant=\"code\"` (default) — language badge + optional filename header.\n * - `variant=\"chat\"` — traffic-light dots + title header.\n *\n * @element ore-code-window\n *\n * @attr {'code'|'chat'} variant - Window style variant\n * @attr {string} lang - Language badge label (variant=\"code\" only)\n * @attr {string} filename - Filename shown next to the badge (variant=\"code\" only)\n * @attr {string} title - Label beside the dots (variant=\"chat\" only)\n *\n * @slot - Main body content (code, conversation turns, or any markup)\n * @slot header-end - Optional content appended to the trailing edge of the header\n *\n * @cssprop --code-window-bg - Window background color\n * @cssprop --code-window-header-bg - Header background color\n * @cssprop --code-window-border-color - Border color\n * @cssprop --code-window-radius - Border radius\n * @cssprop --code-window-shadow - Box shadow\n * @cssprop --code-window-body-padding - Body slot padding\n *\n * @part window - The root window element\n * @part header - The header bar\n * @part lang - The language badge (`variant=\"code\"`)\n * @part filename - The filename label (`variant=\"code\"`)\n * @part dots - The traffic-light dot container (`variant=\"chat\"`)\n * @part title - The title label (`variant=\"chat\"`)\n * @part body - The body container wrapping the default slot\n *\n * @example\n * ```html\n * <ore-code-window lang=\"ts\" filename=\"app.ts\">\n *   <pre>const x = 1;</pre>\n * </ore-code-window>\n *\n * <ore-code-window variant=\"chat\" title=\"MCP tool call\">\n *   <!-- conversation turns go here -->\n * </ore-code-window>\n * ```\n */\nexport const CODE_WINDOW_TAG = 'ore-code-window' as const;\ndefine<OreCodeWindowProps>(CODE_WINDOW_TAG, {\n  props: {\n    filename: prop.string(),\n    lang: prop.string('ts'),\n    title: prop.string('MCP tool call'),\n    variant: prop.oneOf(['code', 'chat'] as const, 'code'),\n  },\n  setup(props) {\n    const isCode = computed(() => props.variant.value === 'code');\n    const hasFilename = computed(() => Boolean(props.filename.value));\n\n    return html`\n      <div class=\"window\" part=\"window\">\n        <div class=\"header\" part=\"header\">\n          ${when(\n            isCode,\n            () => html`\n              <span class=\"lang\" part=\"lang\">${props.lang}</span>\n              ${when(\n                hasFilename,\n                () => html`\n                  <span class=\"filename\" part=\"filename\">${props.filename}</span>\n                `,\n              )}\n            `,\n            () => html`\n              <div class=\"dots\" part=\"dots\" aria-hidden=\"true\">\n                <span></span>\n                <span></span>\n                <span></span>\n              </div>\n              <span class=\"title\" part=\"title\">${props.title}</span>\n            `,\n          )}\n          <div class=\"header-spacer\"></div>\n          <slot name=\"header-end\"></slot>\n        </div>\n        <div class=\"body\" part=\"body\">\n          <slot></slot>\n        </div>\n      </div>\n    `;\n  },\n  styles: [componentStyles],\n});\n","@layer refine.base {\n  :host {\n    --_bg: var(--copy-command-bg, var(--color-contrast-100));\n    --_color: var(--copy-command-color, var(--text-color-body));\n    --_border-color: var(--copy-command-border-color, var(--color-contrast-300));\n    --_radius: var(--copy-command-radius, var(--rounded-md));\n    --_padding: var(--copy-command-padding, var(--size-2) var(--size-3));\n    --_font-size: var(--copy-command-font-size, var(--text-sm));\n    --_icon-color: var(--copy-command-icon-color, var(--text-color-secondary));\n    --_hover-bg: var(--copy-command-hover-bg, var(--color-contrast-200));\n\n    display: inline-block;\n  }\n\n  :host([hidden]) {\n    display: none;\n  }\n\n  /* ── rounded attribute → CSS variable ───────────────────── */\n\n  :host([rounded='none']) {\n    --_radius: var(--rounded-none, 0);\n  }\n\n  :host([rounded='sm']) {\n    --_radius: var(--rounded-sm);\n  }\n\n  :host([rounded='md']) {\n    --_radius: var(--rounded-md);\n  }\n\n  :host([rounded='lg']) {\n    --_radius: var(--rounded-lg);\n  }\n\n  :host([rounded='xl']) {\n    --_radius: var(--rounded-xl);\n  }\n\n  :host([rounded='2xl']) {\n    --_radius: var(--rounded-2xl);\n  }\n\n  :host([rounded='3xl']) {\n    --_radius: var(--rounded-3xl);\n  }\n\n  :host([rounded='full']) {\n    --_radius: var(--rounded-full);\n  }\n\n  /* ── size variants ───────────────────────────────────────── */\n\n  :host([size='sm']) {\n    --_padding: var(--copy-command-padding, var(--size-1) var(--size-2));\n    --_font-size: var(--copy-command-font-size, var(--text-xs));\n  }\n\n  :host([size='lg']) {\n    --_padding: var(--copy-command-padding, var(--size-2-5) var(--size-4));\n    --_font-size: var(--copy-command-font-size, var(--text-base));\n  }\n\n  /* ── visual variants ─────────────────────────────────────── */\n\n  :host([variant='bordered']) {\n    --_bg: var(--copy-command-bg, transparent);\n    --_border-color: var(--copy-command-border-color, var(--color-contrast-400));\n  }\n\n  :host([variant='ghost']) {\n    --_bg: var(--copy-command-bg, transparent);\n    --_border-color: var(--copy-command-border-color, transparent);\n    --_hover-bg: var(--copy-command-hover-bg, var(--color-contrast-100));\n  }\n\n  /* ── layout ──────────────────────────────────────────────── */\n\n  .wrapper {\n    display: inline-flex;\n    align-items: stretch;\n    overflow: hidden;\n    background: var(--_bg);\n    border: var(--border) solid var(--_border-color);\n    border-radius: var(--_radius);\n    transition:\n      border-color var(--transition-normal),\n      background var(--transition-normal);\n  }\n\n  /* ── command button ──────────────────────────────────────── */\n\n  .command {\n    display: inline-flex;\n    flex: 1;\n    gap: var(--size-2);\n    align-items: center;\n    padding: var(--_padding);\n    font-family: var(--font-mono);\n    font-size: var(--_font-size);\n    color: var(--_color);\n    text-align: start;\n    cursor: pointer;\n    background: transparent;\n    border: none;\n    transition: background var(--transition-normal);\n  }\n\n  .command:hover {\n    background: var(--_hover-bg);\n  }\n\n  .command:focus-visible {\n    outline: 2px solid var(--color-primary);\n    outline-offset: -2px;\n    border-radius: calc(var(--_radius) - 1px);\n  }\n\n  /* ── command text ────────────────────────────────────────── */\n\n  .command-text {\n    flex: 1;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    font-family: inherit;\n    font-size: inherit;\n    color: inherit;\n    white-space: nowrap;\n    background: transparent;\n  }\n\n  /* ── copy icon ───────────────────────────────────────────── */\n\n  .copy-icon {\n    display: inline-flex;\n    flex-shrink: 0;\n    align-items: center;\n    color: var(--_icon-color);\n    transition: color var(--transition-normal);\n  }\n\n  .icon-copied {\n    color: var(--color-success, oklch(64% 0.17 142deg));\n  }\n\n  .icon-failed {\n    color: var(--color-danger, oklch(63% 0.21 25deg));\n  }\n\n  /* ── suffix slot ─────────────────────────────────────────── */\n\n  .suffix {\n    display: flex;\n    align-items: stretch;\n    border-inline-start: var(--border) solid var(--_border-color);\n  }\n\n  .suffix[hidden] {\n    display: none;\n  }\n\n  ::slotted([slot='suffix']) {\n    display: flex;\n    align-items: center;\n  }\n\n  /* .sr-only is provided by the shared srOnlyMixin (see styles: [...] in copy-command.ts) */\n}\n","import { define, html, onCleanup, prop, useEmit, useSlots } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { srOnlyMixin } from '../../styles';\nimport type { ComponentSize, RoundedSize } from '../../types';\nimport '../icon/icon';\nimport componentStyles from './copy-command.css?inline';\n\n/** Copy command component properties */\nexport type OreCopyCommandProps = {\n  /** Border radius size */\n  rounded?: RoundedSize;\n  /** Component size */\n  size?: ComponentSize;\n  /** The command string to display and copy to clipboard */\n  value?: string;\n  /** Visual style variant */\n  variant?: 'flat' | 'bordered' | 'ghost';\n};\n\n/** Copy command component events */\nexport type OreCopyCommandEvents = {\n  /** Emitted when the command is successfully copied to the clipboard */\n  copy: { value: string };\n};\n\n/**\n * A styled, copy-to-clipboard command display component.\n * Shows a command string in a monospace code block with a copy button.\n * Clicking the component copies the value to the clipboard, shows a transient\n * check-mark confirmation, and emits a `copy` event.\n *\n * @element ore-copy-command\n *\n * @attr {string} value - The command string to display and copy\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} variant - Visual style: 'flat' | 'bordered' | 'ghost'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n *\n * @fires copy - Emitted on successful clipboard write. detail: { value: string }\n *\n * @slot suffix - Optional controls appended after the copy button (e.g. a cycle button)\n *\n * @cssprop --copy-command-bg - Background color of the command block\n * @cssprop --copy-command-color - Text color of the command string\n * @cssprop --copy-command-border-color - Border color\n * @cssprop --copy-command-radius - Border radius (overrides the `rounded` attribute)\n * @cssprop --copy-command-padding - Inner padding of the command button\n * @cssprop --copy-command-font-size - Font size of the command string\n * @cssprop --copy-command-icon-color - Color of the copy/check icon\n * @cssprop --copy-command-hover-bg - Background on hover\n *\n * @part wrapper - Outer flex container\n * @part command - The copy button element\n * @part command-text - The `<code>` element displaying the command string\n * @part copy-icon - The icon wrapper span\n * @part suffix - Suffix slot container\n *\n * @example\n * ```html\n * <ore-copy-command value=\"npm install @vielzeug/ripple\"></ore-copy-command>\n *\n * <ore-copy-command value=\"npx -y @vielzeug/codex\" size=\"sm\" variant=\"bordered\"></ore-copy-command>\n *\n * <!-- With a suffix slot (e.g. a cycle button) -->\n * <ore-copy-command value=\"npm install @vielzeug/ripple\">\n *   <button slot=\"suffix\" type=\"button\" aria-label=\"Next package\">›</button>\n * </ore-copy-command>\n * ```\n */\nexport const COPY_COMMAND_TAG = 'ore-copy-command' as const;\n\ndefine<OreCopyCommandProps>(COPY_COMMAND_TAG, {\n  props: {\n    rounded: prop.string<RoundedSize>('md'),\n    size: prop.string<ComponentSize>('md'),\n    value: prop.string(''),\n    variant: prop.string<'flat' | 'bordered' | 'ghost'>('flat'),\n  },\n\n  setup(props) {\n    const emit = useEmit<OreCopyCommandEvents>();\n    const slots = useSlots();\n\n    const copied = signal(false);\n    const copyFailed = signal(false);\n    let resetTimer: ReturnType<typeof setTimeout> | null = null;\n\n    onCleanup(() => {\n      if (resetTimer !== null) clearTimeout(resetTimer);\n    });\n\n    const handleCopy = async () => {\n      const text = props.value.value ?? '';\n\n      if (!text) return;\n\n      if (resetTimer !== null) clearTimeout(resetTimer);\n\n      try {\n        await navigator.clipboard.writeText(text);\n        copied.value = true;\n        copyFailed.value = false;\n        emit('copy', { value: text });\n      } catch {\n        // Clipboard access denied or unavailable (e.g. insecure context) — surface it instead of failing silently\n        copied.value = false;\n        copyFailed.value = true;\n      }\n\n      resetTimer = setTimeout(() => {\n        copied.value = false;\n        copyFailed.value = false;\n        resetTimer = null;\n      }, 2000);\n    };\n\n    const hasSuffix = computed(() => slots.has('suffix').value);\n    const btnLabel = computed(() => {\n      if (copied.value) return 'Copied!';\n\n      if (copyFailed.value) return 'Copy failed — press to try again';\n\n      return `Copy: ${props.value.value ?? ''}`;\n    });\n\n    return html`\n      <div class=\"wrapper\" part=\"wrapper\">\n        <button class=\"command\" part=\"command\" type=\"button\" aria-label=\"${btnLabel}\" @click=${handleCopy}>\n          <code class=\"command-text\" part=\"command-text\">${props.value}</code>\n          <span class=\"copy-icon\" part=\"copy-icon\" aria-hidden=\"true\">\n            ${() => {\n              if (copied.value)\n                return html`\n                  <ore-icon name=\"check\" size=\"14\" class=\"icon-copied\" aria-hidden=\"true\"></ore-icon>\n                `;\n\n              if (copyFailed.value)\n                return html`\n                  <ore-icon name=\"circle-alert\" size=\"14\" class=\"icon-failed\" aria-hidden=\"true\"></ore-icon>\n                `;\n\n              return html`\n                <ore-icon name=\"copy\" size=\"14\" aria-hidden=\"true\"></ore-icon>\n              `;\n            }}\n          </span>\n        </button>\n        <div class=\"suffix\" part=\"suffix\" ?hidden=\"${() => !hasSuffix.value}\">\n          <slot name=\"suffix\"></slot>\n        </div>\n      </div>\n      <div role=\"status\" class=\"sr-only\">\n        ${() => {\n          if (copied.value) return 'Copied to clipboard.';\n\n          if (copyFailed.value) return 'Copy failed. Select the command text and copy it manually.';\n\n          return '';\n        }}\n      </div>\n    `;\n  },\n\n  styles: [srOnlyMixin, componentStyles],\n});\n","@layer refine.base {\n  :host {\n    display: block;\n  }\n\n  ::slotted(ore-list-item) {\n    display: block;\n  }\n\n  /* ========================================\n       Bordered Variant\n       ======================================== */\n\n  :host([variant='bordered']) {\n    overflow: hidden;\n    border: var(--border) solid var(--color-contrast-200);\n    border-radius: var(--list-radius, var(--rounded-lg));\n  }\n\n  :host([variant='bordered']) ::slotted(ore-list-item:not(:last-of-type)) {\n    border-bottom: var(--border) solid var(--color-contrast-200);\n  }\n\n  /* ========================================\n       Separated Variant\n       ======================================== */\n\n  :host([variant='separated']) {\n    display: flex;\n    flex-direction: column;\n    gap: var(--_gap, var(--size-2-5));\n  }\n\n  :host([variant='separated']) ::slotted(ore-list-item) {\n    overflow: hidden;\n    border: var(--border) solid var(--color-contrast-200);\n    border-radius: var(--list-radius, var(--rounded-lg));\n  }\n\n  /* ========================================\n       Disabled State\n       ======================================== */\n\n  :host([disabled]) {\n    pointer-events: none;\n    opacity: 0.6;\n  }\n}\n","import { bind, createContext, define, getHost, html, onCleanup, prop, provide, useEmit } from '@vielzeug/ore';\nimport { computed, type Readable, signal, watch } from '@vielzeug/ripple';\nimport { createListControl, lifecycleSignal } from '../../core';\nimport { disablableBundle, LIST_SIZE_PRESET, sizableBundle } from '../../shared';\nimport { sizeVariantMixin } from '../../styles';\nimport type { ComponentSize } from '../../types';\nimport componentStyles from './list.css?inline';\n\n/** Visual variant for `ore-list`. */\nexport type ListVariant = 'bordered' | 'plain' | 'separated';\n\n/** Context provided by `ore-list` to its `ore-list-item` children. */\nexport type ListContext = {\n  /**\n   * Closes every other item's swipe-revealed action panel. Called directly by an item the moment\n   * its own `revealed` attribute transitions to non-null (gesture or direct attribute set) —\n   * replaces listening for a bubbled `reveal` event and re-deriving \"is this actually my direct\n   * child\" with a plain function call, the same shape as `select` below.\n   */\n  requestReveal: (item: HTMLElement) => void;\n  /**\n   * Selects `value` (or clears the selection when `undefined`) and fires `change`. Called\n   * directly by an activated item — mirrors `ore-radio-group`'s `RadioGroupContext.select()`.\n   * No sibling bookkeeping needed here: every item's `selected` is *derived* from `value`, so\n   * changing it here is the only thing that has to happen.\n   */\n  select: (value: string | undefined) => void;\n  selectable: Readable<boolean>;\n  /**\n   * Single source of truth for the current selection — `ore-list-item` never owns its own\n   * \"selected\" state; it's always derived by comparing its own `value` against this one (the\n   * same shape as `ore-radio-group`'s `RadioGroupContext.value`).\n   */\n  value: Readable<string | undefined>;\n};\n/** Injection key for the list context. */\nexport const LIST_CTX = createContext<ListContext>('ListContext');\n\n/** Events emitted by the list component */\nexport type OreListEvents = {\n  /** Emitted when the selected value changes (only when `selectable` is set). */\n  change: { value: null | string };\n};\n\n/** List component properties */\nexport type OreListProps = {\n  /** Disable the entire list — blocks pointer interaction and removes items from tab order */\n  disabled?: boolean;\n  /**\n   * Enables single-selection listbox behavior: clicking (or pressing Enter/Space on) an item\n   * selects it and deselects any previously-selected sibling. Arrow keys / Home / End move\n   * focus between items. Omit for a plain, non-interactive display list.\n   */\n  selectable?: boolean;\n  /** Size applied to all items (propagated via inherited CSS custom properties) */\n  size?: ComponentSize;\n  /**\n   * Selected item's `value` (only meaningful when `selectable`) — the single source of truth for\n   * selection. `ore-list-item` never owns its own selected state; set this directly, bind it for\n   * two-way control, or read it back from `change`.\n   */\n  value?: string;\n  /** Visual variant: 'plain' (default, no dividers) | 'bordered' (outer border + row dividers) | 'separated' (each item is its own card) */\n  variant?: ListVariant;\n};\n\n/**\n * A vertical list container for `ore-list-item` children — plain display list by default, or a\n * keyboard-navigable single-select listbox via `selectable`. Each item can independently reveal\n * a left/right action panel via touch/pointer swipe (see `ore-list-item`'s `actions-left`/\n * `actions-right` slots) — useful for mobile-style row actions (archive, delete, …).\n *\n * @element ore-list\n * @element ore-list-item - Child element for each row\n *\n * @attr {boolean} disabled - Disable the entire list\n * @attr {boolean} selectable - Enable single-selection listbox behavior with arrow-key navigation\n * @attr {string} size - Size applied to all items: 'sm' | 'md' | 'lg'\n * @attr {string} value - Selected item's value (only meaningful when `selectable`) — the single source of truth for selection\n * @attr {string} variant - Visual variant: 'plain' | 'bordered' | 'separated'\n *\n * @fires change - Emitted when the selected value changes. detail: { value: string | null }\n *\n * @slot - `ore-list-item` elements\n *\n * @cssprop --list-radius - Border radius for the 'bordered'/'separated' variants\n *\n * @example\n * ```html\n * <ore-list variant=\"bordered\">\n *   <ore-list-item>Inbox</ore-list-item>\n *   <ore-list-item>Drafts</ore-list-item>\n * </ore-list>\n * <ore-list selectable value=\"inbox\">\n *   <ore-list-item value=\"inbox\">Inbox</ore-list-item>\n *   <ore-list-item value=\"drafts\">Drafts</ore-list-item>\n * </ore-list>\n * ```\n */\nexport const LIST_TAG = 'ore-list' as const;\ndefine<OreListProps>(LIST_TAG, {\n  props: {\n    ...disablableBundle,\n    ...sizableBundle,\n    selectable: prop.bool(false),\n    value: prop.string(),\n    variant: prop.string<ListVariant>(),\n  },\n\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreListEvents>();\n\n    const getItems = (): HTMLElement[] => [\n      ...el.querySelectorAll<HTMLElement>(':scope > ore-list-item:not([disabled])'),\n    ];\n\n    const getAllItems = (): HTMLElement[] => [...el.querySelectorAll<HTMLElement>(':scope > ore-list-item')];\n\n    // Reaches into each item's shadow root for its focusable row — mirrors `ore-accordion`'s\n    // `getSummaryElements()` — rather than relying on `item.focus()` + `shadow: { delegatesFocus:\n    // true }` to land focus correctly, since that cross-boundary reporting is inconsistent enough\n    // between real browsers and jsdom that other multi-item components in this package\n    // (`ore-menu`, `ore-tabs`) defensively check both forms too. Queried via `[part=\"row\"]`, not\n    // the `.row` class — `part` is list-item's declared public seam for exactly this kind of\n    // cross-component reach; the class name is a private styling detail that could change.\n    const getRow = (item: Element): HTMLElement | null =>\n      item.shadowRoot?.querySelector<HTMLElement>('[part=\"row\"]') ?? null;\n\n    const getRows = (): HTMLElement[] =>\n      getItems()\n        .map(getRow)\n        .filter((row): row is HTMLElement => row != null);\n\n    const listControl = createListControl<HTMLElement>({\n      getItems,\n      loop: true,\n      onNavigate: ({ item }) => {\n        getRow(item)?.focus();\n      },\n      signal: lifecycleSignal(onCleanup),\n    });\n\n    // Selection — `selectedValue` is the single source of truth (mirrors `ore-radio-group`'s\n    // `selectedValue`/`RadioGroupContext.value` pattern): reflected onto the `value` attribute,\n    // synced back in when set externally, and read by every item via context to derive its own\n    // `selected` state. No sibling-clearing needed anywhere — changing this one signal is enough.\n    const selectedValue = signal<string | undefined>(props.value.value);\n\n    watch(props.value, (value) => {\n      selectedValue.value = value;\n    });\n\n    const select = (value: string | undefined): void => {\n      if (selectedValue.value === value) return;\n\n      selectedValue.value = value;\n      emit('change', { value: value ?? null });\n    };\n\n    // Only one item's swipe-revealed action panel is open at a time. The item calls this\n    // directly the moment its own `revealed` attribute transitions to non-null — see\n    // `ListContext.requestReveal`'s doc comment for why this replaced a bubbled event.\n    const requestReveal = (item: HTMLElement): void => {\n      for (const sibling of getAllItems()) {\n        if (sibling !== item) sibling.removeAttribute('revealed');\n      }\n    };\n\n    // Closes any swipe-revealed item when the user interacts anywhere outside of it — matches\n    // the outside-pointerdown-closes pattern used by ore-date-picker/ore-time-picker's popovers.\n    const handleOutsidePointerDown = (event: PointerEvent): void => {\n      const open = getAllItems().find((item) => item.hasAttribute('revealed'));\n\n      if (!open || event.composedPath().includes(open)) return;\n\n      open.removeAttribute('revealed');\n    };\n\n    document.addEventListener('pointerdown', handleOutsidePointerDown, { capture: true });\n    onCleanup(() => document.removeEventListener('pointerdown', handleOutsidePointerDown, { capture: true }));\n\n    provide(LIST_CTX, {\n      requestReveal,\n      select,\n      selectable: computed(() => Boolean(props.selectable.value)),\n      value: selectedValue,\n    });\n\n    bind({\n      attr: {\n        'aria-disabled': () => (props.disabled.value ? 'true' : null),\n        role: () => (props.selectable.value ? 'listbox' : 'list'),\n        value: () => selectedValue.value ?? null,\n      },\n      on: {\n        keydown: (event: KeyboardEvent) => {\n          if (!props.selectable.value || props.disabled.value) return;\n\n          const row = event\n            .composedPath()\n            .find((node): node is HTMLElement => node instanceof HTMLElement && node.getAttribute('part') === 'row');\n\n          if (!row) return;\n\n          const focused = getRows().indexOf(row);\n\n          if (focused === -1) return;\n\n          listControl.set(focused);\n          listControl.handleKeydown(event);\n        },\n      },\n    });\n\n    return html`\n      <slot></slot>\n    `;\n  },\n\n  styles: [sizeVariantMixin(LIST_SIZE_PRESET), componentStyles],\n});\n","import { createPanGesture, type PanGesture, type PanGestureDetail } from '@vielzeug/gesture';\nimport type { Readable } from '@vielzeug/ripple';\nimport type { ListItemRevealSide } from './list-item';\n\n/** Drag distance (px) past which the action panel snaps fully open on release. */\nconst REVEAL_THRESHOLD = 64;\n/** Drag distance (px) past which the swipe auto-confirms the action — \"swiped all the way\". */\nconst CONFIRM_THRESHOLD = REVEAL_THRESHOLD * 3;\n/** Fraction of CONFIRM_THRESHOLD past which `data-confirming` warns the drag is about to fire. */\nconst CONFIRM_WARNING_RATIO = 0.85;\n\nexport type RevealStateOptions = {\n  disabled: Readable<boolean>;\n  hasActions: (side: ListItemRevealSide) => boolean;\n  /** The full-swipe-through gesture fired — emit `confirm` and click the slot's own action. */\n  onConfirm: (side: ListItemRevealSide) => void;\n};\n\n/**\n * The swipe-reveal-confirm gesture behind `ore-list-item`'s `actions-left`/`actions-right` slots\n * — isolated here since it's the one genuinely tricky part of the component (three distance\n * thresholds, inline style/attribute choreography during an active drag). Deliberately *not* a\n * shared primitive: `createPanGesture` itself already is one (shared with `ore-toast`),\n * but this two-stage reveal/confirm layer on top of it has exactly one consumer today —\n * generalizing it further would be speculative, not reusable.\n *\n * Only sets/clears the `revealed`/`data-dragging`/`data-confirming` attributes and `--_swipe-x`\n * style — it does not itself emit `reveal`/`conceal`. `ore-list-item` already watches `revealed`\n * for transitions (to cover *both* this gesture and a directly-set attribute uniformly), so this\n * module setting the attribute is enough to drive both that watcher and `list.css`'s\n * `[revealed]` styling.\n */\nexport function createRevealState(el: HTMLElement, target: Element, options: RevealStateOptions): PanGesture {\n  const resolveSide = (detail: PanGestureDetail): ListItemRevealSide => (detail.distance < 0 ? 'right' : 'left');\n\n  // Inline `--_swipe-x` override during an active drag lets the row (and both action panels,\n  // which read the same variable) follow the pointer 1:1 with no transition lag. Clearing it\n  // hands control back to the `[revealed]`/`:focus-within` CSS rules in list-item.css, which\n  // then animate normally via the CSS `transition`.\n  const resetInline = (): void => {\n    el.removeAttribute('data-dragging');\n    el.removeAttribute('data-confirming');\n    el.style.removeProperty('--_swipe-x');\n  };\n\n  let pan: PanGesture;\n\n  pan = createPanGesture(target, {\n    axis: 'x',\n    disabled: () => options.disabled.value,\n    onEnd: (detail) => {\n      resetInline();\n\n      if (detail.reason !== 'release') return;\n\n      const side = resolveSide(detail);\n\n      if (options.hasActions(side) && Math.abs(detail.distance) >= REVEAL_THRESHOLD) el.setAttribute('revealed', side);\n    },\n    onMove: (detail) => {\n      const side = resolveSide(detail);\n\n      if (!options.hasActions(side)) return;\n\n      const distance = Math.abs(detail.distance);\n\n      if (distance >= CONFIRM_THRESHOLD) {\n        pan.cancel();\n        el.removeAttribute('revealed');\n        options.onConfirm(side);\n\n        return;\n      }\n\n      const revealProgress = Math.min(distance / REVEAL_THRESHOLD, 1);\n\n      el.setAttribute('data-dragging', '');\n      el.toggleAttribute('data-confirming', distance / CONFIRM_THRESHOLD >= CONFIRM_WARNING_RATIO);\n      el.style.setProperty('--_swipe-x', String((side === 'left' ? 1 : -1) * revealProgress));\n    },\n    pointerCapture: false,\n  });\n\n  return pan;\n}\n","@layer refine.base {\n  /* `--_gap` / `--_padding` / `--_font-size` are intentionally not emitted by any mixin in this\n     component's own `styles` array — they're inherited from the parent `ore-list`'s\n     `sizeVariantMixin(LIST_SIZE_PRESET)` call the same way `ore-menu-item` inherits\n     `--_gap`/`--_font-size` from `ore-menu` (see `LIST_SIZE_PRESET`'s doc comment). The\n     `var(..., fallback)` defaults below cover standalone use outside an `ore-list`. */\n  :host {\n    --_actions-width: var(--list-item-actions-width, var(--size-24));\n    position: relative;\n    display: block;\n    overflow: hidden;\n    color: var(--color-contrast-700);\n  }\n\n  /* ========================================\n       Row\n       ======================================== */\n\n  .row {\n    position: relative;\n    z-index: 1;\n    box-sizing: border-box;\n    display: flex;\n    gap: var(--_gap, var(--size-4));\n    align-items: center;\n    width: 100%;\n    min-height: var(--_min-height, var(--size-4));\n    padding: var(--_padding, var(--size-2-5) var(--size-4));\n    padding-inline-end: var(--_padding-inline-end, var(--size-6));\n    font-size: var(--_font-size, var(--text-sm));\n    text-align: start;\n    touch-action: pan-y;\n    cursor: default;\n    outline: none;\n    background: var(--list-item-bg, var(--color-canvas));\n    border: none;\n    transform: translateX(calc(var(--_swipe-x, 0) * var(--_actions-width)));\n    transition: var(--_motion-transition, transform var(--transition-fast), background var(--transition-fast));\n  }\n\n  .leading,\n  .trailing {\n    display: flex;\n    flex-shrink: 0;\n    align-items: center;\n  }\n\n  .content {\n    display: flex;\n    flex: 1;\n    flex-direction: column;\n    gap: var(--size-0-5);\n    min-width: 0;\n  }\n\n  .title {\n    display: block;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n  }\n\n  .description {\n    display: block;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    font-size: var(--text-xs);\n    color: var(--color-contrast-400);\n    white-space: nowrap;\n  }\n\n  .description:empty {\n    display: none;\n  }\n\n  .row:hover {\n    background: var(--list-item-hover-bg, var(--color-contrast-100));\n  }\n\n  .row:focus-visible {\n    outline: var(--focus-ring);\n    outline-offset: -2px;\n  }\n\n  /* ========================================\n       Selected / Disabled States\n       ======================================== */\n\n  :host([selected]) .row {\n    color: var(--color-primary);\n    background: var(--list-item-selected-bg, color-mix(in oklch, var(--color-primary) 10%, transparent));\n  }\n\n  :host([disabled]) {\n    pointer-events: none;\n    opacity: 0.6;\n  }\n\n  /* ========================================\n       Swipe Action Panels\n       ======================================== */\n\n  .actions {\n    position: absolute;\n    inset-block: 0;\n    display: flex;\n    align-items: stretch;\n    width: var(--_actions-width);\n    transition: var(--_motion-transition, transform var(--transition-fast));\n  }\n\n  /* A single slotted action button fills the whole revealed panel — the common case (one big\n     tappable target, e.g. a full-height \"Delete\" button) rather than a small icon-sized hit area.\n     This stretches the slotted element's own light-DOM box, which is enough for plain elements\n     (a native <button>, an <a>, ...). It is NOT enough on its own for `ore-button`: its visible\n     surface is an inner `[part=\"button\"]` with a fixed height from its size preset, independent\n     of its own host box size — pass `fullheight` on the `ore-button` itself too (see its own\n     `fullheight` prop) to actually fill this panel edge-to-edge. */\n  .actions ::slotted(*) {\n    flex: 1;\n    height: 100%;\n  }\n\n  .actions-left {\n    left: 0;\n    transform: translateX(calc((var(--_swipe-x, 0) - 1) * 100%));\n  }\n\n  .actions-right {\n    right: 0;\n    transform: translateX(calc((var(--_swipe-x, 0) + 1) * 100%));\n  }\n\n  /* `:host(:has(...))` (`:has()` as `:host()`'s functional argument) is invalid — `:host()`\n     only accepts a compound selector and doesn't accept `:has()` inside it. The plain `:host`\n     pseudo-class chained directly with `:has()` (no parentheses) is the valid form. Kept as\n     separate rules (not grouped via a comma with the `[revealed]` rules) so a selector list\n     doesn't silently drop the whole rule if either half were ever invalid again. */\n  :host([revealed='left']) {\n    --_swipe-x: 1;\n  }\n\n  :host([revealed='right']) {\n    --_swipe-x: -1;\n  }\n\n  :host:has(.actions-left:focus-within) {\n    --_swipe-x: 1;\n  }\n\n  :host:has(.actions-right:focus-within) {\n    --_swipe-x: -1;\n  }\n\n  /* Suppress the transition while a drag is actively updating `--_swipe-x` inline so the row\n     and action panels track the pointer 1:1 instead of lagging behind on every move event. */\n  :host([data-dragging]) .row,\n  :host([data-dragging]) .actions-left,\n  :host([data-dragging]) .actions-right {\n    transition: none;\n  }\n\n  /* Feedback that the drag has passed into \"swipe all the way through\" territory (close to\n     CONFIRM_THRESHOLD) — set by list-item.ts's onMove once past ~85% of that distance, cleared\n     on release/cancel/commit. Visual-only; the confirm itself fires from JS regardless of CSS. */\n  :host([data-confirming]) .actions-left,\n  :host([data-confirming]) .actions-right {\n    filter: saturate(1.4) brightness(0.94);\n  }\n}\n","import {\n  bind,\n  define,\n  getHost,\n  html,\n  inject,\n  onCleanup,\n  onMounted,\n  prop,\n  useEmit,\n  useSlots,\n  watchEffect,\n} from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\n\nimport { disablableBundle } from '../../shared';\nimport { reducedMotionMixin } from '../../styles';\nimport { createRevealState } from './_list-item-reveal';\nimport { LIST_CTX } from './list';\nimport componentStyles from './list-item.css?inline';\n\n/** Which side's action panel is currently revealed on a list item. */\nexport type ListItemRevealSide = 'left' | 'right';\n\n/** Events emitted by the list-item component */\nexport type OreListItemEvents = {\n  /** Emitted when the revealed action panel closes (gesture, tap, or programmatic). */\n  conceal: { item: HTMLElement };\n  /**\n   * Emitted when a swipe crosses the full-swipe-through distance — the \"swiped all the way\"\n   * confirm gesture. Fired just before the slotted action's own click (if any).\n   */\n  confirm: { item: HTMLElement; side: ListItemRevealSide };\n  /** Emitted when the item becomes deselected. */\n  deselect: { item: HTMLElement; value: null | string };\n  /** Emitted when a swipe/focus reveals an action panel. */\n  reveal: { item: HTMLElement; side: ListItemRevealSide };\n  /** Emitted when the item becomes selected (only meaningful inside a `selectable` `ore-list`). */\n  select: { item: HTMLElement; value: null | string };\n};\n\n/** List-item component properties */\nexport type OreListItemProps = {\n  /** Disable this item — blocks pointer interaction, swipe actions, and selection */\n  disabled?: boolean;\n  /** Which action panel is revealed: 'left' | 'right' (absent = closed). Settable programmatically. */\n  revealed?: ListItemRevealSide;\n  /**\n   * Opaque value compared against the parent `selectable` `ore-list`'s own `value` to derive\n   * `selected` — required for selection to work. There's no separate `selected` prop: the parent\n   * list's `value` is the single source of truth, so this item's selected state can't drift from\n   * it. Also reported in `select`/`deselect`/the parent's `change` event.\n   */\n  value?: string;\n};\n\n/** Maps a reveal side to its slot name — the one place this pairing is spelled out. */\nconst actionSlot = (side: ListItemRevealSide): 'actions-left' | 'actions-right' =>\n  side === 'left' ? 'actions-left' : 'actions-right';\n\n/**\n * A single row inside `ore-list`. Renders `leading`/default (title)/`description`/`trailing`\n * content plus two off-canvas action panels (`actions-left`, `actions-right`) that a horizontal\n * pointer/touch swipe reveals — useful for mobile-style row actions (archive, delete, …). An\n * action panel only opens if it actually has slotted content; swiping the other direction is a\n * no-op. Revealed actions stay reachable from the keyboard (Tab focus on a slotted action button\n * reveals its panel via `:focus-within`, independent of any gesture).\n *\n * Swiping past the reveal distance snaps the panel fully open on release; swiping further still —\n * past the full-swipe-through distance — auto-confirms that side's action immediately (fires\n * `confirm` and clicks the slot's first element), the same \"swipe all the way\" shortcut as iOS\n * Mail's delete gesture.\n *\n * Closing a revealed panel is deliberately one-directional: tap/click the row itself, tap outside\n * the item, or open a different item's panel. Reverse-swiping an already-open item is not\n * supported — see `ore-list`'s docs for the reasoning.\n *\n * @element ore-list-item\n *\n * @attr {boolean} disabled - Disable this item\n * @attr {boolean} selected - Read-only reflected attribute: `true` when this item's `value` matches the parent `ore-list`'s `value`. Not independently settable.\n * @attr {string}  value    - Opaque value compared against the parent list's `value` to derive `selected`; also reported in select/change events\n * @attr {string}  revealed - Which action panel is revealed: 'left' | 'right'\n *\n * @fires select   - Item becomes selected. detail: { item: HTMLElement, value: string | null }\n * @fires deselect - Item becomes deselected. detail: { item: HTMLElement, value: string | null }\n * @fires reveal   - An action panel opens. detail: { item: HTMLElement, side: 'left' | 'right' }\n * @fires conceal  - The revealed action panel closes. detail: { item: HTMLElement }\n * @fires confirm  - Swiped all the way through — fires before the slotted action's own click. detail: { item: HTMLElement, side: 'left' | 'right' }\n *\n * @slot leading - Content before the title (e.g. icon, avatar)\n * @slot - Item title\n * @slot description - Secondary line below the title\n * @slot trailing - Content after the title (e.g. meta text, chevron)\n * @slot actions-left - Buttons revealed by swiping right (or focusing into this slot)\n * @slot actions-right - Buttons revealed by swiping left (or focusing into this slot)\n *\n * @cssprop --list-item-actions-width - Width of each action panel (default 6rem)\n * @cssprop --list-item-bg - Row background color\n * @cssprop --list-item-hover-bg - Row background on hover\n * @cssprop --list-item-selected-bg - Row background when selected\n * @part row - The row wrapper (focusable, swipeable)\n * @part leading - The leading slot container\n * @part content - The title + description container\n * @part title - The title slot container\n * @part description - The description slot container\n * @part trailing - The trailing slot container\n * @part actions-start - The left action panel container\n * @part actions-end - The right action panel container\n * @example\n * ```html\n * <ore-list-item>\n *   <ore-icon slot=\"leading\" name=\"mail\"></ore-icon>\n *   Inbox\n *   <span slot=\"trailing\">12</span>\n * </ore-list-item>\n * <ore-list-item>\n *   Newsletter\n *   <span slot=\"description\">From Acme Inc.</span>\n *   <ore-button slot=\"actions-right\" color=\"error\">Delete</ore-button>\n * </ore-list-item>\n * ```\n */\nexport const LIST_ITEM_TAG = 'ore-list-item' as const;\ndefine<OreListItemProps>(LIST_ITEM_TAG, {\n  props: {\n    ...disablableBundle,\n    revealed: prop.oneOf<ListItemRevealSide | undefined>(['left', 'right'], undefined),\n    value: prop.string(),\n  },\n\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreListItemEvents>();\n    const slots = useSlots<'actions-left' | 'actions-right' | 'description' | 'leading' | 'trailing'>();\n\n    const listCtx = inject(LIST_CTX);\n    const isSelectable = computed(() => Boolean(listCtx?.selectable.value));\n    // Derived, not owned: `ore-list`'s `value` is the single source of truth, so this can never\n    // drift out of sync with a sibling the way an independently-settable `selected` prop could.\n    const isSelected = computed(\n      () => props.value.value != null && listCtx != null && listCtx.value.value === props.value.value,\n    );\n\n    const hasActions = (side: ListItemRevealSide): boolean => slots.has(actionSlot(side)).value;\n\n    onMounted(() => {\n      const row = el.shadowRoot?.querySelector<HTMLElement>('.row');\n\n      if (!row) return;\n\n      const pan = createRevealState(el, row, {\n        disabled: computed(() => props.disabled.value || Boolean(props.revealed.value)),\n        hasActions,\n        // Clicks the slot's own first element (the common case: a single action button) so its own\n        // click handler runs the real action — `confirm` covers slots without a clickable element.\n        onConfirm: (side) => {\n          const target = slots.elements(actionSlot(side)).value[0] as HTMLElement | undefined;\n\n          emit('confirm', { item: el, side });\n          target?.click();\n        },\n      });\n\n      onCleanup(() => pan.dispose());\n    });\n\n    // Reflects the derived `selected` state as a plain boolean attribute — the styling/\n    // `[selected]`-selector hook — the same way `prop.bool()`'s own reflection would, since it\n    // isn't a real settable prop anymore.\n    watchEffect(() => {\n      el.toggleAttribute('selected', isSelected.value);\n    });\n\n    // Emits select/deselect/reveal/conceal for both gesture-driven AND externally-set (attribute,\n    // or the parent list's `value`) state changes — the plain-reflected-prop equivalent of\n    // ore-accordion-item's native <details> `toggle`-event listener (there's no backing native\n    // element here to piggyback on).\n    let lastSelected = isSelected.value;\n\n    watchEffect(() => {\n      const current = isSelected.value;\n\n      if (current === lastSelected) return;\n\n      lastSelected = current;\n      emit(current ? 'select' : 'deselect', { item: el, value: props.value.value ?? null });\n    });\n\n    let lastRevealed = props.revealed.value ?? null;\n\n    watchEffect(() => {\n      const current = props.revealed.value ?? null;\n\n      if (current === lastRevealed) return;\n\n      lastRevealed = current;\n\n      if (current) {\n        // Only one item may have its swipe actions revealed at a time — tell the list directly\n        // instead of dispatching an event for it to listen for.\n        listCtx?.requestReveal(el);\n        emit('reveal', { item: el, side: current });\n      } else {\n        emit('conceal', { item: el });\n      }\n    });\n\n    const handleActivate = (event: Event): void => {\n      if (props.disabled.value) return;\n\n      if (props.revealed.value) {\n        event.preventDefault();\n        event.stopPropagation();\n        el.removeAttribute('revealed');\n\n        return;\n      }\n\n      if (!isSelectable.value) return;\n\n      const value = props.value.value;\n\n      // Re-clicking an already-selected item deselects it; a value is required to select at all\n      // (undefined would otherwise match every valueless item at once).\n      if (value != null) listCtx?.select(isSelected.value ? undefined : value);\n    };\n\n    const handleRowKeydown = (event: KeyboardEvent): void => {\n      if (event.key !== 'Enter' && event.key !== ' ') return;\n\n      if (props.disabled.value || (!props.revealed.value && !isSelectable.value)) return;\n\n      event.preventDefault();\n      handleActivate(event);\n    };\n\n    bind({\n      attr: {\n        'aria-disabled': () => (props.disabled.value ? 'true' : null),\n        'aria-selected': () => (isSelectable.value ? String(isSelected.value) : null),\n        role: () => (isSelectable.value ? 'option' : 'listitem'),\n      },\n    });\n\n    return html`\n      <div\n        class=\"row\"\n        part=\"row\"\n        tabindex=\"${() => (props.disabled.value ? '-1' : '0')}\"\n        @click=\"${handleActivate}\"\n        @keydown=\"${handleRowKeydown}\">\n        <span class=\"leading\" part=\"leading\"><slot name=\"leading\"></slot></span>\n        <span class=\"content\" part=\"content\">\n          <span class=\"title\" part=\"title\"><slot></slot></span>\n          <span class=\"description\" part=\"description\"><slot name=\"description\"></slot></span>\n        </span>\n        <span class=\"trailing\" part=\"trailing\"><slot name=\"trailing\"></slot></span>\n      </div>\n      <span class=\"actions actions-left\" part=\"actions-start\"><slot name=\"actions-left\"></slot></span>\n      <span class=\"actions actions-right\" part=\"actions-end\"><slot name=\"actions-right\"></slot></span>\n    `;\n  },\n\n  shadow: { delegatesFocus: true },\n  styles: [reducedMotionMixin, componentStyles],\n});\n","/**\n * Validates that a string is a safe CSS length value before injecting it\n * into a CSS custom property. Accepts standard length units, percentages,\n * CSS keywords, and `calc()`/`var()` expressions without embedded semicolons,\n * curly braces, or other CSS injection vectors.\n *\n * @returns The trimmed value if safe, `null` otherwise.\n */\nexport function safeCSSLength(value: string | null | undefined): string | null {\n  if (!value) return null;\n\n  const v = value.trim();\n\n  // Block CSS injection sequences (parens excluded — needed by var()/calc())\n  if (/[;{}\\n\\r]/.test(v)) return null;\n\n  // Allow: numbers with units, %, keywords, var(--token), calc(...), env(...)\n  if (\n    /^-?(\\d+(\\.\\d+)?)(px|em|rem|%|vh|vw|vmin|vmax|dvh|dvw|svh|svw|ch|ex|lh|rlh|cm|mm|in|pt|pc|fr|s|ms|deg|rad|turn)$/.test(\n      v,\n    )\n  )\n    return v;\n\n  if (/^(0|auto|none|inherit|initial|unset|revert)$/.test(v)) return v;\n\n  // Allow CSS function expressions: var(--token), calc(...), env(...), clamp(...), min(...), max(...)\n  // Tightened pattern: must match the whole value and inner parens must close properly.\n  if (/^(var|calc|env|clamp|min|max)\\([^;{}]*\\)$/.test(v)) return v;\n\n  return null;\n}\n","import { computed, type Readable } from '@vielzeug/ripple';\n\nimport type { LinkTarget } from '../shared';\n\n/**\n * Computes a safe `rel` attribute value for anchor elements.\n *\n * When `target=\"_blank\"`, automatically injects `noopener` and `noreferrer`\n * to prevent reverse tabnapping attacks (the opened page accessing\n * `window.opener` to redirect the origin).\n *\n * @param rel    - The explicit `rel` prop value (may be undefined).\n * @param target - The link `target` prop value (may be undefined).\n * @returns A `rel` string with security tokens merged in, or `null` when no\n *          rel is needed.\n */\nexport function computeSafeRel(rel: string | undefined, target: string | undefined): string | null {\n  const base = rel ?? '';\n\n  if (target !== '_blank') return base || null;\n\n  const parts = new Set(base.split(/\\s+/).filter(Boolean));\n\n  parts.add('noopener');\n  parts.add('noreferrer');\n\n  return [...parts].join(' ');\n}\n\n/**\n * Props required by any component that renders as an anchor when `href` is set.\n * Import and spread into your component's props type to get consistent link support.\n */\nexport type LinkProps = {\n  /** When set, the component renders as an `<a>` instead of its default element. */\n  href?: string;\n  /** Anchor `rel` attribute. `noopener noreferrer` is automatically added for `target=\"_blank\"`. */\n  rel?: string;\n  /** Anchor browsing context. */\n  target?: LinkTarget;\n};\n\n/**\n * Derives computed link state from reactive `href`, `rel`, and `target` signals.\n *\n * Returns:\n * - `isLink` — true when `href` is set (and optionally not disabled)\n * - `effectiveRel` — `rel` merged with security tokens when `target=\"_blank\"`\n *\n * @example\n * ```ts\n * const { isLink, effectiveRel } = useLinkProps(props.href, props.rel, props.target);\n * ```\n */\nexport function useLinkProps(\n  href: Readable<string | undefined>,\n  rel: Readable<string | undefined>,\n  target: Readable<LinkTarget | undefined>,\n  disabled?: Readable<boolean>,\n) {\n  const isLink = computed(() => !!href.value && !disabled?.value);\n  const effectiveRel = computed(() => computeSafeRel(rel.value, target.value));\n\n  return { effectiveRel, isLink };\n}\n","@layer refine.base {\n  /* ========================================\n       Base Styles\n       ======================================== */\n\n  :host {\n    --group-gap: var(--size-2);\n    --group-radius: var(--_radius, var(--rounded-lg));\n    display: inline-flex;\n  }\n\n  .button-group {\n    display: flex;\n    flex-direction: row;\n    gap: var(--group-gap);\n  }\n}\n\n@layer refine.variants {\n  /* ========================================\n       Orientation\n       ======================================== */\n\n  :host([orientation='vertical']) .button-group {\n    flex-direction: column;\n  }\n}\n\n@layer refine.overrides {\n  /* ========================================\n       Full Width\n       ======================================== */\n\n  :host([fullwidth]) {\n    display: flex;\n    width: 100%;\n  }\n\n  :host([fullwidth]) .button-group {\n    width: 100%;\n  }\n\n  :host([fullwidth]) ::slotted(ore-button) {\n    flex: 1;\n  }\n\n  /* ========================================\n       Attached Mode\n       ======================================== */\n\n  :host([attached]) .button-group {\n    gap: 0;\n  }\n\n  /* Ensure attached buttons have proper z-index on hover/focus */\n  :host([attached]) ::slotted(ore-button:hover),\n  :host([attached]) ::slotted(ore-button:focus-within) {\n    position: relative;\n    z-index: 1;\n  }\n\n  /* Horizontal attached - remove inner borders and round corners */\n  :host([attached]:not([orientation='vertical'])) ::slotted(ore-button) {\n    --button-radius: 0;\n  }\n\n  :host([attached]:not([orientation='vertical'])) ::slotted(ore-button:not(:first-child)) {\n    --button-border-start: 0;\n  }\n\n  :host([attached]:not([orientation='vertical'])) ::slotted(ore-button:first-child) {\n    --button-radius: var(--group-radius) 0 0 var(--group-radius);\n  }\n\n  :host([attached]:not([orientation='vertical'])) ::slotted(ore-button:last-child) {\n    --button-radius: 0 var(--group-radius) var(--group-radius) 0;\n  }\n\n  /* Vertical attached - remove inner borders and round corners */\n  :host([attached][orientation='vertical']) ::slotted(ore-button) {\n    --button-radius: 0;\n  }\n\n  :host([attached][orientation='vertical']) ::slotted(ore-button:not(:first-child)) {\n    --button-border-top: 0;\n  }\n\n  :host([attached][orientation='vertical']) ::slotted(ore-button:first-child) {\n    --button-radius: var(--group-radius) var(--group-radius) 0 0;\n  }\n\n  :host([attached][orientation='vertical']) ::slotted(ore-button:last-child) {\n    --button-radius: 0 0 var(--group-radius) var(--group-radius);\n  }\n}\n","import { createContext, define, html, prop, provide } from '@vielzeug/ore';\nimport type { Readable } from '@vielzeug/ripple';\n\nimport type { ComponentSize, RoundedSize, ThemeColor } from '../../shared';\nimport { roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { roundedVariantMixin } from '../../styles';\nimport type { ButtonVariant } from '../button/button';\nimport componentStyles from './button-group.css?inline';\n\n/** Button group properties */\nexport type OreButtonGroupProps = {\n  /** Join buttons together into a single unit */\n  attached?: boolean;\n  /** Theme color tint for all child buttons */\n  color?: ThemeColor;\n  /** Group children span full width */\n  fullwidth?: boolean;\n  /** Label for screen readers */\n  label?: string;\n  /** Layout direction */\n  orientation?: 'horizontal' | 'vertical';\n  /** Corner radius of the group container (and its attached-mode end buttons) */\n  rounded?: RoundedSize | '';\n  /** Shared size for all child buttons */\n  size?: ComponentSize;\n  /** Shared visual variant for all child buttons */\n  variant?: ButtonVariant;\n};\n\n/** Shared context propagated from ore-button-group to child ore-button elements */\nexport type ButtonGroupContext = {\n  color: Readable<ThemeColor | undefined>;\n  size: Readable<ComponentSize | undefined>;\n  variant: Readable<ButtonVariant | undefined>;\n};\n\nexport const BUTTON_GROUP_CTX = createContext<ButtonGroupContext | undefined>('OreButtonGroup');\n\n/**\n * A container for grouping related buttons.\n * Child `ore-button` components automatically inherit the group's color, size, and variant.\n *\n * @element ore-button-group\n *\n * @attr {boolean} attached - Join buttons together into a unit\n * @attr {string} color - Shared color tint: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {boolean} fullwidth - Group spans full width\n * @attr {string} label - Accessible label\n * @attr {string} orientation - 'horizontal' | 'vertical'\n * @attr {string} rounded - Corner radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full' (bare attribute defaults to 'full')\n * @attr {string} size - Shared size: 'sm' | 'md' | 'lg'\n * @attr {string} variant - Shared visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'frost'\n *\n * @slot - Place ore-button elements here\n *\n * @cssprop --group-gap - Gap between buttons (non-attached mode)\n * @cssprop --group-radius - Border radius of the group container, defaults to the `rounded` attribute's token\n * @cssprop --button-radius - Passed through to child buttons to control corner radius\n * @cssprop --button-border-start - Passed through to suppress start borders in attached mode\n * @cssprop --button-border-top - Passed through to suppress top borders in vertical attached mode\n * @part group - Group container.\n * @example\n * ```html\n * <ore-button-group attached rounded=\"full\">\n *   <ore-button variant=\"solid\" color=\"primary\">Save</ore-button>\n *   <ore-button variant=\"solid\" color=\"primary\">Save &amp; Continue</ore-button>\n * </ore-button-group>\n * <ore-button-group orientation=\"vertical\" size=\"sm\">\n *   <ore-button>Top</ore-button>\n *   <ore-button>Middle</ore-button>\n *   <ore-button>Bottom</ore-button>\n * </ore-button-group>\n * ```\n */\nexport const BUTTON_GROUP_TAG = 'ore-button-group' as const;\ndefine<OreButtonGroupProps>(BUTTON_GROUP_TAG, {\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...roundableBundle,\n    attached: prop.bool(false),\n    fullwidth: prop.bool(false),\n    label: prop.string(),\n    orientation: prop.string<'horizontal' | 'vertical'>(),\n    variant: prop.string(),\n  },\n  setup(props) {\n    provide(BUTTON_GROUP_CTX, {\n      color: props.color!,\n      size: props.size!,\n      variant: props.variant!,\n    });\n\n    return html`\n      <div class=\"button-group\" part=\"group\" role=\"group\" aria-label=\"${props.label}\">\n        <slot></slot>\n      </div>\n    `;\n  },\n  styles: [roundedVariantMixin, componentStyles],\n});\n","import { bind } from '@vielzeug/ore';\nimport type { Readable, Signal } from '@vielzeug/ripple';\n\nimport type { ComponentSize } from '../../types';\n\n/**\n * Minimal shape of the handle returned by `createCheckable` that\n * `applyCheckableBinding` needs. Matches both checkbox (with `indeterminate`)\n * and switch (without).\n */\nexport type CheckableBindingHandle = {\n  assistiveId: string;\n  checked: Signal<boolean>;\n  disabled: Readable<boolean>;\n  errorText: Readable<string>;\n  handleClick: (event: MouseEvent) => boolean;\n  handleKeydown: (event: KeyboardEvent) => boolean;\n  helperText: Readable<string>;\n  indeterminate?: Signal<boolean>;\n  labelId: string;\n  /** Reflects `aria-required` — there's no native form control here to carry a real `required` attribute. */\n  required?: Readable<boolean | undefined>;\n};\n\n/**\n * `prop.string()` already reflects `error`'s raw value as an attribute, but that leaves the\n * attribute present-but-empty (`error=\"\"`) once set instead of removing it — this normalizes\n * an empty error back to \"no attribute at all\". Shared by every text-field component\n * (`ore-input`, `ore-textarea`, `ore-message-composer`) since `bind()`'s own `error` writer\n * needs a derived getter, not the raw prop, to get that behavior.\n *\n * @example\n * ```ts\n * bind({ attr: { error: errorAttr(errorText), size: props.size, variant: props.variant } });\n * ```\n */\nexport const errorAttr = (errorText: Readable<string>): (() => string | undefined) => {\n  return () => errorText.value || undefined;\n};\n\n/**\n * Applies the standard host bindings shared by all checkable components\n * (checkbox, switch, radio).\n *\n * Wires `role`, all ARIA attributes, `checked`, `size`, `tabindex`, the\n * `is-checked`/`is-disabled` classes, and the `click`/`keydown` event handlers.\n *\n * Pass `handle.indeterminate` for components that need it (checkbox);\n * omit it for switch/radio.\n */\nexport const applyCheckableBinding = (\n  fCtxSize: Readable<ComponentSize | undefined>,\n  handle: CheckableBindingHandle,\n  role: 'checkbox' | 'radio' | 'switch',\n): void => {\n  const {\n    assistiveId,\n    checked,\n    disabled,\n    errorText,\n    handleClick,\n    handleKeydown,\n    helperText,\n    indeterminate,\n    labelId,\n    required,\n  } = handle;\n\n  bind({\n    attr: {\n      ...(indeterminate !== undefined && { indeterminate }),\n      ariaChecked: () => {\n        if (role === 'checkbox' && indeterminate?.value) return 'mixed';\n\n        return checked.value ? 'true' : 'false';\n      },\n      ariaDescribedby: () => (errorText.value || helperText.value ? assistiveId : null),\n      ariaDisabled: () => (disabled.value ? 'true' : null),\n      ariaInvalid: () => (errorText.value ? 'true' : null),\n      ariaLabelledby: labelId,\n      ariaRequired: () => (required?.value ? 'true' : null),\n      checked,\n      role,\n      size: fCtxSize,\n      tabindex: () => (disabled.value ? undefined : 0),\n    },\n    class: () => ({\n      'is-checked': checked.value,\n      'is-disabled': disabled.value,\n      ...(indeterminate !== undefined && { 'is-indeterminate': indeterminate.value }),\n    }),\n    on: {\n      click: handleClick,\n      keydown: handleKeydown,\n    },\n  });\n};\n","import { html } from '@vielzeug/ore';\nimport type { Readable } from '@vielzeug/ripple';\n\nimport { type CounterState, counterClassName } from '../../core';\n\n/**\n * Renders the standard assistive text region (helper/error) used across all\n * field components. Encapsulates the repeated `aria-live`/`hidden` markup so\n * each component only passes the data.\n *\n * @param assistiveId - The stable ID shared with the ARIA `aria-describedby` attribute.\n * @param errorText   - Reactive error text signal from the field primitive.\n * @param helperText  - Reactive helper text signal from the field primitive.\n * @param setRef      - Optional callback to capture the container element.\n */\nexport const renderHelperRegion = (\n  assistiveId: string,\n  errorText: Readable<string>,\n  helperText: Readable<string>,\n  setRef?: (el: HTMLElement | null) => void,\n) => {\n  return html`\n    <div\n      class=\"helper-text\"\n      part=\"helper-text\"\n      id=\"${assistiveId}\"\n      role=\"${() => (errorText.value ? 'alert' : null)}\"\n      aria-live=\"polite\"\n      ?hidden=\"${() => !errorText.value && !helperText.value}\"\n      ref=${(el: HTMLElement | null) => {\n        setRef?.(el);\n      }}>\n      ${() => errorText.value || helperText.value}\n    </div>\n  `;\n};\n\n/**\n * Inline error/success status icon shown inside a field — identical markup across\n * `ore-input`, `ore-textarea`, and `ore-message-composer` (previously hand-duplicated in all\n * three, down to the same derived-signal names).\n */\nexport const renderStatusIcon = (errorText: Readable<string>) => html`\n  <span\n    class=\"status-icon\"\n    part=\"status-icon\"\n    aria-hidden=\"true\"\n    data-status=\"${() => (errorText.value ? 'error' : 'success')}\">\n    ${() =>\n      errorText.value\n        ? html`\n            <ore-icon name=\"alert-circle\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n          `\n        : html`\n            <ore-icon name=\"check\" size=\"14\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n          `}\n  </span>\n`;\n\n/**\n * Character counter + separate helper/error text regions below a field — identical across\n * `ore-textarea` and `ore-message-composer` (kept out of `ore-input`, which slots its\n * helper/error content and drives its counter off a different data-attribute scheme via its\n * own `char-counter` part — a genuinely different shape, not worth forcing into this one).\n */\nexport const renderFieldStatusRegion = (tf: {\n  assistiveId: string;\n  counter: Readable<CounterState> | null;\n  errorId: string;\n  errorText: Readable<string>;\n  helperText: Readable<string>;\n}) => html`\n  <span class=\"${() => counterClassName(tf.counter?.value)}\" aria-live=\"polite\" ?hidden=\"${() => !tf.counter}\">\n    ${() => tf.counter?.value.counterText.replace(' / ', '/') ?? ''}\n  </span>\n  <div\n    id=\"${tf.assistiveId}\"\n    class=\"helper-text\"\n    aria-live=\"polite\"\n    part=\"helper\"\n    ?hidden=\"${() => !!tf.errorText.value || !tf.helperText.value}\">\n    ${() => tf.helperText.value}\n  </div>\n  <div id=\"${tf.errorId}\" class=\"helper-text\" role=\"alert\" part=\"error\" ?hidden=\"${() => !tf.errorText.value}\">\n    ${() => tf.errorText.value}\n  </div>\n`;\n","import type { Readable } from '@vielzeug/ripple';\n\nimport type { ButtonType } from '../../shared';\n\n/**\n * Handles form submission relay for form-associated button-like components.\n *\n * The inner `<button>` always has `type=\"button\"` so the shadow DOM never\n * drives native form actions directly. This composable intercepts clicks and\n * forwards submit/reset to the associated form via `ElementInternals`.\n *\n * @param form      - The associated HTMLFormElement (from `useField().internals.form`).\n * @param type      - Reactive signal for the button `type` prop.\n * @param isDisabled - Reactive signal indicating whether the button is disabled/loading.\n * @param host       - The host custom element.\n * @returns A click handler to attach to the inner element.\n */\nexport function useFormAction(\n  getForm: () => HTMLFormElement | null,\n  type: Readable<ButtonType | undefined>,\n  isDisabled: Readable<boolean>,\n  host: HTMLElement,\n): (e: MouseEvent) => void {\n  return (e: MouseEvent) => {\n    if (isDisabled.value) {\n      e.preventDefault();\n      e.stopImmediatePropagation();\n\n      return;\n    }\n\n    const form = getForm();\n\n    if (form) {\n      if (type.value === 'submit') {\n        e.preventDefault();\n        form.requestSubmit();\n      } else if (type.value === 'reset') {\n        e.preventDefault();\n        form.reset();\n      }\n    }\n\n    // Re-dispatch if the native click didn't bubble to host (shadow DOM interop).\n    if (!e.composedPath().includes(host)) {\n      host.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, composed: true }));\n    }\n  };\n}\n","@layer refine.base {\n  :host {\n    --_bg: var(--button-bg, var(--color-contrast-100));\n    --_color: var(--button-color, var(--color-contrast-900));\n    --_border-color: var(--button-border-color, var(--color-contrast-300));\n    --_radius: var(--button-radius, var(--rounded-lg));\n\n    display: inline-flex;\n    align-items: center;\n    justify-content: var(--button-justify, center);\n  }\n\n  /* Link mode: disable pointer interaction on the inner <a> while disabled/loading. */\n  :host([disabled]) a,\n  :host([loading]) a {\n    pointer-events: none;\n    cursor: not-allowed;\n  }\n\n  :host([loading]) a {\n    cursor: wait;\n  }\n\n  [part='button'] {\n    position: relative;\n    box-sizing: border-box;\n    display: flex;\n    gap: var(--_gap, var(--size-2));\n    align-items: center;\n    justify-content: var(--button-justify, center);\n    width: 100%;\n    min-width: 0;\n    height: var(--_height, var(--size-10));\n    min-height: var(--_touch-target);\n    padding: var(--_padding, var(--size-2) var(--size-4));\n    font-size: var(--_font-size, var(--text-sm));\n    font-weight: var(--font-medium);\n    line-height: var(--_line-height, var(--leading-normal));\n    color: var(--_color);\n    white-space: nowrap;\n    text-decoration: none;\n    cursor: pointer;\n    user-select: none;\n    background: var(--_bg);\n    border: var(--button-border, var(--border)) solid var(--_border-color);\n    border-block-start-width: var(--button-border-top, var(--button-border, var(--border)));\n    border-block-end-width: var(--button-border-bottom, var(--button-border, var(--border)));\n    border-inline-start-width: var(--button-border-start, var(--button-border, var(--border)));\n    border-inline-end-width: var(--button-border-end, var(--button-border, var(--border)));\n    border-radius: var(--_radius);\n    transition: var(\n      --_motion-transition,\n      background var(--transition-normal),\n      border-color var(--transition-normal),\n      box-shadow var(--transition-normal),\n      color var(--transition-normal),\n      transform 120ms var(--ease-spring)\n    );\n  }\n\n  [part='button']:focus-visible {\n    outline: none;\n  }\n\n  /* Keyframe must live in shadow DOM — @keyframes don't inherit across shadow roots */\n  @keyframes spin {\n    to {\n      transform: rotate(360deg);\n    }\n  }\n\n  .loader {\n    position: absolute;\n    width: 1em;\n    height: 1em;\n    border: var(--border-2) solid currentcolor;\n    border-inline-end-color: transparent;\n    border-radius: 50%;\n    animation: var(--_motion-animation, spin var(--transition-loader) infinite);\n  }\n\n  .content {\n    display: inline-flex;\n    align-items: center;\n    min-width: 0;\n    max-width: 100%;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    vertical-align: middle;\n    white-space: nowrap;\n  }\n\n  ::slotted([slot='prefix']),\n  ::slotted([slot='suffix']) {\n    display: inline-flex;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n  }\n\n  ::slotted(svg) {\n    flex-shrink: 0;\n    width: var(--_icon-size, var(--leading-6));\n    height: var(--_icon-size, var(--leading-6));\n  }\n}\n\n@layer refine.overrides {\n  :host([fullwidth]) {\n    display: flex;\n    width: 100%;\n  }\n\n  /* `[part='button']`'s own height otherwise comes from the fixed size-preset var\n     (`--_height`, default `--size-10`) — overriding just the host's own box height (e.g. via an\n     external `height: 100%` from a swipe-action panel container) stretches an invisible wrapper\n     without moving the visible button surface at all. Both declarations are needed. */\n  :host([fullheight]) {\n    display: flex;\n    height: 100%;\n  }\n\n  :host([fullheight]) [part='button'] {\n    height: 100%;\n  }\n\n  /* Icon-only always uses perfect circle */\n  :host([rounded][icon-only]) [part='button'] {\n    border-radius: 50%;\n  }\n\n  :host([loading]) .content {\n    visibility: hidden;\n  }\n}\n\n@layer refine.variants {\n  :host([icon-only]) [part='button'] {\n    aspect-ratio: 1;\n    padding: 0;\n  }\n\n  /* ── Per-variant token assignments ─────────────────────────────────────────\n     Each variant sets --_bg/--_color/--_border-color (consuming the public\n     --button-* tokens as overrides) plus optional --_hover-* / --_active-*\n     tokens for interactive states.\n     The shared :is(button, a):hover / :active rules below read these tokens.\n     ─────────────────────────────────────────────────────────────────────── */\n\n  /* Solid (Default) */\n  :host(:not([variant])),\n  :host([variant='solid']) {\n    --_bg: var(--button-bg, var(--_theme-base));\n    --_color: var(--button-color, var(--_theme-contrast));\n    --_border-color: var(--button-border-color, var(--_theme-base));\n    --_hover-bg: var(--_theme-focus);\n    --_active-bg: color-mix(in oklch, var(--_theme-focus) 85%, black);\n    --_active-color: var(--_theme-contrast);\n  }\n\n  /* Flat */\n  :host([variant='flat']) {\n    --_bg: var(--button-bg, color-mix(in oklch, var(--_theme-backdrop) 25%, var(--color-contrast-100)));\n    --_color: var(--button-color, var(--_theme-base));\n    --_border-color: var(--button-border-color, color-mix(in oklch, var(--_theme-focus) 20%, transparent));\n    --_hover-bg: var(--_theme-focus);\n    --_hover-color: var(--_theme-contrast);\n    --_active-bg: color-mix(in oklch, var(--_theme-focus) 85%, black);\n    --_active-color: var(--_theme-contrast);\n  }\n\n  :host([variant='flat']) [part='button'] {\n    box-shadow: var(--inset-shadow-2xs);\n  }\n\n  :host([variant='flat']) [part='button']:hover {\n    box-shadow: var(--inset-shadow-xs);\n  }\n\n  :host([variant='flat']) [part='button']:active {\n    box-shadow: var(--inset-shadow-sm);\n  }\n\n  /* Bordered */\n  :host([variant='bordered']) {\n    --_bg: var(--button-bg, var(--_theme-backdrop));\n    --_color: var(--button-color, var(--_theme-base));\n    --_border-color: var(--button-border-color, var(--_theme-border));\n    --_hover-bg: var(--_theme-focus);\n    --_hover-color: var(--_theme-contrast);\n    --_hover-border-color: var(--_theme-focus);\n    --_active-bg: color-mix(in oklch, var(--_theme-focus) 85%, black);\n    --_active-color: var(--_theme-contrast);\n  }\n\n  :host([variant='bordered']) [part='button'] {\n    box-shadow: var(--inset-shadow-xs);\n  }\n\n  :host([variant='bordered']) [part='button']:hover {\n    box-shadow: var(--inset-shadow-xs);\n  }\n\n  :host([variant='bordered']) [part='button']:active {\n    box-shadow: var(--inset-shadow-sm);\n  }\n\n  /* Outline */\n  :host([variant='outline']) {\n    --_bg: var(--button-bg, transparent);\n    --_color: var(--button-color, var(--_theme-base));\n    --_border-color: var(--button-border-color, var(--_theme-base));\n    --_hover-bg: var(--_theme-backdrop);\n    --_hover-border-color: var(--_theme-focus);\n    --_active-bg: color-mix(in oklch, var(--_theme-base) 85%, black);\n    --_active-color: var(--_theme-contrast);\n  }\n\n  /* Ghost */\n  :host([variant='ghost']) {\n    --_bg: var(--button-bg, transparent);\n    --_color: var(--button-color, var(--_theme-base));\n    --_border-color: var(--button-border-color, transparent);\n    --_hover-bg: var(--_theme-backdrop);\n    --_active-bg: color-mix(in oklch, var(--_theme-base) 85%, black);\n    --_active-color: var(--_theme-contrast);\n  }\n\n  :host([variant='ghost']) [part='button'] {\n    border-width: 0;\n  }\n\n  /* Text */\n  :host([variant='text']) {\n    --_bg: var(--button-bg, transparent);\n    --_color: var(--button-color, var(--_theme-base));\n    --_border-color: var(--button-border-color, transparent);\n    --_hover-color: var(--_theme-focus);\n    --_active-color: color-mix(in oklch, var(--_theme-focus) 85%, black);\n  }\n\n  :host([variant='text']) [part='button'] {\n    border-width: 0;\n  }\n\n  /* Frost — sets its own interactive tokens so the shared rules below apply uniformly */\n  :host([variant='frost']:not([color])) {\n    --_hover-bg: var(--button-frost-active-bg, color-mix(in oklch, var(--color-canvas) 70%, transparent));\n    --_hover-border-color: var(\n      --button-frost-active-border-color,\n      color-mix(in oklch, var(--_theme-focus) 40%, transparent)\n    );\n    --_active-bg: var(--button-frost-active-bg, color-mix(in oklch, var(--color-canvas) 70%, transparent));\n    --_active-border-color: var(\n      --button-frost-active-border-color,\n      color-mix(in oklch, var(--_theme-focus) 40%, transparent)\n    );\n  }\n\n  :host([variant='frost'][color]) {\n    --_hover-bg: var(--button-frost-active-bg, color-mix(in oklch, var(--_theme-backdrop) 50%, var(--_theme-base) 50%));\n    --_hover-border-color: var(\n      --button-frost-active-border-color,\n      color-mix(in oklch, var(--_theme-focus) 65%, transparent)\n    );\n    --_active-bg: var(\n      --button-frost-active-bg,\n      color-mix(in oklch, var(--_theme-backdrop) 50%, var(--_theme-base) 50%)\n    );\n    --_active-border-color: var(\n      --button-frost-active-border-color,\n      color-mix(in oklch, var(--_theme-focus) 65%, transparent)\n    );\n  }\n\n  /* ── Shared interactive states — all variants use --_* tokens set above ── */\n\n  [part='button']:hover {\n    color: var(--_hover-color, var(--_color));\n    background: var(--_hover-bg, var(--_bg));\n    border-color: var(--_hover-border-color, var(--_border-color));\n  }\n\n  [part='button']:active {\n    color: var(--_active-color, var(--_color));\n    background: var(--_active-bg, var(--_bg));\n    border-color: var(--_active-border-color, var(--_border-color));\n    box-shadow: var(--inset-shadow-2xs);\n  }\n}\n\n@layer refine.overrides {\n  /* Focus ring — keyboard navigation only; combines focus shadow + halo to avoid shadow pop */\n  [part='button']:focus-visible {\n    outline: none;\n    box-shadow: var(--_theme-shadow), var(--_theme-halo);\n  }\n\n  /* Hover depth — halo border effect matching ore-input focus style */\n  [part='button']:hover,\n  [part='button']:active {\n    border-color: var(--_hover-border-color, var(--_theme-focus));\n    box-shadow: var(--_theme-shadow), var(--_theme-halo);\n  }\n\n  /* Ghost + Text variants: no border/shadow decoration on hover */\n  :host([variant='ghost']) [part='button']:hover,\n  :host([variant='text']) [part='button']:hover {\n    border-color: transparent;\n    box-shadow: none;\n    transform: none;\n  }\n\n  /* ...nor on :active — stay borderless even though the shared rule above now\n     adds a halo to :active too (physical press transform below still applies,\n     this only cancels border-color/box-shadow). */\n  :host([variant='ghost']) [part='button']:active,\n  :host([variant='text']) [part='button']:active {\n    border-color: transparent;\n    box-shadow: none;\n  }\n\n  /* Physical press feedback */\n  [part='button']:active {\n    transform: translateY(1px);\n  }\n}\n","import { bind, define, getHost, html, inject, prop, useField } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport { commonProps } from '../../shared';\nimport {\n  coarsePointerMixin,\n  colorThemeMixin,\n  disabledLoadingMixin,\n  forcedColorsMixin,\n  frostVariantMixin,\n  rainbowEffectMixin,\n  reducedMotionMixin,\n  roundedVariantMixin,\n  shineEffectMixin,\n  sizeVariantMixin,\n} from '../../styles';\nimport type { ButtonType, ComponentSize, LinkTarget, RoundedSize, ThemeColor } from '../../types';\nimport { useLinkProps } from '../../utils';\nimport { BUTTON_GROUP_CTX } from '../button-group/button-group';\nimport { useFormAction } from '../shared';\nimport componentStyles from './button.css?inline';\n\nexport const BUTTON_VARIANTS = ['solid', 'flat', 'bordered', 'outline', 'ghost', 'text', 'frost'] as const;\n\n/** Visual variant for ore-button — derived from BUTTON_VARIANTS for a single source of truth. */\nexport type ButtonVariant = (typeof BUTTON_VARIANTS)[number];\n\n/** Animated border effect for ore-button. */\nexport type ButtonEffect = 'shine' | 'rainbow';\n\n/** Button component properties */\nexport type OreButtonProps = {\n  /** Theme color */\n  color?: ThemeColor;\n  /** Disable interaction */\n  disabled?: boolean;\n  /** Animated border effect: 'shine' (color-aware neon sweep) or 'rainbow' */\n  effect?: ButtonEffect;\n  /**\n   * Full height button (100% of container) — the inner `[part=\"button\"]` fills its host's\n   * height instead of the size preset's fixed height. Useful when the button itself is the\n   * whole tappable surface of a container it doesn't otherwise control the size of (e.g. a\n   * swipe-revealed row action in `ore-list-item`'s `actions-left`/`actions-right` slots).\n   */\n  fullheight?: boolean;\n  /** Full width button (100% of container) */\n  fullwidth?: boolean;\n  /** When set, renders an `<a>` instead of `<button>` */\n  href?: string;\n  /** Icon-only mode (square aspect ratio, no padding) */\n  iconOnly?: boolean;\n  /** Accessible label for the inner button — required for icon-only buttons */\n  label?: string;\n  /** Show loading state with spinner */\n  loading?: boolean;\n  /** Link rel attribute (requires href) */\n  rel?: string;\n  /** Border radius size */\n  rounded?: RoundedSize;\n  /** Component size */\n  size?: ComponentSize;\n  /** Link target (requires href) */\n  target?: LinkTarget;\n  /** HTML button type attribute */\n  type?: ButtonType;\n  /** Visual style variant */\n  variant?: ButtonVariant;\n};\n\n/**\n * A customizable button component with multiple variants, sizes, and states.\n * Supports icons, loading states, and animated border effects.\n *\n * @element ore-button\n *\n * @attr {string} type - HTML button type: 'button' | 'submit' | 'reset'\n * @attr {boolean} disabled - Disable button interaction\n * @attr {boolean} loading - Show loading state with spinner\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'text' | 'frost'\n * @attr {string} size - Button size: 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {string} effect - Animated border effect: 'shine' | 'rainbow'\n * @attr {boolean} icon-only - Icon-only mode (square aspect ratio, no padding)\n * @attr {boolean} fullwidth - Full width button (100% of container)\n * @attr {boolean} fullheight - Full height button (100% of container)\n *\n * @fires click - Emitted when button is clicked (unless disabled/loading)\n *\n * @slot - Button content (text, icons, etc.)\n * @slot prefix - Content before the button text (e.g., icons)\n * @slot suffix - Content after the button text (e.g., icons, badges)\n *\n * @part button - The inner button or anchor element\n * @part loader - The loading spinner element\n * @part content - The button content wrapper\n *\n * @cssprop --button-bg - Background color override\n * @cssprop --button-color - Text color override\n * @cssprop --button-border - Border width override\n * @cssprop --button-border-color - Border color override\n * @cssprop --button-radius - Border radius override\n * @cssprop --button-padding - Inner padding override\n * @cssprop --button-gap - Gap between icon and text override\n * @cssprop --button-font-size - Font size override\n * @cssprop --button-frost-active-bg - Background when pressed (frost variant)\n * @cssprop --button-frost-active-border-color - Border color when pressed (frost variant)\n *\n * @example\n * ```html\n * <ore-button variant=\"solid\" color=\"primary\">Click me</ore-button>\n * <ore-button loading color=\"success\">Processing...</ore-button>\n * <ore-button effect=\"shine\" color=\"primary\">Shine</ore-button>\n * <ore-button effect=\"rainbow\" variant=\"frost\">Rainbow</ore-button>\n * ```\n */\nexport const BUTTON_TAG = 'ore-button' as const;\ndefine<OreButtonProps>(BUTTON_TAG, {\n  formAssociated: true,\n  props: {\n    ...commonProps,\n    effect: prop.string<ButtonEffect>(),\n    fullheight: prop.bool(false),\n    fullwidth: prop.bool(false),\n    href: prop.string(),\n    iconOnly: prop.bool(false),\n    label: prop.string(),\n    rel: prop.string(),\n    target: prop.string<LinkTarget>(),\n    type: prop.oneOf(['button', 'submit', 'reset'] as const, 'button'),\n    variant: prop.oneOf(BUTTON_VARIANTS, 'solid'),\n  },\n  setup(props) {\n    const el = getHost();\n\n    // Prefer group context over own props for color/size/variant.\n    const groupCtx = inject(BUTTON_GROUP_CTX);\n    const effectiveColor = computed(() => groupCtx?.color.value ?? props.color.value);\n    const effectiveSize = computed(() => groupCtx?.size.value ?? props.size.value);\n    const effectiveVariant = computed(() => groupCtx?.variant.value ?? props.variant.value);\n\n    const isDisabled = computed(() => !!(props.disabled.value || props.loading.value));\n\n    // isLink and effectiveRel are computed from signals — correct even if href changes at runtime.\n    const { effectiveRel, isLink } = useLinkProps(props.href, props.rel, props.target);\n\n    // Form association: relay submit/reset clicks to the associated form.\n    // The inner <button> always has type=\"button\" so shadow DOM never drives native form actions.\n    // getForm() returns null for link mode at runtime, so no form actions fire.\n    const formField = useField({\n      disabled: isDisabled,\n      toFormValue: () => null,\n      value: computed(() => ''),\n    });\n\n    const handleClick = (e: MouseEvent) => {\n      if (isDisabled.value) {\n        e.preventDefault();\n\n        return;\n      }\n\n      // Link mode renders a real <a href> below — the browser handles left/middle/ctrl-click\n      // navigation, target, and rel natively. No manual window.open/location.href needed.\n      useFormAction(() => (isLink.value ? null : formField.internals.form), props.type, isDisabled, el)(e);\n    };\n\n    const handleKeydown = (e: KeyboardEvent) => {\n      if (e.key === 'Enter' || e.key === ' ') {\n        e.preventDefault();\n        (el.shadowRoot?.querySelector('[part=\"button\"]') as HTMLElement)?.click();\n      }\n    };\n\n    // ARIA attributes live on the host.\n    bind({\n      attr: {\n        'aria-busy': props.loading,\n        'aria-disabled': isDisabled,\n        'aria-label': props.label,\n        color: effectiveColor,\n        effect: props.effect,\n        role: computed(() => el.getAttribute('role') ?? (isLink.value ? 'link' : 'button')),\n        size: effectiveSize,\n        tabindex: computed(() => (isDisabled.value ? '-1' : '0')),\n        variant: effectiveVariant,\n      },\n      on: {\n        keydown: handleKeydown,\n      },\n    });\n\n    const buttonContent = html`\n      <span class=\"loader\" part=\"loader\" aria-label=\"Loading\" ?hidden=${() => !props.loading.value}></span>\n      <slot name=\"prefix\"></slot>\n      <span class=\"content\" part=\"content\"><slot></slot></span>\n      <slot name=\"suffix\"></slot>\n    `;\n\n    // The inner element (<a> or <span>) is deliberately non-focusable/decorative — this\n    // component's real interactive semantics (role, tabindex, aria-label) live on the\n    // custom-element host itself (see the `bind()` block above), since ore-button is\n    // formAssociated and needs the host, not an inner element, to carry ElementInternals.\n    // This differs from ore-navbar-item / ore-sidebar-item, which aren't form-associated\n    // and so render their <a> as the one real focusable/semantic element.\n    return html`\n      ${() =>\n        isLink.value\n          ? html`\n              <a\n                part=\"button\"\n                role=\"presentation\"\n                tabindex=\"-1\"\n                href=\"${props.href}\"\n                rel=\"${effectiveRel}\"\n                target=\"${props.target}\"\n                @click=\"${handleClick}\">\n                ${buttonContent}\n              </a>\n            `\n          : html`\n              <span part=\"button\" role=\"presentation\" @click=\"${handleClick}\">${buttonContent}</span>\n            `}\n    `;\n  },\n  shadow: { delegatesFocus: false },\n  styles: [\n    colorThemeMixin,\n    coarsePointerMixin,\n    reducedMotionMixin,\n    roundedVariantMixin,\n    forcedColorsMixin,\n    sizeVariantMixin({\n      lg: {\n        fontSize: 'var(--text-base)',\n        gap: 'var(--size-2-5)',\n        height: 'var(--size-12)',\n        iconSize: 'var(--size-6)',\n        lineHeight: 'var(--leading-relaxed)',\n        padding: 'var(--size-2-5) var(--size-5)',\n      },\n      sm: {\n        fontSize: 'var(--text-sm)',\n        gap: 'var(--size-1-5)',\n        height: 'var(--size-8)',\n        iconSize: 'var(--size-4)',\n        lineHeight: 'var(--leading-tight)',\n        padding: 'var(--size-1-5) var(--size-3)',\n      },\n    }),\n    frostVariantMixin('[part=\"button\"]'),\n    rainbowEffectMixin('[part=\"button\"]'),\n    shineEffectMixin('[part=\"button\"]'),\n    disabledLoadingMixin,\n    componentStyles,\n  ],\n});\n","@layer refine.base {\n  :host {\n    --_bg: var(--color-canvas);\n    --_radius: var(--rounded-xl);\n\n    position: relative;\n    display: block;\n    width: 100%;\n    min-height: 240px;\n    overflow: hidden;\n    background: var(--_bg);\n    border-radius: var(--_radius);\n  }\n\n  .track {\n    position: absolute;\n    inset-block: 0;\n    inset-inline-start: 0;\n    display: flex;\n    flex-direction: row;\n    gap: var(--marquee-gap, var(--size-4));\n    align-items: stretch;\n    width: max-content;\n    animation: marquee-scroll var(--_marquee-duration, 20s) linear infinite;\n    will-change: transform;\n  }\n\n  .controls {\n    display: flex;\n    gap: var(--size-0-5);\n    align-items: center;\n    pointer-events: none;\n  }\n\n  :host > .controls {\n    position: absolute;\n    inset-block-end: var(--size-3);\n    inset-inline-end: var(--size-3);\n    padding: var(--size-1-5) var(--size-2);\n    background: color-mix(in oklch, var(--color-canvas) 55%, transparent);\n    border-radius: var(--rounded-full);\n    backdrop-filter: blur(6px);\n  }\n\n  .nav-btn {\n    pointer-events: auto;\n  }\n\n  :host([direction='right']) .track {\n    animation-direction: reverse;\n  }\n\n  :host([pause-on-hover]:hover) .track {\n    animation-play-state: paused;\n  }\n\n  ::slotted(*) {\n    position: relative;\n    flex: 0 0 auto;\n    height: 100%;\n  }\n\n  ::slotted([data-marquee-clone]) {\n    pointer-events: none;\n    user-select: none;\n  }\n\n  @keyframes marquee-scroll {\n    from {\n      transform: translateX(0);\n    }\n\n    to {\n      transform: translateX(var(--_marquee-translate, -50%));\n    }\n  }\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .track {\n    animation: none;\n  }\n}\n","import { define, getHost, html, onMounted, prop } from '@vielzeug/ore';\nimport { watch } from '@vielzeug/ripple';\n\nimport type { ThemeColor } from '../../types';\n\nimport '../icon/icon';\nimport '../../inputs/button/button';\nimport componentStyles from './marquee.css?inline';\n\nexport type MarqueeDirection = 'left' | 'right';\n\nexport type OreMarqueeProps = {\n  /** Theme color for the navigation controls. */\n  color?: ThemeColor;\n  /** Scroll direction. Defaults to `'left'`. */\n  direction?: MarqueeDirection;\n  /** Duration in seconds for one complete ticker cycle. Defaults to `20`. */\n  duration?: number;\n  /** Pause the ticker while it is hovered. Defaults to `false`. */\n  'pause-on-hover'?: boolean;\n  /** Show previous/next navigation controls. Defaults to `true`. */\n  'show-controls'?: boolean;\n};\n\n/**\n * A CSS-driven, continuously scrolling ticker.\n *\n * Direct child elements are duplicated internally for a seamless loop. Cloned\n * content is inert and hidden from assistive technology, so author interactive\n * content only in the original children.\n *\n * @element ore-marquee\n *\n * @attr {string} color - Theme color for the navigation controls.\n * @attr {number} duration - Duration in seconds for one ticker cycle (default: 20)\n * @attr {string} direction - 'left' (default) | 'right'\n * @attr {boolean} pause-on-hover - Pause while hovered (default: false)\n * @attr {boolean} show-controls - Show previous/next controls (default: true)\n *\n * @cssprop --marquee-gap - Gap between ticker items (default: var(--size-4))\n *\n * @part track - The animated ticker track.\n * @example\n * ```html\n * <ore-marquee duration=\"24\" pause-on-hover>\n *   <span>Free shipping</span>\n *   <span>New arrivals</span>\n * </ore-marquee>\n * ```\n */\nexport const MARQUEE_TAG = 'ore-marquee' as const;\n\ndefine<OreMarqueeProps>(MARQUEE_TAG, {\n  props: {\n    color: prop.string<ThemeColor>(),\n    direction: prop.string<MarqueeDirection>('left'),\n    duration: prop.number(20),\n    'pause-on-hover': prop.bool(false),\n    'show-controls': prop.bool(true),\n  },\n  setup(props) {\n    const el = getHost();\n    let activeIndex = 0;\n    let clones: HTMLElement[] = [];\n    let items: HTMLElement[] = [];\n    let layoutFrame: number | null = null;\n    let loopWidth = 0;\n    let resizeObserver: ResizeObserver | null = null;\n    let track: HTMLElement | null = null;\n\n    const seekTo = (index: number): void => {\n      if (!track || items.length === 0) return;\n\n      activeIndex = (index + items.length) % items.length;\n\n      const item = items[activeIndex];\n\n      if (!item || loopWidth === 0) return;\n\n      const duration = props.duration.value ?? 20;\n      const delay = -((item.offsetLeft / loopWidth) * duration);\n\n      track.style.setProperty('animation-delay', `${delay}s`);\n    };\n\n    watch(\n      props.duration,\n      (duration) => {\n        el.style.setProperty('--_marquee-duration', `${duration ?? 20}s`);\n      },\n      { immediate: true },\n    );\n\n    onMounted(() => {\n      track = el.shadowRoot?.querySelector<HTMLElement>('.track') ?? null;\n\n      const slot = el.shadowRoot?.querySelector<HTMLSlotElement>('slot') ?? null;\n\n      const removeClones = (): void => {\n        clones.forEach((clone) => {\n          clone.remove();\n        });\n        clones = [];\n      };\n\n      const appendCloneSet = (): void => {\n        clones.push(\n          ...items.map((item) => {\n            const clone = item.cloneNode(true) as HTMLElement;\n\n            clone.setAttribute('aria-hidden', 'true');\n            clone.setAttribute('data-marquee-clone', '');\n            clone.setAttribute('inert', '');\n            el.appendChild(clone);\n\n            return clone;\n          }),\n        );\n      };\n\n      const syncLoop = (): void => {\n        if (!track || items.length === 0) return;\n\n        const marqueeTrack = track;\n\n        if (layoutFrame !== null) cancelAnimationFrame(layoutFrame);\n\n        removeClones();\n        loopWidth = 0;\n        marqueeTrack.style.removeProperty('--_marquee-translate');\n        appendCloneSet();\n\n        layoutFrame = requestAnimationFrame(() => {\n          layoutFrame = null;\n\n          const firstClone = clones[0];\n          const firstItem = items[0];\n\n          if (!firstClone || !firstItem) return;\n\n          loopWidth = firstClone.offsetLeft - firstItem.offsetLeft;\n\n          if (loopWidth <= 0) return;\n\n          const requiredSets = Math.max(2, Math.ceil((el.clientWidth + loopWidth) / loopWidth));\n\n          for (let set = 2; set < requiredSets; set += 1) appendCloneSet();\n\n          marqueeTrack.style.setProperty('--_marquee-translate', `-${loopWidth}px`);\n        });\n      };\n\n      const refreshItems = (): void => {\n        const nextItems = (slot?.assignedElements() ?? []).filter(\n          (child): child is HTMLElement => child instanceof HTMLElement && !child.hasAttribute('data-marquee-clone'),\n        );\n        const itemsChanged =\n          nextItems.length !== items.length || nextItems.some((item, index) => item !== items[index]);\n\n        if (!itemsChanged) return;\n\n        items = nextItems;\n        activeIndex = Math.min(activeIndex, Math.max(items.length - 1, 0));\n        syncLoop();\n      };\n\n      resizeObserver = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(syncLoop);\n      resizeObserver?.observe(el);\n      slot?.addEventListener('slotchange', refreshItems);\n      refreshItems();\n\n      return () => {\n        if (layoutFrame !== null) cancelAnimationFrame(layoutFrame);\n\n        resizeObserver?.disconnect();\n        slot?.removeEventListener('slotchange', refreshItems);\n        removeClones();\n        track = null;\n        items = [];\n        loopWidth = 0;\n      };\n    });\n\n    return html`\n      <div class=\"track\" part=\"track\" aria-live=\"off\">\n        <slot></slot>\n      </div>\n      ${() =>\n        props['show-controls'].value !== false\n          ? html`\n              <div class=\"controls\" part=\"controls\">\n                <ore-button\n                  class=\"nav-btn prev-btn\"\n                  part=\"prev-btn\"\n                  variant=\"ghost\"\n                  color=${() => props.color.value}\n                  rounded\n                  icon-only\n                  label=\"Previous item\"\n                  @click=${(event: Event) => {\n                    event.stopPropagation();\n                    seekTo(activeIndex - 1);\n                  }}>\n                  <ore-icon name=\"chevron-left\" size=\"16\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n                </ore-button>\n                <ore-button\n                  class=\"nav-btn next-btn\"\n                  part=\"next-btn\"\n                  variant=\"ghost\"\n                  color=${() => props.color.value}\n                  rounded\n                  icon-only\n                  label=\"Next item\"\n                  @click=${(event: Event) => {\n                    event.stopPropagation();\n                    seekTo(activeIndex + 1);\n                  }}>\n                  <ore-icon name=\"chevron-right\" size=\"16\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n                </ore-button>\n              </div>\n            `\n          : null}\n    `;\n  },\n  styles: [componentStyles],\n});\n","@layer refine.base {\n  :host {\n    display: flex;\n    gap: var(--size-1);\n    align-items: center;\n  }\n\n  .pagination {\n    display: flex;\n    gap: var(--pagination-gap, var(--size-1));\n    align-items: center;\n    padding: 0;\n    margin: 0;\n    list-style: none;\n  }\n\n  li {\n    display: contents;\n  }\n\n  button {\n    all: unset;\n    box-sizing: border-box;\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    min-width: var(--pagination-item-size, var(--size-9));\n    height: var(--pagination-item-size, var(--size-9));\n    min-height: var(--_touch-target);\n    padding: 0 var(--size-2);\n    font-size: var(--_font-size, var(--text-sm));\n    font-weight: var(--font-medium);\n    color: var(--color-contrast-700);\n    cursor: pointer;\n    user-select: none;\n    border: var(--border) solid transparent;\n    border-radius: var(--pagination-radius, var(--rounded-lg));\n    transition:\n      background var(--transition-fast),\n      color var(--transition-fast),\n      border-color var(--transition-fast);\n  }\n\n  /* Default (ghost-like) behavior unless variant is specified */\n  :host(:not([variant])) button,\n  :host([variant='ghost']) button {\n    color: var(--color-contrast-700);\n    background: transparent;\n    border-color: transparent;\n    border-width: 0;\n  }\n\n  :host(:not([variant])) button:hover:not(:disabled, [aria-current='page']),\n  :host([variant='ghost']) button:hover:not(:disabled, [aria-current='page']) {\n    background: var(--_theme-backdrop);\n  }\n\n  :host([variant='solid']) button {\n    color: var(--_theme-contrast);\n    background: var(--_theme-base);\n    border-color: var(--_theme-base);\n  }\n\n  :host([variant='solid']) button:hover:not(:disabled, [aria-current='page']) {\n    background: var(--_theme-focus);\n  }\n\n  :host([variant='flat']) button {\n    color: var(--_theme-base);\n    background: color-mix(in oklch, var(--_theme-backdrop) 8%, var(--color-contrast-100));\n    border-color: color-mix(in oklch, var(--_theme-focus) 20%, transparent);\n    box-shadow: var(--inset-shadow-2xs);\n  }\n\n  :host([variant='flat']) button:hover:not(:disabled, [aria-current='page']) {\n    color: var(--_theme-contrast);\n    background: var(--_theme-focus);\n  }\n\n  :host([variant='bordered']) button {\n    color: var(--_theme-base);\n    background: var(--_theme-backdrop);\n    border-color: var(--_theme-border);\n    box-shadow: var(--inset-shadow-xs);\n  }\n\n  :host([variant='bordered']) button:hover:not(:disabled, [aria-current='page']) {\n    color: var(--_theme-contrast);\n    background: var(--_theme-focus);\n    border-color: var(--_theme-focus);\n  }\n\n  :host([variant='outline']) button {\n    color: var(--_theme-base);\n    background: transparent;\n    border-color: var(--_theme-base);\n  }\n\n  :host([variant='outline']) button:hover:not(:disabled, [aria-current='page']) {\n    background: var(--_theme-backdrop);\n    border-color: var(--_theme-focus);\n  }\n\n  :host([variant='text']) button {\n    color: var(--_theme-base);\n    background: transparent;\n    border-color: transparent;\n    border-width: 0;\n  }\n\n  :host([variant='text']) button:hover:not(:disabled, [aria-current='page']) {\n    color: var(--_theme-focus);\n    background: transparent;\n  }\n\n  :host([variant='frost']) button {\n    color: var(--_theme-content);\n    background: color-mix(in oklch, var(--_theme-backdrop) 45%, transparent);\n    border-color: color-mix(in oklch, var(--_theme-border) 45%, transparent);\n    backdrop-filter: blur(var(--blur-xl)) saturate(200%);\n  }\n\n  :host([variant='frost']) button:hover:not(:disabled, [aria-current='page']) {\n    background: color-mix(in oklch, var(--_theme-backdrop) 65%, transparent);\n    border-color: color-mix(in oklch, var(--_theme-focus) 55%, transparent);\n  }\n\n  :host([variant='glass']) button {\n    color: var(--_theme-content);\n    background: color-mix(in oklch, var(--color-canvas) 70%, transparent);\n    border-color: color-mix(in oklch, var(--_theme-border) 40%, transparent);\n    backdrop-filter: blur(var(--blur-md)) saturate(140%);\n  }\n\n  :host([variant='glass']) button:hover:not(:disabled, [aria-current='page']) {\n    background: color-mix(in oklch, var(--color-canvas) 55%, transparent);\n    border-color: color-mix(in oklch, var(--_theme-border) 45%, transparent);\n  }\n\n  button:hover:not(:disabled, [aria-current='page']) {\n    background: var(--color-contrast-100);\n  }\n\n  button:focus-visible {\n    outline: var(--border-2) solid var(--_theme-base, var(--color-contrast-500));\n    outline-offset: var(--border-2);\n  }\n\n  /* Selected page styling - applies to all variants */\n  button[aria-current='page'] {\n    font-weight: var(--font-bold);\n    color: var(--_theme-contrast, var(--color-canvas));\n    cursor: default;\n    background: var(--_theme-base, var(--color-contrast-800));\n    border-color: var(--_theme-base, var(--color-contrast-800));\n  }\n\n  :host([variant='ghost']) button[aria-current='page'],\n  :host(:not([variant])) button[aria-current='page'] {\n    color: var(--_theme-contrast);\n    background: var(--_theme-focus);\n    border-color: var(--_theme-focus);\n  }\n\n  :host([variant='solid']) button[aria-current='page'] {\n    background: var(--_theme-focus);\n    border-color: var(--_theme-focus);\n  }\n\n  :host([variant='flat']) button[aria-current='page'] {\n    color: var(--_theme-contrast);\n    background: var(--_theme-base);\n    border-color: var(--_theme-base);\n  }\n\n  :host([variant='bordered']) button[aria-current='page'] {\n    color: var(--_theme-contrast);\n    background: var(--_theme-focus);\n    border-color: var(--_theme-focus);\n  }\n\n  :host([variant='outline']) button[aria-current='page'] {\n    color: var(--_theme-contrast);\n    background: var(--_theme-base);\n    border-color: var(--_theme-base);\n  }\n\n  :host([variant='text']) button[aria-current='page'] {\n    color: var(--_theme-focus);\n    text-decoration-line: underline;\n    text-decoration-thickness: 2px;\n    text-underline-offset: 4px;\n  }\n\n  :host([variant='frost']) button[aria-current='page'] {\n    color: var(--_theme-contrast);\n    background: color-mix(in oklch, var(--_theme-base) 70%, transparent);\n    border-color: var(--_theme-base);\n  }\n\n  :host([variant='glass']) button[aria-current='page'] {\n    color: var(--_theme-contrast);\n    background: color-mix(in oklch, var(--color-canvas) 90%, transparent);\n    border-color: var(--_theme-base);\n  }\n\n  button:disabled {\n    cursor: not-allowed;\n    opacity: 0.4;\n  }\n\n  .ellipsis {\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    min-width: var(--pagination-item-size, var(--size-9));\n    height: var(--pagination-item-size, var(--size-9));\n    font-size: var(--_font-size, var(--text-sm));\n    color: var(--color-contrast-400);\n    cursor: default;\n  }\n}\n\n@layer refine.utilities {\n  :host([size='sm']) {\n    --pagination-item-size: var(--size-7);\n    --pagination-gap: var(--size-0_5);\n    --_font-size: var(--text-xs);\n  }\n\n  :host([size='lg']) {\n    --pagination-item-size: var(--size-11);\n    --_font-size: var(--text-base);\n  }\n}\n","import { define, getHost, html, prop, useEmit } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\n\nimport '../icon/icon';\nimport '../../inputs/button/button';\n\nimport { sizableBundle, themableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, sizeVariantMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor, VisualVariant } from '../../types';\nimport componentStyles from './pagination.css?inline';\n\nexport type OrePaginationEvents = {\n  change: { page: number };\n};\n\nexport type OrePaginationProps = {\n  color?: ThemeColor;\n  label?: string;\n  page?: number;\n  'show-first-last'?: boolean;\n  'show-prev-next'?: boolean;\n  siblings?: number;\n  size?: ComponentSize;\n  'total-pages'?: number;\n  variant?: VisualVariant;\n};\n\nfunction buildPageRange(\n  currentPage: number,\n  totalPages: number,\n  siblings: number,\n): Array<number | 'ellipsis-start' | 'ellipsis-end'> {\n  const BOUNDARY = 1; // always show first and last page\n  const total = totalPages;\n  const pages: Array<number | 'ellipsis-start' | 'ellipsis-end'> = [];\n\n  // If total is small enough, show all pages\n  if (total <= 2 * BOUNDARY + 2 * siblings + 3) {\n    return Array.from({ length: total }, (_, i) => i + 1);\n  }\n\n  const leftSibling = Math.max(currentPage - siblings, BOUNDARY + 1);\n  const rightSibling = Math.min(currentPage + siblings, total - BOUNDARY);\n\n  pages.push(1);\n\n  if (leftSibling > BOUNDARY + 2) pages.push('ellipsis-start');\n  else if (leftSibling === BOUNDARY + 2) pages.push(BOUNDARY + 1);\n\n  for (let i = leftSibling; i <= rightSibling; i++) pages.push(i);\n\n  if (rightSibling < total - BOUNDARY - 1) pages.push('ellipsis-end');\n  else if (rightSibling === total - BOUNDARY - 1) pages.push(total - BOUNDARY);\n\n  pages.push(total);\n\n  return pages;\n}\n\n/**\n * Page-based navigation control.\n *\n * @element ore-pagination\n *\n * @attr {number} page - Current page (1-indexed, default: 1)\n * @attr {number} total-pages - Total number of pages (required)\n * @attr {number} siblings - Sibling pages around current (default: 1)\n * @attr {boolean} show-first-last - Show first/last page buttons (default: false)\n * @attr {boolean} show-prev-next - Show prev/next buttons (default: false)\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant for nav buttons: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'text' | 'frost' (default: 'ghost')\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} label - Accessible nav label (default: 'Pagination')\n *\n * @fires change - Emitted when the page changes, with { page: number }\n *\n * @cssprop --pagination-item-size - Width/height of each item\n * @cssprop --pagination-gap - Gap between items\n * @cssprop --pagination-radius - Border radius of items\n *\n * @part page-btn - Page button.\n * @part nav - Navigation container.\n * @part list - List container.\n * @part first-btn - First page button.\n * @part prev-btn - Previous page button.\n * @part next-btn - Next page button.\n * @part last-btn - Last page button.\n * @example\n * ```html\n * <!-- Basic -->\n * <ore-pagination page=\"3\" total-pages=\"10\" color=\"primary\"></ore-pagination>\n *\n * <!-- With prev/next and first/last buttons -->\n * <ore-pagination page=\"5\" total-pages=\"20\" show-prev-next show-first-last siblings=\"2\"></ore-pagination>\n *\n * <!-- Compact size -->\n * <ore-pagination page=\"1\" total-pages=\"5\" size=\"sm\" variant=\"ghost\"></ore-pagination>\n * ```\n */\nexport const PAGINATION_TAG = 'ore-pagination' as const;\ndefine<OrePaginationProps>(PAGINATION_TAG, {\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    label: prop.string('Pagination'),\n    page: prop.number(1),\n    'show-first-last': prop.bool(false),\n    'show-prev-next': prop.bool(false),\n    siblings: prop.number(1),\n    'total-pages': prop.number(1),\n    variant: prop.string<VisualVariant>(),\n  },\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OrePaginationEvents>();\n\n    function goTo(page: number) {\n      const total = props['total-pages'].value || 1;\n      const next = Math.min(Math.max(1, page), total);\n\n      if (next === props.page.value) return;\n\n      el.setAttribute('page', String(next));\n      emit('change', { page: next });\n    }\n\n    const pageItems = computed(() =>\n      buildPageRange(props.page.value || 1, props['total-pages'].value || 1, props.siblings.value ?? 1),\n    );\n\n    const isFirst = computed(() => (props.page.value || 1) <= 1);\n    const isLast = computed(() => (props.page.value || 1) >= (props['total-pages'].value || 1));\n\n    return html`\n      <nav aria-label=\"${props.label}\" part=\"nav\">\n        <ol class=\"pagination\" part=\"list\">\n          ${() =>\n            props['show-first-last'].value\n              ? html`\n                  <li>\n                    <button\n                      type=\"button\"\n                      class=\"nav-btn\"\n                      part=\"first-btn\"\n                      aria-label=\"First page\"\n                      ?disabled=${isFirst}\n                      @click=${() => goTo(1)}>\n                      <ore-icon name=\"chevrons-left\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n                    </button>\n                  </li>\n                `\n              : ''}\n          ${() =>\n            props['show-prev-next'].value\n              ? html`\n                  <li>\n                    <button\n                      type=\"button\"\n                      class=\"nav-btn\"\n                      part=\"prev-btn\"\n                      aria-label=\"Previous page\"\n                      ?disabled=${isFirst}\n                      @click=${() => goTo((props.page.value || 1) - 1)}>\n                      <ore-icon name=\"chevron-left\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n                    </button>\n                  </li>\n                `\n              : ''}\n          <li style=\"display: contents;\">\n            ${() =>\n              pageItems.value.map((item) => {\n                if (item === 'ellipsis-start' || item === 'ellipsis-end') {\n                  return html`\n                    <span class=\"ellipsis\" aria-hidden=\"true\">&hellip;</span>\n                  `;\n                }\n\n                const pg = item as number;\n                const isCurrent = pg === (props.page.value || 1);\n                const pgLabel = `Page ${pg}`;\n\n                return isCurrent\n                  ? html`\n                      <button\n                        type=\"button\"\n                        part=\"page-btn\"\n                        aria-label=\"${pgLabel}\"\n                        aria-current=\"page\"\n                        @click=${() => goTo(pg)}>\n                        ${pg}\n                      </button>\n                    `\n                  : html`\n                      <button type=\"button\" part=\"page-btn\" aria-label=\"${pgLabel}\" @click=${() => goTo(pg)}>\n                        ${pg}\n                      </button>\n                    `;\n              })}\n          </li>\n          ${() =>\n            props['show-prev-next'].value\n              ? html`\n                  <li>\n                    <button\n                      type=\"button\"\n                      class=\"nav-btn\"\n                      part=\"next-btn\"\n                      aria-label=\"Next page\"\n                      ?disabled=${isLast}\n                      @click=${() => goTo((props.page.value || 1) + 1)}>\n                      <ore-icon name=\"chevron-right\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n                    </button>\n                  </li>\n                `\n              : ''}\n          ${() =>\n            props['show-first-last'].value\n              ? html`\n                  <li>\n                    <button\n                      type=\"button\"\n                      class=\"nav-btn\"\n                      part=\"last-btn\"\n                      aria-label=\"Last page\"\n                      ?disabled=${isLast}\n                      @click=${() => goTo(props['total-pages'].value || 1)}>\n                      <ore-icon name=\"chevrons-right\" size=\"16\" aria-hidden=\"true\"></ore-icon>\n                    </button>\n                  </li>\n                `\n              : ''}\n        </ol>\n      </nav>\n    `;\n  },\n\n  styles: [coarsePointerMixin, colorThemeMixin, sizeVariantMixin(), componentStyles],\n});\n","@layer refine.base {\n  :host {\n    --_color: var(--separator-color, var(--color-contrast-300));\n    --_size: var(--separator-size, var(--border));\n    --_spacing: var(--separator-spacing, 0);\n\n    display: block;\n  }\n\n  .separator {\n    all: unset;\n    box-sizing: border-box;\n    display: block;\n    margin: var(--_spacing) 0;\n  }\n\n  :host([orientation='horizontal']),\n  :host(:not([orientation='vertical'])) {\n    width: 100%;\n  }\n\n  :host([orientation='horizontal']) .separator,\n  :host(:not([orientation='vertical'])) .separator {\n    width: 100%;\n    border-top: var(--_size) solid var(--_color);\n  }\n\n  :host([orientation='vertical']) {\n    display: inline-block;\n    align-self: stretch;\n  }\n\n  :host([orientation='vertical']) .separator {\n    height: 100%;\n    border-inline-start: var(--_size) solid var(--_color);\n  }\n\n  :host([color]) {\n    --_color: var(--_theme-base);\n  }\n\n  /* Labelled separator */\n  .separator-wrapper {\n    display: flex;\n    gap: var(--size-3);\n    align-items: center;\n  }\n\n  .separator-wrapper .separator {\n    flex: 1;\n  }\n\n  :host([orientation='vertical']) .separator-wrapper {\n    flex-direction: column;\n    align-self: stretch;\n    height: 100%;\n  }\n\n  :host([orientation='vertical']) .separator-wrapper .separator {\n    flex: 1;\n    width: auto;\n    height: auto;\n    border-inline-start: var(--_size) solid var(--_color);\n    border-top: none;\n  }\n\n  .separator-label {\n    font-size: var(--text-xs);\n    font-weight: var(--font-medium);\n    color: var(--_color);\n    white-space: nowrap;\n  }\n}\n","import { define, html, prop } from '@vielzeug/ore';\nimport { colorThemeMixin } from '../../styles';\nimport type { ThemeColor } from '../../types';\nimport componentStyles from './separator.css?inline';\n\n/** Separator component properties */\nexport type OreSeparatorProps = {\n  /** Theme color tint */\n  color?: ThemeColor;\n  /** Decorative only (default true) — set to false for semantic separators */\n  decorative?: boolean;\n  /** Optional label text centered on the separator */\n  label?: string;\n  /** Orientation of the separator */\n  orientation?: 'horizontal' | 'vertical';\n};\n\n/**\n * A simple visual divider between sections of content.\n *\n * @element ore-separator\n *\n * @attr {string} orientation - 'horizontal' (default) | 'vertical'\n * @attr {boolean} decorative - When true (default), aria-hidden is applied\n * @attr {string} label - Optional centered label text\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n *\n * @cssprop --separator-color - Line color\n * @cssprop --separator-size - Line thickness\n * @cssprop --separator-spacing - Vertical margin\n *\n * @part wrapper - Root wrapper container.\n * @part separator - Separator element.\n * @part label - Label element.\n * @example\n * ```html\n * <ore-separator></ore-separator>\n * <ore-separator label=\"or\"></ore-separator>\n * <ore-separator orientation=\"vertical\"></ore-separator>\n * ```\n */\nexport const SEPARATOR_TAG = 'ore-separator' as const;\ndefine<OreSeparatorProps>(SEPARATOR_TAG, {\n  props: {\n    color: prop.string<ThemeColor>(),\n    decorative: prop.bool(true),\n    label: prop.string(),\n    orientation: prop.oneOf(['horizontal', 'vertical'] as const, 'horizontal'),\n  },\n  setup(props) {\n    const roleAttr = () => (props.decorative.value ? 'none' : 'separator');\n    const ariaHidden = () => (props.decorative.value ? 'true' : null);\n\n    return html`\n      ${() =>\n        props.label.value\n          ? html`\n              <div class=\"separator-wrapper\" part=\"wrapper\">\n                <hr\n                  class=\"separator\"\n                  part=\"separator\"\n                  role=\"${roleAttr}\"\n                  aria-hidden=\"${ariaHidden}\"\n                  aria-orientation=\"${() => props.orientation.value}\" />\n                <span class=\"separator-label\" part=\"label\">${() => props.label.value}</span>\n                <hr\n                  class=\"separator\"\n                  part=\"separator\"\n                  role=\"${roleAttr}\"\n                  aria-hidden=\"${ariaHidden}\"\n                  aria-orientation=\"${() => props.orientation.value}\" />\n              </div>\n            `\n          : html`\n              <hr\n                class=\"separator\"\n                part=\"separator\"\n                role=\"${roleAttr}\"\n                aria-hidden=\"${ariaHidden}\"\n                aria-orientation=\"${() => props.orientation.value}\" />\n            `}\n    `;\n  },\n  styles: [colorThemeMixin, componentStyles],\n});\n","/**\n * Pure navigability rule shared by `ore-stepper` (building its own roving-tabindex\n * candidate list) and `ore-step` (reflecting its own `navigable` attribute for CSS/\n * testing). Kept in one place instead of duplicated inline so the two derivations\n * can't drift out of sync.\n */\nexport function isStepNavigable(options: {\n  disabled: boolean;\n  index: number;\n  linear: boolean;\n  stepperClickable: boolean;\n  stepperCurrentIndex: number;\n}): boolean {\n  if (!options.stepperClickable || options.disabled) return false;\n\n  if (options.linear && options.stepperCurrentIndex >= 0 && options.index > options.stepperCurrentIndex) return false;\n\n  return true;\n}\n","@layer refine.base {\n  :host {\n    --step-indicator-size: var(--size-8);\n    --step-font-size: var(--text-sm);\n    --step-gap: var(--size-2);\n    display: flex;\n    flex: 1 1 0%;\n    min-width: 0;\n  }\n\n  .step {\n    position: relative;\n    box-sizing: border-box;\n    display: flex;\n    align-items: center;\n    width: 100%;\n    list-style: none;\n  }\n\n  /* Horizontal (default) layout centers the indicator above the label in each equal-width\n     column (see `.control`/`.content` below) so the indicator sits at a predictable, constant\n     horizontal position — the midpoint of its own step — regardless of label length. The full\n     line between two indicators is drawn as *two* halves — this step's own `.connector-leading`\n     (its own left edge to its own indicator) and `.connector-trailing` (its own indicator to its\n     own right edge) — each confined entirely inside this step's own box. Reaching a single\n     connector backward into the previous step's box (an earlier attempt) doesn't work: `ore-step`\n     is its own custom element/shadow root, so a later sibling's positioned content always paints\n     in front of an earlier sibling's regardless of internal stacking, and `.control`'s own hover\n     background only covers its own box — so the part of the line sitting outside it looked like\n     a stray line poking out next to the hover highlight instead of being part of it. */\n  .connector {\n    position: absolute;\n    top: calc(var(--size-1) + var(--step-indicator-size) / 2);\n    width: calc(50% - var(--step-indicator-size) / 2);\n    height: var(--stepper-connector-size, 2px);\n    background: var(--stepper-connector-color, var(--color-contrast-200));\n    border-radius: var(--rounded-full);\n    transform: translateY(-50%);\n    transition: background var(--transition-fast);\n  }\n\n  .connector-leading {\n    left: 0;\n  }\n\n  .connector-trailing {\n    right: 0;\n  }\n\n  /* No preceding/following step to connect to. */\n  :host(:first-of-type) .connector-leading {\n    display: none;\n  }\n\n  :host(:last-of-type) .connector-trailing {\n    display: none;\n  }\n\n  .control {\n    all: unset;\n\n    /* Declared after `all: unset` (which resets `position` back to `static`), not before it.\n       Puts `.control` in the same paint order as `.connector` (also positioned) instead of\n       `.connector` — being absolutely positioned — automatically painting above all of this\n       *static*, normal-flow content regardless of DOM order. `.control` comes after\n       `.connector` in the markup, so with both positioned it (and the opaque indicator inside\n       it) now correctly paints over the connector line instead of the line cutting across\n       every indicator. */\n    position: relative;\n    box-sizing: border-box;\n    display: flex;\n    flex: 1 1 auto;\n    flex-direction: column;\n    gap: var(--step-gap);\n    align-items: center;\n    width: 100%;\n    min-width: 0;\n    padding: var(--size-1);\n    font-family: inherit;\n    cursor: default;\n    border-radius: var(--rounded-lg);\n  }\n\n  button.control {\n    min-height: var(--_touch-target, auto);\n    cursor: pointer;\n    transition: background var(--transition-fast);\n  }\n\n  button.control:focus-visible {\n    outline: var(--border-2) solid var(--_theme-base, var(--color-contrast-500));\n    outline-offset: var(--border-2);\n  }\n\n  button.control[aria-disabled='true'] {\n    cursor: not-allowed;\n    opacity: 0.5;\n  }\n\n  .indicator {\n    /* Without this, the `border` below adds on top of `width`/`height` instead of being\n       included in them, rendering the indicator ~2 * border-width larger per axis than\n       `--step-indicator-size` — every connector position calc using that variable to line up\n       with the indicator's true center/edge (especially the vertical connector's horizontal\n       `left`, which has no flexbox centering to fall back on) would then be off by that much. */\n    box-sizing: border-box;\n    display: flex;\n    flex: 0 0 auto;\n    align-items: center;\n    justify-content: center;\n    width: var(--step-indicator-size);\n    height: var(--step-indicator-size);\n    font-size: var(--step-font-size);\n    font-weight: var(--font-semibold);\n    color: var(--color-contrast-500);\n    background: var(--color-contrast-100);\n    border: var(--border-2) solid var(--color-contrast-200);\n    border-radius: var(--rounded-full);\n    transition:\n      background var(--transition-fast),\n      color var(--transition-fast),\n      border-color var(--transition-fast);\n  }\n\n  .icon-slot[hidden] {\n    display: none;\n  }\n\n  .number {\n    line-height: 1;\n  }\n\n  .content {\n    display: flex;\n    flex: 1 1 auto;\n    flex-direction: column;\n    align-items: center;\n    min-width: 0;\n    text-align: center;\n  }\n\n  .label {\n    display: flex;\n    gap: var(--size-1);\n    align-items: baseline;\n    justify-content: center;\n    min-width: 0;\n    font-size: var(--step-font-size);\n    font-weight: var(--font-medium);\n    color: var(--color-contrast-700);\n  }\n\n  .label-text {\n    min-width: 0;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n  }\n\n  .optional-hint {\n    flex: 0 0 auto;\n    font-size: var(--text-xs);\n    font-weight: var(--font-normal);\n    color: var(--color-contrast-400);\n  }\n\n  .description {\n    font-size: var(--text-xs);\n    color: var(--color-contrast-500);\n  }\n\n  .description[hidden] {\n    display: none;\n  }\n\n  .sr-only {\n    position: absolute;\n    width: 1px;\n    height: 1px;\n    padding: 0;\n    margin: -1px;\n    overflow: hidden;\n    white-space: nowrap;\n    border-width: 0;\n    clip-path: inset(50%);\n  }\n}\n\n@layer refine.states {\n  :host([current]) .indicator {\n    color: var(--_theme-contrast, var(--color-canvas));\n    background: var(--_theme-base, var(--color-contrast-800));\n    border-color: var(--_theme-base, var(--color-contrast-800));\n  }\n\n  :host([current]) .label {\n    font-weight: var(--font-semibold);\n    color: var(--color-contrast-900);\n  }\n\n  :host([completed]) .indicator {\n    color: var(--_theme-contrast, var(--color-canvas));\n    background: var(--_theme-focus, var(--color-contrast-600));\n    border-color: var(--_theme-focus, var(--color-contrast-600));\n  }\n\n  /* A completed step colors both the segment leading into it and the one trailing out of it\n     (progress has fully passed through); the current step only colors the leading segment\n     (progress has arrived, but not yet moved past it into the next step). */\n  :host([completed]) .connector,\n  :host([current]) .connector-leading {\n    background: var(--_theme-focus, var(--color-contrast-400));\n  }\n\n  :host([error]) .indicator {\n    color: var(--color-canvas);\n    background: var(--color-error);\n    border-color: var(--color-error);\n  }\n\n  :host([error]) .label {\n    color: var(--color-error);\n  }\n\n  :host([disabled]) .label,\n  :host([disabled]) .description {\n    color: var(--color-contrast-400);\n  }\n\n  :host([disabled]) .indicator {\n    opacity: 0.6;\n  }\n}\n\n@layer refine.sizes {\n  :host([size='sm']) {\n    --step-indicator-size: var(--size-6);\n    --step-font-size: var(--text-xs);\n    --step-gap: var(--size-1-5);\n  }\n\n  :host(:not([size])),\n  :host([size='md']) {\n    --step-indicator-size: var(--size-8);\n    --step-font-size: var(--text-sm);\n    --step-gap: var(--size-2);\n  }\n\n  :host([size='lg']) {\n    --step-indicator-size: var(--size-10);\n    --step-font-size: var(--text-base);\n    --step-gap: var(--size-2-5);\n  }\n\n  @media (pointer: coarse) {\n    :host(:not([size])),\n    :host([size='sm']),\n    :host([size='md']) {\n      --step-indicator-size: var(--size-9);\n      --step-font-size: var(--text-sm);\n    }\n  }\n}\n\n@layer refine.orientation {\n  /* Vertical (mobile-friendly) layout: back to the inline icon-beside-label arrangement (more\n     compact for narrow/mobile widths), with `padding-block-start` reserving room for a\n     top-to-bottom connector into this step's own indicator instead of the horizontal\n     center-to-center line above. */\n  :host([orientation='vertical']) {\n    flex: 0 0 auto;\n    width: 100%;\n  }\n\n  :host([orientation='vertical']) .step {\n    align-items: flex-start;\n    padding-block-start: var(--stepper-gap, var(--size-4));\n  }\n\n  :host([orientation='vertical']:first-of-type) .step {\n    padding-block-start: 0;\n  }\n\n  :host([orientation='vertical']) .control {\n    flex-direction: row;\n    align-items: flex-start;\n  }\n\n  :host([orientation='vertical']) .content {\n    align-items: flex-start;\n    text-align: left;\n  }\n\n  :host([orientation='vertical']) .label {\n    justify-content: flex-start;\n  }\n\n  /* Same two-halves idea as horizontal, rotated: `.connector-leading` runs from this step's own\n     top edge down into its indicator (through the `padding-block-start` gap reserved above).\n     `.connector-trailing` runs from the *bottom* of this step's indicator down to this step's\n     own bottom edge — using `top`+`bottom` (no fixed `height`) so it stretches to whatever this\n     step's content actually needs, instead of a fixed length that only reached as far as the\n     padding gap. A step with a longer description is taller, and its trailing segment grows\n     with it — the next step's leading segment then only has to bridge the fixed padding gap,\n     so the two halves always meet exactly at the boundary between the two steps regardless of\n     how much content either one has. */\n  :host([orientation='vertical']) .connector-leading {\n    top: 0;\n    left: calc(var(--size-1) + var(--step-indicator-size) / 2);\n    width: var(--stepper-connector-size, 2px);\n    height: calc(var(--stepper-gap, var(--size-4)) + var(--size-1));\n    transform: translateX(-50%);\n  }\n\n  :host([orientation='vertical']) .connector-trailing {\n    inset: calc(var(--stepper-gap, var(--size-4)) + var(--size-1) + var(--step-indicator-size)) auto 0\n      calc(var(--size-1) + var(--step-indicator-size) / 2);\n    width: var(--stepper-connector-size, 2px);\n    height: auto;\n    transform: translateX(-50%);\n  }\n\n  /* The first step's `padding-block-start` is reset to 0 above (no incoming line to make room\n     for) — `.connector-trailing`'s `top` has to drop the same gap term here, or it starts\n     lower than the indicator's true bottom edge and its `bottom: 0` counterpart can compute a\n     negative (clamped to 0) height, hiding the segment entirely. */\n  :host([orientation='vertical']:first-of-type) .connector-trailing {\n    top: calc(var(--size-1) + var(--step-indicator-size));\n  }\n}\n\n@media (forced-colors: active) {\n  .indicator {\n    border: 1px solid ButtonText;\n  }\n\n  :host([current]) .indicator,\n  :host([completed]) .indicator {\n    border: 1px solid Highlight;\n  }\n}\n","@layer refine.base {\n  :host {\n    display: block;\n    width: 100%;\n  }\n\n  nav {\n    display: block;\n    width: 100%;\n  }\n\n  .steps {\n    /* Spacing between steps comes from each ore-step's own `padding-inline-start` /\n       `padding-block-start` (see step.css), not a flex `gap` here — that lets each step's\n       connector line be drawn from its own edge to its own indicator using the exact same\n       length it was given room for, with no separate gap value to keep in sync by hand. */\n    display: flex;\n    gap: 0;\n    align-items: flex-start;\n    width: 100%;\n    padding: 0;\n    margin: 0;\n    list-style: none;\n  }\n\n  .stepper-message {\n    display: block;\n    margin-top: var(--size-3);\n  }\n}\n\n@layer refine.orientation {\n  :host([orientation='vertical']) .steps {\n    flex-direction: column;\n    align-items: stretch;\n  }\n}\n","import {\n  bind,\n  createContext,\n  define,\n  getHost,\n  html,\n  onCleanup,\n  onMounted,\n  prop,\n  provide,\n  useEmit,\n  useSlots,\n} from '@vielzeug/ore';\nimport { computed, type Readable, signal, watch } from '@vielzeug/ripple';\nimport { createInteraction, createListControl, elementDirection, lifecycleSignal } from '../../core';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport { isStepNavigable } from './_is-step-navigable';\nimport componentStyles from './stepper.css?inline';\n\n// ── Context ─────────────────────────────────────────────────────────────────\n//\n// ore-step derives all of its parent-relative state (current/completed/navigable/\n// index/total/color/size/orientation) from this context instead of ore-stepper\n// pushing 8 attributes onto every child on every change. Matches the\n// provide()/inject() coordination already used by ore-tabs/ore-tab-item,\n// ore-radio-group/ore-radio, and ore-list/ore-list-item — ore-stepper was\n// previously the one outlier doing manual `querySelectorAll` + `setAttribute`\n// fan-out, which meant every reactive change re-walked and re-wrote every step\n// regardless of whether that step's own state actually changed.\n\n/** Context provided by ore-stepper to its ore-step children. */\nexport type StepperContext = {\n  clickable: Readable<boolean>;\n  color: Readable<ThemeColor | undefined>;\n  currentValue: Readable<string | undefined>;\n  linear: Readable<boolean>;\n  orientation: Readable<'horizontal' | 'vertical'>;\n  size: Readable<ComponentSize | undefined>;\n  /** Ordered `value`s of every sibling `ore-step`, used to derive index/total/completed. */\n  stepValues: Readable<string[]>;\n};\n/** Injection key for the stepper context. */\nexport const STEPPER_CTX = createContext<StepperContext>('StepperContext');\n\nexport type OreStepperEvents = {\n  change: { value: string };\n};\n\nexport type OreStepperProps = {\n  /** When true, steps are clickable/keyboard-focusable for navigation. Default: display-only progress. */\n  clickable?: boolean;\n  /** Theme color for the current/completed step indicators */\n  color?: ThemeColor;\n  /** Disables the whole stepper — no step is navigable regardless of `clickable` */\n  disabled?: boolean;\n  /** Accessible label for the nav landmark */\n  label?: string;\n  /**\n   * Restricts navigation to completed steps and the current step — steps ahead of the\n   * current one cannot be clicked or focused, even when `clickable` is set.\n   */\n  linear?: boolean;\n  /** Layout orientation — 'horizontal' (default, desktop) or 'vertical' (compact/mobile-friendly) */\n  orientation?: 'horizontal' | 'vertical';\n  /** Component size */\n  size?: ComponentSize;\n  /** The `value` of the currently active `ore-step` */\n  value?: string;\n};\n\n/**\n * Displays progress through a sequence of numbered steps. Manages step selection and provides\n * shared state (current value, clickability, theming) to its `ore-step` children via context.\n * Can be purely informational (progress display) or interactive navigation.\n *\n * @element ore-stepper\n * @element ore-step - Child element for each step (auto-discovered)\n *\n * @attr {string} value - The value of the currently active step\n * @attr {boolean} clickable - Allow clicking/focusing steps to navigate\n * @attr {boolean} linear - Restrict navigation to completed + current steps only\n * @attr {boolean} disabled - Disables the whole stepper\n * @attr {string} orientation - 'horizontal' (default) | 'vertical'\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n * @attr {string} label - Accessible nav landmark label (default: 'Progress')\n *\n * @fires change - Emitted when the active step changes via click/keyboard. detail: { value: string }\n *\n * @slot - `ore-step` elements\n *\n * @cssprop --stepper-connector-color - Color of the connector line between steps\n * @cssprop --stepper-connector-size - Thickness of the connector line\n * @cssprop --stepper-gap - Gap between steps\n *\n * @part nav - Navigation landmark element\n * @part list - Ordered list container holding the slotted steps\n *\n * @example\n * ```html\n * <!-- Display-only progress -->\n * <ore-stepper value=\"shipping\" color=\"primary\">\n *   <ore-step value=\"cart\">Cart</ore-step>\n *   <ore-step value=\"shipping\">Shipping</ore-step>\n *   <ore-step value=\"payment\">Payment</ore-step>\n * </ore-stepper>\n *\n * <!-- Clickable navigation, mobile-friendly vertical layout -->\n * <ore-stepper value=\"shipping\" clickable linear orientation=\"vertical\">\n *   <ore-step value=\"cart\">Cart</ore-step>\n *   <ore-step value=\"shipping\">Shipping</ore-step>\n *   <ore-step value=\"payment\" disabled>Payment</ore-step>\n * </ore-stepper>\n * ```\n */\nexport const STEPPER_TAG = 'ore-stepper' as const;\ndefine<OreStepperProps>(STEPPER_TAG, {\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...disablableBundle,\n    clickable: prop.bool(false),\n    label: prop.string('Progress'),\n    linear: prop.bool(false),\n    orientation: prop.oneOf(['horizontal', 'vertical'] as const, 'horizontal'),\n    value: prop.string(),\n  },\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreStepperEvents>();\n    const slots = useSlots();\n\n    const getSteps = (): HTMLElement[] => Array.from(el.querySelectorAll(':scope > ore-step')) as HTMLElement[];\n\n    const focusStep = (step: HTMLElement | undefined) => {\n      step?.shadowRoot?.querySelector<HTMLElement>('button.control')?.focus();\n    };\n\n    // ────────────────────────────────────────────────────────────────\n    // Selection State — mirrors ore-tabs' `selectedValue` signal + `ensureSelection()` pattern\n    // ────────────────────────────────────────────────────────────────\n\n    const currentValue = signal<string | undefined>(props.value.value);\n\n    bind({ attr: { value: () => currentValue.value ?? null } });\n\n    const setSelection = (value: string | undefined, shouldEmit = false) => {\n      if (!value || value === currentValue.value) return;\n\n      currentValue.value = value;\n\n      if (shouldEmit) emit('change', { value });\n    };\n\n    const ensureSelection = () => {\n      const steps = getSteps();\n\n      if (steps.length === 0) return;\n\n      const current = currentValue.value;\n      const hasCurrent = current ? steps.some((s) => s.getAttribute('value') === current) : false;\n\n      if (hasCurrent) return;\n\n      const firstEnabled = steps.find((s) => !s.hasAttribute('disabled'))?.getAttribute('value') ?? undefined;\n\n      if (firstEnabled) setSelection(firstEnabled);\n    };\n\n    watch(props.value, (value) => {\n      currentValue.value = value;\n      ensureSelection();\n    });\n\n    // ────────────────────────────────────────────────────────────────\n    // Context provided to ore-step children\n    // ────────────────────────────────────────────────────────────────\n\n    const stepValues = computed(() => {\n      void slots.elements().value;\n\n      return getSteps().map((s) => s.getAttribute('value') ?? '');\n    });\n\n    provide(STEPPER_CTX, {\n      clickable: computed(() => Boolean(props.clickable.value) && !props.disabled.value),\n      color: props.color,\n      currentValue,\n      linear: computed(() => Boolean(props.linear.value)),\n      orientation: computed(() => props.orientation.value ?? 'horizontal'),\n      size: props.size,\n      stepValues,\n    });\n\n    // Deferred to `onMounted()` (mirrors ore-tabs' `ensureSelection()` timing) rather than an\n    // immediate `watch(stepValues, ...)` — `getSteps()` walks the *live* light DOM, and while the\n    // browser is still parsing this element's `ore-step` children (synchronously upgrading each\n    // one as its own tag is reached, which happens whenever `customElements.define()` already\n    // ran before this markup was parsed — exactly what a sandboxed live-preview iframe does by\n    // design), `stepValues` observes that child list mid-populate. Reading it eagerly here used\n    // to call `ensureSelection()` — and therefore write `currentValue` — once per step as each\n    // one was discovered, interleaved with that *same* step's own first render effect further\n    // down the reactive graph. That reentrant write during a child's not-yet-finished initial\n    // render corrupted its rendered output (the step's clickable/static control silently failed\n    // to mount at all). Onmounted's callback runs on a microtask, strictly after the whole\n    // synchronous parse (and thus every child) has completed, so `getSteps()` sees the final list.\n    onMounted(() => {\n      ensureSelection();\n      return undefined;\n    });\n\n    // ────────────────────────────────────────────────────────────────\n    // Keyboard Navigation (roving tabindex over navigable steps)\n    // ────────────────────────────────────────────────────────────────\n\n    const getNavigableSteps = (): HTMLElement[] => {\n      const steps = getSteps();\n      const values = steps.map((s) => s.getAttribute('value') ?? '');\n      const currentIndex = values.indexOf(currentValue.value ?? '');\n      const clickable = Boolean(props.clickable.value) && !props.disabled.value;\n      const linear = Boolean(props.linear.value);\n\n      return steps.filter((step, index) =>\n        isStepNavigable({\n          disabled: step.hasAttribute('disabled'),\n          index,\n          linear,\n          stepperClickable: clickable,\n          stepperCurrentIndex: currentIndex,\n        }),\n      );\n    };\n\n    const listControl = createListControl({\n      direction: () => elementDirection(el),\n      getItems: getNavigableSteps,\n      loop: false,\n      onNavigate: ({ item }) => {\n        // Select BEFORE focusing: changing `currentValue` re-renders each step's\n        // control (the step's navigable/button node-slot depends on the current\n        // index), which destroys the previously focused button. Ripple flushes\n        // effects synchronously, so by the time focusStep() runs the replacement\n        // button exists.\n        const value = item.getAttribute('value');\n\n        if (value) setSelection(value, true);\n\n        focusStep(item);\n      },\n      orientation: () => (props.orientation.value === 'vertical' ? 'vertical' : 'horizontal'),\n      signal: lifecycleSignal(onCleanup),\n    });\n\n    const handleStepClick = (e: Event) => {\n      const step = e\n        .composedPath()\n        .find((node): node is HTMLElement => node instanceof HTMLElement && node.localName === 'ore-step');\n\n      if (!step || step.closest(STEPPER_TAG) !== el || !getNavigableSteps().includes(step)) return;\n\n      const value = step.getAttribute('value');\n\n      setSelection(value ?? undefined, true);\n      // The click focused the step's old control; the selection re-render replaced\n      // it — restore focus onto the new one (see onNavigate's ordering note).\n      focusStep(step);\n    };\n\n    const activateFocusedStep = (): void => {\n      const steps = getNavigableSteps();\n      const focusedStep = steps.find(\n        (step) => step === document.activeElement || step.shadowRoot?.activeElement === document.activeElement,\n      );\n      const value = focusedStep?.getAttribute('value');\n\n      if (value) {\n        setSelection(value, true);\n        focusStep(focusedStep);\n      }\n    };\n\n    const activationPress = createInteraction({ onPress: activateFocusedStep });\n\n    const handleKeydown = (e: KeyboardEvent) => {\n      const steps = getNavigableSteps();\n\n      if (steps.length === 0) return;\n\n      const path = e.composedPath();\n      const stepFromEvent = path.find(\n        (node): node is HTMLElement => node instanceof HTMLElement && node.localName === 'ore-step',\n      );\n      const focused = stepFromEvent ? steps.indexOf(stepFromEvent) : -1;\n\n      if (focused >= 0) listControl.set(focused);\n\n      if (listControl.handleKeydown(e)) return;\n\n      activationPress.handleKeydown(e);\n    };\n\n    bind({\n      on: {\n        click: handleStepClick,\n        keydown: handleKeydown,\n      },\n    });\n\n    return html`\n      <nav part=\"nav\" aria-label=\"${props.label}\">\n        <ol class=\"steps\" role=\"list\" part=\"list\">\n          <slot></slot>\n        </ol>\n      </nav>\n    `;\n  },\n  styles: [componentStyles],\n});\n","import { bind, define, getHost, html, inject, prop, useSlots, watchEffect } from '@vielzeug/ore';\n\nimport type { ComponentSize, ThemeColor } from '../../types';\n\nimport '../icon/icon';\nimport { disablableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, forcedColorsFocusMixin } from '../../styles';\nimport { isStepNavigable } from './_is-step-navigable';\nimport stepStyles from './step.css?inline';\nimport { STEPPER_CTX } from './stepper';\n\nexport type OreStepProps = {\n  /**\n   * Theme color. Inherited from the parent `ore-stepper` when nested inside one (overrides\n   * this value); only takes effect on its own when `ore-step` is rendered standalone.\n   */\n  color?: ThemeColor;\n  /** Disables this step — it cannot be navigated to and is skipped by keyboard navigation. */\n  disabled?: boolean;\n  /** Marks this step as failed/invalid. Overrides the completed/current indicator visuals. */\n  error?: boolean;\n  /**\n   * Marks this step as optional. Renders a small \"(optional)\" hint next to the label.\n   * Purely presentational — has no effect on navigation.\n   */\n  optional?: boolean;\n  /** Orientation. Inherited from the parent `ore-stepper` when nested inside one. */\n  orientation?: 'horizontal' | 'vertical';\n  /** Component size. Inherited from the parent `ore-stepper` when nested inside one. */\n  size?: ComponentSize;\n  /** Unique identifier, matches `ore-stepper`'s `value` attribute. */\n  value: string;\n};\n\n/**\n * A single step trigger. Must be placed as a direct child of `ore-stepper`, which provides\n * this step's current/completed/navigable/index/total state via context — those are derived,\n * read-only attributes on this element, not settable props.\n *\n * @element ore-step\n *\n * @attr {string} value - Unique identifier, matches the parent ore-stepper's `value` attribute\n * @attr {boolean} disabled - Prevents navigation to this step\n * @attr {boolean} error - Marks the step as failed/invalid\n * @attr {boolean} optional - Renders an \"(optional)\" hint next to the label\n * @attr {boolean} current - Read-only. Derived from position relative to the parent ore-stepper's `value`.\n * @attr {boolean} completed - Read-only. Derived from position relative to the parent ore-stepper's `value`.\n * @attr {boolean} navigable - Read-only. Derived from the parent ore-stepper's `clickable`/`linear`/`disabled`.\n * @attr {number} index - Read-only. This step's 1-based position among its siblings.\n * @attr {number} total - Read-only. Total sibling step count.\n * @attr {string} color - Inherited from ore-stepper: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Inherited from ore-stepper: 'sm' | 'md' | 'lg'\n * @attr {string} orientation - Inherited from ore-stepper: 'horizontal' | 'vertical'\n *\n * @slot - Step label\n * @slot description - Optional supporting text shown below the label\n * @slot icon - Custom icon replacing the step number/check/error indicator\n *\n * @part control - Clickable (or static) root element for the step\n * @part indicator - Circular indicator holding the number/icon\n * @part content - Wrapper around the label and description\n * @part label - Step label element\n * @part description - Step description element\n * @part connector - Connector line segments (leading and trailing halves) either side of this step's indicator\n *\n * @example\n * ```html\n * <ore-step value=\"details\">Account details</ore-step>\n * <ore-step value=\"review\" disabled>Review</ore-step>\n * ```\n */\nexport const STEP_TAG = 'ore-step' as const;\ndefine<OreStepProps>(STEP_TAG, {\n  props: {\n    ...disablableBundle,\n    color: prop.string<ThemeColor>(),\n    error: prop.bool(false),\n    optional: prop.bool(false),\n    orientation: prop.oneOf(['horizontal', 'vertical'] as const, 'horizontal'),\n    size: prop.string<ComponentSize>(),\n    value: prop.string(''),\n  },\n  setup(props) {\n    const el = getHost();\n    const slots = useSlots();\n    const stepperCtx = inject(STEPPER_CTX);\n\n    // ────────────────────────────────────────────────────────────────\n    // State derived from the parent ore-stepper's context — see stepper.ts's\n    // module doc comment for why this replaced parent-side attribute fan-out.\n    // ────────────────────────────────────────────────────────────────\n\n    // Plain functions, not `computed()` — every one of these ultimately reads\n    // `stepperCtx.stepValues`/`stepperCtx.currentValue`, which are themselves `computed()`s\n    // owned by the parent `ore-stepper`. Wrapping a *child* `computed()` around a *parent*\n    // `computed()` (a computed-to-computed dependency crossing a `provide()`/`inject()`\n    // boundary) is exactly the shape that surfaced two related bugs: a step's `completed`/\n    // `current` attributes going permanently stale after a few rapid selections, and — worse —\n    // a step's entire clickable/static control silently failing to render at all when its\n    // `ore-step` tag upgrades before its siblings exist in the light DOM yet (true whenever\n    // `ore-step`/`ore-stepper` are already `customElements.define()`d before this markup is\n    // parsed, e.g. every sandboxed live-preview iframe). Reading straight through to the\n    // parent's computeds on every call — no intermediate computed layer of our own to go\n    // stale — made both disappear. Cheap enough to not need memoizing (a couple of `indexOf`/\n    // comparisons over an already-memoized parent computed).\n    const stepIndex = (): number => (stepperCtx ? stepperCtx.stepValues.value.indexOf(props.value.value) : -1);\n    const totalSteps = (): number => stepperCtx?.stepValues.value.length ?? 0;\n    const currentIndex = (): number =>\n      stepperCtx ? stepperCtx.stepValues.value.indexOf(stepperCtx.currentValue.value ?? '') : -1;\n    // 1-based, always-sane values for on-screen text (the step number badge, the sr-only\n    // \"Step X of Y\" label) — falls back to \"1 of 1\" when rendered standalone with no parent\n    // `ore-stepper` to derive a real position from. Kept separate from the `index`/`total`\n    // *attributes* below, which correctly reflect nothing at all in that same standalone case.\n    const displayIndex = (): number => {\n      const index = stepIndex();\n\n      return index >= 0 ? index + 1 : 1;\n    };\n    const displayTotal = (): number => totalSteps() || 1;\n\n    const isCurrent = (): boolean => {\n      const index = stepIndex();\n      const current = currentIndex();\n\n      return index >= 0 && index === current;\n    };\n    // Purely positional — intentionally NOT gated on `props.error.value`. This also drives the\n    // `completed` *attribute* below, which `step.css` uses to color both connector segments\n    // either side of the indicator (`:host([completed]) .connector`); every *consumer* of this\n    // (the icon choice, the sr-only state label) already checks `error` first and short-circuits\n    // before it matters, so folding `!error` in here too would only end up suppressing\n    // `[completed]` on an error step that's before the current one — breaking the connector\n    // color chain right at that step instead of just swapping its icon.\n    const isCompleted = (): boolean => {\n      const index = stepIndex();\n      const current = currentIndex();\n\n      return index >= 0 && current >= 0 && index < current;\n    };\n    const isNavigable = (): boolean => {\n      const index = stepIndex();\n      const current = currentIndex();\n\n      return (\n        !!stepperCtx &&\n        isStepNavigable({\n          disabled: props.disabled.value === true,\n          index,\n          linear: stepperCtx.linear.value,\n          stepperClickable: stepperCtx.clickable.value,\n          stepperCurrentIndex: current,\n        })\n      );\n    };\n    const isDisabled = () => Boolean(props.disabled.value);\n\n    // Purely derived, read-only state — no matching `prop.*` declaration, so `bind()` is the\n    // sole writer and can safely reflect `undefined` (removes the attribute) when this step\n    // isn't nested inside an `ore-stepper` at all.\n    bind({\n      attr: {\n        completed: () => (isCompleted() ? true : undefined),\n        current: () => (isCurrent() ? true : undefined),\n        index: () => {\n          const index = stepIndex();\n\n          return index >= 0 ? String(index + 1) : undefined;\n        },\n        navigable: () => (isNavigable() ? true : undefined),\n        total: () => (stepperCtx ? String(totalSteps()) : undefined),\n      },\n    });\n\n    // `color`/`size`/`orientation` double as regular, independently-settable props (for a step\n    // rendered standalone) *and* stepper-inherited values — mirrors ore-tab-item's handling of\n    // its own `color`/`size`/`variant` inheritance from `ore-tabs`. Only forcibly overwrite the\n    // attribute when a parent context actually exists, so the plain prop reflection is left\n    // alone otherwise.\n    if (stepperCtx) {\n      watchEffect(() => {\n        const color = stepperCtx.color.value;\n        const size = stepperCtx.size.value;\n        const orientation = stepperCtx.orientation.value;\n\n        if (color !== undefined) el.setAttribute('color', color);\n\n        if (size !== undefined) el.setAttribute('size', size);\n\n        el.setAttribute('orientation', orientation);\n      });\n    }\n\n    const stateLabel = (): string | undefined => {\n      if (props.error.value) return 'error';\n\n      if (isCompleted()) return 'completed';\n\n      if (isCurrent()) return 'current step';\n\n      return undefined;\n    };\n\n    const positionLabel = () => `Step ${displayIndex()} of ${displayTotal()}`;\n    const srLabel = () => {\n      const state = stateLabel();\n\n      return state ? `${positionLabel()}, ${state}` : positionLabel();\n    };\n\n    const handleClick = (event: MouseEvent) => {\n      event.stopPropagation();\n\n      if (!isNavigable()) {\n        event.preventDefault();\n\n        return;\n      }\n\n      el.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: { value: props.value.value } }));\n    };\n\n    const indicatorTemplate = () => html`\n      <span class=\"indicator\" part=\"indicator\" aria-hidden=\"true\">\n        <span class=\"icon-slot\" ?hidden=\"${() => !slots.has('icon').value}\"><slot name=\"icon\"></slot></span>\n        ${() =>\n          slots.has('icon').value\n            ? ''\n            : props.error.value\n              ? html`\n                  <ore-icon name=\"x\" size=\"14\" stroke-width=\"3\"></ore-icon>\n                `\n              : isCompleted()\n                ? html`\n                    <ore-icon name=\"check\" size=\"14\" stroke-width=\"3\"></ore-icon>\n                  `\n                : html`\n                    <span class=\"number\">${displayIndex}</span>\n                  `}\n      </span>\n    `;\n\n    const contentTemplate = () => html`\n      <span class=\"content\" part=\"content\">\n        <span class=\"sr-only\">${srLabel}</span>\n        <span class=\"label\" part=\"label\">\n          <span class=\"label-text\"><slot></slot></span>\n          ${() =>\n            props.optional.value\n              ? html`\n                  <span class=\"optional-hint\">(optional)</span>\n                `\n              : ''}\n        </span>\n        <span class=\"description\" part=\"description\" ?hidden=\"${() => !slots.has('description').value}\">\n          <slot name=\"description\"></slot>\n        </span>\n      </span>\n    `;\n\n    return html`\n      <li class=\"step\" role=\"listitem\">\n        <span class=\"connector connector-leading\" part=\"connector\" aria-hidden=\"true\"></span>\n        <span class=\"connector connector-trailing\" part=\"connector\" aria-hidden=\"true\"></span>\n        ${() =>\n          isNavigable()\n            ? html`\n                <button\n                  type=\"button\"\n                  class=\"control\"\n                  part=\"control\"\n                  aria-current=\"${() => (isCurrent() ? 'step' : null)}\"\n                  aria-disabled=\"${isDisabled}\"\n                  tabindex=\"${() => (isCurrent() ? '0' : '-1')}\"\n                  @click=\"${handleClick}\">\n                  ${indicatorTemplate()}${contentTemplate()}\n                </button>\n              `\n            : html`\n                <div class=\"control\" part=\"control\" aria-current=\"${() => (isCurrent() ? 'step' : null)}\">\n                  ${indicatorTemplate()}${contentTemplate()}\n                </div>\n              `}\n      </li>\n    `;\n  },\n  styles: [colorThemeMixin, coarsePointerMixin, forcedColorsFocusMixin('button.control'), stepStyles],\n});\n","/* ore-table — shadow DOM (proxy/mirror).\n *\n * Shadow tree (managed by table.ts):\n *   :host                  display:block   — token host (tableBaseMixin)\n *   └─ .scroll-container   overflow:auto   — sticky / max-height context\n *       └─ table           display:table   — native table semantics\n *           ├─ caption                     — optional caption bar\n *           ├─ thead                       — rows built from ore-tr[head]\n *           ├─ tbody                       — rows built from plain ore-tr\n *           └─ tfoot                       — rows built from ore-tr[foot]\n *               └─ tr > th / td            — mirrored from ore-th / ore-td\n *\n * Light DOM (consumer):\n *   <ore-tr head><ore-th>…</ore-th></ore-tr>\n *   <ore-tr><ore-td>…</ore-td></ore-tr>\n *   <ore-tr foot><ore-td>…</ore-td></ore-tr>\n *\n * tableBaseMixin('table') handles: :host tokens, .scroll-container,\n * table width/collapse, loading state, size variants, fullwidth, bordered,\n * and sticky scroll-container activation.\n * This file handles: caption, section backgrounds, body tr/th/td, and variants.\n * No ::slotted() needed — the shadow tree owns all rendered th/td elements.\n */\n\n@layer refine.base {\n  :host {\n    border: none;\n    border-radius: 0;\n    box-shadow: var(--table-shadow, none);\n  }\n\n  /* ── Caption ─────────────────────────────────────────────────────────── */\n\n  caption {\n    padding: var(--size-3);\n    font-size: var(--text-xs);\n    font-weight: var(--font-semibold);\n    color: var(--color-contrast-500);\n    text-align: start;\n    text-transform: uppercase;\n    letter-spacing: 0.05em;\n    caption-side: top;\n    background: var(--_header-bg);\n  }\n\n  /* ── Section backgrounds ─────────────────────────────────────────────── */\n\n  thead,\n  tfoot {\n    background: var(--_header-bg);\n  }\n\n  thead {\n    border-block-end: var(--border) solid var(--_border-color);\n  }\n\n  tfoot {\n    border-block-start: var(--border) solid var(--_border-color);\n  }\n\n  /* ── Body rows ───────────────────────────────────────────────────────── */\n\n  tbody tr {\n    border-block-end: var(--border) solid var(--_border-color);\n    transition: background var(--transition-fast);\n  }\n\n  tbody tr:hover {\n    background: var(--_row-hover-bg);\n  }\n\n  /* ── Cells ───────────────────────────────────────────────────────────── */\n\n  th,\n  td {\n    padding: var(--_cell-padding-y) var(--_cell-padding-x);\n    font-size: var(--_font-size);\n    font-weight: normal;\n    vertical-align: middle;\n    color: var(--color-contrast-800);\n    text-align: start;\n  }\n\n  /* ── Header cells ────────────────────────────────────────────────────── */\n\n  thead th,\n  thead td,\n  tfoot th,\n  tfoot td {\n    font-size: var(--text-xs);\n    font-weight: var(--font-semibold);\n    color: var(--color-contrast-500);\n    text-transform: uppercase;\n    letter-spacing: 0.04em;\n    white-space: nowrap;\n    user-select: none;\n  }\n}\n\n@layer refine.variants {\n  /* ── Bordered: vertical cell separators ─────────────────────────────── */\n\n  :host([bordered]) th,\n  :host([bordered]) td {\n    border-inline-end: var(--border) solid var(--_border-color);\n  }\n\n  :host([bordered]) th:last-child,\n  :host([bordered]) td:last-child {\n    border-inline-end: none;\n  }\n\n  /* ── Striped ─────────────────────────────────────────────────────────── */\n\n  :host([striped]) tbody tr:nth-child(even) {\n    background: var(--_stripe-bg);\n  }\n\n  /* ── Sticky header ───────────────────────────────────────────────────── */\n\n  /* tableBaseMixin activates overflow-y:auto on .scroll-container when\n     [sticky] is present. position:sticky on thead is relative to that context. */\n\n  :host([sticky]) thead {\n    position: sticky;\n    top: 0;\n    z-index: 2;\n    background: var(--table-sticky-header-bg, color-mix(in oklch, var(--_header-bg) 94%, transparent));\n\n    /* border-collapse merges the bottom border into the cell below, which\n       scrolls away under the sticky header. Use box-shadow instead — it\n       travels with the element regardless of border-collapse. */\n    box-shadow: inset 0 calc(var(--border) * -1) 0 var(--_border-color);\n    backdrop-filter: blur(var(--table-sticky-blur, var(--blur-md))) saturate(140%);\n  }\n}\n","import { bind, define, getHost, html, onMounted, prop, watchEffect } from '@vielzeug/ore';\n\nimport { reducedMotionMixin, tableBaseMixin } from '../../styles';\nimport componentStyles from './table.css?inline';\n\n/* ── Types ───────────────────────────────────────────────────────────────── */\n\n/** Table component properties */\nexport type OreTableProps = {\n  /** Adds a thicker outer border */\n  bordered?: boolean;\n  /** Visible caption text — also used as the accessible table label via `aria-label` */\n  caption?: string;\n  /** Cell density: `'compact'` | `'cozy'` (default) | `'comfortable'` */\n  density?: 'compact' | 'cozy' | 'comfortable';\n  /** Expands the table to 100% of its container width */\n  fullwidth?: boolean;\n  /** Applies a busy/disabled state with reduced opacity */\n  loading?: boolean;\n  /** Enables sticky column headers with a vertical scroll container */\n  sticky?: boolean;\n  /** Alternating row stripe backgrounds */\n  striped?: boolean;\n};\n\n/* ── Child element markers ───────────────────────────────────────────────── */\n// ore-tr, ore-th, ore-td are lightweight light-DOM markers.\n// ore-table reads them and constructs a fully-native shadow <table> so that\n// browser features that require real table elements (colspan/rowspan,\n// position:sticky on <thead>, table layout algorithm) all work correctly.\n// Attributes on ore-th/ore-td are mirrored to the generated native cells.\n\n/**\n * Light-DOM row marker consumed by `<ore-table>`.\n *\n * @element ore-tr\n * @attr {boolean} head - Places the row in the generated `<thead>` section\n * @attr {boolean} foot - Places the row in the generated `<tfoot>` section\n *\n * @example\n * ```html\n * <ore-table>\n *   <ore-tr head><ore-th>Name</ore-th><ore-th>Role</ore-th></ore-tr>\n *   <ore-tr><ore-td>Alice</ore-td><ore-td>Admin</ore-td></ore-tr>\n * </ore-table>\n * ```\n */\nif (!customElements.get('ore-tr')) customElements.define('ore-tr', class extends HTMLElement {});\n\n/**\n * Light-DOM header cell marker consumed by `<ore-table>`.\n *\n * @element ore-th\n * @attr {number} colspan  - Mirrors to native `<th colspan>`\n * @attr {number} rowspan  - Mirrors to native `<th rowspan>`\n * @attr {string} scope    - Mirrors to native `<th scope>`: 'col' | 'row' | 'colgroup' | 'rowgroup'\n * @attr {string} headers  - Mirrors to native `<th headers>`\n *\n * @example\n * ```html\n * <ore-tr head>\n *   <ore-th scope=\"col\">Name</ore-th>\n *   <ore-th scope=\"col\" colspan=\"2\">Address</ore-th>\n * </ore-tr>\n * ```\n */\nif (!customElements.get('ore-th')) customElements.define('ore-th', class extends HTMLElement {});\n\n/**\n * Light-DOM data cell marker consumed by `<ore-table>`.\n *\n * @element ore-td\n * @attr {number} colspan  - Mirrors to native `<td colspan>`\n * @attr {number} rowspan  - Mirrors to native `<td rowspan>`\n * @attr {string} headers  - Mirrors to native `<td headers>`\n *\n * @example\n * ```html\n * <ore-tr>\n *   <ore-td>Alice</ore-td>\n *   <ore-td colspan=\"2\">123 Main St, Springfield</ore-td>\n * </ore-tr>\n * ```\n */\nif (!customElements.get('ore-td')) customElements.define('ore-td', class extends HTMLElement {});\n\n/* ── Proxy/mirror helpers ────────────────────────────────────────────────── */\n\n// Attributes forwarded from ore-th/ore-td to the generated native cell.\n// scope is intentionally excluded — it requires fallback logic and is handled separately.\nconst CELL_ATTRS = ['colspan', 'rowspan', 'headers', 'abbr'];\n\n/**\n * Sync text content and tracked attributes from a light-DOM marker to its\n * native mirror. `fallbackScope` is applied when the source element carries no\n * explicit `scope` attribute, ensuring the auto-inferred value is always\n * present and is restored if an explicit override is later removed.\n */\nfunction syncCell(source: Element, native: HTMLTableCellElement, fallbackScope?: string): void {\n  if (source.childElementCount > 0) {\n    // Source has element children — deep-clone them into the native cell so\n    // components like ore-skeleton render correctly inside the shadow table.\n    // Guard: skip re-clone if the serialised content is identical to avoid\n    // redundant DOM work on every MutationObserver tick (e.g. 250+ cells\n    // of skeleton loaders all cloning on each attribute change).\n    const snapshot = source.innerHTML;\n\n    if (native.getAttribute('data-src-html') === snapshot) return;\n\n    native.setAttribute('data-src-html', snapshot);\n    native.textContent = '';\n\n    for (const child of source.childNodes) {\n      native.appendChild(child.cloneNode(true));\n    }\n  } else {\n    const text = source.textContent ?? '';\n\n    if (native.textContent !== text) native.textContent = text;\n  }\n\n  for (const attr of CELL_ATTRS) {\n    const val = source.getAttribute(attr);\n\n    if (val !== null) native.setAttribute(attr, val);\n    else native.removeAttribute(attr);\n  }\n\n  // scope: explicit attribute wins; otherwise restore the inferred fallback.\n  const explicitScope = source.getAttribute('scope');\n\n  if (explicitScope !== null) native.setAttribute('scope', explicitScope);\n  else if (fallbackScope) native.scope = fallbackScope;\n  else native.removeAttribute('scope');\n}\n\n/** Entry stored in the cell map: native mirror element + its inferred scope fallback. */\ntype CellEntry = { inferredScope: string | undefined; native: HTMLTableCellElement };\n\n/**\n * (Re)build the entire native shadow table from the current light-DOM markers.\n * Returns a WeakMap of source marker → CellEntry for targeted sync by the\n * content observer. Storing `inferredScope` per cell ensures that removing an\n * explicit `scope` attribute reverts to the auto-inferred value rather than\n * dropping it entirely.\n */\nfunction buildTable(\n  host: HTMLElement,\n  thead: HTMLTableSectionElement,\n  tbody: HTMLTableSectionElement,\n  tfoot: HTMLTableSectionElement,\n): WeakMap<Element, CellEntry> {\n  const cellMap = new WeakMap<Element, CellEntry>();\n\n  thead.textContent = '';\n  tbody.textContent = '';\n  tfoot.textContent = '';\n\n  for (const child of host.children) {\n    if (child.localName !== 'ore-tr') continue;\n\n    const section = child.hasAttribute('head') ? thead : child.hasAttribute('foot') ? tfoot : tbody;\n    const tr = document.createElement('tr');\n\n    for (const cell of child.children) {\n      if (cell.localName !== 'ore-th' && cell.localName !== 'ore-td') continue;\n\n      const isHeader = cell.localName === 'ore-th';\n      const native = document.createElement(isHeader ? 'th' : 'td');\n      // Auto-infer scope for <th> elements; undefined for <td>.\n      const inferredScope = isHeader ? (section === thead ? 'col' : 'row') : undefined;\n\n      native.setAttribute('part', section === tbody ? 'cell' : 'header-cell');\n      native.removeAttribute('data-src-html');\n      syncCell(cell, native, inferredScope);\n      cellMap.set(cell, { inferredScope, native });\n      tr.appendChild(native);\n    }\n\n    section.appendChild(tr);\n  }\n\n  return cellMap;\n}\n\n/**\n * Data table component.\n *\n * Reads light-DOM `<ore-tr>`/`<ore-th>`/`<ore-td>` markers and projects them\n * into a fully-native shadow `<table>`. Cell attributes (`colspan`, `rowspan`,\n * `scope`, etc.) are mirrored. Changes are observed and synced incrementally.\n *\n * Native table features — sticky headers, colspan/rowspan, the table layout\n * algorithm — all work because the shadow tree contains real table elements.\n *\n * @element ore-table\n *\n * @attr {boolean} bordered  - Thicker outer border\n * @attr {string}  caption   - Caption text shown above the table\n * @attr {boolean} fullwidth - Expands to 100% container width\n * @attr {boolean} loading   - Busy state: reduced opacity, no pointer events\n * @attr {string}  density   - Cell density: 'compact' | 'cozy' | 'comfortable' (default: 'cozy')\n * @attr {boolean} sticky    - Sticky `<thead>` with scroll container\n * @attr {boolean} striped   - Alternating row backgrounds\n *\n * @part scroll       - Scroll container that hosts the generated native table\n * @part table        - Generated native `<table>` element\n * @part head         - Generated native `<thead>` section\n * @part body         - Generated native `<tbody>` section\n * @part foot         - Generated native `<tfoot>` section\n * @part cell         - Every native `<td>` in `<tbody>` rows\n * @part header-cell  - Every native `<th>` / `<td>` in `<thead>` and `<tfoot>` rows\n *\n * @cssprop --table-bg                - Table background color\n * @cssprop --table-border-color      - Cell separator and outer border color\n * @cssprop --table-radius            - Corner radius of the table container\n * @cssprop --table-shadow            - Box shadow of the table container\n * @cssprop --table-header-bg         - Background of header and footer rows\n * @cssprop --table-accent            - Accent color for interactive states\n * @cssprop --table-row-hover-bg      - Row hover background\n * @cssprop --table-stripe-bg         - Even-row stripe background\n * @cssprop --table-cell-padding-x    - Cell horizontal padding\n * @cssprop --table-cell-padding-y    - Cell vertical padding\n * @cssprop --table-font-size         - Base font size for cells\n * @cssprop --table-sticky-max-height - Max height of the sticky scroll container\n * @cssprop --table-sticky-header-bg  - Background of sticky header cells\n * @cssprop --table-sticky-blur       - Backdrop blur applied to sticky headers\n *\n * @example\n * ```html\n * <ore-table caption=\"Top repositories\" striped bordered sticky>\n *   <ore-tr head>\n *     <ore-th>Repository</ore-th>\n *     <ore-th>Stars</ore-th>\n *   </ore-tr>\n *   <ore-tr>\n *     <ore-td>vielzeug/refine</ore-td>\n *     <ore-td>1 200</ore-td>\n *   </ore-tr>\n * </ore-table>\n * ```\n */\nexport const TABLE_TAG = 'ore-table' as const;\ndefine<OreTableProps>(TABLE_TAG, {\n  props: {\n    bordered: prop.bool(false),\n    caption: prop.string(),\n    density: prop.string<'compact' | 'cozy' | 'comfortable'>(),\n    fullwidth: prop.bool(false),\n    loading: prop.bool(false),\n    sticky: prop.bool(false),\n    striped: prop.bool(false),\n  },\n\n  setup(props) {\n    const el = getHost();\n    const watch = watchEffect;\n\n    bind({\n      attr: {\n        'aria-busy': props.loading,\n        'aria-label': props.caption,\n      },\n    });\n\n    // Build the native shadow table via DOM APIs (not innerHTML) to avoid\n    // HTML-parser foster-parenting, which ejects table section elements from\n    // their intended positions in the tree.\n    onMounted(() => {\n      const scrollContainer = el.shadowRoot?.querySelector('.scroll-container')!;\n\n      const table = document.createElement('table');\n      const captionEl = document.createElement('caption');\n      const thead = document.createElement('thead');\n      const tbody = document.createElement('tbody');\n      const tfoot = document.createElement('tfoot');\n\n      scrollContainer.setAttribute('part', 'scroll');\n      table.setAttribute('part', 'table');\n      thead.setAttribute('part', 'head');\n      tbody.setAttribute('part', 'body');\n      tfoot.setAttribute('part', 'foot');\n      table.append(captionEl, thead, tbody, tfoot);\n      scrollContainer.appendChild(table);\n\n      // Reactively sync caption text and visibility from prop.\n      watch(() => {\n        const text = props.caption.value ?? '';\n\n        captionEl.textContent = text;\n        captionEl.hidden = text === '';\n      });\n\n      // Initial full build.\n      let cellMap = buildTable(el, thead, tbody, tfoot);\n\n      // Content observer: syncs text/attribute changes inside ore-th/ore-td.\n      // Remains connected throughout the component lifetime — no\n      // disconnect/reconnect during structural rebuilds. Records that arrive\n      // for cells no longer in cellMap (after a rebuild) are silently ignored\n      // by the `if (entry)` guard, so there is no correctness risk.\n      const contentObserver = new MutationObserver((records) => {\n        for (const rec of records) {\n          const sourceCell = (rec.target instanceof Element ? rec.target : rec.target.parentElement)?.closest(\n            'ore-th, ore-td',\n          );\n\n          if (sourceCell) {\n            const entry = cellMap.get(sourceCell);\n\n            if (entry) syncCell(sourceCell, entry.native, entry.inferredScope);\n          }\n        }\n      });\n\n      contentObserver.observe(el, {\n        // Include 'scope' in attributeFilter so explicit scope changes are picked\n        // up and the fallback-restore logic in syncCell runs correctly.\n        attributeFilter: [...CELL_ATTRS, 'scope'],\n        attributes: true,\n        characterData: true,\n        childList: true,\n        subtree: true,\n      });\n\n      // Structure observer: triggers a full rebuild when ore-tr elements are\n      // added, removed, or reordered. Scoped to direct children only so it\n      // never fires for cell-level mutations.\n      const structureObserver = new MutationObserver(() => {\n        cellMap = buildTable(el, thead, tbody, tfoot);\n      });\n\n      structureObserver.observe(el, { childList: true });\n\n      return () => {\n        structureObserver.disconnect();\n        contentObserver.disconnect();\n      };\n    });\n\n    return html`\n      <div class=\"scroll-container\"></div>\n    `;\n  },\n\n  styles: [reducedMotionMixin, tableBaseMixin('table'), componentStyles],\n});\n","/* ========================================\n     Base Styles & Defaults\n     ======================================== */\n\n:host {\n  /* Internal variables with CSS custom property fallbacks */\n  --_size: var(--text-size, var(--text-base));\n  --_weight: var(--text-weight, var(--font-normal));\n  --_color: var(--text-color, var(--text-color-body));\n  --_line-height: var(--text-line-height, var(--leading-normal));\n  --_letter-spacing: var(--text-letter-spacing, normal);\n\n  display: block;\n  font-size: var(--_size);\n  font-weight: var(--_weight);\n  line-height: var(--_line-height);\n  color: var(--_color);\n  letter-spacing: var(--_letter-spacing);\n}\n\n:host([hidden]) {\n  display: none;\n}\n\n/* ========================================\n     Unlayered display overrides\n     These must live outside any @layer so they can beat the unlayered\n     display: block on :host. Same cascade rule that was fixed for [lines].\n     ======================================== */\n\n/* Multi-line truncation */\n:host([lines]) {\n  display: -webkit-box;\n  -webkit-box-orient: vertical;\n  overflow: hidden;\n  -webkit-line-clamp: var(--_lines);\n}\n\n/* Inline semantic tags — but not when align/truncate force block layout */\n:host(:is([as='span'], [as='label'], [as='code']):not([align], [truncate])) {\n  display: inline;\n}\n\n/* ========================================\n     Variant Styles\n     ======================================== */\n\n/* Body (default) — uses base defaults above */\n\n/* Heading\n   Default size: --heading-md (24px)\n   Letter-spacing: --tracking-header (-0.05em) per theme guidelines\n   Line-height: --leading-tight (1.15) for display headings */\n:host([variant='heading']) {\n  --_size: var(--text-size, var(--heading-md));\n  --_weight: var(--text-weight, var(--font-semibold));\n  --_color: var(--text-color, var(--text-color-heading));\n  --_line-height: var(--text-line-height, var(--leading-tight));\n  --_letter-spacing: var(--text-letter-spacing, var(--tracking-header));\n}\n\n/* Label — slightly tighter line-height for UI labels */\n:host([variant='label']) {\n  --_size: var(--text-size, var(--text-sm));\n  --_weight: var(--text-weight, var(--font-medium));\n  --_color: var(--text-color, var(--text-color-heading));\n  --_line-height: var(--text-line-height, var(--leading-snug));\n}\n\n/* Caption */\n:host([variant='caption']) {\n  --_size: var(--text-size, var(--text-sm));\n  --_color: var(--text-color, var(--text-color-secondary));\n}\n\n/* Overline */\n:host([variant='overline']) {\n  --_size: var(--text-size, var(--text-xs));\n  --_weight: var(--text-weight, var(--font-semibold));\n  --_line-height: var(--text-line-height, var(--leading-none));\n  --_letter-spacing: var(--text-letter-spacing, 0.08em);\n\n  text-transform: uppercase;\n}\n\n/* Code */\n:host([variant='code']) {\n  --_size: var(--text-size, var(--text-sm));\n\n  font-family: var(--font-mono, monospace);\n}\n\n/* ========================================\n     Size Variants — body scale (--text-*)\n     Used by all variants except heading.\n     ======================================== */\n\n:host([size='2xs']) {\n  --_size: var(--text-size, var(--text-2xs));\n}\n\n:host([size='xs']) {\n  --_size: var(--text-size, var(--text-xs));\n}\n\n:host([size='sm']) {\n  --_size: var(--text-size, var(--text-sm));\n}\n\n:host([size='md']) {\n  --_size: var(--text-size, var(--text-base));\n}\n\n:host([size='lg']) {\n  --_size: var(--text-size, var(--text-lg));\n}\n\n:host([size='xl']) {\n  --_size: var(--text-size, var(--text-xl));\n}\n\n:host([size='2xl']) {\n  --_size: var(--text-size, var(--text-2xl));\n}\n\n/* ========================================\n     Size Variants — heading scale (--heading-*)\n     Compound selectors override the body-scale rules above when\n     variant=\"heading\" and a size is also provided.\n     ======================================== */\n\n:host([variant='heading'][size='xs']) {\n  --_size: var(--text-size, var(--heading-xs));\n}\n\n:host([variant='heading'][size='sm']) {\n  --_size: var(--text-size, var(--heading-sm));\n}\n\n:host([variant='heading'][size='md']) {\n  --_size: var(--text-size, var(--heading-md));\n}\n\n:host([variant='heading'][size='lg']) {\n  --_size: var(--text-size, var(--heading-lg));\n}\n\n:host([variant='heading'][size='xl']) {\n  --_size: var(--text-size, var(--heading-xl));\n}\n\n:host([variant='heading'][size='2xl']) {\n  --_size: var(--text-size, var(--heading-2xl));\n}\n\n/* ========================================\n     Weight Variants\n     ======================================== */\n\n:host([weight='normal']) {\n  --_weight: var(--text-weight, var(--font-normal));\n}\n\n:host([weight='medium']) {\n  --_weight: var(--text-weight, var(--font-medium));\n}\n\n:host([weight='semibold']) {\n  --_weight: var(--text-weight, var(--font-semibold));\n}\n\n:host([weight='bold']) {\n  --_weight: var(--text-weight, var(--font-bold));\n}\n\n/* ========================================\n     Color Variants\n     Semantic colors map to --text-color-* tokens.\n     Theme colors map to --color-* base tokens.\n     ======================================== */\n\n:host([color='primary']) {\n  --_color: var(--text-color, var(--color-primary));\n}\n\n:host([color='secondary']) {\n  --_color: var(--text-color, var(--color-secondary));\n}\n\n:host([color='info']) {\n  --_color: var(--text-color, var(--color-info));\n}\n\n:host([color='success']) {\n  --_color: var(--text-color, var(--color-success));\n}\n\n:host([color='warning']) {\n  --_color: var(--text-color, var(--color-warning));\n}\n\n:host([color='error']) {\n  --_color: var(--text-color, var(--color-error));\n}\n\n/* Semantic text colors */\n:host([color='heading']) {\n  --_color: var(--text-color, var(--text-color-heading)); /* --color-contrast-900 */\n}\n\n:host([color='body']) {\n  --_color: var(--text-color, var(--text-color-body)); /* --color-contrast-800 */\n}\n\n:host([color='muted']) {\n  --_color: var(--text-color, var(--text-color-secondary)); /* --color-contrast-600 — AA compliant */\n}\n\n:host([color='tertiary']) {\n  --_color: var(--text-color, var(--text-color-tertiary)); /* --color-contrast-500 — AA for large text */\n}\n\n:host([color='disabled']) {\n  --_color: var(--text-color, var(--text-color-disabled)); /* --color-contrast-400 */\n}\n\n:host([color='contrast']) {\n  --_color: var(--text-color, var(--text-color-contrast)); /* --color-contrast-100 */\n}\n\n@layer refine.utilities {\n  /* ========================================\n     Alignment\n     ======================================== */\n\n  :host([align]) {\n    display: block;\n  }\n\n  :host([align='left']) {\n    text-align: start;\n  }\n\n  :host([align='center']) {\n    text-align: center;\n  }\n\n  :host([align='right']) {\n    text-align: end;\n  }\n\n  :host([align='justify']) {\n    text-align: justify;\n  }\n\n  /* ========================================\n     Truncate (single-line)\n     ======================================== */\n\n  :host([truncate]) {\n    display: block;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n  }\n\n  /* ========================================\n     Italic\n     ======================================== */\n\n  :host([italic]) {\n    font-style: italic;\n  }\n\n  /* ========================================\n     Block Display for Certain Tags\n     ======================================== */\n\n  :host([as='p']),\n  :host([as='div']),\n  :host(:is([as='h1'], [as='h2'], [as='h3'], [as='h4'], [as='h5'], [as='h6'])) {\n    display: block;\n  }\n\n  /* Note: display: inline for span/label/code is handled outside this @layer\n     (above) so it can override the unlayered :host { display: block }. */\n}\n","import { bind, define, html, prop } from '@vielzeug/ore';\n\nimport styles from './text.css?inline';\n\n/** Text component properties */\nexport type OreTextProps = {\n  /** Text alignment */\n  align?: 'left' | 'center' | 'right' | 'justify';\n  /** Semantic HTML element to render as — sets the correct ARIA role/level on the host */\n  as?: 'span' | 'p' | 'div' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'label' | 'code';\n  /** Text color (semantic + theme colors) */\n  color?:\n    | 'primary'\n    | 'secondary'\n    | 'info'\n    | 'success'\n    | 'warning'\n    | 'error'\n    | 'heading'\n    | 'body'\n    | 'muted'\n    | 'tertiary'\n    | 'disabled'\n    | 'contrast';\n  /** Italic text style */\n  italic?: boolean;\n  /** Clamp text to N lines with an ellipsis (multi-line truncation) */\n  lines?: number;\n  /** Text size — maps to --text-* tokens for body variants and --heading-* tokens for the heading variant */\n  size?: '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n  /** Enable single-line text truncation with ellipsis */\n  truncate?: boolean;\n  /** Text semantic variant */\n  variant?: 'body' | 'heading' | 'label' | 'caption' | 'overline' | 'code';\n  /** Font weight */\n  weight?: 'normal' | 'medium' | 'semibold' | 'bold';\n};\n\n/**\n * A typography component with semantic variants and responsive sizing.\n *\n * @element ore-text\n *\n * @attr {string} variant - Text variant: 'body' | 'heading' | 'label' | 'caption' | 'overline' | 'code'\n * @attr {string} size - Font size: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'. Maps to --text-* tokens for body variants and --heading-* tokens for the heading variant.\n * @attr {string} weight - Font weight: 'normal' | 'medium' | 'semibold' | 'bold'\n * @attr {string} color - Text color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error' | 'heading' | 'body' | 'muted' | 'tertiary' | 'disabled' | 'contrast'\n * @attr {string} align - Text alignment: 'left' | 'center' | 'right' | 'justify'\n * @attr {boolean} truncate - Truncate text with ellipsis when it overflows (single-line)\n * @attr {number} lines - Clamp to N lines with ellipsis (multi-line truncation)\n * @attr {boolean} italic - Italic text style\n * @attr {string} as - Semantic HTML element: 'span' | 'p' | 'div' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'label' | 'code'\n *\n * @slot - Text content\n *\n * @cssprop --text-size - Font size\n * @cssprop --text-weight - Font weight\n * @cssprop --text-color - Text color\n * @cssprop --text-line-height - Line height\n * @cssprop --text-letter-spacing - Letter spacing\n *\n * @example\n * ```html\n * <ore-text variant=\"heading\" size=\"2xl\" weight=\"bold\">Welcome</ore-text>\n * <ore-text as=\"h2\" variant=\"heading\" size=\"xl\">Section title</ore-text>\n * <ore-text color=\"primary\" weight=\"semibold\">Important notice</ore-text>\n * <ore-text variant=\"code\">npm install</ore-text>\n * <ore-text lines=\"2\">Long paragraph that clamps at two lines…</ore-text>\n * ```\n */\n\nexport const TEXT_TAG = 'ore-text' as const;\ndefine<OreTextProps>(TEXT_TAG, {\n  props: {\n    align: prop.string<'left' | 'center' | 'right' | 'justify'>(),\n    as: prop.string<'span' | 'p' | 'div' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'label' | 'code'>(),\n    color: prop.string<\n      | 'primary'\n      | 'secondary'\n      | 'info'\n      | 'success'\n      | 'warning'\n      | 'error'\n      | 'heading'\n      | 'body'\n      | 'muted'\n      | 'tertiary'\n      | 'disabled'\n      | 'contrast'\n    >(),\n    italic: prop.bool(),\n    lines: prop.number(),\n    size: prop.string<'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'>(),\n    truncate: prop.bool(),\n    variant: prop.string<'body' | 'heading' | 'label' | 'caption' | 'overline' | 'code'>(),\n    weight: prop.string<'normal' | 'medium' | 'semibold' | 'bold'>(),\n  },\n  setup(props) {\n    bind({\n      attr: {\n        'aria-level': () => {\n          const match = /^h([1-6])$/.exec((props.as.value as string) ?? '');\n\n          return match ? match[1] : null;\n        },\n        role: () => (/^h([1-6])$/.test((props.as.value as string) ?? '') ? 'heading' : null),\n      },\n      style: {\n        '--_lines': () => (props.lines.value != null ? String(props.lines.value) : null),\n      },\n    });\n\n    return html`\n      <slot></slot>\n    `;\n  },\n  styles: [styles],\n});\n","export type { AvatarStatus, OreAvatarProps } from './avatar/avatar';\nexport { AVATAR_TAG } from './avatar/avatar';\nexport type { OreAvatarGroupProps } from './avatar/avatar-group';\nexport { AVATAR_GROUP_TAG } from './avatar/avatar-group';\nexport type { OreBreadcrumbItemProps, OreBreadcrumbProps } from './breadcrumb/breadcrumb';\nexport { BREADCRUMB_ITEM_TAG, BREADCRUMB_TAG } from './breadcrumb/breadcrumb';\nexport type { OreCardEvents, OreCardProps } from './card/card';\nexport { CARD_TAG } from './card/card';\nexport type { CarouselOrientation, CarouselVariant, OreCarouselEvents, OreCarouselProps } from './carousel/carousel';\nexport { CAROUSEL_SLIDE_TAG, CAROUSEL_TAG } from './carousel/carousel';\nexport type {\n  ChatMessageSender,\n  ChatMessageStatus,\n  OreChatMessageEvents,\n  OreChatMessageProps,\n} from './chat-message/chat-message';\nexport { CHAT_MESSAGE_TAG } from './chat-message/chat-message';\nexport type { CodeWindowVariant, OreCodeWindowProps } from './code-window/code-window';\nexport { CODE_WINDOW_TAG } from './code-window/code-window';\nexport type { OreCopyCommandEvents, OreCopyCommandProps } from './copy-command/copy-command';\nexport { COPY_COMMAND_TAG } from './copy-command/copy-command';\nexport type { IconNode, OreIconProps } from './icon/icon';\nexport { ICON_TAG, registerIcons } from './icon/icon';\nexport type { ListContext, ListVariant, OreListEvents, OreListProps } from './list/list';\nexport { LIST_CTX, LIST_TAG } from './list/list';\nexport type { ListItemRevealSide, OreListItemEvents, OreListItemProps } from './list/list-item';\nexport { LIST_ITEM_TAG } from './list/list-item';\nexport type { MarqueeDirection, OreMarqueeProps } from './marquee/marquee';\nexport { MARQUEE_TAG } from './marquee/marquee';\nexport type { OrePaginationEvents, OrePaginationProps } from './pagination/pagination';\nexport { PAGINATION_TAG } from './pagination/pagination';\nexport type { OreSeparatorProps } from './separator/separator';\nexport { SEPARATOR_TAG } from './separator/separator';\nexport type { OreStepProps } from './stepper/step';\nexport { STEP_TAG } from './stepper/step';\nexport type { OreStepperEvents, OreStepperProps, StepperContext } from './stepper/stepper';\nexport { STEPPER_CTX, STEPPER_TAG } from './stepper/stepper';\nexport type { OreTableProps } from './table/table';\nexport { TABLE_TAG } from './table/table';\nexport type { OreTextProps } from './text/text';\nexport { TEXT_TAG } from './text/text';\n","@layer refine.base {\n  :host {\n    --_bg: var(--accordion-bg);\n    --_border-color: var(--accordion-border-color);\n\n    display: flex;\n    flex-direction: column;\n    gap: var(--size-2);\n    width: 100%;\n    background: var(--_bg);\n  }\n\n  ::slotted(ore-accordion-item) {\n    width: 100%;\n  }\n}\n\n@layer refine.variants {\n  /* ========================================\n       Visual Variants\n       ======================================== */\n\n  /* Bordered variant */\n  :host([variant='bordered']) {\n    gap: var(--size-2);\n  }\n\n  /* Text variant - borderless with dividers */\n  :host([variant='text']) {\n    gap: 0;\n  }\n\n  :host([variant='text']) ::slotted(ore-accordion-item:not(:last-child)) {\n    border-bottom: 1px solid var(--accordion-divider-color, var(--color-contrast-200));\n  }\n\n  /* Contained variants - grouped appearance */\n  :host([variant='solid']),\n  :host([variant='flat']),\n  :host([variant='glass']),\n  :host([variant='frost']) {\n    gap: 0;\n    padding: var(--size-2);\n    border-radius: var(--rounded-lg);\n  }\n\n  /* Solid variant (default) */\n  :host([variant='solid']) {\n    --_bg: var(--accordion-bg, var(--color-contrast-50));\n    --_border-color: var(--accordion-border-color, var(--color-contrast-200));\n\n    border: var(--border) solid var(--_border-color);\n    box-shadow: var(--accordion-shadow, var(--shadow-xs));\n  }\n\n  /* Flat variant */\n  :host([variant='flat']) {\n    --_bg: var(--accordion-bg, var(--color-contrast-100));\n    --_border-color: var(--accordion-border-color, var(--color-contrast-200));\n\n    border: var(--border) solid var(--_border-color);\n    box-shadow: var(--accordion-shadow, var(--inset-shadow-xs));\n  }\n\n  /* Glass & Frost - Shared styles */\n  :host([variant='glass']),\n  :host([variant='frost']) {\n    box-shadow: var(--accordion-shadow, var(--shadow-md), var(--inset-shadow-xs));\n    backdrop-filter: blur(var(--blur-lg)) saturate(180%) brightness(1.05);\n  }\n\n  /* Glass variant - translucent with blur */\n  :host([variant='glass']) {\n    --_bg: var(--accordion-bg, color-mix(in oklch, var(--color-secondary) 30%, var(--color-contrast) 10%));\n  }\n\n  /* Frost variant - canvas-based transparency */\n  :host([variant='frost']) {\n    --_bg: var(--accordion-bg, color-mix(in oklch, var(--color-canvas) 55%, transparent));\n  }\n\n  /* Nested item border radius for glass and frost variants */\n  :host(:is([variant='glass'], [variant='frost'])) ::slotted(ore-accordion-item) {\n    border-radius: 0;\n  }\n\n  :host(:is([variant='glass'], [variant='frost'])) ::slotted(ore-accordion-item:first-child) {\n    border-radius: var(--rounded-lg) var(--rounded-lg) 0 0;\n  }\n\n  :host(:is([variant='glass'], [variant='frost'])) ::slotted(ore-accordion-item:last-child) {\n    border-radius: 0 0 var(--rounded-lg) var(--rounded-lg);\n  }\n\n  :host(:is([variant='glass'], [variant='frost'])) ::slotted(ore-accordion-item:only-child) {\n    border-radius: var(--rounded-lg);\n  }\n}\n","import { bind, createContext, define, getHost, html, onCleanup, prop, provide, useEmit } from '@vielzeug/ore';\nimport { computed, type Readable } from '@vielzeug/ripple';\nimport { createListControl, lifecycleSignal } from '../../core';\nimport type { ComponentSize, SurfaceVariant } from '../../types';\nimport styles from './accordion.css?inline';\n\n/** Context provided by ore-accordion to its ore-accordion-item children. */\nexport type AccordionContext = {\n  selectionMode: Readable<'single' | 'multiple' | undefined>;\n  size: Readable<ComponentSize | undefined>;\n  variant: Readable<SurfaceVariant | undefined>;\n};\n/** Injection key for the accordion context. */\nexport const ACCORDION_CTX = createContext<AccordionContext>('AccordionContext');\n\n/** Accordion component properties */\n\nexport type OreAccordionEvents = {\n  change: { expandedItem: HTMLElement };\n};\n\nexport type OreAccordionProps = {\n  /** Selection mode (single = only one opens, multiple = multiple can be open) */\n  selectionMode?: 'single' | 'multiple';\n  /** Size for all items (propagated via context) */\n  size?: ComponentSize;\n  /** Visual variant for all items (propagated via context) */\n  variant?: SurfaceVariant;\n};\n\n/**\n * A container for accordion items with single or multiple selection modes.\n *\n * @element ore-accordion\n * @element ore-accordion-item - Child element for each collapsible panel\n *\n * @attr {string} selection-mode - Selection mode: 'single' | 'multiple'\n * @attr {string} size - Size for all items: 'sm' | 'md' | 'lg' (propagated to children)\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'text' | 'glass' | 'frost' (propagated to children)\n *\n * @fires expand - Emitted when an item expands. detail: { expanded: boolean; item: HTMLElement }\n * @fires change - Emitted when selection changes (single mode). detail: { expandedItem: HTMLElement }\n *\n * @slot - `ore-accordion-item` elements\n *\n * @cssprop --accordion-bg - Container background color (solid/flat/glass/frost variants)\n * @cssprop --accordion-border-color - Container border color (solid/flat variants)\n * @cssprop --accordion-divider-color - Divider color between items (text variant)\n * @cssprop --accordion-shadow - Container box shadow\n * @example\n * ```html\n * <ore-accordion selection-mode=\"single\">\n *   <ore-accordion-item>\n *     <span slot=\"title\">What is Refine?</span>\n *     <p>Refine is a headless web component library.</p>\n *   </ore-accordion-item>\n *   <ore-accordion-item>\n *     <span slot=\"title\">How do I install it?</span>\n *     <p>Run <code>npm install @vielzeug/refine</code>.</p>\n *   </ore-accordion-item>\n * </ore-accordion>\n * <ore-accordion variant=\"bordered\" selection-mode=\"multiple\">\n *   <ore-accordion-item expanded><span slot=\"title\">Open by default</span><p>Content</p></ore-accordion-item>\n * </ore-accordion>\n * ```\n */\n\nexport const ACCORDION_TAG = 'ore-accordion' as const;\ndefine<OreAccordionProps>(ACCORDION_TAG, {\n  props: {\n    selectionMode: prop.string<'single' | 'multiple'>(),\n    size: prop.string<ComponentSize>(),\n    variant: prop.string<SurfaceVariant>(),\n  },\n\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreAccordionEvents>();\n\n    const handleSelectionMode = (expandedItem: HTMLElement) => {\n      if (props.selectionMode.value !== 'single') return;\n\n      el.querySelectorAll(':scope > ore-accordion-item[expanded]').forEach((item) => {\n        if (item !== expandedItem && item.hasAttribute('expanded')) {\n          item.removeAttribute('expanded');\n        }\n      });\n\n      emit('change', { expandedItem });\n    };\n\n    const getAccordionItems = () => {\n      return [...el.querySelectorAll<HTMLElement>(':scope > ore-accordion-item:not([disabled])')];\n    };\n\n    const getSummaryElements = () => {\n      return getAccordionItems()\n        .map((item) => item.shadowRoot?.querySelector<HTMLElement>('summary'))\n        .filter(Boolean) as HTMLElement[];\n    };\n\n    const listControl = createListControl({\n      getItems: () => getAccordionItems(),\n      loop: true,\n      onNavigate: ({ index }) => {\n        const summaries = getSummaryElements();\n\n        summaries[index]?.focus();\n      },\n      signal: lifecycleSignal(onCleanup),\n    });\n\n    provide(ACCORDION_CTX, {\n      selectionMode: computed(() => props.selectionMode.value),\n      size: props.size,\n      variant: props.variant,\n    });\n\n    // Group-level event and keyboard handling for WAI-ARIA Accordion pattern\n\n    bind({\n      on: {\n        expand: (event: Event) => {\n          const eventTarget = event.composedPath().find((node): node is HTMLElement => node instanceof HTMLElement);\n          const expandedItem = (event as CustomEvent<{ item?: HTMLElement }>).detail?.item ?? eventTarget;\n\n          if (expandedItem?.localName !== 'ore-accordion-item') return;\n\n          // Guard: only respond to accordion-items that belong to THIS accordion instance\n          if (expandedItem.closest('ore-accordion') !== el) return;\n\n          handleSelectionMode(expandedItem);\n        },\n        keydown: (evt: KeyboardEvent) => {\n          const summaries = getSummaryElements();\n\n          if (!summaries.length) return;\n\n          const activeSummary = evt\n            .composedPath()\n            .find((node): node is HTMLElement => node instanceof HTMLElement && node.localName === 'summary');\n          const focused = activeSummary ? summaries.indexOf(activeSummary) : -1;\n\n          if (focused === -1) return; // focus is not on a summary — let native handling proceed\n\n          listControl.set(focused);\n          listControl.handleKeydown(evt);\n        },\n      },\n    });\n\n    return html`\n      <slot></slot>\n    `;\n  },\n\n  styles: [styles],\n});\n","@layer refine.base {\n  /* ========================================\n       Base Styles & Defaults\n       ======================================== */\n\n  :host {\n    --accordion-details-radius: var(--rounded-lg);\n    --accordion-item-transition: var(--transition-normal);\n    --accordion-item-expand-easing: var(--ease-spring);\n    display: block;\n    color: var(--accordion-item-body-color, var(--text-color-body));\n  }\n\n  details {\n    width: 100%;\n    overflow: hidden;\n    border-radius: var(--accordion-item-radius);\n  }\n\n  summary {\n    position: relative;\n    display: flex;\n    gap: var(--size-4);\n    align-items: center;\n    min-height: var(--_touch-target);\n    padding: var(--accordion-item-details-padding, var(--size-3) var(--size-4));\n    font-size: var(--accordion-item-title);\n    cursor: pointer;\n    user-select: none;\n    outline: none;\n    list-style: none;\n    background: var(--accordion-item-bg);\n    border: var(--border) solid var(--accordion-item-border-color);\n    border-radius: var(--accordion-details-radius);\n    transition:\n      background var(--accordion-item-transition),\n      border-color var(--accordion-item-transition),\n      color var(--accordion-item-transition);\n  }\n\n  summary::-webkit-details-marker {\n    display: none;\n  }\n\n  summary:focus {\n    outline: none;\n  }\n\n  summary:focus-visible {\n    outline: var(--border-2) solid currentcolor;\n    outline-offset: var(--border-2);\n    box-shadow: 0 0 0 3px color-mix(in oklch, currentcolor 20%, transparent);\n  }\n\n  .header-content {\n    display: flex;\n    flex: 1;\n    flex-direction: column;\n    min-width: 0;\n  }\n\n  .subtitle {\n    font-size: var(--accordion-item-subtitle-size);\n    line-height: var(--leading-normal);\n    color: var(--accordion-item-subtitle-color, var(--text-color-secondary));\n  }\n\n  .title {\n    overflow: hidden;\n    text-overflow: ellipsis;\n    font-weight: var(--font-medium);\n    color: var(--accordion-item-title-color, var(--text-color-heading));\n    white-space: nowrap;\n  }\n\n  .content-wrapper {\n    display: grid;\n    grid-template-rows: 0fr;\n    font-size: var(--accordion-item-body);\n    background: var(--accordion-item-bg);\n    border-inline: 1px solid var(--accordion-item-border-color);\n    border-bottom: 1px solid var(--accordion-item-border-color);\n    border-radius: var(--accordion-summary-radius);\n    transition: grid-template-rows 200ms var(--accordion-item-expand-easing, var(--ease-spring));\n  }\n\n  details[open] .content-wrapper {\n    grid-template-rows: 1fr;\n  }\n\n  .content-inner {\n    padding: var(--accordion-item-summary-padding, var(--size-2) var(--size-4));\n    overflow: hidden;\n    opacity: 1;\n    transform: translateY(0);\n    transition:\n      opacity 200ms 60ms var(--ease-spring),\n      transform 200ms 60ms var(--ease-spring);\n  }\n\n  /* Opening: set from-state with no transition — transition fires on base rule when class is removed */\n  details.opening .content-inner {\n    opacity: 0;\n    transform: translateY(-6px);\n    transition: none;\n  }\n\n  /* Closing: content fades out immediately, row collapses after */\n  details.closing .content-inner {\n    opacity: 0;\n    transform: translateY(-4px);\n    transition:\n      opacity 150ms var(--ease-spring),\n      transform 150ms var(--ease-spring);\n  }\n\n  /* Keep row expanded while closing animation plays */\n  details.closing .content-wrapper {\n    grid-template-rows: 1fr;\n    transition: grid-template-rows 200ms 120ms var(--accordion-item-expand-easing, var(--ease-spring));\n  }\n}\n\n@layer refine.variants {\n  /* ========================================\n       Visual Variants\n       ======================================== */\n\n  :host,\n  :host([variant='solid']) {\n    --accordion-item-bg: var(--color-contrast-50);\n    --accordion-item-border-color: transparent;\n    --accordion-item-hover-bg: var(--color-contrast-200);\n  }\n\n  :host([variant='flat']) {\n    --accordion-item-bg: var(--color-contrast-100);\n    --accordion-item-hover-bg: var(--color-contrast-200);\n  }\n\n  :host([variant='bordered']) {\n    --accordion-item-bg: var(--color-contrast-100);\n    --accordion-item-border-color: var(--color-divider);\n    --accordion-item-hover-bg: var(--color-contrast-200);\n\n    box-shadow: var(--inset-shadow-xs), var(--shadow-2xs);\n  }\n\n  :host([variant='outline']) {\n    --accordion-item-bg: transparent;\n    --accordion-item-border-color: var(--color-divider);\n    --accordion-item-hover-bg: var(--color-contrast-300);\n  }\n\n  :host([variant='ghost']) {\n    --accordion-item-bg: transparent;\n    --accordion-item-border-color: transparent;\n    --accordion-item-hover-bg: var(--color-contrast-200);\n  }\n\n  :host([variant='text']) {\n    --accordion-item-bg: transparent;\n    --accordion-item-border-color: transparent;\n    --accordion-item-hover-bg: transparent;\n  }\n\n  /* ── Shared hover state reads per-variant --accordion-item-hover-bg ── */\n  :host summary:hover {\n    background: var(--accordion-item-hover-bg);\n  }\n\n  /* Glass & Frost - Shared Styles */\n  :host([variant='glass']) details,\n  :host([variant='frost']) details {\n    border-radius: inherit;\n  }\n\n  :host([variant='glass']) summary,\n  :host([variant='frost']) summary {\n    border-radius: inherit;\n    backdrop-filter: blur(var(--blur-lg)) saturate(180%);\n  }\n\n  :host([variant='glass']) .content-wrapper,\n  :host([variant='frost']) .content-wrapper {\n    border-radius: 0;\n    backdrop-filter: blur(var(--blur-lg)) saturate(180%);\n  }\n\n  /* Glass */\n  :host([variant='glass']) {\n    --accordion-item-bg: color-mix(in oklch, var(--color-secondary) 30%, var(--color-contrast) 10%);\n    --accordion-item-border-color: transparent;\n    --accordion-item-hover-bg: color-mix(in oklch, var(--color-secondary) 20%, transparent);\n    --accordion-item-title-color: color-mix(in oklch, var(--color-secondary-contrast) 100%, transparent);\n    --accordion-item-subtitle-color: color-mix(in oklch, var(--color-secondary-contrast) 60%, transparent);\n    --accordion-item-body-color: color-mix(in oklch, var(--color-secondary-contrast) 80%, transparent);\n  }\n\n  :host([variant='glass']) summary {\n    text-shadow: var(--text-shadow-xs);\n  }\n\n  :host([variant='glass']) .content-wrapper {\n    filter: brightness(1.05);\n  }\n\n  /* Frost */\n  :host([variant='frost']) {\n    --accordion-item-bg: color-mix(in oklch, var(--color-canvas) 55%, transparent);\n    --accordion-item-border-color: transparent;\n    --accordion-item-hover-bg: color-mix(in oklch, var(--color-canvas) 20%, transparent);\n  }\n\n  :host([variant='frost']) summary {\n    text-shadow: var(--text-shadow-2xs);\n  }\n\n  /* ========================================\n     Size Variants\n     ======================================== */\n\n  :host([size='sm']) {\n    --accordion-item-details-padding: var(--size-2) var(--size-4);\n    --accordion-item-summary-padding: var(--size-1) var(--size-5);\n    --accordion-item-title: var(--text-sm);\n    --accordion-item-subtitle-size: var(--text-xs);\n    --accordion-item-body: var(--text-xs);\n  }\n\n  :host(:not([size])),\n  :host([size='md']) {\n    --accordion-item-details-padding: var(--size-3) var(--size-4);\n    --accordion-item-summary-padding: var(--size-1) var(--size-5);\n    --accordion-item-title: var(--text-base);\n    --accordion-item-subtitle-size: var(--text-sm);\n    --accordion-item-body: var(--text-sm);\n  }\n\n  :host([size='lg']) {\n    --accordion-item-details-padding: var(--size-4) var(--size-4);\n    --accordion-item-summary-padding: var(--size-1) var(--size-5);\n    --accordion-item-title: var(--text-lg);\n    --accordion-item-subtitle-size: var(--text-base);\n    --accordion-item-body: var(--text-base);\n  }\n\n  /* ─── coarse pointer: promote one size tier for proportional scaling ─── */\n  @media (pointer: coarse) {\n    :host,\n    :host([size='md']) {\n      --accordion-item-details-padding: var(--size-4) var(--size-5);\n      --accordion-item-title: var(--text-lg);\n      --accordion-item-subtitle-size: var(--text-base);\n      --accordion-item-body: var(--text-base);\n    }\n\n    :host([size='sm']) {\n      --accordion-item-details-padding: var(--size-3) var(--size-4);\n      --accordion-item-title: var(--text-base);\n      --accordion-item-subtitle-size: var(--text-sm);\n      --accordion-item-body: var(--text-sm);\n    }\n  }\n\n  /* ========================================\n     States\n     ======================================== */\n\n  :host([disabled]) {\n    pointer-events: none;\n    opacity: 0.6;\n  }\n\n  /* ========================================\n     Chevron Animation\n     ======================================== */\n\n  .chevron {\n    --ore-icon-size: var(--_size, var(--size-5));\n    width: var(--_size, var(--size-5));\n    height: var(--_size, var(--size-5));\n\n    margin-inline-start: auto;\n    transform: rotate(-90deg);\n    transition: transform 200ms var(--ease-spring);\n  }\n\n  details[open] .chevron {\n    transform: rotate(0deg);\n  }\n\n  /* RTL Support - use .rtl class added by JavaScript */\n  details.rtl .chevron {\n    transform: rotate(90deg);\n  }\n\n  details.rtl[open] .chevron {\n    transform: rotate(0deg);\n  }\n\n  /* :dir(rtl) is inheritance-driven and crosses the shadow boundary; the ancestor-attribute\n     selectors (html[dir='rtl']/[dir='rtl']) cannot match anything inside this shadow root and\n     were removed. */\n  :dir(rtl) .chevron {\n    transform: rotate(90deg);\n  }\n\n  :dir(rtl) details[open] .chevron {\n    transform: rotate(0deg);\n  }\n\n  /* Expanded state - adjust border radius */\n  :host([expanded]) {\n    --accordion-details-radius: var(--rounded-lg) var(--rounded-lg) 0 0;\n    --accordion-summary-radius: 0 0 var(--rounded-lg) var(--rounded-lg);\n  }\n\n  @media (forced-colors: active) {\n    /* Default variant uses a transparent border — ensure a visible border\n         renders in HCM so the summary is distinguishable from the body */\n    summary {\n      border-color: ButtonText;\n    }\n  }\n}\n","import { define, getHost, html, inject, onMounted, prop, ref, useEmit, watchEffect } from '@vielzeug/ore';\n\nimport type { ComponentSize, SurfaceVariant } from '../../types';\n\nimport '../../content/icon/icon';\nimport { elementDirection } from '../../core/direction';\nimport { disablableBundle } from '../../shared';\nimport { coarsePointerMixin } from '../../styles';\nimport { ACCORDION_CTX } from '../accordion/accordion';\nimport styles from './accordion-item.css?inline';\n\n/** Accordion item component properties */\n\nexport type OreAccordionItemEvents = {\n  collapse: { expanded: boolean; item: HTMLElement };\n  expand: { expanded: boolean; item: HTMLElement };\n};\n\nexport type OreAccordionItemProps = {\n  /** Disable accordion item interaction */\n  disabled?: boolean;\n  /** Whether the item is expanded/open */\n  expanded?: boolean;\n  /** Item size */\n  size?: ComponentSize;\n  /** Visual style variant */\n  variant?: SurfaceVariant;\n};\n\n/**\n * An individual accordion item with expand/collapse functionality using native details/summary.\n *\n * @element ore-accordion-item\n *\n * @attr {boolean} expanded - Whether the item is expanded/open\n * @attr {boolean} disabled - Disable accordion item interaction\n * @attr {string} size - Item size: 'sm' | 'md' | 'lg'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'text' | 'glass' | 'frost'\n *\n * @fires expand - Emitted when item expands. detail: { expanded: boolean; item: HTMLElement }\n * @fires collapse - Emitted when item collapses. detail: { expanded: boolean; item: HTMLElement }\n *\n * @slot prefix - Content before the title (e.g., icons)\n * @slot title - Main accordion item title\n * @slot subtitle - Optional subtitle text\n * @slot suffix - Content after the title (e.g., badges)\n * @slot - Accordion item content (shown when expanded)\n *\n * @cssprop --accordion-item-bg - Background color\n * @cssprop --accordion-item-hover-bg - Background color on hover\n * @cssprop --accordion-item-border-color - Border color\n * @cssprop --accordion-item-title-color - Title text color\n * @cssprop --accordion-item-subtitle-color - Subtitle text color\n * @cssprop --accordion-item-body-color - Body text color\n * @cssprop --accordion-item-radius - Border radius\n * @cssprop --accordion-item-transition - Transition duration\n * @cssprop --accordion-item-title - Title font size\n * @cssprop --accordion-item-subtitle-size - Subtitle font size\n * @cssprop --accordion-item-body - Body font size\n * @cssprop --accordion-item-details-padding - Summary/header padding\n * @cssprop --accordion-item-summary-padding - Content padding\n *\n * @part item - Item root element.\n * @part summary - Summary trigger row.\n * @part header - Header container.\n * @part title - Title text element.\n * @part subtitle - Subtitle text element.\n * @part content - Content container.\n * @example\n * ```html\n * <ore-accordion-item><span slot=\"title\">Click to expand</span><p>Content</p></ore-accordion-item>\n * <ore-accordion-item expanded variant=\"bordered\"><span slot=\"title\">Title</span><p>Content</p></ore-accordion-item>\n * ```\n */\n\nexport const ACCORDION_ITEM_TAG = 'ore-accordion-item' as const;\ndefine<OreAccordionItemProps>(ACCORDION_ITEM_TAG, {\n  props: {\n    ...disablableBundle,\n    expanded: prop.bool(false),\n    size: prop.string<ComponentSize>(),\n    variant: prop.string<SurfaceVariant>(),\n  },\n\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreAccordionItemEvents>();\n    const watch = watchEffect;\n\n    // Inherit size/variant from a parent ore-accordion when present.\n    const accordionCtx = inject(ACCORDION_CTX);\n\n    if (accordionCtx) {\n      watch(() => {\n        const size = accordionCtx.size.value;\n        const variant = accordionCtx.variant.value;\n\n        if (size !== undefined) el.setAttribute('size', size);\n\n        if (variant !== undefined) el.setAttribute('variant', variant);\n      });\n    }\n\n    const titleId = 'accordion-item-title';\n    const detailsRef = ref<HTMLDetailsElement>();\n    const summaryRef = ref<HTMLElement>();\n    let isAnimating = false;\n\n    const openItem = () => {\n      const details = detailsRef.value;\n\n      if (!details || details.open) return;\n\n      details.classList.add('opening');\n      details.open = true;\n\n      el.toggleAttribute('expanded', true);\n      emit('expand', { expanded: true, item: el });\n\n      requestAnimationFrame(() => {\n        const inner = details.querySelector<HTMLElement>('.content-inner');\n\n        if (!inner) {\n          details.classList.remove('opening');\n          isAnimating = false;\n\n          return;\n        }\n\n        const onDone = () => {\n          details.classList.remove('opening');\n          isAnimating = false;\n        };\n        const transitions = inner.getAnimations?.().filter((a) => a instanceof CSSTransition) ?? [];\n\n        if (transitions.length > 0) {\n          Promise.allSettled(transitions.map((a) => a.finished)).then(onDone);\n        } else {\n          onDone();\n        }\n      });\n    };\n\n    const closeItem = () => {\n      const details = detailsRef.value;\n\n      if (!details?.open || isAnimating) return;\n\n      isAnimating = true;\n\n      details.classList.add('closing');\n\n      const inner = details.querySelector<HTMLElement>('.content-inner');\n      const onDone = () => {\n        details.classList.remove('closing');\n        details.open = false;\n        el.toggleAttribute('expanded', false);\n        emit('collapse', { expanded: false, item: el });\n        isAnimating = false;\n      };\n\n      if (inner) {\n        const transitions = inner.getAnimations?.().filter((a) => a instanceof CSSTransition) ?? [];\n\n        if (transitions.length > 0) {\n          Promise.allSettled(transitions.map((a) => a.finished)).then(onDone);\n        } else {\n          onDone();\n        }\n      } else {\n        onDone();\n      }\n    };\n\n    let touchHandled = false;\n    let touchStartY = 0;\n\n    const toggleDetails = () => {\n      if (props.disabled.value) return;\n\n      const details = detailsRef.value;\n\n      if (!details) return;\n\n      if (details.open) {\n        closeItem();\n      } else {\n        openItem();\n      }\n    };\n\n    const handleSummaryTouchStart = (e: TouchEvent) => {\n      touchStartY = e.touches[0]?.clientY ?? 0;\n    };\n\n    const handleSummaryTouchEnd = (e: TouchEvent) => {\n      const dy = Math.abs((e.changedTouches[0]?.clientY ?? 0) - touchStartY);\n\n      if (dy > 10) return;\n\n      e.preventDefault();\n      touchHandled = true;\n      toggleDetails();\n    };\n\n    const handleSummaryClick = (e: Event) => {\n      if (touchHandled) {\n        touchHandled = false;\n        e.preventDefault();\n\n        return;\n      }\n\n      e.preventDefault();\n      toggleDetails();\n    };\n\n    const handleToggle = () => {\n      // Only fires for programmatic open/close (e.g. from accordion parent)\n      const isOpen = detailsRef.value?.open ?? false;\n      const wasExpanded = Boolean(props.expanded.value);\n\n      if (isOpen && !wasExpanded) {\n        el.toggleAttribute('expanded', true);\n        emit('expand', { expanded: true, item: el });\n      } else if (!isOpen && wasExpanded) {\n        el.toggleAttribute('expanded', false);\n        emit('collapse', { expanded: false, item: el });\n      }\n    };\n\n    onMounted(() => {\n      const details = detailsRef.value;\n      const summary = summaryRef.value;\n\n      if (!details || !summary) return;\n\n      // Detect RTL so plain CSS classes can target it (see `elementDirection` for the\n      // ancestor-dir / computed-style resolution rule).\n      const checkRTL = () => {\n        details.classList.toggle('rtl', elementDirection(el) === 'rtl');\n      };\n\n      // Check initially\n      checkRTL();\n\n      // Re-check when `dir` changes on this element's own ancestor chain (not the whole\n      // document — `elementDirection` only ever looks at `el`'s ancestors, so that's all we\n      // need to watch).\n      const observer = new MutationObserver((mutations) => {\n        const dirChanged = mutations.some((m) => m.attributeName === 'dir');\n\n        if (dirChanged) {\n          checkRTL();\n        }\n      });\n\n      for (let ancestor: Element | null = el; ancestor; ancestor = ancestor.parentElement) {\n        observer.observe(ancestor, { attributeFilter: ['dir'], attributes: true });\n      }\n\n      details.addEventListener('toggle', handleToggle);\n      summary.addEventListener('touchstart', handleSummaryTouchStart, { passive: true });\n      summary.addEventListener('touchend', handleSummaryTouchEnd, { passive: false });\n      summary.addEventListener('click', handleSummaryClick);\n\n      return () => {\n        observer.disconnect();\n        details.removeEventListener('toggle', handleToggle);\n        summary.removeEventListener('touchstart', handleSummaryTouchStart);\n        summary.removeEventListener('touchend', handleSummaryTouchEnd);\n        summary.removeEventListener('click', handleSummaryClick);\n      };\n    });\n\n    return html`\n      <details part=\"item\" ?open=\"${props.expanded}\" ref=\"${detailsRef}\">\n        <summary\n          part=\"summary\"\n          aria-expanded=\"${() => String(props.expanded.value)}\"\n          aria-disabled=\"${() => (props.disabled.value ? 'true' : 'false')}\"\n          tabindex=\"${() => (props.disabled.value ? '-1' : null)}\"\n          ref=\"${summaryRef}\">\n          <slot name=\"prefix\"></slot>\n          <div class=\"header-content\" part=\"header\">\n            <span class=\"title\" part=\"title\" id=\"${titleId}\">\n              <slot name=\"title\"></slot>\n            </span>\n            <span class=\"subtitle\" part=\"subtitle\">\n              <slot name=\"subtitle\"></slot>\n            </span>\n          </div>\n          <slot name=\"suffix\"></slot>\n          <ore-icon class=\"chevron\" name=\"chevron-down\" size=\"20\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n        </summary>\n        <div class=\"content-wrapper\" part=\"content\" role=\"region\" aria-labelledby=\"${titleId}\">\n          <div class=\"content-inner\">\n            <slot></slot>\n          </div>\n        </div>\n      </details>\n    `;\n  },\n\n  styles: [coarsePointerMixin, styles],\n});\n","@layer refine.base {\n  :host {\n    --tabs-transition: var(--transition-normal);\n    --tabs-radius: var(--rounded-lg);\n    display: flex;\n    flex-direction: column;\n    width: 100%;\n    height: 100%;\n  }\n\n  .tablist-wrapper {\n    position: relative;\n    flex-shrink: 0;\n  }\n\n  [role='tablist'] {\n    position: relative;\n    display: flex;\n    gap: var(--tabs-tab-gap, var(--size-1));\n    align-items: stretch;\n    overflow-x: auto;\n    scrollbar-width: none;\n  }\n\n  [role='tablist']::-webkit-scrollbar {\n    display: none;\n  }\n\n  .indicator {\n    position: absolute;\n    bottom: 0;\n    left: 0;\n    height: 2px;\n    pointer-events: none;\n    background: var(--tabs-indicator-color, var(--_theme-base));\n    border-radius: var(--rounded-full);\n    transition: transform var(--tabs-transition);\n  }\n\n  .panels {\n    display: flex;\n    flex: 1;\n    flex-direction: column;\n    min-height: 0;\n  }\n}\n\n@layer refine.orientation {\n  /* ─── vertical orientation ─── */\n  :host([orientation='vertical']) {\n    flex-direction: row;\n    align-items: flex-start;\n  }\n\n  :host([orientation='vertical']) .tablist-wrapper {\n    display: flex;\n    flex-shrink: 0;\n  }\n\n  :host([orientation='vertical']) [role='tablist'] {\n    flex-direction: column;\n    width: max-content;\n    overflow-x: unset;\n    overflow-y: auto;\n  }\n\n  :host([orientation='vertical']) .indicator {\n    inset-inline-start: 0;\n    top: 0;\n\n    /* Reposition indicator to inline-start side for vertical */\n    bottom: unset;\n    width: 2px;\n    height: unset;\n    transition: transform var(--tabs-transition);\n  }\n}\n\n@layer refine.variants {\n  /* ─── solid (default) ─── */\n  :host,\n  :host([variant='solid']) {\n    --tabs-tab-gap: var(--size-1);\n    --_tablist-bg: var(--tabs-tablist-bg, var(--color-contrast-100));\n    --_tablist-border-color: var(--tabs-tablist-border-color, var(--color-contrast-200));\n  }\n\n  :host [role='tablist'],\n  :host([variant='solid']) [role='tablist'] {\n    padding: var(--size-1);\n    background: var(--_tablist-bg);\n    border: var(--border) solid var(--_tablist-border-color);\n    border-radius: var(--tabs-radius);\n  }\n\n  :host .indicator,\n  :host([variant='solid']) .indicator {\n    display: none;\n  }\n\n  /* ─── flat ─── */\n  :host([variant='flat']) {\n    --_tablist-border-color: var(--tabs-tablist-border-color, var(--color-contrast-200));\n\n    overflow: hidden;\n    background: var(--tabs-bg, var(--color-contrast-100));\n    border: var(--border) solid var(--_tablist-border-color);\n    border-radius: var(--tabs-radius);\n    box-shadow: var(--inset-shadow-xs), var(--shadow-2xs);\n  }\n\n  :host([variant='flat']) [role='tablist'] {\n    gap: var(--size-1);\n    padding: var(--size-1);\n    background: transparent;\n    border: none;\n    border-bottom: var(--border) solid var(--_tablist-border-color);\n    border-radius: 0;\n  }\n\n  :host([variant='flat']) .indicator {\n    display: none;\n  }\n\n  /* ─── bordered ─── */\n  :host([variant='bordered']) {\n    --_tablist-border-color: var(--tabs-tablist-border-color, var(--color-contrast-200));\n  }\n\n  :host([variant='bordered']) [role='tablist'] {\n    gap: var(--size-1);\n    padding: var(--size-1);\n    background: transparent;\n    border: var(--border) solid var(--_tablist-border-color);\n    border-bottom: none;\n    border-radius: var(--tabs-radius) var(--tabs-radius) 0 0;\n  }\n\n  :host([variant='bordered']) .indicator {\n    display: none;\n  }\n\n  :host([variant='bordered']) .panels {\n    border: var(--border) solid var(--_tablist-border-color);\n    border-radius: 0 0 var(--tabs-radius) var(--tabs-radius);\n  }\n\n  :host([variant='bordered'][orientation='vertical']) [role='tablist'] {\n    border-right: none;\n    border-bottom: var(--border) solid var(--_tablist-border-color);\n    border-radius: var(--tabs-radius) 0 0 var(--tabs-radius);\n  }\n\n  :host([variant='bordered'][orientation='vertical']) .panels {\n    border-radius: 0 var(--tabs-radius) var(--tabs-radius) 0;\n  }\n\n  /* ─── ghost ─── */\n  :host([variant='ghost']) [role='tablist'] {\n    gap: var(--size-1);\n    padding: 0;\n    background: transparent;\n    border: none;\n    border-radius: 0;\n  }\n\n  :host([variant='ghost']) .indicator {\n    display: none;\n  }\n\n  /* ─── glass ─── */\n  :host([variant='glass']) {\n    --_tablist-bg: var(--tabs-tablist-bg, color-mix(in oklch, var(--color-secondary) 20%, transparent));\n    --_tablist-border-color: var(\n      --tabs-tablist-border-color,\n      color-mix(in oklch, var(--color-secondary-contrast) 15%, transparent)\n    );\n  }\n\n  :host([variant='glass']) [role='tablist'] {\n    padding: var(--size-1);\n    background: var(--_tablist-bg);\n    border: var(--border) solid var(--_tablist-border-color);\n    border-radius: var(--tabs-radius);\n    box-shadow: var(--shadow-md), var(--inset-shadow-xs);\n    backdrop-filter: blur(var(--blur-lg)) saturate(180%) brightness(1.05);\n  }\n\n  :host([variant='glass']) .indicator {\n    display: none;\n  }\n\n  /* ─── frost ─── */\n  :host([variant='frost']) {\n    --_tablist-bg: var(--tabs-tablist-bg, color-mix(in oklch, var(--color-canvas) 55%, transparent));\n    --_tablist-border-color: var(\n      --tabs-tablist-border-color,\n      color-mix(in oklch, var(--color-contrast-300) 50%, transparent)\n    );\n  }\n\n  :host([variant='frost']) [role='tablist'] {\n    padding: var(--size-1);\n    background: var(--_tablist-bg);\n    border: var(--border) solid var(--_tablist-border-color);\n    border-radius: var(--tabs-radius);\n    box-shadow: var(--shadow-md), var(--inset-shadow-xs);\n    backdrop-filter: blur(var(--blur-lg)) saturate(180%);\n  }\n\n  :host([variant='frost']) .indicator {\n    display: none;\n  }\n}\n","import {\n  bind,\n  createContext,\n  define,\n  getHost,\n  html,\n  onCleanup,\n  onMounted,\n  prop,\n  provide,\n  ref,\n  useEmit,\n} from '@vielzeug/ore';\nimport { computed, type Readable, signal, watch } from '@vielzeug/ripple';\nimport { createInteraction, createListControl, elementDirection, lifecycleSignal } from '../../core';\nimport { sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin } from '../../styles';\nimport type { ComponentSize, SurfaceVariant, ThemeColor } from '../../types';\nimport styles from './tabs.css?inline';\n\n/** Context provided by ore-tabs to its ore-tab-item and ore-tab-panel children. */\nexport type TabsContext = {\n  color: Readable<ThemeColor | undefined>;\n  orientation: Readable<'horizontal' | 'vertical'>;\n  size: Readable<ComponentSize | undefined>;\n  value: Readable<string | undefined>;\n  variant: Readable<SurfaceVariant | undefined>;\n};\n/** Injection key for the tabs context. */\nexport const TABS_CTX = createContext<TabsContext>('TabsContext');\n\nexport type OreTabsEvents = {\n  change: { value: string };\n};\n\nexport type OreTabsProps = {\n  /**\n   * Keyboard activation mode.\n   * - `'auto'` (default): Selecting a tab on arrow-key focus immediately activates it (ARIA recommendation for most cases).\n   * - `'manual'`: Arrow keys only move focus; the user must press Enter or Space to activate the focused tab.\n   */\n  activation?: 'auto' | 'manual';\n  /** Theme color */\n  color?: ThemeColor;\n  /** Accessible label for the tablist (passed as aria-label). Use when there is no visible heading labelling the tabs. */\n  label?: string;\n  /** Tab list orientation */\n  orientation?: 'horizontal' | 'vertical';\n  /** Component size */\n  size?: ComponentSize;\n  /** Currently selected tab value */\n  value?: string;\n  /** Visual style variant */\n  variant?: SurfaceVariant;\n};\n\n/**\n * Tabs container. Manages tab selection and syncs state to child tab items and panels.\n *\n * @element ore-tabs\n * @element ore-tab-item - Child element for tab buttons (auto-discovered)\n * @element ore-tab-panel - Child element for tab content (auto-discovered)\n *\n * @attr {string} value - The value of the currently selected tab\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'ghost' | 'glass' | 'frost'\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n *\n * @fires change - Emitted when the active tab changes with detail: { value: string }\n *\n * @slot tabs - Place `ore-tab-item` elements here\n * @slot - Place `ore-tab-panel` elements here\n *\n * @cssprop --tabs-radius - Border radius of the tablist container and panels\n * @cssprop --tabs-transition - Transition duration/easing for the active indicator\n * @cssprop --tabs-indicator-color - Color of the sliding active indicator line\n * @cssprop --tabs-bg - Background of the host element (flat variant)\n * @cssprop --tabs-tablist-bg - Tablist container background (solid/glass/frost variants)\n * @cssprop --tabs-tablist-border-color - Tablist container border color\n * @part tablist - Container that holds the slotted tab items\n * @part indicator - Active tab indicator element\n * @part panels - Container that holds tab panel content\n * @example\n * ```html\n * <ore-tabs value=\"tab1\" variant=\"bordered\">\n *   <ore-tab-item slot=\"tabs\" value=\"tab1\">Overview</ore-tab-item>\n *   <ore-tab-item slot=\"tabs\" value=\"tab2\">Settings</ore-tab-item>\n *   <ore-tab-panel value=\"tab1\"><p>Overview content</p></ore-tab-panel>\n *   <ore-tab-panel value=\"tab2\"><p>Settings content</p></ore-tab-panel>\n * </ore-tabs>\n * ```\n */\nexport const TABS_TAG = 'ore-tabs' as const;\ndefine<OreTabsProps>(TABS_TAG, {\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    activation: prop.oneOf(['auto', 'manual'] as const, 'auto'),\n    label: prop.string(),\n    orientation: prop.oneOf(['horizontal', 'vertical'] as const, 'horizontal'),\n    value: prop.string(),\n    variant: prop.string<SurfaceVariant>(),\n  },\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreTabsEvents>();\n\n    const shadowRoot = el.shadowRoot;\n    const tablistRef = ref<HTMLElement>();\n    const indicatorRef = ref<HTMLElement>();\n    const selectedValue = signal<string | undefined>(props.value.value);\n    const isManualActivation = () => props.activation.value === 'manual';\n    const isVertical = () => props.orientation.value === 'vertical';\n\n    bind({\n      attr: {\n        value: () => selectedValue.value ?? null,\n      },\n    });\n\n    const getTabs = () => [...el.querySelectorAll<HTMLElement>(':scope > ore-tab-item[slot=\"tabs\"]')];\n    const getEnabledTabs = () => getTabs().filter((t) => !t.hasAttribute('disabled'));\n    const focusTab = (tab: HTMLElement | undefined) => {\n      if (!tab) return;\n\n      const focusable = tab.shadowRoot?.querySelector<HTMLElement>('[role=\"tab\"]') ?? tab;\n\n      focusable.focus();\n    };\n\n    // ────────────────────────────────────────────────────────────────\n    // Selection State Management\n    // ────────────────────────────────────────────────────────────────\n\n    const setSelection = (value: string | undefined, shouldEmit = false) => {\n      selectedValue.value = value;\n\n      if (shouldEmit && value) emit('change', { value });\n    };\n\n    const ensureSelection = () => {\n      const tabs = getTabs();\n\n      if (tabs.length === 0) return; // No tabs yet, keep current selection\n\n      const current = selectedValue.value;\n      const hasCurrent = current\n        ? tabs.some((tab) => tab.getAttribute('value') === current && !tab.hasAttribute('disabled'))\n        : false;\n\n      if (hasCurrent) return;\n\n      const firstEnabled = tabs.find((tab) => !tab.hasAttribute('disabled'))?.getAttribute('value') ?? undefined;\n\n      setSelection(firstEnabled, false);\n    };\n\n    watch(props.value, (value) => {\n      selectedValue.value = value;\n      ensureSelection();\n    });\n\n    // ────────────────────────────────────────────────────────────────\n    // List Control for Keyboard Navigation\n    // ────────────────────────────────────────────────────────────────\n\n    const listControl = createListControl({\n      direction: () => elementDirection(el),\n      getItems: () => getEnabledTabs(),\n      loop: true,\n      onNavigate: ({ item }) => {\n        focusTab(item);\n\n        if (!isManualActivation()) {\n          const value = item.getAttribute('value');\n\n          if (value) setSelection(value, true);\n        }\n      },\n      orientation: () => (isVertical() ? 'vertical' : 'both'),\n      signal: lifecycleSignal(onCleanup),\n    });\n\n    // ────────────────────────────────────────────────────────────────\n    // Context & Indicator Management\n    // ────────────────────────────────────────────────────────────────\n\n    provide(TABS_CTX, {\n      color: props.color,\n      orientation: computed(() => props.orientation.value ?? 'horizontal'),\n      size: props.size,\n      value: selectedValue,\n      variant: props.variant,\n    });\n\n    const moveIndicator = (activeTab: HTMLElement | undefined) => {\n      const indicator = indicatorRef.value;\n      const tablist = tablistRef.value;\n\n      if (!indicator || !tablist || !activeTab) return;\n\n      const tabRect = activeTab.getBoundingClientRect();\n      const listRect = tablist.getBoundingClientRect();\n\n      if (isVertical()) {\n        const y = tabRect.top - listRect.top + tablist.scrollTop;\n\n        indicator.style.transition = 'none';\n        indicator.style.height = `${tabRect.height}px`;\n        indicator.style.width = '';\n        indicator.style.left = '0';\n        indicator.style.top = '0';\n        void indicator.offsetWidth;\n        indicator.style.transition = '';\n        indicator.style.transform = `translateY(${y}px)`;\n      } else {\n        const x = tabRect.left - listRect.left + tablist.scrollLeft;\n\n        indicator.style.transition = 'none';\n        indicator.style.width = `${tabRect.width}px`;\n        indicator.style.height = '';\n        indicator.style.top = '';\n        indicator.style.left = '0';\n        void indicator.offsetWidth;\n        indicator.style.transition = '';\n        indicator.style.transform = `translateX(${x}px)`;\n      }\n    };\n\n    const updateIndicator = () => {\n      const value = selectedValue.value;\n\n      if (!value) return;\n\n      const activeTab = getTabs().find((t) => t.getAttribute('value') === value);\n\n      moveIndicator(activeTab);\n    };\n\n    watch(selectedValue, () => {\n      requestAnimationFrame(updateIndicator);\n    });\n\n    // ────────────────────────────────────────────────────────────────\n    // Event Handlers\n    // ────────────────────────────────────────────────────────────────\n\n    const handleTabClick = (e: Event) => {\n      const tab = e\n        .composedPath()\n        .find((node): node is HTMLElement => node instanceof HTMLElement && node.localName === 'ore-tab-item');\n\n      if (!tab || tab.hasAttribute('disabled')) return;\n\n      // Guard: only respond to tab-items that belong to THIS tabs instance\n      if (tab.closest('ore-tabs') !== el) return;\n\n      const value = tab.getAttribute('value');\n\n      if (!value || value === selectedValue.value) return;\n\n      setSelection(value, true);\n    };\n\n    const activateFocusedTab = (): void => {\n      const tabs = getEnabledTabs();\n      const focusedTab = tabs.find(\n        (tab) => tab === document.activeElement || tab.shadowRoot?.activeElement === document.activeElement,\n      );\n      const focusedValue = focusedTab?.getAttribute('value');\n\n      if (focusedValue && focusedValue !== selectedValue.value) setSelection(focusedValue, true);\n    };\n\n    const manualActivationPress = createInteraction({\n      disabled: computed(() => !isManualActivation()),\n      onPress: activateFocusedTab,\n    });\n\n    const handleKeydown = (e: KeyboardEvent) => {\n      const tabs = getEnabledTabs();\n\n      if (tabs.length === 0) return;\n\n      const path = e.composedPath();\n      const activeTabFromEvent = path.find(\n        (node): node is HTMLElement => node instanceof HTMLElement && node.localName === 'ore-tab-item',\n      );\n\n      const tabFromEvent = activeTabFromEvent ?? tabs.find((t) => t.getAttribute('value') === selectedValue.value);\n      const focused = tabFromEvent ? tabs.indexOf(tabFromEvent) : -1;\n\n      if (focused >= 0) listControl.set(focused);\n\n      if (listControl.handleKeydown(e)) return;\n\n      manualActivationPress.handleKeydown(e);\n    };\n\n    bind({\n      on: {\n        click: handleTabClick,\n        keydown: handleKeydown,\n      },\n    });\n\n    // ────────────────────────────────────────────────────────────────\n    // Lifecycle\n    // ────────────────────────────────────────────────────────────────\n\n    onMounted(() => {\n      const syncSelection = () => {\n        ensureSelection();\n        updateIndicator();\n      };\n\n      const tabsSlot = shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"tabs\"]');\n\n      if (tabsSlot) {\n        tabsSlot.addEventListener('slotchange', syncSelection);\n      }\n\n      syncSelection();\n      requestAnimationFrame(syncSelection);\n\n      return () => {\n        if (tabsSlot) {\n          tabsSlot.removeEventListener('slotchange', syncSelection);\n        }\n      };\n    });\n\n    return html`\n      <div class=\"tablist-wrapper\">\n        <div\n          role=\"tablist\"\n          ref=\"${tablistRef}\"\n          part=\"tablist\"\n          aria-orientation=\"${props.orientation}\"\n          aria-label=\"${props.label}\">\n          <slot name=\"tabs\"></slot>\n        </div>\n        <div class=\"indicator\" ref=\"${indicatorRef}\" part=\"indicator\"></div>\n      </div>\n      <div class=\"panels\" part=\"panels\">\n        <slot></slot>\n      </div>\n    `;\n  },\n  styles: [colorThemeMixin, styles],\n});\n","@layer refine.base {\n  :host {\n    --tab-item-transition: var(--transition-normal);\n    --tab-item-radius: var(--rounded-lg);\n    display: inline-flex;\n    outline: none;\n  }\n\n  button {\n    position: relative;\n    display: inline-flex;\n    gap: var(--size-2);\n    align-items: center;\n    justify-content: center;\n    width: 100%;\n    min-height: var(--_touch-target);\n    padding: var(--tab-item-padding, var(--size-1-5) var(--size-4));\n    font-family: inherit;\n    font-size: var(--tab-item-font-size, var(--text-sm));\n    font-weight: var(--font-medium);\n    color: var(--tab-item-color, var(--text-color-secondary));\n    white-space: nowrap;\n    cursor: pointer;\n    user-select: none;\n    background: transparent;\n    border: none;\n    border-radius: var(--tab-item-radius);\n    transition:\n      background var(--tab-item-transition),\n      color var(--tab-item-transition),\n      box-shadow var(--tab-item-transition);\n  }\n\n  button:focus {\n    outline: none;\n  }\n\n  :host(:focus-visible) button,\n  button:focus-visible {\n    outline: var(--border-2) solid var(--_theme-focus);\n    outline-offset: 2px;\n    box-shadow: 0 0 0 3px var(--_theme-shadow);\n  }\n}\n\n@layer refine.variants {\n  /* ─── solid / default ─── */\n  :host,\n  :host([variant='solid']) {\n    --_hover-bg: var(--tab-item-hover-bg, var(--color-contrast-200));\n    --_active-bg: var(--tab-item-active-bg, var(--color-contrast-0, var(--color-canvas)));\n    --_active-color: var(--tab-item-active-color, var(--text-color-heading));\n    --_active-shadow: var(--tab-item-active-shadow, var(--shadow-xs), var(--inset-shadow-xs));\n  }\n\n  /* ─── flat ─── */\n  :host([variant='flat']) {\n    --_hover-bg: var(--tab-item-hover-bg, var(--color-contrast-200));\n    --_active-bg: var(--tab-item-active-bg, var(--color-contrast-0, var(--color-canvas)));\n    --_active-color: var(--tab-item-active-color, var(--text-color-heading));\n    --_active-shadow: var(--tab-item-active-shadow, var(--shadow-xs), var(--inset-shadow-xs));\n  }\n\n  /* ─── bordered ─── */\n  :host([variant='bordered']) {\n    --_hover-bg: var(--tab-item-hover-bg, var(--color-contrast-200));\n    --_active-bg: var(--tab-item-active-bg, var(--color-contrast-0, var(--color-canvas)));\n    --_active-color: var(--tab-item-active-color, var(--text-color-heading));\n    --_active-shadow: var(--tab-item-active-shadow, var(--shadow-xs));\n  }\n\n  /* ─── ghost ─── */\n  :host([variant='ghost']) {\n    --_hover-bg: var(--tab-item-hover-bg, var(--color-contrast-100));\n    --_active-bg: var(--tab-item-active-bg, var(--_theme-base));\n    --_active-color: var(--tab-item-active-color, var(--_theme-contrast));\n  }\n\n  /* ─── glass ─── */\n  :host([variant='glass']) {\n    --_color: var(--tab-item-color, color-mix(in oklch, var(--color-secondary-contrast) 70%, transparent));\n    --_hover-bg: var(--tab-item-hover-bg, color-mix(in oklch, var(--color-secondary-contrast) 10%, transparent));\n    --_active-bg: var(--tab-item-active-bg, color-mix(in oklch, var(--color-secondary-contrast) 15%, transparent));\n    --_active-color: var(--tab-item-active-color, var(--color-secondary-contrast));\n    --_active-shadow: var(--tab-item-active-shadow, var(--shadow-xs), var(--inset-shadow-xs));\n  }\n\n  :host([variant='glass']) button {\n    color: var(--_color);\n    text-shadow: var(--text-shadow-2xs);\n  }\n\n  :host([variant='glass']) button:hover {\n    color: var(--tab-item-active-color, var(--color-secondary-contrast));\n  }\n\n  /* ─── frost ─── */\n  :host([variant='frost']) {\n    --_hover-bg: var(--tab-item-hover-bg, color-mix(in oklch, var(--color-contrast) 10%, transparent));\n    --_active-bg: var(--tab-item-active-bg, color-mix(in oklch, var(--color-canvas) 60%, transparent));\n    --_active-color: var(--tab-item-active-color, var(--text-color-heading));\n    --_active-shadow: var(--tab-item-active-shadow, var(--shadow-xs), var(--inset-shadow-xs));\n  }\n\n  :host([variant='frost']) button {\n    color: var(--text-color-secondary);\n  }\n\n  /* ─── Shared interactive states (read per-variant --_* tokens) ─── */\n\n  :host button:hover {\n    color: var(--tab-item-active-color, var(--text-color-heading));\n    background: var(--_hover-bg);\n  }\n\n  :host([active]) button {\n    color: var(--_active-color);\n    background: var(--_active-bg);\n    box-shadow: var(--_active-shadow);\n  }\n\n  /* ─── sizes ─── */\n  :host([size='sm']) {\n    --tab-item-font-size: var(--text-xs);\n    --tab-item-padding: var(--size-1) var(--size-3);\n  }\n\n  :host(:not([size])),\n  :host([size='md']) {\n    --tab-item-font-size: var(--text-sm);\n    --tab-item-padding: var(--size-1-5) var(--size-4);\n  }\n\n  :host([size='lg']) {\n    --tab-item-font-size: var(--text-base);\n    --tab-item-padding: var(--size-2) var(--size-5);\n  }\n\n  /* ─── coarse pointer: promote one size tier for proportional scaling ─── */\n  @media (pointer: coarse) {\n    :host,\n    :host([size='md']) {\n      --tab-item-font-size: var(--text-base);\n      --tab-item-padding: var(--size-2) var(--size-5);\n    }\n\n    :host([size='sm']) {\n      --tab-item-font-size: var(--text-sm);\n      --tab-item-padding: var(--size-1-5) var(--size-4);\n    }\n  }\n\n  /* ─── disabled ─── */\n  :host([disabled]) {\n    pointer-events: none;\n    opacity: 0.5;\n  }\n\n  @media (forced-colors: active) {\n    /* Ensure focus ring is visible regardless of variant theme color */\n    button:focus-visible {\n      outline: 2px solid Highlight;\n      box-shadow: none;\n    }\n\n    /* Active tab: box-shadow raised indicator is stripped; use outline inste\n         ad so the selected tab remains distinguishable */\n    :host([active]) button {\n      outline: 2px solid Highlight;\n      outline-offset: -2px;\n    }\n  }\n}\n","import { bind, define, getHost, html, inject, onMounted, prop, ref, watchEffect } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport { setAriaReflection } from '../../core';\nimport { disablableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, forcedColorsFocusMixin } from '../../styles';\nimport type { ComponentSize, SurfaceVariant, ThemeColor } from '../../types';\nimport { TABS_CTX } from '../tabs/tabs';\nimport styles from './tab-item.css?inline';\n\nexport type OreTabItemProps = {\n  /** Whether this tab is currently selected (set by ore-tabs) */\n  active?: boolean;\n  /** Theme color (inherited from ore-tabs) */\n  color?: ThemeColor;\n  /** Disable this tab */\n  disabled?: boolean;\n  /** Size (inherited from ore-tabs) */\n  size?: ComponentSize;\n  /** Unique value identifier — must match a ore-tab-panel value */\n  value: string;\n  /** Visual variant (inherited from ore-tabs) */\n  variant?: SurfaceVariant;\n};\n\n/**\n * Individual tab trigger. Must be placed in the `tabs` slot of `ore-tabs`.\n *\n * @element ore-tab-item\n *\n * @attr {string} value - Unique identifier, matches the corresponding ore-tab-panel value\n * @attr {boolean} active - Set by the parent ore-tabs when this tab is selected\n * @attr {boolean} disabled - Prevents selection\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} variant - Inherited from ore-tabs: 'solid' | 'flat' | 'bordered' | 'ghost' | 'glass' | 'frost'\n * @attr {string} color - Inherited from ore-tabs: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n *\n * @slot prefix - Icon or content before the label\n * @slot - Tab label\n * @slot suffix - Badge or count after the label\n *\n * @cssprop --tab-item-radius - Button border radius\n * @cssprop --tab-item-transition - Transition duration/easing\n * @cssprop --tab-item-padding - Button padding\n * @cssprop --tab-item-font-size - Button font size\n * @cssprop --tab-item-color - Default text color\n * @cssprop --tab-item-hover-bg - Background on hover\n * @cssprop --tab-item-active-bg - Background when active/selected\n * @cssprop --tab-item-active-color - Text color when active/selected\n * @cssprop --tab-item-active-shadow - Box shadow when active/selected\n * @part tab - Tab trigger element.\n * @example\n * ```html\n * <ore-tab-item slot=\"tabs\" value=\"overview\">Overview</ore-tab-item>\n * <ore-tab-item slot=\"tabs\" value=\"settings\" disabled>Settings</ore-tab-item>\n * ```\n */\nexport const TAB_ITEM_TAG = 'ore-tab-item' as const;\ndefine<OreTabItemProps>(TAB_ITEM_TAG, {\n  props: {\n    ...disablableBundle,\n    active: prop.bool(false),\n    color: prop.string<ThemeColor>(),\n    size: prop.string<ComponentSize>(),\n    value: prop.string(''),\n    variant: prop.string<SurfaceVariant>(),\n  },\n  setup(props) {\n    const el = getHost();\n    const watch = watchEffect;\n\n    const tabsCtx = inject(TABS_CTX);\n\n    if (tabsCtx) {\n      watch(() => {\n        const color = tabsCtx.color.value;\n        const size = tabsCtx.size.value;\n        const variant = tabsCtx.variant.value;\n\n        if (color !== undefined) el.setAttribute('color', color);\n\n        if (size !== undefined) el.setAttribute('size', size);\n\n        if (variant !== undefined) el.setAttribute('variant', variant);\n      });\n    }\n\n    const isActive = computed(() =>\n      tabsCtx ? !!tabsCtx.value.value && tabsCtx.value.value === props.value.value : props.active.value,\n    );\n    const isDisabled = () => Boolean(props.disabled.value);\n\n    bind({\n      attr: {\n        active: () => (isActive.value ? true : undefined),\n      },\n    });\n\n    const handleClick = (event: MouseEvent) => {\n      event.stopPropagation();\n\n      if (isDisabled()) {\n        event.preventDefault();\n\n        return;\n      }\n\n      el.dispatchEvent(new CustomEvent('click', { bubbles: true, detail: { value: props.value.value } }));\n    };\n\n    const tabId = () => `tab-${props.value.value}`;\n    const buttonRef = ref<HTMLButtonElement>();\n\n    // `aria-controls` as a plain IDREF attribute cannot resolve across shadow-tree boundaries\n    // (the matching `id` lives inside <ore-tab-panel>'s own shadow root) — see\n    // `setAriaReflection()`'s doc comment. Deferred to `onMounted()`: sibling custom elements\n    // (including the peer `<ore-tab-panel>`) connect in tree order within the same synchronous\n    // insertion, so a sibling's shadow content may not exist yet during this element's own\n    // `setup()` — `onMounted()`'s microtask runs after the whole subtree has connected.\n    onMounted(() => {\n      watchEffect(() => {\n        const button = buttonRef.value;\n        const value = props.value.value;\n\n        if (!button) return;\n\n        const tabsEl = value ? el.closest('ore-tabs') : null;\n        const panelEl = tabsEl?.querySelector<HTMLElement>(`:scope > ore-tab-panel[value=\"${value}\"]`);\n        const panel = panelEl?.shadowRoot?.querySelector<HTMLElement>('.panel') ?? null;\n\n        setAriaReflection(button, 'ariaControlsElements', panel ? [panel] : []);\n      });\n    });\n\n    return html`\n      <button\n        role=\"tab\"\n        type=\"button\"\n        part=\"tab\"\n        ref=\"${buttonRef}\"\n        id=\"${tabId}\"\n        aria-selected=\"${isActive}\"\n        tabindex=\"${() => (isActive.value ? '0' : '-1')}\"\n        aria-disabled=\"${isDisabled}\"\n        @click=\"${handleClick}\">\n        <slot name=\"prefix\"></slot>\n        <slot></slot>\n        <slot name=\"suffix\"></slot>\n      </button>\n    `;\n  },\n  styles: [colorThemeMixin, forcedColorsFocusMixin('button'), coarsePointerMixin, styles],\n});\n","@layer refine.base {\n  :host {\n    display: none;\n    width: 100%;\n  }\n\n  :host([active]) {\n    display: flex;\n    flex: 1;\n    flex-direction: column;\n    min-height: 0;\n  }\n\n  .panel {\n    box-sizing: border-box;\n    flex: 1;\n    height: 100%;\n    min-height: 0;\n    padding: var(--tab-panel-padding, var(--size-4));\n    overflow: auto;\n    font-size: var(--tab-panel-font-size, var(--text-sm));\n    color: var(--text-color-body);\n    animation: var(--_motion-animation, tab-panel-in var(--transition-normal) var(--ease-out) both);\n  }\n}\n\n@layer refine.variants {\n  @keyframes tab-panel-in {\n    from {\n      opacity: 0;\n      translate: 0 4px;\n    }\n\n    to {\n      opacity: 1;\n      translate: 0 0;\n    }\n  }\n}\n","import { bind, define, getHost, html, inject, onMounted, prop, ref, styleMap, watchEffect, when } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\n\nimport { setAriaReflection } from '../../core';\nimport { reducedMotionMixin } from '../../styles';\nimport { TABS_CTX } from '../tabs/tabs';\nimport styles from './tab-panel.css?inline';\n\nconst TAB_PANEL_PADDING_PRESET: Record<string, string> = {\n  '2xl': 'var(--size-12)',\n  lg: 'var(--size-6)',\n  md: 'var(--size-4)',\n  none: '0',\n  sm: 'var(--size-2)',\n  xl: 'var(--size-8)',\n  xs: 'var(--size-1)',\n};\n\nexport type OreTabPanelProps = {\n  /** Active state (managed by ore-tabs) */\n  active?: boolean;\n  /** When true, the panel content is not rendered until first activation (preserves resources) */\n  lazy?: boolean;\n  /** Panel padding size: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' (default: 'md' = var(--size-4)) */\n  padding?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n  /** Must match the `value` of its corresponding ore-tab-item */\n  value: string;\n};\n\n/**\n * Content panel for a tab. Shown when its `value` matches the selected tab.\n *\n * @element ore-tab-panel\n *\n * @attr {string} value - Must match the corresponding ore-tab-item value\n * @attr {boolean} active - Toggled by the parent ore-tabs\n * @attr {string} padding - Panel padding: 'none' | 'xs' | 'sm' | 'md' (default) | 'lg' | 'xl' | '2xl'\n *\n * @slot - Panel content\n *\n * @cssprop --tab-panel-padding - Inner padding of the panel content area\n * @cssprop --tab-panel-font-size - Font size of the panel content\n * @part panel - Panel container.\n * @example\n * ```html\n * <ore-tab-panel value=\"overview\"><p>Overview content here</p></ore-tab-panel>\n * <ore-tab-panel value=\"settings\" padding=\"lg\"><p>Large padding</p></ore-tab-panel>\n * <ore-tab-panel value=\"code\" padding=\"none\"><pre>No padding for code</pre></ore-tab-panel>\n * ```\n */\nexport const TAB_PANEL_TAG = 'ore-tab-panel' as const;\ndefine<OreTabPanelProps>(TAB_PANEL_TAG, {\n  props: {\n    active: prop.bool(false),\n    lazy: prop.bool(false),\n    padding: prop.oneOf(['none', 'xs', 'sm', 'md', 'lg', 'xl', '2xl'] as const, 'md'),\n    value: prop.string(''),\n  },\n  setup(props) {\n    const el = getHost();\n    const watch = watchEffect;\n\n    const tabsCtx = inject(TABS_CTX);\n    const isActive = computed(() =>\n      tabsCtx ? !!tabsCtx.value.value && tabsCtx.value.value === props.value.value : props.active.value,\n    );\n\n    bind({\n      attr: {\n        active: () => (isActive.value ? true : undefined),\n      },\n    });\n\n    // Map padding prop to CSS variable\n    const paddingValue = computed(() => {\n      const key = props.padding.value ?? 'md';\n\n      return TAB_PANEL_PADDING_PRESET[key] ?? TAB_PANEL_PADDING_PRESET.md;\n    });\n    // Track whether the panel has ever been active (for lazy rendering)\n    const hasBeenActive = signal(false);\n\n    watch(() => {\n      if (isActive.value) hasBeenActive.value = true;\n    });\n\n    // shouldRender: true if not lazy OR has been active at least once\n    const shouldRender = computed(() => !props.lazy.value || hasBeenActive.value);\n    const panelStyle = styleMap({ '--tab-panel-padding': paddingValue });\n    const panelId = () => `tabpanel-${props.value.value}`;\n    const panelRef = ref<HTMLElement>();\n\n    // `aria-labelledby` as a plain IDREF attribute cannot resolve across shadow-tree boundaries\n    // (the matching `id` lives inside <ore-tab-item>'s own shadow root) — see\n    // `setAriaReflection()`'s doc comment. Deferred to `onMounted()`: sibling custom elements\n    // (including the peer `<ore-tab-item>`) connect in tree order within the same synchronous\n    // insertion, so a sibling's shadow content may not exist yet during this element's own\n    // `setup()` — `onMounted()`'s microtask runs after the whole subtree has connected.\n    onMounted(() => {\n      watch(() => {\n        const panel = panelRef.value;\n        const value = props.value.value;\n\n        if (!panel) return;\n\n        const tabsEl = value ? el.closest('ore-tabs') : null;\n        const tabEl = tabsEl?.querySelector<HTMLElement>(`:scope > ore-tab-item[value=\"${value}\"]`);\n        const button = tabEl?.shadowRoot?.querySelector<HTMLElement>('[role=\"tab\"]') ?? null;\n\n        setAriaReflection(panel, 'ariaLabelledByElements', button ? [button] : []);\n      });\n    });\n\n    return html`\n      <div\n        class=\"panel\"\n        part=\"panel\"\n        role=\"tabpanel\"\n        ref=\"${panelRef}\"\n        id=\"${panelId}\"\n        aria-hidden=\"${() => String(!isActive.value)}\"\n        style=\"${panelStyle}\"\n        tabindex=\"0\">\n        ${when(\n          shouldRender,\n          () => html`\n            <slot></slot>\n          `,\n        )}\n      </div>\n    `;\n  },\n  styles: [reducedMotionMixin, styles],\n});\n","// IMPORTANT: Registration order matters for context injection.\n// Parents must be registered (customElements.define) before children,\n// otherwise inject() cannot find the context when elements upgrade from static HTML.\n\nexport type { AccordionContext, OreAccordionEvents, OreAccordionProps } from './accordion/accordion';\nexport { ACCORDION_CTX, ACCORDION_TAG } from './accordion/accordion';\nexport type { OreAccordionItemEvents, OreAccordionItemProps } from './accordion-item/accordion-item';\nexport { ACCORDION_ITEM_TAG } from './accordion-item/accordion-item';\nexport type { OreTabItemProps } from './tab-item/tab-item';\nexport { TAB_ITEM_TAG } from './tab-item/tab-item';\nexport type { OreTabPanelProps } from './tab-panel/tab-panel';\nexport { TAB_PANEL_TAG } from './tab-panel/tab-panel';\nexport type { OreTabsEvents, OreTabsProps, TabsContext } from './tabs/tabs';\nexport { TABS_CTX, TABS_TAG } from './tabs/tabs';\n","/**\n * Waits for a CSS exit animation or transition to finish, then calls `onDone`.\n *\n * Uses the Web Animations API (`element.getAnimations()`) when available for\n * precise, synchronous detection. Falls back to a single microtask + immediate\n * call when no relevant animations are running (e.g. `prefers-reduced-motion`\n * or overridden styles).\n *\n * @param el   - The element whose animations/transitions to observe.\n * @param onDone - Callback invoked exactly once when all animations end.\n * @param type - `'animation'` (default) or `'transition'`.\n */\nexport function awaitExit(el: Element, onDone: () => void, type: 'animation' | 'transition' = 'animation'): void {\n  // Force a synchronous style recalc so that any CSS class changes applied\n  // immediately before this call (e.g. adding 'closing') are committed and\n  // CSSTransition / CSSAnimation instances appear in getAnimations().\n  // Reading getComputedStyle() is the lightest layout-flush trigger available;\n  // in jsdom it is a no-op stub so test timing is unaffected.\n  if (typeof getComputedStyle === 'function') void getComputedStyle(el).opacity;\n\n  queueMicrotask(() => {\n    const getAnimations = typeof el.getAnimations === 'function' ? () => el.getAnimations() : () => [];\n    const relevant = getAnimations().filter((a) => {\n      if (type === 'animation') return a instanceof CSSAnimation;\n\n      if (type === 'transition') return a instanceof CSSTransition;\n\n      return false;\n    });\n\n    if (relevant.length === 0) {\n      onDone();\n\n      return;\n    }\n\n    let done = false;\n    const finish = () => {\n      if (done) return;\n\n      done = true;\n      onDone();\n    };\n\n    // Resolve when ALL relevant animations are finished or cancelled.\n    Promise.allSettled(relevant.map((a) => a.finished)).then(finish);\n  });\n}\n","@layer refine.base {\n  :host {\n    --_bg: var(--alert-bg, var(--_theme-backdrop));\n    --_color: var(--alert-color, var(--_theme-base));\n    --_border-color: var(--alert-border-color, var(--_theme-border));\n    --_radius: var(--alert-radius, var(--rounded-lg));\n    --_padding: var(--alert-padding, var(--size-4));\n    --_gap: var(--alert-gap, var(--size-3));\n    --_font-size: var(--alert-font-size, var(--text-sm));\n    --_shadow: var(--alert-shadow, var(--shadow-none));\n\n    display: block;\n  }\n\n  .sr-announce {\n    position: absolute;\n    width: 1px;\n    height: 1px;\n    padding: 0;\n    margin: -1px;\n    overflow: hidden;\n    white-space: nowrap;\n    border-width: 0;\n    clip-path: inset(50%);\n  }\n\n  :host([dismissed]) {\n    display: none;\n  }\n\n  :host([dismissing]) {\n    overflow: hidden;\n    pointer-events: none;\n    animation: var(--_motion-animation, ore-alert-exit var(--transition-slow) var(--ease-in-out) forwards);\n  }\n\n  @keyframes ore-alert-exit {\n    0% {\n      /* Use a large enough value to cover any realistic alert height. */\n      max-height: 600px;\n      margin-bottom: var(--size-3);\n      opacity: 1;\n      transform: scaleY(1);\n    }\n\n    60% {\n      opacity: 0;\n      transform: scaleY(0.8);\n    }\n\n    100% {\n      max-height: 0;\n      padding-top: 0;\n      padding-bottom: 0;\n      margin-bottom: 0;\n      opacity: 0;\n      transform: scaleY(0);\n    }\n  }\n\n  .alert {\n    display: grid;\n    grid-template-columns: auto 1fr auto;\n    row-gap: var(--size-1);\n    padding: var(--_padding);\n    overflow: hidden;\n    font-size: var(--_font-size);\n    line-height: var(--leading-normal);\n    color: var(--_color);\n    background: var(--_bg);\n    border: var(--border) solid var(--_border-color);\n    border-radius: var(--_radius);\n    box-shadow: var(--_shadow);\n    transition:\n      background var(--transition-normal),\n      border-color var(--transition-normal),\n      box-shadow var(--transition-normal),\n      color var(--transition-normal);\n  }\n\n  /* ── Icon ──────────────────────────────────────── */\n\n  .icon {\n    display: inline-flex;\n    grid-row: 1;\n    grid-column: 1;\n    align-items: center;\n    align-self: start;\n    justify-content: center;\n    margin-inline-end: var(--_gap);\n  }\n\n  /* Without heading: icon aligns with the body content */\n  .alert:has(.header[hidden]) .icon {\n    align-self: center;\n  }\n\n  .icon[hidden] {\n    display: none;\n  }\n\n  /* ── Header row (heading + meta) ───────────────── */\n\n  .header {\n    display: flex;\n    grid-row: 1;\n    grid-column: 2;\n    gap: var(--size-2);\n    align-items: baseline;\n  }\n\n  .header[hidden] {\n    display: none;\n  }\n\n  .heading {\n    overflow: hidden;\n    text-overflow: ellipsis;\n    font-weight: var(--font-semibold);\n    line-height: var(--leading-normal);\n    white-space: nowrap;\n  }\n\n  .meta {\n    margin-inline-start: auto;\n    font-size: var(--text-xs);\n    white-space: nowrap;\n    opacity: 0.7;\n  }\n\n  :host(:not(:has([slot='meta']))) .meta {\n    display: none;\n  }\n\n  /* ── Body ──────────────────────────────────────── */\n\n  .body {\n    grid-row: 2;\n    grid-column: 1 / -1;\n    min-width: 0;\n    margin-top: var(--size-1);\n  }\n\n  /* Without heading: body moves up to share row with icon and close */\n  .alert:has(.header[hidden]) .body {\n    grid-row: 1;\n    grid-column: 2;\n    margin-top: 0;\n  }\n\n  /* ── Content ───────────────────────────────────── */\n\n  .content {\n    line-height: var(--leading-relaxed);\n  }\n\n  /* ── Actions ───────────────────────────────────── */\n\n  .actions {\n    display: flex;\n    flex-wrap: wrap;\n    grid-row: 3;\n    grid-column: 1 / -1;\n    gap: var(--size-2);\n    margin-top: var(--size-2);\n  }\n\n  /* Without heading: actions move to row 2 */\n  .alert:has(.header[hidden]) .actions {\n    grid-row: 2;\n  }\n\n  .actions[hidden] {\n    display: none;\n  }\n\n  /* Horizontal mode: 4-column grid — icon | body | actions | close */\n  :host([horizontal]) .alert {\n    grid-template-columns: auto 1fr auto auto;\n  }\n\n  :host([horizontal]) .body {\n    grid-row: 1;\n    grid-column: 2;\n    align-self: center;\n    margin-top: 0;\n  }\n\n  :host([horizontal]) .actions:not([hidden]) {\n    flex-wrap: nowrap;\n    grid-row: 1;\n    grid-column: 3;\n    margin-inline-start: var(--_gap);\n    margin-top: 0;\n  }\n\n  :host([horizontal]) .close {\n    grid-column: 4;\n    align-self: center;\n  }\n\n  /* ── Close button ──────────────────────────────── */\n\n  .close {\n    display: inline-flex;\n    grid-row: 1;\n    grid-column: 3;\n    align-items: center;\n    align-self: start;\n    justify-content: center;\n    width: var(--size-5);\n    min-width: var(--_touch-target);\n    height: var(--size-5);\n    min-height: var(--_touch-target);\n    padding: 0;\n    margin-inline-start: var(--_gap);\n    color: inherit;\n    cursor: pointer;\n    background: transparent;\n    border: none;\n    border-radius: var(--rounded-sm);\n    opacity: 0.7;\n    transition:\n      opacity var(--transition-fast),\n      background var(--transition-fast);\n  }\n\n  .close[hidden] {\n    display: none;\n  }\n\n  .close:hover {\n    background: color-mix(in oklch, currentcolor 12%, transparent);\n    opacity: 1;\n  }\n\n  .close:focus-visible {\n    outline: var(--border-2) solid currentcolor;\n    outline-offset: var(--border-2);\n    opacity: 1;\n  }\n\n  /* Accented left border for flat and bordered variants */\n  :host([variant='flat'][accented]) .alert,\n  :host([variant='bordered'][accented]) .alert {\n    border-inline-start-width: var(--border-4, 4px);\n  }\n}\n\n@layer refine.variants {\n  /* Flat (Default) — canvas background, theme-colored border and text */\n  :host(:not([variant])),\n  :host([variant='flat']) {\n    --_bg: var(--alert-bg, var(--color-canvas));\n    --_color: var(--alert-color, var(--_theme-base));\n    --_border-color: var(--alert-border-color, var(--_theme-base));\n    --_shadow: var(--alert-shadow, var(--shadow-none));\n  }\n\n  /* Solid — fully filled with theme color */\n  :host([variant='solid']) {\n    --_bg: var(--alert-bg, var(--_theme-base));\n    --_color: var(--alert-color, var(--_theme-contrast));\n    --_border-color: var(--alert-border-color, var(--_theme-base));\n    --_shadow: var(--alert-shadow, var(--shadow-xs));\n  }\n\n  /* Bordered — tinted background with a subtle themed border */\n  :host([variant='bordered']) {\n    --_bg: var(--alert-bg, color-mix(in oklch, var(--_theme-backdrop), var(--color-canvas)));\n    --_color: var(--alert-color, var(--_theme-base));\n    --_border-color: var(--alert-border-color, color-mix(in oklch, var(--_theme-focus) 30%, transparent));\n    --_shadow: var(--alert-shadow, var(--inset-shadow-2xs));\n  }\n}\n","import { define, getHost, html, prop, useEmit, useSlots } from '@vielzeug/ore';\n\nimport type { ComponentSize, RoundedSize, ThemeColor } from '../../types';\n\nimport '../../content/icon/icon';\nimport { awaitExit } from '../../overlay/shared/await-exit';\nimport { roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport {\n  coarsePointerMixin,\n  colorThemeMixin,\n  forcedColorsMixin,\n  reducedMotionMixin,\n  roundedVariantMixin,\n  sizeVariantMixin,\n} from '../../styles';\nimport componentStyles from './alert.css?inline';\n\nexport type OreAlertEvents = {\n  dismiss: { originalEvent: MouseEvent };\n};\n\nexport type OreAlertProps = {\n  /** Show a left accent border (for flat/bordered variants) */\n  accented?: boolean;\n  /** Theme color */\n  color?: ThemeColor;\n  /** Show a dismissible (×) button */\n  dismissible?: boolean;\n  /** Heading text shown above the content */\n  heading?: string;\n  /** Position action buttons to the right instead of below */\n  horizontal?: boolean;\n  /** Border radius */\n  rounded?: RoundedSize | '';\n  /** Alert size */\n  size?: ComponentSize;\n  /** Visual style variant */\n  variant?: 'solid' | 'flat' | 'bordered';\n};\n\n/**\n * A status/feedback banner with optional heading, icon slot, and dismiss button.\n *\n * @element ore-alert\n *\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual style: 'flat' | 'solid' | 'bordered'\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {string} heading - Bold heading text above the content\n * @attr {boolean} dismissible - Show a close (×) button\n * @attr {boolean} accented - Add a left accent border (flat/bordered only)\n * @attr {boolean} horizontal - Position action buttons to the right instead of below\n *\n * @fires dismiss - Fired when the alert is dismissed. detail: { originalEvent: MouseEvent }\n *\n * @slot - Default slot for the alert message content\n * @slot icon - Icon on the left side\n * @slot meta - Metadata displayed alongside the heading (lighter, right-aligned)\n * @slot actions - Action buttons shown below the message\n *\n * @cssprop --alert-bg - Background color\n * @cssprop --alert-color - Text/icon color\n * @cssprop --alert-border-color - Border color\n * @cssprop --alert-shadow - Box shadow\n * @cssprop --alert-radius - Border radius\n * @cssprop --alert-padding - Padding\n * @cssprop --alert-gap - Gap between icon, body, and close button\n * @cssprop --alert-font-size - Font size\n *\n * @part alert - Alert root container.\n * @part icon - Icon container.\n * @part header - Header container.\n * @part heading - Heading text element.\n * @part meta - Meta text container.\n * @part body - Body content container.\n * @part content - Content container.\n * @part actions - Actions slot container.\n * @part close - Close action control.\n * @example\n * ```html\n * <ore-alert color=\"success\">Your changes have been saved.</ore-alert>\n * <ore-alert color=\"error\" variant=\"solid\" dismissible heading=\"Something went wrong\">\n *   Please try again later.\n * </ore-alert>\n * ```\n */\nexport const ALERT_TAG = 'ore-alert' as const;\ndefine<OreAlertProps>(ALERT_TAG, {\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...roundableBundle,\n    accented: prop.bool(false),\n    dismissible: prop.bool(false),\n    heading: prop.string(),\n    horizontal: prop.bool(false),\n    variant: prop.string<'solid' | 'flat' | 'bordered'>(),\n  },\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreAlertEvents>();\n    const slots = useSlots();\n\n    let announceEl: HTMLElement | null = null;\n\n    const announce = (message: string) => {\n      if (!announceEl) return;\n\n      announceEl.textContent = '';\n      requestAnimationFrame(() => {\n        if (announceEl) announceEl.textContent = message;\n      });\n    };\n\n    const handleDismiss = (e: MouseEvent) => {\n      if (!props.dismissible.value) return;\n\n      el.setAttribute('dismissing', '');\n      awaitExit(el, () => {\n        el.removeAttribute('dismissing');\n        el.setAttribute('dismissed', '');\n        announce('Alert dismissed');\n        emit('dismiss', { originalEvent: e });\n      });\n    };\n\n    const alertRole = () => (props.color.value === 'error' ? 'alert' : 'status');\n\n    return html`\n      <span\n        class=\"sr-announce\"\n        aria-live=\"polite\"\n        aria-atomic=\"true\"\n        ref=\"${(ref: HTMLElement) => {\n          announceEl = ref;\n        }}\"></span>\n      <div class=\"alert\" role=\"${alertRole}\" part=\"alert\">\n        <span class=\"icon\" part=\"icon\" aria-hidden=\"true\" ?hidden=\"${() => !slots.has('icon').value}\">\n          <slot name=\"icon\"></slot>\n        </span>\n        <div class=\"header\" part=\"header\" ?hidden=\"${() => !props.heading.value}\">\n          <span class=\"heading\" part=\"heading\">${props.heading}</span>\n          <span class=\"meta\" part=\"meta\">\n            <slot name=\"meta\"></slot>\n          </span>\n        </div>\n        <div class=\"body\" part=\"body\">\n          <div class=\"content\" part=\"content\">\n            <slot></slot>\n          </div>\n        </div>\n        <div class=\"actions\" part=\"actions\" ?hidden=\"${() => !slots.has('actions').value}\">\n          <slot name=\"actions\"></slot>\n        </div>\n        <button\n          class=\"close\"\n          part=\"close\"\n          type=\"button\"\n          aria-label=\"Dismiss alert\"\n          ?hidden=\"${() => !props.dismissible.value}\"\n          @click=\"${handleDismiss}\">\n          <ore-icon name=\"x\" size=\"16\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n        </button>\n      </div>\n    `;\n  },\n  styles: [\n    colorThemeMixin,\n    coarsePointerMixin,\n    reducedMotionMixin,\n    roundedVariantMixin,\n    forcedColorsMixin,\n    sizeVariantMixin({\n      lg: { '--_padding': 'var(--size-4) var(--size-5)', fontSize: 'var(--text-base)', gap: 'var(--size-3-5)' },\n      sm: { '--_padding': 'var(--size-2) var(--size-3)', fontSize: 'var(--text-xs)', gap: 'var(--size-2)' },\n    }),\n    componentStyles,\n  ],\n});\n","@layer refine.base {\n  :host {\n    --_color: var(--async-color, var(--color-contrast-500));\n    --_icon-size: var(--async-icon-size, var(--size-12));\n    --_gap: var(--async-gap, var(--size-3));\n\n    display: block;\n  }\n\n  /* ── Status regions ─────────────────────────────────────────────── */\n\n  /* All regions always exist in the shadow DOM; only one is visible at a time. */\n  .region {\n    display: none;\n  }\n\n  :host([status='idle']) .region-idle,\n  :host([status='loading']) .region-loading,\n  :host([status='empty']) .region-empty,\n  :host([status='error']) .region-error,\n  :host([status='success']) .region-success,\n  :host(:not([status])) .region-success {\n    display: block;\n  }\n\n  /* ── Empty state ─────────────────────────────────────────────────── */\n\n  .empty-state {\n    display: flex;\n    flex-direction: column;\n    gap: var(--_gap);\n    align-items: center;\n    justify-content: center;\n    padding: var(--size-10) var(--size-6);\n    color: var(--_color);\n    text-align: center;\n  }\n\n  .empty-state .icon {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: var(--_icon-size);\n    height: var(--_icon-size);\n    opacity: 0.4;\n  }\n\n  .empty-state .icon svg {\n    width: 100%;\n    height: 100%;\n  }\n\n  .empty-state .icon ore-icon {\n    display: flex;\n    width: 100%;\n    height: 100%;\n  }\n\n  .empty-state .title {\n    font-size: var(--text-sm);\n    font-weight: var(--font-semibold);\n    color: var(--color-contrast-700);\n  }\n\n  .empty-state .description {\n    max-width: 28ch;\n    font-size: var(--text-sm);\n    line-height: var(--leading-relaxed);\n    opacity: 0.75;\n  }\n\n  /* ── Error state ─────────────────────────────────────────────────── */\n\n  .error-state {\n    display: flex;\n    flex-direction: column;\n    gap: var(--_gap);\n    align-items: center;\n    justify-content: center;\n    padding: var(--size-10) var(--size-6);\n    color: var(--color-error-600);\n    text-align: center;\n  }\n\n  .error-state .icon {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: var(--_icon-size);\n    height: var(--_icon-size);\n    opacity: 0.7;\n  }\n\n  .error-state .icon svg {\n    width: 100%;\n    height: 100%;\n  }\n\n  .error-state .icon ore-icon {\n    display: flex;\n    width: 100%;\n    height: 100%;\n  }\n\n  .error-state .title {\n    font-size: var(--text-sm);\n    font-weight: var(--font-semibold);\n    color: var(--color-error-700);\n  }\n\n  .error-state .description {\n    max-width: 32ch;\n    font-size: var(--text-sm);\n    line-height: var(--leading-relaxed);\n    opacity: 0.85;\n  }\n\n  .error-state .retry-btn {\n    display: inline-flex;\n    gap: var(--size-1-5);\n    align-items: center;\n    padding: var(--size-2) var(--size-4);\n    font-size: var(--text-sm);\n    font-weight: var(--font-medium);\n    color: var(--color-error-700);\n    cursor: pointer;\n    background: none;\n    border: 1px solid currentcolor;\n    border-radius: var(--rounded-md);\n    transition: var(--_motion-transition, background var(--transition-fast), opacity var(--transition-fast));\n  }\n\n  .error-state .retry-btn ore-icon {\n    flex: none;\n  }\n\n  .error-state .retry-btn:hover {\n    background: color-mix(in oklch, var(--color-error-500) 10%, transparent);\n  }\n\n  .error-state .retry-btn:focus-visible {\n    outline: 2px solid var(--color-error-500);\n    outline-offset: 2px;\n  }\n\n  /* ── Loading (fallback skeleton block) ───────────────────────────── */\n\n  .loading-default {\n    display: flex;\n    flex-direction: column;\n    gap: var(--size-2);\n    padding: var(--size-4);\n  }\n}\n","import { bind, define, html, prop, useEmit, when } from '@vielzeug/ore';\nimport { type Readable, signal } from '@vielzeug/ripple';\n\nimport { reducedMotionMixin } from '../../styles';\nimport componentStyles from './async.css?inline';\n\nexport type AsyncStatus = 'idle' | 'loading' | 'empty' | 'error' | 'success';\n\nexport type OreAsyncEvents = {\n  retry: undefined;\n};\n\nexport type OreAsyncProps = {\n  'empty-description'?: string;\n  'empty-label'?: string;\n  'error-description'?: string;\n  'error-label'?: string;\n  retryable?: boolean;\n  status?: AsyncStatus;\n};\n\n/**\n * A container for handling asynchronous states (loading, empty, error, success).\n * Simplifies data fetching UI by providing consistent fallbacks.\n *\n * @element ore-async\n *\n * @attr {string} status - current state: 'idle' | 'loading' | 'empty' | 'error' | 'success' (default: 'success')\n * @attr {boolean} retryable - show retry button in error state (default: false)\n * @attr {string} empty-label - title for empty state (default: 'No content yet')\n * @attr {string} empty-description - optional text for empty state\n * @attr {string} error-label - title for error state (default: 'Something went wrong')\n * @attr {string} error-description - optional text for error state\n *\n * @fires retry - Emitted when the retry button is clicked (no detail payload)\n *\n * @slot - default content shown in 'success' state\n * @slot loading - custom loading UI (overrides default skeletons)\n * @slot empty - custom empty UI (overrides default icon/label)\n * @slot error - custom error UI (overrides default icon/label)\n *\n * @cssprop --async-color - Text/icon color used by default async state content\n * @cssprop --async-gap - Vertical spacing between icon, title, description, and actions\n * @cssprop --async-icon-size - Icon size for built-in loading/empty/error visuals\n * @example\n * ```html\n * <!-- Success state: default slot is shown -->\n * <ore-async status=\"success\">\n *   <ul><li>Item one</li><li>Item two</li></ul>\n * </ore-async>\n *\n * <!-- Loading state: shows skeleton placeholders -->\n * <ore-async status=\"loading\"></ore-async>\n *\n * <!-- Empty state with custom message -->\n * <ore-async status=\"empty\" empty-label=\"No results\" empty-description=\"Try adjusting your filters.\"></ore-async>\n *\n * <!-- Error state with retry button -->\n * <ore-async status=\"error\" retryable error-label=\"Failed to load\" error-description=\"Check your connection.\"></ore-async>\n * ```\n */\nexport const ASYNC_TAG = 'ore-async' as const;\ndefine<OreAsyncProps>(ASYNC_TAG, {\n  props: {\n    'empty-description': prop.string(),\n    'empty-label': prop.string('No content yet'),\n    'error-description': prop.string(),\n    'error-label': prop.string('Something went wrong'),\n    retryable: prop.bool(false),\n    status: prop.oneOf(['idle', 'loading', 'empty', 'error', 'success'] as const, 'success'),\n  },\n  setup(props) {\n    const emit = useEmit<OreAsyncEvents>();\n\n    const hasLoadingSlot = signal(false);\n    const hasEmptySlot = signal(false);\n    const hasErrorSlot = signal(false);\n\n    // Reflect status onto the host so CSS can show/hide each region.\n    // ARIA attributes are driven reactively by bind().\n    bind({\n      attr: {\n        ariaBusy: () => (props.status.value === 'loading' ? 'true' : 'false'),\n        ariaLabel: () => (props.status.value === 'loading' ? 'Loading…' : null),\n        ariaLive: () => (props.status.value === 'error' ? 'assertive' : 'polite'),\n        status: props.status,\n      },\n    });\n\n    const renderText = (className: 'title' | 'description', text: Readable<string | undefined> | undefined) => () =>\n      text?.value\n        ? html`\n            <p class=\"${className}\">${text}</p>\n          `\n        : '';\n\n    // All four regions are always in the shadow DOM — CSS on :host([status=\"…\"])\n    // toggles their visibility. This means:\n    // - No DOM churn on status transitions (no teardown/rebuild of slot elements).\n    // - Live regions are always present, so screen readers announce correctly.\n    // - focus is never lost across status changes.\n    return html`\n      <div class=\"region region-idle\" role=\"presentation\"></div>\n\n      <div class=\"region region-loading\" role=\"status\">\n        <slot\n          name=\"loading\"\n          @slotchange=${(e: Event) => {\n            hasLoadingSlot.value = (e.target as HTMLSlotElement).assignedNodes().length > 0;\n          }}></slot>\n        ${when(\n          hasLoadingSlot,\n          () => html``,\n          () => html`\n            <div class=\"loading-default\" aria-hidden=\"true\">\n              <ore-skeleton variant=\"text\" lines=\"1\" width=\"40%\"></ore-skeleton>\n              <ore-skeleton variant=\"text\" lines=\"3\" width=\"100%\"></ore-skeleton>\n              <ore-skeleton variant=\"text\" lines=\"1\" width=\"60%\"></ore-skeleton>\n            </div>\n          `,\n        )}\n      </div>\n\n      <div class=\"region region-empty\">\n        <slot\n          name=\"empty\"\n          @slotchange=${(e: Event) => {\n            hasEmptySlot.value = (e.target as HTMLSlotElement).assignedNodes().length > 0;\n          }}></slot>\n        ${when(\n          hasEmptySlot,\n          () => html``,\n          () => html`\n            <div class=\"empty-state\" role=\"status\">\n              <div class=\"icon\">\n                <ore-icon name=\"package\" size=\"100%\" stroke-width=\"1.75\" aria-hidden=\"true\"></ore-icon>\n              </div>\n              ${renderText('title', props['empty-label'])} ${renderText('description', props['empty-description'])}\n            </div>\n          `,\n        )}\n      </div>\n\n      <div class=\"region region-error\">\n        <slot\n          name=\"error\"\n          @slotchange=${(e: Event) => {\n            hasErrorSlot.value = (e.target as HTMLSlotElement).assignedNodes().length > 0;\n          }}></slot>\n        ${when(\n          hasErrorSlot,\n          () => html``,\n          () => html`\n            <div class=\"error-state\" role=\"alert\">\n              <div class=\"icon\">\n                <ore-icon name=\"triangle-alert\" size=\"100%\" stroke-width=\"1.75\" aria-hidden=\"true\"></ore-icon>\n              </div>\n              ${renderText('title', props['error-label'])} ${renderText('description', props['error-description'])}\n              ${when(\n                () => Boolean(props.retryable.value),\n                () => html`\n                  <button class=\"retry-btn\" type=\"button\" @click=${() => emit('retry')}>\n                    <ore-icon name=\"refresh-cw\" size=\"1em\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n                    Try again\n                  </button>\n                `,\n              )}\n            </div>\n          `,\n        )}\n      </div>\n\n      <div class=\"region region-success\" role=\"presentation\">\n        <slot></slot>\n      </div>\n    `;\n  },\n  styles: [reducedMotionMixin, componentStyles],\n});\n","@layer refine.base {\n  :host {\n    --_bg: var(--badge-bg, var(--_theme-backdrop));\n    --_color: var(--badge-color, var(--_theme-base));\n    --_border-color: var(--badge-border-color, var(--_theme-border));\n    --_radius: var(--badge-radius, var(--rounded-lg));\n    --_font-size: var(--badge-font-size, var(--text-xs));\n    --_font-weight: var(--badge-font-weight, var(--font-semibold));\n    --_padding-x: var(--badge-padding-x, var(--size-1-5));\n    --_padding-y: var(--badge-padding-y, var(--size-0-5));\n    --_gap: var(--badge-gap, var(--size-1));\n\n    display: inline-flex;\n    vertical-align: middle;\n  }\n\n  .badge {\n    display: inline-flex;\n    gap: var(--_gap);\n    align-items: center;\n    justify-content: center;\n\n    /* Dot-only (no text slot) gets circular shape */\n    min-width: var(--size-2);\n    max-width: var(--badge-max-width, 24ch);\n    padding: var(--_padding-y) var(--_padding-x);\n    overflow: hidden;\n    text-overflow: ellipsis;\n    font-size: var(--_font-size);\n    font-weight: var(--_font-weight);\n    line-height: 1;\n    color: var(--_color);\n    white-space: nowrap;\n    background: var(--_bg);\n    border: var(--border) solid var(--_border-color);\n    border-radius: var(--_radius);\n  }\n\n  .badge-label {\n    min-width: 0;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n  }\n\n  ::slotted([slot='icon']) {\n    display: inline-flex;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    width: 1em;\n    height: 1em;\n  }\n}\n\n@layer refine.variants {\n  /* Solid (Default) - Full theme color background */\n  :host(:not([variant])),\n  :host([variant='solid']) {\n    --_bg: var(--badge-bg, var(--_theme-base));\n    --_color: var(--badge-color, var(--_theme-contrast));\n    --_border-color: var(--badge-border-color, var(--_theme-base));\n  }\n\n  /* Flat - Subtle background with theme color text */\n  :host([variant='flat']) {\n    --_bg: var(--badge-bg, color-mix(in oklch, var(--_theme-backdrop) 25%, var(--color-contrast-100)));\n    --_color: var(--badge-color, var(--_theme-base));\n    --_border-color: var(--badge-border-color, color-mix(in oklch, var(--_theme-focus) 20%, transparent));\n  }\n\n  /* Bordered - Outlined with filled background */\n  :host([variant='bordered']) {\n    --_bg: var(--badge-bg, var(--_theme-backdrop));\n    --_color: var(--badge-color, var(--_theme-base));\n    --_border-color: var(--badge-border-color, var(--_theme-border));\n  }\n\n  /* Outline - Transparent with colored border */\n  :host([variant='outline']) {\n    --_bg: var(--badge-bg, transparent);\n    --_color: var(--badge-color, var(--_theme-base));\n    --_border-color: var(--badge-border-color, var(--_theme-base));\n  }\n\n  /* Dot-only mode */\n  :host([dot]) .badge {\n    min-width: unset;\n    padding: var(--_dot-padding, var(--size-1));\n    line-height: 0;\n  }\n}\n\n@layer refine.sizes {\n  :host([size='xs']) {\n    --_padding-x: var(--size-1);\n    --_padding-y: 0px;\n    --_font-size: var(--text-2xs);\n    --_dot-padding: var(--size-0-5);\n  }\n}\n\n@layer refine.overrides {\n  /* Dot — always force badge background and border regardless of variant */\n  :host([dot]) {\n    --_bg: var(--badge-bg, var(--_theme-base));\n    --_border-color: var(--badge-border-color, var(--_theme-base));\n  }\n\n  /* ========================================\n       Anchor overlay mode\n       ======================================== */\n\n  :host([anchor]) {\n    position: relative;\n    display: inline-flex;\n  }\n\n  /*\n     * Per-direction multiplier: +1 in LTR, -1 in RTL.\n     * Used to flip the translateX offset so the badge always overflows\n     * the correct physical edge that corresponds to its logical corner.\n     */\n  :host {\n    --_dir: 1;\n  }\n\n  :host(:dir(rtl)) {\n    --_dir: -1;\n  }\n\n  /* Default position: top-end */\n  :host([anchor]) .badge {\n    position: absolute;\n    inset-inline-end: 0;\n    top: 0;\n    z-index: 1;\n    transform: translate(calc(var(--_dir) * 30%), -30%);\n  }\n\n  :host([anchor='top-start']) .badge {\n    inset-inline-start: 0;\n    inset-inline-end: unset;\n    transform: translate(calc(var(--_dir) * -30%), -30%);\n  }\n\n  :host([anchor='bottom-end']) .badge {\n    top: unset;\n    bottom: 0;\n    transform: translate(calc(var(--_dir) * 30%), 30%);\n  }\n\n  :host([anchor='bottom-start']) .badge {\n    inset-inline-start: 0;\n    inset-inline-end: unset;\n    top: unset;\n    bottom: 0;\n    transform: translate(calc(var(--_dir) * -30%), 30%);\n  }\n}\n","import { define, html, prop } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport { roundableBundle, themableBundle } from '../../shared';\nimport {\n  colorThemeMixin,\n  forcedColorsMixin,\n  frostVariantMixin,\n  roundedVariantMixin,\n  sizeVariantMixin,\n} from '../../styles';\nimport type { RoundedSize, ThemeColor, VisualVariant } from '../../types';\nimport componentStyles from './badge.css?inline';\n\ntype BadgeVariant = Extract<VisualVariant, 'solid' | 'flat' | 'bordered' | 'outline' | 'frost'>;\ntype BadgeSize = 'xs' | 'sm' | 'md' | 'lg';\n\n/** Badge component properties */\nexport type OreBadgeProps = {\n  /**\n   * When set, switches to overlay mode: the host becomes `position:relative`\n   * and the badge pins to a corner over the slotted content.\n   * Value controls which corner: 'top-end' (default) | 'top-start' | 'bottom-end' | 'bottom-start'\n   */\n  anchor?: 'top-end' | 'top-start' | 'bottom-end' | 'bottom-start';\n  /** Theme color */\n  color?: ThemeColor;\n  /** Numeric count to display */\n  count?: number;\n  /** Render as a small dot with no label */\n  dot?: boolean;\n  /** Accessible label for assistive technology. Recommended for count-only and dot mode. */\n  label?: string;\n  /** Max count — displays \"<max>+\" when count exceeds this value */\n  max?: number;\n  /** Border radius override */\n  rounded?: RoundedSize;\n  /** Badge size */\n  size?: BadgeSize;\n  /** Visual style variant */\n  variant?: BadgeVariant;\n};\n\n/**\n * A compact badge/chip for counts, statuses, and labels.\n * Supports numeric counts with overflow, dot mode, and icon slots.\n *\n * @element ore-badge\n *\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'frost'\n * @attr {string} size - Component size: 'xs' | 'sm' | 'md' | 'lg'\n * @attr {number} count - Numeric count to display\n * @attr {number} max - Max count before showing \"<max>+\"\n * @attr {boolean} dot - Render as a dot indicator (no text)\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'full' etc.\n *\n * @slot - Badge label text\n * @slot icon - Icon displayed before the label\n * @slot target - Element the badge is anchored to (used with the anchor attribute)\n *\n * @cssprop --badge-bg - Badge background color\n * @cssprop --badge-color - Badge text color\n * @cssprop --badge-border-color - Badge border color\n * @cssprop --badge-radius - Border radius\n * @cssprop --badge-font-size - Font size\n * @cssprop --badge-font-weight - Font weight\n * @cssprop --badge-padding-x - Horizontal padding\n * @cssprop --badge-padding-y - Vertical padding\n * @cssprop --badge-gap - Gap between icon and label\n *\n * @part badge - Shadow part for the `badge` element.\n * @example\n * ```html\n * <ore-badge color=\"primary\">New</ore-badge>\n * <ore-badge color=\"error\" count=\"5\"></ore-badge>\n * <ore-badge color=\"error\" count=\"120\" max=\"99\"></ore-badge>\n * <ore-badge color=\"success\" dot></ore-badge>\n * <ore-badge color=\"warning\" variant=\"flat\">Beta</ore-badge>\n * ```\n */\nexport const BADGE_TAG = 'ore-badge' as const;\ndefine<OreBadgeProps>(BADGE_TAG, {\n  props: {\n    ...themableBundle,\n    size: prop.string<BadgeSize>(),\n    ...roundableBundle,\n    anchor: prop.string<'top-end' | 'top-start' | 'bottom-end' | 'bottom-start'>(),\n    count: prop.number(),\n    dot: prop.bool(false),\n    label: prop.string(),\n    max: prop.number(),\n    variant: prop.string<BadgeVariant>(),\n  },\n  setup(props) {\n    const label = computed(() => {\n      const count = props.count.value != null ? Number(props.count.value) : undefined;\n      const max = props.max.value != null ? Number(props.max.value) : undefined;\n\n      if (count === undefined || Number.isNaN(count)) return undefined;\n\n      if (max !== undefined && !Number.isNaN(max) && count > max) return `${max}+`;\n\n      return String(count);\n    });\n\n    const ariaLabel = computed(() => {\n      if (props.label.value) return props.label.value;\n\n      if (props.dot.value) return undefined;\n\n      if (label.value != null) return `${label.value} notifications`;\n\n      return undefined;\n    });\n\n    return html`\n      <span class=\"badge\" part=\"badge\" aria-label=\"${ariaLabel}\">\n        <slot name=\"icon\"></slot>\n        <span ?hidden=\"${() => label.value == null}\">${label}</span>\n        <span class=\"badge-label\" ?hidden=\"${() => label.value != null}\"><slot></slot></span>\n      </span>\n      <slot name=\"target\"></slot>\n    `;\n  },\n  styles: [\n    colorThemeMixin,\n    forcedColorsMixin,\n    roundedVariantMixin,\n    frostVariantMixin('.badge'),\n    sizeVariantMixin({\n      lg: { '--_padding-x': 'var(--size-2-5)', '--_padding-y': 'var(--size-1)', fontSize: 'var(--text-sm)' },\n      md: { '--_padding-x': 'var(--size-2)', '--_padding-y': 'var(--size-0-5)', fontSize: 'var(--text-xs)' },\n      sm: { '--_padding-x': 'var(--size-1-5)', '--_padding-y': 'var(--size-px)', fontSize: 'var(--text-xs)' },\n    }),\n    componentStyles,\n  ],\n});\n","@layer refine.base {\n  :host {\n    --_bg: var(--chip-bg, var(--color-contrast-150));\n    --_color: var(--chip-color, var(--color-contrast-800));\n    --_border-color: var(--chip-border-color, transparent);\n    --_radius: var(--chip-radius, var(--rounded-lg));\n    --_font-size: var(--chip-font-size, var(--text-sm));\n    --_font-weight: var(--chip-font-weight, var(--font-medium));\n    --_padding-x: var(--chip-padding-x, var(--size-2-5));\n    --_padding-y: var(--chip-padding-y, var(--size-0-5));\n    --_gap: var(--chip-gap, var(--size-1));\n\n    display: inline-flex;\n    align-items: center;\n    max-width: 100%;\n    vertical-align: middle;\n  }\n\n  .chip {\n    position: relative;\n    box-sizing: border-box;\n    display: inline-flex;\n    gap: var(--_gap);\n    align-items: center;\n    max-width: 100%;\n    padding: var(--_padding-y) var(--_padding-x);\n    font-size: var(--_font-size);\n    font-weight: var(--_font-weight);\n    line-height: 1.2;\n    color: var(--_color);\n    white-space: nowrap;\n    background: var(--_bg);\n    border: var(--border) solid var(--_border-color);\n    border-radius: var(--_radius);\n    transition:\n      background var(--transition-fast),\n      border-color var(--transition-fast),\n      box-shadow var(--transition-fast),\n      color var(--transition-fast);\n  }\n\n  .label {\n    flex: 1;\n    min-width: 0;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n  }\n\n  /* ========================================\n       Remove Button\n       ======================================== */\n\n  .remove-btn {\n    display: inline-flex;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    width: 1.35em;\n    height: 1.35em;\n    padding: 0;\n    margin-inline: var(--size-0-5) calc(var(--size-2) * -1);\n    color: inherit;\n    cursor: pointer;\n    background: color-mix(in oklch, currentcolor 12%, transparent);\n    border: none;\n    border-radius: var(--_radius);\n    opacity: 0.7;\n    transition:\n      background var(--transition-fast),\n      opacity var(--transition-fast);\n  }\n\n  .remove-btn:hover {\n    background: color-mix(in oklch, currentcolor 28%, transparent);\n    opacity: 1;\n  }\n\n  .remove-btn:focus-visible {\n    outline: 2px solid currentcolor;\n    outline-offset: 1px;\n    opacity: 1;\n  }\n\n  /* ========================================\n       Icon slot\n       ======================================== */\n\n  ::slotted([slot='icon']) {\n    display: inline-flex;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    width: 1em;\n    height: 1em;\n  }\n\n  .chip-btn {\n    display: inline-flex;\n    width: 100%;\n    padding: 0;\n    margin: 0;\n    font: inherit;\n    color: inherit;\n    text-align: inherit;\n    cursor: pointer;\n    background: none;\n    border: none;\n  }\n\n  .chip-btn:disabled {\n    cursor: not-allowed;\n  }\n\n  :host([mode='selectable'][checked]) .chip {\n    outline: var(--border-2) solid var(--_theme-base, currentColor);\n    outline-offset: -2px;\n  }\n\n  :host([mode='selectable']:not([disabled])) .chip,\n  :host([mode='action']:not([disabled])) .chip {\n    cursor: pointer;\n  }\n\n  .chip-btn:focus-visible {\n    outline: 2px solid var(--_theme-base, currentColor);\n    outline-offset: 2px;\n    border-radius: var(--_radius);\n  }\n}\n\n@layer refine.variants {\n  /* Solid (Default) — full theme color fill */\n  :host(:not([variant])),\n  :host([variant='solid']) {\n    --_bg: var(--chip-bg, var(--_theme-base, var(--color-contrast-700)));\n    --_color: var(--chip-color, var(--_theme-contrast, var(--color-contrast-50)));\n    --_border-color: var(--chip-border-color, transparent);\n    --_hover-bg: var(--chip-hover-bg, var(--_theme-focus, var(--color-contrast-800)));\n    --_active-bg: var(--chip-active-bg, color-mix(in oklch, var(--_theme-focus, var(--color-contrast-800)) 85%, black));\n  }\n\n  /* Flat — subtle tint */\n  :host([variant='flat']) {\n    --_bg: var(--chip-bg, color-mix(in oklch, var(--_theme-backdrop, var(--color-contrast-200)) 55%, transparent));\n    --_color: var(--chip-color, var(--_theme-base, var(--color-contrast-800)));\n    --_border-color: var(--chip-border-color, transparent);\n    --_hover-bg: var(--chip-hover-bg, var(--_theme-focus, var(--color-contrast-700)));\n    --_hover-color: var(--chip-hover-color, var(--_theme-contrast, var(--color-contrast-50)));\n    --_active-bg: var(--chip-active-bg, color-mix(in oklch, var(--_theme-focus, var(--color-contrast-800)) 85%, black));\n    --_active-color: var(--chip-active-color, var(--_theme-contrast, var(--color-contrast-50)));\n  }\n\n  /* Bordered — backdrop fill with themed border */\n  :host([variant='bordered']) {\n    --_bg: var(--chip-bg, var(--_theme-backdrop, var(--color-contrast-50)));\n    --_color: var(--chip-color, var(--_theme-base, var(--color-contrast-900)));\n    --_border-color: var(--chip-border-color, var(--_theme-border, var(--color-contrast-300)));\n    --_remove-bg: var(--chip-remove-bg, var(--_theme-focus, var(--color-contrast-700)));\n    --_remove-color: var(--chip-remove-color, var(--_theme-backdrop, var(--color-contrast-50)));\n    --_hover-bg: var(--chip-hover-bg, var(--_theme-focus, var(--color-contrast-700)));\n    --_hover-color: var(--chip-hover-color, var(--_theme-contrast, var(--color-contrast-50)));\n    --_hover-border-color: var(--chip-hover-border-color, var(--_theme-focus, var(--color-contrast-700)));\n    --_active-bg: var(--chip-active-bg, color-mix(in oklch, var(--_theme-focus, var(--color-contrast-800)) 85%, black));\n    --_active-color: var(--chip-active-color, var(--_theme-contrast, var(--color-contrast-50)));\n  }\n\n  /* Outline — transparent with colored border */\n  :host([variant='outline']) {\n    --_bg: var(--chip-bg, transparent);\n    --_color: var(--chip-color, var(--_theme-base, var(--color-contrast-900)));\n    --_border-color: var(--chip-border-color, var(--_theme-base, var(--color-contrast-400)));\n    --_remove-bg: var(--chip-remove-bg, var(--_theme-focus, var(--color-contrast-700)));\n    --_remove-color: var(--chip-remove-color, var(--_theme-backdrop, var(--color-contrast-50)));\n    --_hover-bg: var(--chip-hover-bg, var(--_theme-backdrop, var(--color-contrast-100)));\n    --_hover-border-color: var(--chip-hover-border-color, var(--_theme-focus, var(--color-contrast-700)));\n    --_active-bg: var(--chip-active-bg, var(--_theme-base, var(--color-contrast-700)));\n    --_active-color: var(--chip-active-color, var(--_theme-contrast, var(--color-contrast-50)));\n  }\n\n  /* Ghost — transparent, no border */\n  :host([variant='ghost']) {\n    --_bg: var(--chip-bg, transparent);\n    --_color: var(--chip-color, var(--_theme-base, var(--color-contrast-900)));\n    --_border-color: var(--chip-border-color, transparent);\n    --_hover-bg: var(--chip-hover-bg, var(--_theme-backdrop, var(--color-contrast-100)));\n    --_active-bg: var(--chip-active-bg, var(--_theme-base, var(--color-contrast-700)));\n    --_active-color: var(--chip-active-color, var(--_theme-contrast, var(--color-contrast-50)));\n  }\n\n  /* ── Remove button theming (tokens set per-variant above) ── */\n\n  :host([variant='bordered']) .remove-btn,\n  :host([variant='outline']) .remove-btn {\n    color: var(--_remove-color);\n    background: var(--_remove-bg);\n    border: var(--border) solid var(--_remove-bg);\n  }\n\n  :host([variant='bordered']) .remove-btn:hover,\n  :host([variant='outline']) .remove-btn:hover {\n    background: var(--chip-remove-hover-bg, color-mix(in oklch, var(--_remove-bg) 80%, var(--color-contrast-900)));\n    opacity: 1;\n  }\n\n  :host([variant='ghost']) .remove-btn {\n    border: var(--border) solid var(--_theme-focus, var(--color-contrast-400));\n  }\n\n  :host([variant='ghost']) .remove-btn:hover {\n    background: var(--chip-remove-hover-bg, color-mix(in oklch, currentcolor 15%, transparent));\n  }\n\n  /* ========================================\n     Hover / Active Feedback — interactive modes\n     ======================================== */\n\n  :host(\n      :is(\n        :not([variant]),\n        [variant='solid'],\n        [variant='flat'],\n        [variant='bordered'],\n        [variant='outline'],\n        [variant='ghost']\n      ):is([mode='selectable'], [mode='action']):not([disabled])\n    )\n    .chip-btn:hover\n    .chip {\n    color: var(--_hover-color, var(--_color));\n    background: var(--_hover-bg, var(--_bg));\n    border-color: var(--_hover-border-color, var(--_border-color));\n  }\n\n  :host(\n      :is(\n        :not([variant]),\n        [variant='solid'],\n        [variant='flat'],\n        [variant='bordered'],\n        [variant='outline'],\n        [variant='ghost']\n      ):is([mode='selectable'], [mode='action']):not([disabled])\n    )\n    .chip-btn:active\n    .chip {\n    color: var(--_active-color, var(--_color));\n    background: var(--_active-bg, var(--_bg));\n    box-shadow: var(--inset-shadow-2xs);\n  }\n}\n","import { bind, define, html, prop, useEmit } from '@vielzeug/ore';\nimport { computed, signal, watch } from '@vielzeug/ripple';\n\nimport type { ComponentSize, RoundedSize, ThemeColor, VisualVariant } from '../../types';\n\nimport '../../content/icon/icon';\nimport {\n  colorThemeMixin,\n  disabledStateMixin,\n  forcedColorsMixin,\n  roundedVariantMixin,\n  sizeVariantMixin,\n} from '../../styles';\n// ============================================\n// Styles\n// ============================================\nimport componentStyles from './chip.css?inline';\n\n// ============================================\n// Types\n// ============================================\n\n/** Chip component properties */\ntype ChipBaseProps = {\n  /** Theme color */\n  color?: ThemeColor;\n  /** Disable interactions */\n  disabled?: boolean;\n  /** Accessible label (required for icon-only chips) */\n  label?: string;\n  /** Border radius override */\n  rounded?: RoundedSize | '';\n  /** Component size */\n  size?: ComponentSize;\n  /** Value associated with this chip — included in emitted event detail */\n  value?: string;\n  /** Visual style variant */\n  variant?: Exclude<VisualVariant, 'text' | 'frost'>;\n};\n\ntype OreChipMode = 'static' | 'removable' | 'selectable' | 'action';\n\n/** Read-only presentation chip */\ntype StaticChipProps = {\n  mode?: Extract<OreChipMode, 'static'>;\n};\n\n/** Removable chip mode */\ntype RemovableChipProps = {\n  mode: Extract<OreChipMode, 'removable'>;\n};\n\n/** Selectable chip mode */\ntype SelectableChipProps = {\n  /** Controlled checked state for `mode=\"selectable\"` */\n  checked?: boolean | undefined;\n  /** Initial checked state for uncontrolled `mode=\"selectable\"` */\n  'default-checked'?: boolean;\n  mode: Extract<OreChipMode, 'selectable'>;\n};\n\n/** Action chip mode — behaves like a button, fires a click event without maintaining state */\ntype ActionChipProps = {\n  mode: Extract<OreChipMode, 'action'>;\n};\n\ntype OreChipComponentProps = ChipBaseProps & {\n  checked?: boolean | undefined;\n  'default-checked'?: boolean;\n  mode?: OreChipMode;\n};\n\nexport type OreChipEvents = {\n  change: { checked: boolean; originalEvent: Event; value: string | undefined };\n  click: { originalEvent: MouseEvent; value: string | undefined };\n  remove: { originalEvent: MouseEvent; value: string | undefined };\n};\n\nexport type OreChipProps = ChipBaseProps &\n  (StaticChipProps | RemovableChipProps | SelectableChipProps | ActionChipProps);\n\n/**\n * A compact, styled label element. Supports icons, a remove button, colors, sizes, and variants.\n * Commonly used to represent tags, filters, or selected options in a multiselect field.\n *\n * @element ore-chip\n *\n * @attr {string}  label     - Accessible label (required for icon-only chips)\n * @attr {string}  color     - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string}  variant   - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost'\n * @attr {string}  size      - Component size: 'sm' | 'md' | 'lg'\n * @attr {string}  rounded   - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {string}  mode      - Interaction mode: 'static' | 'removable' | 'selectable' | 'action'\n * @attr {boolean} disabled  - Disable the chip\n * @attr {string}  value     - Value included in emitted event detail\n * @attr {boolean} checked   - Controlled checked state for selectable chips\n * @attr {boolean} default-checked - Initial checked state for uncontrolled selectable chips\n *\n * @fires remove - Fired when the remove button is clicked. detail: { value: string, originalEvent: MouseEvent }\n * @fires change - Fired when a selectable chip toggles. detail: { checked: boolean, value: string, originalEvent: Event }\n * @fires click  - Fired when an action chip is clicked. detail: { value: string, originalEvent: MouseEvent }\n *\n * @slot         - Chip label text\n * @slot icon    - Leading icon or decoration\n *\n * @cssprop --chip-bg              - Background color\n * @cssprop --chip-color           - Text color\n * @cssprop --chip-border-color    - Border color\n * @cssprop --chip-radius          - Border radius\n * @cssprop --chip-font-size       - Font size\n * @cssprop --chip-font-weight     - Font weight\n * @cssprop --chip-padding-x       - Horizontal padding\n * @cssprop --chip-padding-y       - Vertical padding\n * @cssprop --chip-gap             - Gap between icon, label and remove button\n * @cssprop --chip-hover-bg        - Background on hover (interactive modes)\n * @cssprop --chip-hover-color     - Text color on hover (interactive modes)\n * @cssprop --chip-hover-border-color - Border color on hover (interactive modes)\n * @cssprop --chip-active-bg       - Background when pressed (interactive modes)\n * @cssprop --chip-active-color    - Text color when pressed (interactive modes)\n * @cssprop --chip-remove-bg       - Remove button background (bordered/outline variants)\n * @cssprop --chip-remove-color    - Remove button icon color (bordered/outline variants)\n * @cssprop --chip-remove-hover-bg - Remove button background on hover\n *\n * @part remove-btn - Remove action button.\n * @part chip-btn - Shadow part for the `chip-btn` element.\n * @part chip - Shadow part for the `chip` element.\n * @example\n * ```html\n * <!-- Static chip (read-only) -->\n * <ore-chip color=\"primary\">Design</ore-chip>\n *\n * <!-- Removable chip -->\n * <ore-chip color=\"success\" variant=\"flat\" mode=\"removable\" value=\"ts\">\n *   TypeScript\n * </ore-chip>\n *\n * <!-- Selectable chip (controlled) -->\n * <ore-chip color=\"info\" variant=\"flat\" mode=\"selectable\" checked value=\"ui\">\n *   UI\n * </ore-chip>\n *\n * <!-- Selectable chip (uncontrolled) -->\n * <ore-chip color=\"info\" variant=\"flat\" mode=\"selectable\" default-checked value=\"ui\">\n *   UI\n * </ore-chip>\n *\n * <!-- Action chip (acts like a button) -->\n * <ore-chip color=\"warning\" mode=\"action\" value=\"add\">\n *   <svg slot=\"icon\" ...></svg>\n *   Add Item\n * </ore-chip>\n *\n * <!-- Icon-only chip -->\n * <ore-chip color=\"error\" mode=\"action\" label=\"Delete\">\n *   <svg slot=\"icon\" ...></svg>\n * </ore-chip>\n * ```\n */\nexport const CHIP_TAG = 'ore-chip' as const;\ndefine<OreChipComponentProps>(CHIP_TAG, {\n  props: {\n    checked: {\n      default: undefined as OreChipComponentProps['checked'],\n      parse: (value: string | null) => (value == null ? undefined : value !== 'false'),\n      reflect: false,\n    },\n    color: prop.string<ThemeColor>(),\n    'default-checked': prop.bool(false),\n    disabled: prop.bool(false),\n    label: prop.string(),\n    mode: prop.oneOf(['static', 'removable', 'selectable', 'action'] as const, 'static'),\n    rounded: prop.string<RoundedSize | ''>(),\n    size: prop.string<ComponentSize>(),\n    value: prop.string(),\n    variant: prop.string<Exclude<VisualVariant, 'text' | 'frost'>>(),\n  },\n\n  setup(props) {\n    const emit = useEmit<OreChipEvents>();\n\n    // ============================================\n    // State Management\n    // ============================================\n    // Once a checked prop is provided, treat the chip as controlled for the rest of its lifecycle.\n    const isControlled = signal(props.checked.value !== undefined);\n    // Internal tracking for uncontrolled selectable chips; seeded from default-checked.\n    const checkedState = signal(!isControlled.value && props['default-checked'].value);\n\n    watch(props.checked, (value) => {\n      if (value !== undefined) {\n        isControlled.value = true;\n      }\n    });\n\n    // Effective checked value — reactive to checked prop changes in controlled mode.\n    const isChecked = computed(() => {\n      if (props.mode.value !== 'selectable') return false;\n\n      if (isControlled.value) {\n        return props.checked.value ?? false;\n      }\n\n      return checkedState.value;\n    });\n\n    bind({\n      attr: {\n        checked: () => (props.mode.value === 'selectable' && isChecked.value ? true : undefined),\n      },\n    });\n    // ============================================\n    // Event Handlers\n    // ============================================\n    function handleRemove(e: MouseEvent) {\n      if (props.disabled.value) return;\n\n      emit('remove', { originalEvent: e, value: props.value.value });\n    }\n\n    function handleSelectableActivate(e: MouseEvent) {\n      e.stopPropagation();\n\n      if (props.disabled.value) return;\n\n      const nextChecked = !isChecked.value;\n\n      if (!isControlled.value) {\n        checkedState.value = nextChecked;\n      }\n\n      emit('change', { checked: nextChecked, originalEvent: e, value: props.value.value });\n    }\n\n    function handleActionClick(e: MouseEvent) {\n      if (props.disabled.value) return;\n\n      emit('click', { originalEvent: e, value: props.value.value });\n    }\n\n    // ============================================\n    // Template Helpers\n    // ============================================\n    const renderChipContent = () => html`\n      <slot name=\"icon\"></slot>\n      <span class=\"label\"><slot></slot></span>\n    `;\n\n    const removeBtnLabel = () => {\n      const label = props.label.value || props.value.value;\n\n      return label ? `Remove ${label}` : 'Remove';\n    };\n\n    const renderRemoveButton = () => html`\n      <button\n        class=\"remove-btn\"\n        part=\"remove-btn\"\n        type=\"button\"\n        aria-label=\"${removeBtnLabel}\"\n        ?hidden=\"${() => props.mode.value !== 'removable'}\"\n        disabled=\"${props.disabled}\"\n        @click=\"${handleRemove}\">\n        <ore-icon name=\"x\" size=\"12\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n      </button>\n    `;\n\n    const renderSelectableChip = () => html`\n      <button\n        class=\"chip-btn\"\n        part=\"chip-btn\"\n        type=\"button\"\n        role=\"checkbox\"\n        aria-checked=\"${() => String(isChecked.value)}\"\n        aria-label=\"${props.label}\"\n        disabled=\"${props.disabled}\"\n        @click=\"${handleSelectableActivate}\">\n        <span class=\"chip\" part=\"chip\">${renderChipContent()}</span>\n      </button>\n    `;\n\n    const renderActionChip = () => html`\n      <button\n        class=\"chip-btn\"\n        part=\"chip-btn\"\n        type=\"button\"\n        aria-label=\"${props.label}\"\n        disabled=\"${props.disabled}\"\n        @click=\"${handleActionClick}\">\n        <span class=\"chip\" part=\"chip\">${renderChipContent()}</span>\n      </button>\n    `;\n\n    const renderStaticChip = () => html`\n      <span class=\"chip\" part=\"chip\">${renderChipContent()}</span>\n    `;\n\n    const renderRemovableChip = () => html`\n      <span class=\"chip\" part=\"chip\">${renderChipContent()} ${renderRemoveButton()}</span>\n    `;\n\n    // ============================================\n    // Render\n    // ============================================\n    return html`\n      ${() => {\n        const mode = props.mode.value;\n\n        if (mode === 'selectable') return renderSelectableChip();\n\n        if (mode === 'action') return renderActionChip();\n\n        if (mode === 'removable') return renderRemovableChip();\n\n        return renderStaticChip();\n      }}\n    `;\n  },\n  styles: [\n    colorThemeMixin,\n    disabledStateMixin,\n    roundedVariantMixin,\n    sizeVariantMixin({\n      lg: {\n        '--_font-size': 'var(--text-sm)',\n        '--_gap': 'var(--size-1-5)',\n        '--_padding-x': 'var(--size-3)',\n        '--_padding-y': 'var(--size-1)',\n      },\n      sm: {\n        '--_font-size': 'var(--text-xs)',\n        '--_gap': 'var(--size-0-5)',\n        '--_padding-x': 'var(--size-2-5)',\n        '--_padding-y': 'var(--size-px)',\n      },\n    }),\n    forcedColorsMixin,\n    componentStyles,\n  ],\n});\n","@layer refine.base {\n  :host {\n    --_height: var(--password-strength-height, 0.375rem);\n    --_gap: var(--password-strength-gap, var(--space-1, 0.25rem));\n    --_radius: var(--password-strength-radius, var(--rounded-full));\n    --_track-bg: var(--password-strength-track-bg, var(--color-contrast-300, #d1d5db));\n    --_track-border: var(--password-strength-track-border, var(--color-contrast-400, #9ca3af));\n    --_active-color: var(--password-strength-weak-color, var(--color-warning-500, #f59e0b));\n\n    display: grid;\n    gap: var(--space-1, 0.25rem);\n    width: 100%;\n  }\n\n  :host([data-level='fair']) {\n    --_active-color: var(--password-strength-fair-color, var(--color-warning-600, #d97706));\n  }\n\n  :host([data-level='good']) {\n    --_active-color: var(--password-strength-good-color, var(--color-success-500, #22c55e));\n  }\n\n  :host([data-level='strong']) {\n    --_active-color: var(--password-strength-strong-color, var(--color-success-600, #16a34a));\n  }\n\n  .meter {\n    width: 100%;\n    min-width: 10rem;\n  }\n\n  .segments {\n    display: grid;\n    grid-template-columns: repeat(4, minmax(0, 1fr));\n    gap: var(--_gap);\n  }\n\n  .segment {\n    height: var(--_height);\n    min-height: 0.35rem;\n    background: var(--_track-bg);\n    border: 1px solid var(--_track-border);\n    border-radius: var(--_radius);\n    transition: var(--_motion-transition, background-color var(--transition-fast), border-color var(--transition-fast));\n  }\n\n  .segment.active {\n    background: var(--_active-color);\n    border-color: var(--_active-color);\n  }\n\n  .level-label {\n    min-height: 1.25em;\n    font-size: var(--password-strength-label-size, var(--text-sm, 0.875rem));\n    line-height: 1.25;\n    color: var(--password-strength-label-color, currentColor);\n  }\n}\n","import { bind, define, html, prop } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\n\nimport { reducedMotionMixin } from '../../styles';\nimport componentStyles from './password-strength.css?inline';\n\n/** Scoring levels for password strength. */\nexport type PasswordStrengthLevel = 'empty' | 'weak' | 'fair' | 'good' | 'strong';\n\n/** Props accepted by <ore-password-strength>. */\nexport type OrePasswordStrengthProps = {\n  /** Accessible name for assistive technology. Default: 'Password strength'. */\n  label?: string;\n  /**\n   * Optional level labels in order: empty, weak, fair, good, strong.\n   * If omitted or invalid length, defaults are used.\n   */\n  labels?: string[];\n  /**\n   * Optional score override (0..4). Use this to integrate external scorers\n   * such as zxcvbn while keeping block rendering and accessibility behavior.\n   * -1 means no override (default).\n   */\n  score?: number;\n  /** Whether to render visible textual feedback. Default: true. */\n  'show-label'?: boolean;\n  /** Password string to evaluate. */\n  value?: string;\n};\n\n/**\n * Strong password meter with segmented progress visualization.\n *\n * Built-in scoring is heuristic and conservative:\n * - length < 6 => weak\n * - length >= 8 with mixed case => fair\n * - + digit or symbol => good\n * - length >= 12 with mixed case, digit and symbol => strong\n *\n * @element ore-password-strength\n *\n * @attr {string} value - Password string to evaluate\n * @attr {number} score - Optional score override (0..4). Use -1 for no override (default: -1)\n * @attr {boolean} show-label - Show visible feedback label (default: true)\n * @attr {string} label - Accessible name (default: 'Password strength')\n *\n * @cssprop --password-strength-height       Segment bar height\n * @cssprop --password-strength-gap          Gap between segments\n * @cssprop --password-strength-radius       Segment corner radius\n * @cssprop --password-strength-track-bg     Inactive segment color\n * @cssprop --password-strength-label-size   Visible label font size\n * @cssprop --password-strength-label-color  Visible label color\n * @cssprop --password-strength-weak-color   Weak state segment color\n * @cssprop --password-strength-fair-color   Fair state segment color\n * @cssprop --password-strength-good-color   Good state segment color\n * @cssprop --password-strength-strong-color Strong state segment color\n *\n * @example\n * ```html\n * <!-- Pair with an ore-input to evaluate in real time -->\n * <ore-input type=\"password\" label=\"Password\" name=\"password\" id=\"pwd\"></ore-input>\n * <ore-password-strength id=\"meter\"></ore-password-strength>\n * <script type=\"module\">\n *   document.getElementById('pwd').addEventListener('input', (e) => {\n *     document.getElementById('meter').value = e.target.value;\n *   });\n * </script>\n *\n * <!-- Fixed score display (e.g. from a server-side score) -->\n * <ore-password-strength score=\"3\"></ore-password-strength>\n * ```\n */\nexport const PASSWORD_STRENGTH_TAG = 'ore-password-strength' as const;\ndefine<OrePasswordStrengthProps>(PASSWORD_STRENGTH_TAG, {\n  props: {\n    label: prop.string('Password strength'),\n    labels: prop.json(undefined as string[] | undefined),\n    score: prop.number(-1),\n    'show-label': prop.bool(true),\n    value: prop.string(),\n  },\n\n  setup(props) {\n    const defaultLabels: Record<PasswordStrengthLevel, string> = {\n      empty: '',\n      fair: 'Fair',\n      good: 'Good',\n      strong: 'Strong',\n      weak: 'Weak',\n    };\n\n    const levels: PasswordStrengthLevel[] = ['empty', 'weak', 'fair', 'good', 'strong'];\n\n    const computeScore = (password: string): 0 | 1 | 2 | 3 | 4 => {\n      if (!password) return 0;\n\n      if (password.length < 6) return 1;\n\n      const hasLower = /[a-z]/.test(password);\n      const hasUpper = /[A-Z]/.test(password);\n      const hasDigit = /\\d/.test(password);\n      const hasSymbol = /[^a-zA-Z0-9]/.test(password);\n      const long = password.length >= 12;\n\n      if (long && hasLower && hasUpper && hasDigit && hasSymbol) return 4;\n\n      if ((hasLower || hasUpper) && (hasDigit || hasSymbol) && password.length >= 8) return 3;\n\n      if ((hasLower || hasUpper) && password.length >= 8) return 2;\n\n      return 1;\n    };\n\n    const computeLevel = (): PasswordStrengthLevel => {\n      const external = props.score.value ?? -1;\n      const finalScore =\n        external >= 0 ? Math.max(0, Math.min(4, Math.trunc(external))) : computeScore(props.value.value ?? '');\n\n      return levels[finalScore];\n    };\n\n    const score = computed<0 | 1 | 2 | 3 | 4>(() => {\n      // score >= 0 means an external override was provided\n      const external = props.score.value ?? -1;\n\n      if (external >= 0) {\n        return Math.max(0, Math.min(4, Math.trunc(external))) as 0 | 1 | 2 | 3 | 4;\n      }\n\n      return computeScore(props.value.value ?? '');\n    });\n\n    const levelLabel = computed<string>(() => {\n      const custom = props.labels.value;\n\n      if (Array.isArray(custom) && custom.length === 5) return String(custom[score.value] ?? '');\n\n      return defaultLabels[computeLevel()];\n    });\n\n    const ariaValueText = computed<string | null>(() => {\n      if (score.value === 0) return null;\n\n      return levelLabel.value || null;\n    });\n\n    // Sync level change to data-level attribute reactively\n    bind({\n      attr: {\n        'data-level': () => computeLevel(),\n      },\n    });\n\n    const segClass = (threshold: number) => () => `segment${score.value >= threshold ? ' active' : ''}`;\n\n    return html`\n      <div\n        class=\"meter\"\n        role=\"meter\"\n        aria-label=\"${props.label}\"\n        aria-valuemin=\"0\"\n        aria-valuemax=\"4\"\n        aria-valuenow=\"${() => String(score.value)}\"\n        aria-valuetext=\"${() => ariaValueText.value}\">\n        <div class=\"segments\" aria-hidden=\"true\">\n          <div class=\"${segClass(1)}\"></div>\n          <div class=\"${segClass(2)}\"></div>\n          <div class=\"${segClass(3)}\"></div>\n          <div class=\"${segClass(4)}\"></div>\n        </div>\n      </div>\n      ${() =>\n        props['show-label'].value\n          ? html`\n              <span class=\"level-label\" aria-live=\"polite\" aria-atomic=\"true\">${() => levelLabel.value}</span>\n            `\n          : ''}\n    `;\n  },\n\n  styles: [reducedMotionMixin, componentStyles],\n});\n","@layer refine.base {\n  :host {\n    --_bg: var(--skeleton-bg, var(--color-contrast-200));\n    --_highlight: var(--skeleton-highlight, var(--color-contrast-100));\n    --_radius: var(--skeleton-radius, var(--rounded-lg));\n    --_circle-size: var(--skeleton-size, var(--size-10));\n    --_width: var(--skeleton-width, 100%);\n    --_height: var(--skeleton-height, var(--size-4));\n    --_line-gap: var(--skeleton-line-gap, var(--size-2));\n    --_last-line-width: var(--skeleton-last-line-width, 60%);\n    --_duration: var(--skeleton-duration, 1.6s);\n    --_stripe-size: var(--skeleton-stripe-size, 8px);\n\n    display: inline-block;\n    width: var(--_width);\n    height: var(--_height);\n  }\n\n  .stack {\n    display: grid;\n    gap: var(--_line-gap);\n    width: 100%;\n    height: 100%;\n  }\n\n  .bone {\n    position: relative;\n    width: 100%;\n    height: 100%;\n    overflow: hidden;\n    background: var(--_bg);\n    border-radius: var(--_radius);\n  }\n\n  .bone::after {\n    position: absolute;\n    inset: 0;\n    content: '';\n    background: linear-gradient(90deg, var(--_bg) 0%, var(--_highlight) 50%, var(--_bg) 100%);\n    transform: translateX(-100%);\n    animation: var(--_motion-animation, ore-skeleton-shimmer var(--_duration) linear infinite);\n  }\n\n  :host([data-animated='false']) .bone::after {\n    display: none;\n  }\n\n  /* Pause shimmer when scrolled out of the viewport — no visible effect, saves GPU */\n  :host([data-paused]) .bone::after {\n    animation-play-state: paused;\n  }\n\n  @keyframes ore-skeleton-shimmer {\n    to {\n      transform: translateX(100%);\n    }\n  }\n\n  /* In RTL the shimmer should sweep right-to-left */\n  :host(:dir(rtl)) .bone::after {\n    animation-direction: reverse;\n  }\n}\n\n@layer refine.variants {\n  /* Circle variant — avatars, icons */\n  :host([variant='circle']) {\n    --_radius: var(--rounded-full);\n\n    width: var(--skeleton-width, var(--_circle-size));\n    height: var(--skeleton-height, var(--_circle-size));\n    aspect-ratio: 1 / 1;\n  }\n\n  /* Text variant — thinner, for inline text lines */\n  :host([variant='text']) {\n    --_height: var(--size-3);\n    --_radius: var(--rounded-sm);\n\n    height: auto;\n  }\n\n  :host([variant='text']) .stack {\n    height: auto;\n  }\n\n  :host([variant='text']) .bone {\n    height: var(--_height);\n  }\n\n  :host([variant='text']) .bone[data-last='true'] {\n    width: var(--_last-line-width);\n  }\n}\n\n@layer refine.striped {\n  :host([striped]) .stack {\n    width: calc(100% - 2px);\n  }\n\n  :host([striped]) .bone {\n    --_stripe-color: var(--skeleton-stripe-color, var(--color-contrast-400));\n\n    background-color: transparent;\n    border: var(--border) dashed var(--_stripe-color);\n  }\n\n  :host([striped]) .bone::before {\n    --_stripe-color: var(--skeleton-stripe-color, var(--color-contrast-300));\n\n    position: absolute;\n    inset: 0;\n    content: '';\n    background-color: var(--_stripe-color);\n    mask-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cline x1='0' y1='8' x2='8' y2='0' stroke='white' stroke-width='1'/%3E%3C/svg%3E\");\n    mask-size: var(--_stripe-size) var(--_stripe-size);\n  }\n\n  :host([striped]) .bone::after {\n    display: none;\n  }\n}\n\n@layer refine.utilities {\n  :host([size='sm']) {\n    --_height: var(--size-3);\n    --_circle-size: var(--size-8);\n  }\n\n  :host([size='md']) {\n    --_height: var(--size-4);\n    --_circle-size: var(--size-10);\n  }\n\n  :host([size='lg']) {\n    --_height: var(--size-6);\n    --_circle-size: var(--size-14);\n  }\n}\n\n@media (forced-colors: active) {\n  .bone {\n    background: ButtonFace;\n    border: 1px solid ButtonText;\n  }\n\n  .bone::after {\n    display: none;\n  }\n}\n","import { bind, define, getHost, html, onCleanup, onMounted, prop } from '@vielzeug/ore';\nimport { computed, signal, watch } from '@vielzeug/ripple';\nimport { createIntersection } from '@vielzeug/sentinel';\nimport { sizableBundle } from '../../shared';\nimport { reducedMotionMixin } from '../../styles';\nimport type { ComponentSize } from '../../types';\nimport { safeCSSLength } from '../../utils';\nimport componentStyles from './skeleton.css?inline';\n\n/** Skeleton loader component properties */\nexport type OreSkeletonProps = {\n  /** Toggle shimmer animation */\n  animated?: boolean;\n  /** Height override (e.g. '1rem', '3rem') */\n  height?: string;\n  /** Number of text lines for `variant='text'` */\n  lines?: number;\n  /** Radius override (e.g. '9999px', 'var(--rounded-xl)') */\n  radius?: string;\n  /** Size preset controlling line height and circle size */\n  size?: ComponentSize;\n  /** Render diagonal stripes instead of the shimmer — useful as a design-mode placeholder */\n  striped?: boolean;\n  /** Visual variant: 'rect' (default), 'circle', or 'text' */\n  variant?: 'rect' | 'circle' | 'text';\n  /** Width override (e.g. '12rem', '70%') */\n  width?: string;\n};\n\n/**\n * A shimmer placeholder that represents loading content.\n * Control dimensions via the `--skeleton-width` and `--skeleton-height` CSS custom properties,\n * or via `width` / `height` inline styles.\n *\n * @element ore-skeleton\n *\n * @attr {string}  variant  - Shape: 'rect' (default) | 'circle' | 'text'\n * @attr {string}  size     - Height/circle preset: 'sm' | 'md' | 'lg'\n * @attr {string}  width    - Width override (CSS length/percentage)\n * @attr {string}  height   - Height override (CSS length)\n * @attr {string}  radius   - Radius override\n * @attr {boolean} animated - Disable with `animated=\"false\"`\n * @attr {number}  lines    - Text line count (only for `variant='text'`)\n * @attr {boolean} striped  - Replace shimmer with diagonal stripes\n *\n * @cssprop --skeleton-bg          - Base shimmer color\n * @cssprop --skeleton-highlight - Shimmer highlight color\n * @cssprop --skeleton-radius    - Border radius\n * @cssprop --skeleton-size      - Circle fallback size\n * @cssprop --skeleton-width     - Width (default: 100%)\n * @cssprop --skeleton-height    - Height (default: var(--size-4))\n * @cssprop --skeleton-line-gap  - Vertical gap between text lines\n * @cssprop --skeleton-last-line-width - Width of the final text line\n * @cssprop --skeleton-duration    - Shimmer animation duration\n * @cssprop --skeleton-stripe-size  - Width of each diagonal stripe (default: 6px)\n *\n * @part stack - Stack container.\n * @part bone - Skeleton bone element.\n * @example\n * ```html\n * <!-- Paragraph lines -->\n * <ore-skeleton variant=\"text\" lines=\"3\" width=\"100%\"></ore-skeleton>\n *\n * <!-- Avatar -->\n * <ore-skeleton variant=\"circle\" size=\"md\"></ore-skeleton>\n *\n * <!-- Card image -->\n * <ore-skeleton width=\"100%\" height=\"10rem\"></ore-skeleton>\n * ```\n */\nexport const SKELETON_TAG = 'ore-skeleton' as const;\ndefine<OreSkeletonProps>(SKELETON_TAG, {\n  props: {\n    ...sizableBundle,\n    animated: prop.bool(true),\n    height: prop.string(),\n    lines: prop.number(1),\n    radius: prop.string(),\n    striped: prop.bool(false),\n    variant: prop.oneOf(['rect', 'circle', 'text'] as const, 'rect'),\n    width: prop.string(),\n  },\n  setup(props) {\n    const el = getHost();\n\n    const isPaused = signal(false);\n    const lineCount = () => {\n      const value = Math.floor(Number(props.lines.value));\n\n      return Number.isFinite(value) && value > 0 ? value : 1;\n    };\n    const renderLineCount = () => (props.variant.value === 'text' ? lineCount() : 1);\n    const styleDeps = () =>\n      `${props.width.value ?? ''}|${props.height.value ?? ''}|${props.radius.value ?? ''}|${props.animated.value === false ? '0' : '1'}`;\n\n    watch(\n      computed(styleDeps),\n      () => {\n        const safeWidth = safeCSSLength(props.width.value);\n        const safeHeight = safeCSSLength(props.height.value);\n        const safeRadius = safeCSSLength(props.radius.value);\n\n        if (safeWidth) el.style.setProperty('--skeleton-width', safeWidth);\n        else el.style.removeProperty('--skeleton-width');\n\n        if (safeHeight) el.style.setProperty('--skeleton-height', safeHeight);\n        else el.style.removeProperty('--skeleton-height');\n\n        if (safeRadius) el.style.setProperty('--skeleton-radius', safeRadius);\n        else el.style.removeProperty('--skeleton-radius');\n\n        const rawAnimated = el.getAttribute('animated');\n        const isAnimated = rawAnimated !== 'false' && props.animated.value !== false;\n\n        el.setAttribute('data-animated', isAnimated ? 'true' : 'false');\n      },\n      { immediate: true },\n    );\n\n    bind({\n      attr: {\n        'data-paused': () => (isPaused.value ? true : undefined),\n      },\n    });\n\n    onMounted(() => {\n      const intersection = createIntersection(el, { threshold: 0 });\n\n      onCleanup(() => intersection.dispose());\n\n      watch(intersection, (state) => {\n        const paused = state === null ? false : !state.isIntersecting;\n        isPaused.value = paused;\n      });\n    });\n\n    return html`\n      <div class=\"stack\" part=\"stack\">\n        ${() =>\n          Array.from({ length: renderLineCount() }, (_, index) => {\n            const isLastLine =\n              props.variant.value === 'text' && renderLineCount() > 1 && index === renderLineCount() - 1;\n\n            return html`\n              <div class=\"bone\" part=\"bone\" aria-hidden=\"true\" data-last=\"${() => (isLastLine ? 'true' : null)}\"></div>\n            `;\n          })}\n      </div>\n    `;\n  },\n  styles: [reducedMotionMixin, componentStyles],\n});\n","//#region src/random/uuid.ts\nfunction e() {\n\treturn crypto.randomUUID();\n}\n//#endregion\nexport { e as uuid };\n\n//# sourceMappingURL=uuid.js.map","@layer refine.base {\n  :host {\n    --_position: var(--toast-position, fixed);\n    --_inset-top: var(--toast-inset-top, auto);\n    --_inset-bottom: var(--toast-inset-bottom, 1rem);\n    --_inset-right: var(--toast-inset-right, 1rem);\n    --_inset-left: var(--toast-inset-left, auto);\n    --_z-index: var(--toast-z-index, var(--z-toast));\n    --_max-width: var(--toast-max-width, 400px);\n    --_gap: var(--toast-gap, 0.5rem);\n\n    position: var(--_position);\n    inset: var(--_inset-top) var(--_inset-right) var(--_inset-bottom) var(--_inset-left);\n    z-index: var(--_z-index);\n    display: flex;\n    flex-direction: column;\n    gap: var(--_gap);\n    max-width: var(--_max-width);\n    pointer-events: none;\n  }\n\n  /* ── Position variants ────────────────────────────────────────────────── */\n\n  :host([position='top-left']) {\n    --_inset-top: 1rem;\n    --_inset-bottom: auto;\n    --_inset-left: 1rem;\n    --_inset-right: auto;\n  }\n\n  :host([position='top-center']) {\n    --_inset-top: 1rem;\n    --_inset-bottom: auto;\n    --_inset-left: 50%;\n    --_inset-right: auto;\n\n    transform: translateX(-50%);\n  }\n\n  :host([position='top-right']) {\n    --_inset-top: 1rem;\n    --_inset-bottom: auto;\n    --_inset-right: 1rem;\n    --_inset-left: auto;\n  }\n\n  :host([position='bottom-left']) {\n    --_inset-bottom: 1rem;\n    --_inset-left: 1rem;\n    --_inset-right: auto;\n    --_inset-top: auto;\n  }\n\n  :host([position='bottom-center']) {\n    --_inset-bottom: 1rem;\n    --_inset-left: 50%;\n    --_inset-right: auto;\n    --_inset-top: auto;\n\n    transform: translateX(-50%);\n  }\n\n  :host([position='bottom-right']) {\n    --_inset-bottom: 1rem;\n    --_inset-right: 1rem;\n    --_inset-left: auto;\n    --_inset-top: auto;\n  }\n\n  /* ── Container ────────────────────────────────────────────────────────── */\n\n  .toast-container {\n    display: grid;\n    grid-template-rows: 1fr;\n    grid-template-columns: 1fr;\n    row-gap: 0;\n    perspective: 1200px;\n    perspective-origin: center center;\n    transition: row-gap var(--transition-normal);\n  }\n\n  /* ARIA live regions are layout-transparent. */\n  .toast-live-region {\n    display: contents;\n  }\n\n  :host(.hovered) .toast-container {\n    row-gap: var(--_gap);\n  }\n\n  /* ── Wrapper (layout / stacking only — no animation) ─────────────────── */\n\n  /* .toast-wrapper owns: grid position, z-index, stacking transforms.       */\n\n  /* It never has opacity or transition set on it directly.                  */\n\n  /* This keeps stacking rules and animation rules on separate elements,     */\n\n  /* eliminating all specificity conflicts and !important usage.             */\n\n  :host(:not(.hovered)) .toast-wrapper {\n    grid-row: 1;\n    grid-column: 1;\n    align-self: end;\n  }\n\n  :host([position^='top']:not(.hovered)) .toast-wrapper {\n    align-self: start;\n  }\n\n  .toast-wrapper {\n    position: relative;\n    pointer-events: auto;\n    touch-action: pan-y;\n  }\n\n  /* Stacking (collapsed) — 3D perspective stack */\n  :host(:not(.hovered)) .toast-wrapper:nth-last-child(1) {\n    z-index: 3;\n    transform: translateY(0) scale(1);\n  }\n\n  :host(:not(.hovered)) .toast-wrapper:nth-last-child(2) {\n    z-index: 2;\n    pointer-events: none;\n    transform: translateY(-8px) scale(0.95);\n  }\n\n  :host(:not(.hovered)) .toast-wrapper:nth-last-child(3) {\n    z-index: 1;\n    pointer-events: none;\n    transform: translateY(-14px) scale(0.9);\n  }\n\n  :host(:not(.hovered)) .toast-wrapper:nth-last-child(n + 4) {\n    visibility: hidden;\n    pointer-events: none;\n  }\n\n  /* Top positions: reverse stacking direction */\n  :host([position^='top']) .toast-wrapper {\n    transform-origin: center top;\n  }\n\n  :host([position^='top']:not(.hovered)) .toast-wrapper:nth-last-child(2) {\n    transform: translateY(8px) scale(0.95);\n  }\n\n  :host([position^='top']:not(.hovered)) .toast-wrapper:nth-last-child(3) {\n    transform: translateY(14px) scale(0.9);\n  }\n\n  /* Expanded (hovered) — stacking transforms are released per wrapper */\n  :host(.hovered) .toast-wrapper {\n    z-index: auto;\n    visibility: visible;\n    grid-row: auto;\n    grid-column: 1;\n    align-self: stretch;\n    pointer-events: auto;\n    transform: none;\n  }\n\n  /* Staggered expand delays (applied to wrapper transform only) */\n  :host(.hovered) .toast-wrapper:nth-last-child(2) {\n    transition-delay: var(--duration-75);\n  }\n\n  :host(.hovered) .toast-wrapper:nth-last-child(3) {\n    transition-delay: var(--duration-100);\n  }\n\n  :host(.hovered) .toast-wrapper:nth-last-child(n + 4) {\n    transition-delay: var(--duration-150);\n  }\n\n  /* ── Inner (animation target only — no layout role) ──────────────────── */\n\n  /* .toast-inner owns: opacity, entry/exit transitions.                    */\n\n  /* It never participates in stacking (that's the wrapper's job).          */\n\n  /* Swipe gesture also animates .toast-inner to keep wrapper state clean.  */\n\n  .toast-inner {\n    position: relative;\n    opacity: 1;\n    transition: opacity var(--toast-exit-duration, 300ms) var(--ease-out);\n  }\n\n  /* Entry: snap to invisible with no transition, then rely on class removal to animate in */\n  .toast-inner.entering {\n    opacity: 0;\n    transition: none;\n  }\n\n  /* Exit: fade out — wrapper stays in-flow so grid doesn't snap shut prematurely */\n  .toast-inner.exiting {\n    pointer-events: none;\n    opacity: 0;\n  }\n\n  /* ── Alert inside toast ───────────────────────────────────────────────── */\n\n  ::slotted(ore-alert),\n  ore-alert {\n    --_motion-animation: none;\n    width: 100%;\n    margin: 0;\n    box-shadow: var(--shadow-lg);\n  }\n\n  /* ── Action buttons ───────────────────────────────────────────────────── */\n\n  .toast-actions {\n    display: flex;\n    gap: var(--size-4);\n    justify-content: flex-end;\n  }\n\n  /* ── Responsive: small screens ────────────────────────────────────────── */\n\n  @media (width <= 480px) {\n    :host {\n      --_max-width: calc(100vw - var(--size-4));\n      --_inset-right: var(--size-2);\n      --_inset-left: var(--size-2);\n    }\n\n    :host([position='top-center']),\n    :host([position='bottom-center']) {\n      --_inset-left: var(--size-2);\n\n      inset-inline-start: var(--size-2);\n      transform: none;\n    }\n  }\n}\n","import '../alert/alert';\nimport { uuid } from '@vielzeug/arsenal/random';\nimport { createPanGesture, type PanGesture } from '@vielzeug/gesture';\nimport { define, getHost, html, onCleanup, onMounted, prop, ref, useEmit } from '@vielzeug/ore';\nimport { computed, signal, watch } from '@vielzeug/ripple';\nimport { warn } from '../../_dev';\nimport { reducedMotionMixin } from '../../styles';\nimport type { ComponentSize, RoundedSize, ThemeColor } from '../../types';\nimport componentStyles from './toast.css?inline';\n\n/** Must match toast.css's default opacity transition duration. */\nconst TOAST_EXIT_MS = 300;\n\nexport type OreToastEvents = {\n  add: { id: string };\n  dismiss: { id: string };\n};\n\nexport type OreToastProps = {\n  max?: number;\n  position?: 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';\n};\n\n/** Individual toast notification. */\nexport type ToastItem = {\n  actions?: Array<{\n    color?: ThemeColor;\n    label: string;\n    onClick?: () => void;\n    variant?: 'solid' | 'flat' | 'bordered';\n  }>;\n  color?: ThemeColor;\n  dismissible?: boolean;\n  /** Auto-dismiss delay in ms. Set to 0 for persistent toasts (default: 5000). */\n  duration?: number;\n  heading?: string;\n  /** Show message and actions side-by-side (horizontal layout). */\n  horizontal?: boolean;\n  /** Auto-generated when omitted. */\n  id?: string;\n  message: string;\n  /** Metadata text (for example, a timestamp) shown in the alert meta slot. */\n  meta?: string;\n  /** Called after the toast is fully dismissed and removed. */\n  onDismiss?: () => void;\n  rounded?: RoundedSize | '';\n  size?: ComponentSize;\n  /**\n   * Screen-reader announcement urgency. Error-coloured toasts are assertive by\n   * default; all other toasts are polite.\n   */\n  urgency?: 'polite' | 'assertive';\n  variant?: 'solid' | 'flat' | 'bordered';\n};\n\ntype ToastPhase = 'entering' | 'active' | 'exiting';\n\ntype ToastTimer = {\n  remaining: number;\n  startedAt: number;\n  timeoutId: ReturnType<typeof setTimeout>;\n};\n\ntype ToastEntry = Required<Pick<ToastItem, 'dismissible' | 'duration' | 'id'>> &\n  Omit<ToastItem, 'dismissible' | 'duration' | 'id'> & {\n    exitTimeoutId: ReturnType<typeof setTimeout> | null;\n    id: string;\n    phase: ToastPhase;\n    timer: ToastTimer | null;\n  };\n\ntype ToastStoreEvent = {\n  id: string;\n  type: 'add' | 'dismiss';\n};\n\n/**\n * Owns notification data and every timer. Renderers only subscribe to this\n * store; they never expose imperative mutation methods themselves.\n */\nclass ToastStore {\n  readonly #entries = signal<ToastEntry[]>([]);\n  readonly #listeners = new Set<(entries: ToastEntry[]) => void>();\n  readonly #eventListeners = new Set<(event: ToastStoreEvent) => void>();\n  #disposed = false;\n  #max = 5;\n\n  add(item: ToastItem): string {\n    if (this.#disposed) return item.id ?? uuid();\n\n    const id = item.id ?? uuid();\n    const active = this.#entries.value.filter((entry) => entry.phase !== 'exiting');\n    const overflow = active.length - (this.#max - 1);\n\n    if (overflow > 0) {\n      for (const entry of active.slice(0, overflow)) this.dismiss(entry.id);\n    }\n\n    const entry: ToastEntry = {\n      dismissible: true,\n      duration: 5000,\n      ...item,\n      exitTimeoutId: null,\n      id,\n      phase: 'entering',\n      timer: null,\n    };\n\n    this.#setEntries([...this.#entries.value, entry]);\n    this.#emit({ id, type: 'add' });\n\n    requestAnimationFrame(() => {\n      if (this.#entry(id)?.phase === 'entering') this.#update(id, { phase: 'active' });\n    });\n\n    if (entry.duration > 0) this.#scheduleTimer(id, entry.duration);\n\n    return id;\n  }\n\n  clear(): void {\n    for (const entry of this.#entries.value) {\n      if (entry.phase !== 'exiting') this.dismiss(entry.id);\n    }\n  }\n\n  dispose(): void {\n    if (this.#disposed) return;\n\n    this.#disposed = true;\n\n    for (const entry of this.#entries.value) {\n      if (entry.timer) clearTimeout(entry.timer.timeoutId);\n\n      if (entry.exitTimeoutId) clearTimeout(entry.exitTimeoutId);\n    }\n\n    this.#setEntries([]);\n    this.#listeners.clear();\n    this.#eventListeners.clear();\n  }\n\n  dismiss(id: string): void {\n    const entry = this.#entry(id);\n\n    if (!entry || entry.phase === 'exiting' || this.#disposed) return;\n\n    this.#update(id, { ...this.#clearTimer(entry), phase: 'exiting' });\n    this.scheduleFinalization(id, TOAST_EXIT_MS + 50);\n  }\n\n  finalize(id: string): void {\n    const entry = this.#entry(id);\n\n    if (!entry || this.#disposed) return;\n\n    if (entry.timer) clearTimeout(entry.timer.timeoutId);\n\n    if (entry.exitTimeoutId) clearTimeout(entry.exitTimeoutId);\n\n    this.#setEntries(this.#entries.value.filter((candidate) => candidate.id !== id));\n    entry.onDismiss?.();\n    this.#emit({ id, type: 'dismiss' });\n  }\n\n  pauseTimers(): void {\n    if (this.#disposed) return;\n\n    this.#setEntries(\n      this.#entries.value.map((entry) => {\n        if (!entry.timer) return entry;\n\n        clearTimeout(entry.timer.timeoutId);\n\n        return {\n          ...entry,\n          timer: {\n            ...entry.timer,\n            remaining: Math.max(0, entry.timer.remaining - (Date.now() - entry.timer.startedAt)),\n          },\n        };\n      }),\n    );\n  }\n\n  resumeTimers(): void {\n    if (this.#disposed) return;\n\n    for (const entry of this.#entries.value) {\n      if (entry.phase === 'active' && entry.timer && entry.timer.remaining > 0) {\n        this.#scheduleTimer(entry.id, entry.timer.remaining);\n      }\n    }\n  }\n\n  scheduleFinalization(id: string, delay: number): void {\n    const entry = this.#entry(id);\n\n    if (entry?.phase !== 'exiting' || this.#disposed) return;\n\n    if (entry.exitTimeoutId) clearTimeout(entry.exitTimeoutId);\n\n    const exitTimeoutId = setTimeout(() => this.finalize(id), delay);\n\n    this.#update(id, { exitTimeoutId });\n  }\n\n  setMax(max: number | undefined): void {\n    if (max != null) this.#max = Math.max(1, max);\n  }\n\n  subscribe(listener: (entries: ToastEntry[]) => void): () => void {\n    listener(this.#entries.value);\n    this.#listeners.add(listener);\n\n    return () => this.#listeners.delete(listener);\n  }\n\n  subscribeEvents(listener: (event: ToastStoreEvent) => void): () => void {\n    this.#eventListeners.add(listener);\n\n    return () => this.#eventListeners.delete(listener);\n  }\n\n  update(id: string, updates: Partial<ToastItem>): void {\n    const entry = this.#entry(id);\n\n    if (!entry || this.#disposed) return;\n\n    const cleared = updates.duration !== undefined ? this.#clearTimer(entry) : entry;\n\n    this.#update(id, { ...cleared, ...updates, id });\n\n    if (updates.duration !== undefined && updates.duration > 0) this.#scheduleTimer(id, updates.duration);\n  }\n\n  #clearTimer(entry: ToastEntry): ToastEntry {\n    if (entry.timer) clearTimeout(entry.timer.timeoutId);\n\n    return { ...entry, timer: null };\n  }\n\n  #emit(event: ToastStoreEvent): void {\n    for (const listener of this.#eventListeners) listener(event);\n  }\n\n  #entry(id: string): ToastEntry | undefined {\n    return this.#entries.value.find((entry) => entry.id === id);\n  }\n\n  #scheduleTimer(id: string, remaining: number): void {\n    if (remaining <= 0 || this.#disposed) return;\n\n    const timeoutId = setTimeout(() => this.dismiss(id), remaining);\n\n    this.#update(id, { timer: { remaining, startedAt: Date.now(), timeoutId } });\n  }\n\n  #setEntries(entries: ToastEntry[]): void {\n    this.#entries.value = entries;\n    for (const listener of this.#listeners) listener(entries);\n  }\n\n  #update(id: string, patch: Partial<ToastEntry>): void {\n    this.#setEntries(this.#entries.value.map((entry) => (entry.id === id ? { ...entry, ...patch } : entry)));\n  }\n}\n\ntype ToastHostBinding = {\n  bind: (store: ToastStore) => void;\n  unbind: () => void;\n};\n\nconst hostBindings = new WeakMap<HTMLElement, ToastHostBinding>();\nconst hostStores = new WeakMap<HTMLElement, ToastStore>();\n\nconst bindToastHost = (host: HTMLElement, store: ToastStore): void => {\n  hostStores.set(host, store);\n  hostBindings.get(host)?.bind(store);\n};\n\n/** Renders the action buttons for a toast entry. */\nfunction renderToastActions(entry: ToastEntry, dismiss: () => void) {\n  if (!entry.actions?.length) return '';\n\n  return html`\n    <div slot=\"actions\" class=\"toast-actions\">\n      ${entry.actions.map(\n        (action) => html`\n          <ore-button\n            size=\"sm\"\n            color=${action.color || entry.color || 'primary'}\n            variant=${action.variant || 'solid'}\n            @click=${() => {\n              action.onClick?.();\n              dismiss();\n            }}>\n            ${action.label}\n          </ore-button>\n        `,\n      )}\n    </div>\n  `;\n}\n\nexport const TOAST_TAG = 'ore-toast' as const;\n\n/**\n * Declarative toast host. It subscribes to the service for its scope and\n * renders notifications, but has no imperative mutation API of its own.\n *\n * @element ore-toast\n *\n * @attr {string} position - Stack placement.\n * @attr {number} max - Maximum live notifications for the scoped service.\n */\ndefine<OreToastProps>(TOAST_TAG, {\n  props: {\n    max: prop.number(5),\n    position: prop.oneOf(\n      ['top-left', 'top-center', 'top-right', 'bottom-left', 'bottom-center', 'bottom-right'] as const,\n      'bottom-right',\n    ),\n  },\n  setup() {\n    const el = getHost() as HTMLElement;\n    const emit = useEmit<OreToastEvents>();\n    const containerRef = ref<HTMLDivElement>();\n    const entries = signal<ToastEntry[]>([]);\n    const hoverPaused = signal(false);\n    const focusPaused = signal(false);\n    const paused = computed(() => hoverPaused.value || focusPaused.value);\n    const swipeControls = new Map<string, { element: HTMLElement; gesture: PanGesture }>();\n    const exiting = new Map<string, () => void>();\n    const swiping = new Set<string>();\n    let pendingSyncFrame: number | undefined;\n    let store: ToastStore | null = null;\n    let unsubscribeEntries = () => {};\n    let unsubscribeEvents = () => {};\n\n    const getInner = (wrapper: HTMLElement): HTMLElement | null => {\n      return wrapper.querySelector<HTMLElement>('.toast-inner');\n    };\n\n    const clearExitListener = (id: string): void => {\n      exiting.get(id)?.();\n      exiting.delete(id);\n    };\n\n    const finalizeSwipe = (id: string): void => {\n      swiping.delete(id);\n      store?.finalize(id);\n    };\n\n    const createToastSwipe = (id: string, wrapper: HTMLElement): PanGesture => {\n      const isDismissible = (): boolean => entries.value.find((entry) => entry.id === id)?.dismissible ?? true;\n      const reset = (): void => {\n        const inner = getInner(wrapper);\n\n        if (!inner) return;\n\n        inner.style.transition = '';\n        inner.style.transform = '';\n        inner.style.opacity = '';\n      };\n\n      return createPanGesture(wrapper, {\n        axis: 'x',\n        disabled: () => !isDismissible(),\n        onEnd: ({ distance, reason }) => {\n          if (reason !== 'release' || Math.abs(distance) < 48) {\n            reset();\n\n            return;\n          }\n\n          const inner = getInner(wrapper);\n\n          if (!inner || !store) return;\n\n          swiping.add(id);\n\n          store.dismiss(id);\n\n          const finish = () => finalizeSwipe(id);\n\n          if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {\n            inner.style.opacity = '0';\n            finish();\n\n            return;\n          }\n\n          const direction = distance >= 0 ? 1 : -1;\n\n          inner.style.transition = 'transform 0.22s ease-out, opacity 0.22s ease-out';\n          void inner.offsetWidth;\n          inner.style.transform = `translateX(${direction * 120}%)`;\n          inner.style.opacity = '0';\n\n          const onTransitionEnd = (transition: TransitionEvent) => {\n            if (transition.target !== inner || transition.propertyName !== 'transform') return;\n\n            inner.removeEventListener('transitionend', onTransitionEnd);\n            finish();\n          };\n\n          inner.addEventListener('transitionend', onTransitionEnd);\n          store.scheduleFinalization(id, 300);\n        },\n        onMove: ({ distance }) => {\n          const inner = getInner(wrapper);\n\n          if (!inner) return;\n\n          inner.style.transition = 'none';\n          inner.style.transform = `translateX(${distance}px)`;\n          inner.style.opacity = String(Math.max(0, 1 - Math.abs(distance) / 200));\n        },\n        pointerCapture: false,\n        shouldStart: (event) =>\n          !event\n            .composedPath()\n            .some((node) => node instanceof Element && node.matches('button, a, input, select, textarea, ore-button')),\n      });\n    };\n\n    const beginExit = (id: string): void => {\n      if (!store || exiting.has(id) || swiping.has(id)) return;\n\n      requestAnimationFrame(() => {\n        if (!store || exiting.has(id) || swiping.has(id)) return;\n\n        const inner = containerRef.value?.querySelector<HTMLElement>(`[data-toast-id=\"${id}\"] .toast-inner`);\n\n        if (!inner) {\n          store.scheduleFinalization(id, TOAST_EXIT_MS);\n\n          return;\n        }\n\n        void inner.offsetHeight;\n\n        const duration = parseFloat(getComputedStyle(inner).transitionDuration) * 1000;\n        const exitMs = Number.isFinite(duration) && duration > 0 ? duration : TOAST_EXIT_MS;\n        const onTransitionEnd = (event: TransitionEvent) => {\n          const wrapper = (event.target as HTMLElement | null)?.closest?.(`[data-toast-id=\"${id}\"]`);\n\n          if (!wrapper) return;\n\n          clearExitListener(id);\n          store?.finalize(id);\n        };\n        const remove = () => containerRef.value?.removeEventListener('transitionend', onTransitionEnd);\n\n        exiting.set(id, remove);\n        containerRef.value?.addEventListener('transitionend', onTransitionEnd);\n        store.scheduleFinalization(id, exitMs + 50);\n      });\n    };\n\n    const syncControls = (): void => {\n      const currentIds = new Set(entries.value.map((entry) => entry.id));\n\n      for (const [id, control] of swipeControls) {\n        if (!currentIds.has(id)) {\n          control.gesture.dispose();\n\n          swipeControls.delete(id);\n          clearExitListener(id);\n          swiping.delete(id);\n        }\n      }\n\n      for (const entry of entries.value) {\n        const wrapper = containerRef.value?.querySelector<HTMLElement>(`[data-toast-id=\"${entry.id}\"]`);\n        const control = swipeControls.get(entry.id);\n\n        if (wrapper && control?.element !== wrapper) {\n          control?.gesture.dispose();\n          swipeControls.set(entry.id, { element: wrapper, gesture: createToastSwipe(entry.id, wrapper) });\n        }\n\n        if (entry.phase === 'exiting') beginExit(entry.id);\n      }\n    };\n\n    const scheduleSyncControls = (): void => {\n      syncControls();\n\n      if (pendingSyncFrame !== undefined) cancelAnimationFrame(pendingSyncFrame);\n\n      pendingSyncFrame = requestAnimationFrame(() => {\n        pendingSyncFrame = undefined;\n        syncControls();\n      });\n    };\n\n    watch(entries, scheduleSyncControls);\n    watch(paused, (isPaused) => {\n      if (isPaused) store?.pauseTimers();\n      else store?.resumeTimers();\n    });\n\n    const bind = (nextStore: ToastStore): void => {\n      if (store === nextStore) return;\n\n      unsubscribeEntries();\n\n      unsubscribeEvents();\n      store = nextStore;\n      unsubscribeEntries = store.subscribe((nextEntries) => {\n        entries.value = nextEntries;\n      });\n      unsubscribeEvents = store.subscribeEvents((event) => emit(event.type, { id: event.id }));\n\n      if (paused.value) store.pauseTimers();\n    };\n\n    const renderEntry = (entry: ToastEntry) => {\n      const dismiss = () => store?.dismiss(entry.id);\n\n      return html`\n        <div\n          class=\"toast-wrapper\"\n          data-toast-id=${entry.id}\n          part=\"toast-wrapper\">\n          <div class=\"${() => `toast-inner${entry.phase !== 'active' ? ` ${entry.phase}` : ''}`}\" part=\"toast-inner\">\n            <ore-alert\n              color=${entry.color || (entry.urgency === 'assertive' ? 'error' : 'primary')}\n              variant=${entry.variant || 'solid'}\n              size=${entry.size || 'md'}\n              rounded=${entry.rounded || 'md'}\n              ?horizontal=${entry.horizontal}\n              heading=${entry.heading || ''}\n              ?dismissible=${entry.dismissible}\n              @dismiss=${dismiss}>\n              ${\n                entry.meta\n                  ? html`\n                      <span slot=\"meta\">${entry.meta}</span>\n                    `\n                  : ''\n              }\n              ${entry.message} ${renderToastActions(entry, dismiss)}\n            </ore-alert>\n          </div>\n        </div>\n      `;\n    };\n\n    onMounted(() => {\n      hostBindings.set(el, {\n        bind,\n        unbind() {\n          unsubscribeEntries();\n          unsubscribeEvents();\n          store = null;\n          entries.value = [];\n        },\n      });\n\n      const boundStore = hostStores.get(el);\n\n      if (boundStore) bind(boundStore);\n    });\n\n    onCleanup(() => {\n      hostBindings.get(el)?.unbind();\n\n      hostBindings.delete(el);\n\n      if (pendingSyncFrame !== undefined) cancelAnimationFrame(pendingSyncFrame);\n\n      for (const control of swipeControls.values()) control.gesture.dispose();\n      swipeControls.clear();\n      for (const id of exiting.keys()) clearExitListener(id);\n    });\n\n    const urgencyOf = (entry: ToastEntry) => entry.urgency ?? (entry.color === 'error' ? 'assertive' : 'polite');\n    const politeEntries = computed(() => entries.value.filter((entry) => urgencyOf(entry) === 'polite'));\n    const assertiveEntries = computed(() => entries.value.filter((entry) => urgencyOf(entry) === 'assertive'));\n\n    return html`\n      <div\n        class=\"toast-container\"\n        ref=${containerRef}\n        @pointerenter=${() => {\n          hoverPaused.value = true;\n          el.classList.add('hovered');\n        }}\n        @pointerleave=${() => {\n          hoverPaused.value = false;\n          el.classList.remove('hovered');\n        }}\n        @focusin=${() => {\n          focusPaused.value = true;\n        }}\n        @focusout=${() => {\n          focusPaused.value = false;\n        }}\n        part=\"container\">\n        <div\n          role=\"region\"\n          aria-live=\"polite\"\n          aria-relevant=\"additions removals\"\n          aria-atomic=\"false\"\n          aria-label=\"Notifications\"\n          class=\"toast-live-region\">\n          ${() => politeEntries.value.map(renderEntry)}\n        </div>\n        <div\n          role=\"region\"\n          aria-live=\"assertive\"\n          aria-relevant=\"additions removals\"\n          aria-atomic=\"false\"\n          aria-label=\"Critical notifications\"\n          class=\"toast-live-region\">\n          ${() => assertiveEntries.value.map(renderEntry)}\n        </div>\n        <slot></slot>\n      </div>\n    `;\n  },\n  styles: [reducedMotionMixin, componentStyles],\n});\n\nexport type ToastServiceConfig = OreToastProps;\n\nexport interface ToastService {\n  add(item: ToastItem): string;\n  clear(): void;\n  configure(config: ToastServiceConfig): void;\n  dismiss(id: string): void;\n  readonly disposalSignal: AbortSignal;\n  dispose(): void;\n  readonly disposed: boolean;\n  error(message: string, opts?: Partial<ToastItem>): string;\n  info(message: string, opts?: Partial<ToastItem>): string;\n  promise<T>(\n    promise: Promise<T>,\n    messages: {\n      error: string | ((err: unknown) => string);\n      loading: string;\n      success: string | ((data: T) => string);\n    },\n  ): Promise<T>;\n  success(message: string, opts?: Partial<ToastItem>): string;\n  update(id: string, updates: Partial<ToastItem>): void;\n  warning(message: string, opts?: Partial<ToastItem>): string;\n  [Symbol.dispose](): void;\n}\n\nconst services = new WeakMap<ParentNode, ToastService>();\n\n/**\n * Creates a scoped toast service. The service owns its notification store and\n * binds it to the declarative `<ore-toast>` host inside `root`, creating that\n * host lazily when notifications are first requested.\n */\nexport function createToastService(root: ParentNode = document.body): ToastService {\n  const existing = services.get(root);\n\n  if (existing) return existing;\n\n  const store = new ToastStore();\n  const disposalController = new AbortController();\n  let disposed = false;\n  let configured = false;\n  let pendingConfig: ToastServiceConfig | null = null;\n  let host: HTMLElement | null = null;\n\n  const assertActive = (): boolean => !disposed;\n  const rootNode = root as Element | Document | ShadowRoot;\n  const getHost = (): HTMLElement | null => {\n    if (!assertActive()) return null;\n\n    if (host?.isConnected) return host;\n\n    host = rootNode.querySelector<HTMLElement>(TOAST_TAG);\n\n    if (!host) {\n      host = document.createElement(TOAST_TAG);\n\n      if (pendingConfig?.position) host.setAttribute('position', pendingConfig.position);\n\n      if (pendingConfig?.max != null) host.setAttribute('max', String(pendingConfig.max));\n\n      rootNode.appendChild(host);\n    }\n\n    if (pendingConfig?.max != null) store.setMax(pendingConfig.max);\n    else {\n      const max = Number(host.getAttribute('max'));\n\n      if (Number.isFinite(max) && max > 0) store.setMax(max);\n    }\n\n    pendingConfig = null;\n    configured = true;\n    bindToastHost(host, store);\n\n    return host;\n  };\n  const ensureHost = (): boolean => Boolean(getHost());\n\n  const service: ToastService = {\n    add(item) {\n      if (!ensureHost()) return item.id ?? uuid();\n\n      return store.add(item);\n    },\n\n    clear() {\n      if (ensureHost()) store.clear();\n    },\n\n    configure(config) {\n      if (configured) {\n        warn('toast.configure() called after the container was already created; options ignored.');\n\n        return;\n      }\n\n      pendingConfig = { ...pendingConfig, ...config };\n    },\n\n    dismiss(id) {\n      if (ensureHost()) store.dismiss(id);\n    },\n\n    get disposalSignal() {\n      return disposalController.signal;\n    },\n\n    dispose() {\n      if (disposed) return;\n\n      disposed = true;\n\n      disposalController.abort();\n\n      store.dispose();\n\n      if (services.get(root) === service) services.delete(root);\n    },\n\n    get disposed() {\n      return disposed;\n    },\n\n    error(message, opts) {\n      return service.add({ color: 'error', ...opts, message });\n    },\n\n    info(message, opts) {\n      return service.add({ color: 'info', ...opts, message });\n    },\n\n    async promise(promise, messages) {\n      const id = service.add({ color: 'primary', dismissible: false, duration: 0, message: messages.loading });\n\n      try {\n        const data = await promise;\n\n        service.update(id, {\n          color: 'success',\n          dismissible: true,\n          duration: 5000,\n          message: typeof messages.success === 'function' ? messages.success(data) : messages.success,\n        });\n\n        return data;\n      } catch (err) {\n        service.update(id, {\n          color: 'error',\n          dismissible: true,\n          duration: 5000,\n          message: typeof messages.error === 'function' ? messages.error(err) : messages.error,\n        });\n        throw err;\n      }\n    },\n\n    success(message, opts) {\n      return service.add({ color: 'success', ...opts, message });\n    },\n\n    [Symbol.dispose]() {\n      service.dispose();\n    },\n\n    update(id, updates) {\n      if (ensureHost()) store.update(id, updates);\n    },\n\n    warning(message, opts) {\n      return service.add({ color: 'warning', ...opts, message });\n    },\n  };\n\n  services.set(root, service);\n\n  return service;\n}\n\n/** Singleton service backed by a lazily created host in `document.body`. */\nexport const toast: ToastService = createToastService();\n","@layer refine.base {\n  :host {\n    --_dot-color: var(--typing-indicator-color, var(--_theme-base, var(--color-contrast-400)));\n\n    display: inline-flex;\n    align-items: center;\n  }\n\n  .dots {\n    display: inline-flex;\n    gap: var(--_gap);\n    align-items: center;\n  }\n\n  .dot {\n    display: inline-block;\n    width: var(--_size);\n    height: var(--_size);\n    background: var(--_dot-color);\n    border-radius: 50%;\n    animation: var(--_motion-animation, typing-indicator-bounce 1.2s ease-in-out infinite);\n  }\n\n  .dot:nth-child(2) {\n    animation-delay: 0.15s;\n  }\n\n  .dot:nth-child(3) {\n    animation-delay: 0.3s;\n  }\n\n  @keyframes typing-indicator-bounce {\n    0%,\n    60%,\n    100% {\n      opacity: 0.4;\n      transform: translateY(0);\n    }\n\n    30% {\n      opacity: 1;\n      transform: translateY(-35%);\n    }\n  }\n}\n","import { define, html, prop } from '@vielzeug/ore';\nimport { watch } from '@vielzeug/ripple';\nimport { announce } from '../../core';\nimport { sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, reducedMotionMixin, sizeVariantMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport componentStyles from './typing-indicator.css?inline';\n\n/** Typing indicator component properties */\nexport type OreTypingIndicatorProps = {\n  /** Theme color for the dots */\n  color?: ThemeColor;\n  /** Accessible label announced once via a polite live region (default: `\"Typing…\"`) */\n  label?: string;\n  /** Dot size preset */\n  size?: ComponentSize;\n};\n\n/**\n * Three bouncing dots signaling that the other side of a conversation is composing a reply —\n * the moment before any content exists. For a message whose content is already streaming in,\n * use `ore-chat-message`'s `streaming` attribute (a blinking cursor) instead.\n *\n * The dots are decorative (`aria-hidden`) — `label` is the entire accessibility contract,\n * announced through the shared singleton live region (`core/announcer.ts`) rather than a\n * static `aria-live` element in the template. A live region populated in the same paint as\n * its own insertion is unreliable across browsers/screen readers; routing through the shared\n * announcer (pre-existing region, clear-then-set) is the same pattern already used for other\n * transient status messages across this package.\n *\n * @element ore-typing-indicator\n *\n * @attr {string} label - Accessible label announced once via a polite live region (default: \"Typing…\")\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n *\n * @cssprop --typing-indicator-color - Dot color\n * @cssprop --typing-indicator-size - Dot diameter\n * @cssprop --typing-indicator-gap - Gap between dots\n *\n * @part dots - Dots container.\n * @part dot - Individual dot element.\n * @example\n * ```html\n * <ore-typing-indicator></ore-typing-indicator>\n * <ore-typing-indicator label=\"Assistant is typing…\" color=\"primary\"></ore-typing-indicator>\n * ```\n */\nexport const TYPING_INDICATOR_TAG = 'ore-typing-indicator' as const;\ndefine<OreTypingIndicatorProps>(TYPING_INDICATOR_TAG, {\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    label: prop.string('Typing…'),\n  },\n  setup(props) {\n    watch(\n      () => props.label.value,\n      (label) => announce(label ?? ''),\n      { immediate: true },\n    );\n\n    return html`\n      <span class=\"dots\" part=\"dots\" aria-hidden=\"true\">\n        <span class=\"dot\" part=\"dot\"></span>\n        <span class=\"dot\" part=\"dot\"></span>\n        <span class=\"dot\" part=\"dot\"></span>\n      </span>\n    `;\n  },\n  styles: [\n    colorThemeMixin,\n    reducedMotionMixin,\n    sizeVariantMixin({\n      lg: {\n        gap: 'var(--typing-indicator-gap, var(--size-1-5))',\n        size: 'var(--typing-indicator-size, var(--size-2-5))',\n      },\n      md: { gap: 'var(--typing-indicator-gap, var(--size-1))', size: 'var(--typing-indicator-size, var(--size-2))' },\n      sm: {\n        gap: 'var(--typing-indicator-gap, var(--size-1))',\n        size: 'var(--typing-indicator-size, var(--size-1-5))',\n      },\n    }),\n    componentStyles,\n  ],\n});\n","export type { OreAlertEvents, OreAlertProps } from './alert/alert';\nexport { ALERT_TAG } from './alert/alert';\nexport type { OreAsyncEvents, OreAsyncProps } from './async/async';\nexport { ASYNC_TAG } from './async/async';\nexport type { OreBadgeProps } from './badge/badge';\nexport { BADGE_TAG } from './badge/badge';\nexport type { OreChipEvents, OreChipProps } from './chip/chip';\nexport { CHIP_TAG } from './chip/chip';\nexport type { OrePasswordStrengthProps, PasswordStrengthLevel } from './password-strength/password-strength';\nexport { PASSWORD_STRENGTH_TAG } from './password-strength/password-strength';\nexport type { OreProgressProps } from './progress/progress';\nexport { PROGRESS_TAG } from './progress/progress';\nexport type { OreSkeletonProps } from './skeleton/skeleton';\nexport { SKELETON_TAG } from './skeleton/skeleton';\nexport type { OreToastEvents, OreToastProps, ToastItem, ToastService, ToastServiceConfig } from './toast/toast';\nexport { createToastService, TOAST_TAG, toast } from './toast/toast';\nexport type { OreTypingIndicatorProps } from './typing-indicator/typing-indicator';\nexport { TYPING_INDICATOR_TAG } from './typing-indicator/typing-indicator';\n","@layer refine.base {\n  :host {\n    --_day-selected-bg: var(--calendar-day-selected-bg, var(--_theme-focus));\n    --_day-today-color: var(--calendar-day-today-color, var(--_theme-focus));\n    --_day-outside-opacity: var(--calendar-day-outside-opacity, 0.35);\n    --_bg: var(--calendar-bg, var(--color-canvas));\n    --_border-color: var(--calendar-border-color, var(--color-contrast-200));\n    --_radius: var(--calendar-radius, var(--rounded-xl));\n\n    display: inline-block;\n  }\n\n  :host([fullwidth]) {\n    display: block;\n  }\n\n  :host([color='secondary']) {\n    --_day-selected-bg: var(--calendar-day-selected-bg, var(--_theme-base));\n    --_day-today-color: var(--calendar-day-today-color, var(--_theme-base));\n  }\n\n  /* ── Root panel ──────────────────────────────────────────────────────────── */\n\n  .calendar {\n    display: flex;\n    flex-direction: column;\n    gap: var(--size-2);\n    min-width: 18rem;\n    padding: var(--size-3);\n    background: var(--_bg);\n    border: var(--border) solid var(--_border-color);\n    border-radius: var(--_radius);\n    box-shadow: var(--calendar-shadow, var(--shadow-md));\n  }\n\n  :host([fullwidth]) .calendar {\n    min-width: 0;\n  }\n\n  /* ── Header ──────────────────────────────────────────────────────────────── */\n\n  .cal-header {\n    display: flex;\n    gap: var(--size-1);\n    align-items: center;\n    justify-content: space-between;\n    padding-block-end: var(--size-2);\n    border-block-end: var(--border) solid var(--_border-color);\n  }\n\n  .nav-btn {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: var(--size-8);\n    height: var(--size-8);\n    padding: 0;\n    color: var(--color-contrast-600);\n    cursor: pointer;\n    outline: none;\n    background: transparent;\n    border: none;\n    border-radius: var(--rounded-md);\n    transition:\n      background var(--transition-fast),\n      color var(--transition-fast);\n  }\n\n  .nav-btn:hover:not(:disabled) {\n    color: var(--color-contrast-900);\n    background: var(--color-contrast-300);\n  }\n\n  .nav-btn:focus-visible {\n    box-shadow: 0 0 0 2px var(--_day-selected-bg);\n  }\n\n  .nav-btn:disabled {\n    cursor: not-allowed;\n    opacity: 0.4;\n  }\n\n  .cal-label-btn {\n    flex: 1;\n    padding: var(--size-1) var(--size-2);\n    font-size: var(--text-sm);\n    font-weight: var(--font-semibold);\n    color: var(--color-contrast-900);\n    text-align: center;\n    cursor: pointer;\n    outline: none;\n    background: transparent;\n    border: none;\n    border-radius: var(--rounded-md);\n    transition: background var(--transition-fast);\n  }\n\n  .cal-label-btn:hover:not(:disabled) {\n    background: var(--color-contrast-300);\n  }\n\n  .cal-label-btn:focus-visible {\n    box-shadow: 0 0 0 2px var(--_day-selected-bg);\n  }\n\n  .cal-label-btn:disabled {\n    cursor: not-allowed;\n    opacity: 0.5;\n  }\n\n  .cal-label-month,\n  .cal-label-year {\n    display: inline-block;\n  }\n\n  .cal-label-sep {\n    display: inline-block;\n    padding-inline: var(--size-1);\n    font-weight: var(--font-normal);\n    color: var(--color-contrast-400);\n  }\n\n  /* ── Grid base ───────────────────────────────────────────────────────────── */\n\n  [hidden] {\n    display: none;\n  }\n\n  .cal-grid {\n    display: flex;\n    flex-direction: column;\n    gap: var(--size-0-5);\n  }\n\n  .cal-grid-days {\n    display: grid;\n    grid-template-columns: repeat(7, minmax(0, 1fr));\n    gap: var(--size-0-5);\n\n    /* Reserve max height (6 week rows + 1 header) so the panel never shrinks\n       on 5-week months or when switching to month/year view. */\n    min-height: calc(7 * var(--size-10) + 6 * var(--size-0-5));\n  }\n\n  /* role=\"row\" wrappers exist for ARIA grid structure only — `display: contents`\n     removes them from layout so their children still participate directly in the\n     parent's CSS grid tracks. */\n  .cal-grid [role='row'] {\n    display: contents;\n  }\n\n  .cal-cell {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: var(--text-sm);\n    cursor: pointer;\n    outline: none;\n    border-radius: var(--rounded-md);\n    transition:\n      background var(--transition-fast),\n      color var(--transition-fast);\n  }\n\n  /* ── Column headers ──────────────────────────────────────────────────────── */\n\n  .cal-cell-head {\n    height: var(--size-8);\n    font-size: var(--text-xs);\n    font-weight: var(--font-medium);\n    color: var(--color-contrast-500);\n    cursor: default;\n  }\n\n  /* ── Day cells ───────────────────────────────────────────────────────────── */\n\n  .cal-cell-day {\n    flex-direction: column;\n    gap: var(--size-0-5);\n    min-width: 0;\n    height: var(--size-10);\n    overflow: hidden;\n    color: var(--color-contrast-800);\n  }\n\n  .cal-cell-day:hover:not([data-disabled]) {\n    color: var(--color-contrast-900);\n    background: color-mix(in oklch, var(--_day-selected-bg) 15%, transparent);\n  }\n\n  .cal-cell-day:focus-visible {\n    box-shadow: 0 0 0 2px var(--_day-selected-bg);\n  }\n\n  .cal-cell-day[data-today] {\n    font-weight: var(--font-semibold);\n    color: var(--_day-today-color);\n  }\n\n  .cal-cell-day[data-selected] {\n    font-weight: var(--font-semibold);\n    color: var(--color-white, #fff);\n    background: var(--_day-selected-bg);\n  }\n\n  .cal-cell-day[data-outside] {\n    opacity: var(--_day-outside-opacity);\n  }\n\n  .cal-cell-day[data-disabled] {\n    pointer-events: none;\n    cursor: not-allowed;\n    opacity: 0.3;\n  }\n\n  /* ── Event dots (normal mode) ────────────────────────────────────────────── */\n\n  .cal-dots {\n    display: flex;\n    gap: 2px;\n    align-items: center;\n    justify-content: center;\n    margin-block-start: var(--size-0-5);\n  }\n\n  .cal-dot {\n    --badge-bg: var(--_day-selected-bg);\n    --badge-border-color: var(--_day-selected-bg);\n  }\n\n  .cal-dot-overflow {\n    font-size: 8px;\n    font-weight: var(--font-semibold);\n    line-height: 1;\n    color: var(--color-contrast-500);\n  }\n\n  /* ── Month / year grids ──────────────────────────────────────────────────── */\n\n  .cal-grid-months,\n  .cal-grid-years {\n    /* 4-column grid — same width as cal-grid-days, natural height. */\n    display: grid;\n    grid-template-columns: repeat(4, minmax(0, 1fr));\n    gap: var(--size-1);\n  }\n\n  .cal-cell-month,\n  .cal-cell-year {\n    height: var(--size-10);\n    font-size: var(--text-sm);\n    color: var(--color-contrast-800);\n    cursor: pointer;\n    border-radius: var(--rounded-md);\n  }\n\n  .cal-cell-month:hover:not([data-disabled]),\n  .cal-cell-year:hover:not([data-disabled]) {\n    background: color-mix(in oklch, var(--_day-selected-bg) 15%, transparent);\n  }\n\n  .cal-cell-month:focus-visible,\n  .cal-cell-year:focus-visible {\n    box-shadow: 0 0 0 2px var(--_day-selected-bg);\n  }\n\n  .cal-cell-month[data-selected],\n  .cal-cell-year[data-selected] {\n    font-weight: var(--font-semibold);\n    color: var(--color-white, #fff);\n    background: var(--_day-selected-bg);\n  }\n\n  .cal-cell-month[data-disabled],\n  .cal-cell-year[data-disabled] {\n    pointer-events: none;\n    cursor: not-allowed;\n    opacity: 0.3;\n  }\n\n  /* ── Expanded variant ────────────────────────────────────────────────────── */\n\n  :host([expanded]) {\n    display: block;\n    width: 100%;\n  }\n\n  :host([expanded]) .calendar {\n    width: 100%;\n    min-width: 0;\n    padding: 0;\n    overflow: hidden;\n  }\n\n  :host([expanded]) .cal-header {\n    padding: var(--size-3) var(--size-4);\n  }\n\n  :host([expanded]) .cal-label-btn {\n    font-size: var(--text-base);\n  }\n\n  :host([expanded]) .cal-grid {\n    gap: 0;\n  }\n\n  :host([expanded]) .cal-grid-days {\n    gap: 0;\n    border-block-start: var(--border) solid var(--_border-color);\n  }\n\n  :host([expanded]) .cal-cell {\n    border-radius: 0;\n  }\n\n  :host([expanded]) .cal-cell-head {\n    height: var(--size-9);\n    font-size: var(--text-xs);\n    font-weight: var(--font-semibold);\n    text-transform: uppercase;\n    letter-spacing: 0.05em;\n    border-block-end: var(--border) solid var(--_border-color);\n  }\n\n  :host([expanded]) .cal-cell-day {\n    position: relative;\n    flex-direction: column;\n    gap: 0;\n    align-items: flex-start;\n    justify-content: flex-start;\n    height: auto;\n    min-height: var(--calendar-expanded-cell-height, var(--size-28));\n    aspect-ratio: auto;\n    padding: var(--size-2);\n    font-size: var(--text-sm);\n    vertical-align: top;\n    border-block-end: var(--border) solid var(--_border-color);\n    border-inline-end: var(--border) solid var(--_border-color);\n  }\n\n  /* Remove right border on last column */\n  :host([expanded]) .cal-cell-day:nth-child(7n) {\n    border-inline-end: none;\n  }\n\n  :host([expanded]) .cal-cell-day:hover:not([data-disabled]) {\n    background: color-mix(in oklch, var(--_day-selected-bg) 6%, transparent);\n  }\n\n  /* Selected day — circle around the number only */\n  :host([expanded]) .cal-cell-day[data-selected] {\n    color: inherit;\n    background: transparent;\n  }\n\n  :host([expanded]) .cal-cell-day[data-selected]::before {\n    position: absolute;\n    top: var(--size-1-5);\n    left: var(--size-1-5);\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: var(--size-7);\n    height: var(--size-7);\n    font-size: var(--text-sm);\n    font-weight: var(--font-semibold);\n    color: var(--color-white, #fff);\n    content: attr(data-day);\n    background: var(--_day-selected-bg);\n    border-radius: var(--rounded-full);\n  }\n\n  /* Today — circle in accent colour */\n  :host([expanded]) .cal-cell-day[data-today] {\n    font-weight: inherit;\n    color: inherit;\n  }\n\n  :host([expanded]) .cal-cell-day[data-today]::before {\n    position: absolute;\n    top: var(--size-1-5);\n    left: var(--size-1-5);\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: var(--size-7);\n    height: var(--size-7);\n    font-size: var(--text-sm);\n    font-weight: var(--font-semibold);\n    color: var(--color-white, #fff);\n    content: attr(data-day);\n    background: var(--_day-today-color);\n    border-radius: var(--rounded-full);\n  }\n\n  /* When both today AND selected — selected wins */\n  :host([expanded]) .cal-cell-day[data-today][data-selected]::before {\n    background: var(--_day-selected-bg);\n  }\n\n  /* ── Expanded event pills ────────────────────────────────────────────────── */\n\n  /* Push events below the day-number circle row */\n  :host([expanded]) .cal-events {\n    display: flex;\n    flex-direction: column;\n    gap: 2px;\n    width: 100%;\n    margin-block-start: var(--size-4);\n    overflow: hidden;\n  }\n\n  :host([expanded]) .cal-event-pill {\n    --badge-max-width: 100%;\n    max-width: 100%;\n  }\n\n  :host([expanded]) .cal-event-pill-overflow {\n    padding-inline: var(--size-1);\n    font-size: 10px;\n    font-weight: var(--font-semibold);\n    color: var(--color-contrast-500);\n  }\n\n  /* Dots are hidden in expanded mode — pills take over */\n  :host([expanded]) .cal-dots {\n    display: none;\n  }\n\n  :host([expanded]) .cal-cell-day[data-outside] {\n    background: color-mix(in oklch, var(--color-contrast-900) 2%, transparent);\n  }\n\n  /* Expanded month / year grids */\n  :host([expanded]) .cal-grid-months,\n  :host([expanded]) .cal-grid-years {\n    gap: var(--size-2);\n    min-height: 0;\n    padding: var(--size-4);\n  }\n\n  :host([expanded]) .cal-cell-month,\n  :host([expanded]) .cal-cell-year {\n    min-height: var(--size-16);\n    font-size: var(--text-base);\n    border: var(--border) solid var(--_border-color);\n    border-radius: var(--rounded-lg);\n  }\n\n  :host([expanded]) .cal-cell-month[data-selected],\n  :host([expanded]) .cal-cell-year[data-selected] {\n    border-color: transparent;\n  }\n\n  /* ── Disabled host ───────────────────────────────────────────────────────── */\n\n  :host(.is-disabled) .calendar {\n    pointer-events: none;\n    opacity: 0.6;\n  }\n\n  /* ── Reduced motion ──────────────────────────────────────────────────────── */\n\n  @media (prefers-reduced-motion: reduce) {\n    .nav-btn,\n    .cal-label-btn,\n    .cal-cell {\n      transition: none;\n    }\n  }\n}\n","import { bind, define, html, prop, styleMap, useEmit, useField } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { format, Temporal } from '@vielzeug/tempo';\n\nimport type { ComponentSize, RoundedSize, ThemeColor } from '../../shared';\n\nimport '../../content/icon/icon';\nimport '../../feedback/badge/badge';\nimport { createDatePickerControl, type DatePickerView, parseIso, toIsoString } from '../../core';\nimport { disablableBundle, roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, reducedMotionMixin } from '../../styles';\nimport componentStyles from './calendar.css?inline';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type OreCalendarEvents = {\n  change: { isoValue: string | null };\n};\n\n/**\n * A calendar event entry.\n * Dates must be ISO 8601 strings (yyyy-MM-dd).\n *\n * The `color` field accepts any valid CSS color value (e.g. `'#e11d48'`,\n * `'var(--color-primary)'`). An invalid value silently falls back to the\n * component's theme color. Only pass values you control.\n */\nexport type CalendarEvent = {\n  /**\n   * Any CSS color value for the event dot / pill.\n   * Defaults to the component's theme color when omitted.\n   * Rendered via `styleMap()`, which strips `;`/`{`/`}` so the value can't break out of\n   * its custom-property declaration — it is not a full CSS-color syntax validator, so an\n   * invalid (but injection-safe) value may still render as no color.\n   */\n  color?: string;\n  /** ISO date the event falls on (yyyy-MM-dd) */\n  date: string;\n  /** Unique identifier */\n  id: string;\n  /** Short label shown in the calendar cell */\n  label: string;\n};\n\nexport type OreCalendarProps = {\n  /** Theme color */\n  color?: ThemeColor;\n  /** Disable all date selection */\n  disabled?: boolean;\n  /**\n   * Array of calendar events to display on day cells.\n   * In normal mode each event renders as a small colored dot (max 3 dots, then \"+N\").\n   * In expanded mode each event renders as a full-width colored pill with its label.\n   * Pass as a JS property or as a JSON-encoded attribute.\n   * @example\n   * ```js\n   * calendar.events = [\n   *   { id: '1', date: '2025-06-15', label: 'Team standup', color: 'var(--color-primary)' },\n   *   { id: '2', date: '2025-06-20', label: 'Release', color: '#e11d48' },\n   * ];\n   * ```\n   */\n  events?: CalendarEvent[];\n  /**\n   * Expanded layout — large cells with top-aligned day numbers suitable\n   * for a full-page calendar app view.\n   */\n  expanded?: boolean;\n  /** Expand to container width */\n  fullwidth?: boolean;\n  /** Locale for day/month names (default: browser locale) */\n  locale?: string;\n  /** Latest selectable date in ISO 8601 format (yyyy-MM-dd) */\n  max?: string;\n  /** Earliest selectable date in ISO 8601 format (yyyy-MM-dd) */\n  min?: string;\n  /** Form field name (when used inside a form) */\n  name?: string;\n  /** Mark field as required */\n  required?: boolean;\n  /** Border radius override */\n  rounded?: RoundedSize;\n  /** Component size */\n  size?: ComponentSize;\n  /**\n   * Selected date in ISO 8601 format (yyyy-MM-dd).\n   * @example '2025-06-15'\n   */\n  value?: string;\n  /**\n   * Day-of-week indices to disable (0 = Sunday … 6 = Saturday).\n   * Pass as a JSON array attribute or a JS property.\n   * @example\n   * ```html\n   * <ore-calendar weekend-days=\"[0,6]\"></ore-calendar>\n   * ```\n   */\n  'weekend-days'?: number[];\n};\n\n/**\n * An accessible, keyboard-navigable inline calendar component.\n * Supports day/month/year drill-down views, min/max bounds, disabled weekend\n * days, and optional form association.\n *\n * @element ore-calendar\n *\n * @attr {string} value - Selected date in ISO 8601 format (yyyy-MM-dd)\n * @attr {string} min - Minimum selectable date (yyyy-MM-dd)\n * @attr {string} max - Maximum selectable date (yyyy-MM-dd)\n * @attr {boolean} disabled - Disable all interaction\n * @attr {boolean} required - Required field (form association)\n * @attr {string} name - Form field name\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {string} locale - BCP 47 locale string\n * @attr {string} weekend-days - JSON array of day indices to disable (0=Sun…6=Sat)\n * @attr {boolean} fullwidth - Expand to full container width\n * @attr {boolean} expanded - Large-cell calendar-app layout with top-aligned day numbers\n *\n * @fires change - Fired when a date is selected. detail: { isoValue: string | null }\n *\n * @cssprop --calendar-bg - Calendar background\n * @cssprop --calendar-border-color - Calendar border color\n * @cssprop --calendar-radius - Calendar border radius\n * @cssprop --calendar-shadow - Calendar drop shadow\n * @cssprop --calendar-day-selected-bg - Background of selected day cell\n * @cssprop --calendar-day-today-color - Colour of today's date number\n * @cssprop --calendar-day-outside-opacity - Opacity of days outside visible month\n *\n * @part calendar - The root calendar panel\n * @part header - Calendar header (nav + label)\n * @part grid - Day grid\n * @part day - Individual day cell\n *\n * @example\n * ```html\n * <!-- Single date with bounds -->\n * <ore-calendar value=\"2025-06-15\" min=\"2025-01-01\" max=\"2025-12-31\" color=\"primary\"></ore-calendar>\n *\n * <!-- Expanded calendar-app layout -->\n * <ore-calendar expanded fullwidth color=\"primary\"></ore-calendar>\n * ```\n */\nexport const CALENDAR_TAG = 'ore-calendar' as const;\n\n/** Maximum event dots/pills shown per cell before \"+N\" overflow */\nconst MAX_EVENTS = 3;\n\n// ── Component ────────────────────────────────────────────────────────────────\n\ndefine<OreCalendarProps>(CALENDAR_TAG, {\n  formAssociated: true,\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...disablableBundle,\n    ...roundableBundle,\n    events: prop.json([] as CalendarEvent[]),\n    expanded: prop.bool(false),\n    fullwidth: prop.bool(false),\n    locale: prop.string(),\n    max: prop.string(),\n    min: prop.string(),\n    name: prop.string(),\n    required: prop.bool(false),\n    value: prop.string(),\n    'weekend-days': prop.json([] as number[]),\n  },\n\n  setup(props) {\n    const emit = useEmit<OreCalendarEvents>();\n\n    // ── Derived flags ────────────────────────────────────────────────────────\n\n    const isDisabled = computed(() => props.disabled.value === true);\n    const isExpanded = computed(() => props.expanded.value === true);\n\n    // ── Selected date: local-override pattern ─────────────────────────────────\n    // `localSelection` holds a user-initiated pick (or undefined = no override).\n    // `selectedDate` derives from it, falling back to the value prop reactively.\n    // This eliminates setInterval polling — external prop changes propagate\n    // through the computed graph automatically.\n\n    const localSelection = signal<Temporal.PlainDate | null | undefined>(undefined);\n\n    const selectedDate = computed(() =>\n      localSelection.value !== undefined ? localSelection.value : parseIso(props.value.value),\n    );\n\n    // ── Date-picker control ──────────────────────────────────────────────────\n\n    const ctrl = createDatePickerControl({\n      get locale() {\n        return props.locale.value ?? (typeof navigator !== 'undefined' ? navigator.language : 'en');\n      },\n      get max() {\n        return parseIso(props.max.value);\n      },\n      get min() {\n        return parseIso(props.min.value);\n      },\n      onChange(date) {\n        localSelection.value = date;\n        currentView.value = 'day';\n        displayYear.value = ctrl.displayYear();\n        displayMonth.value = ctrl.displayMonth();\n        emit('change', { isoValue: toIsoString(date) });\n      },\n      get value() {\n        return selectedDate.value;\n      },\n      get weekendDays() {\n        return props['weekend-days'].value ?? [];\n      },\n    });\n\n    // ── Reactive display state ────────────────────────────────────────────────\n    // Three separate primitive signals — the proven pattern. Mutating any one\n    // of them invalidates only the computeds that read it.\n\n    const currentView = signal<DatePickerView>('day');\n    const displayYear = signal(ctrl.displayYear());\n    const displayMonth = signal(ctrl.displayMonth()); // 1-indexed (Temporal)\n\n    // ── Form value ───────────────────────────────────────────────────────────\n\n    useField<string>({\n      disabled: isDisabled,\n      toFormValue: (v) => v || null,\n      value: computed(() => toIsoString(selectedDate.value) ?? ''),\n    });\n\n    // ── Events lookup ─────────────────────────────────────────────────────────\n\n    const eventsByDate = computed(() => {\n      const map = new Map<string, CalendarEvent[]>();\n\n      for (const evt of props.events.value ?? []) {\n        const list = map.get(evt.date) ?? [];\n\n        list.push(evt);\n        map.set(evt.date, list);\n      }\n\n      return map;\n    });\n\n    // ── Derived cells ─────────────────────────────────────────────────────────\n    // Each reads a display signal so they re-run when navigation changes.\n\n    const dayCells = computed(() => {\n      void displayYear.value;\n      void displayMonth.value;\n      void selectedDate.value; // re-run when selection changes to refresh isSelected flags\n\n      return ctrl.dayCells();\n    });\n    const monthCells = computed(() => {\n      void displayYear.value;\n\n      return ctrl.monthCells();\n    });\n    const yearCells = computed(() => {\n      void displayYear.value;\n\n      return ctrl.yearCells();\n    });\n    const weekdayLabels = computed(() => ctrl.weekdayLabels());\n\n    const displayMonth_ = computed(() => {\n      const d = Temporal.PlainDate.from({ day: 1, month: displayMonth.value, year: displayYear.value });\n      const loc = props.locale.value ?? (typeof navigator !== 'undefined' ? navigator.language : 'en');\n\n      return format(d, { intl: { month: 'long' }, locale: loc, timeZone: 'UTC' });\n    });\n\n    const displayYear_ = computed(() => String(displayYear.value));\n    const displayLabel = computed(() => `${displayMonth_.value} ${displayYear_.value}`);\n\n    // ── Navigation ───────────────────────────────────────────────────────────\n\n    function handlePrev(): void {\n      if (currentView.value === 'day') ctrl.prevMonth();\n      else ctrl.prevYear();\n\n      displayYear.value = ctrl.displayYear();\n      displayMonth.value = ctrl.displayMonth();\n    }\n\n    function handleNext(): void {\n      if (currentView.value === 'day') ctrl.nextMonth();\n      else ctrl.nextYear();\n\n      displayYear.value = ctrl.displayYear();\n      displayMonth.value = ctrl.displayMonth();\n    }\n\n    function handleHeaderClick(): void {\n      const views: DatePickerView[] = ['day', 'month', 'year'];\n      const next = views[(views.indexOf(currentView.value) + 1) % views.length];\n\n      ctrl.setView(next);\n      currentView.value = next;\n    }\n\n    // ── Selection handlers — all disabled guards live here ────────────────────\n\n    function handleSelectMonth(month: number): void {\n      if (isDisabled.value) return;\n\n      ctrl.goTo(ctrl.displayYear(), month);\n      ctrl.setView('day');\n      displayYear.value = ctrl.displayYear();\n      displayMonth.value = ctrl.displayMonth();\n      currentView.value = 'day';\n    }\n\n    function handleSelectYear(year: number): void {\n      if (isDisabled.value) return;\n\n      ctrl.goTo(year, ctrl.displayMonth());\n      ctrl.setView('month');\n      displayYear.value = ctrl.displayYear();\n      currentView.value = 'month';\n    }\n\n    function handleSelectDay(isoStr: string): void {\n      if (isDisabled.value) return;\n\n      const date = parseIso(isoStr);\n\n      if (!date) return;\n\n      ctrl.select(date); // ctrl.select() internally rejects disabled/out-of-range dates\n    }\n\n    // ── Day-cell keyboard navigation (full ARIA grid pattern) ─────────────────\n\n    function handleDayKeydown(e: KeyboardEvent): void {\n      const cell = e.currentTarget as HTMLElement;\n      const grid = cell.closest('.cal-grid-days');\n\n      if (!grid) return;\n\n      const allCells = Array.from(grid.querySelectorAll<HTMLElement>('.cal-cell-day'));\n      const idx = allCells.indexOf(cell);\n\n      if (idx === -1) return;\n\n      let target: HTMLElement | undefined;\n\n      if (e.key === 'Enter' || e.key === ' ') {\n        e.preventDefault();\n        handleSelectDay(cell.dataset.iso ?? '');\n\n        return;\n      } else if (e.key === 'ArrowRight') {\n        target = allCells[idx + 1];\n      } else if (e.key === 'ArrowLeft') {\n        target = allCells[idx - 1];\n      } else if (e.key === 'ArrowDown') {\n        target = allCells[idx + 7];\n      } else if (e.key === 'ArrowUp') {\n        target = allCells[idx - 7];\n      } else if (e.key === 'Home') {\n        target = allCells[Math.floor(idx / 7) * 7]; // first cell in same row\n      } else if (e.key === 'End') {\n        target = allCells[Math.floor(idx / 7) * 7 + 6]; // last cell in same row\n      } else {\n        return;\n      }\n\n      e.preventDefault();\n      target?.focus();\n    }\n\n    // ── Month/year-cell keyboard navigation (fixed 4-column grid) ─────────────\n\n    function handleGridKeydown(e: KeyboardEvent, cellSelector: string, columns: number, onSelect: () => void): void {\n      const cell = e.currentTarget as HTMLElement;\n      const grid = cell.closest('.cal-grid');\n\n      if (!grid) return;\n\n      const allCells = Array.from(grid.querySelectorAll<HTMLElement>(cellSelector));\n      const idx = allCells.indexOf(cell);\n\n      if (idx === -1) return;\n\n      let target: HTMLElement | undefined;\n\n      if (e.key === 'Enter' || e.key === ' ') {\n        e.preventDefault();\n        onSelect();\n\n        return;\n      } else if (e.key === 'ArrowRight') {\n        target = allCells[idx + 1];\n      } else if (e.key === 'ArrowLeft') {\n        target = allCells[idx - 1];\n      } else if (e.key === 'ArrowDown') {\n        target = allCells[idx + columns];\n      } else if (e.key === 'ArrowUp') {\n        target = allCells[idx - columns];\n      } else if (e.key === 'Home') {\n        target = allCells[Math.floor(idx / columns) * columns];\n      } else if (e.key === 'End') {\n        target = allCells[Math.min(Math.floor(idx / columns) * columns + columns - 1, allCells.length - 1)];\n      } else {\n        return;\n      }\n\n      e.preventDefault();\n      target?.focus();\n    }\n\n    // ── Host bindings ────────────────────────────────────────────────────────\n\n    bind({\n      attr: {\n        'aria-disabled': () => (isDisabled.value ? 'true' : null),\n        'aria-label': () => displayLabel.value,\n        role: 'group',\n      },\n      class: {\n        'is-disabled': isDisabled,\n      },\n    });\n\n    // ── Template ─────────────────────────────────────────────────────────────\n\n    return html`\n      <div class=\"calendar\" part=\"calendar\" role=\"presentation\">\n        <!-- Header -->\n        <div class=\"cal-header\" part=\"header\">\n          <button class=\"nav-btn\" type=\"button\" aria-label=\"Previous\" ?disabled=\"${isDisabled}\" @click=\"${handlePrev}\">\n            <ore-icon name=\"chevron-left\" size=\"16\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n          </button>\n\n          <button\n            class=\"cal-label-btn\"\n            type=\"button\"\n            aria-label=\"${() =>\n              `Switch to ${currentView.value === 'day' ? 'month' : currentView.value === 'month' ? 'year' : 'day'} view`}\"\n            ?disabled=\"${isDisabled}\"\n            @click=\"${handleHeaderClick}\">\n            <span class=\"cal-label-month\">${displayMonth_}</span>\n            <span class=\"cal-label-sep\" aria-hidden=\"true\">/</span>\n            <span class=\"cal-label-year\">${displayYear_}</span>\n          </button>\n\n          <button class=\"nav-btn\" type=\"button\" aria-label=\"Next\" ?disabled=\"${isDisabled}\" @click=\"${handleNext}\">\n            <ore-icon name=\"chevron-right\" size=\"16\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n          </button>\n        </div>\n\n        <!-- Day view -->\n        <div\n          class=\"cal-grid cal-grid-days\"\n          role=\"grid\"\n          part=\"grid\"\n          aria-label=\"${() => displayLabel.value}\"\n          ?hidden=\"${() => currentView.value !== 'day'}\">\n          <div role=\"row\" class=\"cal-grid-row\">\n            ${() =>\n              weekdayLabels.value.map(\n                (lbl) => html`\n                  <div class=\"cal-cell cal-cell-head\" role=\"columnheader\" aria-label=\"${lbl}\">${lbl}</div>\n                `,\n              )}\n          </div>\n          ${() => {\n            const cells = dayCells.value;\n            const rows: (typeof cells)[number][][] = [];\n\n            for (let i = 0; i < cells.length; i += 7) rows.push(cells.slice(i, i + 7));\n\n            return rows.map(\n              (row) => html`\n                <div role=\"row\" class=\"cal-grid-row\">\n                  ${row.map(\n                    (cell) => html`\n                      <div\n                        class=\"cal-cell cal-cell-day\"\n                        role=\"gridcell\"\n                        part=\"day\"\n                        aria-selected=\"${() => String(cell.isSelected)}\"\n                        aria-disabled=\"${() => String(cell.isDisabled || isDisabled.value)}\"\n                        aria-current=\"${() => (cell.isToday ? 'date' : null)}\"\n                        ?data-selected=\"${() => cell.isSelected}\"\n                        ?data-today=\"${() => cell.isToday}\"\n                        ?data-outside=\"${() => cell.isOutsideMonth}\"\n                        ?data-disabled=\"${() => cell.isDisabled || isDisabled.value}\"\n                        data-iso=\"${cell.iso}\"\n                        data-day=\"${String(cell.day)}\"\n                        tabindex=\"${() => (cell.isDisabled || isDisabled.value ? '-1' : '0')}\"\n                        @click=\"${() => handleSelectDay(cell.iso)}\"\n                        @keydown=\"${handleDayKeydown}\">\n                        ${String(cell.day)}\n                        ${() => {\n                          const evts = eventsByDate.value.get(cell.iso) ?? [];\n\n                          if (!evts.length) return html``;\n\n                          const shown = evts.slice(0, MAX_EVENTS);\n                          const overflow = evts.length - MAX_EVENTS;\n\n                          if (isExpanded.value) {\n                            // Text node is written tag-tight (no inner line breaks) — this custom\n                            // `html` tagged template does not collapse whitespace at runtime like a\n                            // browser parser would, so a pretty-printed multi-line `<span>...</span>`\n                            // here would render literal newlines/indentation into `textContent`.\n                            // biome-ignore format: Preserve text-node whitespace in the template.\n                            const overflowPill =\n                              overflow > 0\n                                ? html`<span class=\"cal-event-pill-overflow\" aria-hidden=\"true\"\n                                  >+${overflow} more</span\n                                >`\n                                : html``;\n\n                            return html`\n                              <div\n                                class=\"cal-events\"\n                                aria-label=\"${() => `${evts.length} event${evts.length > 1 ? 's' : ''}`}\">\n                                ${shown.map(\n                                  (evt) => html`\n                                    <ore-badge\n                                      class=\"cal-event-pill\"\n                                      size=\"xs\"\n                                      rounded=\"sm\"\n                                      aria-label=\"${evt.label}\"\n                                      style=\"${styleMap({\n                                        '--badge-bg': evt.color,\n                                        '--badge-border-color': evt.color,\n                                      })}\">\n                                      ${evt.label}\n                                    </ore-badge>\n                                  `,\n                                )}\n                                ${overflowPill}\n                              </div>\n                            `;\n                          }\n\n                          return html`\n                            <div\n                              class=\"cal-dots\"\n                              aria-label=\"${() => `${evts.length} event${evts.length > 1 ? 's' : ''}`}\">\n                              ${shown.map(\n                                (evt) => html`\n                                  <ore-badge\n                                    class=\"cal-dot\"\n                                    dot\n                                    size=\"xs\"\n                                    aria-hidden=\"true\"\n                                    style=\"${styleMap({\n                                      '--badge-bg': evt.color,\n                                      '--badge-border-color': evt.color,\n                                    })}\"></ore-badge>\n                                `,\n                              )}\n                              ${\n                                overflow > 0\n                                  ? html`\n                                      <span class=\"cal-dot-overflow\" aria-hidden=\"true\">+${overflow}</span>\n                                    `\n                                  : html``\n                              }\n                            </div>\n                          `;\n                        }}\n                      </div>\n                    `,\n                  )}\n                </div>\n              `,\n            );\n          }}\n        </div>\n\n        <!-- Month view -->\n        <div\n          class=\"cal-grid cal-grid-months\"\n          role=\"grid\"\n          aria-label=\"${() => displayYear_.value}\"\n          ?hidden=\"${() => currentView.value !== 'month'}\">\n          ${() => {\n            const cells = monthCells.value;\n            const rows: (typeof cells)[number][][] = [];\n\n            for (let i = 0; i < cells.length; i += 4) rows.push(cells.slice(i, i + 4));\n\n            return rows.map(\n              (row) => html`\n                <div role=\"row\">\n                  ${row.map(\n                    (cell) => html`\n                      <div\n                        class=\"cal-cell cal-cell-month\"\n                        role=\"gridcell\"\n                        aria-selected=\"${() => String(cell.isSelected)}\"\n                        aria-disabled=\"${() => String(cell.isDisabled || isDisabled.value)}\"\n                        ?data-selected=\"${() => cell.isSelected}\"\n                        ?data-disabled=\"${() => cell.isDisabled || isDisabled.value}\"\n                        tabindex=\"${() => (cell.isDisabled || isDisabled.value ? '-1' : '0')}\"\n                        @click=\"${() => handleSelectMonth(cell.month)}\"\n                        @keydown=\"${(e: KeyboardEvent) =>\n                          handleGridKeydown(e, '.cal-cell-month', 4, () => handleSelectMonth(cell.month))}\">\n                        ${cell.shortLabel}\n                      </div>\n                    `,\n                  )}\n                </div>\n              `,\n            );\n          }}\n        </div>\n\n        <!-- Year view -->\n        <div\n          class=\"cal-grid cal-grid-years\"\n          role=\"grid\"\n          aria-label=\"Select year\"\n          ?hidden=\"${() => currentView.value !== 'year'}\">\n          ${() => {\n            const cells = yearCells.value;\n            const rows: (typeof cells)[number][][] = [];\n\n            for (let i = 0; i < cells.length; i += 4) rows.push(cells.slice(i, i + 4));\n\n            return rows.map(\n              (row) => html`\n                <div role=\"row\">\n                  ${row.map(\n                    (cell) => html`\n                      <div\n                        class=\"cal-cell cal-cell-year\"\n                        role=\"gridcell\"\n                        aria-selected=\"${() => String(cell.isSelected)}\"\n                        aria-disabled=\"${() => String(cell.isDisabled || isDisabled.value)}\"\n                        ?data-selected=\"${() => cell.isSelected}\"\n                        ?data-disabled=\"${() => cell.isDisabled || isDisabled.value}\"\n                        tabindex=\"${() => (cell.isDisabled || isDisabled.value ? '-1' : '0')}\"\n                        @click=\"${() => handleSelectYear(cell.year)}\"\n                        @keydown=\"${(e: KeyboardEvent) =>\n                          handleGridKeydown(e, '.cal-cell-year', 4, () => handleSelectYear(cell.year))}\">\n                        ${String(cell.year)}\n                      </div>\n                    `,\n                  )}\n                </div>\n              `,\n            );\n          }}\n        </div>\n      </div>\n    `;\n  },\n  shadow: { delegatesFocus: true },\n  styles: [colorThemeMixin, reducedMotionMixin, componentStyles],\n});\n","@layer refine.base {\n  :host {\n    display: block;\n  }\n\n  fieldset {\n    min-width: 0;\n    padding: 0;\n    margin: 0;\n    border: none;\n  }\n\n  legend {\n    padding: 0;\n    margin-bottom: var(--size-2);\n    font-size: var(--text-sm);\n    font-weight: var(--font-medium);\n    color: var(--color-contrast-600);\n  }\n\n  legend[hidden] {\n    display: none;\n  }\n\n  .checkbox-group-items {\n    display: flex;\n    flex-direction: var(--checkbox-group-direction, column);\n    gap: var(--checkbox-group-gap, var(--size-2));\n  }\n\n  .helper-text[hidden] {\n    display: none;\n  }\n\n  .helper-text {\n    padding-inline: 2px;\n    margin-top: var(--size-1-5);\n    font-size: var(--text-xs);\n    line-height: var(--leading-tight);\n    color: color-mix(in oklch, var(--color-contrast-500) 80%, var(--color-canvas));\n  }\n\n  .error-text {\n    padding-inline: 2px;\n    margin-top: var(--size-1-5);\n    font-size: var(--text-xs);\n    line-height: var(--leading-tight);\n    color: var(--color-error);\n  }\n}\n\n@layer refine.variants {\n  :host([orientation='horizontal']) .checkbox-group-items {\n    --checkbox-group-direction: row;\n\n    flex-wrap: wrap;\n  }\n}\n","import {\n  bind,\n  createContext,\n  createStableId,\n  define,\n  getHost,\n  html,\n  onCleanup,\n  prop,\n  provide,\n  useEmit,\n  useField,\n  useSlots,\n  watchEffect,\n  when,\n} from '@vielzeug/ore';\nimport { computed, type Readable, signal } from '@vielzeug/ripple';\nimport {\n  type ChoiceChangeDetail,\n  createChoiceField,\n  getChoiceLabel,\n  getLightChildrenByTag,\n  lifecycleSignal,\n} from '../../core';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { disabledStateMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport componentStyles from './checkbox-group.css?inline';\n\n// ─── Context ──────────────────────────────────────────────────────────────────\n\nexport type CheckboxGroupContext = {\n  color: Readable<ThemeColor | undefined>;\n  disabled: Readable<boolean>;\n  size: Readable<ComponentSize | undefined>;\n  toggle: (value: string, originalEvent?: Event) => void;\n  values: Readable<string[]>;\n};\n\nexport const CHECKBOX_GROUP_CTX = createContext<CheckboxGroupContext>('CheckboxGroupContext');\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type OreCheckboxGroupProps = {\n  /** Theme color — propagated to all child ore-checkbox elements */\n  color?: ThemeColor;\n  /** Disable all checkboxes in the group */\n  disabled?: boolean;\n  /** Error message shown below the group */\n  error?: string;\n  /** Helper text shown below the group */\n  helper?: string;\n  /** Legend / label for the fieldset. Required for accessibility. */\n  label?: string;\n  /** Form field name used during submission */\n  name?: string;\n  /** Layout direction of the checkbox options */\n  orientation?: 'vertical' | 'horizontal';\n  /** Mark the group as required */\n  required?: boolean;\n  /** Size — propagated to all child ore-checkbox elements */\n  size?: ComponentSize;\n  /** Comma-separated list of currently checked values */\n  values?: string;\n};\n\nexport type OreCheckboxGroupEvents = {\n  change: ChoiceChangeDetail;\n};\n\n/**\n * A fieldset wrapper that groups `ore-checkbox` elements, provides shared\n * `color` and `size` via context, and manages multi-value selection state.\n *\n * @element ore-checkbox-group\n *\n * @attr {string} label - Legend text (required for a11y)\n * @attr {string} values - Comma-separated list of checked values\n * @attr {boolean} disabled - Disable all checkboxes in the group\n * @attr {string} error - Error message\n * @attr {string} helper - Helper text\n * @attr {string} name - Form field name\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} orientation - Layout: 'vertical' | 'horizontal'\n * @attr {boolean} required - Required field\n *\n * @fires change - Emitted when selection changes. detail: { value: string, values: string[], labels: string[], originalEvent?: Event }\n *\n * @slot - Place `ore-checkbox` elements here\n *\n * @cssprop --checkbox-group-direction - Flex direction of the items list ('row' | 'column')\n * @cssprop --checkbox-group-gap - Gap between checkbox items\n * @part items - Items container.\n * @example\n * ```html\n * <ore-checkbox-group name=\"fruits\" label=\"Favourite fruits\" required>\n *   <ore-checkbox value=\"apple\">Apple</ore-checkbox>\n *   <ore-checkbox value=\"banana\">Banana</ore-checkbox>\n *   <ore-checkbox value=\"cherry\">Cherry</ore-checkbox>\n * </ore-checkbox-group>\n * <ore-checkbox-group name=\"options\" orientation=\"horizontal\" color=\"primary\">\n *   <ore-checkbox value=\"a\">Option A</ore-checkbox>\n *   <ore-checkbox value=\"b\">Option B</ore-checkbox>\n * </ore-checkbox-group>\n * ```\n */\nexport const CHECKBOX_GROUP_TAG = 'ore-checkbox-group' as const;\ndefine<OreCheckboxGroupProps>(CHECKBOX_GROUP_TAG, {\n  formAssociated: true,\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...disablableBundle,\n    error: prop.string(),\n    helper: prop.string(),\n    label: prop.string(),\n    name: prop.string(),\n    orientation: prop.string('vertical'),\n    required: prop.bool(false),\n    // Not auto-reflected (`reflect: false`) — the derived, interaction-updated selection\n    // (`choice.formValue`) is the single writer for this attribute, via `bind()` below;\n    // letting `prop.string()`'s own default reflection also write the raw incoming value\n    // would leave two effects racing to set the same attribute from different sources.\n    values: { ...prop.string(), reflect: false },\n  },\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreCheckboxGroupEvents>();\n    const slots = useSlots();\n    const watch = watchEffect;\n\n    const choice = createChoiceField({\n      disabled: props.disabled,\n      error: props.error,\n      helper: props.helper,\n      multiple: signal(true),\n      prefix: 'checkbox-group',\n      required: props.required,\n      signal: lifecycleSignal(onCleanup),\n      value: props.values,\n    });\n\n    choice.attachFormField(\n      useField<string>({\n        disabled: choice.disabled,\n        onReset: choice.reset,\n        toFormValue: (v) => v,\n        validationMessage: choice.validationMessage,\n        validity: choice.validity,\n        value: choice.formValue,\n      }),\n    );\n\n    const checkedValues = choice.selectedValues;\n\n    const getCheckboxes = (): HTMLElement[] => getLightChildrenByTag(el, 'ore-checkbox');\n    const getLabelForValue = (value: string): string => getChoiceLabel(getCheckboxes(), value);\n    const emitChange = (originalEvent?: Event) => {\n      const values = checkedValues.value;\n\n      const labels = values.map(getLabelForValue);\n\n      emit('change', { labels, originalEvent, values });\n    };\n\n    const toggleCheckbox = (val: string, originalEvent?: Event) => {\n      choice.toggleValue(val);\n      choice.triggerValidation('change');\n      emitChange(originalEvent);\n    };\n\n    provide(CHECKBOX_GROUP_CTX, {\n      color: props.color,\n      disabled: computed(() => Boolean(props.disabled.value)),\n      size: props.size,\n      toggle: toggleCheckbox,\n      values: checkedValues,\n    });\n\n    // Sync checked state + color/size/disabled onto slotted ore-checkbox children\n    const syncChildren = () => {\n      const values = checkedValues.value;\n      const color = props.color.value;\n      const size = props.size.value;\n      const disabled = props.disabled.value;\n      const checkboxes = getCheckboxes();\n\n      for (const checkbox of checkboxes) {\n        const val = checkbox.getAttribute('value') ?? '';\n\n        checkbox.toggleAttribute('checked', values.includes(val));\n\n        if (color) checkbox.setAttribute('color', color);\n        else checkbox.removeAttribute('color');\n\n        if (size) checkbox.setAttribute('size', size);\n        else checkbox.removeAttribute('size');\n\n        checkbox.toggleAttribute('disabled', Boolean(disabled));\n      }\n    };\n\n    watch(() => {\n      void slots.elements().value;\n      syncChildren();\n    });\n\n    watch(() => {\n      void slots.elements().value;\n\n      const listeners = getCheckboxes().map((checkbox) => {\n        const handler = (event: Event) => {\n          event.stopPropagation();\n\n          const val = (checkbox.getAttribute('value') ?? '').trim();\n\n          if (!val) return;\n\n          toggleCheckbox(val, event);\n        };\n\n        checkbox.addEventListener('change', handler);\n\n        return () => {\n          checkbox.removeEventListener('change', handler);\n        };\n      });\n\n      return () => {\n        for (const dispose of listeners) dispose();\n      };\n    });\n\n    const legendId = createStableId('checkbox-group-legend');\n    const errorId = `${legendId}-error`;\n    const helperId = `${legendId}-helper`;\n    const hasError = () => Boolean(props.error.value);\n    const hasHelper = () => Boolean(props.helper.value) && !hasError();\n\n    // Reactive, not a one-off `el.setAttribute()` inside the click handler: the host's `values`\n    // attribute must stay in sync with the selection regardless of *why* it changed (a click,\n    // or `reset()` on ancestor form reset — neither of which should need its own copy of this).\n    bind({ attr: { size: props.size, values: choice.formValue } });\n\n    return html`\n      <fieldset\n        role=\"group\"\n        aria-required=\"${() => String(Boolean(props.required.value))}\"\n        aria-invalid=\"${() => String(hasError())}\"\n        aria-errormessage=\"${() => (hasError() ? errorId : null)}\"\n        aria-describedby=\"${() => (hasError() ? errorId : hasHelper() ? helperId : null)}\">\n        <legend id=\"${legendId}\" ?hidden=${() => !props.label.value}>\n          ${props.label}${when(\n            () => Boolean(props.required.value),\n            () => html`\n              <span aria-hidden=\"true\">*</span>\n            `,\n          )}\n        </legend>\n        <div class=\"checkbox-group-items\" part=\"items\">\n          <slot></slot>\n        </div>\n        <div class=\"error-text\" id=\"${errorId}\" role=\"alert\" ?hidden=${() => !hasError()}>${props.error}</div>\n        <div class=\"helper-text\" id=\"${helperId}\" ?hidden=${() => !hasHelper()}>${props.helper}</div>\n      </fieldset>\n    `;\n  },\n  styles: [disabledStateMixin, componentStyles],\n});\n","type FieldHost = HTMLElement & {\n  checked?: boolean;\n  value?: string;\n};\n\nexport const defineFieldChecked = (host: HTMLElement, get: () => boolean, set: (checked: boolean) => void): void => {\n  Object.defineProperty(host, 'checked', {\n    configurable: true,\n    enumerable: true,\n    get,\n    set,\n  });\n};\n\nexport const defineFieldValue = (host: HTMLElement, get: () => string, set: (value: string) => void): void => {\n  Object.defineProperty(host, 'value', {\n    configurable: true,\n    enumerable: true,\n    get,\n    set,\n  });\n};\n\nexport const dispatchNativeFieldEvent = (host: HTMLElement, type: 'change' | 'input'): void => {\n  host.dispatchEvent(new Event(type, { bubbles: true, composed: true }));\n};\n\nexport const setFieldChecked = (host: HTMLElement, checked: boolean): void => {\n  (host as FieldHost).checked = checked;\n};\n\nexport const setFieldValue = (host: HTMLElement, value: string): void => {\n  (host as FieldHost).value = value;\n};\n","@layer refine.base {\n  /* ========================================\n       Base Styles & Defaults\n       ======================================== */\n\n  :host {\n    --_size: var(--checkbox-size, var(--size-5));\n    --_radius: var(--checkbox-radius, var(--rounded-lg));\n    --_font-size: var(--checkbox-font-size, var(--text-sm));\n    --_bg: var(--checkbox-bg, var(--color-contrast-200));\n    --_border: var(--checkbox-border-color, var(--color-contrast-300));\n\n    display: inline-flex;\n    flex-wrap: wrap;\n    gap: var(--_gap, var(--size-2));\n    align-items: center;\n    min-height: var(--_touch-target);\n    cursor: pointer;\n    user-select: none;\n  }\n\n  .checkbox-wrapper {\n    position: relative;\n    display: block;\n    flex-shrink: 0;\n    width: var(--_size);\n    height: var(--_size);\n  }\n\n  .box {\n    position: relative;\n    box-sizing: border-box;\n    width: var(--_size);\n    height: var(--_size);\n    background: var(--_bg);\n    border: var(--border-2) solid var(--_border);\n    border-radius: var(--_radius);\n    transition:\n      background var(--transition-normal),\n      border-color var(--transition-normal),\n      box-shadow var(--transition-normal);\n  }\n\n  /* ========================================\n       Focus State\n       ======================================== */\n\n  :host(:focus-visible) .box {\n    box-shadow: var(--_focus-shadow);\n  }\n\n  /* ========================================\n       Icons (Checkmark & Dash)\n       ======================================== */\n\n  .checkmark,\n  .dash {\n    position: absolute;\n    top: 50%;\n    left: 50%;\n    color: var(--_icon-color);\n    opacity: 0;\n    transform: translate(-50%, -50%) scale(0.5);\n    transition:\n      opacity var(--transition-spring),\n      transform var(--transition-spring);\n  }\n\n  .checkmark::part(svg),\n  .dash::part(svg) {\n    width: calc(var(--_size) * 0.6);\n    height: calc(var(--_size) * 0.6);\n    fill: none;\n    stroke: currentcolor;\n    stroke-width: 3;\n    stroke-linecap: round;\n    stroke-linejoin: round;\n  }\n\n  /* ========================================\n       Label\n       ======================================== */\n\n  .label {\n    font-size: var(--_font-size);\n    color: var(--color-contrast);\n  }\n\n  /* ========================================\n       Helper / Error Text\n       ======================================== */\n\n  .helper-text[hidden] {\n    display: none;\n  }\n\n  .helper-text {\n    width: 100%;\n    padding-inline-start: calc(var(--_size) + var(--size-2));\n    font-size: var(--text-xs);\n    line-height: var(--leading-tight);\n    color: color-mix(in oklch, var(--color-contrast-500) 80%, var(--color-canvas));\n  }\n\n  .helper-text[role='alert'] {\n    color: var(--color-error);\n  }\n}\n\n@layer refine.overrides {\n  /* Map theme variables to checkbox-specific variables */\n  :host {\n    --_active-bg: var(--checkbox-checked-bg, var(--_theme-base));\n    --_icon-color: var(--checkbox-color, var(--_theme-contrast));\n    --_focus-shadow: var(--_theme-shadow);\n  }\n\n  /* ========================================\n       Checked & Indeterminate States\n       ======================================== */\n\n  :host([checked]) .box,\n  :host([indeterminate]) .box {\n    background: var(--_active-bg);\n    border-color: var(--_active-bg);\n  }\n\n  :host([checked]) .checkmark,\n  :host([indeterminate]:not([checked])) .dash {\n    opacity: 1;\n    transform: translate(-50%, -50%) scale(1);\n  }\n}\n","import { define, getHost, html, inject, onCleanup, prop, useField } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport { createCheckable, lifecycleSignal } from '../../core';\nimport type { CheckableProps, ComponentSize, ThemeColor } from '../../types';\nimport '../../content/icon/icon';\nimport { CONTROL_SIZE_PRESET, disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport {\n  coarsePointerMixin,\n  colorThemeMixin,\n  disabledStateMixin,\n  forcedColorsFormControlMixin,\n  sizeVariantMixin,\n} from '../../styles';\nimport { CHECKBOX_GROUP_CTX } from '../checkbox-group/checkbox-group';\nimport { applyCheckableBinding } from '../shared/field-binding';\nimport { defineFieldChecked, dispatchNativeFieldEvent, setFieldChecked } from '../shared/native-field-event';\nimport { renderHelperRegion } from '../shared/templates';\nimport componentStyles from './checkbox.css?inline';\n\nexport type OreCheckboxEvents = {\n  change: Event;\n  input: Event;\n};\n\nexport type OreCheckboxProps = CheckableProps & {\n  /** Theme color */\n  color?: ThemeColor;\n  /** Disable interaction */\n  disabled?: boolean;\n  /** Error message (marks field as invalid) */\n  error?: string;\n  /** Helper text displayed below the checkbox */\n  helper?: string;\n  /** Indeterminate state (partially checked) */\n  indeterminate?: boolean;\n  /** Require this checkbox to be checked for native form validation (e.g. a consent checkbox) */\n  required?: boolean;\n  /** Component size */\n  size?: ComponentSize;\n};\n\n/**\n * A customizable checkbox component with theme colors, sizes, and indeterminate state support.\n *\n * @element ore-checkbox\n *\n * @attr {boolean} checked - Checked state\n * @attr {boolean} disabled - Disable checkbox interaction\n * @attr {boolean} indeterminate - Indeterminate (partially checked) state\n * @attr {boolean} required - Require this checkbox to be checked for native form validation\n * @attr {string} value - Field value submitted with forms\n * @attr {string} name - Form field name\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Checkbox size: 'sm' | 'md' | 'lg'\n * @attr {string} error - Error message (marks field as invalid)\n * @attr {string} helper - Helper text displayed below the checkbox\n *\n * @fires input - Emitted when checkbox is toggled.\n * @fires change - Emitted when checkbox is toggled.\n *\n * @slot - Checkbox label text\n *\n * @cssprop --checkbox-size - Control size (width and height)\n * @cssprop --checkbox-radius - Control border radius\n * @cssprop --checkbox-bg - Unchecked background color\n * @cssprop --checkbox-border-color - Unchecked border color\n * @cssprop --checkbox-checked-bg - Checked/indeterminate background color\n * @cssprop --checkbox-color - Checkmark icon color\n * @cssprop --checkbox-font-size - Label font size\n * @part checkbox - The checkbox wrapper element\n * @part box - The visual checkbox box\n * @part label - The label element\n * @part helper-text - The helper/error text element\n *\n * @example\n * ```html\n * <ore-checkbox name=\"agree\" required>I agree to the terms</ore-checkbox>\n * <ore-checkbox checked color=\"primary\" size=\"lg\">Enabled by default</ore-checkbox>\n * <ore-checkbox error=\"This field is required\" helper=\"Check to continue\">Accept</ore-checkbox>\n * ```\n */\nexport const CHECKBOX_TAG = 'ore-checkbox' as const;\ndefine<OreCheckboxProps>(CHECKBOX_TAG, {\n  formAssociated: true,\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...disablableBundle,\n    checked: prop.bool(false),\n    error: prop.string(),\n    helper: prop.string(),\n    indeterminate: prop.bool(false),\n    name: prop.string(),\n    required: prop.bool(false),\n    value: prop.string('on'),\n  },\n  setup(props) {\n    const el = getHost();\n\n    const groupCtx = inject(CHECKBOX_GROUP_CTX);\n\n    const checkable = createCheckable({\n      checked: props.checked,\n      clearIndeterminateFirst: true,\n      disabled: computed(() => props.disabled.value || Boolean(groupCtx?.disabled.value)),\n      error: props.error,\n      group: groupCtx,\n      helper: props.helper,\n      indeterminate: props.indeterminate,\n      onToggle: (payload) => {\n        checkable.triggerValidation('change');\n        setFieldChecked(el, payload.checked);\n\n        // In a checkbox-group, the group owns change emission/state updates.\n        // Emitting here would bubble to the group and toggle a second time.\n        if (groupCtx) return;\n\n        dispatchNativeFieldEvent(el, 'input');\n        dispatchNativeFieldEvent(el, 'change');\n      },\n      prefix: 'checkbox',\n      required: props.required,\n      signal: lifecycleSignal(onCleanup),\n      value: props.value,\n    });\n\n    checkable.attachFormField(\n      useField<string | null>({\n        disabled: checkable.disabled,\n        onReset: checkable.reset,\n        toFormValue: (v) => v,\n        validationMessage: checkable.validationMessage,\n        validity: checkable.validity,\n        value: checkable.checkableFormValue,\n      }),\n    );\n\n    const {\n      assistiveId,\n      checked,\n      disabled,\n      errorText,\n      handleClick,\n      handleKeydown,\n      helperText,\n      indeterminate,\n      labelId,\n    } = checkable;\n\n    defineFieldChecked(\n      el,\n      () => checked.value,\n      (value) => {\n        checked.value = value;\n      },\n    );\n\n    applyCheckableBinding(\n      props.size,\n      {\n        assistiveId,\n        checked,\n        disabled,\n        errorText,\n        handleClick,\n        handleKeydown,\n        helperText,\n        indeterminate,\n        labelId,\n        required: props.required,\n      },\n      'checkbox',\n    );\n\n    return html`\n      <div class=\"checkbox-wrapper\" part=\"checkbox\">\n        <div class=\"box\" part=\"box\">\n          <ore-icon class=\"checkmark\" name=\"check\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n          <ore-icon class=\"dash\" name=\"minus\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n        </div>\n      </div>\n      <span class=\"label\" part=\"label\" id=\"${labelId}\"><slot></slot></span>\n      ${renderHelperRegion(assistiveId, errorText, helperText)}\n    `;\n  },\n  styles: [\n    colorThemeMixin,\n    forcedColorsFormControlMixin,\n    disabledStateMixin,\n    coarsePointerMixin,\n    sizeVariantMixin(CONTROL_SIZE_PRESET),\n    componentStyles,\n  ],\n});\n","import type { ComboboxOptionItem } from './combobox.types';\n\nexport function parseSlottedOptions(elements: Element[]): ComboboxOptionItem[] {\n  return elements\n    .filter((el) => el.localName === 'ore-combobox-option')\n    .map((el) => ({\n      disabled: el.hasAttribute('disabled'),\n      iconEl: el.querySelector('[slot=\"icon\"]'),\n      label:\n        el.getAttribute('label') ||\n        [...el.childNodes]\n          .filter((node) => node.nodeType === Node.TEXT_NODE)\n          .map((node) => node.textContent?.trim())\n          .filter(Boolean)\n          .join(' ') ||\n        '',\n      value: el.getAttribute('value') ?? '',\n    }));\n}\n\nexport function filterOptions(options: ComboboxOptionItem[], query: string, noFilter: boolean): ComboboxOptionItem[] {\n  if (noFilter) return options;\n\n  const normalizedQuery = query.toLowerCase().trim();\n\n  if (!normalizedQuery) return options;\n\n  return options.filter(\n    (option) =>\n      option.label.toLowerCase().includes(normalizedQuery) || option.value.toLowerCase().includes(normalizedQuery),\n  );\n}\n\nexport function getCreatableLabel(query: string, creatable: boolean, filteredOptions: ComboboxOptionItem[]): string {\n  if (!creatable) return '';\n\n  const trimmedQuery = query.trim();\n\n  if (!trimmedQuery) return '';\n\n  const exactMatch = filteredOptions.some((option) => option.label.toLowerCase() === trimmedQuery.toLowerCase());\n\n  return exactMatch ? '' : `Create \"${trimmedQuery}\"`;\n}\n\nexport function makeCreatableValue(query: string): string {\n  return `__new__:${query.trim()}`;\n}\n","@layer refine.base {\n  /* ========================================\n       Base Styles & Defaults\n       ======================================== */\n\n  :host {\n    --_font-size: var(--input-font-size, var(--text-sm));\n    --_gap: var(--input-gap, var(--size-2));\n    --_field-height: var(--input-height, var(--size-10));\n    --_padding: var(--input-padding, var(--size-1-5) var(--size-3));\n    --_label-block-inset: var(--input-label-block-inset, var(--size-2));\n    --_label-inset: var(--input-label-inset, var(--size-3));\n    --_radius: var(--input-radius, var(--rounded-lg));\n    --_placeholder: var(--input-placeholder-color, var(--color-contrast-500));\n    --_bg: var(--input-bg, var(--color-contrast-100));\n    --_border-color: var(--input-border-color, var(--color-contrast-300));\n\n    display: inline-flex;\n    flex-direction: column;\n    align-items: stretch;\n    min-width: var(--input-min-width, 12rem);\n  }\n\n  .input-wrapper {\n    display: flex;\n    flex-direction: column;\n    gap: 0;\n    width: 100%;\n  }\n\n  .field {\n    box-sizing: border-box;\n    display: flex;\n    flex-direction: column;\n    gap: 0;\n    align-items: stretch;\n    justify-content: center;\n    height: var(--_field-height);\n    min-height: var(--_field-height);\n    padding: var(--_padding);\n    background: var(--_bg);\n    border: var(--border) solid var(--_border-color);\n    border-radius: var(--_radius);\n    box-shadow: var(--shadow-2xs);\n    transition: var(\n      --_motion-transition,\n      background var(--transition-fast),\n      backdrop-filter var(--transition-fast),\n      border-color var(--transition-fast),\n      box-shadow var(--transition-fast)\n    );\n  }\n\n  /* Expand height to fit inset label + input row */\n  .input-wrapper:has(.label:not([hidden])) .field {\n    height: auto;\n  }\n\n  /* Outside placement: label is above the field (natural flow) */\n\n  /* Inset placement (default): label appears inside the field border */\n  :host(:not([label-placement='outside'])) .input-wrapper {\n    position: relative;\n  }\n\n  :host(:not([label-placement='outside'])) .label {\n    position: absolute;\n    inset-block-start: var(--_label-block-inset);\n    inset-inline-start: var(--_label-inset);\n    z-index: 1;\n    pointer-events: none;\n  }\n\n  :host(:not([label-placement='outside'])) .input-wrapper:has(.label:not([hidden])) .field {\n    padding-block-start: calc(var(--_label-block-inset) + 1lh + 2px);\n  }\n\n  .input-row {\n    display: flex;\n    flex: 1;\n    gap: var(--_gap);\n    align-items: center;\n  }\n\n  /* ========================================\n       Label Styles\n       ======================================== */\n\n  .label,\n  label.label {\n    margin-bottom: 2px;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    font-size: var(--text-xs);\n    font-weight: var(--font-medium);\n    line-height: var(--leading-tight);\n    color: var(--color-contrast-500);\n    white-space: nowrap;\n    cursor: pointer;\n    user-select: none;\n    transition: var(--_motion-transition, color var(--transition-fast));\n  }\n\n  /* Outside placement: label moves outside the field via CSS */\n  :host([label-placement='outside']) .label,\n  :host([label-placement='outside']) label.label {\n    order: -1;\n    font-size: var(--text-xs);\n    line-height: var(--leading-loose);\n  }\n\n  /* ========================================\n       Helper Text\n       ======================================== */\n\n  .helper-text {\n    padding-inline: 2px;\n    margin-top: var(--size-1-5);\n    font-size: var(--text-xs);\n    line-height: var(--leading-tight);\n    color: color-mix(in oklch, var(--color-contrast-500) 80%, var(--color-canvas));\n    overflow-wrap: anywhere;\n  }\n\n  .helper-text[hidden] {\n    display: none;\n  }\n\n  /* ========================================\n       Slotted Prefix/Suffix Icons\n       ======================================== */\n\n  ::slotted(svg) {\n    flex-shrink: 0;\n    width: var(--_icon-size, var(--leading-6));\n    height: var(--_icon-size, var(--leading-6));\n  }\n}\n\n@layer refine.overrides {\n  /* ========================================\n       Input Element\n       ======================================== */\n\n  input {\n    flex: 1;\n    min-width: 0;\n    font: inherit;\n    font-size: var(--_font-size);\n    line-height: var(--leading-normal);\n\n    /* No all: unset needed - reset layer handles it */\n    color: var(--color-contrast-900);\n    outline: none;\n    background: transparent;\n    border: none;\n  }\n\n  input::placeholder {\n    color: var(--_placeholder);\n    transition: color var(--transition-fast);\n  }\n\n  input:focus-visible {\n    outline: none;\n  }\n\n  /* ========================================\n       Hover & Focus States\n       ======================================== */\n\n  :host(:not([disabled], [variant='bordered'], [variant='flat'])) .field:hover {\n    border-color: var(--color-contrast-400);\n  }\n\n  :host(:not([disabled])) .field:focus-within .label {\n    color: var(--_theme-focus);\n  }\n\n  :host(:not([disabled])) .field:focus-within ::slotted([slot='prefix']),\n  :host(:not([disabled])) .field:focus-within ::slotted([slot='suffix']) {\n    color: var(--_theme-focus);\n  }\n\n  /* ========================================\n       Clear button\n       ======================================== */\n\n  .clear-btn {\n    display: none;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    width: var(--size-5);\n    min-width: var(--_touch-target);\n    height: var(--size-5);\n    min-height: var(--_touch-target);\n    padding: 0;\n    color: var(--color-contrast-500);\n    cursor: pointer;\n    background: transparent;\n    border: none;\n    border-radius: var(--rounded-sm);\n    transition: var(--_motion-transition, color var(--transition-fast));\n  }\n\n  .clear-btn:hover {\n    color: var(--color-contrast-900);\n  }\n\n  .clear-btn:focus-visible {\n    outline: var(--border-2) solid var(--_theme-focus);\n    outline-offset: var(--border);\n  }\n\n  :host([clearable]) .clear-btn {\n    display: flex;\n  }\n\n  :host([clearable]:not([has-value])) .clear-btn {\n    visibility: hidden;\n    pointer-events: none;\n  }\n\n  /* ========================================\n       Password visibility toggle\n       ======================================== */\n\n  .pwd-toggle-btn {\n    display: none;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    width: var(--size-5);\n    min-width: var(--_touch-target);\n    height: var(--size-5);\n    min-height: var(--_touch-target);\n    padding: 0;\n    color: var(--color-contrast-500);\n    cursor: pointer;\n    background: transparent;\n    border: none;\n    border-radius: var(--rounded-sm);\n    transition: var(--_motion-transition, color var(--transition-fast));\n  }\n\n  .pwd-toggle-btn:hover {\n    color: var(--color-contrast-900);\n  }\n\n  .pwd-toggle-btn:focus-visible {\n    outline: var(--border-2) solid var(--_theme-focus);\n    outline-offset: var(--border);\n  }\n\n  :host([type='password']) .pwd-toggle-btn {\n    display: flex;\n  }\n\n  /* ========================================\n       Character counter\n       ======================================== */\n\n  .char-counter {\n    padding-inline: 2px;\n    font-size: var(--text-xs);\n    line-height: var(--leading-tight);\n    color: var(--color-contrast-400);\n    text-align: end;\n    white-space: nowrap;\n  }\n\n  .char-counter[data-near-limit] {\n    color: var(--color-warning, #f59e0b);\n  }\n\n  .char-counter[data-at-limit] {\n    color: var(--color-error);\n  }\n\n  /* ========================================\n       Error State\n       ======================================== */\n\n  :host([error]:not([error=''])) .field {\n    border-color: var(--color-error);\n  }\n\n  :host([error]:not([error=''])) .label {\n    color: var(--color-error);\n  }\n\n  .helper-text[role='alert'] {\n    color: var(--color-error);\n  }\n\n  /* ========================================\n       Success State (Signal 04)\n       ======================================== */\n\n  :host([success]) .field {\n    border-color: var(--color-success);\n  }\n\n  /* ========================================\n       Status Icon (Signals 03/04: error/success — never color alone)\n       ======================================== */\n\n  .status-icon {\n    display: none;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    width: var(--size-5);\n    height: var(--size-5);\n  }\n\n  :host([error]:not([error=''])) .status-icon,\n  :host([success]) .status-icon {\n    display: flex;\n  }\n\n  .status-icon[data-status='error'] {\n    color: var(--color-error);\n  }\n\n  .status-icon[data-status='success'] {\n    color: var(--color-success);\n  }\n\n  /* ========================================\n       Loading Spinner (Signal 06)\n       ======================================== */\n\n  /* Keyframe must live in shadow DOM — @keyframes don't inherit across shadow roots */\n  @keyframes spin {\n    to {\n      transform: rotate(360deg);\n    }\n  }\n\n  .field-spinner {\n    display: none;\n    flex-shrink: 0;\n    width: var(--size-4);\n    height: var(--size-4);\n    border: var(--border-2) solid var(--_theme-focus, currentcolor);\n    border-inline-end-color: transparent;\n    border-radius: 50%;\n    animation: var(--_motion-animation, spin var(--transition-loader) infinite);\n  }\n\n  :host([loading]) .field-spinner {\n    display: inline-block;\n  }\n}\n\n/*\n * The solid/flat/bordered/outline/ghost variant switch (previously here) now lives in\n * `fieldVariantMixin({ container: '.field', tokenPrefix: 'input' })` in `input.ts`'s `styles`\n * array — shared with `ore-textarea`/`ore-message-composer` instead of hand-duplicated across\n * all three (see the mixin's own doc comment for what it covers and why). `ore-input`'s extra\n * `text` variant (below) is not part of that shared set, so it keeps its own block here.\n */\n@layer refine.variants {\n  /* Text — underline style */\n  :host([variant='text']) {\n    --_bg: var(--input-bg, transparent);\n    --_border-color: var(--input-border-color, var(--color-contrast-300));\n  }\n\n  :host([variant='text']) .field {\n    background: transparent;\n    border: none;\n    border-radius: 0;\n    box-shadow: none;\n  }\n\n  :host([variant='text']) .field:focus-within {\n    box-shadow: none;\n  }\n\n  /*\n   * Focus/error/success `box-shadow` on `.field` — kept here in `refine.variants` (alongside\n   * `fieldVariantMixin`'s rest-state `box-shadow` for solid/outline/ghost) rather than\n   * `refine.overrides`, so normal specificity decides the winner. Cascade layers beat\n   * specificity outright, so a `refine.overrides` box-shadow always lost to every variant's\n   * unconditional rest-state `box-shadow`, focused/error/success or not — the same bug class\n   * fixed for `ore-otp-input`'s focus ring.\n   */\n  :host(:not([disabled], [variant='text'], [variant='flat'])) .field:focus-within {\n    background: var(--color-canvas);\n    border-color: var(--_theme-focus);\n    box-shadow: var(--_theme-shadow, var(--color-primary-focus-shadow));\n  }\n\n  :host([error]:not([error=''])) .field:focus-within {\n    border-color: var(--color-error);\n    box-shadow: var(--color-error-focus-shadow);\n  }\n\n  :host([success]) .field:focus-within {\n    border-color: var(--color-success);\n    box-shadow: var(--color-success-focus-shadow);\n  }\n}\n\n@layer refine.utilities {\n  /* Full width */\n  :host([fullwidth]) {\n    width: 100%;\n  }\n}\n\n/* ========================================\n     Disabled State (Signal 05) — intentionally unlayered\n     ======================================== */\n\n/*\n * The shared `disabledLoadingMixin` (pulled in via `fieldMixins`) dims `:host([disabled])`\n * with `opacity: 0.5` as bare, unlayered CSS. Cascade layers always lose to unlayered rules\n * regardless of source order or specificity, so overriding that from inside any `@layer`\n * block in this file (including `refine.overrides`) would be a no-op — this has to stay\n * unlayered too, to actually win.\n *\n * Per the field-state UX review: opacity-based dimming reads as a washed-out/loading look\n * and can mimic reduced-contrast content for low-vision users, rather than a clearly locked\n * field. Swapped for an explicit grayscale surface + `not-allowed` cursor (the cursor already\n * comes from the shared mixin, left untouched here).\n */\n:host([disabled]) {\n  opacity: 1;\n}\n\n:host([disabled]) .field {\n  background: var(--color-contrast-100);\n  border-color: var(--color-contrast-200);\n  box-shadow: none;\n}\n\n:host([disabled]) input {\n  color: var(--color-contrast-400);\n}\n\n:host([disabled]) input::placeholder {\n  color: var(--color-contrast-300);\n}\n\n:host([disabled]) .label {\n  color: var(--color-contrast-400);\n}\n","import { bind, define, getHost, html, live, onCleanup, onElement, prop, ref, useField, useSlots } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { bindRefCallback, createTextField, lifecycleSignal } from '../../core';\nimport type { TextFieldProps } from '../../shared';\nimport { disablableBundle, FIELD_SIZE_PRESET, roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport type { InputType, VisualVariant } from '../../types';\nimport '../../content/icon/icon';\nimport {\n  coarsePointerMixin,\n  colorThemeMixin,\n  disabledLoadingMixin,\n  fieldVariantMixin,\n  forcedColorsFocusMixin,\n  reducedMotionMixin,\n  roundedVariantMixin,\n  sizeVariantMixin,\n} from '../../styles';\nimport { errorAttr } from '../shared/field-binding';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport { renderStatusIcon } from '../shared/templates';\nimport componentStyles from './input.css?inline';\n\n/** Input component properties */\n\nexport type OreInputEvents = {\n  change: Event;\n  input: InputEvent;\n};\n\nexport type OreInputProps = TextFieldProps<Exclude<VisualVariant, 'frost'>> & {\n  /** Autocomplete hint */\n  autocomplete?: string;\n  /** Show a clear (×) button when the field has a value */\n  clearable?: boolean;\n  /** Virtual keyboard hint for mobile devices */\n  inputmode?: 'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url';\n  /**\n   * Shows an inline spinner inside the field and forces the inner `<input>` into\n   * `disabled` for the duration — use while an async validation/submission request\n   * is in flight (e.g. checking username availability) to prevent double-submits.\n   */\n  loading?: boolean;\n  /** Maximum character length — shows a counter below the input */\n  maxlength?: number;\n  /** Minimum character length */\n  minlength?: number;\n  /** HTML pattern attribute for client-side validation */\n  pattern?: string;\n  /**\n   * JS-only callback fired with the inner `<input>` element when it mounts,\n   * and with `null` when it unmounts. Intended for composed components that\n   * need imperative access to the raw input element.\n   * Set as a JS property: `bitInput.ref = (el) => { ... }`.\n   */\n  ref?: ((el: HTMLInputElement | null) => void) | null;\n  /** HTML input type */\n  type?: InputType;\n};\n\nconst VALID_INPUT_TYPES = [\n  'text',\n  'email',\n  'password',\n  'search',\n  'url',\n  'tel',\n  'number',\n  'date',\n  'time',\n  'datetime-local',\n  'month',\n  'week',\n] as const;\n\n/**\n * A customizable text input component with multiple variants, label placements, and form features.\n *\n * @element ore-input\n *\n * @attr {string} label - Label text\n * @attr {string} label-placement - Label placement: 'inset' | 'outside'\n * @attr {string} type - HTML input type: 'text' | 'email' | 'password' | 'number' | 'tel' | 'url' | 'search'\n * @attr {string} value - Current input value\n * @attr {string} placeholder - Placeholder text\n * @attr {string} name - Form field name\n * @attr {string} helper - Helper text displayed below the input (fallback when the `helper` slot is empty)\n * @attr {string} error - Error message — marks the field as invalid (fallback when the `error` slot is empty)\n * @attr {boolean} disabled - Disable input interaction\n * @attr {boolean} readonly - Make the input read-only\n * @attr {boolean} required - Mark the field as required\n * @attr {boolean} loading - Show an inline spinner and force the field disabled\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'text'\n * @attr {string} size - Input size: 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n *\n * @fires input - Emitted when input value changes (on every keystroke).\n * @fires change - Emitted when input loses focus with changed value.\n *\n * @slot prefix - Content before the input (e.g., icons)\n * @slot suffix - Content after the input (e.g., clear button, validation icon)\n * @slot label - Replaces the label text — slotted content takes precedence over the `label` prop\n * @slot helper - Replaces the helper text — slotted content takes precedence over the `helper` prop\n * @slot error - Replaces the error text — slotted content takes precedence over the `error` prop\n *\n * @part wrapper - The input wrapper element\n * @part label - The label element (inset or outside)\n * @part field - The field container element\n * @part input-row - The input row container element\n * @part input - The input element\n * @part status-icon - The inline error/success icon shown inside the field\n * @part spinner - The inline loading spinner shown inside the field while `loading`\n * @part helper - The helper text element\n *\n * @cssprop --input-bg - Background color\n * @cssprop --input-color - Text color\n * @cssprop --input-border-color - Border color\n * @cssprop --input-placeholder-color - Placeholder text color\n * @cssprop --input-radius - Border radius\n * @cssprop --input-padding - Inner padding (block inline)\n * @cssprop --input-label-block-inset - Inset from the field block start for an inset label\n * @cssprop --input-label-inset - Inset from the field inline start for an inset label\n * @cssprop --input-gap - Gap between prefix/suffix icons and input text\n * @cssprop --input-font-size - Font size\n * @cssprop --input-height - Field height\n * @cssprop --input-hover-bg - Field background on hover (flat/ghost variants)\n * @cssprop --input-hover-border-color - Field border on hover (flat/bordered variants)\n * @cssprop --input-focus-bg - Field background when focused (flat variant)\n * @cssprop --input-focus-border-color - Field border when focused (flat/text variants)\n *\n * @example\n * ```html\n * <ore-input type=\"email\" label=\"Email\" placeholder=\"you@example.com\" />\n * <ore-input label=\"Name\" variant=\"bordered\" color=\"primary\" />\n * <ore-input label=\"Username\" error=\"That username is taken\" />\n * <ore-input label=\"Username\" success />\n * <ore-input label=\"Username\" loading />\n * ```\n */\nexport const INPUT_TAG = 'ore-input' as const;\ndefine<OreInputProps>(INPUT_TAG, {\n  formAssociated: true,\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...disablableBundle,\n    ...roundableBundle,\n    autocomplete: prop.string(),\n    clearable: prop.bool(false),\n    error: prop.string(),\n    fullwidth: prop.bool(false),\n    helper: prop.string(),\n    inputmode: prop.string<'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url'>(),\n    label: prop.string(),\n    'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n    loading: prop.bool(false),\n    maxlength: prop.json(undefined as number | undefined),\n    minlength: prop.json(undefined as number | undefined),\n    name: prop.string(),\n    pattern: prop.string(),\n    placeholder: prop.string(),\n    readonly: prop.bool(false),\n    ref: prop.data<((el: HTMLInputElement | null) => void) | null>(),\n    required: prop.bool(false),\n    success: prop.bool(false),\n    type: prop.oneOf(VALID_INPUT_TYPES, 'text'),\n    value: prop.string(),\n    variant: prop.string<'flat' | 'text' | 'solid' | 'bordered' | 'outline' | 'ghost'>(),\n  },\n  setup(props) {\n    const el = getHost();\n    const slots = useSlots();\n\n    const showPassword = signal(false);\n    const inputRef = ref<HTMLInputElement>();\n\n    const hasLabel = computed(() => !!props.label.value || slots.has('label').value);\n    // `loading` behaves like a temporary `disabled` — forces the inner <input> out of\n    // constraint validation and interaction for the duration, layered on top of any real\n    // `loading` is layered on top of the consumer's explicit `disabled` prop.\n    const isDisabled = computed(() => props.disabled.value || props.loading.value);\n\n    const abortSignal = lifecycleSignal(onCleanup);\n    const tf = createTextField({\n      disabled: isDisabled,\n      error: props.error,\n      hasLabel,\n      helper: props.helper,\n      label: props.label,\n      labelPlacement: props['label-placement'],\n      maxLength: props.maxlength,\n      onChange: (_event: Event, value: string) => {\n        setFieldValue(el, value);\n        dispatchNativeFieldEvent(el, 'change');\n      },\n      onInput: (_event: Event, value: string) => {\n        setFieldValue(el, value);\n        dispatchNativeFieldEvent(el, 'input');\n      },\n      prefix: 'input',\n      readonly: props.readonly,\n      required: props.required,\n      signal: abortSignal,\n      value: props.value,\n    });\n\n    defineFieldValue(\n      el,\n      () => tf.value.value,\n      (value) => {\n        tf.value.value = value;\n      },\n    );\n\n    tf.attachFormField(\n      useField<string>({\n        disabled: tf.disabled,\n        onReset: tf.reset,\n        toFormValue: (v) => v,\n        validationMessage: tf.validationMessage,\n        validity: tf.validity,\n        value: tf.value,\n      }),\n    );\n\n    const {\n      ariaDescribedBy,\n      ariaErrorMessage,\n      ariaInvalid,\n      ariaLabelledBy,\n      assistiveId,\n      clear: clearValue,\n      counter,\n      errorId,\n      errorText,\n      fieldId: inputId,\n      helperText,\n      labelId,\n      labelVisible,\n      value: fieldValue,\n      wire,\n    } = tf;\n\n    onElement(inputRef, (el) => {\n      wire(el, abortSignal);\n\n      const unwireRef = bindRefCallback(props.ref, el);\n\n      return () => {\n        unwireRef();\n      };\n    });\n\n    const clear = (event?: Event): void => {\n      clearValue(event);\n      inputRef.value?.focus();\n    };\n\n    const resolvedInputType = (): string =>\n      props.type.value === 'password' && showPassword.value ? 'text' : (props.type.value ?? 'text');\n\n    bind({\n      attr: {\n        error: errorAttr(errorText),\n        'has-value': () => (fieldValue.value ? true : undefined),\n        size: props.size,\n        // Reflects `success` only once `error` is confirmed empty — keeps the two host\n        // attributes mutually exclusive even if a consumer sets both props at once.\n        success: () => (props.success.value && !errorText.value ? true : undefined),\n        variant: props.variant,\n      },\n    });\n\n    const labelHidden = () => !labelVisible.value;\n    const passwordToggleLabel = () => (showPassword.value ? 'Hide password' : 'Show password');\n    const passwordTogglePressed = () => String(showPassword.value);\n    const passwordToggleIcon = () =>\n      showPassword.value\n        ? html`\n            <ore-icon name=\"eye-off\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n          `\n        : html`\n            <ore-icon name=\"eye\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n          `;\n    const helperHidden = () => !!errorText.value || !helperText.value;\n    const errorHidden = () => !errorText.value;\n    const counterNearLimit = () => (counter?.value.counterNearLimit && !counter?.value.counterAtLimit ? '' : null);\n    const counterAtLimit = () => (counter?.value.counterAtLimit ? '' : null);\n    const counterHidden = () => !counter;\n    const counterText = () => counter?.value.counterText ?? '';\n\n    const clearTabIndex = () => (fieldValue.value ? '0' : '-1');\n    const pwdToggleTabIndex = () => (props.type.value === 'password' ? '0' : '-1');\n\n    const togglePassword = () => {\n      showPassword.value = !showPassword.value;\n      inputRef.value?.focus();\n    };\n\n    return html`\n      <div class=\"input-wrapper\" part=\"wrapper\">\n        <label class=\"label\" for=\"${inputId}\" id=\"${labelId}\" part=\"label\" ?hidden=\"${labelHidden}\">\n          <slot name=\"label\">${props.label}</slot>\n        </label>\n        <div class=\"field\" part=\"field\">\n          <div class=\"input-row\" part=\"input-row\">\n            <slot name=\"prefix\"></slot>\n            <input\n              part=\"input\"\n              id=\"${inputId}\"\n              type=\"${resolvedInputType}\"\n              name=\"${props.name}\"\n              placeholder=\"${props.placeholder}\"\n              autocomplete=\"${props.autocomplete}\"\n              inputmode=\"${props.inputmode}\"\n              maxlength=\"${props.maxlength}\"\n              minlength=\"${props.minlength}\"\n              pattern=\"${props.pattern}\"\n              ?disabled=\"${isDisabled}\"\n              ?readonly=\"${props.readonly}\"\n              ?required=\"${props.required}\"\n              value=\"${live(fieldValue)}\"\n              aria-labelledby=\"${ariaLabelledBy}\"\n              aria-describedby=\"${ariaDescribedBy}\"\n              aria-errormessage=\"${ariaErrorMessage}\"\n              aria-invalid=\"${ariaInvalid}\"\n              aria-busy=\"${() => (props.loading.value ? 'true' : null)}\"\n              ref=\"${inputRef}\" />\n            <slot name=\"suffix\"></slot>\n            ${renderStatusIcon(errorText)}\n            <span class=\"field-spinner\" part=\"spinner\" role=\"status\" aria-label=\"Loading\"></span>\n            <button\n              class=\"pwd-toggle-btn\"\n              part=\"pwd-toggle\"\n              type=\"button\"\n              aria-label=\"${passwordToggleLabel}\"\n              aria-pressed=\"${passwordTogglePressed}\"\n              tabindex=\"${pwdToggleTabIndex}\"\n              @click=\"${togglePassword}\">\n              ${passwordToggleIcon}\n            </button>\n            <button\n              aria-label=\"Clear\"\n              class=\"clear-btn\"\n              part=\"clear\"\n              type=\"button\"\n              tabindex=\"${clearTabIndex}\"\n              @click=\"${clear}\">\n              <ore-icon aria-hidden=\"true\" name=\"x\" size=\"12\" stroke-width=\"2.5\"></ore-icon>\n            </button>\n          </div>\n        </div>\n        <div class=\"helper-text\" aria-live=\"polite\" id=\"${assistiveId}\" part=\"helper\" ?hidden=\"${helperHidden}\">\n          <slot name=\"helper\">${() => helperText.value}</slot>\n        </div>\n        <div class=\"helper-text\" id=\"${errorId}\" role=\"alert\" part=\"error\" ?hidden=\"${errorHidden}\">\n          <slot name=\"error\">${() => errorText.value}</slot>\n        </div>\n        <div\n          class=\"char-counter\"\n          part=\"char-counter\"\n          data-near-limit=\"${counterNearLimit}\"\n          data-at-limit=\"${counterAtLimit}\"\n          ?hidden=\"${counterHidden}\">\n          ${counterText}\n        </div>\n      </div>\n    `;\n  },\n  shadow: { delegatesFocus: true },\n  styles: [\n    colorThemeMixin,\n    coarsePointerMixin,\n    reducedMotionMixin,\n    roundedVariantMixin,\n    disabledLoadingMixin,\n    sizeVariantMixin(FIELD_SIZE_PRESET),\n    forcedColorsFocusMixin('input'),\n    componentStyles,\n    // Must come after `componentStyles` — `@layer` precedence is fixed by which layer name is\n    // *first* referenced across this whole array, and `componentStyles` is what establishes\n    // `refine.base` (the unconditional `--_bg`/`--_border-color` defaults this mixin's\n    // `refine.variants` rules need to win over). Placed earlier, `refine.variants` would end up\n    // registered as the *lower*-priority layer, and every variant would silently render as the\n    // base default — exactly the bug this ordering fixes.\n    fieldVariantMixin({ container: '.field', text: 'input', tokenPrefix: 'input' }),\n  ],\n});\n","@layer refine.base {\n  :host {\n    --_dropdown-bg: var(--combobox-dropdown-bg, var(--color-canvas));\n    --_dropdown-border-color: var(--combobox-dropdown-border-color, var(--color-contrast-200));\n    --_option-hover-bg: var(--combobox-option-hover-bg, var(--color-contrast-100));\n    --_option-focus-bg: var(\n      --combobox-option-focus-bg,\n      color-mix(in oklch, var(--_theme-base) 12%, var(--color-contrast-100))\n    );\n    --_option-selected-bg: var(\n      --combobox-option-selected-bg,\n      color-mix(in oklch, var(--_theme-base) 10%, var(--color-contrast-50))\n    );\n    --_option-selected-focus-bg: var(\n      --combobox-option-selected-focus-bg,\n      color-mix(in oklch, var(--_theme-base) 20%, var(--color-contrast-100))\n    );\n\n    display: inline-flex;\n    flex-direction: column;\n    align-items: stretch;\n    min-width: var(--combobox-min-width, 12rem);\n  }\n\n  :host([fullwidth]) {\n    display: block;\n    width: 100%;\n  }\n\n  /* .sr-only is provided by the shared srOnlyMixin (see styles: [...] in combobox.ts) */\n\n  /* ore-input cursor override so the field still feels like a text input */\n  .trigger::part(input) {\n    cursor: text;\n  }\n\n  /* Allow the field to grow vertically when chips wrap to multiple rows. */\n  .trigger::part(field) {\n    height: auto;\n    min-height: var(--input-height, var(--size-10));\n  }\n\n  /* Wrap chips + input across rows; suffix stays on same row as input.\n     Only row-gap is set here — column spacing between chips is handled\n     via margin on ore-chip so the empty prefix slot adds no extra offset\n     (which would shift the input rightward vs the inset label). */\n  .trigger::part(input-row) {\n    flex-wrap: wrap;\n    row-gap: var(--size-1);\n    align-items: center;\n  }\n\n  /* ========================================\n       Chips (prefix slot)\n       ======================================== */\n\n  /* display:contents removes chips-row from the flex layout so chips\n     become direct flex items of input-row — no extra gap before input\n     when there are no chips (fixes inset-label alignment). */\n  .chips-row {\n    display: contents;\n  }\n\n  /* chips-list is also display:contents so individual ore-chip elements\n     are the direct flex items, wrapping inline with the search input. */\n  .chips-list {\n    display: contents;\n  }\n\n  /* Trailing space after each chip covers both inter-chip spacing and\n     the gap between the last chip and the search input. */\n  ore-chip {\n    margin-inline-end: var(--size-1);\n  }\n\n  /* ========================================\n       Suffix: clear button + loader + chevron\n       ======================================== */\n\n  .combobox-suffix {\n    display: flex;\n    flex-shrink: 0;\n    gap: var(--size-1);\n    align-items: center;\n  }\n\n  .clear-btn {\n    display: inline-flex;\n    flex-shrink: 0;\n    align-items: center;\n    padding: 0;\n    color: var(--color-contrast-400);\n    cursor: pointer;\n    background: none;\n    border: 0;\n  }\n\n  .clear-btn[hidden] {\n    display: none;\n  }\n\n  .clear-btn:hover {\n    color: var(--color-contrast-600);\n  }\n\n  .combobox-suffix-end {\n    display: flex;\n    gap: var(--size-1);\n    align-items: center;\n    color: var(--color-contrast-500);\n  }\n\n  .chevron {\n    display: inline-flex;\n    flex-shrink: 0;\n    align-items: center;\n    transition: var(--_motion-transition, transform var(--transition-fast));\n  }\n\n  :host([open]) .chevron {\n    transform: rotate(180deg);\n  }\n\n  .loader {\n    display: none;\n    flex-shrink: 0;\n    width: 1em;\n    height: 1em;\n    border: 2px solid currentcolor;\n    border-inline-end-color: transparent;\n    border-radius: 50%;\n    animation: var(--_motion-animation, spin var(--transition-loader) infinite);\n  }\n\n  /* Keyframe must live in shadow DOM — @keyframes don't inherit across shadow roots */\n  @keyframes spin {\n    to {\n      transform: rotate(360deg);\n    }\n  }\n\n  :host([loading]) .loader {\n    display: inline-block;\n  }\n\n  /* ========================================\n       Dropdown / Listbox\n       ======================================== */\n\n  .dropdown {\n    position: fixed;\n    inset: 0 auto auto 0;\n    z-index: calc(var(--z-popover, 1000) + 1);\n    box-sizing: border-box;\n    max-height: min(16rem, 50dvh);\n    padding: var(--size-1);\n    margin: 0;\n    overflow-y: auto;\n    overscroll-behavior: contain;\n    text-align: start;\n    pointer-events: none;\n    scrollbar-width: thin;\n    background: var(--_dropdown-bg);\n    border: var(--border) solid var(--_dropdown-border-color);\n    border-radius: var(--_radius);\n    box-shadow: var(--shadow-lg);\n    opacity: 0;\n    backdrop-filter: blur(var(--blur-md));\n    transform: translateY(var(--overlay-enter-translate-y));\n    transition: var(\n      --_motion-transition,\n      opacity var(--transition-fast),\n      transform var(--transition-fast),\n      display var(--transition-fast) allow-discrete\n    );\n  }\n\n  .dropdown[data-open] {\n    pointer-events: auto;\n    opacity: 1;\n    transform: translateY(0);\n\n    @starting-style {\n      opacity: 0;\n      transform: translateY(var(--overlay-enter-translate-y));\n    }\n  }\n\n  /* ========================================\n       Option Items\n       ======================================== */\n\n  .option {\n    display: flex;\n    gap: var(--size-2);\n    align-items: center;\n    padding: var(--size-1-5) var(--size-2-5);\n    font-size: var(--text-sm);\n    line-height: var(--leading-normal);\n    cursor: pointer;\n    border-radius: var(--rounded-sm);\n    transition:\n      background var(--transition-fast),\n      color var(--transition-fast);\n  }\n\n  /* Truncate long labels so options always stay single-line (fixed virtualizer row height). */\n  .option > span:not(.option-check, .option-icon) {\n    flex: 1;\n    min-width: 0;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n  }\n\n  .option:hover:not([data-disabled]) {\n    background: var(--_option-hover-bg);\n  }\n\n  .option[data-focused]:not([data-disabled]) {\n    color: var(--_theme-base);\n    background: var(--_option-focus-bg);\n  }\n\n  .option[data-selected],\n  .option[aria-selected='true'] {\n    font-weight: var(--font-medium);\n    color: var(--_theme-base);\n    background: var(--_option-selected-bg);\n  }\n\n  .option[data-selected][data-focused],\n  .option[aria-selected='true'][data-focused] {\n    background: var(--_option-selected-focus-bg);\n  }\n\n  .option[data-disabled] {\n    color: var(--color-contrast-400);\n    cursor: not-allowed;\n    opacity: 0.6;\n  }\n\n  .option-check {\n    display: inline-flex;\n    flex-shrink: 0;\n    margin-inline-start: auto;\n    color: var(--_theme-base);\n    opacity: 0;\n    transition: opacity var(--transition-fast);\n  }\n\n  .option[data-selected] .option-check,\n  .option[aria-selected='true'] .option-check {\n    opacity: 1;\n  }\n\n  .no-results,\n  .no-results-create,\n  .dropdown-loading {\n    padding: var(--size-3) var(--size-2-5);\n    font-size: var(--text-sm);\n    color: var(--color-contrast-400);\n    text-align: center;\n  }\n\n  .no-results-create {\n    display: flex;\n    gap: var(--size-1-5);\n    align-items: center;\n    width: 100%;\n    padding: var(--size-1-5) var(--size-2-5);\n    font-size: var(--text-sm);\n    color: var(--_theme-content, var(--color-primary-content));\n    text-align: start;\n    cursor: pointer;\n    background: none;\n    border: 0;\n    border-radius: var(--rounded-sm);\n  }\n\n  .no-results-create:hover,\n  .no-results-create[data-focused] {\n    background: color-mix(in oklch, var(--_theme-base, var(--color-primary)) 10%, transparent);\n  }\n\n  /* ========================================\n       Option Icon\n       ======================================== */\n\n  .option-icon {\n    display: inline-flex;\n    flex-shrink: 0;\n    align-items: center;\n  }\n\n  /* ========================================\n       Slotted option elements (hidden data nodes)\n       ======================================== */\n\n  ::slotted(ore-combobox-option) {\n    display: none;\n  }\n}\n","import {\n  bind,\n  define,\n  getHost,\n  html,\n  onCleanup,\n  onElement,\n  prop,\n  ref,\n  useEmit,\n  useField,\n  watchEffect,\n} from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport {\n  createChoiceField,\n  createInteraction,\n  createListboxDropdown,\n  type DropdownCloseReason,\n  lifecycleSignal,\n  type OverlayOpenReason,\n} from '../../core';\nimport { colorThemeMixin, reducedMotionMixin, roundedVariantMixin, srOnlyMixin } from '../../styles';\nimport type { AddEventListeners, ComponentSize, RoundedSize, ThemeColor } from '../../types';\nimport { dispatchNativeFieldEvent } from '../shared/native-field-event';\nimport type { ComboboxOptionInput, ComboboxOptionItem, OreComboboxEvents, OreComboboxProps } from './combobox.types';\nimport { filterOptions, getCreatableLabel, makeCreatableValue, parseSlottedOptions } from './combobox-options';\nimport '../../feedback/chip/chip';\nimport '../input/input';\nimport componentStyles from './combobox.css?inline';\n\nexport type { OreComboboxEvents, OreComboboxProps } from './combobox.types';\n\n/**\n * A searchable select field with multiple selection, custom option creation, and large-list support.\n *\n * @element ore-combobox\n *\n * @attr {string} value - Selected value(s). Use comma-separated for multiple.\n * @attr {boolean} multiple - Enable multiple selection\n * @attr {boolean} creatable - Allow users to create custom options from search query\n * @attr {boolean} no-filter - Disable client-side filtering (useful for server-side search)\n * @attr {string} placeholder - Placeholder text\n * @attr {boolean} required - Require a non-blank selection for native form validation\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n *\n * @fires input - Emitted when the selection changes.\n * @fires change - Emitted when the selection changes.\n * @fires open-change - Emitted when the dropdown state changes. detail: { open, reason }\n * @fires {CustomEvent} search - Emitted when user types. detail: { query: string }\n *\n * @slot - Slotted combobox options and option groups\n * @cssprop --combobox-dropdown-bg - Dropdown panel background color\n * @cssprop --combobox-dropdown-border-color - Dropdown panel border color\n * @cssprop --combobox-option-hover-bg - Option background on hover\n * @cssprop --combobox-option-focus-bg - Option background when keyboard-focused\n * @cssprop --combobox-option-selected-bg - Option background when selected\n * @cssprop --combobox-option-selected-focus-bg - Option background when selected and focused\n * @cssprop --input-bg - Field background (passed through to ore-input)\n * @cssprop --input-border-color - Field border color (passed through to ore-input)\n *\n * @part wrapper - Root wrapper around the entire field\n * @part label - Label element shown inside or outside the field\n * @part field - Field container that holds the trigger input and clear button\n * @part input - Search input used to filter and select options\n * @part clear-btn - Button that clears the current selection/query\n * @part dropdown - Popup list container for options\n * @part helper-text - Helper text displayed below the field\n * @example\n * ```html\n * <ore-combobox label=\"Country\" name=\"country\">\n *   <ore-combobox-option value=\"us\">United States</ore-combobox-option>\n *   <ore-combobox-option value=\"gb\">United Kingdom</ore-combobox-option>\n *   <ore-combobox-option value=\"de\" disabled>Germany</ore-combobox-option>\n * </ore-combobox>\n * ```\n */\nexport const COMBOBOX_TAG = 'ore-combobox' as const;\ndefine<OreComboboxProps>(COMBOBOX_TAG, {\n  formAssociated: true,\n  props: {\n    autoclose: prop.bool(false),\n    color: prop.string<ThemeColor>(),\n    creatable: prop.bool(false),\n    disabled: prop.bool(false),\n    error: prop.string(),\n    fullwidth: prop.bool(false),\n    helper: prop.string(),\n    label: prop.string(),\n    'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n    loading: prop.bool(false),\n    multiple: prop.bool(false),\n    name: prop.string(),\n    'no-filter': prop.bool(false),\n    options: prop.data<ComboboxOptionInput[]>(),\n    placeholder: prop.string('Select...'),\n    required: prop.bool(false),\n    rounded: prop.string<RoundedSize>(),\n    size: prop.string<ComponentSize>(),\n    success: prop.bool(false),\n    value: prop.string(),\n    variant: prop.string<'flat' | 'solid' | 'bordered' | 'outline' | 'ghost'>(),\n  },\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreComboboxEvents>();\n    const watch = watchEffect;\n\n    const query = signal('');\n\n    // Element refs needed by the listbox dropdown.\n    let inputEl: HTMLInputElement | null = null;\n    let fieldEl: HTMLElement | null = null; // set to the ore-input host once it mounts\n    let dropdownEl: HTMLElement | null = null;\n    let listboxEl: HTMLElement | null = null;\n\n    // Ref to the ore-input host; resolved when the template renders.\n    const bitInputRef = ref<HTMLElement>();\n\n    const abortSignal = lifecycleSignal(onCleanup);\n    const choice = createChoiceField({\n      disabled: props.disabled,\n      error: props.error,\n      helper: props.helper,\n      label: props.label,\n      labelPlacement: props['label-placement'],\n      multiple: props.multiple,\n      prefix: 'combobox',\n      required: props.required,\n      signal: abortSignal,\n      value: props.value,\n    });\n\n    // filteredOptions signal declared before optionList so the getItems getter\n    // captures the live signal reference rather than needing a factory indirection.\n    const filteredOptions = signal<ComboboxOptionItem[]>([]);\n\n    const optionList = createListboxDropdown<ComboboxOptionItem>({\n      getBoundary: () => el,\n      getFocusedOptionElement: () => dropdownEl?.querySelector<HTMLElement>('[data-focused]') ?? null,\n      getItems: () => filteredOptions.value,\n      getOptionId: (index) => `${choice.fieldId}-opt-${index}`,\n      getPanel: () => dropdownEl,\n      getReference: () => fieldEl,\n      getTrigger: () => inputEl,\n      isDisabled: () => choice.disabled.value,\n      isItemDisabled: (option) => option.disabled,\n      onClose: (reason) => {\n        emit('open-change', { open: false, reason });\n\n        if (!abortSignal.aborted) restoreQueryFromSelection();\n\n        choice.triggerValidation('blur');\n      },\n      onOpen: (reason) => emit('open-change', { open: true, reason }),\n      restoreFocus: false,\n      signal: abortSignal,\n    });\n\n    const { disabled: isDisabled, fieldId: comboId, selectedValues, triggerValidation } = choice;\n\n    choice.attachFormField(\n      useField<string>({\n        disabled: choice.disabled,\n        onReset: choice.reset,\n        toFormValue: (v) => v,\n        validationMessage: choice.validationMessage,\n        validity: choice.validity,\n        value: choice.formValue,\n      }),\n    );\n\n    const { focusedIndex, isOpen, scrollFocusedIntoView, updatePosition } = optionList;\n    // ── State ────────────────────────────────────────────────────────────────\n    const isMultiple = () => Boolean(props.multiple.value);\n    const isCreatable = () => Boolean(props.creatable.value);\n    const isNoFilter = () => Boolean(props['no-filter'].value);\n\n    bind({\n      attr: {\n        open: () => (isOpen.value ? true : undefined),\n        size: props.size,\n        variant: props.variant,\n      },\n    });\n\n    let lastQueryBeforeClear: string | null = null;\n    let isRestoringQuery = false;\n\n    const selectedValue = computed(() => selectedValues.value[0] ?? '');\n\n    // Expose a native-like, string-valued `.value` property on the host.\n    Object.defineProperty(el, 'value', {\n      configurable: true,\n      get: () => choice.formValue.value,\n      set: (val: unknown) => {\n        const v = val as string | string[] | null | undefined;\n\n        if (Array.isArray(v)) {\n          choice.setValues(v.map((entry) => String(entry ?? '')));\n\n          return;\n        }\n\n        if (v == null || v === '') {\n          choice.clear();\n\n          return;\n        }\n\n        choice.setValues(isMultiple() ? String(v).split(',') : [String(v)]);\n      },\n    });\n\n    const hasValue = () => selectedValues.value.length > 0;\n\n    function focusLiveInput() {\n      inputEl?.focus();\n    }\n\n    // ── Options ──────────────────────────────────────────────────────────────\n    const slottedOptions = signal<ComboboxOptionItem[]>([]);\n    const createdOptions = signal<ComboboxOptionItem[]>([]);\n    const isLoading = () => Boolean(props.loading.value);\n\n    function normalizeOption(option: ComboboxOptionInput): ComboboxOptionItem {\n      return {\n        disabled: Boolean(option.disabled),\n        iconEl: option.iconEl ?? null,\n        label: option.label ?? option.value,\n        value: option.value,\n      };\n    }\n\n    // Merged options: explicit prop value overrides slotted options.\n    const allOptions = computed<ComboboxOptionItem[]>(() => {\n      const optionsProp = props.options.value;\n      const base = Array.isArray(optionsProp) ? optionsProp.map(normalizeOption) : slottedOptions.value;\n\n      if (createdOptions.value.length === 0) return base;\n\n      return [...base, ...createdOptions.value];\n    });\n\n    const selectionController = {\n      clear: () => {\n        choice.clear();\n      },\n      remove: (key: string) => {\n        choice.removeValue(key);\n      },\n      select: (key: string) => {\n        choice.selectValue(key);\n      },\n      toggle: (key: string) => {\n        choice.toggleValue(key);\n      },\n    };\n\n    function readOptions(elements: Element[] = Array.from(el.children)) {\n      slottedOptions.value = parseSlottedOptions(elements);\n\n      if (!isMultiple()) {\n        const match = allOptions.value.find((option) => option.value === selectedValue.value);\n\n        query.value = match?.label ?? selectedValue.value;\n      }\n    }\n\n    // Initialize from light DOM immediately; onMounted/observer keep this in sync afterwards.\n    readOptions();\n\n    watch(() => {\n      const nextOptions = filterOptions(allOptions.value, query.value, isNoFilter());\n\n      filteredOptions.value = isMultiple()\n        ? nextOptions.filter((option) => !selectedValues.value.includes(option.value))\n        : nextOptions;\n    });\n\n    // \"Create\" option shown when creatable + query doesn't match any existing option\n    const creatableLabel = computed(() => {\n      return getCreatableLabel(query.value, isCreatable(), filteredOptions.value);\n    });\n    const inputPlaceholder = () =>\n      isMultiple() && selectedValues.value.length > 0 ? '' : props.placeholder.value || '';\n\n    function emitChange() {\n      dispatchNativeFieldEvent(el, 'input');\n      dispatchNativeFieldEvent(el, 'change');\n    }\n\n    function removeChip(event: Event): void {\n      event.stopPropagation();\n\n      const value = (event as CustomEvent<{ value?: string }>).detail?.value;\n\n      if (value === undefined) return;\n\n      selectionController.remove(value);\n      emitChange();\n      triggerValidation('change');\n    }\n\n    function restoreQueryFromSelection() {\n      // Keep input text and selected value in sync whenever the popup closes.\n      if (!isMultiple()) {\n        const match = allOptions.value.find((option) => option.value === selectedValue.value);\n\n        isRestoringQuery = true;\n        query.value = match?.label ?? '';\n        Promise.resolve().then(() => {\n          isRestoringQuery = false;\n        });\n\n        return;\n      }\n\n      query.value = '';\n    }\n\n    watch(() => {\n      if (isOpen.value && !isMultiple() && selectedValue.value && focusedIndex.value === -1 && query.value === '') {\n        const selectedIndex = filteredOptions.value.findIndex((option) => option.value === selectedValue.value);\n\n        if (selectedIndex >= 0) {\n          optionList.set(selectedIndex);\n        }\n      }\n    });\n\n    // ── Open / Close ─────────────────────────────────────────────────────────\n    function openPopup(clearFilter = true, reason: OverlayOpenReason = 'programmatic') {\n      if (clearFilter) {\n        lastQueryBeforeClear = query.value;\n        query.value = '';\n      }\n\n      // Pre-compute focused index BEFORE opening so the first render has it set\n      if (!isMultiple() && selectedValue.value) {\n        const freshOptions = filterOptions(allOptions.value, '', isNoFilter());\n        const selectedIndex = freshOptions.findIndex((option) => option.value === selectedValue.value);\n\n        if (selectedIndex >= 0) {\n          optionList.set(selectedIndex);\n        }\n      }\n\n      optionList.open(reason);\n\n      if (!isMultiple() && selectedValue.value && focusedIndex.value >= 0) {\n        requestAnimationFrame(() => {\n          scrollFocusedIntoView();\n        });\n      }\n    }\n\n    function closePopup(reason: DropdownCloseReason = 'programmatic') {\n      optionList.close(reason);\n    }\n\n    const fieldPress = createInteraction({\n      disabled: isDisabled,\n      onPress: () => {\n        if (!isOpen.value) openPopup(true, 'click');\n\n        focusLiveInput();\n      },\n    });\n\n    const enterPress = createInteraction({\n      disabled: isDisabled,\n      keys: ['Enter'],\n      onPress: (originalEvent: Event) => {\n        const opts = filteredOptions.value;\n\n        if (isOpen.value && focusedIndex.value >= 0 && focusedIndex.value < opts.length) {\n          selectOption(opts[focusedIndex.value], originalEvent);\n        } else if (isOpen.value && focusedIndex.value === -1 && creatableLabel.value) {\n          // Focused on the \"create\" item\n          createOption(query.value, originalEvent);\n        } else if (!isOpen.value) {\n          openPopup(true, 'keyboard');\n        }\n      },\n    });\n\n    // ── Selection ────────────────────────────────────────────────────────────\n    function selectOption(opt: ComboboxOptionItem, _originalEvent?: Event) {\n      if (opt.disabled) return;\n\n      if (isMultiple()) {\n        selectionController.toggle(opt.value);\n        query.value = '';\n        emitChange();\n        triggerValidation('change');\n\n        if (props.autoclose.value) {\n          closePopup();\n        }\n\n        // Keep dropdown open in multiple mode (unless autoclose is true)\n        focusLiveInput();\n        requestAnimationFrame(() => focusLiveInput());\n      } else {\n        selectionController.select(opt.value);\n        query.value = opt.label;\n        emitChange();\n        triggerValidation('change');\n        closePopup();\n        focusLiveInput();\n      }\n    }\n    function resolveOptionFromElement(optionEl: HTMLElement): ComboboxOptionItem | null {\n      const indexAttr = optionEl.getAttribute('data-option-index');\n      const index = indexAttr ? Number(indexAttr) : -1;\n\n      if (Number.isInteger(index) && index >= 0 && index < filteredOptions.value.length) {\n        return filteredOptions.value[index] ?? null;\n      }\n\n      const valueAttr = optionEl.getAttribute('data-option-value');\n\n      if (valueAttr) {\n        const byValue = filteredOptions.value.find((option) => option.value === valueAttr);\n\n        if (byValue) return byValue;\n      }\n\n      const labelText = optionEl.querySelector('span')?.textContent?.trim() ?? optionEl.textContent?.trim() ?? '';\n\n      if (!labelText) return null;\n\n      return filteredOptions.value.find((option) => option.label === labelText || option.value === labelText) ?? null;\n    }\n    function clearValue(e: Event) {\n      e.stopPropagation();\n      selectionController.clear();\n      query.value = '';\n      emitChange();\n      triggerValidation('change');\n      focusLiveInput();\n    }\n    function handleInput(e: InputEvent) {\n      const target = e.target as HTMLInputElement;\n      const newValue = target.value;\n\n      // Skip all input processing if we're in the middle of restoring the query\n      // This prevents the clearing logic from firing during close/restore\n      if (isRestoringQuery) {\n        return;\n      }\n\n      if (newValue === query.value) return;\n\n      query.value = newValue;\n\n      if (!isMultiple()) {\n        const currentItem = selectedValues.value[0];\n        const currentLabel = currentItem\n          ? (allOptions.value.find((o) => o.value === currentItem)?.label ?? currentItem)\n          : '';\n\n        // Preserve the current selection while typing. Selection should only\n        // change when a new option is committed or when the user explicitly clears.\n        const isJustOpening = newValue === '' && lastQueryBeforeClear === currentLabel;\n\n        if (isJustOpening) {\n          lastQueryBeforeClear = null;\n        }\n      }\n\n      optionList.navigate('first');\n\n      if (!isOpen.value) openPopup(false, 'keyboard');\n\n      emit('search', { query: target.value });\n    }\n    function handleFocus() {\n      // Intentionally no-op: open only on explicit click or keyboard.\n      // Opening on every focus surprises users tabbing through a form.\n    }\n\n    // ── Keyboard Navigation ──────────────────────────────────────────────────\n    function handleKeydown(e: KeyboardEvent) {\n      if (isDisabled.value) return;\n\n      if (optionList.handleKeydown(e)) return;\n\n      switch (e.key) {\n        case 'ArrowDown':\n          e.preventDefault();\n\n          if (!isOpen.value) {\n            openPopup(true, 'keyboard');\n            optionList.navigate('first');\n          } else {\n            optionList.navigate('next');\n          }\n\n          break;\n        case 'ArrowUp':\n          e.preventDefault();\n\n          if (!isOpen.value) {\n            openPopup(true, 'keyboard');\n          } else {\n            optionList.navigate('prev');\n          }\n\n          break;\n        case 'Backspace':\n          // In multiple mode, remove the last chip when the input is empty\n          if (isMultiple() && !query.value && selectedValues.value.length > 0) {\n            choice.removeValue(selectedValues.value[selectedValues.value.length - 1] ?? '');\n            emitChange();\n            triggerValidation('change');\n          }\n\n          break;\n        case 'Enter':\n          enterPress.handleKeydown(e);\n\n          break;\n        case 'Tab':\n          closePopup('programmatic');\n          break;\n        default:\n          break;\n      }\n    }\n\n    // ── Create option ────────────────────────────────────────────────────────\n    function createOption(rawQuery: string, originalEvent?: Event) {\n      const actualLabel = rawQuery.trim();\n\n      if (!actualLabel) return;\n\n      const value = makeCreatableValue(actualLabel);\n      const newOpt: ComboboxOptionItem = { disabled: false, iconEl: null, label: actualLabel, value };\n\n      createdOptions.value = [...createdOptions.value, newOpt];\n      selectOption(newOpt, originalEvent);\n    }\n    // ── Lifecycle ────────────────────────────────────────────────────────────\n\n    const observeLightDomOptions = (): (() => void) => {\n      const observer = new MutationObserver(() => {\n        readOptions();\n      });\n\n      observer.observe(el, {\n        attributeFilter: ['disabled', 'label', 'value'],\n        attributes: true,\n        childList: true,\n        subtree: true,\n      });\n\n      return () => observer.disconnect();\n    };\n\n    const stopObserving = observeLightDomOptions();\n\n    const createListboxListeners = (listEl: HTMLElement): (() => void) => {\n      const handleActivate = (event: Event) => {\n        const target = event.target;\n\n        if (!(target instanceof Element)) return;\n\n        const createRow = target.closest<HTMLElement>('.no-results-create');\n\n        if (createRow) {\n          event.preventDefault();\n          event.stopPropagation();\n          createOption(query.value, event);\n\n          return;\n        }\n\n        const optionEl = target.closest<HTMLElement>('.option');\n\n        if (!optionEl) return;\n\n        event.preventDefault();\n        event.stopPropagation();\n\n        const option = resolveOptionFromElement(optionEl);\n\n        if (!option || option.disabled) return;\n\n        selectOption(option, event);\n      };\n\n      const handlePointerMove = (event: PointerEvent) => {\n        const target = event.target;\n\n        if (!(target instanceof Element)) return;\n\n        const optionEl = target.closest<HTMLElement>('.option');\n\n        if (!optionEl) return;\n\n        const option = resolveOptionFromElement(optionEl);\n\n        if (!option) return;\n\n        const focusedIdx = filteredOptions.value.findIndex((candidate) => candidate.value === option.value);\n\n        if (focusedIdx >= 0) {\n          optionList.set(focusedIdx);\n        }\n      };\n\n      listEl.addEventListener('click', handleActivate);\n      listEl.addEventListener('pointermove', handlePointerMove);\n\n      return () => {\n        listEl.removeEventListener('click', handleActivate);\n        listEl.removeEventListener('pointermove', handlePointerMove);\n      };\n    };\n\n    let stopListboxListeners: (() => void) | null = null;\n    let listboxListenersTarget: HTMLElement | null = null;\n\n    const setListboxElement = (el: HTMLElement | null): void => {\n      listboxEl = el;\n\n      if (listboxListenersTarget === el) return;\n\n      stopListboxListeners?.();\n      stopListboxListeners = null;\n      listboxListenersTarget = null;\n\n      if (!el) return;\n\n      stopListboxListeners = createListboxListeners(el);\n      listboxListenersTarget = el;\n    };\n\n    const ensureListboxListeners = (): void => {\n      if (!listboxEl) return;\n\n      if (listboxListenersTarget === listboxEl && stopListboxListeners) return;\n\n      stopListboxListeners?.();\n      stopListboxListeners = createListboxListeners(listboxEl);\n      listboxListenersTarget = listboxEl;\n    };\n\n    watch(() => {\n      ensureListboxListeners();\n\n      if (isOpen.value) {\n        if (dropdownEl && 'showPopover' in dropdownEl && !dropdownEl.matches(':popover-open')) dropdownEl.showPopover();\n\n        updatePosition();\n      } else {\n        if (dropdownEl && 'hidePopover' in dropdownEl && dropdownEl.matches(':popover-open')) dropdownEl.hidePopover();\n      }\n    });\n\n    // Once ore-input is in the DOM, grab its inner <input> from its shadow root\n    // and attach all combobox-specific ARIA + event handlers imperatively.\n    // MUST be registered before the ARIA effects below so inputEl is set first\n    // when bitInputRef fires (effects run in registration order).\n    onElement(bitInputRef, (bitInputEl) => {\n      fieldEl = bitInputEl;\n\n      const rawInput = bitInputEl.shadowRoot?.querySelector<HTMLInputElement>('input') ?? null;\n\n      if (!rawInput) return;\n\n      inputEl = rawInput;\n\n      rawInput.setAttribute('role', 'combobox');\n      rawInput.setAttribute('autocomplete', 'off');\n      rawInput.setAttribute('aria-autocomplete', 'list');\n      rawInput.setAttribute('aria-haspopup', 'listbox');\n      rawInput.setAttribute('spellcheck', 'false');\n      rawInput.setAttribute('aria-controls', `${comboId}-listbox`);\n\n      const handleInputClick = (): void => {\n        if (!isOpen.value) openPopup(true, 'click');\n\n        focusLiveInput();\n      };\n\n      rawInput.addEventListener('input', handleInput as EventListener);\n      rawInput.addEventListener('keydown', handleKeydown as EventListener);\n      rawInput.addEventListener('focus', handleFocus);\n      rawInput.addEventListener('click', handleInputClick);\n\n      return () => {\n        inputEl = null;\n        fieldEl = null;\n        rawInput.removeEventListener('input', handleInput as EventListener);\n        rawInput.removeEventListener('keydown', handleKeydown as EventListener);\n        rawInput.removeEventListener('focus', handleFocus);\n        rawInput.removeEventListener('click', handleInputClick);\n      };\n    });\n\n    // Reactively sync combobox-specific ARIA attrs that ore-input doesn't manage.\n    // Uses bitInputRef (a signal) as the gate so the effect re-runs when the\n    // inner input mounts — inputEl is a plain variable and would not trigger re-runs.\n    watch(() => {\n      if (!bitInputRef.value) return;\n\n      const el = inputEl;\n\n      if (!el) return;\n\n      el.setAttribute('aria-expanded', String(isOpen.value));\n\n      if (isDisabled.value) {\n        el.setAttribute('aria-disabled', 'true');\n      } else {\n        el.removeAttribute('aria-disabled');\n      }\n\n      if (props.error.value) {\n        el.setAttribute('aria-invalid', 'true');\n        el.setAttribute('aria-errormessage', `${comboId}-error`);\n      } else {\n        el.removeAttribute('aria-invalid');\n        el.removeAttribute('aria-errormessage');\n      }\n    });\n\n    // Reactively sync the query signal into the raw input value.\n    watch(() => {\n      if (!bitInputRef.value) return;\n\n      const el = inputEl;\n\n      if (!el) return;\n\n      if (el.value !== query.value) el.value = query.value;\n    });\n\n    onCleanup(() => {\n      stopListboxListeners?.();\n      stopListboxListeners = null;\n      listboxListenersTarget = null;\n      stopObserving();\n    });\n\n    const inputColor = () => props.color?.value ?? undefined;\n    const inputSize = () => props.size?.value ?? undefined;\n    const inputVariant = () => props.variant?.value ?? undefined;\n    const inputRounded = () => props.rounded?.value ?? undefined;\n    const inputFullwidth = () => (props.fullwidth.value ? true : undefined);\n\n    return html`\n      <slot></slot>\n      <ore-input\n        class=\"trigger\"\n        ref=${bitInputRef}\n        label=\"${() => props.label.value ?? ''}\"\n        placeholder=\"${inputPlaceholder}\"\n        label-placement=\"${() => props['label-placement'].value ?? 'inset'}\"\n        color=\"${inputColor}\"\n        size=\"${inputSize}\"\n        variant=\"${inputVariant}\"\n        rounded=\"${inputRounded}\"\n        helper=\"${() => props.helper.value ?? ''}\"\n        error=\"${() => props.error.value ?? ''}\"\n        ?disabled=\"${isDisabled}\"\n        ?required=\"${() => false}\"\n        ?fullwidth=\"${inputFullwidth}\"\n        ?success=\"${() => props.success.value}\"\n        name=\"${() => props.name.value ?? ''}\"\n        @click=\"${(e: MouseEvent) => {\n          fieldPress.handleClick(e);\n        }}\"\n        part=\"wrapper\">\n        <div slot=\"prefix\" class=\"chips-row\">\n          <!-- Keep chip list diffing isolated so input node identity stays stable. -->\n          <span class=\"chips-list\">\n            ${() =>\n              (isMultiple() ? selectedValues.value : []).map(\n                (value) => html`\n                  <ore-chip\n                    value=${value}\n                    label=${allOptions.value.find((option) => option.value === value)?.label ?? value}\n                    mode=\"removable\"\n                    variant=\"flat\"\n                    size=\"sm\"\n                    color=\"${props.color}\"\n                    @remove=${removeChip}>\n                    ${allOptions.value.find((option) => option.value === value)?.label ?? value}\n                  </ore-chip>\n                `,\n              )}\n          </span>\n        </div>\n        <span slot=\"suffix\" class=\"combobox-suffix\" aria-hidden=\"true\">\n          <button\n            class=\"clear-btn\"\n            part=\"clear-btn\"\n            type=\"button\"\n            aria-label=\"Clear\"\n            tabindex=\"-1\"\n            ?hidden=${() => !hasValue()}\n            @click=\"${clearValue}\">\n            <ore-icon name=\"x\" size=\"12\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n          </button>\n          <span class=\"combobox-suffix-end\">\n            <span class=\"loader\"></span>\n            <span class=\"chevron\">\n              <ore-icon name=\"chevron-down\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n            </span>\n          </span>\n        </span>\n      </ore-input>\n      <span\n        class=\"sr-only\"\n        id=\"${() => `${comboId}-error`}\"\n        role=\"alert\"\n        aria-live=\"assertive\"\n        ?hidden=\"${() => !props.error.value}\">\n        ${() => props.error.value ?? ''}\n      </span>\n      <div\n        class=\"dropdown\"\n        part=\"dropdown\"\n        id=\"${() => `${comboId}-dropdown`}\"\n        popover=\"manual\"\n        ?data-open=${() => isOpen.value}\n        ref=${(el: HTMLElement | null) => {\n          dropdownEl = el;\n        }}>\n        <div\n          role=\"listbox\"\n          id=\"${() => `${comboId}-listbox`}\"\n          style=\"${() =>\n            isOpen.value && filteredOptions.value.length > 0 ? `height:${filteredOptions.value.length * 36}px;` : ''}\"\n          aria-label=\"${() => props.label.value || props.placeholder.value || 'Options'}\"\n          ref=${(el: HTMLElement | null) => {\n            setListboxElement(el);\n          }}>\n          ${() => {\n            if (!isOpen.value) return '';\n\n            if (isLoading()) {\n              return html`\n                <div class=\"dropdown-loading\">Loading...</div>\n              `;\n            }\n\n            if (filteredOptions.value.length === 0) {\n              if (creatableLabel.value) {\n                return html`\n                  <button type=\"button\" class=\"no-results-create\" ?data-focused=${() => focusedIndex.value === -1}>\n                    ${creatableLabel.value}\n                  </button>\n                `;\n              }\n\n              return html`\n                <div class=\"no-results\" role=\"presentation\">No results found</div>\n              `;\n            }\n\n            return filteredOptions.value.map((option, index) => {\n              return html`\n                <div\n                  class=\"option\"\n                  role=\"option\"\n                  id=\"${`${comboId}-opt-${index}`}\"\n                  data-option-index=\"${index}\"\n                  data-option-value=\"${option.value}\"\n                  aria-selected=\"${() =>\n                    String(\n                      isMultiple() ? selectedValues.value.includes(option.value) : selectedValue.value === option.value,\n                    )}\"\n                  aria-disabled=\"${String(option.disabled)}\"\n                  style=\"${`position:absolute;top:0;left:0;right:0;transform:translateY(${index * 36}px);`}\"\n                  ?data-focused=${() => focusedIndex.value === index}\n                  ?data-selected=${() =>\n                    isMultiple() ? selectedValues.value.includes(option.value) : selectedValue.value === option.value}\n                  ?data-disabled=${option.disabled}>\n                  <span>${option.label}</span>\n                  <span class=\"option-check\" aria-hidden=\"true\">\n                    <ore-icon name=\"check\" size=\"14\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n                  </span>\n                </div>\n              `;\n            });\n          }}\n        </div>\n      </div>\n    `;\n  },\n  shadow: { delegatesFocus: true },\n  styles: [colorThemeMixin, reducedMotionMixin, roundedVariantMixin, srOnlyMixin, componentStyles],\n}) as unknown as AddEventListeners<OreComboboxEvents>;\n","import \"../_dev.js\";\n//#region src/function/debounce.ts\nfunction e(e, t = 300, n = {\n\tleading: !1,\n\ttrailing: !0\n}) {\n\tlet r = n.leading ?? !1, i = n.trailing ?? !0, a, o, s, c = !1, l = () => {\n\t\ta !== void 0 && (clearTimeout(a), a = void 0);\n\t}, u = () => {\n\t\tif (l(), c = !1, !o) return;\n\t\tlet t = o;\n\t\treturn o = void 0, s = e(...t), s;\n\t};\n\treturn Object.assign((...n) => (o = n, r && !c && (c = !0, s = e(...n), o = void 0, !i) ? (a = setTimeout(() => {\n\t\ta = void 0, c = !1;\n\t}, t), s) : r && !i && c ? s : (l(), a = setTimeout(u, t), s)), {\n\t\tcancel: () => {\n\t\t\tl(), o = void 0, c = !1;\n\t\t},\n\t\tflush: () => u(),\n\t\tpending: () => a !== void 0\n\t});\n}\n//#endregion\nexport { e as debounce };\n\n//# sourceMappingURL=debounce.js.map","@layer refine.base {\n  :host {\n    display: inline-block;\n    min-width: var(--select-min-width, 12rem);\n  }\n\n  :host([fullwidth]) {\n    display: block;\n    width: 100%;\n  }\n\n  /* Hide native <option> elements — we render our own UI */\n  ::slotted(option),\n  ::slotted(optgroup) {\n    display: none;\n  }\n\n  /* ore-input is readonly so pointer defaults to text — override to pointer.\n     `width: 100%` matters just as much: `:host` is `display: inline-block`, which — unlike a\n     flex/grid container with `align-items`/`justify-items: stretch` — never stretches its own\n     children to fill its own box. Without this, `.trigger` (an `ore-input`, whose own `:host`\n     only guarantees a 12rem *minimum*) stays shrink-wrapped to that minimum even when this\n     select's own host has already been stretched wider by an ancestor grid/flex track — visibly\n     narrower than a sibling field (e.g. `ore-number-input`) occupying the same-width track. */\n  .trigger {\n    width: 100%;\n    cursor: pointer;\n  }\n\n  .trigger::part(input) {\n    cursor: pointer;\n    caret-color: transparent;\n    user-select: none;\n  }\n\n  /* Chips slot inside ore-input prefix */\n  .chips-row {\n    display: flex;\n    flex-wrap: wrap;\n    gap: var(--size-1);\n    align-items: center;\n    min-width: 0;\n  }\n\n  .chips-row[hidden] {\n    display: none;\n  }\n\n  /* Suffix: loader (left) + chevron (right) */\n  .trigger-suffix {\n    display: flex;\n    gap: var(--size-1);\n    align-items: center;\n    color: var(--color-contrast-500);\n  }\n\n  .trigger-icon {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    transition: transform var(--transition-fast);\n  }\n\n  :host([open]) .trigger-icon {\n    transform: rotate(180deg);\n  }\n\n  .loader {\n    display: none;\n    flex-shrink: 0;\n    width: 1em;\n    height: 1em;\n    border: 2px solid currentcolor;\n    border-inline-end-color: transparent;\n    border-radius: 50%;\n    animation: var(--_motion-animation, spin var(--transition-loader) infinite);\n  }\n\n  /* Keyframe must live in shadow DOM — @keyframes don't inherit across shadow roots */\n  @keyframes spin {\n    to {\n      transform: rotate(360deg);\n    }\n  }\n\n  :host([loading]) .loader {\n    display: inline-block;\n  }\n\n  /* ========================================\n       Dropdown Listbox\n       ======================================== */\n\n  .dropdown {\n    position: fixed;\n    inset: 0 auto auto 0;\n    z-index: var(--z-dropdown, 8000);\n    box-sizing: border-box;\n    display: flex;\n    flex-direction: column;\n    gap: var(--size-0-5);\n    max-height: 260px;\n    padding: var(--size-1);\n    margin: 0;\n    overflow-y: auto;\n    overscroll-behavior: contain;\n    text-align: start;\n    pointer-events: none;\n    background: var(--color-canvas);\n    border: var(--border) solid var(--color-contrast-200);\n    border-radius: var(--_radius);\n    box-shadow: var(--shadow-lg);\n\n    /* Hidden by default */\n    opacity: 0;\n    backdrop-filter: blur(var(--blur-md));\n    transform: translateY(var(--overlay-enter-translate-y));\n    transition: var(\n      --_motion-transition,\n      opacity var(--transition-fast),\n      transform var(--transition-fast),\n      display var(--transition-fast) allow-discrete\n    );\n  }\n\n  .dropdown[data-open] {\n    pointer-events: auto;\n    opacity: 1;\n    transform: translateY(0);\n\n    @starting-style {\n      opacity: 0;\n      transform: translateY(var(--overlay-enter-translate-y));\n    }\n  }\n\n  .options-list {\n    display: flex;\n    flex-direction: column;\n    gap: 0;\n  }\n\n  /* ========================================\n       Option Items\n       ======================================== */\n\n  .option {\n    display: flex;\n    gap: var(--size-2);\n    align-items: center;\n    padding: var(--size-1-5) var(--size-2-5);\n    font-size: var(--text-sm);\n    line-height: var(--leading-normal);\n    cursor: pointer;\n    border-radius: var(--rounded-sm);\n    transition:\n      background var(--transition-fast),\n      color var(--transition-fast);\n  }\n\n  /* Truncate long labels to keep option rows compact and readable. */\n  .option > span:first-child {\n    flex: 1;\n    min-width: 0;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n  }\n\n  .option:hover:not([data-disabled]) {\n    background: var(--color-contrast-100);\n  }\n\n  .option[data-focused]:not([data-disabled]) {\n    color: var(--_theme-base);\n    background: color-mix(in oklch, var(--_theme-base) 12%, var(--color-contrast-100));\n  }\n\n  .option[data-selected] {\n    font-weight: var(--font-medium);\n    color: var(--_theme-base);\n    background: color-mix(in oklch, var(--_theme-base) 10%, var(--color-contrast-50));\n  }\n\n  .option[data-selected][data-focused] {\n    background: color-mix(in oklch, var(--_theme-base) 20%, var(--color-contrast-100));\n  }\n\n  .option[data-disabled] {\n    color: var(--color-contrast-400);\n    cursor: not-allowed;\n    opacity: 0.6;\n  }\n\n  .option-check {\n    display: inline-flex;\n    flex-shrink: 0;\n    margin-inline-start: auto;\n    color: var(--_theme-base);\n    opacity: 0;\n    transition: opacity var(--transition-fast);\n  }\n\n  .option[data-selected] .option-check {\n    opacity: 1;\n  }\n\n  /* ========================================\n       Option Groups\n       ======================================== */\n\n  .optgroup-label {\n    padding: var(--size-1-5) var(--size-2-5) var(--size-1);\n    font-size: var(--text-xs);\n    font-weight: var(--font-semibold);\n    color: var(--color-contrast-500);\n    text-transform: uppercase;\n    letter-spacing: var(--tracking-wide, 0.05em);\n  }\n\n  /* ========================================\n       Loading / No-Results\n       ======================================== */\n\n  .dropdown-loading,\n  .dropdown-empty {\n    padding: var(--size-3) var(--size-2-5);\n    font-size: var(--text-sm);\n    color: var(--color-contrast-500);\n    text-align: center;\n  }\n}\n","import { bind, define, getHost, html, onCleanup, onMounted, prop, useEmit, useField, useSlots } from '@vielzeug/ore';\nimport { computed, effect, signal, watch } from '@vielzeug/ripple';\n\nimport type { OverlayOpenChangeDetail, OverlayOpenReason } from '../../core';\nimport { createChoiceField, createListboxDropdown, lifecycleSignal } from '../../core';\nimport type { SelectableFieldProps } from '../../shared';\nimport type { VisualVariant } from '../../types';\nimport '../../feedback/chip/chip';\nimport '../../content/icon/icon';\nimport '../input/input';\nimport { disablableBundle, loadableBundle, roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, reducedMotionMixin, roundedVariantMixin } from '../../styles';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport componentStyles from './select.css?inline';\n\n// ── Types ─────────────────────────────────────────────────────────────\n\ntype OptionItem = {\n  disabled: boolean;\n  group?: string;\n  label: string;\n  value: string;\n};\n\nexport type OreSelectOptionInput = {\n  disabled?: boolean;\n  group?: string;\n  label?: string;\n  value: string;\n};\n\ntype FlatRow =\n  | {\n      idx: number;\n      opt: OptionItem;\n      type: 'option';\n    }\n  | {\n      label: string;\n      type: 'group';\n    };\n\n// ── Styles ─────────────────────────────────────────────────────────────\n\n// ── Component Props ─────────────────────────────────────────────────────────────\n\n/** Select component properties */\n\nexport type OreSelectEvents = {\n  change: Event;\n  input: Event;\n  'open-change': OverlayOpenChangeDetail;\n};\n\nexport type OreSelectProps = SelectableFieldProps<Exclude<VisualVariant, 'frost'>> & {\n  /** Show loading state in dropdown */\n  loading?: boolean;\n  /** Allow selecting multiple options */\n  multiple?: boolean;\n  /** JS options array (alternative to slotted <option> elements) */\n  options?: OreSelectOptionInput[];\n  /** Mark the field as required */\n  required?: boolean;\n};\n\n/**\n * A fully custom form-associated select dropdown with keyboard navigation and ARIA support.\n * Reads `<option>` and `<optgroup>` children from the default slot.\n *\n * @element ore-select\n *\n * @attr {string} label - Label text\n * @attr {string} label-placement - 'inset' | 'outside'\n * @attr {string} value - Current selected value(s) (comma-separated for multiple)\n * @attr {string} placeholder - Placeholder when no option selected\n * @attr {string} name - Form field name\n * @attr {boolean} multiple - Enable multi-select\n * @attr {boolean} disabled - Disable the select\n * @attr {boolean} required - Required field\n * @attr {string} helper - Helper text below the select\n * @attr {string} error - Error message\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'text'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {boolean} fullwidth - Expand to full width\n *\n * @fires input - Fired when selection changes.\n * @fires change - Fired when selection changes.\n * @fires open-change - Fired when the dropdown state changes. detail: { open, reason }\n *\n * @slot - `<option>` and `<optgroup>` elements\n *\n * @cssprop --select-bg - Background\n * @cssprop --select-border-color - Border color\n * @cssprop --select-radius - Border radius\n * @cssprop --select-padding - Padding\n * @cssprop --select-font-size - Font size\n * @cssprop --select-placeholder-color - Placeholder text color\n *\n * @part trigger - The `ore-input` trigger element that opens the dropdown.\n * @part dropdown - The dropdown listbox panel container.\n *\n * @example\n * ```html\n * <ore-select label=\"Role\" value=\"admin\">\n *   <option value=\"admin\">Administrator</option>\n *   <option value=\"editor\">Editor</option>\n *   <option value=\"viewer\">Viewer</option>\n * </ore-select>\n *\n * <ore-select label=\"Tags\" multiple color=\"primary\">\n *   <optgroup label=\"Frontend\">\n *     <option value=\"react\">React</option>\n *     <option value=\"vue\">Vue</option>\n *   </optgroup>\n *   <optgroup label=\"Backend\">\n *     <option value=\"node\">Node.js</option>\n *   </optgroup>\n * </ore-select>\n * ```\n */\nexport const SELECT_TAG = 'ore-select' as const;\ndefine<OreSelectProps>(SELECT_TAG, {\n  formAssociated: true,\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...disablableBundle,\n    ...loadableBundle,\n    ...roundableBundle,\n    error: prop.string(),\n    fullwidth: prop.bool(false),\n    helper: prop.string(),\n    label: prop.string(),\n    'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n    multiple: prop.bool(false),\n    name: prop.string(),\n    options: prop.json(undefined as OreSelectOptionInput[] | undefined),\n    placeholder: prop.string(),\n    required: prop.bool(false),\n    success: prop.bool(false),\n    value: prop.string(),\n    variant: prop.string<Exclude<VisualVariant, 'frost'>>(),\n  },\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreSelectEvents>();\n    const slots = useSlots();\n\n    const shadowRoot = el.shadowRoot;\n    // ────────────────────────────────────────────────────────────────\n    // State & Context\n    // ────────────────────────────────────────────────────────────────\n\n    const slottedOptions = signal<OptionItem[]>([]);\n    const isLoading = computed(() => Boolean(props.loading.value));\n\n    // Merged options: explicit prop value overrides slotted options\n    function normalizeOption(option: OreSelectOptionInput): OptionItem {\n      return {\n        disabled: Boolean(option.disabled),\n        group: option.group,\n        label: option.label ?? option.value,\n        value: option.value,\n      };\n    }\n\n    const options = computed(() => {\n      const explicitOptions = props.options.value;\n\n      return Array.isArray(explicitOptions) ? explicitOptions.map(normalizeOption) : slottedOptions.value;\n    });\n    let triggerEl: HTMLElement | null = null;\n    let dropdownEl: HTMLElement | null = null;\n\n    const abortSignal = lifecycleSignal(onCleanup);\n    const choice = createChoiceField({\n      disabled: props.disabled,\n      error: props.error,\n      helper: props.helper,\n      label: props.label,\n      labelPlacement: props['label-placement'],\n      multiple: props.multiple,\n      prefix: 'select',\n      required: props.required,\n      signal: abortSignal,\n      value: props.value,\n    });\n\n    choice.attachFormField(\n      useField<string>({\n        disabled: choice.disabled,\n        onReset: choice.reset,\n        toFormValue: (v) => v,\n        validationMessage: choice.validationMessage,\n        validity: choice.validity,\n        value: choice.formValue,\n      }),\n    );\n\n    const optionList = createListboxDropdown<OptionItem>({\n      getBoundary: () => el,\n      getFocusedOptionElement: () => dropdownEl?.querySelector<HTMLElement>('[data-focused]') ?? null,\n      getItems: () => options.value,\n      getPanel: () => dropdownEl,\n      getReference: () => triggerEl,\n      getTrigger: () => triggerEl,\n      isDisabled: () => choice.disabled.value,\n      isItemDisabled: (option) => option.disabled,\n      onClose: (reason) => {\n        emit('open-change', { open: false, reason });\n        choice.triggerValidation('blur');\n      },\n      onOpen: (reason) => emit('open-change', { open: true, reason }),\n      signal: abortSignal,\n    });\n\n    const { triggerValidation } = choice;\n    const selectedValues = choice.selectedValues;\n    const isDisabled = choice.disabled;\n\n    defineFieldValue(\n      el,\n      () => choice.formValue.value,\n      (value) => {\n        choice.setValues(value ? value.split(',') : []);\n      },\n    );\n\n    const { fieldId: selectId } = choice;\n    const listboxId = `listbox-${selectId}`;\n    const { focusedIndex, isOpen } = optionList;\n\n    // Sync host attributes for CSS hooks\n    bind({\n      attr: {\n        'has-error': () => (props.error.value ? true : undefined),\n        open: () => (isOpen.value ? true : undefined),\n        size: props.size,\n        variant: props.variant,\n      },\n    });\n\n    // ────────────────────────────────────────────────────────────────\n    // Option Reading from Slot\n    // ────────────────────────────────────────────────────────────────\n\n    function readOptions() {\n      const slot = shadowRoot?.querySelector<HTMLSlotElement>('slot');\n\n      if (!slot) return;\n\n      const assigned = slot.assignedElements({ flatten: true });\n      const items: OptionItem[] = [];\n\n      for (const el of assigned) {\n        if (el.tagName === 'OPTION') {\n          const opt = el as HTMLOptionElement;\n\n          items.push({ disabled: opt.disabled, label: opt.text || opt.value, value: opt.value });\n        } else if (el.tagName === 'OPTGROUP') {\n          const group = el as HTMLOptGroupElement;\n          const groupLabel = group.label;\n\n          for (const child of Array.from(group.querySelectorAll('option'))) {\n            const opt = child as HTMLOptionElement;\n\n            items.push({ disabled: opt.disabled, group: groupLabel, label: opt.text || opt.value, value: opt.value });\n          }\n        }\n      }\n\n      slottedOptions.value = items;\n    }\n\n    const displayLabel = computed(() => {\n      if (selectedValues.value.length === 0) return '';\n\n      if (props.multiple.value && selectedValues.value.length > 1) {\n        return `${selectedValues.value.length} selected`;\n      }\n\n      const first = selectedValues.value[0];\n\n      return options.value.find((o) => o.value === first)?.label ?? first;\n    });\n    const selectedChipItems = computed(() => {\n      if (!props.multiple.value) return [];\n\n      return selectedValues.value.map((value) => ({\n        label: options.value.find((o) => o.value === value)?.label ?? value,\n        value,\n      }));\n    });\n    const showChips = computed(() => props.multiple.value && selectedValues.value.length > 0);\n    const triggerText = computed(() => displayLabel.value || props.placeholder.value || '');\n\n    function buildFlatList(opts: OptionItem[]): FlatRow[] {\n      const flat: FlatRow[] = [];\n      const groups = new Map<string | undefined, OptionItem[]>();\n\n      for (const opt of opts) {\n        const key = opt.group;\n\n        let group = groups.get(key);\n\n        if (!group) {\n          group = [];\n          groups.set(key, group);\n        }\n\n        group.push(opt);\n      }\n\n      let globalIdx = 0;\n\n      for (const [groupLabel, groupOpts] of groups) {\n        if (groupLabel !== undefined) flat.push({ label: groupLabel, type: 'group' });\n\n        for (const opt of groupOpts) flat.push({ idx: globalIdx++, opt, type: 'option' });\n      }\n\n      return flat;\n    }\n\n    const flatRows = computed(() => buildFlatList(options.value));\n\n    function emitChange(): void {\n      setFieldValue(el, choice.formValue.value);\n      dispatchNativeFieldEvent(el, 'input');\n      dispatchNativeFieldEvent(el, 'change');\n    }\n\n    function removeChip(event: Event): void {\n      event.stopPropagation();\n\n      const value = (event as CustomEvent<{ value?: string }>).detail?.value;\n\n      if (value === undefined) return;\n\n      choice.removeValue(value);\n      emitChange();\n      triggerValidation('change');\n    }\n\n    function openPopup(reason: OverlayOpenReason = 'programmatic') {\n      optionList.open(reason);\n\n      requestAnimationFrame(() => {\n        const selectedIndex =\n          selectedValues.value.length > 0\n            ? options.value.findIndex((option) => option.value === selectedValues.value[0])\n            : -1;\n\n        if (selectedIndex >= 0) {\n          optionList.set(selectedIndex);\n\n          return;\n        }\n\n        optionList.navigate('first');\n      });\n    }\n\n    // Selection\n\n    function selectOption(opt: OptionItem, _e?: Event) {\n      if (opt.disabled) return;\n\n      if (props.multiple.value) {\n        choice.toggleValue(opt.value);\n      } else {\n        choice.selectValue(opt.value);\n        optionList.close();\n      }\n\n      emitChange();\n      triggerValidation('change');\n    }\n\n    // Keyboard navigation\n\n    function handleTriggerKeydown(e: KeyboardEvent) {\n      if (isDisabled.value) return;\n\n      // Let optionList handle arrow key navigation\n      if (optionList.handleKeydown(e)) return;\n\n      switch (e.key) {\n        case ' ':\n        case 'Enter':\n          e.preventDefault();\n\n          if (isOpen.value) {\n            const idx = focusedIndex.value;\n            const opts = options.value;\n\n            if (idx >= 0 && idx < opts.length) selectOption(opts[idx], e);\n          } else {\n            openPopup('keyboard');\n          }\n\n          break;\n        case 'Tab':\n          optionList.close();\n          break;\n      }\n    }\n\n    // ore-input prop helpers\n    const inputValue = () => triggerText.value;\n    const inputLabel = () => props.label.value ?? '';\n    const inputPlaceholder = () => props.placeholder.value ?? '';\n    const inputLabelPlacement = () => props['label-placement'].value ?? 'inset';\n    const inputColor = () => props.color?.value ?? undefined;\n    const inputSize = () => props.size?.value ?? undefined;\n    const inputVariant = () => props.variant?.value ?? undefined;\n    const inputRounded = () => props.rounded?.value ?? undefined;\n    const inputHelper = () => props.helper.value ?? '';\n    const inputError = () => props.error.value ?? '';\n    const inputDisabled = () => (isDisabled.value ? true : undefined);\n    const inputRequired = () => (props.required.value ? true : undefined);\n    const inputFullwidth = () => (props.fullwidth.value ? true : undefined);\n    const tabIndexAttr = () => (isDisabled.value ? '-1' : '0');\n\n    watch(slots.elements(), () => readOptions(), { immediate: true });\n\n    const stopPopoverSync = effect(() => {\n      if (isOpen.value) {\n        if (dropdownEl && 'showPopover' in dropdownEl && !dropdownEl.matches(':popover-open')) dropdownEl.showPopover();\n      } else {\n        if (dropdownEl && 'hidePopover' in dropdownEl && dropdownEl.matches(':popover-open')) dropdownEl.hidePopover();\n      }\n    });\n\n    onCleanup(() => stopPopoverSync.dispose());\n\n    onMounted(() => {\n      let onTriggerClick: ((event: MouseEvent) => void) | null = null;\n      let onTriggerKeydown: ((event: KeyboardEvent) => void) | null = null;\n\n      if (triggerEl) {\n        onTriggerClick = (event: MouseEvent) => {\n          event.stopPropagation();\n\n          if (isDisabled.value) return;\n\n          if (isOpen.value) optionList.close('trigger');\n          else openPopup('click');\n        };\n        onTriggerKeydown = (event: KeyboardEvent) => {\n          handleTriggerKeydown(event);\n        };\n\n        triggerEl.addEventListener('click', onTriggerClick);\n        triggerEl.addEventListener('keydown', onTriggerKeydown);\n      }\n\n      return () => {\n        if (triggerEl && onTriggerClick) triggerEl.removeEventListener('click', onTriggerClick);\n\n        if (triggerEl && onTriggerKeydown) triggerEl.removeEventListener('keydown', onTriggerKeydown);\n      };\n    });\n\n    return html`\n      <slot style=\"display:none\"></slot>\n      <ore-input\n        class=\"trigger\"\n        part=\"trigger\"\n        readonly\n        tabindex=\"${tabIndexAttr}\"\n        role=\"combobox\"\n        aria-haspopup=\"listbox\"\n        aria-controls=\"${listboxId}\"\n        aria-disabled=\"${() => (isDisabled.value ? 'true' : null)}\"\n        aria-expanded=\"${() => String(isOpen.value)}\"\n        aria-invalid=\"${() => (props.error.value ? 'true' : null)}\"\n        value=\"${inputValue}\"\n        label=\"${inputLabel}\"\n        placeholder=\"${inputPlaceholder}\"\n        label-placement=\"${inputLabelPlacement}\"\n        color=\"${inputColor}\"\n        size=\"${inputSize}\"\n        variant=\"${inputVariant}\"\n        rounded=\"${inputRounded}\"\n        helper=\"${inputHelper}\"\n        error=\"${inputError}\"\n        ?disabled=\"${inputDisabled}\"\n        ?required=\"${inputRequired}\"\n        ?fullwidth=\"${inputFullwidth}\"\n        ?success=\"${() => props.success.value}\"\n        ref=\"${(el: HTMLElement) => {\n          triggerEl = el;\n        }}\">\n        <div slot=\"prefix\" class=\"chips-row\" ?hidden=\"${() => !showChips.value}\">\n          ${() =>\n            selectedChipItems.value.map(\n              (item) => html`\n                <ore-chip\n                  value=\"${item.value}\"\n                  label=\"${item.label}\"\n                  mode=\"removable\"\n                  variant=\"flat\"\n                  size=\"sm\"\n                  color=\"${props.color}\"\n                  @remove=\"${removeChip}\">\n                  ${item.label}\n                </ore-chip>\n              `,\n            )}\n        </div>\n        <span slot=\"suffix\" class=\"trigger-suffix\" aria-hidden=\"true\">\n          <span class=\"loader\"></span>\n          <span class=\"trigger-icon\">\n            <ore-icon name=\"chevron-down\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n          </span>\n        </span>\n      </ore-input>\n      <div\n        class=\"dropdown\"\n        part=\"dropdown\"\n        popover=\"manual\"\n        ?data-open=\"${isOpen}\"\n        role=\"listbox\"\n        id=\"${listboxId}\"\n        aria-label=\"Options\"\n        ref=\"${(el: HTMLElement) => {\n          dropdownEl = el;\n        }}\">\n        <div class=\"dropdown-loading\" ?hidden=\"${() => !isLoading.value}\">Loading…</div>\n        <div class=\"dropdown-empty\" ?hidden=\"${() => isLoading.value || options.value.length > 0}\">No options</div>\n        <div class=\"options-list\" ?hidden=\"${() => isLoading.value || options.value.length === 0}\">\n          ${() =>\n            flatRows.value.map((row) =>\n              row.type === 'group'\n                ? html`\n                    <div class=\"optgroup-label\" role=\"presentation\">${row.label}</div>\n                  `\n                : html`\n                    <div\n                      class=\"option\"\n                      role=\"option\"\n                      id=\"${`${selectId}-opt-${row.idx}`}\"\n                      data-option-index=\"${String(row.idx)}\"\n                      data-option-value=\"${row.opt.value}\"\n                      aria-selected=\"${() => String(selectedValues.value.includes(row.opt.value))}\"\n                      aria-disabled=\"${() => String(row.opt.disabled)}\"\n                      ?data-focused=\"${() => focusedIndex.value === row.idx}\"\n                      ?data-selected=\"${() => selectedValues.value.includes(row.opt.value)}\"\n                      ?data-disabled=\"${() => row.opt.disabled}\"\n                      @click=\"${(e: MouseEvent) => {\n                        e.stopPropagation();\n                        selectOption(row.opt, e);\n                      }}\"\n                      @pointerenter=\"${() => {\n                        optionList.set(row.idx);\n                      }}\">\n                      <span>${row.opt.label}</span>\n                      <span class=\"option-check\" aria-hidden=\"true\">\n                        <ore-icon name=\"check\" size=\"14\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n                      </span>\n                    </div>\n                  `,\n            )}\n        </div>\n      </div>\n    `;\n  },\n  shadow: { delegatesFocus: true },\n  styles: [colorThemeMixin, reducedMotionMixin, roundedVariantMixin, componentStyles],\n});\n","import type { Placement } from '@vielzeug/orbit';\n\nimport { computePosition, flip, offset, shift } from '@vielzeug/orbit';\nimport { type Readable, type Signal, signal, watch } from '@vielzeug/ripple';\n\nimport {\n  createOutsidePointerDismissal,\n  type DialogCloseReason,\n  lifecycleSignal,\n  type OverlayOpenReason,\n} from '../../core';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type FloatingTriggerType = 'click' | 'focus' | 'hover';\n\nexport type AriaBindFn = (triggerEl: HTMLElement) => () => void;\n\nexport type FloatingTriggerOptions = {\n  /** ARIA binding factory: called with the trigger element, returns a cleanup. */\n  bindTriggerAria: AriaBindFn;\n  /** Initial uncontrolled visibility. Ignored when `openProp` is defined. */\n  defaultOpen: Readable<boolean | undefined>;\n  /** If true, disable all trigger interactions and close if open. */\n  disabled: Readable<boolean>;\n  /** Returns the host element (e.g. ore-popover) so slotted content clicks aren't treated as outside clicks. */\n  getHost?: () => Element | null;\n  /** Returns the panel element, if mounted. */\n  getPanel: () => HTMLElement | null;\n  /** Gap from reference to floating panel in px. Default: 8. Accepts a signal for runtime reactivity. */\n  offset?: Readable<number | undefined> | number;\n  /** Cleanup registrar from the component setup ctx. Automatically called on disconnect. */\n  onCleanup: (fn: () => void) => void;\n  /** Called when the popover closes. */\n  onClose?: (reason: DialogCloseReason) => void;\n  /** Called when the popover opens. */\n  onOpen?: (reason: OverlayOpenReason) => void;\n  /** Callback when resolved placement changes (useful for CSS attribute). */\n  onPlacementChange?: (placement: Placement) => void;\n  /** Controlled open prop. When defined, disables uncontrolled logic. */\n  openProp: Readable<boolean | undefined>;\n  /** Preferred placement. Default: 'bottom'. */\n  placement: Readable<Placement>;\n  /** Slot element or a factory to lazily find it. Resolved each time bindEvents runs. */\n  slot: HTMLSlotElement | null | (() => HTMLSlotElement | null);\n  /** Slot elements signal — used to rebind when slotted elements change. */\n  slotElements: Readable<Element[]>;\n  /** Which triggers are active. Set to empty array or omit if handling events manually. */\n  triggers: Readable<FloatingTriggerType[]>;\n};\n\nexport type FloatingTriggerHandle = {\n  /** Closes the panel. No-op if controlled. */\n  close: (reason?: DialogCloseReason) => void;\n  /**\n   * Call inside `onMounted`. Sets up slot + trigger event watchers\n   * and returns a cleanup function to pass back to the framework.\n   */\n  mount: () => () => void;\n  /** Opens the panel. No-op if controlled. */\n  open: (reason?: OverlayOpenReason) => void;\n  /** Toggles the panel. No-op if controlled. */\n  toggle: () => void;\n  /** Manually trigger a position recalculation. */\n  updatePosition: () => void;\n  /** Whether the panel is currently visible. */\n  visible: Signal<boolean>;\n};\n\n// ── Implementation ─────────────────────────────────────────────────────────────\n\n/**\n * Shared logic for floating-panel triggers (tooltip, popover).\n *\n * Handles:\n * - Slot-based trigger element detection and rebinding\n * - Event binding per trigger type (hover / focus / click)\n * - Floating-element positioning via `@vielzeug/orbit`\n * - Controlled mode via `openProp` watcher\n * - Keyboard escape dismissal\n *\n * ARIA binding is intentionally delegated to the caller via `bindTriggerAria`\n * so that tooltip (`describedby`) and popover (`expanded`/`controls`/…) can diverge.\n */\nexport const useFloatingTrigger = (options: FloatingTriggerOptions): FloatingTriggerHandle => {\n  const {\n    bindTriggerAria,\n    defaultOpen,\n    disabled,\n    getPanel,\n    onClose,\n    onOpen,\n    onPlacementChange,\n    openProp,\n    placement,\n    slot,\n    slotElements,\n    triggers,\n  } = options;\n\n  const resolveSlot = (): HTMLSlotElement | null => (typeof slot === 'function' ? slot() : slot);\n  const getOffset = (): number => {\n    const o = options.offset;\n\n    if (o == null) return 8;\n\n    const val = typeof o === 'object' ? (o as Readable<number | undefined>).value : o;\n\n    return val ?? 8;\n  };\n  const abortSignal = lifecycleSignal(options.onCleanup);\n  const visible = signal(false);\n  const isControlled = () => openProp.value !== undefined;\n  let currentTrigger: HTMLElement | null = null;\n  let triggerBinding: (() => void) | null = null;\n\n  function updatePosition(): void {\n    const panel = getPanel();\n    const trigger =\n      currentTrigger ?? (resolveSlot()?.assignedElements({ flatten: true })[0] as HTMLElement | undefined);\n\n    if (!panel || !trigger) return;\n\n    const previousTransition = panel.style.transition;\n    const previousTransform = panel.style.transform;\n\n    panel.style.transition = 'none';\n    panel.style.transform = 'none';\n\n    const result = computePosition(trigger, panel, {\n      middleware: [offset(getOffset()), flip(), shift({ padding: 8 })],\n      placement: placement.value,\n    });\n\n    panel.style.left = `${result.x}px`;\n    panel.style.top = `${result.y}px`;\n    panel.style.transition = previousTransition;\n    panel.style.transform = previousTransform;\n    panel.dataset.placement = result.placement;\n\n    onPlacementChange?.(result.placement as Placement);\n  }\n\n  function showFloat(): void {\n    visible.value = true;\n\n    const panel = getPanel();\n\n    if (panel) {\n      panel.dataset.open = '';\n\n      if ('showPopover' in panel) {\n        try {\n          if (!panel.matches(':popover-open')) panel.showPopover();\n        } catch {\n          // Popover API restricted (e.g. sandboxed iframe); data-open CSS fallback handles visibility.\n        }\n      }\n    }\n\n    updatePosition();\n  }\n\n  function hideFloat(): void {\n    visible.value = false;\n\n    const panel = getPanel();\n\n    if (panel) {\n      delete panel.dataset.open;\n\n      if ('hidePopover' in panel) {\n        try {\n          if (panel.matches(':popover-open')) panel.hidePopover();\n        } catch {\n          // Popover API restricted; data-open removal handles visibility.\n        }\n      }\n    }\n  }\n\n  function open(reason: OverlayOpenReason = 'programmatic'): void {\n    if (isControlled() || disabled.value || visible.value) return;\n\n    showFloat();\n    onOpen?.(reason);\n  }\n\n  function close(reason: DialogCloseReason = 'trigger'): void {\n    if (isControlled() || !visible.value) return;\n\n    hideFloat();\n    onClose?.(reason);\n  }\n\n  function toggle(): void {\n    if (isControlled()) return;\n\n    if (visible.value) close();\n    else open('click');\n  }\n\n  function handleKeydown(e: KeyboardEvent): void {\n    if (e.key === 'Escape') close('escape');\n  }\n\n  function handleFocusOut(e: FocusEvent): void {\n    const next = e.relatedTarget as Element | null;\n    const panel = getPanel();\n\n    if (next && panel?.contains(next)) return;\n\n    if (next && currentTrigger?.contains(next)) return;\n\n    close('trigger');\n  }\n\n  const bindEvents = (): void => {\n    triggerBinding?.();\n    triggerBinding = null;\n\n    const triggerEl = resolveSlot()?.assignedElements({ flatten: true })[0] as HTMLElement | undefined;\n\n    if (!triggerEl) {\n      currentTrigger = null;\n\n      return;\n    }\n\n    currentTrigger = triggerEl;\n\n    const removeAria = bindTriggerAria(triggerEl);\n    const cleanups: Array<() => void> = [];\n\n    const add = (\n      target: EventTarget,\n      event: string,\n      listener: EventListener,\n      eventOptions?: AddEventListenerOptions,\n    ): void => {\n      target.addEventListener(event, listener, eventOptions);\n      cleanups.push(() => target.removeEventListener(event, listener, eventOptions));\n    };\n\n    const t = triggers.value;\n\n    if (t.includes('click')) {\n      add(triggerEl, 'click', toggle as EventListener);\n    }\n\n    if (t.includes('hover')) {\n      add(triggerEl, 'pointerenter', () => open('hover'));\n      add(triggerEl, 'pointerleave', () => close('trigger'));\n\n      const panelEl = getPanel();\n\n      if (panelEl) {\n        add(panelEl, 'pointerenter', () => open('hover'));\n        add(panelEl, 'pointerleave', () => close('trigger'));\n      }\n    }\n\n    if (t.includes('focus')) {\n      add(triggerEl, 'focusin', () => open('focus'));\n      add(triggerEl, 'focusout', handleFocusOut as EventListener);\n\n      const panelEl = getPanel();\n\n      if (panelEl) add(panelEl, 'focusout', handleFocusOut as EventListener);\n    }\n\n    add(document, 'keydown', handleKeydown as EventListener);\n\n    triggerBinding = () => {\n      removeAria();\n\n      for (const cleanup of cleanups) cleanup();\n\n      currentTrigger = null;\n    };\n  };\n\n  const stopOutsidePointerDismissal = createOutsidePointerDismissal({\n    getTargets: () => [currentTrigger, getPanel(), options.getHost?.()],\n    isActive: () => visible.value && triggers.value.includes('click'),\n    onDismiss: () => close('outsideClick'),\n    signal: abortSignal,\n  });\n\n  const mount = (): (() => void) => {\n    let initializedOpenProp = false;\n    const triggerSlot = resolveSlot();\n    const rebind = (): void => {\n      queueMicrotask(() => {\n        if (!abortSignal.aborted) bindEvents();\n      });\n    };\n\n    triggerSlot?.addEventListener('slotchange', rebind);\n    rebind();\n    watch(slotElements, bindEvents, { immediate: true });\n\n    watch(\n      openProp,\n      (openVal) => {\n        if (openVal === undefined || openVal === null) {\n          if (initializedOpenProp && visible.value) {\n            hideFloat();\n            onClose?.('programmatic');\n          }\n\n          initializedOpenProp = true;\n\n          return;\n        }\n\n        initializedOpenProp = true;\n\n        if (openVal) {\n          showFloat();\n          onOpen?.('programmatic');\n        } else if (visible.value) {\n          hideFloat();\n          onClose?.('programmatic');\n        }\n      },\n      { immediate: true },\n    );\n\n    if (openProp.value === undefined && defaultOpen.value) {\n      showFloat();\n      onOpen?.('programmatic');\n    }\n\n    watch(disabled, (isNowDisabled) => {\n      if (isNowDisabled) close('programmatic');\n    });\n\n    return () => {\n      triggerSlot?.removeEventListener('slotchange', rebind);\n      triggerBinding?.();\n      triggerBinding = null;\n\n      const panel = getPanel();\n\n      if (panel) {\n        delete panel.dataset.open;\n\n        if ('hidePopover' in panel) {\n          try {\n            if (panel.matches(':popover-open')) panel.hidePopover();\n          } catch {\n            // Popover API restricted; data-open removal handles visibility.\n          }\n        }\n      }\n\n      stopOutsidePointerDismissal();\n    };\n  };\n\n  return { close, mount, open, toggle, updatePosition, visible };\n};\n","@layer refine.base {\n  :host {\n    --_panel-bg: var(--popover-bg, var(--color-canvas));\n    --_panel-blur: var(--popover-panel-blur, var(--blur-md));\n    --_panel-border-color: var(--popover-border-color, var(--color-divider));\n    --_panel-shadow: var(--popover-shadow, var(--shadow-xl));\n\n    position: relative;\n    display: inline-block;\n  }\n\n  .panel {\n    position: fixed;\n\n    /* Popover UA resets */\n    inset: unset;\n    box-sizing: border-box;\n    min-width: var(--popover-min-width, 12rem);\n    max-width: var(--popover-max-width, 24rem);\n    max-height: var(--popover-max-height, min(70vh, 32rem));\n    padding: 0;\n    margin: 0;\n    overflow: auto;\n    word-break: auto-phrase;\n    overflow-wrap: anywhere;\n    background: var(--_panel-bg);\n    border: var(--border) solid var(--_panel-border-color);\n    border-radius: var(--rounded-lg);\n    box-shadow: var(--_panel-shadow);\n\n    /* Hidden by default */\n    opacity: 0;\n    backdrop-filter: blur(var(--_panel-blur));\n    transform: scale(var(--overlay-enter-scale-dialog)) translateY(4px);\n    transition:\n      opacity var(--transition-fast),\n      transform 200ms var(--ease-spring),\n      display var(--transition-fast) allow-discrete,\n      overlay var(--transition-fast) allow-discrete;\n  }\n\n  .panel[data-open] {\n    display: block;\n  }\n\n  .panel:popover-open,\n  .panel[data-open] {\n    opacity: 1;\n    transform: scale(1) translateY(0);\n\n    @starting-style {\n      opacity: 0;\n      transform: scale(var(--overlay-enter-scale-dialog)) translateY(4px);\n    }\n  }\n}\n","import type { Placement } from '@vielzeug/orbit';\nimport {\n  bind,\n  createStableId,\n  define,\n  getHost,\n  html,\n  onCleanup,\n  onMounted,\n  prop,\n  useEmit,\n  useSlots,\n} from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\n\nimport { type OverlayOpenChangeDetail, parseStringTriggers } from '../../core';\nimport { disablableBundle } from '../../shared';\nimport { reducedMotionMixin } from '../../styles';\nimport { useFloatingTrigger } from '../shared/use-floating-trigger';\nimport styles from './popover.css?inline';\n\nexport type PopoverTrigger = 'click' | 'focus' | 'hover';\n\nconst PANEL_OFFSET = 8;\nconst VALID_TRIGGERS = new Set<PopoverTrigger>(['click', 'focus', 'hover']);\nconst DEFAULT_POPOVER_TRIGGERS: PopoverTrigger[] = ['click'];\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n  value == null ? undefined : value === '' || value === 'true';\n\nconst normalizeTriggers = (value: unknown): PopoverTrigger[] =>\n  parseStringTriggers(String(value ?? ''), VALID_TRIGGERS, DEFAULT_POPOVER_TRIGGERS);\n\nexport type OrePopoverEvents = {\n  'open-change': OverlayOpenChangeDetail;\n};\n\n/** Popover component properties */\nexport type OrePopoverProps = {\n  /** Initial uncontrolled open state. Ignored when `open` is set. */\n  'default-open'?: boolean;\n  /** Disable the popover */\n  disabled?: boolean;\n  /** Accessible label for the panel */\n  label?: string;\n  /** Gap between trigger and panel in px */\n  offset?: number;\n  /** Controlled open state */\n  open?: boolean;\n  /** Preferred placement relative to the trigger */\n  placement?: Placement;\n  /** Which trigger(s) open/close the popover */\n  trigger?: string;\n};\n\n/**\n * A floating panel anchored to a trigger element.\n *\n * @element ore-popover\n * @attr {string} placement - Preferred placement (default: 'bottom')\n * @attr {string} trigger - 'click' | 'hover' | 'focus' (default: 'click')\n * @attr {boolean} open - Controlled open state\n * @attr {boolean} default-open - Initial uncontrolled open state\n * @attr {number} offset - Gap in px (default: 8)\n * @attr {boolean} disabled - Disables the popover\n * @attr {string} label - aria-label on the panel\n * @fires open-change - When the panel state changes. detail: { open, reason }\n * @slot - The trigger element\n * @slot content - Panel content\n * @part panel - Panel container.\n *\n * @example\n * ```html\n * <ore-popover placement=\"bottom\" trigger=\"click\">\n *   <ore-button>Open info</ore-button>\n *   <div slot=\"content\">\n *     <p>Popover body content goes here.</p>\n *   </div>\n * </ore-popover>\n * ```\n */\nexport const POPOVER_TAG = 'ore-popover' as const;\ndefine<OrePopoverProps>(POPOVER_TAG, {\n  props: {\n    ...disablableBundle,\n    'default-open': prop.bool(false),\n    label: prop.string(),\n    offset: prop.number(PANEL_OFFSET),\n    open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n    placement: prop.oneOf(\n      [\n        'bottom',\n        'bottom-end',\n        'bottom-start',\n        'left',\n        'left-end',\n        'left-start',\n        'right',\n        'right-end',\n        'right-start',\n        'top',\n        'top-end',\n        'top-start',\n      ] as const,\n      'bottom',\n    ),\n    trigger: prop.string('click'),\n  },\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OrePopoverEvents>();\n    const slots = useSlots();\n\n    const shadowRoot = el.shadowRoot;\n    const isDisabled = computed(() => Boolean(props.disabled.value));\n    const panelId = createStableId('popover');\n    const triggers = computed<PopoverTrigger[]>(() => normalizeTriggers(props.trigger.value));\n    let panelEl: HTMLElement | null = null;\n\n    const floating = useFloatingTrigger({\n      bindTriggerAria: (triggerEl) =>\n        bind(\n          {\n            aria: {\n              controls: () => panelId,\n              disabled: () => String(isDisabled.value),\n              expanded: () => String(floating.visible.value),\n              haspopup: 'dialog',\n            },\n          },\n          { target: triggerEl },\n        ),\n      defaultOpen: props['default-open'],\n      disabled: isDisabled,\n      getHost: () => el,\n      getPanel: () => panelEl,\n      offset: props.offset,\n      onCleanup,\n      onClose: (reason) => emit('open-change', { open: false, reason }),\n      onOpen: (reason) => emit('open-change', { open: true, reason }),\n      openProp: props.open as typeof props.open & { value: boolean | undefined },\n      placement: computed(() => props.placement.value as Placement),\n      slot: () => shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])') ?? null,\n      slotElements: slots.elements(),\n      triggers,\n    });\n\n    onMounted(() => floating.mount());\n\n    return html`\n      <slot></slot>\n      <div\n        class=\"panel\"\n        part=\"panel\"\n        id=\"${panelId}\"\n        role=\"dialog\"\n        aria-modal=\"false\"\n        popover=\"manual\"\n        aria-label=\"${props.label}\"\n        aria-hidden=\"${() => String(!floating.visible.value)}\"\n        ref=${(ref: HTMLElement) => {\n          panelEl = ref;\n        }}>\n        <slot name=\"content\"></slot>\n      </div>\n    `;\n  },\n  styles: [reducedMotionMixin, styles],\n});\n","@layer refine.base {\n  :host {\n    /* ── Datagrid-specific token overrides on top of tableBaseMixin ─────── */\n    --_row-hover-bg: var(--datagrid-row-hover-bg, color-mix(in oklch, var(--color-contrast-500) 5%, transparent));\n    --_row-selected-bg: var(--datagrid-row-selected-bg, color-mix(in oklch, var(--_accent) 10%, transparent));\n    --_row-selected-border: var(--datagrid-row-selected-border, var(--_accent));\n  }\n\n  /* ── Scroll wrapper ───────────────────────────────────────────────────────── */\n\n  .dg-scroll {\n    max-height: var(--datagrid-max-height, none);\n    overflow: auto;\n  }\n\n  /* ── Table ────────────────────────────────────────────────────────────────── */\n\n  .dg-table {\n    width: 100%;\n    font-size: var(--_font-size);\n    table-layout: auto;\n    border-collapse: collapse;\n  }\n\n  /* ── Head ─────────────────────────────────────────────────────────────────── */\n\n  .dg-head {\n    position: sticky;\n    top: 0;\n    z-index: 2;\n    background: var(--_header-bg);\n    box-shadow: inset 0 calc(var(--border) * -1) 0 var(--_border-color);\n  }\n\n  .dg-th {\n    padding: var(--_cell-padding-y) var(--_cell-padding-x);\n    font-size: var(--text-xs);\n    font-weight: var(--font-semibold);\n    color: var(--color-contrast-500);\n    text-align: start;\n    text-transform: uppercase;\n    letter-spacing: 0.04em;\n    white-space: nowrap;\n    user-select: none;\n    border-right: var(--border) solid var(--_border-color);\n\n    &[data-align='center'] {\n      text-align: center;\n    }\n\n    &[data-align='right'] {\n      text-align: right;\n    }\n\n    &:has(.dg-sort-btn) {\n      padding: 0;\n    }\n  }\n\n  .dg-sort-btn {\n    --button-padding: var(--_cell-padding-y) var(--_cell-padding-x);\n    --button-font-size: var(--text-xs);\n    --button-font-weight: var(--font-semibold);\n    --button-color: var(--color-contrast-500);\n    --button-justify: flex-start;\n\n    height: 100%;\n  }\n\n  .dg-th[data-align='center'] .dg-sort-btn {\n    --button-justify: center;\n  }\n\n  .dg-th[data-align='right'] .dg-sort-btn {\n    --button-justify: flex-end;\n  }\n\n  :host(:dir(rtl)) .dg-th,\n  :dir(rtl) .dg-th {\n    border-right: none;\n    border-left: var(--border) solid var(--_border-color);\n  }\n\n  .dg-th:last-child,\n  .dg-th.dg-th-check,\n  .dg-th.dg-th-expand,\n  .dg-th.dg-th-last {\n    border-right: none;\n  }\n\n  :host(:dir(rtl)) .dg-th:last-child,\n  :host(:dir(rtl)) .dg-th.dg-th-check,\n  :host(:dir(rtl)) .dg-th.dg-th-expand,\n  :host(:dir(rtl)) .dg-th.dg-th-last,\n  :dir(rtl) .dg-th:last-child,\n  :dir(rtl) .dg-th.dg-th-check,\n  :dir(rtl) .dg-th.dg-th-expand,\n  :dir(rtl) .dg-th.dg-th-last {\n    border-left: none;\n  }\n\n  .dg-th-inner {\n    position: relative;\n    display: flex;\n    gap: var(--size-1);\n    align-items: center;\n  }\n\n  .dg-th[aria-sort]:has(.dg-sort-btn:hover):not(:has(.dg-sort-btn[aria-disabled='true'])) {\n    background: color-mix(in oklch, var(--color-contrast-900) 5%, transparent);\n  }\n\n  .dg-th[aria-sort='ascending'] .dg-sort-icon,\n  .dg-th[aria-sort='descending'] .dg-sort-icon {\n    color: var(--_accent);\n  }\n\n  /* Select-all checkbox cell */\n  .dg-th-check {\n    width: var(--size-5);\n    min-width: var(--size-5);\n    padding: var(--_cell-padding-y) var(--_cell-padding-x);\n  }\n\n  .dg-th-check,\n  .dg-td-check {\n    vertical-align: middle;\n    text-align: center;\n  }\n\n  .dg-td.dg-td-check {\n    padding: var(--size-1) 0 0;\n  }\n\n  /* ore-checkbox used for select-all and row checkboxes — label-less, compact */\n  .dg-check {\n    display: inline-flex;\n    gap: 0;\n    align-items: center;\n    justify-content: center;\n    min-height: 0;\n    cursor: pointer;\n  }\n\n  /* ── Body rows ────────────────────────────────────────────────────────────── */\n\n  .dg-body .dg-tr {\n    border-block-end: var(--border) solid var(--_border-color);\n    transition: background var(--transition-fast);\n  }\n\n  .dg-body .dg-tr:hover:not([data-disabled], [aria-selected='true']) {\n    background: var(--_row-hover-bg);\n  }\n\n  /* ── Selection ─────────────────────────────────────────────────────────────── */\n\n  .dg-body .dg-tr[aria-selected='true'] {\n    background: var(--_row-selected-bg);\n  }\n\n  .dg-body .dg-tr[data-selectable] {\n    cursor: pointer;\n    outline: none;\n  }\n\n  .dg-body .dg-tr[data-selectable]:focus-visible {\n    box-shadow: inset 0 0 0 2px var(--_row-selected-border);\n  }\n\n  .dg-body .dg-tr[data-disabled] {\n    pointer-events: none;\n    opacity: 0.45;\n  }\n\n  /* Striped rows */\n  :host([striped]) .dg-body .dg-tr:nth-child(even) {\n    background: var(--_stripe-bg);\n  }\n\n  :host([striped]) .dg-body .dg-tr:nth-child(even)[aria-selected='true'] {\n    background: var(--_row-selected-bg);\n  }\n\n  /* ── Body cells ────────────────────────────────────────────────────────────── */\n\n  .dg-td {\n    max-width: var(--datagrid-cell-max-width, 32ch);\n    padding: var(--_cell-padding-y) var(--_cell-padding-x);\n    overflow: hidden;\n    text-overflow: ellipsis;\n    vertical-align: middle;\n    color: var(--color-contrast-800);\n    white-space: nowrap;\n    border-right: var(--border) solid var(--_border-color);\n\n    &[data-align='center'] {\n      text-align: center;\n    }\n\n    &[data-align='right'] {\n      text-align: right;\n    }\n  }\n\n  :host(:dir(rtl)) .dg-td,\n  :dir(rtl) .dg-td {\n    border-right: none;\n    border-left: var(--border) solid var(--_border-color);\n  }\n\n  .dg-td:last-child,\n  .dg-td.dg-td-check,\n  .dg-td.dg-td-expand,\n  .dg-td.dg-td-last {\n    border-right: none;\n  }\n\n  :host(:dir(rtl)) .dg-td:last-child,\n  :host(:dir(rtl)) .dg-td.dg-td-check,\n  :host(:dir(rtl)) .dg-td.dg-td-expand,\n  :host(:dir(rtl)) .dg-td.dg-td-last,\n  :dir(rtl) .dg-td:last-child,\n  :dir(rtl) .dg-td.dg-td-check,\n  :dir(rtl) .dg-td.dg-td-expand,\n  :dir(rtl) .dg-td.dg-td-last {\n    border-left: none;\n  }\n\n  /* ── Empty state ──────────────────────────────────────────────────────────── */\n\n  .dg-empty {\n    padding: var(--size-12) var(--_cell-padding-x);\n    font-size: var(--text-sm);\n    color: var(--color-contrast-400);\n    text-align: center;\n  }\n\n  .dg-empty-content {\n    display: flex;\n    flex-direction: column;\n    gap: var(--size-4);\n    align-items: center;\n    justify-content: center;\n  }\n\n  .dg-empty-actions {\n    margin-top: var(--size-2);\n  }\n\n  /* ── Controls bar (tabs + action row) ───────────────────────────────────── */\n\n  .dg-controls {\n    display: flex;\n    gap: var(--size-3);\n    align-items: center;\n    justify-content: space-between;\n    height: var(--size-8);\n    padding: var(--size-1-5) var(--_cell-padding-x);\n    background: var(--_header-bg);\n    border-block-end: var(--border) solid var(--_border-color);\n  }\n\n  /* ── Tab system (left) ───────────────────────────────────────────────────── */\n\n  .dg-tabs {\n    display: flex;\n    flex: 1;\n    gap: var(--size-1);\n    align-items: center;\n    min-width: 0;\n    overflow: hidden;\n  }\n\n  .dg-tab {\n    --button-padding: var(--size-0-5) var(--size-2-5);\n    --button-font-size: var(--text-xs);\n    --button-color: var(--color-contrast-500);\n\n    flex: 1;\n    min-width: 0;\n  }\n\n  .dg-tab--active {\n    --button-color: var(--color-contrast-900);\n    --button-bg: color-mix(in oklch, var(--color-contrast-500) 10%, transparent);\n    --button-border-color: var(--_border-color);\n    --button-border: var(--border);\n\n    font-weight: var(--font-semibold);\n  }\n\n  /* ── Action bar (right) ──────────────────────────────────────────────────── */\n\n  .dg-actions {\n    display: flex;\n    flex-shrink: 0;\n    gap: var(--size-0-5);\n    align-items: center;\n  }\n\n  /* ── Shared icon button — used by action bar, search-expand clear, popover header icons ── */\n\n  .dg-action-divider {\n    display: inline-block;\n    flex-shrink: 0;\n    width: var(--border);\n    height: var(--size-4);\n    margin-inline: var(--size-1);\n    background: var(--_border-color);\n\n    &[hidden] {\n      display: none;\n    }\n  }\n\n  .dg-filter {\n    display: block;\n    width: 100%;\n  }\n\n  /* ── Search toggle (rightmost action) ───────────────────────────────────── */\n\n  .dg-search {\n    display: flex;\n    flex-direction: row-reverse;\n    gap: var(--size-1);\n    align-items: center;\n  }\n\n  .dg-search-input {\n    --input-height: var(--size-7);\n    display: block;\n    flex-shrink: 0;\n    width: 0;\n    overflow: hidden;\n    opacity: 0;\n    transition:\n      width var(--transition-fast),\n      opacity var(--transition-fast);\n  }\n\n  .dg-search--open .dg-search-input {\n    width: 12rem;\n    overflow: visible;\n    opacity: 1;\n  }\n\n  @media (prefers-reduced-motion: reduce) {\n    .dg-search-input {\n      transition: none;\n    }\n  }\n\n  /* ── ore-popover: action popover wrapper ─────────────────────────────────── */\n\n  .dg-action-popover {\n    display: inline-flex;\n  }\n\n  /* ── Popover content: shared header row ─────────────────────────────────── */\n\n  .dg-pop-header {\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    padding: var(--size-3) var(--size-3) var(--size-2);\n  }\n\n  .dg-pop-title {\n    font-size: var(--text-xs);\n    font-weight: var(--font-semibold);\n    color: var(--color-contrast-600);\n    letter-spacing: 0.02em;\n  }\n\n  /* ── Sort / Group by popover content ────────────────────────────────────── */\n\n  .dg-pop-sort {\n    display: flex;\n    flex-direction: column;\n    padding-block-end: var(--size-2);\n  }\n\n  .dg-pop-sort-row {\n    display: flex;\n    gap: var(--size-2);\n    align-items: center;\n    padding: var(--size-1) var(--size-3);\n  }\n\n  .dg-pop-select {\n    --select-min-width: var(--size-20);\n\n    flex: 2;\n  }\n\n  .dg-pop-dir-select {\n    --select-min-width: var(--size-10);\n\n    flex: 1;\n  }\n\n  /* ── Filter popover content ──────────────────────────────────────────────── */\n\n  .dg-pop-filter {\n    display: flex;\n    flex-direction: column;\n  }\n\n  /* Field picker: select columns to add filter rules. */\n  .dg-pop-filter-fields {\n    padding: 0 var(--size-3) var(--size-3);\n  }\n\n  /* ── Filter rules section ────────────────────────────────────────────────── */\n\n  .dg-pop-filter-rules {\n    padding-block-start: var(--size-1);\n    border-block-start: var(--border) solid var(--_border-color);\n\n    &[hidden] {\n      display: none;\n    }\n  }\n\n  .dg-pop-filter-rule {\n    display: flex;\n    flex-direction: column;\n    gap: var(--size-2);\n    padding: var(--size-2) var(--size-3);\n  }\n\n  .dg-pop-filter-rule-header {\n    display: flex;\n    gap: var(--size-1-5);\n    align-items: center;\n  }\n\n  .dg-pop-filter-field {\n    font-size: var(--text-xs);\n    font-weight: var(--font-semibold);\n    color: var(--color-contrast-800);\n    white-space: nowrap;\n  }\n\n  .dg-pop-filter-op-select {\n    --select-min-width: 0;\n    --select-height: var(--size-6);\n    --select-font-size: var(--text-2xs);\n    --select-padding-x: var(--size-1-5);\n\n    flex: 1;\n    min-width: 6rem;\n  }\n\n  .dg-pop-col-item {\n    --button-radius: var(--rounded-md);\n\n    justify-content: flex-start;\n  }\n\n  .dg-pop-col-list {\n    display: flex;\n    flex-wrap: wrap;\n    gap: var(--size-1);\n    max-width: 25rem;\n    padding: var(--size-3);\n  }\n\n  /* ── Footer / pagination bar ─────────────────────────────────────────────── */\n\n  .dg-footer {\n    display: flex;\n    gap: var(--size-2);\n    align-items: center;\n    padding: var(--size-2) var(--_cell-padding-x);\n    font-size: var(--text-xs);\n    color: var(--color-contrast-500);\n    background: var(--_header-bg);\n  }\n\n  .dg-footer-info {\n    white-space: nowrap;\n  }\n\n  .dg-footer-end {\n    display: flex;\n    gap: var(--size-2);\n    align-items: center;\n    width: fit-content;\n    margin-inline-start: auto;\n  }\n\n  .dg-page-size-wrap {\n    flex-shrink: 0;\n    width: 5rem;\n  }\n\n  .dg-page-size-select {\n    --select-min-width: 0;\n    --select-height: var(--size-7);\n    --select-font-size: var(--text-xs);\n    --select-padding-x: var(--size-2);\n  }\n\n  .dg-pagination {\n    display: flex;\n    gap: var(--size-1);\n    align-items: center;\n  }\n\n  :host(:dir(rtl)) .dg-page-btn,\n  :dir(rtl) .dg-page-btn {\n    transform: scaleX(-1);\n  }\n\n  .dg-page-btn {\n    --button-color: var(--color-contrast-600);\n    --button-radius: var(--rounded-md);\n\n    width: var(--size-7);\n    height: var(--size-7);\n  }\n\n  .dg-page-btn:hover {\n    --button-color: var(--color-contrast-900);\n    --button-bg: var(--color-contrast-300);\n  }\n\n  .dg-page-btn:disabled {\n    cursor: not-allowed;\n    opacity: 0.35;\n  }\n\n  .dg-page-label {\n    padding-inline: var(--size-1);\n    white-space: nowrap;\n  }\n\n  /* ── Column resize handle (F4) ───────────────────────────────────────────── */\n\n  .dg-col-resize {\n    position: absolute;\n    inset-block: calc(var(--_cell-padding-y) * -1);\n    inset-inline-end: calc((var(--_cell-padding-x) + var(--border) + 2px) * -1);\n    width: var(--size-1);\n    cursor: col-resize;\n    user-select: none;\n    background: transparent;\n    border-radius: var(--rounded);\n    transition: background var(--transition-fast);\n  }\n\n  .dg-col-resize:hover,\n  .dg-col-resize:active {\n    background: var(--_accent, var(--color-contrast-300));\n  }\n\n  /* ── Cell keyboard focus (ARIA grid roving tabindex) ─────────────────────── */\n\n  .dg-td:focus-visible,\n  .dg-th:focus-visible {\n    outline: 2px solid var(--_row-selected-border);\n    outline-offset: -2px;\n  }\n\n  /* ── Row expansion ────────────────────────────────────────────────────────── */\n\n  .dg-tr-expanded .dg-td-expanded {\n    padding: var(--_cell-padding-y) var(--_cell-padding-x);\n    border: none;\n\n    /* Paint background + bottom separator via box-shadow so it is\n       direction-agnostic and covers the host outer border on both sides. */\n    box-shadow:\n      inset 0 0 0 9999px color-mix(in oklch, var(--color-contrast-600) 4%, var(--_bg, transparent)),\n      inset 0 calc(var(--border) * -1) 0 var(--_border-color);\n  }\n\n  .dg-tr-expanded:last-child .dg-td-expanded {\n    box-shadow: inset 0 0 0 9999px color-mix(in oklch, var(--color-contrast-900) 4%, var(--_bg, transparent));\n  }\n\n  .dg-tr:has(+ .dg-tr-expanded) {\n    border-block-end: none;\n  }\n\n  .dg-th-expand,\n  .dg-td-expand {\n    width: var(--size-8);\n    min-width: var(--size-8);\n    padding-block: var(--size-1) 0;\n    padding-inline: 0 var(--size-2);\n    text-align: center;\n    white-space: nowrap;\n    border-right: none;\n    border-left: none;\n  }\n\n  .dg-expand-btn {\n    --button-color: var(--color-contrast-500);\n    --button-radius: var(--rounded-sm);\n\n    width: var(--size-5);\n    height: var(--size-5);\n  }\n\n  .dg-expand-btn:hover {\n    --button-color: var(--color-contrast-900);\n  }\n\n  .dg-expand-btn:disabled {\n    cursor: not-allowed;\n    opacity: 0.4;\n  }\n\n  /* ── Loading overlay ──────────────────────────────────────────────────────── */\n\n  .dg-loading-overlay {\n    position: absolute;\n    inset: 0;\n    z-index: 3;\n    display: none;\n    align-items: center;\n    justify-content: center;\n    background: color-mix(in oklch, var(--_bg, white) 40%, transparent);\n    backdrop-filter: blur(1px);\n  }\n\n  :host([loading]) .dg-loading-overlay {\n    display: flex;\n  }\n\n  :host([loading]) .dg-scroll table {\n    pointer-events: none;\n    opacity: 0.5;\n  }\n\n  .dg-spin {\n    animation: dg-spin 1s linear infinite;\n  }\n\n  @keyframes dg-spin {\n    from {\n      transform: rotate(0deg);\n    }\n\n    to {\n      transform: rotate(360deg);\n    }\n  }\n}\n","import { warn } from '../../_dev';\nimport type { DataGridColumn } from './datagrid-model';\n\n// ── Declarative ore-column element ────────────────────────────────────────────\n\n/**\n * Declarative column definition for `<ore-datagrid>`.\n * Use as a child element instead of setting the `columns` prop imperatively.\n *\n * @element ore-column\n *\n * @attr {string} key - Row property key (required)\n * @attr {string} label - Header display label (required)\n * @attr {boolean} sortable - Makes the column sortable\n * @attr {boolean} resizable - Adds a drag handle to resize the column\n * @attr {string} align - Text alignment: 'left' | 'center' | 'right'\n * @attr {string} width - CSS column width (e.g. '12rem')\n * @attr {string} header-label - Accessible label override for the column header\n *\n * @example\n * ```html\n * <ore-datagrid>\n *   <ore-column key=\"name\" label=\"Name\" sortable></ore-column>\n *   <ore-column key=\"email\" label=\"Email\" width=\"20rem\"></ore-column>\n * </ore-datagrid>\n * ```\n */\nif (!customElements.get('ore-column'))\n  customElements.define(\n    'ore-column',\n    class extends HTMLElement {\n      connectedCallback(): void {\n        if (!this.getAttribute('key')) {\n          warn('ore-column: missing required `key` attribute');\n        }\n\n        if (!this.getAttribute('label')) {\n          warn('ore-column: missing required `label` attribute');\n        }\n      }\n    },\n  );\n\nexport const COLUMN_TAG = 'ore-column' as const;\n\n/** Attributes observed by the column MutationObserver in ore-datagrid. */\nexport const COLUMN_OBSERVED_ATTRS = [\n  'key',\n  'label',\n  'sortable',\n  'resizable',\n  'align',\n  'width',\n  'header-label',\n] as const;\n\n/** Parse all `<ore-column>` direct children of `host` into DataGridColumn descriptors. */\nexport function parseColumnChildren(host: HTMLElement): DataGridColumn[] {\n  return Array.from(host.querySelectorAll(':scope > ore-column')).map((el) => ({\n    align: (el.getAttribute('align') as 'left' | 'center' | 'right' | null) ?? undefined,\n    headerLabel: el.getAttribute('header-label') ?? undefined,\n    key: el.getAttribute('key') ?? '',\n    label: el.getAttribute('label') ?? '',\n    resizable: el.hasAttribute('resizable'),\n    sortable: el.hasAttribute('sortable'),\n    width: el.getAttribute('width') ?? undefined,\n  }));\n}\n","import { computed, type Readable, signal, watch } from '@vielzeug/ripple';\n\nexport type SortDirection = 'asc' | 'desc' | 'none';\n\nexport type SortState = {\n  direction: SortDirection;\n  key: string;\n};\n\nexport type DataGridColumn<T = Record<string, unknown>> = {\n  align?: 'left' | 'center' | 'right';\n  cell?: (item: T) => string;\n  headerLabel?: string;\n  key: string;\n  label: string;\n  renderExpanded?: (item: T) => string;\n  resizable?: boolean;\n  sortable?: boolean;\n  sortValue?: (item: T) => number | string;\n  width?: string;\n};\n\nexport type SelectionMode = 'multi' | 'none' | 'single';\n\nexport type FilterOption = {\n  key: string;\n  label: string;\n  operators?: { label: string; value: string }[];\n  options: { label?: string; value: string }[];\n};\n\nexport type FilterOperator = 'contains' | 'equals' | 'gt' | 'lt';\n\nexport type FilterRule = {\n  operator: FilterOperator;\n  values: Set<string>;\n};\n\nexport type DataGridView = {\n  id: string;\n  label: string;\n};\n\nexport type DataGridModelOptions<T = Record<string, unknown>> = {\n  clientSide: Readable<boolean>;\n  columns: Readable<DataGridColumn<T>[]>;\n  filterOptions: Readable<FilterOption[] | undefined>;\n  getRowKey: (item: T) => string;\n  items: Readable<T[]>;\n  onSelectionChange?: (keys: Set<string>) => void;\n  onSortChange?: (sort: SortState) => void;\n  pageSize: Readable<number>;\n  selectionMode: Readable<SelectionMode>;\n  sortMode: Readable<'client' | 'server'>;\n};\n\nexport type DataGridModel<T = Record<string, unknown>> = {\n  activateFilterKey(key: string): void;\n  clearAllFilters(): void;\n  clearSelection(): void;\n  readonly currentPageItems: Readable<T[]>;\n  readonly filterDefs: Readable<FilterOption[]>;\n  readonly filteredRows: Readable<T[]>;\n  readonly filterValues: Readable<Map<string, FilterRule>>;\n  goToPage(index: number): void;\n  readonly hasNextPage: Readable<boolean>;\n  readonly hasPrevPage: Readable<boolean>;\n  readonly hiddenColumns: Readable<Set<string>>;\n  isAllSelected(): boolean;\n  nextPage(): void;\n  readonly pageCount: Readable<number>;\n  readonly pageIndex: Readable<number>;\n  prevPage(): void;\n  removeFilter(key: string): void;\n  resetFilters(): void;\n  resetSearch(): void;\n  readonly searchActive: Readable<boolean>;\n  readonly searchQuery: Readable<string>;\n  selectAll(): void;\n  readonly selectedKeys: Readable<ReadonlySet<string>>;\n  readonly selectedRows: Readable<T[]>;\n  setActiveFilterKeys(keys: string[]): void;\n  setFilter(key: string, values: string[]): void;\n  setFilterOperator(key: string, operator: FilterOperator): void;\n  setSearchQuery(query: string): void;\n  setSelection(keys: Set<string>): void;\n  sortBy(key: string): void;\n  readonly sortState: Readable<SortState>;\n  sortTo(key: string, direction: SortDirection): void;\n  toggleColumnVisibility(key: string): void;\n  toggleRow(key: string): void;\n  toggleSearch(): void;\n  readonly totalItems: Readable<number>;\n  readonly visibleColumns: Readable<DataGridColumn<T>[]>;\n};\n\nconst DEFAULT_OPERATORS: { label: string; value: FilterOperator }[] = [\n  { label: 'Contains', value: 'contains' },\n  { label: 'Equals', value: 'equals' },\n  { label: 'Greater than', value: 'gt' },\n  { label: 'Less than', value: 'lt' },\n];\n\n/**\n * Feature-owned state and transform pipeline for `ore-datagrid`.\n *\n * Rows flow through query, filters, sorting, and pagination in order. Selection\n * and column visibility share the same model so every interactive grid concern\n * has one reactive owner. Source-backed grids retain their server-owned rows by\n * setting `clientSide` to false.\n */\nexport const createDataGridModel = <T extends Record<string, unknown>>(\n  options: DataGridModelOptions<T>,\n): DataGridModel<T> => {\n  const searchQuery = signal('');\n  const searchActive = signal(false);\n  const hiddenColumns = signal(new Set<string>());\n  const activeFilterKeys = signal(new Set<string>());\n  const filterValues = signal(new Map<string, FilterRule>());\n  const sortKey = signal('');\n  const sortDirection = signal<SortDirection>('none');\n  const selectedKeys = signal(new Set<string>());\n  const pageIndex = signal(0);\n\n  const columnKeys = computed(() => new Set(options.columns.value.map((column) => column.key)));\n  const visibleColumns = computed(() => options.columns.value.filter((column) => !hiddenColumns.value.has(column.key)));\n\n  const colOptions = computed(() => {\n    const externalKeys = new Set((options.filterOptions.value ?? []).map((filter) => filter.key));\n    const activeKeys = [...activeFilterKeys.value].filter((key) => !externalKeys.has(key));\n\n    if (!activeKeys.length) return new Map<string, { label: string; value: string }[]>();\n\n    const derived = new Map<string, { label: string; value: string }[]>();\n\n    for (const key of activeKeys) {\n      const seen = new Set<string>();\n      const values: { label: string; value: string }[] = [];\n\n      for (const row of options.items.value) {\n        const value = row[key];\n        const stringValue = value == null ? '' : String(value);\n\n        if (!seen.has(stringValue)) {\n          seen.add(stringValue);\n          values.push({ label: stringValue || '(empty)', value: stringValue });\n        }\n      }\n\n      derived.set(key, values);\n    }\n\n    return derived;\n  });\n\n  const filterDefs = computed<FilterOption[]>(() => {\n    const provided = options.filterOptions.value ?? [];\n    const providedKeys = new Set(provided.map((filter) => filter.key));\n    const derived = [...activeFilterKeys.value]\n      .filter((key) => !providedKeys.has(key))\n      .map((key) => {\n        const column = options.columns.value.find((candidate) => candidate.key === key);\n\n        return {\n          key,\n          label: column?.label ?? key,\n          operators: DEFAULT_OPERATORS,\n          options: colOptions.value.get(key) ?? [],\n        };\n      });\n\n    return [...provided.map((filter) => ({ ...filter, operators: filter.operators ?? DEFAULT_OPERATORS })), ...derived];\n  });\n\n  const searchedRows = computed(() => {\n    const rows = options.items.value;\n\n    if (!options.clientSide.value) return rows;\n\n    const query = searchQuery.value.trim().toLowerCase();\n\n    if (!query) return rows;\n\n    return rows.filter((row) =>\n      Object.values(row).some((value) => value != null && String(value).toLowerCase().includes(query)),\n    );\n  });\n\n  const filteredRows = computed(() => {\n    const rows = searchedRows.value;\n\n    if (!options.clientSide.value || !filterValues.value.size) return rows;\n\n    return rows.filter((row) => {\n      for (const [key, rule] of filterValues.value) {\n        if (!rule.values.size || !columnKeys.value.has(key)) continue;\n\n        const value = row[key];\n        const stringValue = value == null ? '' : String(value);\n\n        if (rule.operator === 'equals' && !rule.values.has(stringValue)) return false;\n\n        if (\n          rule.operator === 'contains' &&\n          ![...rule.values].some((target) => stringValue.toLowerCase().includes(target.toLowerCase()))\n        ) {\n          return false;\n        }\n\n        if (rule.operator === 'gt' || rule.operator === 'lt') {\n          const numericValue = parseFloat(stringValue);\n          const targets = [...rule.values].map(parseFloat).filter((target) => !Number.isNaN(target));\n\n          if (!targets.length) continue;\n\n          if (rule.operator === 'gt' && !targets.some((target) => numericValue > target)) return false;\n\n          if (rule.operator === 'lt' && !targets.some((target) => numericValue < target)) return false;\n        }\n      }\n\n      return true;\n    });\n  });\n\n  const sortState = computed<SortState>(() => ({ direction: sortDirection.value, key: sortKey.value }));\n  const sortedRows = computed(() => {\n    const rows = filteredRows.value;\n\n    if (!options.clientSide.value || options.sortMode.value === 'server') return rows;\n\n    const { direction, key } = sortState.value;\n\n    if (!key || direction === 'none') return rows;\n\n    const column = options.columns.value.find((candidate) => candidate.key === key);\n\n    return rows.slice().sort((a, b) => {\n      const aValue = column?.sortValue ? column.sortValue(a) : (a[key] as number | string);\n      const bValue = column?.sortValue ? column.sortValue(b) : (b[key] as number | string);\n      const comparison =\n        typeof aValue === 'number' && typeof bValue === 'number'\n          ? aValue - bValue\n          : String(aValue ?? '').localeCompare(String(bValue ?? ''));\n\n      return direction === 'asc' ? comparison : -comparison;\n    });\n  });\n\n  const totalItems = computed(() => sortedRows.value.length);\n  const pageCount = computed(() => {\n    const size = options.pageSize.value;\n\n    return Math.ceil(totalItems.value / (size <= 0 ? Number.MAX_SAFE_INTEGER : size));\n  });\n  const safePageIndex = computed(() => (pageCount.value ? Math.min(pageIndex.value, pageCount.value - 1) : -1));\n  const currentPageItems = computed(() => {\n    const size = options.pageSize.value;\n\n    if (size <= 0) return sortedRows.value;\n\n    const start = safePageIndex.value * size;\n\n    return sortedRows.value.slice(start, start + size);\n  });\n  const hasNextPage = computed(() => pageCount.value > 0 && safePageIndex.value < pageCount.value - 1);\n  const hasPrevPage = computed(() => safePageIndex.value > 0);\n  const selectedRows = computed(() =>\n    options.items.value.filter((item) => selectedKeys.value.has(options.getRowKey(item))),\n  );\n\n  watch(\n    columnKeys,\n    (keys) => {\n      const nextActiveKeys = new Set([...activeFilterKeys.value].filter((key) => keys.has(key)));\n      const nextValues = new Map([...filterValues.value].filter(([key]) => keys.has(key)));\n\n      if (nextActiveKeys.size !== activeFilterKeys.value.size) activeFilterKeys.value = nextActiveKeys;\n\n      if (nextValues.size !== filterValues.value.size) filterValues.value = nextValues;\n    },\n    { immediate: false },\n  );\n\n  watch(sortedRows, () => {\n    pageIndex.value = 0;\n  });\n\n  const commitSelection = (next: Set<string>): void => {\n    selectedKeys.value = next;\n    options.onSelectionChange?.(next);\n  };\n\n  const setFilter = (key: string, values: string[]): void => {\n    const next = new Map(filterValues.value);\n\n    if (values.length) {\n      next.set(key, { operator: next.get(key)?.operator ?? 'contains', values: new Set(values) });\n    } else {\n      next.delete(key);\n    }\n\n    filterValues.value = next;\n  };\n\n  const setFilterOperator = (key: string, operator: FilterOperator): void => {\n    const rule = filterValues.value.get(key);\n\n    if (rule) filterValues.value = new Map(filterValues.value).set(key, { ...rule, operator });\n  };\n\n  const sortTo = (key: string, direction: SortDirection): void => {\n    sortKey.value = direction === 'none' ? '' : key;\n    sortDirection.value = direction;\n    pageIndex.value = 0;\n    options.onSortChange?.(sortState.value);\n  };\n\n  return {\n    activateFilterKey: (key) => {\n      if (!activeFilterKeys.value.has(key)) activeFilterKeys.value = new Set([...activeFilterKeys.value, key]);\n    },\n    clearAllFilters: () => {\n      activeFilterKeys.value = new Set();\n      filterValues.value = new Map();\n    },\n    clearSelection: () => commitSelection(new Set()),\n    currentPageItems,\n    filterDefs,\n    filteredRows,\n    filterValues,\n    goToPage: (index) => {\n      if (Number.isFinite(index)) pageIndex.value = Math.max(0, index);\n    },\n    hasNextPage,\n    hasPrevPage,\n    hiddenColumns,\n    isAllSelected: () => {\n      const page = currentPageItems.value;\n\n      return page.length > 0 && page.every((item) => selectedKeys.value.has(options.getRowKey(item)));\n    },\n    nextPage: () => {\n      if (hasNextPage.value) pageIndex.value = safePageIndex.value + 1;\n    },\n    pageCount,\n    pageIndex: safePageIndex,\n    prevPage: () => {\n      if (hasPrevPage.value) pageIndex.value = safePageIndex.value - 1;\n    },\n    removeFilter: (key) => {\n      const nextActiveKeys = new Set(activeFilterKeys.value);\n\n      nextActiveKeys.delete(key);\n      activeFilterKeys.value = nextActiveKeys;\n\n      const nextValues = new Map(filterValues.value);\n\n      nextValues.delete(key);\n      filterValues.value = nextValues;\n    },\n    resetFilters: () => {\n      activeFilterKeys.value = new Set();\n      filterValues.value = new Map();\n    },\n    resetSearch: () => {\n      searchQuery.value = '';\n      searchActive.value = false;\n    },\n    searchActive,\n    searchQuery,\n    selectAll: () => {\n      if (options.selectionMode.value !== 'multi') return;\n\n      const next = new Set(selectedKeys.value);\n\n      if (currentPageItems.value.every((item) => next.has(options.getRowKey(item)))) {\n        for (const item of currentPageItems.value) next.delete(options.getRowKey(item));\n      } else {\n        for (const item of currentPageItems.value) next.add(options.getRowKey(item));\n      }\n\n      commitSelection(next);\n    },\n    selectedKeys: computed(() => new Set(selectedKeys.value)),\n    selectedRows,\n    setActiveFilterKeys: (keys) => {\n      const nextActiveKeys = new Set(keys);\n\n      activeFilterKeys.value = nextActiveKeys;\n      filterValues.value = new Map([...filterValues.value].filter(([key]) => nextActiveKeys.has(key)));\n    },\n    setFilter,\n    setFilterOperator,\n    setSearchQuery: (query) => {\n      searchQuery.value = query;\n    },\n    setSelection: (keys) => commitSelection(new Set(keys)),\n    sortBy: (key) => {\n      const nextDirection =\n        sortKey.value !== key\n          ? 'asc'\n          : sortDirection.value === 'asc'\n            ? 'desc'\n            : sortDirection.value === 'desc'\n              ? 'none'\n              : 'asc';\n\n      sortTo(nextDirection === 'none' ? '' : key, nextDirection);\n    },\n    sortState,\n    sortTo,\n    toggleColumnVisibility: (key) => {\n      const next = new Set(hiddenColumns.value);\n\n      if (next.has(key)) next.delete(key);\n      else next.add(key);\n\n      hiddenColumns.value = next;\n    },\n    toggleRow: (key) => {\n      if (options.selectionMode.value === 'none') return;\n\n      const next = new Set(selectedKeys.value);\n\n      if (next.has(key)) next.delete(key);\n      else {\n        if (options.selectionMode.value === 'single') next.clear();\n\n        next.add(key);\n      }\n\n      commitSelection(next);\n    },\n    toggleSearch: () => {\n      if (searchActive.value) searchQuery.value = '';\n\n      searchActive.value = !searchActive.value;\n    },\n    totalItems,\n    visibleColumns,\n  };\n};\n","import { type Readable, signal } from '@vielzeug/ripple';\n\n// ── Types ──────────────────────────────────────────────────────────────────────\n\n/** Position in the 2D grid model (0-based row/col indices). */\nexport type GridCellPos = { col: number; row: number };\n\n/** Handle returned by createGridNav for programmatic control. */\nexport type GridNavHandle = {\n  /** Current active cell position. Reactive signal. */\n  readonly activeCell: Readable<GridCellPos>;\n  /**\n   * Move focus to a specific cell by position.\n   * Clamps to valid grid bounds; no-ops for invalid positions.\n   */\n  focusCell(pos: GridCellPos): void;\n};\n\n// ── Selector ───────────────────────────────────────────────────────────────────\n\nconst CELL_SELECTOR = '.dg-td, .dg-th';\n\n/** Build a 2D array of focusable cells from the shadow root. One sub-array per <tr>. */\nfunction getGrid(shadow: ShadowRoot): HTMLElement[][] {\n  return Array.from(shadow.querySelectorAll<HTMLElement>('tr'))\n    .map((tr) => Array.from(tr.querySelectorAll<HTMLElement>(CELL_SELECTOR)))\n    .filter((row) => row.length > 0);\n}\n\n// ── Factory ────────────────────────────────────────────────────────────────────\n\n/**\n * Keyboard navigation for the ARIA grid pattern (roving tabindex).\n *\n * - Arrow keys move focus between cells.\n * - Home/End move to the first/last cell in the row.\n * - Ctrl+Home/Ctrl+End move to the first/last cell in the grid.\n * - Only the active cell has `tabindex=\"0\"`; all others have `\"-1\"`.\n *\n * @param table - The `.dg-table` element to attach the keydown listener to.\n * @param shadow - The shadow root containing the grid cells.\n * @returns A handle with `focusCell` and a reactive `activeCell` signal, plus a cleanup fn.\n */\nexport function createGridNav(table: HTMLElement, shadow: ShadowRoot): { cleanup: () => void; handle: GridNavHandle } {\n  const activeCell = signal<GridCellPos>({ col: 0, row: 0 });\n\n  const focusCell = (pos: GridCellPos): void => {\n    const grid = getGrid(shadow);\n    const rowIdx = Math.max(0, Math.min(pos.row, grid.length - 1));\n    const row = grid[rowIdx];\n\n    if (!row) return;\n\n    const colIdx = Math.max(0, Math.min(pos.col, row.length - 1));\n    const target = row[colIdx];\n\n    if (!target) return;\n\n    for (const r of grid) {\n      for (const cell of r) cell.setAttribute('tabindex', '-1');\n    }\n\n    target.setAttribute('tabindex', '0');\n    target.focus();\n    activeCell.value = { col: colIdx, row: rowIdx };\n  };\n\n  const handleArrow = (e: KeyboardEvent): void => {\n    const active = shadow.activeElement as HTMLElement | null;\n\n    if (!active?.matches(CELL_SELECTOR)) return;\n\n    const grid = getGrid(shadow);\n    const rowIdx = grid.findIndex((row) => row.includes(active));\n\n    if (rowIdx === -1) return;\n\n    const colIdx = grid[rowIdx].indexOf(active);\n    const lastRow = grid.length - 1;\n    const lastCol = grid[rowIdx].length - 1;\n\n    let nextRow = rowIdx;\n    let nextCol = colIdx;\n\n    if (e.key === 'ArrowRight') nextCol = colIdx + 1;\n    else if (e.key === 'ArrowLeft') nextCol = colIdx - 1;\n    else if (e.key === 'ArrowDown') nextRow = rowIdx + 1;\n    else if (e.key === 'ArrowUp') nextRow = rowIdx - 1;\n    else if (e.key === 'Home') {\n      nextCol = 0;\n\n      if (e.ctrlKey) nextRow = 0;\n    } else if (e.key === 'End') {\n      nextCol = lastCol;\n\n      if (e.ctrlKey) nextRow = lastRow;\n    } else return;\n\n    e.preventDefault();\n    focusCell({\n      col: Math.max(0, Math.min(nextCol, (grid[Math.max(0, Math.min(nextRow, lastRow))]?.length ?? 1) - 1)),\n      row: Math.max(0, Math.min(nextRow, lastRow)),\n    });\n  };\n\n  table.addEventListener('keydown', handleArrow);\n\n  return {\n    cleanup: () => table.removeEventListener('keydown', handleArrow),\n    handle: { activeCell, focusCell },\n  };\n}\n","import { debounce } from '@vielzeug/arsenal/function';\nimport { define, getHost, html, onCleanup, onMounted, prop, unsafeHtml, useEmit, useSlots } from '@vielzeug/ore';\nimport { computed, signal, watch } from '@vielzeug/ripple';\n\nimport { warn } from '../../_dev';\nimport '../../content/icon/icon';\nimport '../../inputs/button/button';\nimport '../../inputs/checkbox/checkbox';\nimport '../../inputs/combobox/combobox';\nimport '../../inputs/select/select';\nimport '../../overlay/popover/popover';\nimport { disablableBundle, loadableBundle } from '../../shared';\nimport { tableBaseMixin } from '../../styles';\nimport componentStyles from './datagrid.css?inline';\nimport { COLUMN_OBSERVED_ATTRS, parseColumnChildren } from './datagrid-column';\nimport {\n  createDataGridModel,\n  type DataGridColumn,\n  type DataGridModel,\n  type DataGridView,\n  type FilterOperator,\n  type FilterOption,\n  type SelectionMode,\n  type SortDirection,\n  type SortState,\n} from './datagrid-model';\nimport { createGridNav, type GridNavHandle } from './datagrid-nav';\n\ntype SortMode = 'client' | 'server';\n\nexport { COLUMN_TAG } from './datagrid-column';\nexport type { DataGridView, FilterOperator, FilterOption } from './datagrid-model';\n\n// ── Pure module-level helpers ─────────────────────────────────────────────────\n\n/**\n * Returns the Lucide icon name for a column's sort state.\n * Pure function — no closure dependency on the grid model.\n */\nexport function sortIconName(state: SortState, key: string): string {\n  if (state.key !== key || state.direction === 'none') return 'chevrons-up-down';\n\n  return state.direction === 'asc' ? 'chevron-up' : 'chevron-down';\n}\n\n/**\n * Returns the WAI-ARIA `aria-sort` value for a column.\n * Pure function — independently unit-testable.\n */\nexport function ariaSortValue(state: SortState, key: string): 'ascending' | 'descending' | 'none' {\n  if (state.key !== key || state.direction === 'none') return 'none';\n\n  return state.direction === 'asc' ? 'ascending' : 'descending';\n}\n\n// ── Types ──────────────────────────────────────────────────────────────────────\n\nexport type OreDataGridEvents<T = Record<string, unknown>> = {\n  /** Fired when the user cycles the density via the toolbar button. */\n  'density-change': { density: 'compact' | 'cozy' | 'comfortable' };\n  /** Fired when the active page changes. */\n  'page-change': { pageIndex: number; pageSize: number };\n  /** Fired when a row is expanded or collapsed. */\n  'row-expand': { expanded: boolean; key: string };\n  /** Fired when row selection changes. */\n  'selection-change': { keys: string[]; rows: T[] };\n  /** Fired when the sort column or direction changes. */\n  'sort-change': { direction: SortDirection; key: string };\n  /** Fired when the active view tab changes. detail: { id, label } */\n  'view-change': { id: string; label: string };\n};\n\nexport type OreDataGridProps<T = Record<string, unknown>> = {\n  /**\n   * The ID of the currently active view. Must match an `id` in `views`.\n   * When omitted, no view is active (all data shown).\n   * @example `grid.activeView = 'open'`\n   */\n  activeView?: string;\n  /**\n   * Column definitions (imperative API). Takes precedence over `<ore-column>` children.\n   * Passing `[]` explicitly clears declarative children.\n   * Pass `undefined` (or omit) to use `<ore-column>` children instead.\n   * @example\n   * ```js\n   * grid.columns = [\n   *   { key: 'name', label: 'Name', sortable: true },\n   *   { key: 'email', label: 'Email' },\n   * ];\n   * ```\n   */\n  columns?: DataGridColumn<T>[];\n  /** Cell density: `'compact'` | `'cozy'` (default) | `'comfortable'` */\n  density?: 'compact' | 'cozy' | 'comfortable';\n  /** Disable all interaction. */\n  disabled?: boolean;\n  /** Text shown when there are no rows. */\n  emptyText?: string;\n  /**\n   * Enable row expansion. When set, each row gets a toggle button.\n   * Requires at least one column to have a `renderExpanded` function.\n   *\n   * @security The `renderExpanded` callback's returned HTML string is inserted through\n   * Ore's `unsafeHtml()` directive. If data originates from untrusted user input, sanitize\n   * it before returning (for example, with DOMPurify or your CSP-compliant sanitizer).\n   */\n  expandable?: boolean;\n  /**\n   * Pre-defined filter option definitions per column key.\n   * When provided, these options replace the auto-derived ones in the Filter popover.\n   * @example\n   * ```js\n   * grid.filterOptions = [\n   *   { key: 'role', label: 'Role', options: [{ value: 'Admin' }, { value: 'Editor' }] },\n   * ];\n   * ```\n   */\n  filterOptions?: FilterOption[];\n  /** Stretch the grid to fill its container's width. */\n  fullwidth?: boolean;\n  /**\n   * Function that returns a unique string key per row.\n   * Defaults to `(row) => String(row['id'])`.\n   */\n  getRowKey?: (row: T) => string;\n  /** Accessible label for the grid. Recommended for screen readers. */\n  label?: string;\n  /** Show a busy/loading state with reduced opacity. */\n  loading?: boolean;\n  /** Number of rows per page. Defaults to `10`. Set to `0` to disable pagination. */\n  pageSize?: number;\n  /**\n   * Options for the per-page size selector rendered in the footer.\n   * When provided, a `ore-select` is shown next to the pagination controls.\n   * @example `grid.pageSizeOptions = [10, 25, 50, 100]`\n   */\n  pageSizeOptions?: number[];\n  /**\n   * Row data. Pass as a JS property — not serialisable to an HTML attribute.\n   * @example\n   * ```js\n   * grid.rows = [{ id: '1', name: 'Alice', email: 'alice@example.com' }];\n   * ```\n   */\n  rows?: T[];\n  /**\n   * Accessible label for the search toggle button. Supports localization.\n   * Defaults to `'Search'` (open) and `'Close search'` (close).\n   * Pass a tuple `[openLabel, closeLabel]` to override both.\n   * @example `grid.searchLabel = ['Suchen', 'Suche schließen']`\n   */\n  searchLabel?: [open: string, close: string];\n  /** Placeholder text for the inline search input in the controls bar. */\n  searchPlaceholder?: string;\n  /**\n   * Pre-selected row keys. Setting this from outside will update the internal selection.\n   * @example `grid.selectedKeys = ['1', '3']`\n   */\n  selectedKeys?: string[];\n  /** Row selection mode. */\n  selectionMode?: SelectionMode;\n  /**\n   * Whether sorting is client-side (default) or server-side.\n   * When `'server'`, `sort-change` fires but items are not sorted by the control.\n   */\n  sortMode?: SortMode;\n  /**\n   * A reactive data source from `@vielzeug/sourcerer` (or any compatible object).\n   * When set, the source drives row data, pagination, and search — the `rows` prop is ignored.\n   * Client-side sort and filter are bypassed; wire `sort-change` to `source.setQuery()` externally.\n   * @example\n   * ```js\n   * import { createPageSource } from '@vielzeug/sourcerer';\n   * const source = createPageSource({ load: ({ query, signal }) => api.users(query, { signal }) });\n   * grid.source = source;\n   * ```\n   */\n  source?: DataGridSource<T>;\n  /** Apply alternating row backgrounds. */\n  striped?: boolean;\n  /**\n   * Named view definitions for the controls bar tab strip.\n   * Each view is a label displayed as a tab; switching tabs fires `view-change`.\n   * The consumer is responsible for restoring filter/sort state per view.\n   * @example\n   * ```js\n   * grid.views = [\n   *   { id: 'all', label: 'All' },\n   *   { id: 'open', label: 'Open' },\n   *   { id: 'mine', label: 'Mine' },\n   * ];\n   * grid.activeView = 'all';\n   * ```\n   */\n  views?: DataGridView[];\n};\n\n/**\n * An accessible, keyboard-navigable data grid with sorting, pagination,\n * single/multi row selection, inline search, filter, and named views.\n *\n * @element ore-datagrid\n * @element ore-column - Optional declarative column definition child\n *\n * @attr {boolean} disabled - Disable all interaction\n * @attr {boolean} loading - Show busy/loading state\n * @attr {boolean} striped - Apply alternating row backgrounds\n * @attr {boolean} fullwidth - Stretch the grid to fill its container's width\n * @attr {data} search-label - Tuple [openLabel, closeLabel] for the search toggle button\n * @attr {string} search-placeholder - Placeholder for the inline search input\n * @attr {number} page-size - Rows per page (0 = no pagination, default 10)\n * @attr {string} selection-mode - Row selection: 'none' | 'single' | 'multi'\n * @attr {string} sort-mode - Sorting: 'client' (default) | 'server'\n * @attr {string} density - Cell density: compact | cozy (default) | comfortable\n * @attr {string} empty-text - Text shown when there are no rows\n * @attr {string} label - Accessible label for the grid\n * @attr {string} active-view - ID of the currently active view tab\n *\n * @fires selection-change - Fired when row selection changes. detail: { keys: string[], rows: T[] }\n * @fires sort-change - Fired when sort state changes. detail: { key: string, direction: SortDirection }\n * @fires page-change - Fired when page changes. detail: { pageIndex: number, pageSize: number }\n * @fires row-expand - Fired when a row is expanded or collapsed. detail: { expanded: boolean; key: string }\n * @fires view-change - Fired when the active view tab changes. detail: { id: string, label: string }\n *\n * @cssprop --datagrid-bg - Grid background color\n * @cssprop --datagrid-border-color - Grid and cell border color\n * @cssprop --datagrid-radius - Grid border radius\n * @cssprop --datagrid-shadow - Grid box shadow\n * @cssprop --datagrid-header-bg - Column header background\n * @cssprop --datagrid-row-hover-bg - Row hover background\n * @cssprop --datagrid-row-selected-bg - Selected row background\n * @cssprop --datagrid-stripe-bg - Even-row stripe background\n * @cssprop --datagrid-cell-padding-x - Cell horizontal padding\n * @cssprop --datagrid-cell-padding-y - Cell vertical padding\n * @cssprop --datagrid-cell-max-width - Maximum cell content width before truncating\n * @cssprop --datagrid-max-height - Max scrollable height of the table area\n * @cssprop --datagrid-font-size - Base font size for cells\n *\n * @part controls - The controls bar (tabs + action row)\n * @part table - The `<table>` element\n * @part thead - The `<thead>` element\n * @part tbody - The `<tbody>` element\n * @part row - A body `<tr>` element\n * @part cell - A body `<td>` element\n * @part footer - The pagination footer bar\n *\n * @example\n * ```html\n * <ore-datagrid id=\"grid\" label=\"Users\" selection-mode=\"multi\"></ore-datagrid>\n * <script>\n *   const grid = document.getElementById('grid');\n *   grid.columns = [\n *     { key: 'name', label: 'Name', sortable: true },\n *     { key: 'role', label: 'Role' },\n *   ];\n *   grid.rows = [\n *     { id: '1', name: 'Alice', role: 'Admin' },\n *     { id: '2', name: 'Bob',   role: 'Viewer' },\n *   ];\n *   grid.views = [{ id: 'all', label: 'All' }, { id: 'open', label: 'Open' }];\n *   grid.activeView = 'all';\n * </script>\n * ```\n */\n/**\n * Minimal structural interface for a reactive data source accepted by `ore-datagrid`.\n *\n * Any page-shaped `@vielzeug/sourcerer` source satisfies this interface automatically — no direct\n * sourcerer import is required in refine.\n *\n * When `source` is set on the grid:\n * - `rows` prop is ignored; `source.snapshot.data` drives displayed items.\n * - Pagination reads `source.snapshot.pagination`.\n * - Prev/next buttons call `source.page.previous()` / `source.page.next()`.\n * - Search calls `source.setQuery({ search })`.\n * - `source.snapshot.isFetching` contributes to the grid's `aria-busy` state.\n * - Client-side sort and filter are bypassed; wire `sort-change` to `source.setQuery()` externally.\n *\n * @example\n * ```ts\n * import { createPageSource } from '@vielzeug/sourcerer';\n *\n * const source = createPageSource({\n *   load: ({ query, signal }) =>\n *     fetch(`/api/users?page=${query.page}&limit=${query.pageSize}&search=${query.search}`, { signal })\n *       .then(r => r.json()),\n * });\n *\n * const grid = document.querySelector('ore-datagrid');\n * grid.source = source;\n * ```\n */\nexport type DataGridSource<T = Record<string, unknown>> = {\n  readonly page?: {\n    next(): Promise<void> | void;\n    previous(): Promise<void> | void;\n  };\n  setQuery?(changes: { search?: string }): Promise<void> | void;\n  readonly snapshot: {\n    readonly data: readonly T[];\n    readonly error: { message: string } | null;\n    readonly isFetching: boolean;\n    readonly pagination: {\n      readonly count: number;\n      readonly hasNext: boolean;\n      readonly hasPrevious: boolean;\n      readonly index: number;\n      readonly kind: 'page';\n      readonly size: number;\n      readonly total: number;\n    };\n    readonly query: { readonly search?: string };\n  };\n  subscribe(listener: (snapshot: DataGridSource<T>['snapshot']) => void): () => void;\n};\n\nexport const DATAGRID_TAG = 'ore-datagrid' as const;\n\ndefine<OreDataGridProps>(DATAGRID_TAG, {\n  props: {\n    activeView: prop.string(),\n    density: prop.string<'compact' | 'cozy' | 'comfortable'>(),\n    ...disablableBundle,\n    ...loadableBundle,\n    columns: prop.data<DataGridColumn[]>(),\n    emptyText: prop.string('No data'),\n    expandable: prop.bool(false),\n    filterOptions: prop.data<FilterOption[]>(),\n    fullwidth: prop.bool(false),\n    getRowKey: prop.data<(row: Record<string, unknown>) => string>(),\n    label: prop.string(),\n    pageSize: prop.number(10),\n    pageSizeOptions: prop.data<number[]>(),\n    rows: prop.data<Record<string, unknown>[]>(),\n    searchLabel: prop.data<[string, string]>(),\n    searchPlaceholder: prop.string('Search…'),\n    selectedKeys: prop.data<string[]>(),\n    selectionMode: prop.string<SelectionMode>('none'),\n    sortMode: prop.string<SortMode>('client'),\n    source: prop.data<DataGridSource>(),\n    striped: prop.bool(false),\n    views: prop.data<DataGridView[]>(),\n  },\n\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreDataGridEvents>();\n    const slots = useSlots();\n\n    const isDisabled = computed(() => props.disabled.value === true);\n    const selectionMode = computed(() => props.selectionMode.value ?? 'none');\n\n    // ── Row expansion (hoisted — needed by checkOffset + effectiveColCount) ──\n    const expandedKeys = signal(new Set<string>());\n\n    // resolvedColumns is declared further below; this callback is lazy and only\n    // evaluates when .value is first read (after setup completes), so the\n    // forward closure reference is safe at runtime.\n    const hasExpander = computed(\n      () =>\n        props.expandable.value === true && resolvedColumns.value.some((c) => typeof c.renderExpanded === 'function'),\n    );\n\n    const checkOffset = computed(() => (selectionMode.value === 'multi' ? 1 : 0));\n\n    // ── Page size ────────────────────────────────────────────────────────\n    // Signal driven by the `page-size` prop. Stays in sync with prop changes\n    // so consumers can set grid.pageSize = n reactively after mount.\n    // The per-page size selector also writes to this signal directly.\n    const pageSize = signal<number>(props.pageSize.value ?? 10);\n\n    watch(props.pageSize, (n) => {\n      if (n != null) pageSize.value = n;\n    });\n\n    // ── Declarative ore-column children ─────────────────────────────────────\n    // A writable signal holding columns parsed from <ore-column> children.\n    // Updated on mount and whenever children change. The JS `columns` prop\n    // takes precedence when explicitly set (non-empty).\n    const declarativeColumns = signal<DataGridColumn[]>([]);\n\n    onMounted(() => {\n      declarativeColumns.value = parseColumnChildren(el);\n\n      const columnObserver = new MutationObserver(() => {\n        declarativeColumns.value = parseColumnChildren(el);\n      });\n\n      columnObserver.observe(el, {\n        attributeFilter: COLUMN_OBSERVED_ATTRS as unknown as string[],\n        attributes: true,\n        childList: true,\n        subtree: true,\n      });\n\n      return () => columnObserver.disconnect();\n    });\n\n    // Resolved columns: prop wins when explicitly set (even to []); undefined = not set → use declarative children.\n    const resolvedColumns = computed<DataGridColumn[]>(() => {\n      const propCols = props.columns.value;\n\n      return propCols !== undefined ? propCols : declarativeColumns.value;\n    });\n\n    // ── Key resolution ─────────────────────────────────────────────────────────\n    // Reads getRowKey prop dynamically so changes after mount are reflected.\n\n    const resolveKey = (item: Record<string, unknown>): string => {\n      const fn = props.getRowKey.value;\n\n      if (fn) return fn(item);\n\n      const id = item.id;\n\n      if (id == null) {\n        warn('ore-datagrid: row missing `id` — keys will collide. Provide `getRowKey` or add a unique `id` field.');\n\n        return `__missing_${Math.random().toString(36).slice(2)}`;\n      }\n\n      return String(id);\n    };\n\n    // ── Reactive source bridge ────────────────────────────────────────────────\n    // When `source` is provided it drives rows, pagination, and search.\n    // The `rows` prop and client-side filter pipeline are bypassed.\n\n    type SourceMetaState = {\n      error: { message: string } | null;\n      isLoading: boolean;\n      pageCount: number;\n      pageNumber: number;\n      pageSize: number;\n      totalItems: number;\n    };\n\n    const hasSource = computed(() => props.source.value != null);\n    const sourceItems = signal<Record<string, unknown>[]>([]);\n    const sourceMeta = signal<SourceMetaState>({\n      error: null,\n      isLoading: false,\n      pageCount: 1,\n      pageNumber: 1,\n      pageSize: pageSize.value,\n      totalItems: 0,\n    });\n\n    let _sourceUnsub: (() => void) | null = null;\n\n    onCleanup(() => {\n      _sourceUnsub?.();\n      _sourceUnsub = null;\n    });\n\n    watch(\n      props.source,\n      (src) => {\n        _sourceUnsub?.();\n        _sourceUnsub = null;\n\n        if (!src) {\n          sourceItems.value = [];\n          sourceMeta.value = {\n            error: null,\n            isLoading: false,\n            pageCount: 1,\n            pageNumber: 1,\n            pageSize: pageSize.value,\n            totalItems: 0,\n          };\n\n          return;\n        }\n\n        const update = (snapshot: DataGridSource['snapshot'] = src.snapshot): void => {\n          sourceItems.value = snapshot.data as Record<string, unknown>[];\n          sourceMeta.value = {\n            error: snapshot.error,\n            isLoading: snapshot.isFetching,\n            pageCount: snapshot.pagination.count,\n            pageNumber: snapshot.pagination.index,\n            pageSize: snapshot.pagination.size,\n            totalItems: snapshot.pagination.total,\n          };\n        };\n\n        update();\n        _sourceUnsub = src.subscribe(update);\n      },\n      { immediate: true },\n    );\n\n    // ── Feature model ─────────────────────────────────────────────────────────\n    // One model owns every client-side grid transform and interaction state.\n    // Source-backed grids retain source-owned filtering, sorting, and pagination.\n\n    const model: DataGridModel = createDataGridModel({\n      clientSide: computed(() => !hasSource.value),\n      columns: resolvedColumns,\n      filterOptions: props.filterOptions,\n      getRowKey: resolveKey,\n      items: computed<Record<string, unknown>[]>(() =>\n        hasSource.value ? sourceItems.value : (props.rows.value ?? []),\n      ),\n      onSelectionChange: (keys) => {\n        emit('selection-change', { keys: [...keys], rows: model.selectedRows.value });\n      },\n      onSortChange: (sort) => {\n        emit('sort-change', sort);\n      },\n      pageSize: computed(() => (hasSource.value ? 0 : pageSize.value)),\n      selectionMode,\n      sortMode: computed(() => props.sortMode.value ?? 'client'),\n    });\n\n    const debouncedSearch = debounce((query: unknown) => {\n      const source = props.source.value;\n\n      if (source?.setQuery) void source.setQuery({ search: query as string });\n      else model.setSearchQuery(query as string);\n    }, 250);\n\n    // ── Sync external selected-keys prop into the feature model ───────────────\n\n    watch(\n      props.selectedKeys,\n      (keys) => {\n        if (Array.isArray(keys)) model.setSelection(new Set(keys));\n      },\n      { immediate: true },\n    );\n\n    // ── Column resize (F4) ───────────────────────────────────────────────────\n    // Stores user-dragged widths as { key → px } so they survive re-renders.\n    // Only columns with `resizable: true` get a drag handle.\n\n    const colWidths = signal<Record<string, number>>({});\n\n    const createColResizeHandler =\n      (key: string, th: HTMLElement): ((e: PointerEvent) => void) =>\n      (e: PointerEvent): void => {\n        e.preventDefault();\n\n        const startX = e.clientX;\n        const startW = th.getBoundingClientRect().width;\n        // AbortController ensures listeners are removed even if the component\n        // is destroyed mid-drag (e.g. during SPA navigation).\n        const ac = new AbortController();\n        const { signal: sig } = ac;\n\n        window.addEventListener(\n          'pointermove',\n          (mv: PointerEvent) => {\n            colWidths.value = { ...colWidths.value, [key]: Math.max(40, startW + mv.clientX - startX) };\n          },\n          { signal: sig },\n        );\n\n        window.addEventListener('pointerup', () => ac.abort(), { signal: sig });\n      };\n\n    // ── Visible columns (respects hide/show from column menu) ────────────────\n\n    const visibleColumns = model.visibleColumns;\n\n    // ── Cell value helper ────────────────────────────────────────────────────\n\n    const getCellValue = (col: DataGridColumn, item: Record<string, unknown>): string => {\n      if (col.cell) return col.cell(item);\n\n      const v = item[col.key];\n\n      return v == null ? '' : String(v);\n    };\n\n    // ── Pagination handlers ───────────────────────────────────────────────────\n\n    function handlePage(direction: 'next' | 'prev'): void {\n      const src = props.source.value;\n\n      if (src) {\n        if (direction === 'prev') void src.page?.previous();\n        else void src.page?.next();\n\n        return;\n      }\n\n      // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n      direction === 'prev' ? model.prevPage() : model.nextPage();\n      emit('page-change', { pageIndex: model.pageIndex.value, pageSize: pageSize.value });\n    }\n\n    // ── Select-all helpers ────────────────────────────────\n\n    const isSomeSelected = computed(() => {\n      const page = model.currentPageItems.value;\n\n      if (!page.length || model.isAllSelected()) return false;\n\n      return page.some((item) => model.selectedKeys.value.has(resolveKey(item as Record<string, unknown>)));\n    });\n\n    // ── Column count (used in keyboard nav + empty colspan) ───────────────────\n\n    const effectiveColCount = computed(\n      () => visibleColumns.value.length + (selectionMode.value === 'multi' ? 1 : 0) + (hasExpander.value ? 1 : 0),\n    );\n\n    // ── Pagination info text ──────────────────────────────────────────────────\n\n    const paginationEnabled = computed(() => {\n      if (hasSource.value) return sourceMeta.value.pageCount > 1;\n\n      return pageSize.value > 0;\n    });\n\n    const paginationInfo = computed(() => {\n      if (hasSource.value) {\n        const { pageNumber, pageSize: pSize, totalItems } = sourceMeta.value;\n        const safePSize = Math.max(1, pSize);\n\n        if (!paginationEnabled.value) return `${totalItems} row${totalItems !== 1 ? 's' : ''}`;\n\n        if (totalItems === 0) return '0 to 0 of 0';\n\n        const start = (pageNumber - 1) * safePSize + 1;\n        const end = Math.min(start + safePSize - 1, totalItems);\n\n        return `${start} to ${end} of ${totalItems}`;\n      }\n\n      const total = model.totalItems.value;\n\n      if (!paginationEnabled.value) return `${total} row${total !== 1 ? 's' : ''}`;\n\n      if (total === 0) return '0 to 0 of 0';\n\n      const start = model.pageIndex.value * pageSize.value + 1;\n      const end = Math.min(start + pageSize.value - 1, total);\n\n      return `${start} to ${end} of ${total}`;\n    });\n\n    // ── Source-aware loading and pagination helpers ───────────────────────────\n\n    const isLoading = computed(() => props.loading.value === true || (hasSource.value && sourceMeta.value.isLoading));\n\n    const effectiveHasPrev = computed(() =>\n      hasSource.value ? sourceMeta.value.pageNumber > 1 : model.hasPrevPage.value,\n    );\n\n    const effectiveHasNext = computed(() =>\n      hasSource.value ? sourceMeta.value.pageNumber < sourceMeta.value.pageCount : model.hasNextPage.value,\n    );\n\n    const effectivePageLabel = computed(() => {\n      if (hasSource.value) {\n        return sourceMeta.value.totalItems === 0\n          ? '0 / 0'\n          : `${sourceMeta.value.pageNumber} / ${sourceMeta.value.pageCount}`;\n      }\n\n      return `${model.pageIndex.value + 1} / ${model.pageCount.value}`;\n    });\n\n    // ── Density toggle (E5) ──────────────────────────────────────────────────\n    // Local signal so the toolbar button can cycle density without requiring\n    // the consumer to wire up an external prop. Stays in sync with the `density`\n    // prop: prop changes win; button clicks write back to the host attribute so\n    // the CSS layer picks them up immediately.\n\n    type Density = 'compact' | 'cozy' | 'comfortable';\n\n    const DENSITY_CYCLE: Density[] = ['compact', 'cozy', 'comfortable'];\n    const DENSITY_ICONS: Record<Density, string> = {\n      comfortable: 'rows-2',\n      compact: 'rows-4',\n      cozy: 'rows-3',\n    };\n    const DENSITY_LABELS: Record<Density, string> = {\n      comfortable: 'Density: Comfortable',\n      compact: 'Density: Compact',\n      cozy: 'Density: Cozy',\n    };\n\n    const densitySignal = signal<Density>(props.density.value ?? 'cozy');\n\n    watch(props.density, (d) => {\n      if (d) densitySignal.value = d;\n    });\n\n    const cycleDensity = (): void => {\n      const idx = DENSITY_CYCLE.indexOf(densitySignal.value);\n      const next = DENSITY_CYCLE[(idx + 1) % DENSITY_CYCLE.length]!;\n\n      densitySignal.value = next;\n      el.setAttribute('density', next);\n      emit('density-change', { density: next });\n    };\n\n    // ── Filter badge hover state ────────────────────────────────────────────\n    // Drives the dot↔count toggle on the filter toolbar badge: dot at rest,\n    // count on hover/focus so the number is revealed on interaction only.\n    const filterBadgeActive = signal(false);\n\n    // ── Row expansion (toggle handler) ───────────────────────────────────────\n\n    const toggleExpand = (key: string): void => {\n      const next = new Set(expandedKeys.value);\n      const expanded = !next.has(key);\n\n      // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n      expanded ? next.add(key) : next.delete(key);\n      expandedKeys.value = next;\n      emit('row-expand', { expanded, key });\n    };\n\n    // ── Keyboard cell navigation (roving tabindex — extracted to datagrid-nav.ts) ──\n    // navHandle is initialised with a real sentinel signal so the first render\n    // produces correct tabindex values (row=0, col=0 → '0') before onMounted.\n    // onMounted replaces it with the live handle from createGridNav.\n\n    let navHandle: GridNavHandle = {\n      activeCell: signal({ col: 0, row: 0 }),\n      focusCell: () => {},\n    };\n\n    onMounted(() => {\n      const shadow = el.shadowRoot!;\n      const table = shadow.querySelector<HTMLElement>('.dg-table');\n\n      if (!table) return;\n\n      const { cleanup, handle } = createGridNav(table, shadow);\n\n      navHandle = handle;\n\n      return cleanup;\n    });\n\n    // Expose programmatic focusCell API on the host element (F6)\n    (el as HTMLElement & { focusCell: (pos: { col: number; row: number }) => void }).focusCell = (pos) =>\n      navHandle.focusCell(pos);\n\n    // ── Render helpers ────────────────────────────────────────────────────────\n    // Each helper renders one self-contained region, closing only over the\n    // signals it actually needs. This keeps the root template readable.\n\n    const renderViewTabs = (): unknown => {\n      const views = props.views.value ?? [];\n      const activeId = props.activeView.value;\n\n      return html`\n        <div\n          class=\"dg-tabs\"\n          role=\"tablist\"\n          aria-label=\"Views\"\n          aria-controls=\"dg-tabpanel\"\n          @keydown=\"${(e: KeyboardEvent) => {\n            if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(e.key)) return;\n\n            const tabs = Array.from((e.currentTarget as HTMLElement).querySelectorAll('.dg-tab'));\n            const activeIdx = tabs.findIndex((t) => t.classList.contains('dg-tab--active'));\n\n            let nextIdx = activeIdx;\n\n            if (e.key === 'ArrowLeft') nextIdx = Math.max(0, activeIdx - 1);\n            else if (e.key === 'ArrowRight') nextIdx = Math.min(tabs.length - 1, activeIdx + 1);\n            else if (e.key === 'Home') nextIdx = 0;\n            else if (e.key === 'End') nextIdx = tabs.length - 1;\n\n            if (nextIdx !== activeIdx) {\n              e.preventDefault();\n\n              const nextTab = tabs[nextIdx] as HTMLElement;\n\n              nextTab.focus();\n              nextTab.click();\n            }\n          }}\">\n          ${views.map(\n            (view) => html`\n              <ore-button\n                class=\"${() => `dg-tab${activeId === view.id ? ' dg-tab--active' : ''}`}\"\n                role=\"tab\"\n                variant=\"ghost\"\n                rounded=\"full\"\n                size=\"sm\"\n                tabindex=\"${() => (activeId === view.id ? '0' : '-1')}\"\n                aria-selected=\"${() => String(activeId === view.id)}\"\n                aria-controls=\"dg-tabpanel\"\n                @click=\"${() => {\n                  emit('view-change', { id: view.id, label: view.label });\n                }}\">\n                ${view.label}\n              </ore-button>\n            `,\n          )}\n        </div>\n      `;\n    };\n\n    const renderSortPopover = (): unknown => html`\n      <ore-popover class=\"dg-action-popover\" placement=\"bottom-end\" label=\"Sort\" style=\"--popover-min-width:18rem\">\n        <ore-button variant=\"ghost\" size=\"sm\" icon-only label=\"Sort\">\n          <ore-icon name=\"arrow-up-down\" size=\"15\" stroke-width=\"1.75\" aria-hidden=\"true\"></ore-icon>\n        </ore-button>\n        <div slot=\"content\" class=\"dg-pop-sort\">\n          <div class=\"dg-pop-header\">\n            <span class=\"dg-pop-title\">Sort by</span>\n            <ore-button\n              class=\"dg-icon-btn\"\n              variant=\"ghost\"\n              size=\"sm\"\n              icon-only\n              label=\"Clear sort\"\n              disabled=\"${() => model.sortState.value.direction === 'none' || undefined}\"\n              @click=\"${() => model.sortTo('', 'none')}\">\n              <ore-icon name=\"trash-2\" size=\"14\" stroke-width=\"1.75\" aria-hidden=\"true\"></ore-icon>\n            </ore-button>\n          </div>\n          <div class=\"dg-pop-sort-row\">\n            <ore-select\n              class=\"dg-pop-select\"\n              variant=\"flat\"\n              size=\"sm\"\n              rounded=\"lg\"\n              placeholder=\"Property\"\n              fullwidth\n              value=\"${() => model.sortState.value.key}\"\n              options=\"${() => resolvedColumns.value.map((c) => ({ label: c.label, value: c.key }))}\"\n              @change=\"${(e: CustomEvent<{ values: string[] }>) => {\n                const key = e.detail.values[0] ?? '';\n                const dir = model.sortState.value.direction === 'none' ? 'asc' : model.sortState.value.direction;\n\n                model.sortTo(key, dir);\n              }}\"></ore-select>\n            <ore-select\n              class=\"dg-pop-dir-select\"\n              variant=\"flat\"\n              size=\"sm\"\n              rounded=\"lg\"\n              fullwidth\n              disabled=\"${() => !model.sortState.value.key || undefined}\"\n              value=\"${() => (model.sortState.value.direction === 'none' ? 'asc' : model.sortState.value.direction)}\"\n              options=\"${() => [\n                { label: 'A → Z', value: 'asc' },\n                { label: 'Z → A', value: 'desc' },\n              ]}\"\n              @change=\"${(e: CustomEvent<{ values: string[] }>) => {\n                if (model.sortState.value.key) {\n                  model.sortTo(model.sortState.value.key, (e.detail.values[0] ?? 'asc') as 'asc' | 'desc');\n                }\n              }}\"></ore-select>\n          </div>\n        </div>\n      </ore-popover>\n    `;\n\n    const renderFilterPopover = (): unknown => html`\n      <ore-popover\n        class=\"dg-action-popover\"\n        placement=\"bottom-end\"\n        label=\"Filter\"\n        style=\"--popover-min-width:16rem;--popover-max-height:min(90vh,48rem)\">\n        ${() =>\n          model.filterDefs.value.length\n            ? html`\n                <ore-badge\n                  anchor=\"top-end\"\n                  color=\"primary\"\n                  size=\"xs\"\n                  count=\"${() => (filterBadgeActive.value ? model.filterDefs.value.length : undefined)}\"\n                  dot=\"${() => !filterBadgeActive.value || undefined}\"\n                  label=\"${() =>\n                    `${model.filterDefs.value.length} active filter${model.filterDefs.value.length > 1 ? 's' : ''}`}\"\n                  aria-hidden=\"true\"\n                  @mouseenter=\"${() => (filterBadgeActive.value = true)}\"\n                  @mouseleave=\"${() => (filterBadgeActive.value = false)}\"\n                  @focusin=\"${() => (filterBadgeActive.value = true)}\"\n                  @focusout=\"${() => (filterBadgeActive.value = false)}\">\n                  <ore-button slot=\"target\" variant=\"ghost\" size=\"sm\" icon-only label=\"Filter\">\n                    <ore-icon name=\"filter\" size=\"15\" stroke-width=\"1.75\" aria-hidden=\"true\"></ore-icon>\n                  </ore-button>\n                </ore-badge>\n              `\n            : html`\n                <ore-button class=\"dg-icon-btn\" variant=\"ghost\" size=\"sm\" icon-only label=\"Filter\">\n                  <ore-icon name=\"filter\" size=\"15\" stroke-width=\"1.75\" aria-hidden=\"true\"></ore-icon>\n                </ore-button>\n              `}\n        <div slot=\"content\" class=\"dg-pop-filter\">\n          <div class=\"dg-pop-header\">\n            <span class=\"dg-pop-title\">Filter by</span>\n            ${() =>\n              model.filterDefs.value.length\n                ? html`\n                    <ore-button\n                      class=\"dg-icon-btn\"\n                      variant=\"ghost\"\n                      size=\"sm\"\n                      icon-only\n                      label=\"Clear all filters\"\n                      @click=\"${() => model.clearAllFilters()}\">\n                      <ore-icon name=\"trash-2\" size=\"14\" stroke-width=\"1.75\" aria-hidden=\"true\"></ore-icon>\n                    </ore-button>\n                  `\n                : html``}\n          </div>\n\n          <!-- Always-visible field picker: select columns to add filter rules -->\n          <div class=\"dg-pop-filter-fields\">\n            <ore-combobox\n              placeholder=\"Add filter…\"\n              multiple\n              fullwidth\n              autoclose\n              options=\"${() =>\n                resolvedColumns.value.map((col) => ({\n                  label: col.label,\n                  value: col.key,\n                }))}\"\n              value=\"${() => model.filterDefs.value.map((f) => f.key)}\"\n              @change=\"${(e: CustomEvent<{ values: string[] }>) => {\n                model.setActiveFilterKeys(e.detail.values);\n              }}\"></ore-combobox>\n          </div>\n\n          <!-- Active filter rules (appear below the field picker as rules are added) -->\n          <div class=\"dg-pop-filter-rules\" ?hidden=\"${() => !model.filterDefs.value.length}\">\n            ${() =>\n              model.filterDefs.value.map(\n                (f) => html`\n                  <div class=\"dg-pop-filter-rule\">\n                    <div class=\"dg-pop-filter-rule-header\">\n                      <span class=\"dg-pop-filter-field\">${f.label}</span>\n                      <ore-select\n                        class=\"dg-pop-filter-op-select\"\n                        variant=\"ghost\"\n                        size=\"sm\"\n                        fullwidth\n                        value=\"${() => model.filterValues.value.get(f.key)?.operator ?? 'contains'}\"\n                        options=\"${() => f.operators ?? []}\"\n                        @change=\"${(e: CustomEvent<{ values: string[] }>) => {\n                          model.setFilterOperator(f.key, e.detail.values[0] as FilterOperator);\n                        }}\"></ore-select>\n                      <ore-button\n                        class=\"dg-icon-btn\"\n                        variant=\"ghost\"\n                        size=\"sm\"\n                        icon-only\n                        label=\"Remove filter\"\n                        @click=\"${() => model.removeFilter(f.key)}\">\n                        <ore-icon name=\"trash-2\" size=\"13\" stroke-width=\"1.75\" aria-hidden=\"true\"></ore-icon>\n                      </ore-button>\n                    </div>\n                    <ore-combobox\n                      class=\"dg-filter\"\n                      placeholder=\"${() => f.label}\"\n                      options=\"${() => f.options}\"\n                      value=\"${() => [...(model.filterValues.value.get(f.key)?.values ?? [])]}\"\n                      disabled=\"${() => isDisabled.value || undefined}\"\n                      multiple\n                      fullwidth\n                      autoclose\n                      @change=\"${(e: CustomEvent<{ values: string[] }>) => {\n                        model.setFilter(f.key, e.detail.values);\n                      }}\"></ore-combobox>\n                  </div>\n                `,\n              )}\n          </div>\n        </div>\n      </ore-popover>\n    `;\n\n    const renderColumnMenu = (): unknown => html`\n      <ore-popover\n        class=\"dg-action-popover\"\n        placement=\"bottom-end\"\n        label=\"Column options\"\n        style=\"--popover-min-width:18rem\">\n        <ore-button class=\"dg-icon-btn\" variant=\"ghost\" size=\"sm\" icon-only label=\"Column options\">\n          <ore-icon name=\"columns-2\" size=\"15\" stroke-width=\"1.75\" aria-hidden=\"true\"></ore-icon>\n        </ore-button>\n        <div slot=\"content\" class=\"dg-pop-col-list\" role=\"menu\" aria-label=\"Column visibility\">\n          ${() =>\n            resolvedColumns.value.map(\n              (col) => html`\n                <ore-button\n                  class=\"dg-pop-col-item\"\n                  role=\"menuitemcheckbox\"\n                  variant=\"ghost\"\n                  size=\"sm\"\n                  aria-checked=\"${() => String(!model.hiddenColumns.value.has(col.key))}\"\n                  @click=\"${() => model.toggleColumnVisibility(col.key)}\">\n                  <ore-icon\n                    slot=\"prefix\"\n                    name=\"${() => (model.hiddenColumns.value.has(col.key) ? 'eye-off' : 'eye')}\"\n                    size=\"13\"\n                    stroke-width=\"2\"\n                    aria-hidden=\"true\"></ore-icon>\n                  ${col.label}\n                </ore-button>\n              `,\n            )}\n        </div>\n      </ore-popover>\n    `;\n\n    // ── Template ──────────────────────────────────────────────────────────────\n\n    return html`\n      <!-- ── Controls Bar ────────────────────────────────────────────────── -->\n      <div class=\"dg-controls\" part=\"controls\">\n        <!-- Left: view tabs -->\n        ${() => renderViewTabs()}\n\n        <!-- Right: Action bar -->\n        <div class=\"dg-actions\">\n          ${() => renderSortPopover()} ${() => renderFilterPopover()} ${() => renderColumnMenu()}\n\n          <!-- Density toggle -->\n          <ore-button\n            class=\"dg-icon-btn\"\n            variant=\"ghost\"\n            size=\"sm\"\n            icon-only\n            label=\"${() => DENSITY_LABELS[densitySignal.value]}\"\n            @click=\"${cycleDensity}\">\n            <ore-icon\n              name=\"${() => DENSITY_ICONS[densitySignal.value]}\"\n              size=\"15\"\n              stroke-width=\"1.75\"\n              aria-hidden=\"true\"></ore-icon>\n          </ore-button>\n\n          <span class=\"dg-action-divider\" aria-hidden=\"true\" ?hidden=\"${() => !slots.has('actions').value}\"></span>\n\n          <slot name=\"actions\"></slot>\n\n          <!-- Search toggle: rightmost, expands in-place -->\n          <div class=\"${() => `dg-search${model.searchActive.value ? ' dg-search--open' : ''}`}\">\n            ${() =>\n              model.searchActive.value\n                ? html`\n                    <ore-input\n                      class=\"dg-search-input\"\n                      type=\"search\"\n                      variant=\"flat\"\n                      size=\"sm\"\n                      rounded=\"full\"\n                      placeholder=\"${() => props.searchPlaceholder.value ?? 'Search…'}\"\n                      disabled=\"${() => isDisabled.value || undefined}\"\n                      ref=\"${(inputEl: HTMLElement | null) => {\n                        if (inputEl) requestAnimationFrame(() => (inputEl as HTMLElement).focus());\n                      }}\"\n                      @input=\"${(e: CustomEvent<{ value: string }>) => {\n                        debouncedSearch(e.detail.value);\n                      }}\"\n                      @keydown=\"${(e: KeyboardEvent) => {\n                        if (e.key === 'Escape') {\n                          const src = props.source.value;\n\n                          if (src?.setQuery) void src.setQuery({ search: '' });\n\n                          model.toggleSearch();\n                        }\n                      }}\">\n                      <ore-icon slot=\"prefix\" name=\"search\" size=\"13\" stroke-width=\"1.75\" aria-hidden=\"true\"></ore-icon>\n                    </ore-input>\n                  `\n                : html``}\n            <ore-button\n              variant=\"ghost\"\n              size=\"sm\"\n              icon-only\n              label=\"${() => {\n                const [open, close] = props.searchLabel.value ?? ['Search', 'Close search'];\n\n                return model.searchActive.value ? close : open;\n              }}\"\n              @click=\"${() => {\n                const src = props.source.value;\n\n                if (src?.setQuery && model.searchActive.value) void src.setQuery({ search: '' });\n\n                model.toggleSearch();\n              }}\">\n              <ore-icon\n                name=\"${() => (model.searchActive.value ? 'x' : 'search')}\"\n                size=\"15\"\n                stroke-width=\"1.75\"\n                aria-hidden=\"true\"></ore-icon>\n            </ore-button>\n          </div>\n        </div>\n      </div>\n\n      <div id=\"dg-tabpanel\" class=\"dg-scroll\" role=\"tabpanel\" aria-label=\"Data\">\n        <div class=\"dg-loading-overlay\">\n          <ore-icon name=\"loader-2\" size=\"24\" class=\"dg-spin\" aria-hidden=\"true\"></ore-icon>\n        </div>\n        <table\n          class=\"dg-table\"\n          part=\"table\"\n          role=\"grid\"\n          aria-label=\"${() => props.label.value ?? undefined}\"\n          aria-busy=\"${() => (isLoading.value ? 'true' : null)}\"\n          aria-disabled=\"${() => (isDisabled.value ? 'true' : null)}\">\n          <!-- Head -->\n          <thead class=\"dg-head\" part=\"thead\">\n            <tr role=\"row\">\n              ${() =>\n                selectionMode.value === 'multi'\n                  ? html`\n                      <th\n                        class=\"dg-th dg-th-check\"\n                        role=\"columnheader\"\n                        scope=\"col\"\n                        tabindex=\"${() =>\n                          navHandle.activeCell.value.row === 0 &&\n                          navHandle.activeCell.value.col === 0 &&\n                          checkOffset.value >= 1\n                            ? '0'\n                            : '-1'}\">\n                        <ore-checkbox\n                          class=\"dg-check\"\n                          checked=\"${() => model.isAllSelected()}\"\n                          indeterminate=\"${isSomeSelected}\"\n                          ?disabled=\"${isDisabled}\"\n                          aria-label=\"Select all rows on this page\"\n                          @change=\"${() => {\n                            if (!isDisabled.value) model.selectAll();\n                          }}\"></ore-checkbox>\n                      </th>\n                    `\n                  : html``}\n              ${() =>\n                visibleColumns.value.map((col: DataGridColumn, colIdx: number) => {\n                  const isLast = colIdx === visibleColumns.value.length - 1;\n\n                  return html`\n                    <th\n                      class=\"${`dg-th${isLast && hasExpander.value ? ' dg-th-last' : ''}`}\"\n                      role=\"columnheader\"\n                      scope=\"col\"\n                      tabindex=\"${() => {\n                        const ac = navHandle.activeCell.value;\n\n                        return ac.row === 0 && ac.col === colIdx + checkOffset.value ? '0' : '-1';\n                      }}\"\n                      data-align=\"${col.align ?? 'left'}\"\n                      aria-sort=\"${() => (col.sortable ? ariaSortValue(model.sortState.value, col.key) : undefined)}\"\n                      aria-label=\"${col.sortable ? undefined : (col.headerLabel ?? col.label)}\"\n                      style=\"${() => {\n                        const dragged = colWidths.value[col.key];\n\n                        return dragged ? `width:${dragged}px` : col.width ? `width:${col.width}` : '';\n                      }}\">\n                      <div class=\"dg-th-inner\">\n                        ${() =>\n                          col.sortable\n                            ? html`\n                                <ore-button\n                                  class=\"dg-sort-btn\"\n                                  variant=\"text\"\n                                  size=\"sm\"\n                                  fullwidth\n                                  label=\"${col.headerLabel ?? col.label}\"\n                                  disabled=\"${() => isDisabled.value || undefined}\"\n                                  @click=\"${() => {\n                                    if (!isDisabled.value) model.sortBy(col.key);\n                                  }}\">\n                                  ${col.label}\n                                  <ore-icon\n                                    slot=\"suffix\"\n                                    class=\"dg-sort-icon\"\n                                    name=\"${() => sortIconName(model.sortState.value, col.key)}\"\n                                    size=\"14\"\n                                    stroke-width=\"2\"></ore-icon>\n                                </ore-button>\n                              `\n                            : col.label}\n                        ${\n                          col.resizable\n                            ? html`\n                                <span\n                                  class=\"dg-col-resize\"\n                                  aria-hidden=\"true\"\n                                  ref=\"${(handleEl: HTMLElement | null) => {\n                                    if (!handleEl) return;\n\n                                    const th = handleEl.closest('th') as HTMLElement | null;\n\n                                    if (th)\n                                      handleEl.addEventListener('pointerdown', createColResizeHandler(col.key, th));\n                                  }}\"></span>\n                              `\n                            : html``\n                        }\n                      </div>\n                    </th>\n                  `;\n                })}\n              ${() =>\n                hasExpander.value\n                  ? html`\n                      <th\n                        class=\"dg-th dg-th-expand\"\n                        role=\"columnheader\"\n                        scope=\"col\"\n                        aria-label=\"Row details\"\n                        tabindex=\"-1\"></th>\n                    `\n                  : html``}\n            </tr>\n          </thead>\n\n          <!-- Body -->\n          <tbody class=\"dg-body\" part=\"tbody\">\n            ${() =>\n              model.currentPageItems.value.length === 0\n                ? html`\n                    <tr role=\"row\">\n                      <td class=\"dg-empty\" role=\"gridcell\" colspan=\"${() => String(effectiveColCount.value)}\">\n                        <div class=\"dg-empty-content\">\n                          ${() => props.emptyText.value ?? 'No data'}\n                          ${() =>\n                            model.searchQuery.value || model.filterValues.value.size\n                              ? html`\n                                  <div class=\"dg-empty-actions\">\n                                    <ore-button\n                                      variant=\"text\"\n                                      size=\"sm\"\n                                      @click=\"${() => {\n                                        model.resetSearch();\n                                        model.resetFilters();\n                                      }}\">\n                                      Clear all filters & search\n                                    </ore-button>\n                                  </div>\n                                `\n                              : html``}\n                        </div>\n                      </td>\n                    </tr>\n                  `\n                : model.currentPageItems.value.map((item: Record<string, unknown>, itemIdx: number) => {\n                    const key = resolveKey(item);\n                    const isSelectable = selectionMode.value !== 'none' && !isDisabled.value;\n                    const rowIdx = itemIdx + 1;\n\n                    return html`\n                      <tr\n                        class=\"dg-tr\"\n                        part=\"row\"\n                        role=\"row\"\n                        aria-selected=\"${() =>\n                          selectionMode.value !== 'none' ? String(model.selectedKeys.value.has(key)) : null}\"\n                        aria-expanded=\"${() => (hasExpander.value ? String(expandedKeys.value.has(key)) : null)}\"\n                        ?data-selectable=\"${isSelectable}\"\n                        ?data-disabled=\"${isDisabled}\"\n                        @click=\"${() => {\n                          if (isSelectable && selectionMode.value === 'single') model.toggleRow(key);\n                        }}\"\n                        @keydown=\"${(e: KeyboardEvent) => {\n                          if (\n                            (e.key === 'Enter' || e.key === ' ') &&\n                            isSelectable &&\n                            selectionMode.value === 'single'\n                          ) {\n                            e.preventDefault();\n                            model.toggleRow(key);\n                          }\n                        }}\">\n                        ${() =>\n                          selectionMode.value === 'multi'\n                            ? html`\n                                <td\n                                  class=\"dg-td dg-td-check\"\n                                  role=\"gridcell\"\n                                  tabindex=\"${() => {\n                                    const ac = navHandle.activeCell.value;\n\n                                    return ac.row === rowIdx && ac.col === 0 ? '0' : '-1';\n                                  }}\"\n                                  @keydown=\"${(e: KeyboardEvent) => {\n                                    if (e.key === 'Enter' || e.key === ' ') {\n                                      e.preventDefault();\n\n                                      if (!isDisabled.value) model.toggleRow(key);\n                                    }\n                                  }}\">\n                                  <ore-checkbox\n                                    class=\"dg-check\"\n                                    checked=\"${() => model.selectedKeys.value.has(key)}\"\n                                    ?disabled=\"${isDisabled}\"\n                                    aria-label=\"Select row\"\n                                    tabindex=\"-1\"\n                                    @click=\"${(e: MouseEvent) => e.stopPropagation()}\"\n                                    @change=\"${() => {\n                                      if (!isDisabled.value) model.toggleRow(key);\n                                    }}\"></ore-checkbox>\n                                </td>\n                              `\n                            : html``}\n                        ${visibleColumns.value.map((col: DataGridColumn, colIdx: number) => {\n                          const value = getCellValue(col, item as Record<string, unknown>);\n\n                          const isLastCol = colIdx === visibleColumns.value.length - 1;\n\n                          return html`\n                            <td\n                              class=\"${`dg-td${isLastCol && hasExpander.value ? ' dg-td-last' : ''}`}\"\n                              part=\"cell\"\n                              role=\"gridcell\"\n                              data-align=\"${col.align ?? 'left'}\"\n                              tabindex=\"${() => {\n                                const ac = navHandle.activeCell.value;\n\n                                return ac.row === rowIdx && ac.col === colIdx + checkOffset.value ? '0' : '-1';\n                              }}\"\n                              title=\"${value}\">\n                              ${value}\n                            </td>\n                          `;\n                        })}\n                        ${() =>\n                          hasExpander.value\n                            ? html`\n                                <td\n                                  class=\"dg-td dg-td-expand\"\n                                  role=\"gridcell\"\n                                  tabindex=\"${() => {\n                                    const ac = navHandle.activeCell.value;\n\n                                    return ac.row === rowIdx && ac.col === effectiveColCount.value - 1 ? '0' : '-1';\n                                  }}\"\n                                  @keydown=\"${(e: KeyboardEvent) => {\n                                    if (e.key === 'Enter' || e.key === ' ') {\n                                      e.preventDefault();\n\n                                      if (!isDisabled.value) toggleExpand(key);\n                                    }\n                                  }}\">\n                                  <ore-button\n                                    class=\"dg-expand-btn\"\n                                    variant=\"ghost\"\n                                    size=\"sm\"\n                                    icon-only\n                                    tabindex=\"-1\"\n                                    label=\"${() => (expandedKeys.value.has(key) ? 'Collapse row' : 'Expand row')}\"\n                                    aria-expanded=\"${() => String(expandedKeys.value.has(key))}\"\n                                    disabled=\"${() => isDisabled.value || undefined}\"\n                                    @click=\"${(e: MouseEvent) => {\n                                      e.stopPropagation();\n\n                                      if (!isDisabled.value) toggleExpand(key);\n                                    }}\">\n                                    <ore-icon\n                                      name=\"${() => (expandedKeys.value.has(key) ? 'chevron-up' : 'chevron-down')}\"\n                                      size=\"14\"\n                                      stroke-width=\"2\"\n                                      aria-hidden=\"true\"></ore-icon>\n                                  </ore-button>\n                                </td>\n                              `\n                            : html``}\n                      </tr>\n                      ${() =>\n                        hasExpander.value && expandedKeys.value.has(key)\n                          ? html`\n                              <tr class=\"dg-tr-expanded\" role=\"row\">\n                                <td\n                                  class=\"dg-td-expanded\"\n                                  role=\"gridcell\"\n                                  colspan=\"${() => String(effectiveColCount.value)}\">\n                                  ${\n                                    // This deliberately marks the HTML sink. Callers must\n                                    // sanitize untrusted content inside renderExpanded().\n                                    unsafeHtml(() => {\n                                      const renderer = resolvedColumns.value.find(\n                                        (c) => typeof c.renderExpanded === 'function',\n                                      );\n\n                                      return renderer?.renderExpanded?.(item) ?? '';\n                                    })\n                                  }\n                                </td>\n                              </tr>\n                            `\n                          : html``}\n                    `;\n                  })}\n          </tbody>\n        </table>\n      </div>\n\n      <!-- Footer / Pagination -->\n      ${() =>\n        paginationEnabled.value\n          ? html`\n              <div class=\"dg-footer\" part=\"footer\" role=\"navigation\" aria-label=\"Pagination\">\n                ${() =>\n                  !(props.pageSizeOptions.value ?? []).length\n                    ? html`\n                        <span class=\"dg-footer-info\" dir=\"ltr\" aria-live=\"polite\" aria-atomic=\"true\">\n                          ${paginationInfo}\n                        </span>\n                      `\n                    : html``}\n                <div class=\"dg-footer-end\">\n                  ${() => {\n                    const opts = props.pageSizeOptions.value ?? [];\n\n                    return opts.length\n                      ? html`\n                          <div class=\"dg-page-size-wrap\">\n                            <ore-select\n                              class=\"dg-page-size-select\"\n                              fullwidth\n                              aria-label=\"Rows per page\"\n                              value=\"${() => String(pageSize.value)}\"\n                              options=\"${() => opts.map((n) => ({ label: String(n), value: String(n) }))}\"\n                              disabled=\"${() => isDisabled.value || undefined}\"\n                              @change=\"${(e: CustomEvent<{ values: string[] }>) => {\n                                const n = parseInt(e.detail.values[0], 10);\n\n                                if (!Number.isNaN(n)) {\n                                  pageSize.value = n;\n                                  model.goToPage(0);\n                                  emit('page-change', { pageIndex: 0, pageSize: n });\n                                }\n                              }}\"></ore-select>\n                          </div>\n                        `\n                      : html``;\n                  }}\n                  <div class=\"dg-pagination\" role=\"group\" aria-label=\"Page navigation\">\n                    <ore-button\n                      class=\"dg-page-btn\"\n                      variant=\"ghost\"\n                      size=\"sm\"\n                      icon-only\n                      label=\"Previous page\"\n                      disabled=\"${() => !effectiveHasPrev.value || isDisabled.value}\"\n                      @click=\"${() => handlePage('prev')}\">\n                      <ore-icon name=\"chevron-left\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n                    </ore-button>\n                    <span\n                      class=\"dg-page-label\"\n                      dir=\"ltr\"\n                      aria-current=\"page\"\n                      role=\"status\"\n                      aria-live=\"polite\"\n                      aria-atomic=\"true\">\n                      ${() => effectivePageLabel.value}\n                    </span>\n                    <ore-button\n                      class=\"dg-page-btn\"\n                      variant=\"ghost\"\n                      size=\"sm\"\n                      icon-only\n                      label=\"Next page\"\n                      disabled=\"${() => !effectiveHasNext.value || isDisabled.value}\"\n                      @click=\"${() => handlePage('next')}\">\n                      <ore-icon name=\"chevron-right\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n                    </ore-button>\n                  </div>\n                </div>\n              </div>\n            `\n          : html``}\n    `;\n  },\n\n  shadow: { delegatesFocus: true },\n  styles: [tableBaseMixin('datagrid'), componentStyles],\n});\n","@layer refine.base {\n  :host {\n    --_day-selected-bg: var(--date-picker-day-selected-bg, var(--_theme-focus));\n    --_day-today-color: var(--date-picker-day-today-color, var(--_theme-focus));\n    --_day-outside-opacity: var(--date-picker-day-outside-opacity, 0.35);\n    --_bg: var(--date-picker-bg, var(--color-canvas));\n    --_border-color: var(--date-picker-border-color, var(--color-contrast-200));\n    --_radius: var(--date-picker-radius, var(--rounded-xl));\n\n    display: inline-block;\n    min-width: var(--date-picker-min-width, 12rem);\n  }\n\n  :host([fullwidth]) {\n    display: block;\n  }\n\n  :host([color='secondary']) {\n    --_day-selected-bg: var(--date-picker-day-selected-bg, var(--_theme-base));\n    --_day-today-color: var(--date-picker-day-today-color, var(--_theme-base));\n  }\n\n  /* Make the trigger look like a button — ore-input is readonly so pointer changes to text by\n     default. `width: 100%` matters just as much — see ore-select's own `.trigger` for why:\n     `:host` is `display: inline-block`, which never stretches its own children to fill its own\n     box the way a flex/grid container with `stretch` alignment would. */\n  .trigger {\n    width: 100%;\n    cursor: pointer;\n  }\n\n  .trigger::part(input) {\n    cursor: pointer;\n    caret-color: transparent;\n    user-select: none;\n  }\n\n  /* ── Calendar popup ──────────────────────────────────────────────────────── */\n\n  /* `fixed` (not `absolute`) — positioned via JS-computed top/left (see the positioner in\n     date-picker.ts), same as ore-select's own `.dropdown`. Laid out relative to the viewport,\n     so it never affects any ancestor's box size or scrollable-overflow area — `absolute`\n     positioned relative to the host did, once the host sat near a scroll/clip ancestor's edge. */\n  .calendar {\n    position: fixed;\n    inset: 0 auto auto 0;\n    z-index: var(--z-dropdown, 8000);\n    display: flex;\n    flex-direction: column;\n    gap: var(--size-2);\n    min-width: 18rem;\n    padding: var(--size-3);\n    pointer-events: none;\n    background: var(--_bg);\n    border: var(--border) solid var(--_border-color);\n    border-radius: var(--_radius);\n    box-shadow: var(--date-picker-shadow, var(--shadow-lg));\n\n    /* Hidden by default */\n    opacity: 0;\n    backdrop-filter: blur(var(--blur-sm));\n    transform: translateY(var(--overlay-enter-translate-y));\n    transition: var(\n      --_motion-transition,\n      opacity var(--transition-fast),\n      transform var(--transition-fast),\n      display var(--transition-fast) allow-discrete\n    );\n  }\n\n  .calendar[data-open] {\n    pointer-events: auto;\n    opacity: 1;\n    transform: translateY(0);\n\n    @starting-style {\n      opacity: 0;\n      transform: translateY(var(--overlay-enter-translate-y));\n    }\n  }\n\n  /* ── Calendar header ─────────────────────────────────────────────────────── */\n\n  .cal-header {\n    display: flex;\n    gap: var(--size-1);\n    align-items: center;\n    justify-content: space-between;\n    padding-block-end: var(--size-2);\n    border-block-end: var(--border) solid var(--_border-color);\n  }\n\n  .nav-btn {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: var(--size-8);\n    height: var(--size-8);\n    padding: 0;\n    color: var(--color-contrast-600);\n    cursor: pointer;\n    outline: none;\n    background: transparent;\n    border: none;\n    border-radius: var(--rounded-md);\n    transition:\n      background var(--transition-fast),\n      color var(--transition-fast);\n  }\n\n  .nav-btn:hover {\n    color: var(--color-contrast-900);\n    background: var(--color-contrast-300);\n  }\n\n  .nav-btn:focus-visible {\n    box-shadow: 0 0 0 2px var(--_day-selected-bg);\n  }\n\n  .cal-label-btn {\n    flex: 1;\n    padding: var(--size-1) var(--size-2);\n    font-size: var(--text-sm);\n    font-weight: var(--font-semibold);\n    color: var(--color-contrast-900);\n    text-align: center;\n    cursor: pointer;\n    outline: none;\n    background: transparent;\n    border: none;\n    border-radius: var(--rounded-md);\n    transition: background var(--transition-fast);\n  }\n\n  .cal-label-btn:hover {\n    background: var(--color-contrast-300);\n  }\n\n  .cal-label-btn:focus-visible {\n    box-shadow: 0 0 0 2px var(--_day-selected-bg);\n  }\n\n  .cal-label-month,\n  .cal-label-year {\n    display: inline-block;\n  }\n\n  .cal-label-sep {\n    display: inline-block;\n    padding-inline: var(--size-1);\n    font-weight: var(--font-normal);\n    color: var(--color-contrast-400);\n  }\n\n  /* ── Day grid ────────────────────────────────────────────────────────────── */\n\n  /* Prevent display:flex from overriding the [hidden] attribute */\n  [hidden] {\n    display: none;\n  }\n\n  .cal-grid {\n    display: flex;\n    flex-direction: column;\n    gap: var(--size-0-5);\n  }\n\n  .cal-grid-days {\n    display: grid;\n    grid-template-columns: repeat(7, 1fr);\n    gap: var(--size-0-5);\n    min-height: calc(7 * var(--size-10) + 6 * var(--size-0-5));\n  }\n\n  /* role=\"row\" wrappers exist for ARIA grid structure only — `display: contents`\n     removes them from layout so their children still participate directly in the\n     parent's CSS grid tracks. */\n  .cal-grid [role='row'] {\n    display: contents;\n  }\n\n  .cal-cell {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: var(--text-sm);\n    cursor: pointer;\n    outline: none;\n    border-radius: var(--rounded-md);\n    transition:\n      background var(--transition-fast),\n      color var(--transition-fast);\n  }\n\n  .cal-cell-head {\n    height: var(--size-8);\n    font-size: var(--text-xs);\n    font-weight: var(--font-medium);\n    color: var(--color-contrast-500);\n    cursor: default;\n  }\n\n  .cal-cell-day {\n    height: var(--size-8);\n    color: var(--color-contrast-800);\n  }\n\n  .cal-cell-day:hover:not([data-disabled]) {\n    color: var(--color-contrast-900);\n    background: color-mix(in oklch, var(--_day-selected-bg) 15%, transparent);\n  }\n\n  .cal-cell-day:focus-visible {\n    box-shadow: 0 0 0 2px var(--_day-selected-bg);\n  }\n\n  .cal-cell-day[data-today] {\n    font-weight: var(--font-semibold);\n    color: var(--_day-today-color);\n  }\n\n  .cal-cell-day[data-selected] {\n    font-weight: var(--font-semibold);\n    color: var(--color-white, #fff);\n    background: var(--_day-selected-bg);\n  }\n\n  .cal-cell-day[data-outside] {\n    opacity: var(--_day-outside-opacity);\n  }\n\n  .cal-cell-day[data-disabled] {\n    pointer-events: none;\n    cursor: not-allowed;\n    opacity: 0.3;\n  }\n\n  /* ── Month / Year grids ──────────────────────────────────────────────────── */\n\n  .cal-grid-months,\n  .cal-grid-years {\n    /* 4-column grid — same width as cal-grid-days, natural height. */\n    display: grid;\n    grid-template-columns: repeat(4, minmax(0, 1fr));\n    gap: var(--size-1);\n  }\n\n  .cal-cell-month,\n  .cal-cell-year {\n    height: var(--size-10);\n    font-size: var(--text-sm);\n    color: var(--color-contrast-800);\n    cursor: pointer;\n    border-radius: var(--rounded-md);\n  }\n\n  .cal-cell-month:hover:not([data-disabled]),\n  .cal-cell-year:hover:not([data-disabled]) {\n    background: color-mix(in oklch, var(--_day-selected-bg) 15%, transparent);\n  }\n\n  .cal-cell-month:focus-visible,\n  .cal-cell-year:focus-visible {\n    box-shadow: 0 0 0 2px var(--_day-selected-bg);\n  }\n\n  .cal-cell-month[data-selected],\n  .cal-cell-year[data-selected] {\n    font-weight: var(--font-semibold);\n    color: var(--color-white, #fff);\n    background: var(--_day-selected-bg);\n  }\n\n  .cal-cell-month[data-disabled],\n  .cal-cell-year[data-disabled] {\n    pointer-events: none;\n    cursor: not-allowed;\n    opacity: 0.3;\n  }\n\n  /* ── Reduced motion ──────────────────────────────────────────────────────── */\n\n  @media (prefers-reduced-motion: reduce) {\n    .field,\n    .nav-btn,\n    .cal-label-btn,\n    .cal-cell {\n      transition: none;\n    }\n  }\n}\n","import { bind, define, getHost, html, onMounted, prop, ref, useField } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { format, Temporal } from '@vielzeug/tempo';\nimport {\n  createDatePickerControl,\n  createDropdownPositioner,\n  type DatePickerView,\n  formatDisplayDate,\n  parseIso,\n  toIsoString,\n} from '../../core';\nimport type { ComponentSize, RoundedSize, ThemeColor, VisualVariant } from '../../shared';\nimport '../../content/icon/icon';\nimport '../input/input';\nimport { disablableBundle, roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, reducedMotionMixin } from '../../styles';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport componentStyles from './date-picker.css?inline';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type OreDatePickerEvents = {\n  change: Event;\n  input: Event;\n};\n\nexport type OreDatePickerProps = {\n  /** Theme color */\n  color?: ThemeColor;\n  /** Disable the picker */\n  disabled?: boolean;\n  /** Validation error message */\n  error?: string;\n  /** Expand to container width */\n  fullwidth?: boolean;\n  /** Helper text below the field */\n  helper?: string;\n  /** Visible label */\n  label?: string;\n  /** Label placement */\n  'label-placement'?: 'inset' | 'outside';\n  /** Locale for day/month names (default: browser locale) */\n  locale?: string;\n  /** Latest selectable date in ISO 8601 format (yyyy-MM-dd) */\n  max?: string;\n  /** Earliest selectable date in ISO 8601 format (yyyy-MM-dd) */\n  min?: string;\n  /** Form field name */\n  name?: string;\n  /** Placeholder shown in the text trigger */\n  placeholder?: string;\n  /** Mark field as required */\n  required?: boolean;\n  /** Border radius */\n  rounded?: RoundedSize;\n  /** Component size */\n  size?: ComponentSize;\n  /**\n   * Shows an inline green check icon inside the field to confirm the value has\n   * passed validation. Ignored while `error` is set — an error always wins.\n   */\n  success?: boolean;\n  /**\n   * Selected date in ISO 8601 format (yyyy-MM-dd).\n   * @example '2025-06-15'\n   */\n  value?: string;\n  /** Visual variant */\n  variant?: Exclude<VisualVariant, 'text' | 'frost'>;\n  /**\n   * Day-of-week indices to disable (0 = Sunday … 6 = Saturday).\n   * Pass as a JSON array attribute or a JS property.\n   * @example\n   * ```html\n   * <ore-date-picker weekend-days=\"[0,6]\"></ore-date-picker>\n   * ```\n   */\n  'weekend-days'?: number[];\n};\n\n/**\n * An accessible, keyboard-navigable date picker with an inline calendar popup.\n * Supports min/max bounds, disabled weekend days, and form association.\n *\n * @element ore-date-picker\n *\n * @attr {string} value - Selected date in ISO 8601 format (yyyy-MM-dd)\n * @attr {string} min - Minimum selectable date (yyyy-MM-dd)\n * @attr {string} max - Maximum selectable date (yyyy-MM-dd)\n * @attr {string} label - Label text\n * @attr {string} label-placement - 'inset' | 'outside'\n * @attr {string} placeholder - Trigger placeholder\n * @attr {boolean} disabled - Disable the picker\n * @attr {boolean} required - Required field\n * @attr {string} name - Form field name\n * @attr {string} error - Error message\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {string} helper - Helper text\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {string} locale - BCP 47 locale string\n * @attr {string} weekend-days - Comma-separated day indices to disable\n *\n * @fires input - Fired when a date is selected.\n * @fires change - Fired when a date is selected.\n *\n * @slot label - Custom label for the trigger field\n * @slot prefix - Content before the trigger text (e.g. icon)\n * @slot helper - Custom helper text\n * @slot error - Custom error content\n *\n * @cssprop --date-picker-bg - Calendar background\n * @cssprop --date-picker-border-color - Calendar border color\n * @cssprop --date-picker-radius - Calendar border radius\n * @cssprop --date-picker-day-selected-bg - Background of selected day\n * @cssprop --date-picker-day-today-color - Color of today's date number\n * @cssprop --date-picker-day-outside-opacity - Opacity of days outside visible month\n *\n * @part field - The trigger button/field\n * @part calendar - The floating calendar panel\n * @part header - Calendar header (nav + label)\n * @part grid - Day grid\n * @part day - Individual day cell\n *\n * @example\n * ```html\n * <!-- Single date with constraints -->\n * <ore-date-picker label=\"Appointment date\" name=\"date\" min=\"2025-01-01\" max=\"2025-12-31\" color=\"primary\"></ore-date-picker>\n *\n *\n * <!-- Outside label, bordered variant -->\n * <ore-date-picker label=\"Start date\" label-placement=\"outside\" variant=\"bordered\"></ore-date-picker>\n * ```\n */\nexport const DATE_PICKER_TAG = 'ore-date-picker' as const;\n\ndefine<OreDatePickerProps>(DATE_PICKER_TAG, {\n  formAssociated: true,\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...disablableBundle,\n    ...roundableBundle,\n    error: prop.string(),\n    fullwidth: prop.bool(false),\n    helper: prop.string(),\n    label: prop.string(),\n    'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n    locale: prop.string(),\n    max: prop.string(),\n    min: prop.string(),\n    name: prop.string(),\n    placeholder: prop.string(),\n    required: prop.bool(false),\n    success: prop.bool(false),\n    value: prop.string(),\n    variant: prop.string<'flat' | 'solid' | 'bordered' | 'outline' | 'ghost'>(),\n    'weekend-days': prop.json([] as number[]),\n  },\n\n  setup(props) {\n    const el = getHost();\n\n    // ── Signals ─────────────────────────────────────────────────────────────\n\n    const isOpen = signal(false);\n\n    // ── Selected date: local-override pattern ──────────────────────────────\n    // localSelection holds a user-initiated pick (or undefined = no override).\n    // selectedDate falls back to the value prop reactively — no setInterval needed.\n\n    const localSelection = signal<Temporal.PlainDate | null | undefined>(undefined);\n\n    const selectedDate = computed(() =>\n      localSelection.value !== undefined ? localSelection.value : parseIso(props.value.value),\n    );\n\n    defineFieldValue(\n      el,\n      () => toIsoString(selectedDate.value) ?? '',\n      (value) => {\n        localSelection.value = parseIso(value);\n      },\n    );\n\n    const isDisabled = computed(() => Boolean(props.disabled.value));\n    const locale = computed(() => props.locale.value || (typeof navigator !== 'undefined' ? navigator.language : 'en'));\n\n    // ── Date-picker control ─────────────────────────────────────────────────\n\n    const ctrl = createDatePickerControl({\n      get locale() {\n        return locale.value;\n      },\n      get max() {\n        return parseIso(props.max.value);\n      },\n      get min() {\n        return parseIso(props.min.value);\n      },\n      onChange(date) {\n        localSelection.value = date;\n        isOpen.value = false;\n        ctrl.setView('day');\n        currentView.value = 'day';\n        displayYear.value = ctrl.displayYear();\n        displayMonth.value = ctrl.displayMonth();\n        setFieldValue(el, toIsoString(date) ?? '');\n        dispatchNativeFieldEvent(el, 'input');\n        dispatchNativeFieldEvent(el, 'change');\n      },\n      get value() {\n        return selectedDate.value;\n      },\n      get weekendDays() {\n        return props['weekend-days'].value ?? [];\n      },\n    });\n\n    // ── Reactive display state ────────────────────────────────────────────\n    // Three separate primitive signals — the proven pattern.\n\n    const currentView = signal<DatePickerView>('day');\n    const displayYear = signal(ctrl.displayYear());\n    const displayMonth = signal(ctrl.displayMonth()); // 1-indexed (Temporal)\n\n    // ── Form value (host is formAssociated) ──────────────────────────────────\n\n    useField<string>({\n      disabled: isDisabled,\n      toFormValue: (v) => v || null,\n      value: computed(() => toIsoString(selectedDate.value) ?? ''),\n    });\n\n    const dialogId = `date-picker-${Math.random().toString(36).slice(2, 9)}-calendar`;\n\n    // ── Floating position ────────────────────────────────────────────────────\n    // The old CSS-only `position: absolute; top: 100%` positioned the calendar relative to\n    // the host box — fine until the host sits near a scroll/clip ancestor's edge (e.g. a form\n    // grid inside a dialog), where the same absolute box also expands that ancestor's\n    // *scrollable* overflow area even though it never changes the ancestor's own layout size,\n    // which reads as \"the dialog got bigger\"/jumped. `createDropdownPositioner` — the same\n    // Orbit-powered primitive `ore-select`'s dropdown already uses — positions via `fixed` +\n    // computed `top`/`left`, auto-detecting both the nearest clipping ancestor (so flip/shift\n    // keep the calendar within the dialog panel, not just the page viewport) and any ancestor\n    // that establishes a containing block for `position: fixed` (a dialog panel's entrance\n    // transition commonly leaves a permanent, if visually-identity, `transform` at rest) —\n    // see `createDropdownPositioner`'s own `boundary`/`containingBlock` docs.\n    const triggerRef = ref<HTMLElement>();\n    const calendarRef = ref<HTMLElement>();\n\n    const positioner = createDropdownPositioner({\n      getFloating: () => calendarRef.value ?? null,\n      getReference: () => triggerRef.value ?? null,\n      matchWidth: false,\n      offsetPx: 4,\n    });\n\n    let stopAutoUpdate: (() => void) | null = null;\n\n    // ── Derived display values ───────────────────────────────────────────────\n\n    const triggerText = computed(() => {\n      if (selectedDate.value) return formatDisplayDate(selectedDate.value, locale.value);\n\n      return props.placeholder.value || '';\n    });\n\n    const displayMonth_ = computed(() => {\n      const d = Temporal.PlainDate.from({ day: 1, month: displayMonth.value, year: displayYear.value });\n\n      return format(d, { intl: { month: 'long' }, locale: locale.value, timeZone: 'UTC' });\n    });\n\n    const displayYear_ = computed(() => String(displayYear.value));\n    const displayLabel = computed(() => `${displayMonth_.value} ${displayYear_.value}`);\n\n    const dayCells = computed(() => {\n      void displayYear.value;\n      void displayMonth.value;\n      void selectedDate.value; // re-run when selection changes to refresh isSelected flags\n\n      return ctrl.dayCells();\n    });\n    const monthCells = computed(() => {\n      void displayYear.value;\n\n      return ctrl.monthCells();\n    });\n    const yearCells = computed(() => {\n      void displayYear.value;\n\n      return ctrl.yearCells();\n    });\n    const weekdayLabels = computed(() => ctrl.weekdayLabels());\n    const tabIndex = () => (isDisabled.value ? '-1' : '0');\n\n    // ── Navigation handlers ──────────────────────────────────────────────────\n    // In year/month views navigate by year; in day view navigate by month.\n\n    function handlePrev(): void {\n      if (currentView.value === 'day') ctrl.prevMonth();\n      else ctrl.prevYear();\n\n      displayYear.value = ctrl.displayYear();\n      displayMonth.value = ctrl.displayMonth();\n    }\n\n    function handleNext(): void {\n      if (currentView.value === 'day') ctrl.nextMonth();\n      else ctrl.nextYear();\n\n      displayYear.value = ctrl.displayYear();\n      displayMonth.value = ctrl.displayMonth();\n    }\n\n    function handleHeaderClick(): void {\n      const views: DatePickerView[] = ['day', 'month', 'year'];\n      const next = views[(views.indexOf(currentView.value) + 1) % views.length];\n\n      ctrl.setView(next);\n      currentView.value = next;\n    }\n\n    function handleSelectMonth(month: number): void {\n      ctrl.goTo(ctrl.displayYear(), month);\n      ctrl.setView('day');\n      displayYear.value = ctrl.displayYear();\n      displayMonth.value = ctrl.displayMonth();\n      currentView.value = 'day';\n    }\n\n    function handleSelectYear(year: number): void {\n      ctrl.goTo(year, ctrl.displayMonth());\n      ctrl.setView('month');\n      displayYear.value = ctrl.displayYear();\n      currentView.value = 'month';\n    }\n\n    function handleSelectDay(isoStr: string): void {\n      const date = parseIso(isoStr);\n\n      if (!date) return;\n\n      ctrl.select(date);\n    }\n\n    function handleDayKeydown(e: KeyboardEvent): void {\n      const cell = e.currentTarget as HTMLElement;\n      const grid = cell.closest('.cal-grid-days');\n\n      if (!grid) return;\n\n      const allCells = Array.from(grid.querySelectorAll<HTMLElement>('.cal-cell-day'));\n      const idx = allCells.indexOf(cell);\n\n      if (idx === -1) return;\n\n      let target: HTMLElement | undefined;\n\n      if (e.key === 'Enter' || e.key === ' ') {\n        e.preventDefault();\n        handleSelectDay(cell.dataset.iso ?? '');\n\n        return;\n      } else if (e.key === 'ArrowRight') {\n        target = allCells[idx + 1];\n      } else if (e.key === 'ArrowLeft') {\n        target = allCells[idx - 1];\n      } else if (e.key === 'ArrowDown') {\n        target = allCells[idx + 7];\n      } else if (e.key === 'ArrowUp') {\n        target = allCells[idx - 7];\n      } else if (e.key === 'Home') {\n        target = allCells[Math.floor(idx / 7) * 7];\n      } else if (e.key === 'End') {\n        target = allCells[Math.floor(idx / 7) * 7 + 6];\n      } else {\n        return;\n      }\n\n      e.preventDefault();\n      target?.focus();\n    }\n\n    // ── Month/year-cell keyboard navigation (fixed 4-column grid) ─────────────\n\n    function handleGridKeydown(e: KeyboardEvent, cellSelector: string, columns: number, onSelect: () => void): void {\n      const cell = e.currentTarget as HTMLElement;\n      const grid = cell.closest('.cal-grid');\n\n      if (!grid) return;\n\n      const allCells = Array.from(grid.querySelectorAll<HTMLElement>(cellSelector));\n      const idx = allCells.indexOf(cell);\n\n      if (idx === -1) return;\n\n      let target: HTMLElement | undefined;\n\n      if (e.key === 'Enter' || e.key === ' ') {\n        e.preventDefault();\n        onSelect();\n\n        return;\n      } else if (e.key === 'ArrowRight') {\n        target = allCells[idx + 1];\n      } else if (e.key === 'ArrowLeft') {\n        target = allCells[idx - 1];\n      } else if (e.key === 'ArrowDown') {\n        target = allCells[idx + columns];\n      } else if (e.key === 'ArrowUp') {\n        target = allCells[idx - columns];\n      } else if (e.key === 'Home') {\n        target = allCells[Math.floor(idx / columns) * columns];\n      } else if (e.key === 'End') {\n        target = allCells[Math.min(Math.floor(idx / columns) * columns + columns - 1, allCells.length - 1)];\n      } else {\n        return;\n      }\n\n      e.preventDefault();\n      target?.focus();\n    }\n\n    // ── Open / close ─────────────────────────────────────────────────────────\n\n    function openPicker(): void {\n      if (isDisabled.value) return;\n\n      isOpen.value = true;\n      ctrl.setView('day');\n      currentView.value = 'day';\n\n      const sel = selectedDate.value;\n\n      if (sel) {\n        ctrl.goTo(sel.year, sel.month);\n        displayYear.value = ctrl.displayYear();\n        displayMonth.value = ctrl.displayMonth();\n      }\n\n      positioner.update();\n      stopAutoUpdate = positioner.startAutoUpdate?.() ?? null;\n    }\n\n    function closePicker(): void {\n      isOpen.value = false;\n      ctrl.setView('day');\n      currentView.value = 'day';\n      stopAutoUpdate?.();\n      stopAutoUpdate = null;\n    }\n\n    function handleTriggerClick(): void {\n      if (isOpen.value) closePicker();\n      else openPicker();\n    }\n\n    // ── Keyboard handlers ────────────────────────────────────────────────────\n\n    function handleTriggerKeydown(e: KeyboardEvent): void {\n      if (isDisabled.value) return;\n\n      if (e.key === 'Enter' || e.key === ' ') {\n        e.preventDefault();\n        handleTriggerClick();\n      } else if (e.key === 'Escape' && isOpen.value) {\n        e.preventDefault();\n        closePicker();\n      }\n    }\n\n    function handleCalendarKeydown(e: KeyboardEvent): void {\n      if (e.key === 'Escape') {\n        e.preventDefault();\n        closePicker();\n      }\n    }\n\n    function handleOutsideClick(e: PointerEvent | MouseEvent): void {\n      if (!isOpen.value) return;\n\n      const path = e.composedPath();\n\n      if (!path.includes(el)) closePicker();\n    }\n\n    // ── Lifecycle ────────────────────────────────────────────────────────────\n\n    onMounted(() => {\n      document.addEventListener('pointerdown', handleOutsideClick, { capture: true });\n\n      return () => {\n        document.removeEventListener('pointerdown', handleOutsideClick, { capture: true });\n        stopAutoUpdate?.();\n        stopAutoUpdate = null;\n      };\n    });\n\n    // ── Host bindings ────────────────────────────────────────────────────────\n\n    bind({\n      attr: {\n        open: () => (isOpen.value ? true : undefined),\n      },\n    });\n\n    // ── Template ─────────────────────────────────────────────────────────────\n\n    const inputValue = () => triggerText.value;\n    const inputLabel = () => props.label.value ?? '';\n    const inputPlaceholder = () => props.placeholder.value ?? '';\n    const inputLabelPlacement = () => props['label-placement'].value ?? 'inset';\n    const inputColor = () => props.color?.value ?? undefined;\n    const inputSize = () => props.size?.value ?? undefined;\n    const inputVariant = () => props.variant?.value ?? undefined;\n    const inputRounded = () => props.rounded?.value ?? undefined;\n    const inputHelper = () => props.helper.value ?? '';\n    const inputError = () => props.error.value ?? '';\n    const inputDisabled = () => (isDisabled.value ? true : undefined);\n    const inputRequired = () => (props.required.value ? true : undefined);\n    const inputFullwidth = () => (props.fullwidth.value ? true : undefined);\n\n    return html`\n      <!-- Trigger: ore-input in readonly display mode -->\n      <ore-input\n        class=\"trigger\"\n        ref=\"${triggerRef}\"\n        readonly\n        tabindex=\"${tabIndex}\"\n        role=\"combobox\"\n        aria-haspopup=\"dialog\"\n        aria-controls=\"${dialogId}\"\n        aria-expanded=\"${() => String(isOpen.value)}\"\n        aria-disabled=\"${() => (isDisabled.value ? 'true' : null)}\"\n        value=\"${inputValue}\"\n        label=\"${inputLabel}\"\n        placeholder=\"${inputPlaceholder}\"\n        label-placement=\"${inputLabelPlacement}\"\n        color=\"${inputColor}\"\n        size=\"${inputSize}\"\n        variant=\"${inputVariant}\"\n        rounded=\"${inputRounded}\"\n        helper=\"${inputHelper}\"\n        error=\"${inputError}\"\n        ?disabled=\"${inputDisabled}\"\n        ?required=\"${inputRequired}\"\n        ?fullwidth=\"${inputFullwidth}\"\n        ?success=\"${() => props.success.value}\"\n        @click=\"${handleTriggerClick}\"\n        @keydown=\"${handleTriggerKeydown}\">\n        <ore-icon slot=\"suffix\" name=\"calendar\" size=\"16\" stroke-width=\"1.75\" aria-hidden=\"true\"></ore-icon>\n      </ore-input>\n\n      <!-- Calendar popup -->\n      <div\n        class=\"calendar\"\n        ref=\"${calendarRef}\"\n        id=\"${dialogId}\"\n        role=\"dialog\"\n        aria-modal=\"true\"\n        aria-label=\"${() => `Choose date — ${displayLabel.value}`}\"\n        ?data-open=\"${isOpen}\"\n        @keydown=\"${handleCalendarKeydown}\">\n        <!-- Calendar header -->\n        <div class=\"cal-header\" part=\"header\">\n          <button class=\"nav-btn\" type=\"button\" aria-label=\"Previous\" @click=\"${handlePrev}\">\n            <ore-icon name=\"chevron-left\" size=\"16\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n          </button>\n          <button\n            class=\"cal-label-btn\"\n            type=\"button\"\n            aria-label=\"${() =>\n              `Switch to ${currentView.value === 'day' ? 'month' : currentView.value === 'month' ? 'year' : 'day'} view`}\"\n            @click=\"${handleHeaderClick}\">\n            <span class=\"cal-label-month\">${displayMonth_}</span>\n            <span class=\"cal-label-sep\" aria-hidden=\"true\">/</span>\n            <span class=\"cal-label-year\">${displayYear_}</span>\n          </button>\n          <button class=\"nav-btn\" type=\"button\" aria-label=\"Next\" @click=\"${handleNext}\">\n            <ore-icon name=\"chevron-right\" size=\"16\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n          </button>\n        </div>\n\n        <!-- Day view: flat 7-column CSS grid, weekday headers + day cells -->\n        <div\n          class=\"cal-grid cal-grid-days\"\n          role=\"grid\"\n          part=\"grid\"\n          aria-label=\"${() => displayLabel.value}\"\n          ?hidden=\"${() => currentView.value !== 'day'}\">\n          <div role=\"row\" class=\"cal-grid-row\">\n            ${() =>\n              weekdayLabels.value.map(\n                (lbl) => html`\n                  <div class=\"cal-cell cal-cell-head\" role=\"columnheader\" aria-label=\"${lbl}\">${lbl}</div>\n                `,\n              )}\n          </div>\n          ${() => {\n            const cells = dayCells.value;\n            const rows: (typeof cells)[number][][] = [];\n\n            for (let i = 0; i < cells.length; i += 7) rows.push(cells.slice(i, i + 7));\n\n            return rows.map(\n              (row) => html`\n                <div role=\"row\" class=\"cal-grid-row\">\n                  ${row.map(\n                    (cell) => html`\n                      <div\n                        class=\"cal-cell cal-cell-day\"\n                        role=\"gridcell\"\n                        part=\"day\"\n                        aria-selected=\"${() => String(cell.isSelected)}\"\n                        aria-disabled=\"${() => String(cell.isDisabled)}\"\n                        aria-current=\"${() => (cell.isToday ? 'date' : null)}\"\n                        ?data-selected=\"${() => cell.isSelected}\"\n                        ?data-today=\"${() => cell.isToday}\"\n                        ?data-outside=\"${() => cell.isOutsideMonth}\"\n                        ?data-disabled=\"${() => cell.isDisabled}\"\n                        data-iso=\"${cell.iso}\"\n                        tabindex=\"${() => (cell.isDisabled ? '-1' : '0')}\"\n                        @click=\"${() => handleSelectDay(cell.iso)}\"\n                        @keydown=\"${handleDayKeydown}\">\n                        ${String(cell.day)}\n                      </div>\n                    `,\n                  )}\n                </div>\n              `,\n            );\n          }}\n        </div>\n\n        <!-- Month view -->\n        <div\n          class=\"cal-grid cal-grid-months\"\n          role=\"grid\"\n          aria-label=\"${() => displayYear_.value}\"\n          ?hidden=\"${() => currentView.value !== 'month'}\">\n          ${() => {\n            const cells = monthCells.value;\n            const rows: (typeof cells)[number][][] = [];\n\n            for (let i = 0; i < cells.length; i += 4) rows.push(cells.slice(i, i + 4));\n\n            return rows.map(\n              (row) => html`\n                <div role=\"row\">\n                  ${row.map(\n                    (cell) => html`\n                      <div\n                        class=\"cal-cell cal-cell-month\"\n                        role=\"gridcell\"\n                        aria-selected=\"${() => String(cell.isSelected)}\"\n                        aria-disabled=\"${() => String(cell.isDisabled)}\"\n                        ?data-selected=\"${() => cell.isSelected}\"\n                        ?data-disabled=\"${() => cell.isDisabled}\"\n                        tabindex=\"${() => (cell.isDisabled ? '-1' : '0')}\"\n                        @click=\"${() => {\n                          if (!cell.isDisabled) handleSelectMonth(cell.month);\n                        }}\"\n                        @keydown=\"${(e: KeyboardEvent) =>\n                          handleGridKeydown(e, '.cal-cell-month', 4, () => {\n                            if (!cell.isDisabled) handleSelectMonth(cell.month);\n                          })}\">\n                        ${cell.shortLabel}\n                      </div>\n                    `,\n                  )}\n                </div>\n              `,\n            );\n          }}\n        </div>\n\n        <!-- Year view -->\n        <div\n          class=\"cal-grid cal-grid-years\"\n          role=\"grid\"\n          aria-label=\"Select year\"\n          ?hidden=\"${() => currentView.value !== 'year'}\">\n          ${() => {\n            const cells = yearCells.value;\n            const rows: (typeof cells)[number][][] = [];\n\n            for (let i = 0; i < cells.length; i += 4) rows.push(cells.slice(i, i + 4));\n\n            return rows.map(\n              (row) => html`\n                <div role=\"row\">\n                  ${row.map(\n                    (cell) => html`\n                      <div\n                        class=\"cal-cell cal-cell-year\"\n                        role=\"gridcell\"\n                        aria-selected=\"${() => String(cell.isSelected)}\"\n                        aria-disabled=\"${() => String(cell.isDisabled)}\"\n                        ?data-selected=\"${() => cell.isSelected}\"\n                        ?data-disabled=\"${() => cell.isDisabled}\"\n                        tabindex=\"${() => (cell.isDisabled ? '-1' : '0')}\"\n                        @click=\"${() => {\n                          if (!cell.isDisabled) handleSelectYear(cell.year);\n                        }}\"\n                        @keydown=\"${(e: KeyboardEvent) =>\n                          handleGridKeydown(e, '.cal-cell-year', 4, () => {\n                            if (!cell.isDisabled) handleSelectYear(cell.year);\n                          })}\">\n                        ${String(cell.year)}\n                      </div>\n                    `,\n                  )}\n                </div>\n              `,\n            );\n          }}\n        </div>\n      </div>\n    `;\n  },\n\n  shadow: { delegatesFocus: true },\n  styles: [colorThemeMixin, reducedMotionMixin, componentStyles],\n});\n","@layer refine.base {\n  :host {\n    --_font-size: var(--file-input-font-size, var(--text-sm));\n    --_radius: var(--file-input-radius, var(--rounded-lg));\n    --_bg: var(--file-input-bg, var(--color-contrast-100));\n    --_border-color: var(--file-input-border-color, var(--color-contrast-300));\n    --_min-height: var(--file-input-min-height, var(--size-36));\n\n    display: inline-flex;\n    flex-direction: column;\n    align-items: stretch;\n  }\n\n  .file-input-wrapper {\n    display: flex;\n    flex-direction: column;\n    gap: var(--size-1-5);\n    width: 100%;\n  }\n\n  /* ========================================\n       Label\n       ======================================== */\n\n  .label-outside {\n    font-size: var(--text-sm);\n    font-weight: var(--font-medium);\n    line-height: var(--leading-none);\n    color: var(--color-contrast-500);\n    cursor: default;\n    user-select: none;\n    transition: color var(--transition-fast);\n  }\n\n  /* ========================================\n       Dropzone\n       ======================================== */\n\n  .dropzone {\n    position: relative;\n    box-sizing: border-box;\n    display: flex;\n    flex-direction: column;\n    gap: var(--size-2);\n    align-items: center;\n    justify-content: center;\n    min-height: var(--_min-height);\n    padding: var(--size-6) var(--size-4);\n    text-align: center;\n    cursor: pointer;\n    outline: none;\n    background: var(--_bg);\n    border: var(--border-2) dashed var(--_border-color);\n    border-radius: var(--_radius);\n    transition:\n      background var(--transition-fast),\n      border-color var(--transition-fast),\n      box-shadow var(--transition-fast);\n  }\n\n  .dropzone-content {\n    display: flex;\n    flex-direction: column;\n    gap: var(--size-2);\n    align-items: center;\n    pointer-events: none;\n  }\n\n  .dropzone-icon {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    color: var(--color-contrast-400);\n    transition:\n      color var(--transition-fast),\n      transform var(--transition-fast);\n  }\n\n  .dropzone-title {\n    font-size: var(--_font-size);\n    font-weight: var(--font-medium);\n    line-height: var(--leading-snug);\n    color: var(--color-contrast-700);\n  }\n\n  .dropzone-title u {\n    color: var(--_theme-focus, var(--color-primary));\n    text-decoration: underline;\n    text-decoration-color: transparent;\n    text-underline-offset: 2px;\n    transition: text-decoration-color var(--transition-fast);\n  }\n\n  /* Signal 01: the copy itself during an active drag, not just the border/glow. */\n  .dropzone-title-active {\n    color: var(--_theme-focus, var(--color-primary));\n  }\n\n  .dropzone-hint {\n    font-size: var(--text-xs);\n    line-height: var(--leading-tight);\n    color: var(--color-contrast-400);\n  }\n\n  /* ========================================\n       Helper Text\n       ======================================== */\n\n  .helper-text[hidden] {\n    display: none;\n  }\n\n  .helper-text {\n    padding-inline: 2px;\n    font-size: var(--text-xs);\n    line-height: var(--leading-tight);\n    color: color-mix(in oklch, var(--color-contrast-500) 80%, var(--color-canvas));\n  }\n\n  /* ========================================\n       File List\n       ======================================== */\n\n  .file-list {\n    display: flex;\n    flex-direction: column;\n    gap: var(--size-1);\n    padding: 0;\n    margin: 0;\n    list-style: none;\n  }\n\n  .file-item {\n    box-sizing: border-box;\n    display: flex;\n    gap: var(--size-3);\n    align-items: center;\n    padding: var(--size-2) var(--size-3);\n    background: var(--color-contrast-50);\n    border: var(--border) solid var(--color-contrast-200);\n    border-radius: var(--_radius);\n    transition: background var(--transition-fast);\n  }\n\n  .file-item:hover {\n    background: var(--color-contrast-100);\n  }\n\n  .file-icon {\n    flex-shrink: 0;\n    color: var(--_theme-focus, var(--color-primary));\n  }\n\n  .file-meta {\n    display: flex;\n    flex: 1;\n    flex-direction: column;\n    gap: var(--size-0-5);\n    min-width: 0;\n  }\n\n  .file-name {\n    overflow: hidden;\n    text-overflow: ellipsis;\n    font-size: var(--text-sm);\n    font-weight: var(--font-medium);\n    color: var(--color-contrast-700);\n    white-space: nowrap;\n  }\n\n  .file-size {\n    font-size: var(--text-xs);\n    color: var(--color-contrast-400);\n  }\n\n  .file-actions {\n    display: flex;\n    flex-shrink: 0;\n    gap: var(--size-0-5);\n  }\n\n  .file-remove,\n  .file-action {\n    display: flex;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    padding: var(--size-1);\n    color: var(--color-contrast-400);\n    cursor: pointer;\n    background: transparent;\n    border: none;\n    border-radius: var(--rounded-sm);\n    transition:\n      color var(--transition-fast),\n      background var(--transition-fast);\n  }\n\n  .file-remove:hover {\n    color: var(--color-error);\n    background: var(--color-error-backdrop, color-mix(in oklch, var(--color-error) 12%, transparent));\n  }\n\n  /* Signal 03/04: retry and replace share one neutral-hover treatment — distinct from remove's\n     error-red hover so the destructive action doesn't blend in with the recovery ones. */\n  .file-action:hover {\n    color: var(--_theme-focus, var(--color-primary));\n    background: var(--_theme-backdrop, color-mix(in oklch, var(--color-primary) 12%, transparent));\n  }\n\n  /* ========================================\n       Upload Status (Signals 02, 03, 04)\n       ======================================== */\n\n  .file-progress-meta {\n    font-size: var(--text-xs);\n    color: var(--color-contrast-400);\n  }\n\n  .file-error-text {\n    overflow: hidden;\n    text-overflow: ellipsis;\n    font-size: var(--text-xs);\n    color: var(--color-error);\n    white-space: nowrap;\n  }\n\n  .file-item[data-status='success'] .file-icon {\n    color: var(--color-success);\n  }\n\n  .file-item[data-status='error'] .file-icon {\n    color: var(--color-error);\n  }\n\n  .file-item[data-status='error'] {\n    border-color: color-mix(in oklch, var(--color-error) 40%, var(--color-contrast-200));\n  }\n\n  /* ========================================\n       File Gallery (preview grid)\n       ======================================== */\n\n  .file-grid {\n    --_thumb-size: var(--file-input-thumb-size, var(--size-24));\n\n    display: grid;\n    grid-template-columns: repeat(auto-fill, minmax(var(--_thumb-size), 1fr));\n    gap: var(--size-2);\n    padding: 0;\n    margin: 0;\n    list-style: none;\n  }\n\n  .file-card {\n    box-sizing: border-box;\n    display: flex;\n    flex-direction: column;\n    gap: var(--size-1);\n  }\n\n  .file-thumb-frame {\n    position: relative;\n    display: block;\n  }\n\n  .file-thumb {\n    box-sizing: border-box;\n    display: block;\n    width: 100%;\n    aspect-ratio: 1;\n    object-fit: cover;\n    background: var(--color-contrast-100);\n    border: var(--border) solid var(--color-contrast-200);\n    border-radius: var(--_radius);\n  }\n\n  .file-thumb-generic {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    color: var(--color-contrast-400);\n  }\n\n  .file-card[data-status='uploading'] .file-thumb {\n    opacity: 0.6;\n  }\n\n  .file-card[data-status='error'] .file-thumb {\n    border-color: color-mix(in oklch, var(--color-error) 50%, var(--color-contrast-200));\n  }\n\n  .file-card-name {\n    overflow: hidden;\n    text-overflow: ellipsis;\n    font-size: var(--text-xs);\n    color: var(--color-contrast-600);\n    text-align: center;\n    white-space: nowrap;\n  }\n\n  /* Signal 04: a small badge over the thumbnail corner — an explicit success/error indicator\n     next to the visual proof itself, not just a caption line below it. */\n  .file-status-badge {\n    position: absolute;\n    top: var(--size-1);\n    left: var(--size-1);\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: var(--size-5);\n    height: var(--size-5);\n    color: var(--color-canvas);\n    border-radius: var(--rounded-full);\n  }\n\n  .file-status-badge-success {\n    background: var(--color-success);\n  }\n\n  .file-status-badge-error {\n    background: var(--color-error);\n  }\n\n  .file-card-actions {\n    position: absolute;\n    top: var(--size-1);\n    right: var(--size-1);\n    display: flex;\n    gap: var(--size-0-5);\n  }\n\n  .file-card-action {\n    display: flex;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    width: var(--size-5);\n    height: var(--size-5);\n    padding: 0;\n    color: var(--color-contrast-50);\n    cursor: pointer;\n    background: color-mix(in oklch, var(--color-contrast-900) 55%, transparent);\n    border: none;\n    border-radius: var(--rounded-full);\n    transition:\n      background var(--transition-fast),\n      color var(--transition-fast);\n  }\n\n  .file-card-remove:hover {\n    color: var(--color-canvas);\n    background: var(--color-error);\n  }\n\n  .file-card-action:not(.file-card-remove):hover {\n    color: var(--color-canvas);\n    background: var(--color-primary);\n  }\n\n  .file-card .file-progress-meta,\n  .file-card .file-error-text {\n    text-align: center;\n    white-space: normal;\n  }\n\n  /* ========================================\n       Hover & Focus\n       ======================================== */\n\n  :host(:not([disabled])) .dropzone:hover {\n    border-color: var(--color-contrast-400);\n  }\n\n  :host(:not([disabled])) .dropzone:hover .dropzone-title u {\n    text-decoration-color: var(--_theme-focus, var(--color-primary));\n  }\n\n  :host(:not([disabled])) .dropzone:focus-visible {\n    border-color: var(--_theme-focus, var(--color-primary));\n    box-shadow: var(--_theme-shadow, var(--color-primary-focus-shadow));\n  }\n\n  :host(:not([disabled])) .dropzone:hover .dropzone-icon,\n  :host(:not([disabled])) .dropzone:focus-visible .dropzone-icon {\n    color: var(--_theme-focus, var(--color-primary));\n    transform: translateY(-1px);\n  }\n\n  /* ========================================\n       Drag-Over State\n       ======================================== */\n\n  :host([drag-over]) .dropzone {\n    background: color-mix(in oklch, var(--_theme-base, var(--color-primary)) 8%, transparent);\n    border-color: var(--_theme-focus, var(--color-primary));\n    border-style: solid;\n\n    /* A genuine glow (not the same subtle ring `:focus-visible` uses above) — a soft inner\n       ring plus a wider, brighter halo, so an active drag reads unmistakably differently from\n       a merely-focused, idle dropzone. */\n    box-shadow:\n      0 0 0 3px color-mix(in oklch, var(--_theme-focus, var(--color-primary)) 25%, transparent),\n      0 0 20px 2px color-mix(in oklch, var(--_theme-focus, var(--color-primary)) 45%, transparent);\n  }\n\n  :host([drag-over]) .dropzone .dropzone-icon {\n    color: var(--_theme-focus, var(--color-primary));\n    transform: translateY(-2px) scale(1.05);\n  }\n\n  /* ========================================\n       Error State\n       ======================================== */\n\n  :host([invalid]) .dropzone {\n    border-color: var(--color-error);\n  }\n\n  :host([invalid]) .label-outside {\n    color: var(--color-error);\n  }\n\n  /* Signal 03: an in-field icon alongside the border shift — never color alone. */\n  .dropzone-icon[data-status='error'] {\n    color: var(--color-error);\n  }\n\n  /* ========================================\n       Error Text\n       ======================================== */\n\n  .helper-text-error {\n    color: var(--color-error);\n  }\n}\n\n@layer refine.variants {\n  /* Solid (Default) */\n  :host(:not([variant])),\n  :host([variant='solid']) {\n    --_bg: var(--file-input-bg, var(--color-contrast-50));\n    --_border-color: var(--file-input-border-color, var(--color-contrast-300));\n  }\n\n  /* Flat — a near-invisible border, deliberately weaker than bordered's\n     70%-focus border (matches button.css's flat/bordered split) so the two\n     don't read as the same box at a glance. */\n  :host([variant='flat']) {\n    --_bg: var(--file-input-bg, var(--color-contrast-100));\n    --_border-color: var(--file-input-border-color, color-mix(in oklch, var(--_theme-focus) 20%, transparent));\n  }\n\n  :host([variant='flat']) .dropzone:hover {\n    background: var(--file-input-hover-bg, color-mix(in oklch, var(--_theme-base) 6%, var(--color-contrast-100)));\n    border-color: var(\n      --file-input-hover-border-color,\n      color-mix(in oklch, var(--_theme-base) 35%, var(--color-contrast-300))\n    );\n  }\n\n  :host([variant='flat']) .dropzone:focus-visible,\n  :host([variant='flat'][drag-over]) .dropzone {\n    background: var(--file-input-focus-bg, color-mix(in oklch, var(--_theme-base) 8%, var(--color-canvas)));\n    border-color: var(--file-input-focus-border-color, color-mix(in oklch, var(--_theme-focus) 60%, transparent));\n    box-shadow: var(--_theme-shadow);\n  }\n\n  /* Bordered */\n  :host([variant='bordered']) {\n    --_bg: var(--file-input-bg, var(--_theme-backdrop));\n    --_border-color: var(--file-input-border-color, color-mix(in oklch, var(--_theme-focus) 70%, transparent));\n  }\n\n  :host([variant='bordered']) .dropzone:hover {\n    border-color: var(--file-input-hover-border-color, var(--_theme-focus));\n  }\n\n  /* Outline */\n  :host([variant='outline']) {\n    --_bg: var(--file-input-bg, transparent);\n  }\n\n  /* Ghost */\n\n  /* Borderless at rest — only reveals a border on hover (the border-*width* stays reserved via\n     a transparent color, not `none`, so revealing it on hover never shifts layout). Focus\n     already gets its own themed border + glow from the generic `:focus-visible` rule above,\n     regardless of variant, so it needs no ghost-specific override here. */\n  :host([variant='ghost']) {\n    --_bg: var(--file-input-bg, transparent);\n    --_border-color: var(--file-input-border-color, transparent);\n  }\n\n  :host(:not([disabled])[variant='ghost']) .dropzone:hover {\n    background: var(--file-input-hover-bg, var(--color-contrast-100));\n    border-color: var(--file-input-hover-border-color, var(--color-contrast-200));\n  }\n}\n\n@layer refine.utilities {\n  :host([fullwidth]) {\n    width: 100%;\n  }\n}\n\n/* ========================================\n     Disabled State — intentionally unlayered\n     ======================================== */\n\n/*\n * The shared `disabledLoadingMixin` (pulled in via `fieldMixins`) dims `:host([disabled])`\n * with `opacity: 0.5` as bare, unlayered CSS. Cascade layers always lose to unlayered rules\n * regardless of source order or specificity, so overriding that from inside any `@layer`\n * block in this file (including `refine.overrides`) would be a no-op — this has to stay\n * unlayered too, to actually win. See `ore-input`'s `input.css` for the same pattern.\n *\n * Per the field-state UX review: opacity-based dimming reads as a washed-out/loading look\n * and can mimic reduced-contrast content for low-vision users, rather than a clearly locked\n * field. Swapped for an explicit grayscale surface + `not-allowed` cursor (the cursor already\n * comes from the shared mixin, left untouched here).\n */\n:host([disabled]) {\n  opacity: 1;\n}\n\n:host([disabled]) .dropzone {\n  background: var(--color-contrast-100);\n  border-color: var(--color-contrast-200);\n}\n\n:host([disabled]) .dropzone-icon,\n:host([disabled]) .dropzone-title,\n:host([disabled]) .dropzone-hint,\n:host([disabled]) .dropzone-title u {\n  color: var(--color-contrast-400);\n}\n\n:host([disabled]) .label-outside {\n  color: var(--color-contrast-400);\n}\n","import { matchesAccept } from '@vielzeug/dnd';\nimport { type Readable, signal, watch } from '@vielzeug/ripple';\n\nimport { announce } from '../../core';\n\n// ── Byte/speed formatting ────────────────────────────────────────────────────\n\nexport const formatBytes = (bytes: number): string => {\n  if (bytes === 0) return '0 B';\n\n  const k = 1024;\n  const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];\n  const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n  return `${parseFloat((bytes / k ** i).toFixed(1))} ${sizes[i]}`;\n};\n\nconst isFileSizeAllowed = (file: File, maxSize: number): boolean => !maxSize || file.size <= maxSize;\n\nconst formatSpeed = (bytesPerSecond: number): string => (bytesPerSecond > 0 ? `${formatBytes(bytesPerSecond)}/s` : '');\n\nconst parseAccept = (accept: string | undefined): string[] => (accept ? accept.split(',').map((t) => t.trim()) : []);\n\n// ── Upload lifecycle types ───────────────────────────────────────────────────\n\n/** Upload lifecycle status for a single file. `idle` covers both \"no `upload` handler wired up\"\n * (picker-only mode, fully supported) and \"not started yet\". */\nexport type FileUploadStatus = 'error' | 'idle' | 'success' | 'uploading';\n\n/** Per-file upload snapshot. One reactive signal per file — see `createFileQueue` — not one\n * signal holding a map, so a progress tick for one file never invalidates another's bindings. */\nexport type FileUploadState = {\n  error: string | null;\n  loaded: number;\n  speedBps: number;\n  status: FileUploadStatus;\n  total: number;\n};\n\nconst IDLE_UPLOAD_STATE: Omit<FileUploadState, 'total'> = { error: null, loaded: 0, speedBps: 0, status: 'idle' };\n\nconst formatEta = (state: FileUploadState): string => {\n  if (state.speedBps <= 0 || state.status !== 'uploading') return '';\n\n  const remainingSeconds = Math.max(0, Math.round((state.total - state.loaded) / state.speedBps));\n\n  if (remainingSeconds < 60) return `${remainingSeconds}s left`;\n\n  return `${Math.round(remainingSeconds / 60)}m left`;\n};\n\n/**\n * Consumer-supplied transport — this component has no built-in network layer (zero-dependency,\n * transport-agnostic by design, same reasoning as `courier`'s own fetch-wrapping-only stance).\n * This function is the seam between the UI's upload lifecycle (progress, retry, per-file\n * isolation) and however the app actually moves bytes (`fetch`, `XMLHttpRequest`, a presigned S3\n * PUT, `@vielzeug/courier`, …).\n *\n * `resumeFrom` is a *hint*, not a guarantee: it's the byte offset the component last observed\n * via `onProgress` before the previous attempt failed (0 on a fresh upload). A transport that\n * supports byte ranges (e.g. an HTTP `Range`/`Content-Range` header, S3 multipart, tus) can use\n * it to genuinely resume from that point; a plain `fetch(url, { body: file })` can ignore it and\n * simply re-send the whole file — the UI still shows a resumed-from-N-bytes experience either\n * way, since the file itself was never dropped from memory.\n */\nexport type FileUploadFn = (\n  file: File,\n  ctx: { onProgress: (loaded: number, total: number) => void; resumeFrom: number; signal: AbortSignal },\n) => Promise<void>;\n\n// ── Queue ─────────────────────────────────────────────────────────────────────\n\nexport type FileQueueOptions = {\n  accept: Readable<string | undefined>;\n  disabled: Readable<boolean>;\n  maxFiles: Readable<number>;\n  maxSize: Readable<number>;\n  multiple: Readable<boolean>;\n  onChange: (files: File[], originalEvent?: Event) => void;\n  onRemove: (file: File, files: File[], originalEvent?: Event) => void;\n  onUploadError: (file: File, error: unknown) => void;\n  onUploadProgress: (file: File, loaded: number, total: number) => void;\n  onUploadSuccess: (file: File) => void;\n  upload: Readable<FileUploadFn | undefined>;\n};\n\nexport type FileQueue = {\n  addFiles(newFiles: File[], originalEvent?: Event): void;\n  dispose(): void;\n  readonly files: Readable<File[]>;\n  fileState(file: File): FileUploadState;\n  removeFile(file: File, originalEvent?: Event): void;\n  /** Validates `newFile` (accept/max-size) and, if accepted, swaps it in for `oldFile` in place\n   * and starts its upload. Returns whether the replacement was accepted. Also fires `onRemove`\n   * for `oldFile` — a replace is a removal-and-add that happen to land in the same slot, and a\n   * consumer listening only for removal (e.g. to clean up a server-side record) still needs to\n   * hear that the old file is gone. */\n  replaceFile(oldFile: File, newFile: File, originalEvent?: Event): boolean;\n  retryUpload(file: File): void;\n  statusIconName(file: File): string;\n  uploadMetaText(file: File): string;\n  uploadPercent(file: File): number;\n};\n\n/**\n * Owns file selection *and* the opt-in upload lifecycle together — they were never really\n * separable (adding a file starts its upload; removing one must abort it; replacing one is both\n * at once). Independent of `html`/rendering, following the same shape as `datagrid`'s\n * `createDataGridControls` and `combobox`'s `combobox-options.ts`: a factory `file-input.ts`\n * wires into drag/drop/native-input events and the template, directly unit-testable without\n * mounting a component.\n *\n * Every file-level rule (accept, max-size, max-files, disabled) and every upload-lifecycle rule\n * (progress, retry-from-offset, per-file isolation) lives here in one place.\n */\nexport function createFileQueue(options: FileQueueOptions): FileQueue {\n  const files = signal<File[]>([]);\n  const stateSignals = new Map<File, ReturnType<typeof signal<FileUploadState>>>();\n  const controllers = new Map<File, AbortController>();\n\n  function stateSignal(file: File): ReturnType<typeof signal<FileUploadState>> {\n    let s = stateSignals.get(file);\n\n    if (!s) {\n      s = signal<FileUploadState>({ ...IDLE_UPLOAD_STATE, total: file.size });\n      stateSignals.set(file, s);\n    }\n\n    return s;\n  }\n\n  function fileState(file: File): FileUploadState {\n    return stateSignal(file).value;\n  }\n\n  function patchState(file: File, patch: Partial<FileUploadState>): void {\n    const s = stateSignal(file);\n\n    s.value = { ...s.value, ...patch };\n  }\n\n  // Each file gets its own `AbortController` and its own promise chain — nothing here `await`s\n  // another file's upload, so one file's rejection can never block, freeze, or cancel the others.\n  function startUpload(file: File, resumeFrom = 0): void {\n    if (options.disabled.value) return;\n\n    const uploadFn = options.upload.value;\n\n    if (!uploadFn) return;\n\n    controllers.get(file)?.abort();\n\n    const controller = new AbortController();\n\n    controllers.set(file, controller);\n    patchState(file, { error: null, loaded: resumeFrom, speedBps: 0, status: 'uploading', total: file.size });\n\n    // Rolling (exponential-moving-average) speed estimate rather than a naive\n    // `loaded / elapsedSinceStart` average — the latter drags heavily behind the file's actual\n    // *current* rate right after a slow start or a mid-transfer stall.\n    let lastSampleAt = performance.now();\n    let lastSampleLoaded = resumeFrom;\n\n    uploadFn(file, {\n      onProgress: (loaded, total) => {\n        if (controller.signal.aborted) return;\n\n        const now = performance.now();\n        const elapsedSeconds = (now - lastSampleAt) / 1000;\n        const instantBps = elapsedSeconds > 0 ? Math.max(0, (loaded - lastSampleLoaded) / elapsedSeconds) : 0;\n        const previousBps = fileState(file).speedBps;\n        const speedBps = previousBps > 0 ? previousBps * 0.7 + instantBps * 0.3 : instantBps;\n\n        lastSampleAt = now;\n        lastSampleLoaded = loaded;\n        patchState(file, { loaded, speedBps, total: total || file.size });\n        options.onUploadProgress(file, loaded, total || file.size);\n      },\n      resumeFrom,\n      signal: controller.signal,\n    })\n      .then(() => {\n        if (controller.signal.aborted) return;\n\n        patchState(file, { loaded: file.size, speedBps: 0, status: 'success' });\n        announce(`${file.name} uploaded successfully.`);\n        options.onUploadSuccess(file);\n      })\n      .catch((error: unknown) => {\n        if (controller.signal.aborted) return;\n\n        const message = error instanceof Error ? error.message : String(error);\n\n        patchState(file, { error: message, speedBps: 0, status: 'error' });\n        announce(`${file.name} failed to upload: ${message}`, { politeness: 'assertive' });\n        options.onUploadError(file, error);\n      });\n  }\n\n  // Resumes from the last byte offset this file actually reached, not from 0 — see\n  // `FileUploadFn`'s doc comment on what \"resume\" honestly means when the transport is\n  // consumer-supplied.\n  function retryUpload(file: File): void {\n    if (options.disabled.value) return;\n\n    startUpload(file, fileState(file).loaded);\n  }\n\n  // Aborts + drops upload state for any file no longer in `files` — covers plain removal, a\n  // non-`multiple` selection replacing the previous file, and `replaceFile()` swapping one File\n  // for another. One cleanup path instead of duplicating it at every call site that can shrink\n  // `files`.\n  function dropOrphanedState(activeFiles: File[]): void {\n    const keep = new Set(activeFiles);\n\n    for (const file of stateSignals.keys()) {\n      if (keep.has(file)) continue;\n\n      controllers.get(file)?.abort();\n      controllers.delete(file);\n      stateSignals.delete(file);\n    }\n  }\n\n  const filesWatch = watch(files, dropOrphanedState);\n\n  function addFiles(newFiles: File[], originalEvent?: Event): void {\n    if (options.disabled.value) return;\n\n    const isMultiple = options.multiple.value;\n    let incoming = Array.from(newFiles);\n\n    if (!isMultiple) incoming = incoming.slice(0, 1);\n\n    const acceptList = parseAccept(options.accept.value);\n    const maxSize = options.maxSize.value;\n\n    incoming = incoming.filter((f) => matchesAccept(f, acceptList) && isFileSizeAllowed(f, maxSize));\n\n    let updated: File[] = isMultiple ? [...files.value] : [];\n    const added: File[] = [];\n\n    for (const f of incoming) {\n      if (!updated.includes(f)) {\n        updated.push(f);\n        added.push(f);\n      }\n    }\n\n    const maxFiles = options.maxFiles.value;\n\n    if (maxFiles > 0 && updated.length > maxFiles) updated = updated.slice(0, maxFiles);\n\n    files.value = updated;\n    options.onChange(files.value, originalEvent);\n\n    for (const f of added) {\n      if (files.value.includes(f)) startUpload(f);\n    }\n  }\n\n  function removeFile(file: File, originalEvent?: Event): void {\n    if (options.disabled.value) return;\n\n    files.value = files.value.filter((f) => f !== file);\n    options.onRemove(file, files.value, originalEvent);\n    options.onChange(files.value, originalEvent);\n  }\n\n  function replaceFile(oldFile: File, newFile: File, originalEvent?: Event): boolean {\n    if (options.disabled.value) return false;\n\n    const acceptList = parseAccept(options.accept.value);\n\n    if (!matchesAccept(newFile, acceptList) || !isFileSizeAllowed(newFile, options.maxSize.value)) return false;\n\n    files.value = files.value.map((f) => (f === oldFile ? newFile : f));\n    options.onRemove(oldFile, files.value, originalEvent);\n    options.onChange(files.value, originalEvent);\n    startUpload(newFile);\n\n    return true;\n  }\n\n  function uploadPercent(file: File): number {\n    const state = fileState(file);\n\n    if (state.total <= 0) return 0;\n\n    return Math.min(100, Math.round((state.loaded / state.total) * 100));\n  }\n\n  // Speed + ETA on one line — percent itself is rendered separately (e.g. `<ore-progress>`'s\n  // own `label`), so this only needs the two metrics that wouldn't otherwise fit there.\n  function uploadMetaText(file: File): string {\n    const state = fileState(file);\n\n    return [formatSpeed(state.speedBps), formatEta(state)].filter(Boolean).join(' · ');\n  }\n\n  function statusIconName(file: File): string {\n    const status = fileState(file).status;\n\n    if (status === 'success') return 'check';\n\n    if (status === 'error') return 'alert-circle';\n\n    return 'file';\n  }\n\n  function dispose(): void {\n    filesWatch.dispose();\n\n    for (const controller of controllers.values()) controller.abort();\n\n    controllers.clear();\n    stateSignals.clear();\n  }\n\n  return {\n    addFiles,\n    dispose,\n    fileState,\n    files,\n    removeFile,\n    replaceFile,\n    retryUpload,\n    statusIconName,\n    uploadMetaText,\n    uploadPercent,\n  };\n}\n","import { createDropZone } from '@vielzeug/dnd';\nimport {\n  bind,\n  createStableId,\n  define,\n  html,\n  onCleanup,\n  onElement,\n  onEvent,\n  onMounted,\n  prop,\n  ref,\n  useEmit,\n  useField,\n  when,\n} from '@vielzeug/ore';\nimport { computed, signal, watch } from '@vielzeug/ripple';\n\nimport '../../content/icon/icon';\nimport '../../feedback/progress/progress';\nimport { bindRefCallback, createInteraction } from '../../core';\nimport { FILE_INPUT_SIZE_PRESET } from '../../shared';\nimport {\n  coarsePointerMixin,\n  colorThemeMixin,\n  disabledLoadingMixin,\n  forcedColorsFocusMixin,\n  reducedMotionMixin,\n  roundedVariantMixin,\n  sizeVariantMixin,\n} from '../../styles';\nimport componentStyles from './file-input.css?inline';\nimport { createFileQueue, type FileUploadFn, formatBytes } from './file-input-upload';\n\nexport type { FileUploadFn, FileUploadState, FileUploadStatus } from './file-input-upload';\n\nconst isImageFile = (file: File): boolean => file.type.startsWith('image/');\n\n/** File input component properties */\nexport type OreFileInputProps = {\n  /** Accepted file types (comma-separated, e.g. '.jpg, .png, image/*') */\n  accept?: string;\n  /** Theme color tint */\n  color?: string;\n  /** Disabled state */\n  disabled?: boolean;\n  /** Error message text */\n  error?: string;\n  /**\n   * Render selected files as a grid of image thumbnails/previews instead of the default\n   * single-column list. Non-image files fall back to a generic file icon in the same grid.\n   */\n  gallery?: boolean;\n  /** Helper text displayed below the input */\n  helper?: string;\n  /** Input label text */\n  label?: string;\n  /** Max number of files allowed (only used if multiple is true) */\n  'max-files'?: number;\n  /** Max size of a single file in bytes */\n  'max-size'?: number;\n  /** Allow multiple files selection */\n  multiple?: boolean;\n  /** Form field name */\n  name?: string;\n  /**\n   * JS-only callback fired with the inner `<input type=\"file\">` element when it\n   * mounts, and with `null` when it unmounts. Intended for composed components\n   * that need imperative access to the raw element.\n   * Set as a JS property: `bitFileInput.ref = (el) => { ... }`.\n   */\n  ref?: ((el: HTMLInputElement | null) => void) | null;\n  /** Required field */\n  required?: boolean;\n  /** Field size preset */\n  size?: string;\n  /**\n   * JS-only upload transport (see `FileUploadFn`). When set, every newly added file starts\n   * uploading immediately and independently — progress/speed/ETA, retry-on-failure, and a\n   * success confirmation card are all driven from here. Omit it to keep the component in its\n   * original picker-only mode (select files, no upload lifecycle).\n   * Set as a JS property: `fileInput.upload = async (file, { onProgress, signal }) => { ... }`.\n   */\n  upload?: FileUploadFn | null;\n};\n\n/** Events emitted by the file-input component */\nexport type OreFileInputEvents = {\n  /** Emitted when files are added or removed */\n  change: { files: File[]; originalEvent?: Event; value: File[] };\n  /** Emitted when a specific file is removed */\n  remove: { file: File; files: File[]; originalEvent?: Event; value: File[] };\n  /** Emitted when `upload` rejects for a file (after a fresh attempt or a retry) */\n  'upload-error': { error: unknown; file: File };\n  /** Emitted whenever `upload`'s `onProgress` reports new bytes for a file */\n  'upload-progress': { file: File; loaded: number; total: number };\n  /** Emitted when `upload` resolves for a file */\n  'upload-success': { file: File };\n};\n\n/**\n * A file upload field with drag-and-drop support, built-in validation messaging, and — once a\n * `upload` transport is wired up — a full per-file upload lifecycle: live progress/speed/ETA,\n * retry-on-failure, a success confirmation card, and fully independent handling of concurrent\n * files (one failing never blocks or cancels the others). Picking files with no `upload` set\n * keeps the original, upload-free selection-only behavior.\n *\n * @element ore-file-input\n *\n * @attr {string} accept - Comma-separated file extensions or MIME types\n * @attr {boolean} multiple - Enable multiple files selection\n * @attr {boolean} gallery - Show selected files as an image thumbnail/preview grid\n * @attr {number} max-files - Max number of files allowed\n * @attr {number} max-size - Max size of each file in bytes\n * @attr {boolean} disabled - Disable interaction\n * @attr {string} error - Show an error state/message\n * @attr {string} helper - Provide helper context below the dropzone\n *\n * @fires change - detail: { files: File[], value: File[] }\n * @fires remove - detail: { file: File, files: File[] }\n * @fires upload-progress - detail: { file: File, loaded: number, total: number }\n * @fires upload-success - detail: { file: File }\n * @fires upload-error - detail: { file: File, error: unknown }\n *\n * @cssprop --file-input-bg - Dropzone background color\n * @cssprop --file-input-border-color - Dropzone border color\n * @cssprop --file-input-font-size - Font size\n * @cssprop --file-input-radius - Dropzone border radius\n * @cssprop --file-input-min-height - Minimum dropzone height\n * @cssprop --file-input-hover-bg - Dropzone background on hover (flat/ghost variants)\n * @cssprop --file-input-hover-border-color - Dropzone border on hover (flat/bordered variants)\n * @cssprop --file-input-focus-bg - Dropzone background when focused/drag-over (flat variant)\n * @cssprop --file-input-focus-border-color - Dropzone border when focused/drag-over (flat variant)\n * @cssprop --file-input-thumb-size - Gallery thumbnail width/height\n * @part wrapper - Root wrapper around the file input field\n * @part label - Visible label rendered above the dropzone\n * @part dropzone - Interactive drag-and-drop target\n * @part input - Native file input element\n * @part gallery - Gallery grid container (rendered instead of `file-list` when `gallery` is set)\n * @part helper - Helper text shown beneath the dropzone\n * @part error - Error message shown beneath the field\n * @example\n * ```html\n * <ore-file-input label=\"Upload files\" accept=\"image/*\" multiple />\n * <ore-file-input label=\"Photos\" accept=\"image/*\" multiple gallery />\n * <ore-file-input label=\"Resume\" accept=\".pdf,.doc,.docx\" max-size=\"5242880\" />\n * <ore-file-input variant=\"bordered\" color=\"primary\" />\n * ```\n * ```ts\n * // Wire up a real upload transport — progress/retry/success are then handled automatically.\n * // `XMLHttpRequest` is used here (not `fetch`) because it's the only browser API that reports\n * // upload progress; swap in whatever transport the app already uses.\n * const input = document.querySelector('ore-file-input');\n * input.upload = (file, { onProgress, signal, resumeFrom }) =>\n *   new Promise((resolve, reject) => {\n *     const xhr = new XMLHttpRequest();\n *\n *     xhr.upload.addEventListener('progress', (e) => onProgress(resumeFrom + e.loaded, file.size));\n *     xhr.addEventListener('load', () => (xhr.status < 400 ? resolve() : reject(new Error(xhr.statusText))));\n *     xhr.addEventListener('error', () => reject(new Error('Network error')));\n *     signal.addEventListener('abort', () => xhr.abort());\n *\n *     xhr.open('PUT', '/uploads');\n *     if (resumeFrom > 0) xhr.setRequestHeader('Content-Range', `bytes ${resumeFrom}-/${file.size}`);\n *     xhr.send(file);\n *   });\n * ```\n */\nexport const FILE_INPUT_TAG = 'ore-file-input' as const;\ndefine<OreFileInputProps>(FILE_INPUT_TAG, {\n  formAssociated: true,\n  props: {\n    accept: prop.string(),\n    color: prop.string(),\n    disabled: prop.bool(false),\n    error: prop.string(),\n    gallery: prop.bool(false),\n    helper: prop.string(),\n    label: prop.string(),\n    'max-files': prop.number(0),\n    'max-size': prop.number(0),\n    multiple: prop.bool(false),\n    name: prop.string(),\n    ref: prop.data<((el: HTMLInputElement | null) => void) | null>(),\n    required: prop.bool(false),\n    size: prop.string(),\n    upload: prop.data<FileUploadFn>(),\n  },\n  setup(props) {\n    const emit = useEmit<OreFileInputEvents>();\n\n    // ============================================\n    // State\n    // ============================================\n\n    const isDragging = signal(false);\n    // Set while a \"Replace\" action is waiting for the (shared) native file input's next\n    // `change` — routes that selection into `queue.replaceFile()` instead of `queue.addFiles()`.\n    const replaceTarget = signal<File | null>(null);\n\n    const isDisabled = computed(() => Boolean(props.disabled.value));\n    const maxFilesLimit = computed(() => props['max-files'].value ?? 0);\n    const maxSizeLimit = computed(() => props['max-size'].value ?? 0);\n\n    // File selection + the opt-in upload lifecycle (progress, retry, replace, per-file\n    // isolation) live in `createFileQueue` — see file-input-upload.ts for why they're one unit.\n    const queue = createFileQueue({\n      accept: props.accept,\n      disabled: isDisabled,\n      maxFiles: maxFilesLimit,\n      maxSize: maxSizeLimit,\n      multiple: computed(() => Boolean(props.multiple.value)),\n      onChange: (changedFiles, originalEvent) =>\n        emit('change', { files: changedFiles, originalEvent, value: changedFiles }),\n      onRemove: (file, remainingFiles, originalEvent) =>\n        emit('remove', { file, files: remainingFiles, originalEvent, value: remainingFiles }),\n      onUploadError: (file, error) => emit('upload-error', { error, file }),\n      onUploadProgress: (file, loaded, total) => emit('upload-progress', { file, loaded, total }),\n      onUploadSuccess: (file) => emit('upload-success', { file }),\n      upload: computed(() => props.upload.value ?? undefined),\n    });\n\n    onCleanup(() => queue.dispose());\n\n    // ============================================\n    // Form Integration\n    // ============================================\n\n    useField({\n      disabled: isDisabled,\n      toFormValue: (fi: File[]) => {\n        if (fi.length === 0) return null;\n\n        const name = props.name.value || 'file';\n        const fd = new FormData();\n\n        for (const file of fi) fd.append(name, file);\n\n        return fd;\n      },\n      value: queue.files,\n    });\n\n    // Sync host attributes for CSS selectors\n    const isInvalid = computed(() => Boolean(props.error.value));\n\n    bind({\n      attr: {\n        'drag-over': () => (isDragging.value ? true : undefined),\n        invalid: () => (isInvalid.value ? true : undefined),\n        size: props.size,\n      },\n    });\n\n    // ============================================\n    // IDs\n    // ============================================\n    const fileInputId = createStableId('file-input');\n    const labelId = `label-${fileInputId}`;\n    const helperId = `helper-${fileInputId}`;\n    const errorId = `error-${fileInputId}`;\n\n    // ============================================\n    // Refs\n    // ============================================\n    const dropzoneRef = ref<HTMLDivElement>();\n    const inputRef = ref<HTMLInputElement>();\n    const hintText = computed(() => {\n      const parts: string[] = [];\n\n      if (props.accept.value) {\n        parts.push(\n          props.accept.value\n            .split(',')\n            .map((s: string) => s.trim())\n            .join(', '),\n        );\n      }\n\n      const maxSize = maxSizeLimit.value;\n\n      if (maxSize > 0) parts.push(`max ${formatBytes(maxSize)}`);\n\n      const maxFiles = maxFilesLimit.value;\n\n      if (maxFiles > 0) parts.push(`up to ${maxFiles} file${maxFiles !== 1 ? 's' : ''}`);\n\n      return parts.join(' · ');\n    });\n\n    // ============================================\n    // Replace (\"swap this one file\" — see file-input-upload.ts's `replaceFile`)\n    // ============================================\n    function beginReplace(file: File): void {\n      replaceTarget.value = file;\n      inputRef.value?.click();\n    }\n\n    // ============================================\n    // Gallery Preview URLs\n    // ============================================\n    // Object URLs are created lazily (only while `gallery` is enabled) and revoked as soon\n    // as their file is no longer selected, plus unconditionally on disconnect — otherwise\n    // each preview leaks its backing blob for the life of the page.\n    const previewUrls = new Map<File, string>();\n\n    function getPreviewUrl(file: File): string {\n      let url = previewUrls.get(file);\n\n      if (!url) {\n        url = URL.createObjectURL(file);\n        previewUrls.set(file, url);\n      }\n\n      return url;\n    }\n\n    function revokeStalePreviewUrls(activeFiles: File[]): void {\n      const keep = new Set(activeFiles);\n\n      for (const [file, url] of previewUrls) {\n        if (!keep.has(file)) {\n          URL.revokeObjectURL(url);\n          previewUrls.delete(file);\n        }\n      }\n    }\n\n    watch(queue.files, revokeStalePreviewUrls);\n\n    onCleanup(() => {\n      for (const url of previewUrls.values()) URL.revokeObjectURL(url);\n\n      previewUrls.clear();\n    });\n\n    // ============================================\n    // Mount\n    // ============================================\n    // ============================================\n    // Template\n    // ============================================\n    onElement(inputRef, (inp) => bindRefCallback(props.ref, inp));\n\n    onMounted(() => {\n      const inp = inputRef.value!;\n      const dz = dropzoneRef.value!;\n      let skipNextClick = false;\n      const pressControl = createInteraction({\n        disabled: isDisabled,\n        onPress: () => {\n          inp.click();\n        },\n      });\n\n      // Native input → add files, or — if a \"Replace\" action opened the picker — swap the one\n      // file it targeted instead of appending a new entry.\n      onEvent(inp, 'change', (e: Event) => {\n        const input = e.target as HTMLInputElement;\n        const target = replaceTarget.value;\n\n        replaceTarget.value = null;\n\n        if (target && input.files?.[0]) queue.replaceFile(target, input.files[0], e);\n        else if (input.files?.length) queue.addFiles(Array.from(input.files), e);\n\n        input.value = ''; // reset so the same file triggers change again\n      });\n      // Click dropzone → open file picker\n      onEvent(dz, 'click', (e: MouseEvent) => {\n        if (e.target === inp) return;\n\n        if (skipNextClick) {\n          skipNextClick = false;\n\n          return;\n        }\n\n        if (!isDisabled.value) inp.click();\n      });\n      // Keyboard: Enter / Space → open picker\n      onEvent(dz, 'keydown', (e: KeyboardEvent) => {\n        skipNextClick = pressControl.handleKeydown(e) && e.key === 'Enter';\n      });\n\n      // `createDropZone` has no way to update `disabled` after creation — recreate the zone\n      // whenever the prop changes instead of capturing a stale snapshot from this one `onMounted`\n      // run. `watch`'s own returned cleanup (not a second `onCleanup`) disposes the current zone\n      // both on the next toggle and on final teardown.\n      watch(\n        isDisabled,\n        (disabled) => {\n          const dropZone = createDropZone({\n            disabled,\n            element: dz,\n            onDrop: (droppedFiles) => queue.addFiles(droppedFiles),\n            onHoverChange: (hovered) => {\n              isDragging.value = hovered;\n            },\n          });\n\n          return () => dropZone.dispose();\n        },\n        { immediate: true },\n      );\n    });\n\n    return html`\n      <div class=\"file-input-wrapper\" part=\"wrapper\">\n        <label class=\"label-outside\" id=\"${labelId}\" part=\"label\" ?hidden=${() => !props.label.value}>\n          ${props.label}\n        </label>\n        <div\n          class=\"dropzone\"\n          part=\"dropzone\"\n          ref=${dropzoneRef}\n          role=\"button\"\n          tabindex=\"${() => (isDisabled.value ? '-1' : '0')}\"\n          aria-disabled=\"${() => String(isDisabled.value)}\"\n          aria-label=\"${() => (!props.label.value ? 'File upload drop zone' : null)}\"\n          aria-labelledby=\"${() => (props.label.value ? labelId : null)}\"\n          aria-describedby=\"${helperId}\">\n          <input\n            type=\"file\"\n            ref=${inputRef}\n            part=\"input\"\n            id=\"${fileInputId}\"\n            accept=\"${props.accept}\"\n            ?multiple=\"${props.multiple}\"\n            ?required=\"${props.required}\"\n            ?disabled=\"${isDisabled}\"\n            name=\"${props.name}\"\n            hidden\n            inert\n            tabindex=\"-1\" />\n          <div class=\"dropzone-content\">\n            <span class=\"dropzone-icon\" aria-hidden=\"true\" data-status=\"${() => (isInvalid.value ? 'error' : null)}\">\n              ${() =>\n                isInvalid.value\n                  ? html`\n                      <ore-icon name=\"alert-circle\" size=\"36\" stroke-width=\"1.5\" aria-hidden=\"true\"></ore-icon>\n                    `\n                  : html`\n                      <ore-icon name=\"upload\" size=\"36\" stroke-width=\"1.5\" aria-hidden=\"true\"></ore-icon>\n                    `}\n            </span>\n            <!-- Signal 01: the copy itself shifts on drag-entry (not just border/glow) — a\n                 static \"Drop files here\" during an active drag reads as if the drop target\n                 hasn't noticed the file yet. -->\n            ${when(\n              () => isDragging.value,\n              () => html`\n                <span class=\"dropzone-title dropzone-title-active\">Release to upload</span>\n              `,\n            )}\n            ${when(\n              () => !isDragging.value,\n              () => html`\n                <span class=\"dropzone-title\">\n                  Drop files here or\n                  <u>click to browse</u>\n                </span>\n              `,\n            )}\n            <span class=\"dropzone-hint\" ?hidden=${() => !hintText.value}>${hintText}</span>\n          </div>\n        </div>\n        <ul\n          class=\"${() => (props.gallery.value ? 'file-grid' : 'file-list')}\"\n          part=\"${() => (props.gallery.value ? 'gallery' : null)}\"\n          role=\"list\"\n          aria-label=\"Selected files\"\n          ?hidden=${() => queue.files.value.length === 0}>\n          ${() =>\n            queue.files.value.map((file: File) =>\n              props.gallery.value\n                ? html`\n                    <li class=\"file-card\" data-status=${() => queue.fileState(file).status}>\n                      <span class=\"file-thumb-frame\">\n                        ${\n                          // Decorative: the file name is already announced via the visible\n                          // `.file-card-name` caption below — repeating it as `alt` text would\n                          // duplicate it (and often trips redundant-alt checks, since real\n                          // filenames commonly contain words like \"photo\" or \"image\").\n                          isImageFile(file)\n                            ? // Object URLs use the `blob:` scheme, which ore's attribute-level\n                              // XSS guard blocks unconditionally on `src` (and other\n                              // URL-accepting attributes) — set it as a DOM property via `ref`\n                              // instead, bypassing that string-based check. Safe here: the value\n                              // comes from `URL.createObjectURL(file)` on a real `File` object we\n                              // control, never from untrusted text.\n                              html`\n                                <img\n                                  class=\"file-thumb\"\n                                  alt=\"\"\n                                  ref=\"${(el: HTMLImageElement | null) => {\n                                    if (el) el.src = getPreviewUrl(file);\n                                  }}\" />\n                              `\n                            : html`\n                                <span class=\"file-thumb file-thumb-generic\" aria-hidden=\"true\">\n                                  <ore-icon name=\"file\" size=\"28\" stroke-width=\"1.5\" aria-hidden=\"true\"></ore-icon>\n                                </span>\n                              `\n                        }\n                        ${when(\n                          () => queue.fileState(file).status === 'success',\n                          () => html`\n                            <span class=\"file-status-badge file-status-badge-success\" aria-hidden=\"true\">\n                              <ore-icon name=\"check\" size=\"11\" stroke-width=\"3\" aria-hidden=\"true\"></ore-icon>\n                            </span>\n                          `,\n                        )}\n                        ${when(\n                          () => queue.fileState(file).status === 'error',\n                          () => html`\n                            <span class=\"file-status-badge file-status-badge-error\" aria-hidden=\"true\">\n                              <ore-icon name=\"alert-circle\" size=\"12\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n                            </span>\n                          `,\n                        )}\n                        <span class=\"file-card-actions\">\n                          ${when(\n                            () => queue.fileState(file).status === 'error',\n                            () => html`\n                              <button\n                                class=\"file-card-action\"\n                                type=\"button\"\n                                aria-label=\"${`Retry uploading ${file.name}`}\"\n                                @click=${() => queue.retryUpload(file)}>\n                                <ore-icon name=\"refresh-cw\" size=\"12\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n                              </button>\n                            `,\n                          )}\n                          ${when(\n                            () =>\n                              queue.fileState(file).status === 'success' &&\n                              Boolean(props.multiple.value) &&\n                              Boolean(props.upload.value),\n                            () => html`\n                              <button\n                                class=\"file-card-action\"\n                                type=\"button\"\n                                aria-label=\"${`Replace ${file.name}`}\"\n                                @click=${() => beginReplace(file)}>\n                                <ore-icon name=\"upload\" size=\"12\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n                              </button>\n                            `,\n                          )}\n                          <button\n                            class=\"file-card-action file-card-remove\"\n                            type=\"button\"\n                            aria-label=\"${`Remove ${file.name}`}\"\n                            @click=${(e: Event) => queue.removeFile(file, e)}>\n                            <ore-icon name=\"x\" size=\"12\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n                          </button>\n                        </span>\n                      </span>\n                      <span class=\"file-card-name\" title=\"${file.name}\">${file.name}</span>\n                      ${when(\n                        () => queue.fileState(file).status === 'uploading',\n                        () => html`\n                          <ore-progress\n                            type=\"linear\"\n                            size=\"sm\"\n                            value=${() => queue.uploadPercent(file)}\n                            label=${() => `${queue.uploadPercent(file)}%`}></ore-progress>\n                          <span class=\"file-progress-meta\">${() => queue.uploadMetaText(file)}</span>\n                        `,\n                      )}\n                      ${when(\n                        () => queue.fileState(file).status === 'error',\n                        () => html`\n                          <span class=\"file-error-text\">${() => queue.fileState(file).error}</span>\n                        `,\n                      )}\n                    </li>\n                  `\n                : html`\n                    <li class=\"file-item\" data-status=${() => queue.fileState(file).status}>\n                      <span class=\"file-icon\" aria-hidden=\"true\">\n                        <ore-icon\n                          name=${() => queue.statusIconName(file)}\n                          size=\"18\"\n                          stroke-width=\"1.75\"\n                          aria-hidden=\"true\"></ore-icon>\n                      </span>\n                      <span class=\"file-meta\">\n                        <span class=\"file-name\" title=\"${file.name}\">${file.name}</span>\n                        ${when(\n                          () => queue.fileState(file).status === 'uploading',\n                          () => html`\n                            <ore-progress\n                              type=\"linear\"\n                              size=\"sm\"\n                              value=${() => queue.uploadPercent(file)}\n                              label=${() => `${queue.uploadPercent(file)}%`}></ore-progress>\n                            <span class=\"file-progress-meta\">${() => queue.uploadMetaText(file)}</span>\n                          `,\n                        )}\n                        ${when(\n                          () => queue.fileState(file).status === 'error',\n                          () => html`\n                            <span class=\"file-error-text\">${() => queue.fileState(file).error}</span>\n                          `,\n                        )}\n                        ${when(\n                          () => queue.fileState(file).status === 'idle' || queue.fileState(file).status === 'success',\n                          () => html`\n                            <span class=\"file-size\">${formatBytes(file.size)}</span>\n                          `,\n                        )}\n                      </span>\n                      <span class=\"file-actions\">\n                        ${when(\n                          () => queue.fileState(file).status === 'error',\n                          () => html`\n                            <button\n                              class=\"file-action\"\n                              type=\"button\"\n                              aria-label=\"${`Retry uploading ${file.name}`}\"\n                              @click=${() => queue.retryUpload(file)}>\n                              <ore-icon name=\"refresh-cw\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n                            </button>\n                          `,\n                        )}\n                        ${when(\n                          () =>\n                            queue.fileState(file).status === 'success' &&\n                            Boolean(props.multiple.value) &&\n                            Boolean(props.upload.value),\n                          () => html`\n                            <button\n                              class=\"file-action\"\n                              type=\"button\"\n                              aria-label=\"${`Replace ${file.name}`}\"\n                              @click=${() => beginReplace(file)}>\n                              <ore-icon name=\"upload\" size=\"14\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n                            </button>\n                          `,\n                        )}\n                        <button\n                          class=\"file-remove\"\n                          type=\"button\"\n                          aria-label=\"${`Remove ${file.name}`}\"\n                          @click=${(e: Event) => queue.removeFile(file, e)}>\n                          <ore-icon name=\"x\" size=\"12\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n                        </button>\n                      </span>\n                    </li>\n                  `,\n            )}\n        </ul>\n        <div class=\"helper-text\" id=\"${helperId}\" part=\"helper\" ?hidden=${() => isInvalid.value || !props.helper.value}>\n          ${props.helper}\n        </div>\n        <div\n          class=\"helper-text helper-text-error\"\n          id=\"${errorId}\"\n          role=\"alert\"\n          part=\"error\"\n          ?hidden=${() => !isInvalid.value}>\n          ${() => props.error.value ?? ''}\n        </div>\n      </div>\n    `;\n  },\n  shadow: { delegatesFocus: true },\n  styles: [\n    colorThemeMixin,\n    coarsePointerMixin,\n    reducedMotionMixin,\n    roundedVariantMixin,\n    disabledLoadingMixin,\n    sizeVariantMixin(FILE_INPUT_SIZE_PRESET),\n    forcedColorsFocusMixin('.dropzone'),\n    componentStyles,\n  ],\n});\n","/*\n * Unlike the first version of this component, the field here is a plain `<textarea>` owned\n * directly by this stylesheet — not a nested `ore-textarea` with its own chrome suppressed via\n * `::part()` overrides. There is exactly one implementation of \"what the field looks like\" to\n * maintain (this file), not two.\n */\n@layer refine.base {\n  :host {\n    /* --_bg/--_border-color are set per-variant in @layer refine.variants below (every host\n       matches exactly one variant rule, including the implicit \"no attribute\" default) — no\n       fallback needed here. --_padding/--_font-size/--_gap are set per-size by\n       sizeVariantMixin(MESSAGE_COMPOSER_SIZE_PRESET) (see message-composer.ts's `styles`); this\n       is the `--message-composer-padding` public-override fallback for the \"md\" tier, matching\n       the same pattern `ore-textarea` uses for `--textarea-padding`. */\n    --_radius: var(--message-composer-radius, var(--rounded-2xl));\n    --_padding: var(--message-composer-padding, var(--size-3));\n    --_surface: var(--_bg);\n\n    display: flex;\n    width: fit-content;\n    max-width: 100%;\n  }\n\n  :host([fullwidth]) {\n    width: 100%;\n  }\n\n  .composer {\n    position: relative;\n    display: flex;\n    flex-direction: column;\n    gap: var(--message-composer-gap, var(--_gap));\n    width: 100%;\n    padding: var(--_padding);\n    background: var(--_surface);\n    border: var(--border) solid var(--_border-color);\n    border-radius: var(--_radius);\n    box-shadow: var(--shadow-2xs);\n    transition:\n      background var(--transition-fast),\n      border-color var(--transition-fast),\n      box-shadow var(--transition-fast);\n  }\n\n  /* `flat` excluded — it gets its own theme-tinted hover/focus recipe below instead of the\n     plain canvas-background one every other variant shares (mirrors `ore-textarea`). */\n  :host(:not([disabled], [variant='bordered'], [variant='flat'])) .composer:hover {\n    border-color: var(--color-contrast-400);\n  }\n\n  :host([error]:not([error=''])) .composer {\n    border-color: var(--color-error);\n  }\n\n  :host([success]) .composer {\n    border-color: var(--color-success);\n  }\n\n  /* ========================================\n       Status Icon (error/success — never color alone)\n       ======================================== */\n\n  .status-icon {\n    position: absolute;\n    inset-block-start: var(--_padding);\n    inset-inline-end: var(--_padding);\n    display: none;\n    align-items: center;\n    justify-content: center;\n    width: var(--size-5);\n    height: var(--size-5);\n  }\n\n  :host([error]:not([error=''])) .status-icon,\n  :host([success]) .status-icon {\n    display: flex;\n  }\n\n  .status-icon[data-status='error'] {\n    color: var(--color-error);\n  }\n\n  .status-icon[data-status='success'] {\n    color: var(--color-success);\n  }\n\n  .field {\n    box-sizing: border-box;\n    width: 100%;\n    min-width: 0;\n\n    /* Floor so an inline `height` from auto-resize (JS, set on `<textarea>` directly — see\n       auto-resize.ts) can never visually collapse the field below one line, e.g. before the\n       first `scrollHeight` read has actually happened. `ore-textarea` has the equivalent\n       `--_min-height` for the same reason. */\n    min-height: var(--message-composer-min-height, 1lh);\n    padding: 0;\n    font: inherit;\n    font-size: var(--_font-size);\n    line-height: var(--leading-relaxed);\n    color: var(--text-color-body);\n    resize: none;\n    outline: none;\n    background: transparent;\n    border: none;\n  }\n\n  .field::placeholder {\n    color: var(--message-composer-placeholder-color, var(--color-contrast-500));\n  }\n\n  .helper-text[hidden] {\n    display: none;\n  }\n\n  .helper-text {\n    padding-inline: 2px;\n    font-size: var(--text-xs);\n    line-height: var(--leading-tight);\n    color: color-mix(in oklch, var(--color-contrast-500) 80%, var(--color-canvas));\n  }\n\n  .counter {\n    align-self: flex-end;\n    padding-inline: 2px;\n    font-size: var(--text-xs);\n    line-height: var(--leading-tight);\n    color: var(--color-contrast-400);\n  }\n\n  .counter.near-limit {\n    color: var(--color-warning);\n  }\n\n  .counter.at-limit {\n    color: var(--color-error);\n  }\n\n  .toolbar {\n    display: flex;\n    gap: var(--message-composer-gap, var(--_gap));\n    align-items: center;\n    justify-content: space-between;\n  }\n\n  .toolbar-start,\n  .toolbar-end {\n    display: flex;\n    gap: var(--message-composer-gap, var(--_gap));\n    align-items: center;\n    min-width: 0;\n  }\n\n  .send-btn {\n    flex-shrink: 0;\n  }\n}\n\n/*\n * The solid/flat/bordered/outline/ghost variant switch (previously `@layer refine.variants`\n * here) now lives in `fieldVariantMixin({ container: '.composer', text: '.field', tokenPrefix:\n * 'message-composer' })` in `message-composer.ts`'s `styles` array — shared with `ore-input`/\n * `ore-textarea` instead of hand-duplicated across all three (see the mixin's own doc comment\n * for what it covers and why).\n */\n\n/*\n * Focus/error/success `box-shadow` on `.composer` — kept in `refine.variants` (alongside\n * `fieldVariantMixin`'s rest-state `box-shadow` for solid/outline/ghost) rather than\n * `refine.base`, so normal specificity decides the winner. Cascade layers beat specificity\n * outright, so a `refine.base` box-shadow here always lost to every variant's unconditional\n * rest-state `box-shadow`, focused/error/success or not — the same bug class fixed for\n * `ore-otp-input`'s focus ring.\n */\n@layer refine.variants {\n  :host(:not([disabled], [variant='flat'])) .composer:focus-within {\n    --_surface: var(--color-canvas);\n\n    border-color: var(--_theme-focus);\n    box-shadow: var(--_theme-shadow);\n  }\n\n  :host([error]:not([error=''])) .composer:focus-within {\n    border-color: var(--color-error);\n    box-shadow: var(--color-error-focus-shadow);\n  }\n\n  :host([success]) .composer:focus-within {\n    border-color: var(--color-success);\n    box-shadow: var(--color-success-focus-shadow);\n  }\n}\n\n/* ========================================\n     Disabled / Loading overrides — intentionally unlayered\n     ======================================== */\n\n/*\n * The shared `disabledLoadingMixin` treats `[disabled]` and `[loading]` identically: bare,\n * unlayered `opacity: 0.5` plus `pointer-events: none` on every direct child (this component's\n * template root is a single `.composer` div, so that means the whole card). Cascade layers always\n * lose to unlayered rules regardless of source order or specificity, so these overrides have to\n * stay unlayered too, to actually win — see `ore-input`'s `input.css` for the same pattern.\n *\n * `loading` here documents itself as \"blocks further sends... without disabling editing\" (see\n * the `loading` prop's own doc comment) — the send button already disables itself via\n * `composer.canSend`. Inheriting the generic mixin's `[loading]` treatment silently broke that:\n * `pointer-events: none` on `.composer` cascades (it's an inherited property) to the `<textarea>`\n * itself, blocking typing during every in-flight send. `:not([disabled])` keeps a real `disabled`\n * still fully blocking, exactly like every other field.\n */\n:host([loading]:not([disabled])) {\n  opacity: 1;\n}\n\n:host([loading]:not([disabled])) .composer {\n  pointer-events: auto;\n}\n\n:host([disabled]) {\n  opacity: 1;\n}\n\n:host([disabled]) .composer {\n  background: var(--color-contrast-100);\n  border-color: var(--color-contrast-200);\n  box-shadow: none;\n}\n\n:host([disabled]) .field {\n  color: var(--color-contrast-400);\n}\n\n:host([disabled]) .field::placeholder {\n  color: var(--color-contrast-300);\n}\n","import {\n  bind,\n  define,\n  getHost,\n  html,\n  live,\n  onCleanup,\n  onElement,\n  prop,\n  ref,\n  useEmit,\n  useField,\n  useSlots,\n} from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport {\n  bindRefCallback,\n  createAutoResize,\n  createComposerControl,\n  createTextField,\n  lifecycleSignal,\n  type SendShortcut,\n} from '../../core';\nimport {\n  disablableBundle,\n  loadableBundle,\n  MESSAGE_COMPOSER_SIZE_PRESET,\n  sizableBundle,\n  themableBundle,\n} from '../../shared';\nimport {\n  coarsePointerMixin,\n  colorThemeMixin,\n  disabledLoadingMixin,\n  fieldVariantMixin,\n  forcedColorsFocusMixin,\n  forcedColorsMixin,\n  reducedMotionMixin,\n  sizeVariantMixin,\n} from '../../styles';\nimport type { ComponentSize, ThemeColor, VisualVariant } from '../../types';\nimport { errorAttr } from '../shared/field-binding';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport { renderFieldStatusRegion, renderStatusIcon } from '../shared/templates';\nimport '../../content/icon/icon';\nimport '../button/button';\nimport componentStyles from './message-composer.css?inline';\n\nexport type { SendShortcut } from '../../core';\n\nconst DEFAULT_SEND_LABEL = 'Send message';\nconst SEND_ICON = 'arrow-up';\n\n/** Events emitted by the message composer */\nexport type OreMessageComposerEvents = {\n  input: InputEvent;\n  /**\n   * Fired for a send attempt (the resolved `send-shortcut` or the send button) while the\n   * composer isn't blank/disabled/loading. Cancelable — call `preventDefault()` to keep the\n   * current text in the field instead of the default clear + refocus.\n   */\n  send: { originalEvent: KeyboardEvent | MouseEvent; value: string };\n};\n\n/** Message composer properties */\nexport type OreMessageComposerProps = {\n  /** Clear the value and refocus after a non-cancelled `send` (default `true`) */\n  'clear-on-send'?: boolean;\n  /** Theme color (card focus ring + default send button color) */\n  color?: ThemeColor;\n  /** Disable the whole composer (field, slots, and send action) */\n  disabled?: boolean;\n  /** Error message shown below the field */\n  error?: string;\n  /** Stretch the composer to the full width of its container */\n  fullwidth?: boolean;\n  /** Helper text shown below the field */\n  helper?: string;\n  /** Accessible name for the field — never rendered visually, only as `aria-label` */\n  label?: string;\n  /** Blocks further sends (e.g. a send is already in flight) without disabling editing */\n  loading?: boolean;\n  /** Maximum character count; shows a counter */\n  maxlength?: number;\n  /** Form field name */\n  name?: string;\n  /** Placeholder text */\n  placeholder?: string;\n  /** Make the field read-only */\n  readonly?: boolean;\n  /**\n   * JS-only callback fired with the inner `<textarea>` element when it mounts, and with\n   * `null` when it unmounts. Set as a JS property: `composer.ref = (el) => { ... }`.\n   */\n  ref?: ((el: HTMLTextAreaElement | null) => void) | null;\n  /** Require a non-blank value for native form validation */\n  required?: boolean;\n  /** Number of visible rows before auto-resize grows the field */\n  rows?: number;\n  /** Lucide icon name for the default send button (default `'arrow-up'`) */\n  'send-icon'?: string;\n  /** Accessible label for the send button (default `'Send message'`) */\n  'send-label'?: string;\n  /** Keyboard shortcut that sends: 'enter' (Shift+Enter for a newline) or 'mod+enter' (Enter always inserts a newline; Ctrl/Cmd+Enter sends) */\n  'send-shortcut'?: SendShortcut;\n  /** Component size */\n  size?: ComponentSize;\n  /**\n   * Shows an inline green check icon inside the field to confirm the value has\n   * passed validation. Ignored while `error` is set — an error always wins.\n   */\n  success?: boolean;\n  /** Current text value */\n  value?: string;\n  /** Visual variant of the card — same variant set as `ore-textarea`, applied to the card. */\n  variant?: Exclude<VisualVariant, 'frost' | 'text'>;\n};\n\n/**\n * A message/comment composer — a card with an auto-resizing field on top and a toolbar row\n * below it, built directly on the same core primitives as `ore-textarea` (`createTextField`,\n * `createAutoResize`) rather than composing `ore-textarea` itself. Nesting a fully-styled sibling\n * component and suppressing most of its chrome (as an earlier version of this component did) is\n * a leaky composition — this owns its single `<textarea>` outright, so there's exactly one\n * implementation of the field's appearance to reason about, not two fighting each other.\n *\n * Handles the send gesture (Enter to send, Shift+Enter for a newline, or a Ctrl/Cmd+Enter\n * alternative), IME-safe composition, and clear-and-refocus after sending.\n *\n * @element ore-message-composer\n *\n * @attr {string} value - Current text value\n * @attr {string} placeholder - Placeholder text\n * @attr {string} label - Accessible name for the field (not rendered visually)\n * @attr {string} name - Form field name\n * @attr {string} helper - Helper text shown below the field\n * @attr {string} error - Error message shown below the field\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {boolean} disabled - Disable the whole composer\n * @attr {boolean} readonly - Read-only mode\n * @attr {boolean} required - Require a non-blank value for native form validation\n * @attr {boolean} loading - Blocks further sends without disabling editing\n * @attr {number} maxlength - Max character count; shows a counter\n * @attr {number} rows - Visible rows before auto-resize grows the field (default 1)\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant of the card: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {boolean} fullwidth - Stretch to the full width of the container\n * @attr {string} send-icon - Lucide icon name for the default send button (default 'arrow-up')\n * @attr {string} send-label - Accessible label for the send button (default 'Send message')\n * @attr {string} send-shortcut - 'enter' (default) | 'mod+enter'\n * @attr {boolean} clear-on-send - Clear the value and refocus after a non-cancelled send (default true)\n *\n * @fires input - Fired on every keystroke. detail: { value, originalEvent }\n * @fires send - Fired on a send attempt. Cancelable. detail: { value, originalEvent }\n *\n * @slot prefix - Content at the start of the toolbar row (e.g. an attach menu)\n * @slot suffix - Content at the end of the toolbar row, before the send button (e.g. a model picker)\n * @slot send - Replaces the default send button entirely — the only supported way to customize it\n *\n * @cssprop --message-composer-bg - Card background color\n * @cssprop --message-composer-border-color - Card border color\n * @cssprop --message-composer-radius - Card border radius\n * @cssprop --message-composer-padding - Card inner padding\n * @cssprop --message-composer-gap - Gap between the field/toolbar rows and between toolbar items\n * @cssprop --message-composer-placeholder-color - Field placeholder text color\n * @cssprop --message-composer-min-height - Minimum field height (default one line)\n * @cssprop --message-composer-hover-bg - Card background on hover (flat/ghost variants)\n * @cssprop --message-composer-hover-border-color - Card border on hover (flat/bordered variants)\n * @cssprop --message-composer-focus-bg - Card background when focused (flat variant)\n * @cssprop --message-composer-focus-border-color - Card border when focused (flat variant)\n *\n * @part composer - Root card container\n * @part field - The native `<textarea>` element\n * @part status-icon - The inline error/success icon shown inside the field\n * @part helper - Helper text element\n * @part error - Error text element (`role=\"alert\"`)\n * @part toolbar - Toolbar row below the field\n * @part toolbar-start - Toolbar group holding the `prefix` slot\n * @part toolbar-end - Toolbar group holding the `suffix` slot and the send button\n * @part send-button - The default send button (absent when the `send` slot is used)\n *\n * @example\n * ```html\n * <ore-message-composer placeholder=\"Message…\" send-shortcut=\"mod+enter\"></ore-message-composer>\n * ```\n */\nexport const MESSAGE_COMPOSER_TAG = 'ore-message-composer' as const;\ndefine<OreMessageComposerProps>(MESSAGE_COMPOSER_TAG, {\n  formAssociated: true,\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...disablableBundle,\n    ...loadableBundle,\n    'clear-on-send': prop.bool(true),\n    error: prop.string(),\n    fullwidth: prop.bool(false),\n    helper: prop.string(),\n    label: prop.string(),\n    maxlength: prop.json(undefined as number | undefined),\n    name: prop.string(),\n    placeholder: prop.string(),\n    readonly: prop.bool(false),\n    ref: prop.data<((el: HTMLTextAreaElement | null) => void) | null>(),\n    required: prop.bool(false),\n    rows: prop.json(undefined as number | undefined),\n    'send-icon': prop.string(),\n    'send-label': prop.string(),\n    'send-shortcut': prop.oneOf(['enter', 'mod+enter'] as const, 'enter'),\n    success: prop.bool(false),\n    value: prop.string(),\n    variant: prop.string<Exclude<VisualVariant, 'frost' | 'text'>>(),\n  },\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreMessageComposerEvents>();\n    const slots = useSlots<'prefix' | 'send' | 'suffix'>();\n\n    const isDisabled = props.disabled;\n\n    const abortSignal = lifecycleSignal(onCleanup);\n    const textareaRef = ref<HTMLTextAreaElement>();\n    const autoResize = createAutoResize();\n\n    const tf = createTextField({\n      disabled: isDisabled,\n      error: props.error,\n      helper: props.helper,\n      maxLength: props.maxlength,\n      onInput: (_event, value) => {\n        setFieldValue(el, value);\n        dispatchNativeFieldEvent(el, 'input');\n      },\n      prefix: 'composer',\n      readonly: props.readonly,\n      required: props.required,\n      signal: abortSignal,\n      value: props.value,\n    });\n\n    defineFieldValue(\n      el,\n      () => tf.value.value,\n      (value) => {\n        tf.value.value = value;\n      },\n    );\n\n    // Directly form-associated now that the field is owned here rather than borrowed from a\n    // nested `ore-textarea` (which previously registered with the ancestor `<form>` on this\n    // component's behalf).\n    tf.attachFormField(\n      useField<string>({\n        disabled: tf.disabled,\n        onReset: () => {\n          tf.reset();\n          autoResize.recompute();\n        },\n        toFormValue: (v) => v,\n        validationMessage: tf.validationMessage,\n        validity: tf.validity,\n        value: tf.value,\n      }),\n    );\n\n    function attemptSend(event: KeyboardEvent | MouseEvent): void {\n      const notPrevented = emit('send', { originalEvent: event, value: tf.value.value.trim() });\n\n      // `preventDefault()` on `send` means \"keep the current text — skip the default clear\n      // + refocus\" (see the event's own doc comment): both halves of that default are gated on\n      // the same condition, not just the clear.\n      if (notPrevented && props['clear-on-send'].value !== false) {\n        tf.clear();\n        autoResize.recompute();\n        textareaRef.value?.focus();\n      }\n    }\n\n    const composer = createComposerControl({\n      disabled: isDisabled,\n      loading: computed(() => Boolean(props.loading.value)),\n      onSend: attemptSend,\n      sendShortcut: props['send-shortcut'],\n      value: tf.value,\n    });\n\n    onElement(textareaRef, (textareaEl) => {\n      const unwireField = tf.wire(textareaEl);\n      const unwireAutoResize = autoResize.wire(textareaEl);\n      const unwireRef = bindRefCallback(props.ref, textareaEl);\n      const handleKeydown = (e: KeyboardEvent) => composer.handleKeydown(e);\n\n      textareaEl.addEventListener('keydown', handleKeydown);\n\n      return () => {\n        textareaEl.removeEventListener('keydown', handleKeydown);\n        unwireField();\n        unwireAutoResize();\n        unwireRef();\n      };\n    });\n\n    bind({\n      attr: {\n        error: errorAttr(tf.errorText),\n        size: props.size,\n        // Reflects `success` only once `error` is confirmed empty — keeps the two host\n        // attributes mutually exclusive even if a consumer sets both props at once.\n        success: () => (props.success.value && !tf.errorText.value ? true : undefined),\n        variant: props.variant,\n      },\n    });\n\n    return html`\n      <div class=\"composer\" part=\"composer\">\n        <textarea\n          class=\"field\"\n          part=\"field\"\n          ref=\"${textareaRef}\"\n          rows=\"${() => props.rows.value ?? 1}\"\n          name=\"${() => props.name.value ?? ''}\"\n          placeholder=\"${() => props.placeholder.value ?? 'Message…'}\"\n          maxlength=\"${() => props.maxlength.value}\"\n          ?disabled=\"${isDisabled}\"\n          ?readonly=\"${() => Boolean(props.readonly.value)}\"\n          ?required=\"${() => Boolean(props.required.value)}\"\n          value=\"${live(tf.value)}\"\n          aria-label=\"${() => props.label.value || 'Message'}\"\n          aria-keyshortcuts=\"${composer.keyShortcutsHint}\"\n          aria-describedby=\"${tf.ariaDescribedBy}\"\n          aria-errormessage=\"${tf.ariaErrorMessage}\"\n          aria-invalid=\"${tf.ariaInvalid}\"></textarea>\n        ${renderStatusIcon(tf.errorText)} ${renderFieldStatusRegion(tf)}\n        <div class=\"toolbar\" part=\"toolbar\">\n          <div class=\"toolbar-start\" part=\"toolbar-start\">\n            <slot name=\"prefix\"></slot>\n          </div>\n          <div class=\"toolbar-end\" part=\"toolbar-end\">\n            <slot name=\"suffix\"></slot>\n            <slot name=\"send\"></slot>\n            ${() =>\n              slots.has('send').value\n                ? ''\n                : html`\n                    <ore-button\n                      class=\"send-btn\"\n                      part=\"send-button\"\n                      type=\"button\"\n                      icon-only\n                      variant=\"solid\"\n                      color=\"${() => props.color.value || 'primary'}\"\n                      size=\"${props.size}\"\n                      label=\"${() => props['send-label'].value || DEFAULT_SEND_LABEL}\"\n                      ?loading=\"${() => Boolean(props.loading.value)}\"\n                      ?disabled=\"${() => !composer.canSend.value}\"\n                      @click=\"${(e: MouseEvent) => composer.send(e)}\">\n                      <ore-icon name=\"${() => props['send-icon'].value || SEND_ICON}\" size=\"16\"></ore-icon>\n                    </ore-button>\n                  `}\n          </div>\n        </div>\n      </div>\n    `;\n  },\n  shadow: { delegatesFocus: true },\n  styles: [\n    colorThemeMixin,\n    coarsePointerMixin,\n    reducedMotionMixin,\n    disabledLoadingMixin,\n    forcedColorsMixin,\n    forcedColorsFocusMixin('.field'),\n    sizeVariantMixin(MESSAGE_COMPOSER_SIZE_PRESET),\n    componentStyles,\n    // Must come after `componentStyles` — see `ore-input`'s identical ordering note for why\n    // (`@layer` precedence is fixed by which layer name is *first* referenced across this whole\n    // array; `componentStyles` establishes `refine.base`, which this mixin's `refine.variants`\n    // rules need to win over).\n    fieldVariantMixin({ container: '.composer', text: '.field', tokenPrefix: 'message-composer' }),\n  ],\n});\n","@layer refine.base {\n  /* No explicit `width` here, on purpose — matches every other field's own `:host` (`ore-input`,\n     `ore-select`, `ore-combobox`, `ore-date-picker`). A grid/flex item with `width: auto` (the\n     default) stretches to fill its track by default; the old `width: fit-content` here overrode\n     that default and forced this one field to shrink-wrap while every sibling field stretched to\n     match the column, e.g. in a 2-column form grid.\n     `min-width` is different: every field above sets the same `12rem` floor (each via its own\n     `--<field>-min-width` custom property) so that a row of mixed field types — this one included\n     — doesn't shrink-wrap to noticeably different widths purely because their *content* (a typed\n     number vs. a selected option's label vs. free text) happens to differ. */\n  :host {\n    display: inline-flex;\n    min-width: var(--number-input-min-width, 12rem);\n  }\n\n  /* Explicit opt-in still forces full width outside a stretching grid/flex context — same\n     convention as ore-input's own :host([fullwidth]). */\n  :host([fullwidth]) {\n    width: 100%;\n  }\n\n  /* The inner `ore-input` (class=\"field\", see number-input.ts) is a flex item of this `:host`'s\n     own `inline-flex` box — without `flex: 1` it only ever grows to its own `min-width` (12rem)\n     and no further, leaving this component visibly narrower than its host once the host itself\n     stretches to fill a wider grid/flex track (e.g. next to a full-width sibling field). `flex: 1`\n     lets it grow to match; its own `min-width` (inherited from `ore-input`'s `:host`) still holds\n     as the shrink floor, so this doesn't affect the min-width consistency across field types. */\n  .field {\n    flex: 1;\n  }\n\n  /* Centre the typed number inside the field */\n  .field::part(input) {\n    text-align: center;\n  }\n\n  /* Stepper buttons — slotted into ore-input's own prefix/suffix, so they render inside its\n     bordered box like its built-in clear/password-toggle buttons, not as separate controls. */\n  button[part='decrement-btn'],\n  button[part='increment-btn'] {\n    display: inline-flex;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    width: var(--size-6);\n    min-width: var(--size-6);\n    height: var(--size-6);\n    min-height: var(--size-6);\n    padding: 0;\n    color: var(--color-contrast-600);\n    cursor: pointer;\n    background: transparent;\n    border: none;\n    border-radius: var(--rounded-sm);\n    transition:\n      color var(--transition-fast),\n      background var(--transition-fast);\n  }\n\n  button[part='decrement-btn']:hover:not(:disabled),\n  button[part='increment-btn']:hover:not(:disabled) {\n    color: var(--color-contrast-900);\n    background: var(--color-contrast-150, var(--color-contrast-100));\n  }\n\n  button[part='decrement-btn']:active:not(:disabled),\n  button[part='increment-btn']:active:not(:disabled) {\n    background: var(--color-contrast-200);\n  }\n\n  button[part='decrement-btn']:disabled,\n  button[part='increment-btn']:disabled {\n    color: var(--color-contrast-300);\n    cursor: not-allowed;\n    background: transparent;\n  }\n\n  button[part='decrement-btn']:focus-visible,\n  button[part='increment-btn']:focus-visible {\n    outline: 2px solid var(--color-primary-500);\n    outline-offset: -2px;\n  }\n}\n\n/* ========================================\n     Disabled State — intentionally unlayered\n     ======================================== */\n\n/*\n * `disabledStateMixin` (passed directly in `styles:`, not via `fieldMixins`) dims\n * `:host([disabled])` with `opacity: 0.5` as bare, unlayered CSS. Cascade layers always lose to\n * unlayered rules regardless of source order or specificity, so overriding that from inside any\n * `@layer` block in this file would be a no-op — this has to stay unlayered too, to actually win.\n * See `ore-input`'s `input.css` for the same pattern.\n *\n * The visible surface here is entirely the inner `ore-input`'s own `.field` (already fixed to a\n * grayscale look, not opacity) plus these slotted stepper buttons (muted via `:disabled` above,\n * also not opacity) — so this host itself needs no compensating background/color, just dropping\n * the blanket opacity that would otherwise wash out both of those over again.\n */\n:host([disabled]) {\n  opacity: 1;\n}\n","import { clamp } from '@vielzeug/arsenal/math';\nimport { bind, define, getHost, html, onElement, prop, ref, watchEffect } from '@vielzeug/ore';\nimport { computed, watch as rippleWatch, signal } from '@vielzeug/ripple';\nimport { createSpinnerControl } from '../../core';\nimport type { ComponentSize, ThemeColor, VisualVariant } from '../../types';\nimport '../../content/icon/icon';\nimport '../input/input';\nimport { disablableBundle, roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { disabledLoadingMixin } from '../../styles';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport componentStyles from './number-input.css?inline';\n\nexport type OreNumberInputEvents = {\n  change: Event;\n  input: InputEvent;\n};\n\n/** Number Input props */\nexport type OreNumberInputProps = {\n  /** Theme color */\n  color?: ThemeColor;\n  /** Disable interaction */\n  disabled?: boolean;\n  /** Error message */\n  error?: string;\n  /** Stretch to full width of container */\n  fullwidth?: boolean;\n  /** Helper text */\n  helper?: string;\n  /** Visible label */\n  label?: string;\n  /** Label placement: 'inset' renders the label inside the control box, 'outside' renders it above */\n  'label-placement'?: 'inset' | 'outside';\n  /** Large step (for Page Up/Down, default: 10 × step) */\n  'large-step'?: number;\n  /**\n   * Shows an inline spinner inside the field and forces the control into `disabled` for the\n   * duration — use while an async validation/submission request is in flight to prevent\n   * double-submits.\n   */\n  loading?: boolean;\n  /** Maximum allowed value */\n  max?: number;\n  /** Minimum allowed value */\n  min?: number;\n  /** Form field name */\n  name?: string;\n  /** Placeholder text */\n  placeholder?: string;\n  /** Make the input read-only */\n  readonly?: boolean;\n  /**\n   * JS-only callback fired with the inner `<input>` element when it mounts,\n   * and with `null` when it unmounts.\n   * Set as a JS property: `bitNumberInput.ref = (el) => { ... }`.\n   */\n  ref?: ((el: HTMLInputElement | null) => void) | null;\n  /** Border radius */\n  rounded?: string;\n  /** Component size */\n  size?: ComponentSize;\n  /** Step size for increment/decrement */\n  step?: number;\n  /**\n   * Shows an inline green check icon inside the field to confirm the value has\n   * passed validation. Ignored while `error` is set — an error always wins.\n   */\n  success?: boolean;\n  /** Current numeric value */\n  value?: number;\n  /** Visual variant */\n  variant?: VisualVariant;\n};\n\n/**\n * A numeric spin-button input with +/− controls, min/max clamping, and full keyboard support.\n *\n * @element ore-number-input\n *\n * @attr {number} value - Current value\n * @attr {number} min - Minimum value\n * @attr {number} max - Maximum value\n * @attr {number} step - Increment/decrement step (default: 1)\n * @attr {number} large-step - Step for Page Up/Down (default: 10)\n * @attr {boolean} disabled - Disables the control\n * @attr {boolean} readonly - Read-only mode\n * @attr {boolean} loading - Show an inline spinner and force the control disabled\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {string} label - Visible label\n * @attr {string} name - Form field name\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} placeholder - Input placeholder\n *\n * @fires input - On every keystroke.\n * @fires change - On committed value change.\n *\n * @slot prefix - Content before the input (e.g. icon)\n * @slot suffix - Content after the input (e.g. unit label)\n * @slot label - Custom label content\n * @slot helper - Custom helper text content\n * @slot error - Custom error content\n *\n * @cssprop --number-input-height - Control height\n * @cssprop --number-input-border-color - Border color\n * @cssprop --number-input-radius - Border radius\n * @cssprop --number-input-bg - Background\n * @cssprop --number-input-btn-bg - Spin button background\n *\n * @part control - Control container.\n * @part decrement-btn - Decrement stepper button.\n * @part input - Input element.\n * @part increment-btn - Increment stepper button.\n * @example\n * ```html\n * <ore-number-input label=\"Quantity\" value=\"1\" min=\"1\" max=\"99\" step=\"1\"></ore-number-input>\n * <ore-number-input label=\"Quantity\" success></ore-number-input>\n * <ore-number-input label=\"Quantity\" loading></ore-number-input>\n * ```\n */\nexport const NUMBER_INPUT_TAG = 'ore-number-input' as const;\ndefine<OreNumberInputProps>(NUMBER_INPUT_TAG, {\n  formAssociated: true,\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...disablableBundle,\n    ...roundableBundle,\n    error: prop.string(),\n    fullwidth: prop.bool(false),\n    helper: prop.string(),\n    label: prop.string(),\n    'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n    'large-step': prop.json(undefined as number | undefined),\n    loading: prop.bool(false),\n    max: prop.json(undefined as number | undefined),\n    min: prop.json(undefined as number | undefined),\n    name: prop.string(),\n    placeholder: prop.string(),\n    readonly: prop.bool(false),\n    ref: prop.data<((el: HTMLInputElement | null) => void) | null>(),\n    step: prop.number(1),\n    success: prop.bool(false),\n    value: prop.json(undefined as number | undefined),\n    variant: prop.string<VisualVariant>(),\n  },\n  setup(props) {\n    const el = getHost();\n    const watch = watchEffect;\n\n    // `loading` behaves like a temporary `disabled` — see ore-input's identical computation.\n    const isDisabled = computed(() => props.disabled.value || props.loading.value);\n    const isReadonly = computed(() => Boolean(props.readonly.value));\n\n    // Internal numeric value signal (string representation for the input)\n    const fieldValue = signal(props.value.value != null ? String(props.value.value) : '');\n\n    defineFieldValue(\n      el,\n      () => fieldValue.value,\n      (value) => {\n        fieldValue.value = value;\n      },\n    );\n\n    // Keep fieldValue in sync when props.value changes externally\n    rippleWatch(props.value, (v) => {\n      const next = v != null ? String(v) : '';\n\n      if (fieldValue.value !== next) fieldValue.value = next;\n    });\n\n    function parseValue(): number | null {\n      const v = fieldValue.value.trim();\n\n      if (!v) return null;\n\n      const n = Number.parseFloat(v);\n\n      return Number.isNaN(n) ? null : n;\n    }\n\n    function commit(val: number | null, _originalEvent?: Event) {\n      const min = props.min.value != null ? Number(props.min.value) : undefined;\n      const max = props.max.value != null ? Number(props.max.value) : undefined;\n      const clamped = val != null ? clamp(val, min, max) : null;\n      const nextValue = clamped != null ? String(clamped) : '';\n\n      if (fieldValue.value !== nextValue) fieldValue.value = nextValue;\n\n      setFieldValue(el, nextValue);\n      dispatchNativeFieldEvent(el, 'change');\n    }\n\n    const spinner = createSpinnerControl({\n      commit,\n      disabled: isDisabled,\n      largeStep: props['large-step'],\n      max: props.max,\n      min: props.min,\n      parse: parseValue,\n      readonly: isReadonly,\n      step: props.step,\n    });\n\n    // Composition uses ore-input's own documented `ref` prop (fired with the raw\n    // <input> on mount, `null` on unmount) instead of reaching into its shadow DOM —\n    // see `packages/refine/AGENTS.md` / input.ts's `ref` JSDoc for the supported contract.\n    // Set imperatively (rather than declared in the template) because ore's template\n    // engine treats a function-valued attr binding as a reactive getter to invoke, not\n    // a literal value to assign — a plain property assignment avoids that entirely.\n    const bitInputRef = ref<HTMLElementTagNameMap['ore-input']>();\n    let stopAriaWatch: (() => void) | null = null;\n    let detachListeners: (() => void) | null = null;\n    let refSub: { dispose(): void } | null = null;\n\n    const handleFieldRef = (rawInput: HTMLInputElement | null): void => {\n      if (!rawInput) {\n        stopAriaWatch?.();\n        detachListeners?.();\n        refSub?.dispose();\n        stopAriaWatch = null;\n        detachListeners = null;\n        refSub = null;\n        props.ref.value?.(null);\n\n        return;\n      }\n\n      rawInput.setAttribute('inputmode', 'decimal');\n      // The wrapper div is a plain layout container — WAI-ARIA spinbutton semantics\n      // live on the actually-focusable element (the raw <input> rendered by ore-input).\n      rawInput.setAttribute('role', 'spinbutton');\n\n      const handleChange = (e: Event) => {\n        const val = (e.target as HTMLInputElement).value;\n        const n = val !== '' ? Number.parseFloat(val) : null;\n\n        commit(Number.isNaN(n ?? NaN) ? null : n, e);\n      };\n\n      const handleInput = (e: Event) => {\n        const val = (e.target as HTMLInputElement).value;\n\n        fieldValue.value = val;\n        setFieldValue(el, val);\n        dispatchNativeFieldEvent(el, 'input');\n      };\n\n      rawInput.addEventListener('change', handleChange);\n      rawInput.addEventListener('input', handleInput);\n      detachListeners = () => {\n        rawInput.removeEventListener('change', handleChange);\n        rawInput.removeEventListener('input', handleInput);\n      };\n\n      stopAriaWatch = watch(() => {\n        const now = parseValue();\n\n        if (now == null) rawInput.removeAttribute('aria-valuenow');\n        else rawInput.setAttribute('aria-valuenow', String(now));\n\n        if (props.min.value != null) rawInput.setAttribute('aria-valuemin', String(props.min.value));\n        else rawInput.removeAttribute('aria-valuemin');\n\n        if (props.max.value != null) rawInput.setAttribute('aria-valuemax', String(props.max.value));\n        else rawInput.removeAttribute('aria-valuemax');\n\n        if (isReadonly.value) rawInput.setAttribute('aria-readonly', 'true');\n        else rawInput.removeAttribute('aria-readonly');\n      });\n\n      // Fire user ref callback\n      props.ref.value?.(rawInput);\n\n      refSub = rippleWatch(props.ref, (cb) => {\n        cb?.(rawInput);\n      });\n    };\n\n    // ore-input's own onElement/ref lifecycle calls this back with `null` when its\n    // inner <input> unmounts, so no explicit teardown is needed here.\n    onElement(bitInputRef, (bitInputEl) => {\n      bitInputEl.ref = handleFieldRef;\n    });\n\n    bind({\n      attr: {\n        size: props.size,\n        value: () => fieldValue.value || null,\n        variant: props.variant,\n      },\n    });\n\n    const isNonInteractive = computed(() => isDisabled.value || isReadonly.value);\n\n    // The stepper buttons are slotted *into* ore-input's own `prefix`/`suffix` slots instead of\n    // sitting outside it in a separate wrapper — they render inside ore-input's own bordered\n    // box (same as its built-in clear/password-toggle buttons), matching every other field's\n    // single-box look instead of floating as two detached icon buttons either side of a\n    // narrow field. `@keydown` moves to ore-input itself: native keyboard events are\n    // `composed: true` and bubble out past a shadow boundary, so it still sees keydowns\n    // originating from ore-input's internal <input> as well as from these slotted buttons.\n    return html`\n      <ore-input\n        class=\"field\"\n        part=\"field control\"\n        ref=\"${bitInputRef}\"\n        value=\"${() => fieldValue.value ?? 0}\"\n        label=\"${() => props.label.value ?? ''}\"\n        label-placement=\"${() => props['label-placement'].value ?? 'inset'}\"\n        placeholder=\"${() => props.placeholder.value ?? ''}\"\n        name=\"${() => props.name.value ?? ''}\"\n        helper=\"${() => props.helper.value ?? ''}\"\n        error=\"${() => props.error.value ?? ''}\"\n        size=\"${props.size}\"\n        color=\"${() => props.color.value ?? ''}\"\n        variant=\"${props.variant}\"\n        rounded=\"${() => props.rounded.value}\"\n        ?disabled=\"${props.disabled}\"\n        ?readonly=\"${isReadonly}\"\n        ?fullwidth=\"${() => props.fullwidth.value}\"\n        ?loading=\"${() => props.loading.value}\"\n        ?success=\"${() => props.success.value}\"\n        @keydown=\"${(e: KeyboardEvent) => spinner.handleKeydown(e)}\">\n        <button\n          slot=\"prefix\"\n          type=\"button\"\n          part=\"decrement-btn\"\n          aria-label=\"Decrease\"\n          ?disabled=\"${() => isNonInteractive.value || spinner.atMin()}\"\n          @click=\"${(e: Event) => spinner.incrementBy(-(Number(props.step.value) || 1), e)}\">\n          <ore-icon name=\"minus\" size=\"14\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n        </button>\n        <button\n          slot=\"suffix\"\n          type=\"button\"\n          part=\"increment-btn\"\n          aria-label=\"Increase\"\n          ?disabled=\"${() => isNonInteractive.value || spinner.atMax()}\"\n          @click=\"${(e: Event) => spinner.incrementBy(Number(props.step.value) || 1, e)}\">\n          <ore-icon name=\"plus\" size=\"14\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n        </button>\n      </ore-input>\n    `;\n  },\n  shadow: { delegatesFocus: true },\n  styles: [disabledLoadingMixin, componentStyles],\n});\n","@layer refine.base {\n  :host {\n    --_cell-size: var(--otp-cell-size, var(--size-12));\n    --_cell-gap: var(--otp-cell-gap, var(--size-2));\n    --_cell-font-size: var(--otp-cell-font-size, var(--text-xl));\n    --_cell-radius: var(--otp-cell-radius, var(--rounded-lg));\n    --_cell-border: var(--otp-cell-border, var(--border));\n\n    /* --_bg/--_border-color (not --_cell-*-prefixed, unlike the rest of this component's tokens)\n       — this is the shared name `fieldVariantMixin` reads/writes, matching `ore-input`/`ore-\n       textarea`/`ore-message-composer`. Public override is still `--otp-cell-bg`/`--otp-cell-\n       border-color` either way. */\n    --_border-color: var(--otp-cell-border-color, var(--color-contrast-300));\n    --_bg: var(--otp-cell-bg, var(--color-canvas));\n    --_cell-focus-border: var(--otp-cell-focus-border, var(--_theme-base, var(--color-contrast-700)));\n\n    display: inline-flex;\n    flex-direction: column;\n    gap: var(--size-1);\n  }\n\n  .otp-group {\n    display: flex;\n    gap: var(--_cell-gap);\n    align-items: center;\n  }\n\n  .cell {\n    box-sizing: border-box;\n    display: block;\n    width: var(--_cell-size);\n    height: var(--_cell-size);\n    padding: 0;\n    font-size: var(--_cell-font-size);\n    font-weight: var(--font-semibold);\n    line-height: 1;\n    color: var(--color-contrast-900);\n    text-align: center;\n    caret-color: var(--_cell-focus-border);\n    background: var(--_bg);\n    border: var(--_cell-border) solid var(--_border-color);\n    border-radius: var(--_cell-radius);\n    transition:\n      border-color var(--transition-fast),\n      box-shadow var(--transition-fast);\n  }\n\n  .cell::selection {\n    background: var(--_theme-backdrop, var(--color-contrast-100));\n  }\n\n  /* Ring box-shadow lives in `@layer refine.variants` below, not here — every variant's own\n     rest-state `box-shadow` (`fieldVariantMixin`'s solid/outline/ghost rules) is *also* in\n     `refine.variants`, and cascade layers decide the winner before specificity ever gets\n     consulted. A `refine.base` box-shadow here would always lose to those, focused or not. */\n  .cell:focus {\n    outline: none;\n    border-color: var(--_cell-focus-border);\n  }\n\n  .cell:disabled {\n    cursor: not-allowed;\n    opacity: 0.5;\n  }\n\n  .separator {\n    font-size: var(--_cell-font-size);\n    color: var(--color-contrast-400);\n    user-select: none;\n  }\n}\n\n/*\n * The solid/flat/bordered/outline/ghost variant switch (previously `@layer refine.variants`\n * here) now lives in `fieldVariantMixin({ accentVar: '--_cell-focus-border', container: '.cell',\n * tokenPrefix: 'otp-cell' })` in `otp-input.ts`'s `styles` array — shared with `ore-input`/\n * `ore-textarea`/`ore-message-composer` instead of hand-duplicated. `accentVar` overrides the\n * shared `--_theme-focus` accent with this component's own per-cell focus-color token, since\n * that (not the shared theme-focus token) is what `flat`/`bordered` mixed into their border\n * color here even before this shared version existed.\n */\n@layer refine.variants {\n  /* Focus glow — the same `--_theme-shadow` halo `ore-input`/`ore-textarea`/`ore-message-\n     composer` use, kept out of the shared mixin only because `.cell` is the focusable element\n     itself (not a wrapper, so this is `:focus` not `:focus-within`, and it targets `.cell`\n     directly rather than a mixin-supplied `container`). `flat` excluded — the mixin's own\n     `flat:focus-within` rule already sets a bespoke `box-shadow` for it. */\n  :host(:not([disabled], [variant='flat'])) .cell:focus {\n    box-shadow: var(--_theme-shadow, var(--color-primary-focus-shadow));\n  }\n}\n\n@layer refine.utilities {\n  :host([size='sm']) {\n    --_cell-size: var(--size-9);\n    --_cell-font-size: var(--text-base);\n  }\n\n  :host([size='lg']) {\n    --_cell-size: var(--size-14);\n    --_cell-font-size: var(--text-2xl);\n  }\n}\n","import { bind, define, getHost, html, onCleanup, onMounted, prop, useEmit, useField } from '@vielzeug/ore';\nimport { computed, signal, watch } from '@vielzeug/ripple';\nimport { createListControl, lifecycleSignal } from '../../core';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, fieldVariantMixin, forcedColorsFocusMixin, sizeVariantMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor, VisualVariant } from '../../types';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport componentStyles from './otp-input.css?inline';\n\nexport type OreOtpInputEvents = {\n  change: Event;\n  complete: { originalEvent?: Event; value: string };\n  input: Event;\n};\n\n/** OTP Input props */\nexport type OreOtpInputProps = {\n  /** Theme color */\n  color?: ThemeColor;\n  /** Make inputs disabled */\n  disabled?: boolean;\n  /** Accessible label */\n  label?: string;\n  /** Number of input cells */\n  length?: number;\n  /** Mask input (show dots instead of characters) */\n  masked?: boolean;\n  /** Form field name */\n  name?: string;\n  /** Show a separator in the middle (e.g. \"–\") */\n  separator?: string;\n  /** Component size */\n  size?: ComponentSize;\n  /** Input type: 'numeric' (digits only) or 'alphanumeric' */\n  type?: 'numeric' | 'alphanumeric';\n  /** Current value */\n  value?: string;\n  /** Visual variant */\n  variant?: Exclude<VisualVariant, 'text' | 'frost'>;\n};\n\n/**\n * A segmented OTP (One-Time Password) input with N individual cells.\n * Auto-advances focus on input, auto-backs on Backspace, handles paste.\n *\n * @element ore-otp-input\n *\n * @attr {number} length - Number of cells (default: 6)\n * @attr {string} type - 'numeric' (default) | 'alphanumeric'\n * @attr {string} value - Current code value\n * @attr {boolean} disabled - Disable all cells\n * @attr {boolean} masked - Show as password\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} name - Form field name\n * @attr {string} label - Group aria-label\n * @attr {string} separator - Optional separator character shown in the middle\n *\n * @fires input - Emitted whenever a cell changes.\n * @fires change - Emitted whenever a cell changes.\n * @fires complete - Emitted when all cells are filled. detail: { value: string, originalEvent?: Event }\n *\n * @slot label - Custom label above the OTP input\n * @slot helper - Custom helper text below the OTP input\n * @slot error - Custom error content below the OTP input\n *\n * @cssprop --otp-cell-size - Width and height of each cell\n * @cssprop --otp-cell-gap - Gap between cells\n * @cssprop --otp-cell-font-size - Font size inside cells\n * @cssprop --otp-cell-radius - Border radius of cells\n * @cssprop --otp-cell-bg - Cell background color\n * @cssprop --otp-cell-border-color - Default border color\n * @cssprop --otp-cell-focus-border - Focused border/caret color\n * @cssprop --otp-cell-hover-bg - Cell background on hover (flat/ghost variants)\n * @cssprop --otp-cell-hover-border-color - Cell border on hover (flat/bordered variants)\n * @cssprop --otp-cell-focus-bg - Cell background when focused (flat variant)\n * @cssprop --otp-cell-focus-border-color - Cell border when focused (flat variant)\n *\n * @part group - Group container.\n * @part cell - Shadow part for the `cell` element.\n * @example\n * ```html\n * <ore-otp-input length=\"6\" color=\"primary\"></ore-otp-input>\n * ```\n */\nexport const OTP_INPUT_TAG = 'ore-otp-input' as const;\ndefine<OreOtpInputProps>(OTP_INPUT_TAG, {\n  formAssociated: true,\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...disablableBundle,\n    label: prop.string('One-time password'),\n    length: prop.number(6),\n    masked: prop.bool(false),\n    name: prop.string(),\n    separator: prop.string(),\n    type: prop.oneOf(['numeric', 'alphanumeric'] as const, 'numeric'),\n    value: prop.string(),\n    variant: prop.string<Exclude<VisualVariant, 'text' | 'frost'>>(),\n  },\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreOtpInputEvents>();\n\n    const lengthValue = computed(() => Number(props.length.value) || 6);\n    const isDisabled = computed(() => Boolean(props.disabled.value));\n    const cells = computed(() => Array.from({ length: lengthValue.value }, (_, i) => i));\n    const otpValue = signal(String(props.value.value || ''));\n    const normalizedPropValue = () => String(props.value.value || '');\n\n    // Form association: the joined cell value is the single form value for `name`,\n    // since individual per-cell <input> elements inside the shadow root cannot\n    // participate in an ancestor <form>'s submission on their own.\n    useField<string>({ disabled: isDisabled, toFormValue: (v) => v, value: otpValue });\n\n    bind({\n      attr: {\n        size: props.size,\n        value: () => otpValue.value || null,\n        variant: props.variant,\n      },\n    });\n\n    function getInputs(): HTMLInputElement[] {\n      return [...(el.shadowRoot?.querySelectorAll<HTMLInputElement>('input.cell') ?? [])];\n    }\n\n    const listControl = createListControl({\n      getItems: () => getInputs(),\n      keys: { next: ['ArrowRight'], prev: ['ArrowLeft'] },\n      loop: false,\n      onNavigate: ({ item }) => {\n        item.focus();\n      },\n      signal: lifecycleSignal(onCleanup),\n    });\n\n    function getValue(): string {\n      return getInputs()\n        .map((i) => i.value)\n        .join('');\n    }\n    function syncInputsFromValue(raw: string) {\n      const allInputs = getInputs();\n      const normalized = String(raw || '').slice(0, allInputs.length);\n\n      for (const input of allInputs) input.value = '';\n\n      normalized.split('').forEach((c, i) => {\n        if (allInputs[i]) allInputs[i].value = c;\n      });\n\n      otpValue.value = getValue();\n    }\n    defineFieldValue(\n      el,\n      () => otpValue.value,\n      (value) => {\n        syncInputsFromValue(value);\n      },\n    );\n    function emitOtpState(originalEvent?: Event, forceComplete?: boolean): void {\n      const allInputs = getInputs();\n      const full = getValue();\n      const complete = forceComplete ?? (full.length === allInputs.length && full.split('').every(Boolean));\n\n      otpValue.value = full;\n      setFieldValue(el, full);\n      dispatchNativeFieldEvent(el, 'input');\n      dispatchNativeFieldEvent(el, 'change');\n\n      if (complete) emit('complete', { originalEvent, value: full });\n    }\n    function isAllowed(char: string): boolean {\n      if (props.type.value === 'numeric') return /^\\d$/.test(char);\n\n      return /^[a-z\\d]$/i.test(char);\n    }\n    function handleInput(e: Event, index: number) {\n      const input = e.target as HTMLInputElement;\n      let val = input.value;\n\n      // Keep only last character if multiple were typed somehow\n      if (val.length > 1) val = val.slice(-1);\n\n      // Validate character\n      if (val && !isAllowed(val)) {\n        input.value = '';\n\n        return;\n      }\n\n      input.value = val;\n\n      const allInputs = getInputs();\n\n      emitOtpState(e);\n\n      // Auto-advance\n      if (val && index < allInputs.length - 1) {\n        allInputs[index + 1].focus();\n        allInputs[index + 1].select();\n      }\n    }\n    function handleKeydown(e: KeyboardEvent, index: number) {\n      const input = e.target as HTMLInputElement;\n      const allInputs = getInputs();\n\n      listControl.set(index);\n\n      if (e.key === 'Backspace') {\n        if (input.value) {\n          input.value = '';\n        } else if (index > 0) {\n          const prevIndex = listControl.navigate('prev');\n          const prevInput = allInputs[prevIndex];\n\n          if (prevInput) {\n            prevInput.select();\n            prevInput.value = '';\n          }\n        }\n\n        emitOtpState(e, false);\n        e.preventDefault();\n      } else {\n        listControl.handleKeydown(e);\n      }\n    }\n    function handlePaste(e: ClipboardEvent) {\n      e.preventDefault();\n\n      const pasted = e.clipboardData?.getData('text') ?? '';\n      const chars = pasted\n        .split('')\n        .filter((c) => isAllowed(c))\n        .slice(0, lengthValue.value);\n      const allInputs = getInputs();\n\n      chars.forEach((char, i) => {\n        if (allInputs[i]) allInputs[i].value = char;\n      });\n\n      emitOtpState(e);\n\n      // Focus the cell after last pasted char\n      const focusIdx = Math.min(chars.length, allInputs.length - 1);\n\n      allInputs[focusIdx]?.focus();\n    }\n\n    watch(props.value, (value) => {\n      syncInputsFromValue(String(value || ''));\n    });\n\n    watch(props.length, () => {\n      // Cells re-render when length changes; sync after DOM updates.\n      requestAnimationFrame(() => syncInputsFromValue(normalizedPropValue()));\n    });\n\n    const separatorIdx = computed(() => {\n      const len = Number(props.length.value) || 6;\n\n      return props.separator.value != null ? Math.floor(len / 2) : -1;\n    });\n\n    onMounted(() => {\n      // Populate cells from value prop on mount\n      syncInputsFromValue(normalizedPropValue());\n    });\n\n    return html`\n      <div class=\"otp-group\" part=\"group\" role=\"group\" aria-label=\"${props.label}\">\n        ${() =>\n          cells.value.map(\n            (i) => html`\n              ${() =>\n                separatorIdx.value > 0 && i === separatorIdx.value\n                  ? html`\n                      <span class=\"separator\" aria-hidden=\"true\">${() => props.separator.value || '-'}</span>\n                    `\n                  : ''}\n              <input\n                class=\"cell\"\n                part=\"cell\"\n                type=\"${() => (props.masked.value ? 'password' : 'text')}\"\n                inputmode=\"${() => (props.type.value === 'numeric' ? 'numeric' : 'text')}\"\n                maxlength=\"1\"\n                autocomplete=\"${() => (i === 0 ? 'one-time-code' : 'off')}\"\n                aria-label=\"${() => `Digit ${i + 1} of ${lengthValue.value}`}\"\n                disabled=\"${() => (isDisabled.value ? true : null)}\"\n                @input=\"${(e: Event) => handleInput(e, i)}\"\n                @keydown=\"${(e: KeyboardEvent) => handleKeydown(e, i)}\"\n                @paste=\"${(e: ClipboardEvent) => (i === 0 ? handlePaste(e) : e.preventDefault())}\"\n                @focus=\"${(e: FocusEvent) => (e.target as HTMLInputElement).select()}\" />\n            `,\n          )}\n      </div>\n    `;\n  },\n  styles: [\n    colorThemeMixin,\n    sizeVariantMixin({}),\n    forcedColorsFocusMixin('.cell'),\n    componentStyles,\n    // Must come after `componentStyles` — see `ore-input`'s identical ordering note for why.\n    fieldVariantMixin({ accentVar: '--_cell-focus-border', container: '.cell', tokenPrefix: 'otp-cell' }),\n  ],\n});\n","@layer refine.base {\n  :host {\n    display: block;\n  }\n\n  fieldset {\n    min-width: 0;\n    padding: 0;\n    margin: 0;\n    border: none;\n  }\n\n  legend {\n    padding: 0;\n    margin-bottom: var(--size-2);\n    font-size: var(--text-sm);\n    font-weight: var(--font-medium);\n    color: var(--color-contrast-600);\n  }\n\n  legend[hidden] {\n    display: none;\n  }\n\n  .radio-group-items {\n    display: flex;\n    flex-direction: var(--radio-group-direction, column);\n    gap: var(--radio-group-gap, var(--size-2));\n  }\n\n  .helper-text[hidden] {\n    display: none;\n  }\n\n  .helper-text {\n    padding-inline: 2px;\n    margin-top: var(--size-1-5);\n    font-size: var(--text-xs);\n    line-height: var(--leading-tight);\n    color: color-mix(in oklch, var(--color-contrast-500) 80%, var(--color-canvas));\n  }\n\n  .error-text {\n    padding-inline: 2px;\n    margin-top: var(--size-1-5);\n    font-size: var(--text-xs);\n    line-height: var(--leading-tight);\n    color: var(--color-error);\n  }\n}\n\n@layer refine.variants {\n  :host([orientation='horizontal']) .radio-group-items {\n    --radio-group-direction: row;\n\n    flex-wrap: wrap;\n  }\n}\n","import {\n  bind,\n  createContext,\n  createStableId,\n  define,\n  getHost,\n  html,\n  onCleanup,\n  prop,\n  provide,\n  useEmit,\n  useField,\n  useSlots,\n  watchEffect,\n  when,\n} from '@vielzeug/ore';\nimport type { Readable } from '@vielzeug/ripple';\nimport {\n  type ChoiceChangeDetail,\n  createChoiceField,\n  createListControl,\n  getChoiceLabel,\n  getLightChildrenByTag,\n  lifecycleSignal,\n} from '../../core';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { disabledStateMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport componentStyles from './radio-group.css?inline';\n\n/** Radio group component properties */\nexport type OreRadioGroupProps = {\n  /** Theme color tint */\n  color?: ThemeColor;\n  /** Disabled state */\n  disabled?: boolean;\n  /** Error message text */\n  error?: string;\n  /** Helper text displayed below the items */\n  helper?: string;\n  /** Group label text */\n  label?: string;\n  /** Form field name */\n  name?: string;\n  /** Layout orientation */\n  orientation?: 'horizontal' | 'vertical';\n  /** Required field */\n  required?: boolean;\n  /** Items size preset */\n  size?: ComponentSize;\n  /** Initial selected value */\n  value?: string;\n};\n\nexport type RadioGroupContext = {\n  color: Readable<ThemeColor | undefined>;\n  disabled: Readable<boolean>;\n  name: Readable<string | undefined>;\n  select: (value: string, originalEvent?: Event) => void;\n  size: Readable<ComponentSize | undefined>;\n  value: Readable<string | undefined>;\n};\n\nexport const RADIO_GROUP_CTX = createContext<RadioGroupContext | undefined>('OreRadioGroup');\n\n/** Events emitted by the radio-group component */\nexport type OreRadioGroupEvents = {\n  /** Emitted when the selection changes */\n  change: ChoiceChangeDetail;\n};\n\n/**\n * A group of radio buttons that allows users to select a single option from a set.\n * Supports keyboard navigation (arrows) and automatic value management.\n *\n * @element ore-radio-group\n *\n * @attr {string} value - Selected value\n * @attr {string} name - Form field name\n * @attr {string} label - Group label\n * @attr {string} orientation - Layout: 'vertical' | 'horizontal'\n * @attr {boolean} required - Required field\n *\n * @fires change - Emitted when a radio is selected. detail: { values: string[], labels: string[], originalEvent?: Event }\n *\n * @slot - Place `ore-radio` elements here\n *\n * @cssprop --radio-group-direction - Flex direction of the items list ('row' | 'column')\n * @cssprop --radio-group-gap - Gap between radio items\n * @part items - Items container.\n * @example\n * ```html\n * <ore-radio-group name=\"plan\" label=\"Choose a plan\" value=\"free\" required>\n *   <ore-radio value=\"free\">Free</ore-radio>\n *   <ore-radio value=\"pro\">Pro</ore-radio>\n *   <ore-radio value=\"enterprise\">Enterprise</ore-radio>\n * </ore-radio-group>\n * <ore-radio-group name=\"direction\" orientation=\"horizontal\" color=\"primary\">\n *   <ore-radio value=\"left\">Left</ore-radio>\n *   <ore-radio value=\"right\">Right</ore-radio>\n * </ore-radio-group>\n * ```\n */\nexport const RADIO_GROUP_TAG = 'ore-radio-group' as const;\ndefine<OreRadioGroupProps>(RADIO_GROUP_TAG, {\n  formAssociated: true,\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...disablableBundle,\n    error: prop.string(),\n    helper: prop.string(),\n    label: prop.string(),\n    name: prop.string(),\n    orientation: prop.oneOf(['horizontal', 'vertical'] as const, 'vertical'),\n    required: prop.bool(false),\n    // Not auto-reflected (`reflect: false`) — the derived, interaction-updated selection\n    // (`selectedValue`) is the single writer for this attribute, via `bind()` below; letting\n    // `prop.string()`'s own default reflection also write the raw incoming value would leave\n    // two effects racing to set the same attribute from different sources.\n    value: { ...prop.string(), reflect: false },\n  },\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreRadioGroupEvents>();\n    const slots = useSlots();\n    const watch = watchEffect;\n\n    const choice = createChoiceField({\n      disabled: props.disabled,\n      error: props.error,\n      helper: props.helper,\n      label: props.label,\n      prefix: 'radio-group',\n      required: props.required,\n      signal: lifecycleSignal(onCleanup),\n      value: props.value,\n    });\n\n    choice.attachFormField(\n      useField<string>({\n        disabled: choice.disabled,\n        onReset: choice.reset,\n        toFormValue: (v) => v,\n        validationMessage: choice.validationMessage,\n        validity: choice.validity,\n        value: choice.formValue,\n      }),\n    );\n\n    const selectedValue = choice.selectedValue;\n    const isDisabled = props.disabled;\n\n    bind({\n      attr: {\n        size: props.size,\n        value: () => selectedValue.value || null,\n      },\n    });\n\n    const getSlottedRadios = (): HTMLElement[] => getLightChildrenByTag(el, 'ore-radio');\n\n    const getEnabledRadios = (): HTMLElement[] =>\n      isDisabled.value ? [] : getSlottedRadios().filter((radio) => !radio.hasAttribute('disabled'));\n\n    const getLabelForValue = (value: string): string => getChoiceLabel(getSlottedRadios(), value);\n\n    const selectRadio = (val: string, originalEvent?: Event): void => {\n      choice.setValues(val ? [val] : []);\n\n      const labels = val ? [getLabelForValue(val)] : [];\n      const values = val ? [val] : [];\n\n      emit('change', { labels, originalEvent, values });\n      choice.triggerValidation('blur');\n    };\n\n    provide(RADIO_GROUP_CTX, {\n      color: props.color as Readable<ThemeColor | undefined>,\n      disabled: isDisabled,\n      name: props.name,\n      select: selectRadio,\n      size: props.size as Readable<ComponentSize | undefined>,\n      value: selectedValue,\n    });\n\n    // Sync name/color/size/disabled/checked onto slotted ore-radio children.\n    watch(() => {\n      void slots.elements().value;\n      void selectedValue.value;\n\n      const radios = getSlottedRadios();\n\n      for (const radio of radios) {\n        const val = radio.getAttribute('value') ?? '';\n\n        radio.toggleAttribute('checked', val === selectedValue.value);\n\n        if (props.name.value) radio.setAttribute('name', props.name.value);\n        else radio.removeAttribute('name');\n\n        if (props.color.value) radio.setAttribute('color', props.color.value);\n        else radio.removeAttribute('color');\n\n        if (props.size.value) radio.setAttribute('size', props.size.value);\n        else radio.removeAttribute('size');\n\n        radio.toggleAttribute('disabled', isDisabled.value);\n      }\n    });\n\n    // Roving tabindex: only the selected (or first) radio is tabbable.\n    watch(() => {\n      void slots.elements().value;\n\n      const radios = getSlottedRadios();\n      let hasFocusable = false;\n\n      for (const radio of radios) {\n        const isSelected = radio.getAttribute('value') === selectedValue.value;\n\n        radio.setAttribute('tabindex', isSelected && !isDisabled.value ? '0' : '-1');\n\n        if (isSelected && !isDisabled.value) hasFocusable = true;\n      }\n\n      if (!hasFocusable && radios.length > 0) {\n        const first = radios.find((r) => !r.hasAttribute('disabled'));\n\n        if (first) first.setAttribute('tabindex', '0');\n      }\n    });\n\n    const listControl = createListControl<HTMLElement>({\n      getItems: getEnabledRadios,\n      keys: { next: ['ArrowDown', 'ArrowRight'], prev: ['ArrowUp', 'ArrowLeft'] },\n      loop: true,\n      onNavigate: ({ event, item }) => {\n        item.focus();\n\n        if (item.tagName === 'ORE-RADIO') {\n          selectRadio(item.getAttribute('value') ?? '', event);\n        }\n      },\n      signal: lifecycleSignal(onCleanup),\n    });\n\n    bind({\n      on: {\n        change: (e: Event) => {\n          if (e.target === el) return;\n\n          e.stopPropagation();\n          selectRadio((e.target as HTMLElement).getAttribute('value') ?? '', e);\n        },\n        keydown: (e: KeyboardEvent) => {\n          const radios = getEnabledRadios();\n\n          if (!radios.length) return;\n\n          const focused = radios.indexOf(document.activeElement as HTMLElement);\n\n          if (focused === -1) return;\n\n          listControl.set(focused);\n          listControl.handleKeydown(e);\n        },\n      },\n    });\n\n    const legendId = createStableId('radio-group-legend');\n\n    return html`\n      <fieldset\n        role=\"radiogroup\"\n        aria-required=\"${() => String(Boolean(props.required.value))}\"\n        aria-invalid=\"${choice.ariaInvalid}\"\n        aria-errormessage=\"${choice.ariaErrorMessage}\"\n        aria-describedby=\"${choice.ariaDescribedBy}\">\n        <legend id=\"${legendId}\" ?hidden=${() => !props.label.value}>\n          ${props.label}${when(\n            () => Boolean(props.required.value),\n            () => html`\n              <span aria-hidden=\"true\">*</span>\n            `,\n          )}\n        </legend>\n        <div class=\"radio-group-items\" part=\"items\">\n          <slot></slot>\n        </div>\n        <div\n          class=\"helper-text\"\n          part=\"helper\"\n          id=\"${choice.assistiveId}\"\n          role=\"${() => (choice.errorText.value ? 'alert' : null)}\"\n          aria-live=\"polite\"\n          ?hidden=\"${() => !choice.errorText.value && !choice.helperText.value}\">\n          ${() => choice.errorText.value || choice.helperText.value}\n        </div>\n      </fieldset>\n    `;\n  },\n  styles: [disabledStateMixin, componentStyles],\n});\n","@layer refine.base {\n  /* ========================================\n       Base Styles & Defaults\n       ======================================== */\n\n  :host {\n    --_size: var(--radio-size, var(--size-5));\n    --_font-size: var(--radio-font-size, var(--text-sm));\n    --_bg: var(--radio-bg, var(--color-contrast-200));\n    --_border: var(--radio-border-color, var(--color-contrast-300));\n\n    display: inline-flex;\n    flex-wrap: wrap;\n    gap: var(--_gap, var(--size-2));\n    align-items: center;\n    min-height: var(--_touch-target);\n    cursor: pointer;\n    user-select: none;\n  }\n\n  .radio-wrapper {\n    position: relative;\n    display: block;\n    flex-shrink: 0;\n    width: var(--_size);\n    height: var(--_size);\n  }\n\n  .circle {\n    position: relative;\n    box-sizing: border-box;\n    width: var(--_size);\n    height: var(--_size);\n    background: var(--_bg);\n    border: var(--border-2) solid var(--_border);\n    border-radius: 50%;\n    transition:\n      background var(--transition-normal),\n      border-color var(--transition-normal),\n      box-shadow var(--transition-normal);\n  }\n\n  /* ========================================\n       Focus State\n       ======================================== */\n\n  :host(:focus-visible) .circle {\n    box-shadow: var(--_focus-shadow);\n  }\n\n  /* ========================================\n       Inner Dot\n       ======================================== */\n\n  .dot {\n    position: absolute;\n    top: 50%;\n    left: 50%;\n    width: 50%;\n    height: 50%;\n    background: var(--_dot-color);\n    border-radius: 50%;\n    opacity: 0;\n    transform: translate(-50%, -50%) scale(0.5);\n    transition:\n      opacity var(--transition-spring),\n      transform var(--transition-spring);\n  }\n\n  /* ========================================\n       Label\n       ======================================== */\n\n  .label {\n    font-size: var(--_font-size);\n    color: var(--color-contrast);\n  }\n\n  /* ========================================\n       Helper / Error Text\n       ======================================== */\n\n  .helper-text[hidden] {\n    display: none;\n  }\n\n  .helper-text {\n    width: 100%;\n    padding-inline-start: calc(var(--_size) + var(--size-2));\n    font-size: var(--text-xs);\n    line-height: var(--leading-tight);\n    color: color-mix(in oklch, var(--color-contrast-500) 80%, var(--color-canvas));\n  }\n\n  .helper-text[role='alert'] {\n    color: var(--color-error);\n  }\n}\n\n@layer refine.overrides {\n  /* Map theme variables to radio-specific variables */\n  :host {\n    --_active-bg: var(--radio-checked-bg, var(--_theme-base));\n    --_dot-color: var(--radio-color, var(--_theme-contrast));\n    --_focus-shadow: var(--_theme-shadow);\n  }\n\n  /* ========================================\n       Checked State\n       ======================================== */\n\n  :host([checked]) .circle {\n    background: var(--_active-bg);\n    border-color: var(--_active-bg);\n  }\n\n  :host([checked]) .dot {\n    opacity: 1;\n    transform: translate(-50%, -50%) scale(1);\n  }\n}\n","import { bind, define, getHost, html, inject, onCleanup, prop, useField } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport { createCheckable, createListControl, elementDirection, lifecycleSignal } from '../../core';\nimport { CONTROL_SIZE_PRESET, disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport {\n  coarsePointerMixin,\n  colorThemeMixin,\n  disabledStateMixin,\n  forcedColorsFormControlMixin,\n  sizeVariantMixin,\n} from '../../styles';\nimport type { CheckableProps, ComponentSize, ThemeColor } from '../../types';\nimport { RADIO_GROUP_CTX } from '../radio-group/radio-group';\nimport { defineFieldChecked, dispatchNativeFieldEvent, setFieldChecked } from '../shared/native-field-event';\nimport { renderHelperRegion } from '../shared/templates';\nimport componentStyles from './radio.css?inline';\n\n/** Radio component properties */\n\nexport type OreRadioEvents = {\n  change: Event;\n  input: Event;\n};\n\nexport type OreRadioProps = CheckableProps & {\n  /** Theme color */\n  color?: ThemeColor;\n  /** Disable interaction */\n  disabled?: boolean;\n  /** Error message (marks field as invalid) */\n  error?: string;\n  /** Helper text displayed below the radio */\n  helper?: string;\n  /** Component size */\n  size?: ComponentSize;\n};\n\n/**\n * A customizable radio button component for mutually exclusive selections.\n *\n * @element ore-radio\n *\n * @attr {boolean} checked - Checked state\n * @attr {boolean} disabled - Disable radio interaction\n * @attr {string} value - Field value (required for radio groups)\n * @attr {string} name - Form field name (required for radio groups)\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Radio size: 'sm' | 'md' | 'lg'\n * @attr {string} error - Error message (marks field as invalid)\n * @attr {string} helper - Helper text displayed below the radio\n *\n * @fires input - Emitted when radio is selected.\n * @fires change - Emitted when radio is selected.\n *\n * @slot - Radio button label text\n *\n * @cssprop --radio-size - Control size (width and height)\n * @cssprop --radio-bg - Unchecked background color\n * @cssprop --radio-border-color - Unchecked border color\n * @cssprop --radio-checked-bg - Selected indicator background color\n * @cssprop --radio-color - Selected indicator dot color\n * @cssprop --radio-font-size - Label font size\n * @part radio - The radio wrapper element\n * @part circle - The visual radio circle\n * @part label - The label element\n * @part helper-text - The helper/error text element\n *\n * @example\n * ```html\n * <ore-radio name=\"plan\" value=\"free\">Free</ore-radio>\n * <ore-radio name=\"plan\" value=\"pro\" checked color=\"primary\">Pro</ore-radio>\n * <ore-radio name=\"plan\" value=\"enterprise\" disabled>Enterprise</ore-radio>\n * ```\n */\nexport const RADIO_TAG = 'ore-radio' as const;\ndefine<OreRadioProps>(RADIO_TAG, {\n  formAssociated: true,\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...disablableBundle,\n    checked: prop.bool(false),\n    error: prop.string(),\n    helper: prop.string(),\n    name: prop.string(),\n    value: prop.string(),\n  },\n  setup(props) {\n    const el = getHost();\n\n    const groupCtx = inject(RADIO_GROUP_CTX);\n    const effectiveName = computed(() => groupCtx?.name.value || props.name.value || '');\n    const effectiveSize = computed(() => groupCtx?.size.value ?? props.size.value);\n    const effectiveColor = computed(() => groupCtx?.color.value ?? props.color.value);\n    const checkedFromState = computed(() => {\n      if (groupCtx) return groupCtx.value.value === props.value.value;\n\n      return Boolean(props.checked.value);\n    });\n\n    const getRadioGroup = (): HTMLElement[] => {\n      const radioName = effectiveName.value;\n\n      if (!radioName) return [];\n\n      return Array.from(document.querySelectorAll<HTMLElement>(`ore-radio[name=\"${radioName}\"]`)).filter(\n        (r) => !r.hasAttribute('disabled'),\n      );\n    };\n\n    const selectRadio = (radio: HTMLElement, originalEvent?: Event): void => {\n      if (groupCtx) {\n        groupCtx.select(radio.getAttribute('value') ?? '', originalEvent);\n\n        return;\n      }\n\n      radio.click();\n    };\n\n    const listControl = createListControl({\n      direction: () => elementDirection(el),\n      getItems: () => getRadioGroup(),\n      // 'both' accepts every arrow key regardless of the group's visual layout (radio groups\n      // may render horizontally or vertically via CSS) — RTL mirroring of Left/Right still\n      // applies via `direction` since nav.ts's default keymap covers 'both' too.\n      loop: true,\n      onNavigate: ({ event, item }) => {\n        item.focus();\n        selectRadio(item, event);\n      },\n      orientation: 'both',\n      signal: lifecycleSignal(onCleanup),\n    });\n\n    const activateSelf = (originalEvent?: Event): void => {\n      if (checkable.checked.value) return;\n\n      if (groupCtx) {\n        groupCtx.select(props.value.value ?? '', originalEvent);\n\n        return;\n      }\n\n      checkable.toggle(originalEvent ?? new Event('change'));\n    };\n\n    const checkable = createCheckable({\n      checked: checkedFromState,\n      disabled: computed(() => props.disabled.value || Boolean(groupCtx?.disabled.value)),\n      error: props.error,\n      helper: props.helper,\n      onToggle: (payload) => {\n        setFieldChecked(el, payload.checked);\n        dispatchNativeFieldEvent(el, 'input');\n        dispatchNativeFieldEvent(el, 'change');\n      },\n      prefix: 'radio',\n      signal: lifecycleSignal(onCleanup),\n      value: props.value,\n    });\n\n    checkable.attachFormField(\n      useField<string | null>({\n        disabled: checkable.disabled,\n        toFormValue: (v) => v,\n        value: checkable.checkableFormValue,\n      }),\n    );\n\n    const { assistiveId, checked, disabled, errorText, helperText, labelId, toggle } = checkable;\n\n    defineFieldChecked(\n      el,\n      () => checked.value,\n      (value) => {\n        checked.value = value;\n      },\n    );\n\n    bind({\n      attr: {\n        ariaChecked: () => (checked.value ? 'true' : 'false'),\n        ariaDescribedby: () => (errorText.value || helperText.value ? assistiveId : null),\n        ariaDisabled: () => (disabled.value ? 'true' : null),\n        ariaInvalid: () => (errorText.value ? 'true' : null),\n        ariaLabelledby: labelId,\n        checked,\n        color: effectiveColor,\n        disabled: () => (disabled.value ? true : undefined),\n        name: () => effectiveName.value || undefined,\n        role: 'radio',\n        size: effectiveSize,\n        tabindex: () => {\n          if (disabled.value) return undefined;\n\n          return checked.value ? 0 : -1;\n        },\n      },\n      class: () => ({\n        'is-checked': checked.value,\n        'is-disabled': disabled.value,\n      }),\n      on: {\n        click: (e: MouseEvent) => {\n          if (disabled.value) return;\n\n          if (groupCtx) {\n            groupCtx.select(props.value.value ?? '', e);\n          } else {\n            if (!effectiveName.value) return;\n\n            if (!checked.value) {\n              const radioName = props.name.value;\n              const allRadios = document.querySelectorAll<HTMLElement>(`ore-radio[name=\"${radioName}\"]`);\n\n              allRadios.forEach((radio) => {\n                if (radio !== el) radio.removeAttribute('checked');\n              });\n\n              toggle(e);\n            }\n          }\n        },\n        keydown: (e: KeyboardEvent) => {\n          if (e.key === ' ' || e.key === 'Enter') {\n            e.preventDefault();\n            activateSelf(e);\n\n            return;\n          }\n\n          const radios = getRadioGroup();\n\n          if (radios.length === 0) return;\n\n          const selfIndex = radios.indexOf(el);\n\n          if (selfIndex === -1) return;\n\n          listControl.set(selfIndex);\n          listControl.handleKeydown(e);\n        },\n      },\n    });\n\n    return html`\n      <div class=\"radio-wrapper\" part=\"radio\">\n        <div class=\"circle\" part=\"circle\">\n          <div class=\"dot\" part=\"dot\"></div>\n        </div>\n      </div>\n      <span class=\"label\" part=\"label\" id=\"${labelId}\"><slot></slot></span>\n      ${renderHelperRegion(assistiveId, errorText, helperText)}\n    `;\n  },\n  styles: [\n    colorThemeMixin,\n    forcedColorsFormControlMixin,\n    disabledStateMixin,\n    coarsePointerMixin,\n    sizeVariantMixin(CONTROL_SIZE_PRESET),\n    componentStyles,\n  ],\n});\n","@layer refine.base {\n  :host {\n    --_star-size: var(--rating-star-size, var(--size-7));\n    --_color-empty: var(--rating-color-empty, var(--color-contrast-200));\n    --_color-filled: var(--rating-color-filled, var(--_theme-base, var(--color-warning)));\n    --_gap: var(--rating-gap, var(--size-0_5));\n\n    display: inline-flex;\n    flex-wrap: wrap;\n    align-items: center;\n  }\n\n  .stars {\n    position: relative;\n    display: flex;\n    gap: var(--_gap);\n    align-items: center;\n  }\n\n  .sparkle-layer {\n    position: absolute;\n    inset: 0;\n    overflow: visible;\n    pointer-events: none;\n  }\n\n  .sparkle {\n    position: absolute;\n    pointer-events: none;\n    background: var(--_color-filled);\n    border-radius: 50%;\n    animation: var(--_motion-animation, sparkle-fly var(--_dur, 500ms) var(--ease-out) forwards);\n  }\n\n  @keyframes sparkle-fly {\n    from {\n      opacity: 0.9;\n      transform: translate(-50%, -50%) rotate(var(--_angle)) translateY(0) scale(1);\n    }\n\n    to {\n      opacity: 0;\n      transform: translate(-50%, -50%) rotate(var(--_angle)) translateY(calc(-1 * var(--_dist))) scale(0);\n    }\n  }\n\n  .star-btn {\n    all: unset;\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    width: var(--_star-size);\n    min-width: var(--_touch-target);\n    height: var(--_star-size);\n    min-height: var(--_touch-target);\n    color: var(--_color-empty);\n    cursor: pointer;\n    border-radius: var(--rounded-sm);\n    transition:\n      color var(--transition-fast),\n      transform 120ms var(--ease-spring);\n  }\n\n  .star-btn[data-filled] {\n    color: var(--_color-filled);\n  }\n\n  :host([solid]) .star-btn ore-icon::part(svg) {\n    fill: none;\n  }\n\n  :host([solid]) .star-btn[data-filled] ore-icon::part(svg) {\n    fill: currentcolor;\n  }\n\n  .star-btn:hover:not([disabled]),\n  .star-btn:focus-visible:not([disabled]) {\n    transform: scale(1.08);\n  }\n\n  .star-btn:focus-visible {\n    outline: var(--border-2) solid var(--_color-filled);\n    outline-offset: var(--border-2);\n  }\n\n  .star-btn[disabled] {\n    cursor: default;\n  }\n\n  :host([readonly]) .star-btn,\n  :host([disabled]) .star-btn {\n    pointer-events: none;\n  }\n\n  :host([disabled]) {\n    opacity: 0.5;\n  }\n}\n\n@layer refine.utilities {\n  :host([size='sm']) {\n    --_star-size: var(--size-5);\n  }\n\n  :host([size='lg']) {\n    --_star-size: var(--size-9);\n  }\n\n  @media (forced-colors: active) {\n    /* Distinguish filled vs unfilled stars with system button colors */\n    .star-btn {\n      color: ButtonText;\n    }\n\n    .star-btn[data-filled] {\n      color: Highlight;\n      forced-color-adjust: none;\n    }\n\n    .star-btn:focus-visible {\n      outline: 2px solid Highlight;\n      box-shadow: none;\n    }\n  }\n\n  /* ========================================\n       Helper / Error Text\n       ======================================== */\n\n  .helper-text[hidden] {\n    display: none;\n  }\n\n  .helper-text {\n    width: 100%;\n    margin-block-start: var(--size-1);\n    font-size: var(--text-xs);\n    line-height: var(--leading-tight);\n    color: color-mix(in oklch, var(--color-contrast-500) 80%, var(--color-canvas));\n  }\n\n  .helper-text[role='alert'] {\n    color: var(--color-error);\n  }\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .sparkle {\n    display: none;\n  }\n}\n","import { bind, createStableId, define, getHost, html, prop, useField } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { createErrorHelperState, createSliderControl } from '../../core';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport '../../content/icon/icon';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { coarsePointerMixin, colorThemeMixin, reducedMotionMixin, sizeVariantMixin } from '../../styles';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport { renderHelperRegion } from '../shared/templates';\nimport componentStyles from './rating.css?inline';\n\nexport type OreRatingEvents = {\n  change: Event;\n  input: Event;\n};\n\n/** Rating props */\nexport type OreRatingProps = {\n  /** Theme color */\n  color?: ThemeColor;\n  /** Disable interaction */\n  disabled?: boolean;\n  /** Error message — marks the field as invalid (fallback when the `error` slot is empty) */\n  error?: string;\n  /** Helper text displayed below the stars (fallback when the `helper` slot is empty) */\n  helper?: string;\n  /** Accessible group label */\n  label?: string;\n  /** Maximum rating (number of stars) */\n  max?: number;\n  /** Form field name */\n  name?: string;\n  /** Make rating read-only */\n  readonly?: boolean;\n  /** Component size */\n  size?: ComponentSize;\n  /** Render selected stars as solid-filled instead of outline-only */\n  solid?: boolean;\n  /** Current rating value */\n  value?: number;\n};\n\n/**\n * A star rating input.\n *\n * @element ore-rating\n *\n * @attr {number} value - Current rating value (default: 0)\n * @attr {number} max - Maximum number of stars (default: 5)\n * @attr {boolean} readonly - Read-only display mode\n * @attr {boolean} disabled - Disabled state\n * @attr {string} label - aria-label for the group (default: 'Rating')\n * @attr {string} color - Theme color for filled stars: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} name - Form field name\n * @attr {boolean} solid - Fill selected stars (outline remains default when omitted)\n * @attr {string} helper - Helper text below the stars\n * @attr {string} error - Error message below the stars\n *\n * @fires input - Emitted when the rating changes.\n * @fires change - Emitted when the rating changes.\n *\n * @cssprop --rating-star-size - Star diameter\n * @cssprop --rating-color-empty - Empty star color\n * @cssprop --rating-color-filled - Filled star color\n * @cssprop --rating-gap - Gap between stars\n *\n * @part stars - Stars container.\n * @part star - Star item element.\n * @part helper-text - The helper/error text element.\n * @example\n * ```html\n * <ore-rating value=\"3\" max=\"5\" color=\"warning\"></ore-rating>\n * <ore-rating value=\"4\" solid></ore-rating>\n * ```\n */\nexport const RATING_TAG = 'ore-rating' as const;\ndefine<OreRatingProps>(RATING_TAG, {\n  formAssociated: true,\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...disablableBundle,\n    error: prop.string(),\n    helper: prop.string(),\n    label: prop.string('Rating'),\n    max: prop.number(5),\n    name: prop.string(),\n    readonly: prop.bool(false),\n    solid: prop.bool(false),\n    value: prop.number(0),\n  },\n  setup(props) {\n    const el = getHost();\n    const normalizedValue = computed(() => {\n      const max = Math.max(1, Number(props.max?.value) || 5);\n      const raw = Number(props.value?.value);\n      const safe = Number.isFinite(raw) ? raw : 0;\n\n      return Math.min(max, Math.max(0, safe));\n    });\n\n    const isDisabled = computed(() => Boolean(props.disabled.value));\n\n    defineFieldValue(\n      el,\n      () => String(normalizedValue.value),\n      (value) => {\n        el.setAttribute('value', value);\n      },\n    );\n\n    useField({\n      disabled: isDisabled,\n      value: computed(() => String(normalizedValue.value || 0)),\n    });\n\n    const assistiveId = createStableId('helper');\n    const assistive = createErrorHelperState({ error: props.error, helper: props.helper });\n    const errorText = computed(() => assistive.value.errorText);\n    const helperText = computed(() => assistive.value.helperText);\n    const ariaDescribedBy = computed(() => (errorText.value || helperText.value ? assistiveId : null));\n\n    const isInteractive = computed(() => !props.readonly?.value && !isDisabled.value);\n    const hovered = signal<number | null>(null);\n    const displayValue = computed(() => hovered.value ?? normalizedValue.value);\n    const getStarButtons = () => {\n      return [...(el.shadowRoot?.querySelectorAll<HTMLButtonElement>('[data-star]') ?? [])];\n    };\n    const ratingControl = createSliderControl({\n      max: computed(() => Number(props.max?.value) || 5),\n      min: signal(1),\n      step: signal(1),\n    });\n\n    function spawnSparkles(star: number) {\n      const layer = el.shadowRoot?.querySelector<HTMLElement>('.sparkle-layer');\n      const btn = el.shadowRoot?.querySelector<HTMLElement>(`[data-star=\"${star}\"]`);\n\n      if (!layer || !btn) return;\n\n      const cx = btn.offsetLeft + btn.offsetWidth / 2;\n      const cy = btn.offsetTop + btn.offsetHeight / 2;\n      const count = 10;\n\n      for (let i = 0; i < count; i++) {\n        const p = document.createElement('span');\n        const angle = (360 / count) * i + (Math.random() * 30 - 15);\n        const dist = 18 + Math.random() * 20;\n        const size = 3 + Math.random() * 4;\n        const dur = 380 + Math.random() * 220;\n\n        p.className = 'sparkle';\n        p.style.cssText = [\n          `left:${cx}px`,\n          `top:${cy}px`,\n          `--_angle:${angle}deg`,\n          `--_dist:${dist}px`,\n          `width:${size}px`,\n          `height:${size}px`,\n          `--_dur:${dur}ms`,\n          `animation-delay:${Math.random() * 60}ms`,\n        ].join(';');\n        layer.appendChild(p);\n        p.addEventListener('animationend', () => p.remove(), { once: true });\n      }\n    }\n    function select(star: number, _originalEvent?: Event) {\n      if (!isInteractive.value) return;\n\n      const max = Math.max(1, Number(props.max?.value) || 5);\n      const nextValue = Math.min(max, Math.max(0, star));\n\n      if (nextValue === normalizedValue.value) return;\n\n      setFieldValue(el, String(nextValue));\n      dispatchNativeFieldEvent(el, 'input');\n      dispatchNativeFieldEvent(el, 'change');\n      spawnSparkles(nextValue);\n    }\n    function handleKeydown(e: KeyboardEvent, star: number) {\n      const next = ratingControl.nextFromKey(e.key, star);\n\n      if (next == null) return;\n\n      e.preventDefault();\n      select(next, e);\n\n      const buttons = getStarButtons();\n\n      buttons[next - 1]?.focus();\n    }\n\n    const stars = computed(() => {\n      const max = Number(props.max?.value) || 5;\n\n      return Array.from({ length: max }, (_, i) => i + 1);\n    });\n\n    bind({ attr: { size: props.size } });\n\n    return html`\n      <div\n        class=\"stars\"\n        part=\"stars\"\n        role=\"radiogroup\"\n        aria-label=\"${props.label}\"\n        aria-describedby=\"${ariaDescribedBy}\">\n        ${() =>\n          stars.value.map(\n            (star) => html`\n              <button\n                class=\"star-btn\"\n                part=\"star\"\n                type=\"button\"\n                role=\"radio\"\n                aria-label=\"${() => `${star} ${star === 1 ? 'star' : 'stars'}`}\"\n                aria-checked=\"${() => String(star === normalizedValue.value)}\"\n                data-star=\"${star}\"\n                ?data-filled=\"${() => star <= displayValue.value}\"\n                disabled=\"${() => (!isInteractive.value ? true : null)}\"\n                @click=\"${(e: Event) => select(star, e)}\"\n                @pointerenter=\"${() => {\n                  if (isInteractive.value) hovered.value = star;\n                }}\"\n                @pointerleave=\"${() => {\n                  hovered.value = null;\n                }}\"\n                @keydown=\"${(e: KeyboardEvent) => handleKeydown(e, star)}\">\n                <ore-icon name=\"star\" size=\"var(--_star-size)\" stroke-width=\"1.5\" aria-hidden=\"true\"></ore-icon>\n              </button>\n            `,\n          )}\n        <div class=\"sparkle-layer\"></div>\n      </div>\n      ${renderHelperRegion(assistiveId, errorText, helperText)}\n    `;\n  },\n  styles: [colorThemeMixin, sizeVariantMixin({}), coarsePointerMixin, reducedMotionMixin, componentStyles],\n});\n","@layer refine.base {\n  /* ========================================\n       Base Styles & Defaults\n       ======================================== */\n\n  /* No unconditional `width: 100%` here, on purpose — matches every other field's own `:host`\n     (`ore-input`, `ore-select`, `ore-number-input`, `ore-combobox`, `ore-date-picker`): shrink to\n     `min-width` by default, opt into full width via `:host([fullwidth])` below. A hardcoded\n     `width: 100%` here (the previous default) meant the slider always claimed the entire row in\n     a flex layout regardless of layout intent — e.g. sitting next to a label/hint column in a\n     settings-style row, it forced that column down to near its text's min-content width instead\n     of sharing the row the way a same-row `ore-select`/`ore-number-input` naturally does. */\n  :host {\n    --_size: var(--slider-size, var(--size-5));\n    --_height: var(--slider-height, var(--size-1));\n    --_track: var(--slider-track-bg, var(--color-contrast-300));\n    --_fill: var(--slider-fill, var(--color-neutral));\n    --_thumb: var(--slider-thumb-bg, var(--color-contrast-50));\n    --_thumb-size: var(--_size);\n    --_thumb-inset: var(--slider-thumb-inset, var(--size-2-5));\n    --_touch-target: var(--size-11);\n    --_font-size: var(--text-sm);\n    --_shadow: var(--color-neutral-focus-shadow);\n\n    position: relative;\n    display: inline-flex;\n    flex-wrap: wrap;\n    gap: var(--_gap, var(--size-3));\n    align-items: center;\n    min-width: var(--slider-min-width, 12rem);\n    touch-action: none;\n    cursor: pointer;\n    user-select: none;\n  }\n\n  /* Explicit opt-in still forces full width outside a stretching grid/flex context — same\n     convention as ore-input's own :host([fullwidth]). */\n  :host([fullwidth]) {\n    width: 100%;\n  }\n}\n\n/* ========================================\n     Track, Fill & Thumb\n     ======================================== */\n\n.slider-container {\n  position: relative;\n  box-sizing: border-box;\n  display: flex;\n  flex: 1;\n  align-items: center;\n  width: 100%;\n  min-height: var(--_touch-target);\n  padding-inline: var(--_thumb-inset);\n}\n\n.slider-track {\n  position: relative;\n  width: 100%;\n  height: var(--_height);\n  background: var(--_track);\n  border-radius: var(--rounded-full);\n}\n\n/* Fill: always driven by --_fill-start / --_fill-width */\n.slider-fill {\n  position: absolute;\n  top: 0;\n  left: var(--_fill-start, 0%);\n  width: var(--_fill-width, 0%);\n  height: 100%;\n  background: var(--_fill);\n  border-radius: var(--rounded-full);\n  transition: var(--_motion-transition, left var(--transition-fast), width var(--transition-fast));\n}\n\n:host([data-dragging]) .slider-fill {\n  transition: none;\n}\n\n.slider-thumb {\n  position: absolute;\n  top: 50%;\n  z-index: 1;\n  box-sizing: border-box;\n  width: var(--_thumb-size);\n  height: var(--_thumb-size);\n  cursor: grab;\n  background: var(--_thumb);\n  border: 2px solid var(--_fill);\n  border-radius: var(--rounded-full);\n  box-shadow: var(--shadow-sm);\n  transform: translate(-50%, -50%);\n  transition: var(--_motion-transition, box-shadow var(--transition-fast), left var(--transition-fast));\n  will-change: transform;\n}\n\n:host([data-dragging]) .slider-thumb {\n  cursor: grabbing;\n  box-shadow: var(--_shadow);\n  transition: var(--_motion-transition, box-shadow var(--transition-fast));\n}\n\n/* ── Single-value thumb ─────────────────────────────────── */\n\n.slider-thumb-sole {\n  left: var(--_thumb-pos, 0%);\n}\n\n:host(:focus-visible) .slider-thumb-sole,\n:host(:active) .slider-thumb-sole {\n  box-shadow: var(--_shadow);\n}\n\n/* ── Range thumbs ───────────────────────────────────────── */\n\n.slider-thumb-start {\n  left: var(--_thumb-start, 0%);\n}\n\n.slider-thumb-end {\n  left: var(--_thumb-end, 100%);\n}\n\n.slider-thumb-start:focus-visible,\n.slider-thumb-end:focus-visible {\n  z-index: 2;\n  outline: var(--border-2) solid var(--_fill);\n  outline-offset: var(--size-0-5);\n  box-shadow: var(--_shadow);\n}\n\n/* ── Visibility gating ──────────────────────────────────── */\n\n:host(:not([range])) .slider-thumb-start,\n:host(:not([range])) .slider-thumb-end {\n  display: none;\n}\n\n:host([range]) .slider-thumb-sole {\n  display: none;\n}\n\n@media (hover: hover) {\n  :host(:not([disabled])) .slider-thumb:hover {\n    box-shadow: var(--_shadow);\n  }\n}\n\n@media (forced-colors: active) {\n  :host(:focus-visible) .slider-thumb-sole,\n  .slider-thumb-start:focus-visible,\n  .slider-thumb-end:focus-visible {\n    outline: 2px solid Highlight;\n    outline-offset: 2px;\n    box-shadow: none;\n  }\n}\n\n@layer refine.overrides {\n  :host {\n    --_fill: var(--slider-fill, var(--_theme-base));\n    --_shadow: var(--_theme-shadow);\n  }\n}\n\n/* ========================================\n     Label\n     ======================================== */\n\n.label {\n  font-size: var(--_font-size);\n  color: var(--color-contrast);\n  white-space: nowrap;\n}\n\n.helper-text[hidden] {\n  display: none;\n}\n\n.helper-text {\n  width: 100%;\n  font-size: var(--text-xs);\n  line-height: var(--leading-tight);\n  color: color-mix(in oklch, var(--color-contrast-500) 80%, var(--color-canvas));\n}\n\n.helper-text[role='alert'] {\n  color: var(--color-error);\n}\n","import {\n  bind,\n  createStableId,\n  define,\n  getHost,\n  html,\n  onCleanup,\n  onEvent,\n  onMounted,\n  prop,\n  ref,\n  useField,\n  useSlots,\n} from '@vielzeug/ore';\nimport { computed, signal, watch } from '@vielzeug/ripple';\nimport { createErrorHelperState, createSliderControl } from '../../core';\nimport { disablableBundle, SLIDER_SIZE_PRESET, sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, disabledStateMixin, reducedMotionMixin, sizeVariantMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor } from '../../types';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport { renderHelperRegion } from '../shared/templates';\nimport componentStyles from './slider.css?inline';\n\nconst guard =\n  <E extends Event = Event>(condition: () => unknown, handler: (e: E) => void): ((e: E) => void) =>\n  (e) => {\n    if (condition()) handler(e);\n  };\n\n/** Slider component properties */\n\nexport type OreSliderEvents = {\n  change: Event;\n  input: Event;\n};\n\nexport type OreSliderProps = {\n  /** Theme color */\n  color?: ThemeColor;\n  /** Disable interaction */\n  disabled?: boolean;\n  /** Error message — marks the field as invalid (fallback when the `error` slot is empty) */\n  error?: string;\n  /** Range mode: lower bound */\n  from?: number | string;\n  /** Range mode a11y label for the start thumb (e.g. \"$20\") */\n  'from-value-text'?: string;\n  /** Stretch to full width of container */\n  fullwidth?: boolean;\n  /** Helper text displayed below the slider (fallback when the `helper` slot is empty) */\n  helper?: string;\n  /** Maximum value */\n  max?: number | string;\n  /** Minimum value */\n  min?: number | string;\n  /** Single-value mode: form field name */\n  name?: string;\n  /** Activate two-thumb range selection */\n  range?: boolean;\n  /** Component size */\n  size?: ComponentSize;\n  /** Step increment */\n  step?: number | string;\n  /** Range mode: upper bound */\n  to?: number | string;\n  /** Range mode a11y label for the end thumb (e.g. \"$80\") */\n  'to-value-text'?: string;\n  /** Single-value mode: current value */\n  value?: number | string;\n  /** Single-value mode a11y label override (e.g. \"75%\"). Overrides raw aria-valuenow. */\n  'value-text'?: string;\n};\n\n/**\n * A slider for selecting a single numeric value or a numeric range.\n *\n * Add the boolean `range` attribute to activate two-thumb range mode.\n *\n * @element ore-slider\n *\n * @attr {number}  min   - Minimum value (default: 0)\n * @attr {number}  max   - Maximum value (default: 100)\n * @attr {number}  step  - Step increment (default: 1)\n * @attr {number}  value - Current value (single mode)\n * @attr {number}  from  - Lower bound (range mode)\n * @attr {number}  to    - Upper bound (range mode)\n * @attr {boolean} range - Activate range mode\n * @attr {boolean} disabled - Disable interaction\n * @attr {string}  name  - Form field name (single mode)\n * @attr {string}  color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string}  size  - 'sm' | 'md' | 'lg'\n * @attr {string}  helper - Helper text below the slider\n * @attr {string}  error  - Error message below the slider\n * @attr {boolean} fullwidth - Stretch to full width of container\n *\n * @fires input - Emitted when the slider value changes.\n * @fires change - Emitted when the slider value changes.\n *\n * @slot - Slider label text\n *\n * @part slider      - Slider container\n * @part track       - Track element\n * @part fill        - Fill element\n * @part thumb       - Single-value thumb\n * @part thumb-start - Range start thumb\n * @part thumb-end   - Range end thumb\n * @part label       - Label element\n * @part helper-text - The helper/error text element\n *\n * @cssprop --slider-height    - Track height\n * @cssprop --slider-size      - Thumb dimensions\n * @cssprop --slider-track-bg  - Track background color\n * @cssprop --slider-fill      - Active fill color\n * @cssprop --slider-thumb-bg  - Thumb background color\n *\n * @example\n * ```html\n * <ore-slider value=\"50\" name=\"volume\">Volume</ore-slider>\n * <ore-slider range from=\"20\" to=\"80\" color=\"primary\">Price range</ore-slider>\n * ```\n */\nexport const SLIDER_TAG = 'ore-slider' as const;\ndefine<OreSliderProps>(SLIDER_TAG, {\n  formAssociated: true,\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...disablableBundle,\n    error: prop.string(),\n    from: prop.number(0),\n    'from-value-text': prop.string(),\n    fullwidth: prop.bool(false),\n    helper: prop.string(),\n    max: prop.number(100),\n    min: prop.number(0),\n    name: prop.string(),\n    range: prop.bool(false),\n    step: prop.number(1),\n    to: prop.number(100),\n    'to-value-text': prop.string(),\n    value: prop.number(0),\n    'value-text': prop.string(),\n  },\n  setup(props) {\n    const el = getHost();\n    const slots = useSlots();\n\n    // Treat `range` as static — determined at first render\n    const isRange = props.range.value;\n    // ── Shared helpers ────────────────────────────────────────────\n    const sliderControl = createSliderControl({\n      max: props.max,\n      min: props.min,\n      step: props.step,\n    });\n    // ── Single-value state ────────────────────────────────────────\n    const isDragging = signal(false);\n    const isDisabled = computed(() => Boolean(props.disabled.value));\n    const labelledById = signal<string | undefined>(undefined);\n    const assistiveId = createStableId('helper');\n    const assistive = createErrorHelperState({ error: props.error, helper: props.helper });\n    const errorText = computed(() => assistive.value.errorText);\n    const helperText = computed(() => assistive.value.helperText);\n    const ariaDescribedBy = computed(() => (errorText.value || helperText.value ? assistiveId : null));\n\n    bind({\n      attr: {\n        'data-dragging': () => (isDragging.value ? true : undefined),\n        size: props.size,\n      },\n    });\n\n    const valueSignal = signal('0');\n\n    if (!isRange) {\n      useField({ disabled: isDisabled, value: valueSignal });\n      watch(\n        props.value,\n        (v) => {\n          valueSignal.value = String(v);\n        },\n        { immediate: true },\n      );\n      bind({\n        attr: {\n          ariaDescribedby: () => ariaDescribedBy.value ?? null,\n          ariaDisabled: () => (isDisabled.value ? 'true' : null),\n          ariaLabelledby: () => labelledById.value ?? null,\n          ariaValuemax: () => sliderControl.max(),\n          ariaValuemin: () => sliderControl.min(),\n          ariaValuenow: () => Number(valueSignal.value || 0),\n          ariaValuetext: () => props['value-text'].value ?? null,\n          role: () => 'slider',\n          tabindex: () => (isDisabled.value ? null : '0'),\n        },\n      });\n    }\n\n    // ── Range state ───────────────────────────────────────────────\n    const startVal = signal(0);\n    const endVal = signal(100);\n\n    defineFieldValue(\n      el,\n      () => (isRange ? `${startVal.value},${endVal.value}` : valueSignal.value),\n      (value) => {\n        if (isRange) {\n          const [from, to] = value.split(',').map(Number);\n\n          if (Number.isFinite(from)) startVal.value = sliderControl.snap(from);\n\n          if (Number.isFinite(to)) endVal.value = sliderControl.snap(to);\n\n          return;\n        }\n\n        const next = Number(value);\n\n        if (Number.isFinite(next)) valueSignal.value = String(sliderControl.snap(next));\n      },\n    );\n\n    if (isRange) {\n      useField<{\n        from: number;\n        to: number;\n      }>({\n        disabled: isDisabled,\n        toFormValue: ({ from, to }) => {\n          const name = props.name.value;\n\n          if (!name) return null;\n\n          const fd = new FormData();\n\n          fd.append(`${name}[from]`, String(from));\n          fd.append(`${name}[to]`, String(to));\n\n          return fd;\n        },\n        value: computed(() => ({ from: startVal.value, to: endVal.value })),\n      });\n      watch(\n        props.from,\n        (v) => {\n          startVal.value = sliderControl.snap(Number(v));\n        },\n        { immediate: true },\n      );\n      watch(\n        props.to,\n        (v) => {\n          endVal.value = sliderControl.snap(Number(v));\n        },\n        { immediate: true },\n      );\n    }\n\n    // ── Refs ──────────────────────────────────────────────────────\n    const containerRef = ref<HTMLDivElement>();\n    const labelRef = ref<HTMLSpanElement>();\n    const trackRef = ref<HTMLDivElement>();\n    const thumbStartRef = ref<HTMLDivElement>();\n    const thumbEndRef = ref<HTMLDivElement>();\n    const startId = createStableId('slider-start');\n    const endId = createStableId('slider-end');\n    // ── CSS update helpers ────────────────────────────────────────\n    const updateSingleCSS = (value: number) => {\n      const pct = sliderControl.toPercent(value);\n\n      el.style.setProperty('--_thumb-pos', `${pct}%`);\n      el.style.setProperty('--_fill-start', '0%');\n      el.style.setProperty('--_fill-width', `${pct}%`);\n    };\n    const updateRangeCSS = () => {\n      const s = sliderControl.toPercent(startVal.value);\n      const e = sliderControl.toPercent(endVal.value);\n\n      el.style.setProperty('--_thumb-start', `${s}%`);\n      el.style.setProperty('--_thumb-end', `${e}%`);\n      el.style.setProperty('--_fill-start', `${s}%`);\n      el.style.setProperty('--_fill-width', `${e - s}%`);\n    };\n    const emitValueChange = () => {\n      const value = isRange ? `${startVal.value},${endVal.value}` : valueSignal.value;\n\n      setFieldValue(el, value);\n      dispatchNativeFieldEvent(el, 'input');\n      dispatchNativeFieldEvent(el, 'change');\n    };\n\n    // ── Range mode setup ──────────────────────────────────────────\n    const setupRangeMode = (container: HTMLDivElement, track: HTMLDivElement) => {\n      updateRangeCSS();\n\n      const clientToValue = (clientX: number) => {\n        const rect = track.getBoundingClientRect();\n\n        return sliderControl.fromClientX(clientX, rect);\n      };\n      let dragging: 'start' | 'end' | null = null;\n      const applyDrag = (val: number) => {\n        if (dragging === 'start') startVal.value = Math.min(sliderControl.snap(val), endVal.value);\n        else if (dragging === 'end') endVal.value = Math.max(sliderControl.snap(val), startVal.value);\n\n        startVal.value = sliderControl.clamp(startVal.value);\n        endVal.value = sliderControl.clamp(endVal.value);\n        updateRangeCSS();\n        emitValueChange();\n      };\n\n      onEvent(\n        container,\n        'pointerdown',\n        guard(\n          () => !isDisabled.value,\n          (e: PointerEvent) => {\n            e.preventDefault();\n\n            const val = clientToValue(e.clientX);\n\n            dragging = Math.abs(val - startVal.value) <= Math.abs(val - endVal.value) ? 'start' : 'end';\n            (e.target as Element).setPointerCapture(e.pointerId);\n            applyDrag(val);\n          },\n        ),\n      );\n      onEvent(\n        container,\n        'pointermove',\n        guard(\n          () => !!dragging,\n          (e: PointerEvent) => {\n            e.preventDefault();\n\n            if (!isDragging.value) isDragging.value = true;\n\n            applyDrag(clientToValue(e.clientX));\n          },\n        ),\n      );\n      onEvent(\n        container,\n        'pointerup',\n        guard(\n          () => !!dragging,\n          (e: PointerEvent) => {\n            e.preventDefault();\n            dragging = null;\n            isDragging.value = false;\n            (e.target as Element).releasePointerCapture(e.pointerId);\n          },\n        ),\n      );\n\n      const makeThumbKeydown = (getVal: () => number, setVal: (v: number) => void) => (e: KeyboardEvent) => {\n        if (isDisabled.value) return;\n\n        const next = sliderControl.nextFromKey(e.key, getVal());\n\n        if (next === null) return;\n\n        e.preventDefault();\n        setVal(sliderControl.snap(next));\n        updateRangeCSS();\n        emitValueChange();\n      };\n      const thumbStartEl = thumbStartRef.value;\n      const thumbEndEl = thumbEndRef.value;\n\n      if (thumbStartEl) {\n        onEvent(\n          thumbStartEl,\n          'keydown',\n          makeThumbKeydown(\n            () => startVal.value,\n            (v) => {\n              startVal.value = Math.min(v, endVal.value);\n            },\n          ),\n        );\n        onCleanup(\n          bind(\n            {\n              aria: {\n                label: 'Range start',\n                valuemax: () => endVal.value,\n                valuemin: () => sliderControl.min(),\n                valuenow: () => startVal.value,\n                valuetext: () => props['from-value-text'].value ?? null,\n              },\n            },\n            { target: thumbStartEl },\n          ),\n        );\n      }\n\n      if (thumbEndEl) {\n        onEvent(\n          thumbEndEl,\n          'keydown',\n          makeThumbKeydown(\n            () => endVal.value,\n            (v) => {\n              endVal.value = Math.max(v, startVal.value);\n            },\n          ),\n        );\n        onCleanup(\n          bind(\n            {\n              aria: {\n                label: 'Range end',\n                valuemax: () => sliderControl.max(),\n                valuemin: () => startVal.value,\n                valuenow: () => endVal.value,\n                valuetext: () => props['to-value-text'].value ?? null,\n              },\n            },\n            { target: thumbEndEl },\n          ),\n        );\n      }\n    };\n    // ── Single-value mode setup ───────────────────────────────────\n    const setupSingleMode = (container: HTMLDivElement, track: HTMLDivElement) => {\n      updateSingleCSS(Number(valueSignal.value));\n\n      const updateValue = (clientX: number) => {\n        if (isDisabled.value) return;\n\n        const rect = track.getBoundingClientRect();\n        const newValue = sliderControl.fromClientX(clientX, rect);\n\n        if (Number(valueSignal.value) !== newValue) {\n          valueSignal.value = newValue.toString();\n          updateSingleCSS(newValue);\n          emitValueChange();\n        }\n      };\n      let isPointerDragging = false;\n\n      onEvent(\n        container,\n        'pointerdown',\n        guard(\n          () => !isDisabled.value,\n          (e: PointerEvent) => {\n            e.preventDefault();\n            isPointerDragging = true;\n            updateValue(e.clientX);\n            (e.target as Element).setPointerCapture(e.pointerId);\n          },\n        ),\n      );\n      onEvent(\n        container,\n        'pointermove',\n        guard(\n          () => isPointerDragging,\n          (e: PointerEvent) => {\n            e.preventDefault();\n\n            if (!isDragging.value) isDragging.value = true;\n\n            updateValue(e.clientX);\n          },\n        ),\n      );\n      onEvent(\n        container,\n        'pointerup',\n        guard(\n          () => isPointerDragging,\n          (e: PointerEvent) => {\n            e.preventDefault();\n            isPointerDragging = false;\n            isDragging.value = false;\n            (e.target as Element).releasePointerCapture(e.pointerId);\n          },\n        ),\n      );\n      onEvent(\n        el,\n        'keydown',\n        guard(\n          () => !isDisabled.value,\n          (e: KeyboardEvent) => {\n            const val = Number(valueSignal.value || 0);\n            const next = sliderControl.nextFromKey(e.key, val);\n\n            if (next === null) return;\n\n            e.preventDefault();\n\n            const newValue = sliderControl.clamp(next);\n\n            if (newValue !== val) {\n              valueSignal.value = newValue.toString();\n              updateSingleCSS(newValue);\n              emitValueChange();\n            }\n          },\n        ),\n      );\n    };\n\n    onMounted(() => {\n      const container = containerRef.value;\n      const track = trackRef.value;\n\n      if (!container || !track) return;\n\n      if (slots.has().value && labelRef.value) {\n        const labelId = createStableId('slider-label');\n\n        labelRef.value.id = labelId;\n\n        if (!isRange) labelledById.value = labelId;\n      }\n\n      if (isRange) setupRangeMode(container, track);\n      else setupSingleMode(container, track);\n    });\n\n    return html`\n      <div class=\"slider-container\" part=\"slider\" ref=${containerRef}>\n        <div class=\"slider-track\" part=\"track\" ref=${trackRef}>\n          <div class=\"slider-fill\" part=\"fill\"></div>\n          <div class=\"slider-thumb slider-thumb-sole\" part=\"thumb\"></div>\n          <div\n            class=\"slider-thumb slider-thumb-start\"\n            part=\"thumb-start\"\n            ref=${thumbStartRef}\n            role=\"slider\"\n            tabindex=\"${() => (isDisabled.value ? '-1' : '0')}\"\n            aria-describedby=\"${ariaDescribedBy}\"\n            id=\"${startId}\"></div>\n          <div\n            class=\"slider-thumb slider-thumb-end\"\n            part=\"thumb-end\"\n            ref=${thumbEndRef}\n            role=\"slider\"\n            tabindex=\"${() => (isDisabled.value ? '-1' : '0')}\"\n            aria-describedby=\"${ariaDescribedBy}\"\n            id=\"${endId}\"></div>\n        </div>\n      </div>\n      <span class=\"label\" part=\"label\" ref=${labelRef}><slot></slot></span>\n      ${renderHelperRegion(assistiveId, errorText, helperText)}\n    `;\n  },\n  styles: [\n    disabledStateMixin,\n    colorThemeMixin,\n    sizeVariantMixin(SLIDER_SIZE_PRESET),\n    componentStyles,\n    reducedMotionMixin,\n  ],\n});\n","@layer refine.base {\n  :host {\n    --_width: var(--switch-width, var(--size-10));\n    --_height: var(--switch-height, var(--size-5));\n    --_padding: var(--size-0-5);\n    --_thumb-size: calc(var(--_height) - var(--_padding) * 2);\n    --_track-bg: var(--switch-track-bg, var(--color-contrast-300));\n    --_thumb-bg: var(--switch-thumb-bg, white);\n    --_font-size: var(--switch-font-size, var(--text-sm));\n\n    display: inline-flex;\n    flex-wrap: wrap;\n    gap: var(--_gap, var(--size-2-5));\n    align-items: center;\n    min-height: var(--_touch-target);\n    touch-action: manipulation;\n    cursor: pointer;\n    user-select: none;\n  }\n\n  /* ========================================\n       Track & Thumb\n       ======================================== */\n\n  .switch-wrapper {\n    display: flex;\n    flex-shrink: 0;\n  }\n\n  .switch-track {\n    position: relative;\n    width: var(--_width);\n    height: var(--_height);\n    background: var(--_track-bg);\n    border-radius: var(--rounded-full);\n    transition:\n      background var(--transition-normal),\n      box-shadow var(--transition-normal);\n  }\n\n  .switch-thumb {\n    position: absolute;\n    inset-inline-start: var(--_padding);\n    top: var(--_padding);\n    width: var(--_thumb-size);\n    height: var(--_thumb-size);\n    background: var(--_thumb-bg);\n    border-radius: var(--rounded-full);\n    box-shadow: var(--shadow-sm);\n    transition:\n      transform var(--transition-spring),\n      box-shadow var(--transition-normal);\n    will-change: transform;\n  }\n\n  /* ========================================\n       Focus State\n       ======================================== */\n\n  :host(:focus-visible) .switch-track {\n    box-shadow: var(--_focus-shadow);\n  }\n\n  /* ========================================\n       Label\n       ======================================== */\n\n  .label {\n    font-size: var(--_font-size);\n    color: var(--color-contrast);\n  }\n}\n\n@layer refine.overrides {\n  /* Map theme variables to switch-specific variables */\n  :host {\n    --_active-bg: var(--switch-checked-bg, var(--_theme-base));\n    --_focus-shadow: var(--_theme-shadow);\n  }\n\n  /* ========================================\n       Checked State\n       ======================================== */\n\n  :host([checked]) .switch-track {\n    background: var(--_active-bg);\n  }\n\n  :host([checked]) .switch-thumb {\n    transform: translateX(calc(var(--_width) - var(--_height)));\n  }\n\n  /* In RTL the thumb starts at the inline-end edge; slide left to reach inline-start */\n  :host(:dir(rtl)[checked]) .switch-thumb {\n    transform: translateX(calc(-1 * (var(--_width) - var(--_height))));\n  }\n\n  /* ========================================\n       Hover & Active States\n       ======================================== */\n\n  :host(:hover:not([disabled], [checked])) .switch-track {\n    background: var(--color-contrast-400);\n  }\n\n  :host(:hover:not([disabled])[checked]) .switch-track {\n    filter: brightness(1.1);\n  }\n\n  /* ========================================\n       Helper / Error Text\n       ======================================== */\n\n  .helper-text[hidden] {\n    display: none;\n  }\n\n  .helper-text {\n    width: 100%;\n    padding-inline-start: calc(var(--_width) + var(--size-2-5));\n    font-size: var(--text-xs);\n    line-height: var(--leading-tight);\n    color: color-mix(in oklch, var(--color-contrast-500) 80%, var(--color-canvas));\n  }\n\n  .helper-text[role='alert'] {\n    color: var(--color-error);\n  }\n}\n","import { define, getHost, html, onCleanup, prop, useField } from '@vielzeug/ore';\nimport { createCheckable, lifecycleSignal } from '../../core';\nimport { disablableBundle, SWITCH_SIZE_PRESET, sizableBundle, themableBundle } from '../../shared';\nimport {\n  coarsePointerMixin,\n  colorThemeMixin,\n  disabledStateMixin,\n  forcedColorsFormControlMixin,\n  sizeVariantMixin,\n} from '../../styles';\nimport type { CheckableProps, ComponentSize, ThemeColor } from '../../types';\nimport { applyCheckableBinding } from '../shared/field-binding';\nimport { defineFieldChecked, dispatchNativeFieldEvent, setFieldChecked } from '../shared/native-field-event';\nimport { renderHelperRegion } from '../shared/templates';\nimport componentStyles from './switch.css?inline';\n\nexport type OreSwitchEvents = {\n  change: Event;\n  input: Event;\n};\n\nexport type OreSwitchProps = CheckableProps & {\n  /** Theme color */\n  color?: ThemeColor;\n  /** Disable interaction */\n  disabled?: boolean;\n  /** Error message (marks field as invalid) */\n  error?: string;\n  /** Helper text displayed below the switch */\n  helper?: string;\n  /** Component size */\n  size?: ComponentSize;\n};\n\n/**\n * A toggle switch component for binary on/off states.\n *\n * @element ore-switch\n *\n * @attr {boolean} checked - Checked/on state\n * @attr {boolean} disabled - Disable switch interaction\n * @attr {string} value - Field value\n * @attr {string} name - Form field name\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Switch size: 'sm' | 'md' | 'lg'\n * @attr {string} error - Error message (marks field as invalid)\n * @attr {string} helper - Helper text displayed below the switch\n *\n * @fires input - Emitted when switch is toggled.\n * @fires change - Emitted when switch is toggled.\n *\n * @slot - Switch label text\n *\n * @cssprop --switch-width - Track width\n * @cssprop --switch-height - Track height\n * @cssprop --switch-track-bg - Inactive track background color\n * @cssprop --switch-checked-bg - Active/checked track background color\n * @cssprop --switch-thumb-bg - Thumb background color\n * @cssprop --switch-font-size - Label font size\n * @part switch - The switch wrapper element\n * @part track - The switch track element\n * @part thumb - The switch thumb element\n * @part label - The label element\n * @part helper-text - The helper/error text element\n *\n * @example\n * ```html\n * <ore-switch name=\"notifications\" checked color=\"primary\">Enable notifications</ore-switch>\n * <ore-switch name=\"darkMode\" size=\"sm\">Dark mode</ore-switch>\n * <ore-switch disabled helper=\"Contact admin to change\">Admin only</ore-switch>\n * ```\n */\nexport const SWITCH_TAG = 'ore-switch' as const;\ndefine<OreSwitchProps>(SWITCH_TAG, {\n  formAssociated: true,\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...disablableBundle,\n    checked: prop.bool(false),\n    error: prop.string(),\n    helper: prop.string(),\n    name: prop.string(),\n    value: prop.string('on'),\n  },\n  setup(props) {\n    const el = getHost();\n\n    const checkable = createCheckable({\n      checked: props.checked,\n      clearIndeterminateFirst: false,\n      disabled: props.disabled,\n      error: props.error,\n      helper: props.helper,\n      onToggle: (payload) => {\n        checkable.triggerValidation('change');\n        setFieldChecked(el, payload.checked);\n        dispatchNativeFieldEvent(el, 'input');\n        dispatchNativeFieldEvent(el, 'change');\n      },\n      prefix: 'switch',\n      signal: lifecycleSignal(onCleanup),\n      value: props.value,\n    });\n\n    checkable.attachFormField(\n      useField<string | null>({\n        disabled: checkable.disabled,\n        toFormValue: (v) => v,\n        value: checkable.checkableFormValue,\n      }),\n    );\n\n    const { assistiveId, checked, disabled, errorText, handleClick, handleKeydown, helperText, labelId } = checkable;\n\n    defineFieldChecked(\n      el,\n      () => checked.value,\n      (value) => {\n        checked.value = value;\n      },\n    );\n\n    applyCheckableBinding(\n      props.size,\n      { assistiveId, checked, disabled, errorText, handleClick, handleKeydown, helperText, labelId },\n      'switch',\n    );\n\n    return html`\n      <div class=\"switch-wrapper\" part=\"switch\">\n        <div class=\"switch-track\" part=\"track\">\n          <div class=\"switch-thumb\" part=\"thumb\"></div>\n        </div>\n      </div>\n      <span class=\"label\" part=\"label\" id=\"${labelId}\"><slot></slot></span>\n      ${renderHelperRegion(assistiveId, errorText, helperText)}\n    `;\n  },\n  styles: [\n    colorThemeMixin,\n    forcedColorsFormControlMixin,\n    disabledStateMixin,\n    coarsePointerMixin,\n    sizeVariantMixin(SWITCH_SIZE_PRESET),\n    componentStyles,\n  ],\n});\n","@layer refine.base {\n  :host {\n    --_font-size: var(--textarea-font-size, var(--text-sm));\n    --_gap: var(--textarea-gap, var(--size-2));\n    --_padding: var(--textarea-padding, var(--size-2) var(--size-3));\n    --_radius: var(--textarea-radius, var(--rounded-lg));\n    --_placeholder: var(--textarea-placeholder-color, var(--color-contrast-500));\n    --_bg: var(--textarea-bg, var(--color-contrast-100));\n    --_border-color: var(--textarea-border-color, var(--color-contrast-300));\n    --_min-height: var(--textarea-min-height, var(--size-24));\n    --_max-height: var(--textarea-max-height, none);\n    --_resize: var(--textarea-resize, vertical);\n\n    display: inline-flex;\n    flex-direction: column;\n    align-items: stretch;\n    min-width: 12rem;\n  }\n\n  .textarea-wrapper {\n    display: flex;\n    flex-direction: column;\n    gap: var(--size-1);\n    min-width: 0; /* Allow shrinking below content size */\n  }\n\n  /* Inset placement (default): label positioned inside field border */\n  :host(:not([label-placement='outside'])) .textarea-wrapper {\n    position: relative;\n  }\n\n  :host(:not([label-placement='outside'])) .label {\n    position: absolute;\n    inset-block-start: var(--size-2);\n    inset-inline-start: var(--_padding-x, var(--size-3));\n    z-index: 1;\n    pointer-events: none;\n  }\n\n  :host(:not([label-placement='outside'])) .textarea-wrapper:has(.label:not([hidden])) .field {\n    padding-block-start: calc(var(--size-2) + 1lh + 2px);\n  }\n\n  .field {\n    position: relative;\n    box-sizing: border-box;\n    display: grid; /* Grid automatically sizes to content */\n    min-width: 0; /* Allow shrinking */\n    padding: var(--_padding);\n    background: var(--_bg);\n    border: var(--border) solid var(--_border-color);\n    border-radius: var(--_radius);\n    box-shadow: var(--shadow-2xs);\n    transition:\n      background var(--transition-fast),\n      backdrop-filter var(--transition-fast),\n      border-color var(--transition-fast),\n      box-shadow var(--transition-fast);\n  }\n\n  /* ========================================\n       Status Icon & Loading Spinner (top-right corner — clear of the\n       bottom-right native resize handle)\n       ======================================== */\n\n  .status-icon,\n  .field-spinner {\n    position: absolute;\n    inset-block-start: var(--size-2);\n    inset-inline-end: var(--size-2);\n  }\n\n  .status-icon {\n    display: none;\n    align-items: center;\n    justify-content: center;\n    width: var(--size-5);\n    height: var(--size-5);\n  }\n\n  :host([error]:not([error=''])) .status-icon,\n  :host([success]) .status-icon {\n    display: flex;\n  }\n\n  .status-icon[data-status='error'] {\n    color: var(--color-error);\n  }\n\n  .status-icon[data-status='success'] {\n    color: var(--color-success);\n  }\n\n  /* Keyframe must live in shadow DOM — @keyframes don't inherit across shadow roots */\n  @keyframes spin {\n    to {\n      transform: rotate(360deg);\n    }\n  }\n\n  .field-spinner {\n    display: none;\n    width: var(--size-4);\n    height: var(--size-4);\n    border: var(--border-2) solid var(--_theme-focus, currentcolor);\n    border-inline-end-color: transparent;\n    border-radius: 50%;\n    animation: var(--_motion-animation, spin var(--transition-loader) infinite);\n  }\n\n  :host([loading]) .field-spinner {\n    display: inline-block;\n  }\n\n  /* ========================================\n       Label Styles\n       ======================================== */\n\n  .label,\n  label.label {\n    /* Default: inset style */\n    margin-bottom: 2px;\n    font-size: var(--text-xs);\n    font-weight: var(--font-medium);\n    line-height: var(--leading-tight);\n    color: var(--color-contrast-500);\n    cursor: pointer;\n    user-select: none;\n    transition: color var(--transition-fast);\n  }\n\n  /* Outside placement overrides */\n  :host([label-placement='outside']) .label,\n  :host([label-placement='outside']) label.label {\n    margin-bottom: 0;\n    font-size: var(--text-sm);\n    line-height: var(--leading-none);\n  }\n\n  /* ========================================\n       Helper / Error Text\n       ======================================== */\n\n  .helper-text[hidden] {\n    display: none;\n  }\n\n  .helper-text {\n    padding-inline: 2px;\n    font-size: var(--text-xs);\n    line-height: var(--leading-tight);\n    color: color-mix(in oklch, var(--color-contrast-500) 80%, var(--color-canvas));\n  }\n\n  /* ========================================\n       Textarea Element\n       ======================================== */\n\n  textarea {\n    box-sizing: border-box;\n    min-width: 12rem; /* Match :host min-width to prevent resize below minimum */\n    min-height: var(--_min-height);\n    max-height: var(--_max-height);\n    padding: 0;\n    font: inherit;\n    font-size: var(--_font-size);\n    line-height: var(--leading-relaxed);\n    color: var(--textarea-color, var(--text-color-body));\n    resize: vertical; /* Default resize, can be overridden by inline style */\n    outline: none;\n    background: transparent;\n    border: none;\n  }\n\n  textarea::placeholder {\n    color: var(--_placeholder);\n    transition: color var(--transition-fast);\n  }\n\n  textarea:focus-visible {\n    outline: none;\n  }\n\n  /* ========================================\n       Character Counter\n       ======================================== */\n\n  .counter {\n    align-self: flex-end;\n    padding-inline: 2px;\n    margin-top: var(--size-1);\n    font-size: var(--text-xs);\n    line-height: var(--leading-tight);\n    color: var(--color-contrast-400);\n    transition: color var(--transition-fast);\n  }\n\n  .counter.near-limit {\n    color: var(--color-warning);\n  }\n\n  .counter.at-limit {\n    color: var(--color-error);\n  }\n\n  /* ========================================\n       Hover & Focus States\n       ======================================== */\n\n  :host(:not([disabled], [variant='bordered'], [variant='flat'])) .field:hover {\n    border-color: var(--color-contrast-400);\n  }\n\n  :host(:not([disabled])) .field:focus-within ~ .label,\n  :host(:not([disabled])) .textarea-wrapper:has(.field:focus-within) .label {\n    color: var(--_theme-focus);\n  }\n\n  /* Error State */\n  :host([error]:not([error=''])) .field {\n    border-color: var(--color-error);\n  }\n\n  :host([error]:not([error=''])) .label {\n    color: var(--color-error);\n  }\n\n  /* Success State */\n  :host([success]) .field {\n    border-color: var(--color-success);\n  }\n}\n\n/*\n * Focus/error/success `box-shadow` on `.field` — moved out of `@layer refine.base` into\n * `refine.variants` (alongside `fieldVariantMixin`'s rest-state `box-shadow` for solid/outline/\n * ghost) so normal specificity decides the winner. Cascade layers beat specificity outright, so\n * a `refine.base` box-shadow here always lost to every variant's unconditional rest-state\n * `box-shadow`, focused/error/success or not — the same bug class fixed for `ore-otp-input`'s\n * focus ring.\n */\n@layer refine.variants {\n  :host(:not([disabled], [variant='flat'])) .field:focus-within {\n    background: var(--color-canvas);\n    border-color: var(--_theme-focus);\n    box-shadow: var(--_theme-shadow, var(--color-primary-focus-shadow));\n  }\n\n  :host([error]:not([error=''])) .field:focus-within {\n    border-color: var(--color-error);\n    box-shadow: var(--color-error-focus-shadow);\n  }\n\n  :host([success]) .field:focus-within {\n    border-color: var(--color-success);\n    box-shadow: var(--color-success-focus-shadow);\n  }\n}\n\n/*\n * The solid/flat/bordered/outline/ghost variant switch (previously here) now lives in\n * `fieldVariantMixin({ container: '.field', text: 'textarea', tokenPrefix: 'textarea' })`\n * in `textarea.ts`'s `styles` array — shared with `ore-input`/`ore-message-composer` instead of\n * hand-duplicated across all three (see the mixin's own doc comment for what it covers and why).\n */\n\n@layer refine.utilities {\n  /* Auto-resize hides overflow */\n  :host([auto-resize]) textarea {\n    overflow: hidden;\n  }\n\n  /* Full width */\n  :host([fullwidth]) {\n    width: 100%;\n  }\n}\n\n/* ========================================\n     Disabled State — intentionally unlayered\n     ======================================== */\n\n/*\n * The shared `disabledLoadingMixin` (pulled in via `fieldMixins`) dims `:host([disabled])`\n * with `opacity: 0.5` as bare, unlayered CSS. Cascade layers always lose to unlayered rules\n * regardless of source order or specificity, so overriding that from inside any `@layer`\n * block in this file (including `refine.overrides`) would be a no-op — this has to stay\n * unlayered too, to actually win. See `ore-input`'s `input.css` for the same pattern.\n *\n * Per the field-state UX review: opacity-based dimming reads as a washed-out/loading look\n * and can mimic reduced-contrast content for low-vision users, rather than a clearly locked\n * field. Swapped for an explicit grayscale surface + `not-allowed` cursor (the cursor already\n * comes from the shared mixin, left untouched here).\n */\n:host([disabled]) {\n  opacity: 1;\n}\n\n:host([disabled]) .field {\n  background: var(--color-contrast-100);\n  border-color: var(--color-contrast-200);\n  box-shadow: none;\n}\n\n:host([disabled]) textarea {\n  color: var(--color-contrast-400);\n}\n\n:host([disabled]) textarea::placeholder {\n  color: var(--color-contrast-300);\n}\n\n:host([disabled]) .label {\n  color: var(--color-contrast-400);\n}\n","import {\n  bind,\n  define,\n  getHost,\n  html,\n  live,\n  onCleanup,\n  onElement,\n  prop,\n  ref,\n  useField,\n  watchEffect,\n} from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\nimport { bindRefCallback, createAutoResize, createTextField, lifecycleSignal } from '../../core';\nimport type { TextFieldProps } from '../../shared';\nimport type { VisualVariant } from '../../types';\nimport '../../content/icon/icon';\nimport { disablableBundle, roundableBundle, sizableBundle, TEXTAREA_SIZE_PRESET, themableBundle } from '../../shared';\nimport {\n  coarsePointerMixin,\n  colorThemeMixin,\n  disabledLoadingMixin,\n  fieldVariantMixin,\n  forcedColorsFocusMixin,\n  reducedMotionMixin,\n  roundedVariantMixin,\n  sizeVariantMixin,\n} from '../../styles';\nimport { errorAttr } from '../shared/field-binding';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport { renderFieldStatusRegion, renderStatusIcon } from '../shared/templates';\nimport componentStyles from './textarea.css?inline';\n\n/** Textarea component properties */\n\nexport type OreTextareaEvents = {\n  change: Event;\n  input: InputEvent;\n};\n\nexport type OreTextareaProps = TextFieldProps<Exclude<VisualVariant, 'frost' | 'text'>> & {\n  /** Allow auto-grow with content */\n  'auto-resize'?: boolean;\n  /**\n   * Shows an inline spinner inside the field and forces the inner `<textarea>` into\n   * `disabled` for the duration — use while an async validation/submission request\n   * is in flight to prevent double-submits.\n   */\n  loading?: boolean;\n  /** Maximum character count; shows a counter when set */\n  maxlength?: number;\n  /** Disable a manual resize handle */\n  'no-resize'?: boolean;\n  /**\n   * JS-only callback fired with the inner `<textarea>` element when it mounts,\n   * and with `null` when it unmounts. Intended for composed components that\n   * need imperative access to the raw element.\n   * Set as a JS property: `bitTextarea.ref = (el) => { ... }`.\n   */\n  ref?: ((el: HTMLTextAreaElement | null) => void) | null;\n  /** Resize direction override */\n  resize?: 'none' | 'horizontal' | 'both' | 'vertical';\n  /** Number of visible text rows */\n  rows?: number;\n};\n\n/**\n * A multi-line text input with label, helper text, character counter, and auto-resize.\n *\n * @element ore-textarea\n *\n * @attr {string} label - Label text\n * @attr {string} label-placement - 'inset' | 'outside'\n * @attr {string} value - Current value\n * @attr {string} placeholder - Placeholder text\n * @attr {string} name - Form field name\n * @attr {number} rows - Visible row count\n * @attr {number} maxlength - Max character count (shows counter)\n * @attr {string} helper - Helper text below the textarea\n * @attr {string} error - Error message\n * @attr {boolean} disabled - Disable interaction\n * @attr {boolean} readonly - Read-only mode\n * @attr {boolean} required - Required field\n * @attr {boolean} no-resize - Disable manual resize\n * @attr {boolean} auto-resize - Grow with content\n * @attr {boolean} loading - Show an inline spinner and force the field disabled\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {string} resize - Resize direction: 'none' | 'horizontal' | 'both' | 'vertical'\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n *\n * @fires input - Fired on every keystroke with current value.\n * @fires change - Fired on blur with changed value.\n *\n * @slot helper - Complex helper content\n *\n * @part status-icon - The inline error/success icon shown inside the field\n * @part spinner - The inline loading spinner shown inside the field while `loading`\n *\n * @cssprop --textarea-bg - Background color\n * @cssprop --textarea-border-color - Border color\n * @cssprop --textarea-placeholder-color - Placeholder text color\n * @cssprop --textarea-radius - Border radius\n * @cssprop --textarea-padding - Inner padding (block inline)\n * @cssprop --textarea-gap - Gap between label and field\n * @cssprop --textarea-font-size - Font size\n * @cssprop --textarea-min-height - Minimum field height\n * @cssprop --textarea-max-height - Maximum field height (none = unlimited)\n * @cssprop --textarea-resize - CSS resize direction ('vertical' | 'horizontal' | 'both' | 'none')\n * @cssprop --textarea-hover-bg - Field background on hover (flat/ghost variants)\n * @cssprop --textarea-hover-border-color - Field border on hover (flat/bordered variants)\n * @cssprop --textarea-focus-bg - Field background when focused (flat variant)\n * @cssprop --textarea-focus-border-color - Field border when focused (flat variant)\n *\n * @part wrapper - Outer wrapper element.\n * @part label - Label element.\n * @part field - Field container.\n * @part textarea - The native `<textarea>` element.\n * @part helper - The helper text element.\n * @part error - The error text element (`role=\"alert\"`).\n *\n * @example\n * ```html\n * <ore-textarea></ore-textarea>\n * <ore-textarea label=\"Bio\" success></ore-textarea>\n * <ore-textarea label=\"Bio\" loading></ore-textarea>\n * ```\n */\nexport const TEXTAREA_TAG = 'ore-textarea' as const;\ndefine<OreTextareaProps>(TEXTAREA_TAG, {\n  formAssociated: true,\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...disablableBundle,\n    ...roundableBundle,\n    'auto-resize': prop.bool(false),\n    error: prop.string(),\n    fullwidth: prop.bool(false),\n    helper: prop.string(),\n    label: prop.string(),\n    'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n    loading: prop.bool(false),\n    maxlength: prop.json(undefined as number | undefined),\n    name: prop.string(),\n    'no-resize': prop.bool(false),\n    placeholder: prop.string(),\n    readonly: prop.bool(false),\n    ref: prop.data<((el: HTMLTextAreaElement | null) => void) | null>(),\n    required: prop.bool(false),\n    resize: prop.string<'none' | 'both' | 'horizontal' | 'vertical'>(),\n    rows: prop.json(undefined as number | undefined),\n    success: prop.bool(false),\n    value: prop.string(),\n    variant: prop.string<'flat' | 'solid' | 'bordered' | 'outline' | 'ghost'>(),\n  },\n  setup(props) {\n    const el = getHost();\n    const watch = watchEffect;\n\n    const textareaRef = ref<HTMLTextAreaElement>();\n    const autoResize = createAutoResize({ enabled: props['auto-resize'] });\n    // `loading` behaves like a temporary `disabled` — see ore-input's identical computation.\n    const isDisabled = computed(() => props.disabled.value || props.loading.value);\n\n    const abortSignal = lifecycleSignal(onCleanup);\n    const tf = createTextField({\n      disabled: isDisabled,\n      error: props.error,\n      helper: props.helper,\n      label: props.label,\n      labelPlacement: props['label-placement'],\n      maxLength: props.maxlength,\n      onChange: (_event: Event, value: string) => {\n        setFieldValue(el, value);\n        dispatchNativeFieldEvent(el, 'change');\n      },\n      onInput: (_event: Event, value: string) => {\n        setFieldValue(el, value);\n        dispatchNativeFieldEvent(el, 'input');\n      },\n      prefix: 'textarea',\n      readonly: props.readonly,\n      required: props.required,\n      signal: abortSignal,\n      value: props.value,\n    });\n\n    defineFieldValue(\n      el,\n      () => tf.value.value,\n      (value) => {\n        tf.value.value = value;\n      },\n    );\n\n    tf.attachFormField(\n      useField<string>({\n        disabled: tf.disabled,\n        onReset: () => {\n          tf.reset();\n          requestAnimationFrame(() => autoResize.recompute());\n        },\n        toFormValue: (v) => v,\n        validationMessage: tf.validationMessage,\n        validity: tf.validity,\n        value: tf.value,\n      }),\n    );\n\n    const {\n      ariaDescribedBy,\n      ariaErrorMessage,\n      ariaInvalid,\n      ariaLabelledBy,\n      assistiveId,\n      counter,\n      errorId,\n      errorText,\n      fieldId: textareaId,\n      helperText,\n      labelId,\n      labelVisible,\n    } = tf;\n\n    onElement(textareaRef, (textareaEl) => {\n      const unwireEl = tf.wire(textareaEl);\n      const unwireAutoResize = autoResize.wire(textareaEl);\n      const unwireRef = bindRefCallback(props.ref, textareaEl);\n\n      const stopLayoutEffect = watch(() => {\n        textareaEl.style.resize =\n          props['auto-resize'].value || props['no-resize'].value ? 'none' : props.resize.value || 'vertical';\n\n        // Deferred a frame: on mount (or right after `auto-resize` flips true) the browser\n        // hasn't necessarily finished laying out the textarea yet, so `scrollHeight` read\n        // synchronously here could be stale.\n        requestAnimationFrame(() => autoResize.recompute());\n      });\n\n      return () => {\n        unwireRef();\n        unwireEl();\n        unwireAutoResize();\n        stopLayoutEffect();\n      };\n    });\n\n    bind({\n      attr: {\n        error: errorAttr(errorText),\n        size: props.size,\n        // Reflects `success` only once `error` is confirmed empty — keeps the two host\n        // attributes mutually exclusive even if a consumer sets both props at once.\n        success: () => (props.success.value && !errorText.value ? true : undefined),\n        variant: props.variant,\n      },\n    });\n\n    return html`\n      <div class=\"textarea-wrapper\" part=\"wrapper\">\n        <label class=\"label\" part=\"label\" for=\"${textareaId}\" id=\"${labelId}\" ?hidden=\"${() => !labelVisible.value}\">\n          ${props.label}\n        </label>\n        <div class=\"field\" part=\"field\">\n          <textarea\n            part=\"textarea\"\n            ref=\"${textareaRef}\"\n            id=\"${textareaId}\"\n            name=\"${props.name}\"\n            placeholder=\"${props.placeholder}\"\n            rows=\"${props.rows}\"\n            maxlength=\"${props.maxlength}\"\n            ?disabled=\"${isDisabled}\"\n            ?readonly=\"${props.readonly}\"\n            ?required=\"${props.required}\"\n            value=\"${live(tf.value)}\"\n            aria-describedby=\"${ariaDescribedBy}\"\n            aria-errormessage=\"${ariaErrorMessage}\"\n            aria-invalid=\"${ariaInvalid}\"\n            aria-labelledby=\"${ariaLabelledBy}\"\n            aria-busy=\"${() => (props.loading.value ? 'true' : null)}\"></textarea>\n          ${renderStatusIcon(errorText)}\n          <span class=\"field-spinner\" part=\"spinner\" role=\"status\" aria-label=\"Loading\"></span>\n        </div>\n        ${renderFieldStatusRegion({ assistiveId, counter, errorId, errorText, helperText })}\n      </div>\n    `;\n  },\n  shadow: { delegatesFocus: true },\n  styles: [\n    colorThemeMixin,\n    coarsePointerMixin,\n    reducedMotionMixin,\n    roundedVariantMixin,\n    disabledLoadingMixin,\n    sizeVariantMixin(TEXTAREA_SIZE_PRESET),\n    forcedColorsFocusMixin('textarea'),\n    componentStyles,\n    // Must come after `componentStyles` — see `ore-input`'s identical ordering note for why\n    // (`@layer` precedence is fixed by which layer name is *first* referenced across this whole\n    // array; `componentStyles` establishes `refine.base`, which this mixin's `refine.variants`\n    // rules need to win over).\n    fieldVariantMixin({ container: '.field', text: 'textarea', tokenPrefix: 'textarea' }),\n  ],\n});\n","@layer refine.base {\n  :host {\n    --_selected-bg: var(--time-picker-selected-bg, var(--_theme-focus));\n    --_hover-bg: var(--time-picker-option-hover-bg, color-mix(in oklch, var(--_selected-bg) 12%, transparent));\n    --_bg: var(--time-picker-bg, var(--color-canvas));\n    --_border-color: var(--time-picker-border-color, var(--color-contrast-200));\n    --_radius: var(--time-picker-radius, var(--rounded-xl));\n\n    display: inline-block;\n  }\n\n  :host([fullwidth]) {\n    display: block;\n  }\n\n  :host([color='secondary']) {\n    --_selected-bg: var(--time-picker-selected-bg, var(--_theme-base));\n  }\n\n  /* Prevent display:flex/grid from overriding [hidden] attribute */\n  [hidden] {\n    display: none;\n  }\n\n  /* ── Trigger ─────────────────────────────────────────────────────────────── */\n\n  .trigger {\n    cursor: pointer;\n  }\n\n  .trigger::part(input) {\n    cursor: pointer;\n    caret-color: transparent;\n    user-select: none;\n  }\n\n  /* ── Dropdown ────────────────────────────────────────────────────────────── */\n\n  /* `fixed` (not `absolute`) — positioned via JS-computed top/left (see the positioner in\n     time-picker.ts), same as ore-date-picker's own `.calendar`. Laid out relative to the\n     viewport, so it never affects any ancestor's box size or scrollable-overflow area. */\n  .dropdown {\n    position: fixed;\n    inset: 0 auto auto 0;\n    z-index: var(--z-dropdown, 200);\n    display: flex;\n    flex-direction: column;\n    min-width: 12rem;\n    overflow: hidden;\n    pointer-events: none;\n    background: var(--time-picker-bg, var(--_bg));\n    border: var(--border) solid var(--time-picker-border-color, var(--_border-color));\n    border-radius: var(--time-picker-radius, var(--_radius));\n    box-shadow: var(--time-picker-shadow, var(--shadow-lg));\n\n    /* Hidden by default */\n    opacity: 0;\n    backdrop-filter: blur(var(--blur-sm));\n    transform: translateY(var(--overlay-enter-translate-y));\n    transition: var(\n      --_motion-transition,\n      opacity var(--transition-fast),\n      transform var(--transition-fast),\n      display var(--transition-fast) allow-discrete\n    );\n  }\n\n  .dropdown[data-open] {\n    pointer-events: auto;\n    opacity: 1;\n    transform: translateY(0);\n\n    @starting-style {\n      opacity: 0;\n      transform: translateY(var(--overlay-enter-translate-y));\n    }\n  }\n\n  /* ── Columns row ────────────────────────────────────────────────────────── */\n\n  .cols-row {\n    display: flex;\n    flex-direction: row;\n    align-items: stretch;\n  }\n\n  /* ── Columns (hours / sep / minutes / [period]) ──────────────────────────── */\n\n  .col,\n  .col-sep {\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n  }\n\n  .col {\n    flex: 1;\n    min-width: var(--size-14);\n    border-block-end: var(--border) solid var(--_border-color);\n  }\n\n  .col-period {\n    flex: 0 0 auto;\n    min-width: var(--size-16);\n  }\n\n  /* ── Column header label ─────────────────────────────────────────────────── */\n\n  .col-label {\n    width: 100%;\n    padding: var(--size-1) var(--size-2);\n    font-size: var(--text-xs);\n    font-weight: var(--font-medium);\n    color: var(--color-contrast-400);\n    text-align: center;\n    letter-spacing: 0.05em;\n    border-block-end: var(--border) solid var(--_border-color);\n  }\n\n  /* ── Scrollable option list ──────────────────────────────────────────────── */\n\n  .col-scroll {\n    width: 100%;\n    max-height: 11rem;\n    padding-block: var(--size-1);\n    overflow-y: auto;\n    scrollbar-width: thin;\n  }\n\n  /* ── Separator between hours and minutes ─────────────────────────────────── */\n\n  .col-sep {\n    display: flex;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    padding-block-start: var(--size-8); /* visually align with first option row */\n    padding-inline: var(--size-0-5);\n    font-size: var(--text-lg);\n    font-weight: var(--font-semibold);\n    color: var(--color-contrast-500);\n    user-select: none;\n    border-block-end: var(--border) solid var(--_border-color);\n  }\n\n  /* ── Option cells ────────────────────────────────────────────────────────── */\n\n  .option {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    height: var(--size-8);\n    padding-inline: var(--size-2);\n    margin-inline: var(--size-1);\n    font-size: var(--text-sm);\n    color: var(--color-contrast-800);\n    cursor: pointer;\n    outline: none;\n    border-radius: var(--rounded-sm);\n    transition:\n      background var(--transition-fast),\n      color var(--transition-fast);\n  }\n\n  .option:hover:not([data-disabled]) {\n    color: var(--color-contrast-900);\n    background: var(--_hover-bg);\n  }\n\n  .option:focus-visible {\n    box-shadow: 0 0 0 2px var(--_selected-bg);\n  }\n\n  .option[aria-selected='true'] {\n    font-weight: var(--font-semibold);\n    color: var(--color-white, #fff);\n    background: var(--_selected-bg);\n  }\n\n  .option[data-disabled] {\n    pointer-events: none;\n    cursor: not-allowed;\n    opacity: 0.3;\n  }\n\n  /* ── Reduced motion ──────────────────────────────────────────────────────── */\n\n  @media (prefers-reduced-motion: reduce) {\n    .option {\n      transition: none;\n    }\n  }\n}\n","import { bind, define, getHost, html, onMounted, prop, ref, useField } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { createDropdownPositioner } from '../../core';\nimport type { VisualVariant } from '../../shared';\nimport '../../content/icon/icon';\nimport '../input/input';\nimport { disablableBundle, roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, reducedMotionMixin } from '../../styles';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport componentStyles from './time-picker.css?inline';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type OreTimePickerEvents = {\n  change: Event;\n  input: Event;\n};\n\nexport type OreTimePickerProps = {\n  /** Theme color */\n  color?: string;\n  /** Disable the picker */\n  disabled?: boolean;\n  /** Validation error message */\n  error?: string;\n  /** Expand to container width */\n  fullwidth?: boolean;\n  /** Helper text below the field */\n  helper?: string;\n  /** Visible label */\n  label?: string;\n  /** Label placement */\n  'label-placement'?: 'inset' | 'outside';\n  /** Maximum selectable time in HH:MM format (24-hour) */\n  max?: string;\n  /** Minimum selectable time in HH:MM format (24-hour) */\n  min?: string;\n  /** Minute step interval (1–59) */\n  'minute-step'?: number;\n  /** Form field name */\n  name?: string;\n  /** Placeholder shown in the trigger */\n  placeholder?: string;\n  /** Mark field as required */\n  required?: boolean;\n  /** Border radius */\n  rounded?: string;\n  /** Component size */\n  size?: string;\n  /**\n   * Shows an inline green check icon inside the field to confirm the value has\n   * passed validation. Ignored while `error` is set — an error always wins.\n   */\n  success?: boolean;\n  /** Display format: '12' for AM/PM, '24' for 24-hour (default: '24') */\n  'time-format'?: '12' | '24';\n  /** Selected time in HH:MM format (24-hour) */\n  value?: string;\n  /** Visual variant */\n  variant?: Exclude<VisualVariant, 'text' | 'frost'>;\n};\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\n/** Parse \"HH:MM\" → { hours: 0-23, minutes: 0-59 } | null */\nfunction parseTime(val: string | undefined | null): { hours: number; minutes: number } | null {\n  if (!val) return null;\n\n  const match = /^(\\d{1,2}):(\\d{2})$/.exec(val.trim());\n\n  if (!match) return null;\n\n  const h = Number(match[1]);\n  const m = Number(match[2]);\n\n  if (h < 0 || h > 23 || m < 0 || m > 59) return null;\n\n  return { hours: h, minutes: m };\n}\n\n/** Format { hours, minutes } → \"HH:MM\" (24-hour, zero-padded) */\nfunction formatTime(h: number, m: number): string {\n  return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`;\n}\n\n/** Format for display label (respects 12/24 mode) */\nfunction formatDisplay(h: number, m: number, format: '12' | '24'): string {\n  if (format === '12') {\n    const period = h >= 12 ? 'PM' : 'AM';\n    const displayH = h % 12 === 0 ? 12 : h % 12;\n\n    return `${String(displayH).padStart(2, '0')}:${String(m).padStart(2, '0')} ${period}`;\n  }\n\n  return formatTime(h, m);\n}\n\n/** Clamp value to [min, max] in total minutes */\nfunction clampTime(\n  h: number,\n  m: number,\n  minVal: string | undefined | null,\n  maxVal: string | undefined | null,\n): { hours: number; minutes: number } {\n  const total = h * 60 + m;\n  const minParsed = parseTime(minVal);\n  const maxParsed = parseTime(maxVal);\n  const minMins = minParsed ? minParsed.hours * 60 + minParsed.minutes : 0;\n  const maxMins = maxParsed ? maxParsed.hours * 60 + maxParsed.minutes : 23 * 60 + 59;\n  const clamped = Math.min(Math.max(total, minMins), maxMins);\n\n  return { hours: Math.floor(clamped / 60), minutes: clamped % 60 };\n}\n\n/**\n * An accessible time picker with a scrollable clock dropdown.\n * Supports 12/24-hour display formats, min/max bounds, minute steps, and form association.\n *\n * @element ore-time-picker\n *\n * @attr {string} value - Selected time in HH:MM (24-hour) format\n * @attr {string} min - Minimum selectable time (HH:MM)\n * @attr {string} max - Maximum selectable time (HH:MM)\n * @attr {string} label - Label text\n * @attr {string} label-placement - 'inset' | 'outside'\n * @attr {string} placeholder - Trigger placeholder\n * @attr {boolean} disabled - Disable the picker\n * @attr {boolean} required - Required field\n * @attr {string} name - Form field name\n * @attr {string} error - Error message\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {string} helper - Helper text\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {string} time-format - '12' or '24' (default: '24')\n * @attr {number} minute-step - Minute increment (default: 5)\n *\n * @fires input - Fired when a time is selected.\n * @fires change - Fired when a time is selected.\n *\n * @slot label - Custom label for the trigger field\n * @slot prefix - Content before the trigger text (e.g. icon)\n * @slot helper - Custom helper text\n * @slot error - Custom error content\n *\n * @cssprop --time-picker-bg - Dropdown background\n * @cssprop --time-picker-border-color - Dropdown border color\n * @cssprop --time-picker-radius - Dropdown border radius\n * @cssprop --time-picker-shadow - Dropdown shadow\n * @cssprop --time-picker-selected-bg - Selected option background\n * @cssprop --time-picker-option-hover-bg - Option hover background\n *\n * @part field - The trigger field\n * @part dropdown - The floating time dropdown\n * @part column - A scrollable column (hours / minutes / period)\n * @part option - An individual time option cell\n *\n * @example\n * ```html\n * <!-- 24-hour clock, 15-minute steps -->\n * <ore-time-picker label=\"Meeting time\" value=\"09:30\" minute-step=\"15\" color=\"primary\"></ore-time-picker>\n *\n * <!-- 12-hour AM/PM format -->\n * <ore-time-picker label=\"Appointment\" time-format=\"12\" minute-step=\"30\"></ore-time-picker>\n *\n * <!-- Outside label, bordered variant -->\n * <ore-time-picker label=\"Start time\" label-placement=\"outside\" variant=\"bordered\"></ore-time-picker>\n * ```\n */\nexport const TIME_PICKER_TAG = 'ore-time-picker' as const;\n\ndefine<OreTimePickerProps>(TIME_PICKER_TAG, {\n  formAssociated: true,\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...disablableBundle,\n    ...roundableBundle,\n    error: prop.string(),\n    fullwidth: prop.bool(false),\n    helper: prop.string(),\n    label: prop.string(),\n    'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n    max: prop.string(),\n    min: prop.string(),\n    'minute-step': prop.number(5),\n    name: prop.string(),\n    placeholder: prop.string(),\n    required: prop.bool(false),\n    success: prop.bool(false),\n    'time-format': prop.oneOf(['12', '24'] as const, '24'),\n    value: prop.string(),\n    variant: prop.string<'flat' | 'solid' | 'bordered' | 'outline' | 'ghost'>(),\n  },\n\n  setup(props) {\n    const el = getHost();\n\n    // ── Signals ──────────────────────────────────────────────────────────────\n\n    const isOpen = signal(false);\n    const selectedTime = signal<{ hours: number; minutes: number } | null>(parseTime(props.value.value));\n\n    defineFieldValue(\n      el,\n      () => {\n        const value = selectedTime.value;\n\n        return value ? formatTime(value.hours, value.minutes) : '';\n      },\n      (value) => {\n        selectedTime.value = parseTime(value);\n      },\n    );\n\n    // ── Floating position ────────────────────────────────────────────────────\n    // Same Orbit-powered positioner ore-date-picker's `.calendar` popup uses (see its own\n    // comment for the full rationale) — `fixed` + computed `top`/`left` instead of a static\n    // `position: absolute; top: 100%`, so the dropdown flips/shifts to stay within the nearest\n    // clipping ancestor instead of silently overflowing it.\n    const triggerRef = ref<HTMLElement>();\n    const dropdownRef = ref<HTMLElement>();\n\n    const positioner = createDropdownPositioner({\n      getFloating: () => dropdownRef.value ?? null,\n      getReference: () => triggerRef.value ?? null,\n      matchWidth: false,\n      offsetPx: 4,\n    });\n\n    let stopAutoUpdate: (() => void) | null = null;\n\n    const isDisabled = computed(() => Boolean(props.disabled.value));\n\n    // ── Form value ────────────────────────────────────────────────────────────\n\n    useField<string>({\n      disabled: isDisabled,\n      toFormValue: (v) => v || null,\n      value: computed(() => {\n        const t = selectedTime.value;\n\n        return t ? formatTime(t.hours, t.minutes) : '';\n      }),\n    });\n\n    // ── Computed helpers ──────────────────────────────────────────────────────\n\n    const fmt = computed(() => props['time-format'].value ?? '24');\n    const minuteStep = computed(() => Math.max(1, Math.min(59, props['minute-step'].value ?? 5)));\n\n    const triggerText = computed(() => {\n      if (!selectedTime.value) return props.placeholder.value || '';\n\n      return formatDisplay(selectedTime.value.hours, selectedTime.value.minutes, fmt.value as '12' | '24');\n    });\n\n    /** All hour options for the column (0-23 in 24h; 1-12 in 12h) */\n    const hourOptions = computed<number[]>(() => {\n      if (fmt.value === '12') {\n        return Array.from({ length: 12 }, (_, i) => i + 1);\n      }\n\n      return Array.from({ length: 24 }, (_, i) => i);\n    });\n\n    /** All minute options for the column, stepped */\n    const minuteOptions = computed<number[]>(() => {\n      const step = minuteStep.value;\n      const opts: number[] = [];\n\n      for (let m = 0; m < 60; m += step) opts.push(m);\n\n      return opts;\n    });\n\n    const dialogId = `time-picker-${Math.random().toString(36).slice(2, 9)}-dropdown`;\n\n    /** Convert 24h hour to display hour in current format */\n    function toDisplayHour(h24: number): number {\n      if (fmt.value === '24') return h24;\n\n      const h12 = h24 % 12;\n\n      return h12 === 0 ? 12 : h12;\n    }\n\n    /** Convert display hour + period → 24h hour */\n    function to24Hour(displayHour: number, period: 'AM' | 'PM'): number {\n      if (fmt.value === '24') return displayHour;\n\n      if (period === 'AM') return displayHour === 12 ? 0 : displayHour;\n\n      return displayHour === 12 ? 12 : displayHour + 12;\n    }\n\n    /** Whether a given HH:MM is out of [min, max] */\n    function isTimeDisabled(h: number, m: number): boolean {\n      const total = h * 60 + m;\n      const minParsed = parseTime(props.min.value);\n      const maxParsed = parseTime(props.max.value);\n\n      if (minParsed && total < minParsed.hours * 60 + minParsed.minutes) return true;\n\n      if (maxParsed && total > maxParsed.hours * 60 + maxParsed.minutes) return true;\n\n      return false;\n    }\n\n    // ── State for focused/pending selection ───────────────────────────────────\n\n    /** Pending hour (24h) while user is navigating columns */\n    const pendingHour = signal<number>(selectedTime.value?.hours ?? 0);\n    /** Pending minute */\n    const pendingMinute = signal<number>(selectedTime.value?.minutes ?? 0);\n    /** Pending period (12h mode) */\n    const pendingPeriod = signal<'AM' | 'PM'>((selectedTime.value?.hours ?? 0) >= 12 ? 'PM' : 'AM');\n\n    // ── Sync value prop externally ────────────────────────────────────────────\n\n    let lastValueProp = props.value.value;\n\n    onMounted(() => {\n      const interval = setInterval(() => {\n        const current = props.value.value;\n\n        if (current !== lastValueProp) {\n          lastValueProp = current;\n\n          const parsed = parseTime(current);\n\n          selectedTime.value = parsed;\n\n          if (parsed) {\n            pendingHour.value = parsed.hours;\n            pendingMinute.value = parsed.minutes;\n            pendingPeriod.value = parsed.hours >= 12 ? 'PM' : 'AM';\n          }\n        }\n      }, 50);\n\n      return () => clearInterval(interval);\n    });\n\n    // ── Commit ────────────────────────────────────────────────────────────────\n\n    function commit(h24: number, m: number): void {\n      const clamped = clampTime(h24, m, props.min.value, props.max.value);\n      const snapped = Math.round(clamped.minutes / minuteStep.value) * minuteStep.value;\n      const snappedMin = Math.min(snapped, 59);\n\n      selectedTime.value = { hours: clamped.hours, minutes: snappedMin };\n      setFieldValue(el, formatTime(clamped.hours, snappedMin));\n      dispatchNativeFieldEvent(el, 'input');\n      dispatchNativeFieldEvent(el, 'change');\n    }\n\n    function commitFromMinute(m: number): void {\n      const h24 = fmt.value === '12' ? to24Hour(pendingHour.value, pendingPeriod.value) : pendingHour.value;\n\n      pendingMinute.value = m;\n      commit(h24, m);\n      closePicker();\n    }\n\n    // ── Open / close ──────────────────────────────────────────────────────────\n\n    function openPicker(): void {\n      if (isDisabled.value) return;\n\n      const current = selectedTime.value;\n\n      if (current) {\n        pendingHour.value = fmt.value === '12' ? toDisplayHour(current.hours) : current.hours;\n        pendingMinute.value = current.minutes;\n        pendingPeriod.value = current.hours >= 12 ? 'PM' : 'AM';\n      } else {\n        pendingHour.value = fmt.value === '12' ? 12 : 0;\n        pendingMinute.value = 0;\n        pendingPeriod.value = 'AM';\n      }\n\n      isOpen.value = true;\n      positioner.update();\n      stopAutoUpdate = positioner.startAutoUpdate?.() ?? null;\n    }\n\n    function closePicker(): void {\n      isOpen.value = false;\n      stopAutoUpdate?.();\n      stopAutoUpdate = null;\n    }\n\n    function handleTriggerClick(): void {\n      if (isOpen.value) closePicker();\n      else openPicker();\n    }\n\n    // ── Outside click ─────────────────────────────────────────────────────────\n\n    function handleOutsideClick(e: PointerEvent | MouseEvent): void {\n      if (!isOpen.value) return;\n\n      if (!e.composedPath().includes(el)) closePicker();\n    }\n\n    onMounted(() => {\n      document.addEventListener('pointerdown', handleOutsideClick, { capture: true });\n\n      return () => {\n        document.removeEventListener('pointerdown', handleOutsideClick, { capture: true });\n        stopAutoUpdate?.();\n        stopAutoUpdate = null;\n      };\n    });\n\n    // ── Keyboard ──────────────────────────────────────────────────────────────\n\n    function handleTriggerKeydown(e: KeyboardEvent): void {\n      if (isDisabled.value) return;\n\n      if (e.key === 'Enter' || e.key === ' ') {\n        e.preventDefault();\n        handleTriggerClick();\n      } else if (e.key === 'Escape' && isOpen.value) {\n        e.preventDefault();\n        closePicker();\n      } else if ((e.key === 'ArrowDown' || e.key === 'ArrowUp') && !isOpen.value) {\n        e.preventDefault();\n        openPicker();\n      }\n    }\n\n    function handleDropdownKeydown(e: KeyboardEvent): void {\n      if (e.key === 'Escape') {\n        e.preventDefault();\n        closePicker();\n      }\n    }\n\n    function handleHourKeydown(e: KeyboardEvent): void {\n      const opts = hourOptions.value;\n      const idx = opts.indexOf(pendingHour.value);\n\n      if (e.key === 'ArrowUp') {\n        e.preventDefault();\n        pendingHour.value = opts[(idx - 1 + opts.length) % opts.length];\n      } else if (e.key === 'ArrowDown') {\n        e.preventDefault();\n        pendingHour.value = opts[(idx + 1) % opts.length];\n      }\n    }\n\n    function handleMinuteKeydown(e: KeyboardEvent): void {\n      const opts = minuteOptions.value;\n      const idx = opts.indexOf(pendingMinute.value);\n\n      if (e.key === 'ArrowUp') {\n        e.preventDefault();\n        pendingMinute.value = opts[(idx - 1 + opts.length) % opts.length];\n      } else if (e.key === 'ArrowDown') {\n        e.preventDefault();\n        pendingMinute.value = opts[(idx + 1) % opts.length];\n      }\n    }\n\n    function handlePeriodKeydown(e: KeyboardEvent): void {\n      if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n        e.preventDefault();\n        pendingPeriod.value = pendingPeriod.value === 'AM' ? 'PM' : 'AM';\n      }\n    }\n\n    // ── Host bindings ─────────────────────────────────────────────────────────\n\n    bind({\n      attr: {\n        open: () => (isOpen.value ? true : undefined),\n      },\n    });\n\n    // ── ore-input prop helpers ────────────────────────────────────────────────\n\n    const inputValue = () => triggerText.value;\n    const inputLabel = () => props.label.value ?? '';\n    const inputPlaceholder = () => props.placeholder.value ?? '';\n    const inputLabelPlacement = () => props['label-placement'].value ?? 'inset';\n    const inputColor = () => props.color?.value ?? undefined;\n    const inputSize = () => props.size?.value ?? undefined;\n    const inputVariant = () => props.variant?.value ?? undefined;\n    const inputRounded = () => props.rounded?.value ?? undefined;\n    const inputHelper = () => props.helper.value ?? '';\n    const inputError = () => props.error.value ?? '';\n    const inputDisabled = () => (isDisabled.value ? true : undefined);\n    const inputRequired = () => (props.required.value ? true : undefined);\n    const inputFullwidth = () => (props.fullwidth.value ? true : undefined);\n\n    return html`\n      <!-- Trigger -->\n      <ore-input\n        class=\"trigger\"\n        ref=\"${triggerRef}\"\n        readonly\n        tabindex=\"0\"\n        role=\"combobox\"\n        aria-haspopup=\"listbox\"\n        aria-controls=\"${dialogId}\"\n        aria-expanded=\"${() => String(isOpen.value)}\"\n        aria-disabled=\"${() => (isDisabled.value ? 'true' : null)}\"\n        value=\"${inputValue}\"\n        label=\"${inputLabel}\"\n        placeholder=\"${inputPlaceholder}\"\n        label-placement=\"${inputLabelPlacement}\"\n        color=\"${inputColor}\"\n        size=\"${inputSize}\"\n        variant=\"${inputVariant}\"\n        rounded=\"${inputRounded}\"\n        helper=\"${inputHelper}\"\n        error=\"${inputError}\"\n        ?disabled=\"${inputDisabled}\"\n        ?required=\"${inputRequired}\"\n        ?fullwidth=\"${inputFullwidth}\"\n        ?success=\"${() => props.success.value}\"\n        @click=\"${handleTriggerClick}\"\n        @keydown=\"${handleTriggerKeydown}\">\n        <ore-icon slot=\"suffix\" name=\"clock\" size=\"16\" stroke-width=\"1.75\" aria-hidden=\"true\"></ore-icon>\n      </ore-input>\n\n      <!-- Dropdown -->\n      <div\n        class=\"dropdown\"\n        ref=\"${dropdownRef}\"\n        id=\"${dialogId}\"\n        role=\"listbox\"\n        aria-label=\"${() => (props.label.value ? `${props.label.value} — select time` : 'Select time')}\"\n        ?data-open=\"${isOpen}\"\n        @keydown=\"${handleDropdownKeydown}\">\n        <div class=\"cols-row\">\n          <!-- Hours column -->\n          <div class=\"col\" part=\"column\" role=\"group\" aria-label=\"Hours\">\n            <div class=\"col-label\" aria-hidden=\"true\">HH</div>\n            <div class=\"col-scroll\">\n              ${() =>\n                hourOptions.value.map((h) => {\n                  const h24 = fmt.value === '12' ? to24Hour(h, pendingPeriod.value) : h;\n                  const disabled = isTimeDisabled(h24, pendingMinute.value);\n\n                  return html`\n                    <div\n                      class=\"option\"\n                      part=\"option\"\n                      role=\"option\"\n                      tabindex=\"${() => (pendingHour.value === h && !disabled ? '0' : '-1')}\"\n                      aria-selected=\"${() => String(pendingHour.value === h)}\"\n                      aria-disabled=\"${() => String(disabled)}\"\n                      ?data-disabled=\"${() => disabled}\"\n                      @click=\"${() => {\n                        if (!disabled) pendingHour.value = h;\n                      }}\"\n                      @keydown=\"${handleHourKeydown}\">\n                      ${String(h).padStart(2, '0')}\n                    </div>\n                  `;\n                })}\n            </div>\n          </div>\n\n          <div class=\"col-sep\" aria-hidden=\"true\">:</div>\n\n          <!-- Minutes column -->\n          <div class=\"col\" part=\"column\" role=\"group\" aria-label=\"Minutes\">\n            <div class=\"col-label\" aria-hidden=\"true\">MM</div>\n            <div class=\"col-scroll\">\n              ${() =>\n                minuteOptions.value.map((m) => {\n                  const h24 = fmt.value === '12' ? to24Hour(pendingHour.value, pendingPeriod.value) : pendingHour.value;\n                  const disabled = isTimeDisabled(h24, m);\n\n                  return html`\n                    <div\n                      class=\"option\"\n                      part=\"option\"\n                      role=\"option\"\n                      tabindex=\"${() => (pendingMinute.value === m && !disabled ? '0' : '-1')}\"\n                      aria-selected=\"${() => String(pendingMinute.value === m)}\"\n                      aria-disabled=\"${() => String(disabled)}\"\n                      ?data-disabled=\"${() => disabled}\"\n                      @click=\"${() => {\n                        if (!disabled) commitFromMinute(m);\n                      }}\"\n                      @keydown=\"${handleMinuteKeydown}\">\n                      ${String(m).padStart(2, '0')}\n                    </div>\n                  `;\n                })}\n            </div>\n          </div>\n\n          <!-- AM/PM column (12h mode only) -->\n          ${() =>\n            fmt.value === '12'\n              ? html`\n                  <div class=\"col col-period\" part=\"column\" role=\"group\" aria-label=\"Period\">\n                    <div class=\"col-label\" aria-hidden=\"true\">AM/PM</div>\n                    <div class=\"col-scroll\">\n                      ${(['AM', 'PM'] as const).map(\n                        (p) => html`\n                          <div\n                            class=\"option\"\n                            part=\"option\"\n                            role=\"option\"\n                            tabindex=\"${() => (pendingPeriod.value === p ? '0' : '-1')}\"\n                            aria-selected=\"${() => String(pendingPeriod.value === p)}\"\n                            @click=\"${() => {\n                              pendingPeriod.value = p;\n                            }}\"\n                            @keydown=\"${handlePeriodKeydown}\">\n                            ${p}\n                          </div>\n                        `,\n                      )}\n                    </div>\n                  </div>\n                `\n              : html``}\n        </div>\n      </div>\n    `;\n  },\n\n  shadow: { delegatesFocus: true },\n  styles: [colorThemeMixin, reducedMotionMixin, componentStyles],\n});\n","export type { BaseFormProps, SelectableFieldProps, TextFieldProps } from '../shared';\nexport type { OreButtonProps } from './button/button';\nexport { BUTTON_TAG } from './button/button';\nexport type { ButtonGroupContext, OreButtonGroupProps } from './button-group/button-group';\nexport { BUTTON_GROUP_CTX, BUTTON_GROUP_TAG } from './button-group/button-group';\nexport type { CalendarEvent, OreCalendarEvents, OreCalendarProps } from './calendar/calendar';\nexport { CALENDAR_TAG } from './calendar/calendar';\nexport type { OreCheckboxEvents, OreCheckboxProps } from './checkbox/checkbox';\nexport { CHECKBOX_TAG } from './checkbox/checkbox';\nexport type { OreCheckboxGroupEvents, OreCheckboxGroupProps } from './checkbox-group/checkbox-group';\nexport { CHECKBOX_GROUP_CTX, CHECKBOX_GROUP_TAG } from './checkbox-group/checkbox-group';\nexport type { OreComboboxEvents, OreComboboxProps } from './combobox/combobox';\nexport { COMBOBOX_TAG } from './combobox/combobox';\nexport type { OreComboboxOptionProps } from './combobox/combobox.types';\nexport type { DataGridSource, OreDataGridEvents, OreDataGridProps } from './datagrid/datagrid';\nexport { DATAGRID_TAG } from './datagrid/datagrid';\nexport type { OreDatePickerEvents, OreDatePickerProps } from './date-picker/date-picker';\nexport { DATE_PICKER_TAG } from './date-picker/date-picker';\nexport type { OreFileInputEvents, OreFileInputProps } from './file-input/file-input';\nexport { FILE_INPUT_TAG } from './file-input/file-input';\nexport type { OreInputEvents, OreInputProps } from './input/input';\nexport { INPUT_TAG } from './input/input';\nexport type { OreMessageComposerEvents, OreMessageComposerProps } from './message-composer/message-composer';\nexport { MESSAGE_COMPOSER_TAG } from './message-composer/message-composer';\nexport type { OreNumberInputEvents, OreNumberInputProps } from './number-input/number-input';\nexport { NUMBER_INPUT_TAG } from './number-input/number-input';\nexport type { OreOtpInputEvents, OreOtpInputProps } from './otp-input/otp-input';\nexport { OTP_INPUT_TAG } from './otp-input/otp-input';\nexport type { OreRadioEvents, OreRadioProps } from './radio/radio';\nexport { RADIO_TAG } from './radio/radio';\nexport type { OreRadioGroupEvents, OreRadioGroupProps } from './radio-group/radio-group';\nexport { RADIO_GROUP_CTX, RADIO_GROUP_TAG } from './radio-group/radio-group';\nexport type { OreRatingEvents, OreRatingProps } from './rating/rating';\nexport { RATING_TAG } from './rating/rating';\nexport type { OreSelectEvents, OreSelectProps } from './select/select';\nexport { SELECT_TAG } from './select/select';\nexport type { OreSliderEvents, OreSliderProps } from './slider/slider';\nexport { SLIDER_TAG } from './slider/slider';\nexport type { OreSwitchEvents, OreSwitchProps } from './switch/switch';\nexport { SWITCH_TAG } from './switch/switch';\nexport type { OreTextareaEvents, OreTextareaProps } from './textarea/textarea';\nexport { TEXTAREA_TAG } from './textarea/textarea';\nexport type { OreTimePickerEvents, OreTimePickerProps } from './time-picker/time-picker';\nexport { TIME_PICKER_TAG } from './time-picker/time-picker';\n","@layer refine.base {\n  :host {\n    --_bg: var(--box-bg, var(--color-canvas));\n    --_color: var(--box-color, var(--color-contrast-900));\n    --_border-width: var(--box-border, var(--border));\n    --_border-color: var(--box-border-color, var(--color-divider));\n    --_radius: var(--box-radius, var(--rounded-lg));\n    --_padding: var(--box-padding, var(--size-4));\n    --_shadow: var(--box-shadow, var(--shadow-sm));\n\n    position: relative;\n    display: block;\n  }\n\n  .box {\n    position: relative;\n    box-sizing: border-box;\n    width: 100%;\n    height: 100%;\n    padding: var(--_padding);\n    color: var(--_color);\n    background: var(--_bg);\n    border: var(--_border-width) solid var(--_border-color);\n    border-radius: var(--_radius);\n    box-shadow: var(--_shadow);\n    backdrop-filter: blur(var(--blur-md));\n    transition:\n      backdrop-filter var(--transition-fast),\n      box-shadow var(--transition-normal),\n      background var(--transition-normal),\n      border-color var(--transition-normal);\n  }\n}\n\n@layer refine.variants {\n  /* Color theme integration — custom props still take priority */\n  :host([color]) {\n    --_bg: var(--box-bg, var(--_theme-backdrop));\n    --_border-color: var(--box-border-color, var(--_theme-border));\n  }\n\n  /* Flat - border only, no shadow */\n  :host([variant='flat']) {\n    --_shadow: none;\n  }\n\n  /* Glass */\n  :host([variant='glass']:not([color])) {\n    --_bg: color-mix(in oklch, var(--color-secondary) 20%, transparent);\n    --_border-color: color-mix(in oklch, var(--color-secondary-contrast) 15%, transparent);\n  }\n\n  :host([variant='glass'][color]) {\n    --_bg: color-mix(in oklch, var(--_theme-base) 20%, transparent);\n    --_border-color: color-mix(in oklch, var(--_theme-contrast) 15%, transparent);\n    --_color: var(--_theme-content);\n  }\n\n  :host([variant='glass']) .box {\n    box-shadow: var(--shadow-md), var(--inset-shadow-xs);\n    backdrop-filter: blur(var(--blur-lg)) saturate(180%) brightness(1.05);\n  }\n\n  /* Subtle hover for solid/default + color (glass & frost manage their own hover) */\n  :host([color]:not([variant='glass'], [variant='frost']):hover) {\n    --_bg: color-mix(in oklch, var(--_theme-base) 16%, var(--color-contrast-50));\n    --_border-color: var(--_theme-focus);\n  }\n}\n\n@layer refine.utilities {\n  :host([fullwidth]) {\n    width: 100%;\n  }\n}\n","import { define, html, prop } from '@vielzeug/ore';\nimport {\n  colorThemeMixin,\n  elevationMixin,\n  frostVariantMixin,\n  paddingMixin,\n  rainbowEffectMixin,\n  roundedVariantMixin,\n} from '../../styles';\nimport type { ElevationLevel, PaddingSize, RoundedSize, ThemeColor } from '../../types';\nimport componentStyles from './box.css?inline';\n\n/** Box component properties */\nexport type OreBoxProps = {\n  /** Theme color */\n  color?: ThemeColor;\n  /** Animated border effect */\n  effect?: 'rainbow';\n  /** Shadow elevation level (0–5) */\n  elevation?: ElevationLevel;\n  /** Full width mode (100% of container) */\n  fullwidth?: boolean;\n  /** Internal padding size */\n  padding?: PaddingSize;\n  /** Border radius size */\n  rounded?: RoundedSize;\n  /** Visual style variant */\n  variant?: 'solid' | 'flat' | 'glass' | 'frost';\n};\n\n/**\n * ore-box — A foundational layout primitive with theming support.\n *\n * @element ore-box\n *\n * @attr {string} variant - Style variant: 'solid' | 'flat' | 'glass' | 'frost'\n * @attr {string} color - Color theme: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} padding - Padding size: 'none' | 'sm' | 'md' | 'lg' | 'xl'\n * @attr {string} elevation - Shadow elevation: '0' | '1' | '2' | '3' | '4' | '5'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {string} effect - Animated border effect: 'rainbow'\n * @attr {boolean} fullwidth - Expand to full width\n *\n * @slot - Default slot for content\n *\n * @part box - The inner box element\n *\n * @cssprop --box-bg - Background color\n * @cssprop --box-color - Text color\n * @cssprop --box-border - Border width\n * @cssprop --box-border-color - Border color\n * @cssprop --box-radius - Border radius\n * @cssprop --box-padding - Inner padding\n * @cssprop --box-shadow - Box shadow\n *\n * @example\n * ```html\n * <ore-box padding=\"lg\" elevation=\"2\">Simple content</ore-box>\n * <ore-box variant=\"glass\" color=\"primary\">Glass effect</ore-box>\n * <ore-box variant=\"frost\" effect=\"rainbow\">Frosted glass</ore-box>\n * ```\n */\nexport const BOX_TAG = 'ore-box' as const;\ndefine<OreBoxProps>(BOX_TAG, {\n  props: {\n    color: prop.string<ThemeColor>(),\n    effect: prop.string<'rainbow'>(),\n    elevation: prop.number<ElevationLevel>(),\n    fullwidth: prop.bool(),\n    padding: prop.string<PaddingSize>(),\n    rounded: prop.string<RoundedSize>(),\n    variant: prop.string<'flat' | 'solid' | 'frost' | 'glass'>(),\n  },\n  setup() {\n    return html`\n      <div class=\"box\" part=\"box\"><slot></slot></div>\n    `;\n  },\n\n  styles: [\n    colorThemeMixin,\n    elevationMixin,\n    paddingMixin,\n    roundedVariantMixin,\n    frostVariantMixin('.box'),\n    rainbowEffectMixin('.box'),\n    componentStyles,\n  ],\n});\n","@layer refine.base {\n  :host {\n    --_cols: var(--grid-cols, repeat(auto-fit, minmax(250px, 1fr)));\n    --_rows: var(--grid-rows, auto);\n    --_gap: var(--grid-gap, var(--size-4));\n    --_row-gap: var(--grid-row-gap, var(--_gap));\n    --_col-gap: var(--grid-col-gap, var(--_gap));\n\n    display: grid;\n    grid-template-rows: var(--_rows);\n    grid-template-columns: var(--_cols);\n    grid-auto-flow: row;\n    gap: var(--_row-gap) var(--_col-gap);\n  }\n\n  :host([gap='none']) {\n    --_row-gap: 0;\n    --_col-gap: 0;\n  }\n\n  :host([gap='xs']) {\n    --_row-gap: var(--size-1);\n    --_col-gap: var(--size-1);\n  }\n\n  :host([gap='sm']) {\n    --_row-gap: var(--size-2);\n    --_col-gap: var(--size-2);\n  }\n\n  :host([gap='md']) {\n    --_row-gap: var(--size-4);\n    --_col-gap: var(--size-4);\n  }\n\n  :host([gap='lg']) {\n    --_row-gap: var(--size-6);\n    --_col-gap: var(--size-6);\n  }\n\n  :host([gap='xl']) {\n    --_row-gap: var(--size-8);\n    --_col-gap: var(--size-8);\n  }\n\n  :host([gap='2xl']) {\n    --_row-gap: var(--size-12);\n    --_col-gap: var(--size-12);\n  }\n\n  :host([align='start']) {\n    align-items: start;\n  }\n\n  :host([align='center']) {\n    align-items: center;\n  }\n\n  :host([align='end']) {\n    align-items: end;\n  }\n\n  :host([align='stretch']) {\n    align-items: stretch;\n  }\n\n  :host([align='baseline']) {\n    align-items: baseline;\n  }\n\n  :host([justify='start']) {\n    justify-items: start;\n  }\n\n  :host([justify='center']) {\n    justify-items: center;\n  }\n\n  :host([justify='end']) {\n    justify-items: end;\n  }\n\n  :host([justify='stretch']) {\n    justify-items: stretch;\n  }\n\n  :host([flow='row']) {\n    grid-auto-flow: row;\n  }\n\n  :host([flow='column']) {\n    grid-auto-flow: column;\n  }\n\n  :host([flow='row-dense']) {\n    grid-auto-flow: row dense;\n  }\n\n  :host([flow='column-dense']) {\n    grid-auto-flow: column dense;\n  }\n\n  :host([fullwidth]) {\n    width: 100%;\n  }\n}\n","import { define, getHost, html, onCleanup, onMounted, prop, watchEffect } from '@vielzeug/ore';\nimport { createElementSize } from '@vielzeug/sentinel';\n\nimport styles from './grid.css?inline';\n\nconst BREAKPOINTS: ['cols2xl' | 'colsXl' | 'colsLg' | 'colsMd' | 'colsSm', string][] = [\n  ['cols2xl', '--size-screen-2xl'],\n  ['colsXl', '--size-screen-xl'],\n  ['colsLg', '--size-screen-lg'],\n  ['colsMd', '--size-screen-md'],\n  ['colsSm', '--size-screen-sm'],\n];\n\nconst AREAS_BREAKPOINTS: ['areas2xl' | 'areasXl' | 'areasLg' | 'areasMd' | 'areasSm', string][] = [\n  ['areas2xl', '--size-screen-2xl'],\n  ['areasXl', '--size-screen-xl'],\n  ['areasLg', '--size-screen-lg'],\n  ['areasMd', '--size-screen-md'],\n  ['areasSm', '--size-screen-sm'],\n];\n\nconst resolveBp = (host: HTMLElement, varName: string, fallback: number): number => {\n  const raw = getComputedStyle(host).getPropertyValue(varName).trim();\n  const parsed = Number.parseFloat(raw);\n\n  return Number.isFinite(parsed) ? parsed : fallback;\n};\n\nconst BP_FALLBACKS: Record<string, number> = {\n  '--size-screen-2xl': 1536,\n  '--size-screen-lg': 1024,\n  '--size-screen-md': 768,\n  '--size-screen-sm': 640,\n  '--size-screen-xl': 1280,\n};\n\ntype ColCount = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12' | 'auto';\n\n/** Grid component properties */\nexport type OreGridProps = {\n  /** Align items vertically */\n  align?: 'start' | 'center' | 'end' | 'stretch' | 'baseline';\n  /** CSS grid-template-areas value */\n  areas?: string;\n  /** grid-template-areas at 2xl breakpoint (≥1536px) */\n  areas2xl?: string;\n  /** grid-template-areas at lg breakpoint (≥1024px) */\n  areasLg?: string;\n  /** grid-template-areas at md breakpoint (≥768px) */\n  areasMd?: string;\n  /** grid-template-areas at sm breakpoint (≥640px) */\n  areasSm?: string;\n  /** grid-template-areas at xl breakpoint (≥1280px) */\n  areasXl?: string;\n  /** Number of columns: '1'-'12' | 'auto' */\n  cols?: ColCount;\n  /** Columns at 2xl breakpoint (≥1536px) */\n  cols2xl?: ColCount;\n  /** Columns at lg breakpoint (≥1024px) */\n  colsLg?: ColCount;\n  /** Columns at md breakpoint (≥768px) */\n  colsMd?: ColCount;\n  /** Columns at sm breakpoint (≥640px) */\n  colsSm?: ColCount;\n  /** Columns at xl breakpoint (≥1280px) */\n  colsXl?: ColCount;\n  /** Grid auto flow direction */\n  flow?: 'row' | 'column' | 'row-dense' | 'column-dense';\n  /** Stretch the grid to fill its container's full width */\n  fullwidth?: boolean;\n  /** Gap between items */\n  gap?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n  /** Justify items horizontally */\n  justify?: 'start' | 'center' | 'end' | 'stretch';\n  /** Minimum column width for responsive mode (default: 250px) */\n  minColWidth?: string;\n  /** Use auto-fit responsive columns */\n  responsive?: boolean;\n  /** Number of rows: '1'-'12' | 'auto' */\n  rows?: '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12' | 'auto';\n};\n\n/**\n * ore-grid — Flexible grid layout with responsive column control.\n *\n * Columns are computed in JS and applied as `--_cols` inline, so they respond\n * to the element's own width via ResizeObserver. CSS custom properties\n * `--grid-cols`, `--grid-rows`, `--grid-gap`, `--grid-row-gap`, `--grid-col-gap`\n * are honoured as fallbacks when no attribute is set.\n *\n * @element ore-grid\n *\n * @attr {string} cols - Column count: '1'–'12' | 'auto'\n * @attr {string} cols-sm - Columns when width ≥ 640px\n * @attr {string} cols-md - Columns when width ≥ 768px\n * @attr {string} cols-lg - Columns when width ≥ 1024px\n * @attr {string} cols-xl - Columns when width ≥ 1280px\n * @attr {string} cols-2xl - Columns when width ≥ 1536px\n * @attr {string} rows - Row count: '1'–'12' | 'auto'\n * @attr {string} gap - Gap token: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'\n * @attr {string} align - align-items: 'start' | 'center' | 'end' | 'stretch' | 'baseline'\n * @attr {string} justify - justify-items: 'start' | 'center' | 'end' | 'stretch'\n * @attr {string} flow - grid-auto-flow: 'row' | 'column' | 'row-dense' | 'column-dense'\n * @attr {boolean} responsive - Enables auto-fit columns without a fixed count\n * @attr {string} min-col-width - Min column width for responsive mode (default: 250px)\n * @attr {boolean} fullwidth - Stretch the grid to fill its container's full width\n * @attr {string} areas - CSS grid-template-areas value (e.g. \"'header header' 'nav main'\")\n * @attr {string} areas-sm - grid-template-areas when width ≥ 640px\n * @attr {string} areas-md - grid-template-areas when width ≥ 768px\n * @attr {string} areas-lg - grid-template-areas when width ≥ 1024px\n * @attr {string} areas-xl - grid-template-areas when width ≥ 1280px\n * @attr {string} areas-2xl - grid-template-areas when width ≥ 1536px\n *\n * @slot - Grid items\n *\n * @cssprop --grid-cols - Fallback column template (used when no cols attr is set)\n * @cssprop --grid-rows - Fallback row template\n * @cssprop --grid-gap - Fallback gap\n * @cssprop --grid-row-gap - Fallback row gap\n * @cssprop --grid-col-gap - Fallback column gap\n *\n * @example\n * <ore-grid cols=\"1\" cols-sm=\"2\" cols-lg=\"4\" gap=\"md\">\n *   <div>Item</div>\n * </ore-grid>\n *\n * @example\n * <!-- Responsive auto-fit -->\n * <ore-grid responsive min-col-width=\"200px\" gap=\"sm\">\n *   <div>Card</div>\n * </ore-grid>\n *\n * @example\n * <!-- Named grid areas -->\n * <ore-grid cols=\"2\" rows=\"2\" areas=\"'header header' 'nav main'\">\n *   <header style=\"grid-area: header\">Header</header>\n *   <nav style=\"grid-area: nav\">Nav</nav>\n *   <main style=\"grid-area: main\">Main</main>\n * </ore-grid>\n */\nexport const GRID_TAG = 'ore-grid' as const;\ndefine<OreGridProps>(GRID_TAG, {\n  props: {\n    align: prop.string<'start' | 'center' | 'end' | 'stretch' | 'baseline'>(),\n    areas: prop.string(),\n    areas2xl: prop.string(),\n    areasLg: prop.string(),\n    areasMd: prop.string(),\n    areasSm: prop.string(),\n    areasXl: prop.string(),\n    cols: prop.string<ColCount>(),\n    cols2xl: prop.string<ColCount>(),\n    colsLg: prop.string<ColCount>(),\n    colsMd: prop.string<ColCount>(),\n    colsSm: prop.string<ColCount>(),\n    colsXl: prop.string<ColCount>(),\n    flow: prop.string<'row' | 'column' | 'row-dense' | 'column-dense'>(),\n    fullwidth: prop.bool(false),\n    gap: prop.string<'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'>(),\n    justify: prop.string<'start' | 'center' | 'end' | 'stretch'>(),\n    minColWidth: prop.string(),\n    responsive: prop.bool(false),\n    rows: prop.string<'1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12' | 'auto'>(),\n  },\n\n  setup(props) {\n    const el = getHost();\n    const watch = watchEffect;\n\n    const computeCols = (activeCols: string | undefined, responsive: boolean, minW: string): string | null => {\n      if (activeCols === 'auto' || (!activeCols && responsive)) {\n        return `repeat(auto-fit, minmax(${minW || '250px'}, 1fr))`;\n      }\n\n      return activeCols ? `repeat(${activeCols}, 1fr)` : null;\n    };\n    const updateCols = () => {\n      const w = el.offsetWidth;\n      const responsive = Boolean(props.responsive.value);\n      const minW = props.minColWidth.value ?? '';\n      let activeCols: string | undefined;\n\n      for (const [key, cssVar] of BREAKPOINTS) {\n        if (w >= resolveBp(el, cssVar, BP_FALLBACKS[cssVar]) && props[key].value) {\n          activeCols = props[key].value!;\n          break;\n        }\n      }\n      activeCols ||= props.cols.value || undefined;\n\n      const colsValue = computeCols(activeCols, responsive, minW);\n\n      if (colsValue) {\n        el.style.setProperty('--_cols', colsValue);\n      } else {\n        el.style.removeProperty('--_cols');\n      }\n    };\n\n    // Re-run cols whenever any responsive prop changes\n    watch(() => {\n      void [\n        props.cols.value,\n        props.colsSm.value,\n        props.colsMd.value,\n        props.colsLg.value,\n        props.colsXl.value,\n        props.cols2xl.value,\n        props.responsive.value,\n        props.minColWidth.value,\n      ];\n      updateCols();\n    });\n\n    const updateAreas = () => {\n      const w = el.offsetWidth;\n      let active = '';\n\n      for (const [key, cssVar] of AREAS_BREAKPOINTS) {\n        if (w >= resolveBp(el, cssVar, BP_FALLBACKS[cssVar]) && props[key].value) {\n          active = props[key].value!;\n          break;\n        }\n      }\n      active ||= props.areas.value || '';\n\n      if (active) {\n        el.style.setProperty('grid-template-areas', active);\n      } else {\n        el.style.removeProperty('grid-template-areas');\n      }\n    };\n\n    // Rows\n    watch(() => {\n      const rows = props.rows.value;\n\n      if (rows && rows !== 'auto') {\n        el.style.setProperty('--_rows', `repeat(${rows}, 1fr)`);\n      } else {\n        el.style.removeProperty('--_rows');\n      }\n    });\n    // Grid template areas (responsive)\n    watch(() => {\n      void [\n        props.areas.value,\n        props.areasSm.value,\n        props.areasMd.value,\n        props.areasLg.value,\n        props.areasXl.value,\n        props.areas2xl.value,\n      ];\n      updateAreas();\n    });\n\n    // Also, update on element resize (drives breakpoint switching)\n    onMounted(() => {\n      const size = createElementSize(el);\n\n      onCleanup(() => size.dispose());\n\n      watch(() => {\n        const dims = size.value;\n        if (dims) {\n          updateCols();\n          updateAreas();\n        }\n      });\n    });\n\n    return html`\n      <slot></slot>\n    `;\n  },\n\n  styles: [styles],\n});\n","@layer refine.base {\n  :host {\n    display: block;\n  }\n}\n\n@layer refine.utilities {\n  :host([align='start']) {\n    align-self: start;\n  }\n\n  :host([align='center']) {\n    align-self: center;\n  }\n\n  :host([align='end']) {\n    align-self: end;\n  }\n\n  :host([align='stretch']) {\n    align-self: stretch;\n  }\n\n  :host([justify='start']) {\n    justify-self: start;\n  }\n\n  :host([justify='center']) {\n    justify-self: center;\n  }\n\n  :host([justify='end']) {\n    justify-self: end;\n  }\n\n  :host([justify='stretch']) {\n    justify-self: stretch;\n  }\n}\n","import { bind, define, html, prop } from '@vielzeug/ore';\nimport { computed } from '@vielzeug/ripple';\n\nimport styles from './grid-item.css?inline';\n\n/** Grid item component properties */\nexport type OreGridItemProps = {\n  /** Align self vertically within the grid cell */\n  align?: 'start' | 'center' | 'end' | 'stretch';\n  /** Named grid area to place the item into. */\n  area?: string;\n  /** Explicit grid-column value — overrides col-span (e.g. '2 / 5', 'span 3', '1 / -1'). */\n  col?: string;\n  /** Span N columns. Use 'full' to span all columns (1 / -1). */\n  colSpan?: '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12' | 'full';\n  /** Justify self horizontally within the grid cell */\n  justify?: 'start' | 'center' | 'end' | 'stretch';\n  /** Explicit grid-row value — overrides row-span (e.g. '1 / 3', 'span 2'). */\n  row?: string;\n  /** Span N rows. Use 'full' to span all rows (1 / -1). */\n  rowSpan?: '1' | '2' | '3' | '4' | '5' | '6' | 'full';\n};\n\n/**\n * ore-grid-item — A grid cell with declarative placement and span control.\n *\n * Use `col-span` / `row-span` for the common case of spanning columns/rows.\n * Use `col` / `row` for full CSS grid-column / grid-row shorthand power\n * (e.g. explicit placement, mixed span + start, negative lines).\n *\n * @element ore-grid-item\n *\n * @attr {string} area - CSS grid-area value for named-area placement\n * @attr {string} col-span - Columns to span: '1'–'12' | 'full'\n * @attr {string} row-span - Rows to span: '1'–'6' | 'full'\n * @attr {string} col - CSS grid-column value (overrides col-span)\n * @attr {string} row - CSS grid-row value (overrides row-span)\n * @attr {string} align - align-self: 'start' | 'center' | 'end' | 'stretch'\n * @attr {string} justify - justify-self: 'start' | 'center' | 'end' | 'stretch'\n *\n * @slot - Grid item content\n *\n * @example\n * <!-- Span 2 columns -->\n * <ore-grid-item col-span=\"2\">Wide</ore-grid-item>\n *\n * @example\n * <!-- Full-width row -->\n * <ore-grid-item col-span=\"full\">Banner</ore-grid-item>\n *\n * @example\n * <!-- Named area placement -->\n * <ore-grid-item area=\"sidebar\">Nav</ore-grid-item>\n *\n * @example\n * <!-- Explicit placement -->\n * <ore-grid-item col=\"2 / 5\" row=\"1 / 3\">Placed</ore-grid-item>\n */\nexport const GRID_ITEM_TAG = 'ore-grid-item' as const;\ndefine<OreGridItemProps>(GRID_ITEM_TAG, {\n  props: {\n    align: prop.string<'start' | 'center' | 'end' | 'stretch'>(),\n    area: prop.string(),\n    col: prop.string(),\n    colSpan: prop.string<'1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12' | 'full'>(),\n    justify: prop.string<'start' | 'center' | 'end' | 'stretch'>(),\n    row: prop.string(),\n    rowSpan: prop.string<'1' | '2' | '3' | '4' | '5' | '6' | 'full'>(),\n  },\n  setup(props) {\n    const gridColumn = computed(() => {\n      const col = props.col.value;\n      const span = props.colSpan.value;\n\n      if (col) return col;\n\n      if (span === 'full') return '1 / -1';\n\n      if (span) return `span ${span}`;\n\n      return '';\n    });\n\n    const gridRow = computed(() => {\n      const row = props.row.value;\n      const span = props.rowSpan.value;\n\n      if (row) return row;\n\n      if (span === 'full') return '1 / -1';\n\n      if (span) return `span ${span}`;\n\n      return '';\n    });\n\n    bind({\n      style: {\n        gridArea: props.area,\n        gridColumn,\n        gridRow,\n      },\n    });\n\n    return html`\n      <slot></slot>\n    `;\n  },\n  styles: [styles],\n});\n","@layer refine.base {\n  :host {\n    --_navbar-height: var(--navbar-height, var(--size-14));\n    --_navbar-width: var(--navbar-width, min(100%, 80rem));\n    --_navbar-offset: var(--navbar-offset, var(--size-3));\n    --_navbar-bg: var(--navbar-bg, var(--color-canvas));\n    --_navbar-color: var(--navbar-color, var(--color-contrast-900));\n    --_navbar-border-color: var(--navbar-border-color, var(--color-divider));\n    --_navbar-shadow: var(--navbar-shadow, var(--shadow-md));\n    --_navbar-radius: var(--navbar-radius, var(--rounded-lg));\n\n    box-sizing: border-box;\n    display: block;\n    width: 100%;\n    color: var(--_navbar-color);\n  }\n\n  :host([data-mode='sticky']) {\n    position: sticky;\n    top: 0;\n    z-index: var(--z-sticky);\n  }\n\n  :host([data-mode='floating']) {\n    position: fixed;\n    inset-inline: var(--_navbar-offset);\n    top: var(--_navbar-offset);\n    z-index: var(--z-sticky);\n  }\n\n  /* Preview mode: use absolute positioning so component stays within container bounds */\n  :host([data-preview-mode][data-mode='floating']) {\n    position: absolute;\n    inset-inline: var(--_navbar-offset);\n    top: auto;\n  }\n\n  :host([floating][sticky][data-scrolled]) {\n    inset-inline: 0;\n    top: 0;\n    width: 100%;\n  }\n\n  :host([data-preview-mode][floating][sticky][data-scrolled]) {\n    position: absolute;\n    inset-inline: 0;\n    top: auto;\n    width: auto;\n  }\n\n  :host > nav {\n    position: relative;\n    display: flex;\n    flex-direction: column;\n    width: 100%;\n  }\n\n  .navbar {\n    box-sizing: border-box;\n    display: flex;\n    flex-wrap: nowrap;\n    gap: var(--size-2);\n    align-items: center;\n    width: 100%;\n    max-width: var(--_navbar-width);\n    min-height: var(--_navbar-height);\n    padding: var(--size-2) var(--size-4);\n    margin-inline: auto;\n    overflow: auto hidden;\n    color: inherit;\n    white-space: nowrap;\n    background: var(--_navbar-bg);\n    border-top: none;\n    border-right: none;\n    border-bottom: var(--border) solid var(--_navbar-border-color);\n    border-left: none;\n    border-radius: 0;\n    backdrop-filter: var(--navbar-backdrop-filter, blur(var(--blur-md)));\n    transition: var(\n      --_motion-transition,\n      background var(--transition-normal),\n      border-color var(--transition-normal),\n      box-shadow var(--transition-normal),\n      transform var(--transition-normal)\n    );\n  }\n\n  :host([data-mode='floating']) .navbar {\n    border-top: var(--border) solid var(--_navbar-border-color);\n    border-right: var(--border) solid var(--_navbar-border-color);\n    border-bottom: var(--border) solid var(--_navbar-border-color);\n    border-left: var(--border) solid var(--_navbar-border-color);\n    border-radius: var(--_navbar-radius);\n  }\n\n  :host([data-mode='sticky']) .navbar,\n  :host([floating][sticky][data-scrolled]) .navbar {\n    max-width: 100%;\n    border-inline: none;\n    border-radius: 0;\n  }\n\n  :host([data-mode-transitioning][data-mode='sticky']) .navbar {\n    animation: navbar-floating-to-sticky var(--transition-normal) var(--ease-in-out);\n  }\n\n  :host([data-mode-transitioning][data-mode='floating']) .navbar {\n    animation: navbar-sticky-to-floating var(--transition-normal) var(--ease-in-out);\n  }\n\n  .navbar-logo,\n  .navbar-start,\n  .navbar-center,\n  .navbar-end {\n    display: flex;\n    align-items: center;\n    min-width: 0;\n    white-space: nowrap;\n  }\n\n  .navbar-logo {\n    flex: 0 0 auto;\n  }\n\n  .navbar-start {\n    flex: 0 0 auto;\n    gap: var(--size-1);\n  }\n\n  .navbar-center {\n    display: flex;\n    flex: 0 1 auto;\n    gap: var(--size-1);\n    justify-content: flex-start;\n    min-width: 0;\n  }\n\n  .navbar-end {\n    flex: 0 0 auto;\n    gap: var(--size-1);\n    margin-inline-start: auto;\n  }\n\n  .mobile-toggle {\n    display: none;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    width: var(--size-9);\n    height: var(--size-9);\n    padding: 0;\n    color: var(--color-contrast-700);\n    cursor: pointer;\n    background: transparent;\n    border: var(--border) solid transparent;\n    border-radius: var(--rounded-md);\n    transition:\n      background var(--transition-fast),\n      border-color var(--transition-fast),\n      color var(--transition-fast);\n  }\n\n  .mobile-toggle:hover {\n    color: var(--color-contrast-900);\n    background: var(--color-contrast-100);\n    border-color: var(--color-contrast-200);\n  }\n\n  .mobile-toggle:focus-visible {\n    outline: var(--focus-ring);\n  }\n\n  .mobile-menu-panel {\n    position: relative;\n    z-index: 1;\n    box-sizing: border-box;\n    display: none;\n    width: 100%;\n    max-width: var(--_navbar-width);\n    padding: var(--size-2);\n    margin-block-start: var(--size-2);\n    margin-inline: auto;\n    background: var(--_navbar-bg);\n    border: var(--border) solid var(--_navbar-border-color);\n    border-radius: var(--rounded-lg);\n    box-shadow: var(--_shadow, var(--_navbar-shadow));\n    backdrop-filter: var(--navbar-backdrop-filter, blur(var(--blur-md)));\n    transform-origin: top;\n    animation: navbar-mobile-in var(--transition-fast) var(--ease-out);\n  }\n\n  /* `:not([hidden])` — same reasoning as `.mobile-toggle` above: this panel's own `?hidden=`\n     binding (navbar.ts) already covers \"not mobile\" / \"menu closed\" / \"no mobile-menu content\",\n     but an unconditional `display: grid` here would still override that `[hidden]` for the \"no\n     content\" case specifically, since author styles always win over the UA stylesheet. */\n  :host([data-mobile][data-mobile-open]) .mobile-menu-panel:not([hidden]) {\n    display: grid;\n    gap: var(--size-1);\n  }\n\n  :host([data-mobile][data-mobile-open][data-mode='floating']) .mobile-menu-panel {\n    margin-block-start: var(--size-1-5);\n  }\n\n  :host([data-mobile][data-mobile-open][data-mode='sticky']) .mobile-menu-panel,\n  :host([data-mobile][data-mobile-open][floating][sticky][data-scrolled]) .mobile-menu-panel {\n    position: absolute;\n    inset-inline: 0;\n    top: 100%;\n    z-index: 2;\n    max-width: 100%;\n    margin: 0;\n    border-inline: none;\n    border-top: none;\n    border-radius: 0 0 var(--rounded-md) var(--rounded-md);\n  }\n\n  /* `:not([hidden])` matters — the component's own `?hidden=` binding (navbar.ts) hides this\n     button when there's neither `mobile-menu` slot content nor a `mobile-sidebar` target to\n     toggle. Without it, this rule's `display: inline-flex` — an author-stylesheet declaration —\n     unconditionally overrides the UA stylesheet's `[hidden] { display: none }`, since author\n     styles always win over UA styles regardless of selector specificity. That left the button\n     visibly clickable while toggling a `mobile-menu-panel` that stays hidden too (its own\n     `?hidden=` binding includes the same \"nothing to show\" check) — clicking did nothing\n     visible at all. */\n  :host([data-mobile]) .mobile-toggle:not([hidden]) {\n    display: inline-flex;\n    order: -1;\n  }\n\n  :host([data-mobile]) .navbar-start,\n  :host([data-mobile]) .navbar-center,\n  :host([data-mobile]) .navbar-end {\n    display: none;\n  }\n\n  :host([data-mobile][data-mobile-open]) .navbar {\n    border-bottom-right-radius: var(--rounded-md);\n    border-bottom-left-radius: var(--rounded-md);\n  }\n\n  @starting-style {\n    .mobile-menu-panel {\n      opacity: 0;\n      transform: translateY(var(--overlay-enter-translate-y));\n    }\n  }\n\n  @keyframes navbar-mobile-in {\n    from {\n      opacity: 0;\n      transform: translateY(var(--overlay-enter-translate-y));\n    }\n\n    to {\n      opacity: 1;\n      transform: translateY(0);\n    }\n  }\n\n  @keyframes navbar-floating-to-sticky {\n    from {\n      opacity: 0.92;\n      transform: translateY(6px) scale(0.985);\n    }\n\n    to {\n      opacity: 1;\n      transform: translateY(0) scale(1);\n    }\n  }\n\n  @keyframes navbar-sticky-to-floating {\n    from {\n      opacity: 0.95;\n      transform: translateY(-2px) scale(1);\n    }\n\n    to {\n      opacity: 1;\n      transform: translateY(0) scale(0.99);\n    }\n  }\n\n  .item {\n    box-sizing: border-box;\n    display: inline-flex;\n    flex-shrink: 0;\n    gap: var(--size-1);\n    align-items: center;\n    min-height: var(--_touch-target);\n    padding: var(--size-1-5) var(--size-2-5);\n    font-size: var(--text-sm);\n    font-weight: var(--font-medium);\n    color: var(--navbar-item-color, var(--color-contrast-700));\n    white-space: nowrap;\n    text-decoration: none;\n    appearance: none;\n    cursor: pointer;\n    background: transparent;\n    border: none;\n    border-radius: var(--rounded-md);\n    transition:\n      background var(--transition-fast),\n      color var(--transition-fast);\n  }\n\n  .item:hover,\n  .item:focus-visible {\n    color: var(--navbar-item-hover-color, var(--color-contrast-900));\n    outline: var(--focus-ring);\n    outline-offset: 1px;\n    background: var(--navbar-item-hover-bg, var(--color-contrast-100));\n  }\n\n  :host([active]) .item {\n    color: var(--navbar-item-active-color, var(--color-primary));\n    background: var(--navbar-item-active-bg, color-mix(in oklch, var(--color-primary) 12%, transparent));\n  }\n\n  :host([disabled]) .item,\n  :host([disabled]) .item:hover,\n  :host([disabled]) .item:focus-visible {\n    color: var(--color-contrast-400);\n    pointer-events: none;\n    cursor: not-allowed;\n    outline: none;\n    background: transparent;\n  }\n\n  .item-icon,\n  .item-end {\n    display: inline-flex;\n    align-items: center;\n  }\n\n  .item-label {\n    min-width: 0;\n    white-space: nowrap;\n  }\n\n  /* Icon-only items (no visible label — name conveyed via aria-label) hide the empty label\n     region so it stops reserving a `gap` slot next to the icon, and switch to compact,\n     symmetric padding instead of the icon+label layout's wider horizontal padding. Without\n     this, an icon-only item ends up lopsided: too much horizontal space around the icon plus\n     a phantom gap left over for a label that never renders. */\n  :host([icon-only]) .item-label {\n    display: none;\n  }\n\n  :host([icon-only]) .item {\n    padding: var(--size-1-5);\n  }\n\n  :host([navbar-mobile]) {\n    display: block;\n    width: 100%;\n  }\n\n  :host([navbar-mobile]) .item {\n    display: flex;\n    justify-content: flex-start;\n    width: 100%;\n  }\n}\n\n@layer refine.variants {\n  :host([variant='flat']) {\n    --_navbar-bg: color-mix(in oklch, var(--color-canvas) 88%, transparent);\n    --_navbar-shadow: none;\n  }\n\n  :host([variant='bordered']) {\n    --_navbar-bg: var(--color-canvas);\n    --_navbar-border-color: color-mix(in oklch, var(--color-contrast-500) 32%, transparent);\n  }\n\n  :host([variant='outline']) {\n    --_navbar-bg: transparent;\n    --_navbar-shadow: none;\n    --_navbar-border-color: color-mix(in oklch, var(--color-contrast-500) 40%, transparent);\n  }\n\n  :host([variant='glass']) {\n    --_navbar-bg: color-mix(in oklch, var(--color-canvas) 70%, transparent);\n    --navbar-backdrop-filter: blur(var(--blur-lg)) saturate(180%);\n  }\n\n  :host([color]) {\n    --_navbar-border-color: color-mix(in oklch, var(--_theme-border) 30%, transparent);\n  }\n}\n\n@media (width <= 768px) {\n  @layer refine.base {\n    :host([data-mode='floating']) {\n      inset-inline: var(--size-2);\n      top: var(--size-2);\n    }\n\n    :host([floating][sticky][data-scrolled]) {\n      inset-inline: 0;\n      top: 0;\n    }\n  }\n}\n","import {\n  bind,\n  createContext,\n  define,\n  getHost,\n  html,\n  inject,\n  onCleanup,\n  onMounted,\n  prop,\n  provide,\n  useEmit,\n  useSlots,\n} from '@vielzeug/ore';\nimport { computed, type Readable, signal, untrack, watch } from '@vielzeug/ripple';\nimport { createElementSize, createMediaQuery, SentinelUnavailableError } from '@vielzeug/sentinel';\n\nimport type { ElevationLevel, RoundedSize, ThemeColor, VisualVariant } from '../../types';\n\nimport '../../content/icon/icon';\nimport {\n  coarsePointerMixin,\n  colorThemeMixin,\n  elevationMixin,\n  frostVariantMixin,\n  reducedMotionMixin,\n  roundedVariantMixin,\n} from '../../styles';\nimport { computeSafeRel } from '../../utils';\nimport navbarStyles from './navbar.css?inline';\n\nconst listen = <E extends Event = Event>(\n  el: EventTarget | null | undefined,\n  name: string,\n  handler: (e: E) => void,\n  options?: AddEventListenerOptions,\n): (() => void) => {\n  if (!el) return () => {};\n\n  el.addEventListener(name, handler as EventListener, options);\n\n  return () => el.removeEventListener(name, handler as EventListener, options);\n};\n\ntype NavbarMode = 'floating' | 'sticky';\n\nconst hasElementContent = (el: Element): boolean => {\n  if (!(el instanceof HTMLElement)) return true;\n\n  if (el.tagName.includes('-')) return true;\n\n  if (el.childElementCount > 0) return true;\n\n  return (el.textContent ?? '').trim().length > 0;\n};\n\nconst parseMaxWidthPx = (query: string | undefined): number | undefined => {\n  const value = String(query ?? '').trim();\n\n  if (!value) return undefined;\n\n  const match = /max-width\\s*:\\s*([0-9]+(?:\\.[0-9]+)?)px/i.exec(value);\n\n  if (!match) return undefined;\n\n  const parsed = Number.parseFloat(match[1]);\n\n  return Number.isFinite(parsed) ? parsed : undefined;\n};\n\nconst resolveContainerElement = (el: HTMLElement): HTMLElement | null => {\n  let container = el.parentElement;\n\n  while (container?.tagName.toLowerCase() === 'ore-grid-item') {\n    container = container.parentElement;\n  }\n\n  return container;\n};\n\nconst readContainerWidth = (el: HTMLElement): number => {\n  const parentWidth = resolveContainerElement(el)?.clientWidth ?? 0;\n\n  if (parentWidth > 0) return parentWidth;\n\n  return el.offsetWidth;\n};\n\nconst findScrollContainer = (start: HTMLElement): HTMLElement | null => {\n  let current: HTMLElement | null = start.parentElement;\n\n  while (current) {\n    const styles = window.getComputedStyle(current);\n    const overflowY = styles.overflowY;\n\n    if (overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'overlay') {\n      return current;\n    }\n\n    current = current.parentElement;\n  }\n\n  return null;\n};\n\n/** Context provided by `ore-navbar` to `ore-navbar-item` children. */\nexport type NavbarContext = {\n  closeMobileMenu: () => void;\n  isMobile: Readable<boolean>;\n  mobileMenuOpen: Readable<boolean>;\n};\n\n/** Injection key for navbar context. */\nexport const NAVBAR_CTX = createContext<NavbarContext>('NavbarContext');\n\n/** Navbar component events */\nexport type OreNavbarEvents = {\n  'mobile-menu-change': { open: boolean };\n};\n\n/** Navbar component element interface */\nexport type NavbarElement = HTMLElement &\n  OreNavbarProps & {\n    closeMobileMenu(): void;\n    openMobileMenu(): void;\n    toggleMobileMenu(): void;\n  };\n\ntype MobileSidebarElement = HTMLElement & {\n  closeMobile?: () => void;\n  openMobile?: () => void;\n  toggleMobile?: () => void;\n};\n\n/** Navbar component properties */\nexport type OreNavbarProps = {\n  /** CSS media query used for mobile layout switching */\n  breakpoint?: string;\n  /** Theme color */\n  color?: ThemeColor;\n  /** Evaluate mobile breakpoint against container width only when possible. */\n  'container-breakpoints'?: boolean;\n  /** Shadow elevation level (0-5) */\n  elevation?: ElevationLevel;\n  /** Start as detached floating navbar */\n  floating?: boolean;\n  /** Accessible nav landmark label */\n  label?: string;\n  /** CSS selector for an external sidebar toggled by the mobile button */\n  'mobile-sidebar'?: string;\n  /** Border radius size */\n  rounded?: RoundedSize;\n  /** Scroll threshold in px used by floating+sticky transition */\n  'scroll-threshold'?: number;\n  /** Stick to top of viewport */\n  sticky?: boolean;\n  /** Visual style variant */\n  variant?: Exclude<VisualVariant, 'ghost' | 'text'>;\n};\n\n/** Navbar item properties */\nexport type OreNavbarItemProps = {\n  /** Whether this item represents the current page */\n  active?: boolean;\n  /** Whether this item is disabled */\n  disabled?: boolean;\n  /** Link target URL. Renders an anchor when provided. */\n  href?: string;\n  /**\n   * Icon-only mode — hides the (empty) label region and switches to compact, symmetric\n   * padding instead of the icon+label layout's wider horizontal padding. Set this whenever\n   * the default slot is intentionally left empty (name conveyed via `aria-label` instead),\n   * otherwise the empty label still reserves its inter-element gap and the item ends up\n   * with lopsided padding around the icon.\n   */\n  'icon-only'?: boolean;\n  /** Relationship of linked URL (anchor-only) */\n  rel?: string;\n  /** Browsing context for link (anchor-only) */\n  target?: string;\n};\n\n/**\n * `ore-navbar` — Responsive navigation with sticky/floating modes and a mobile overflow panel.\n *\n * @element ore-navbar\n * @element ore-navbar-item - Navigation link or button placed in the default or mobile-menu slot\n *\n * @attr {string} label - Accessible nav landmark label\n * @attr {boolean} sticky - Makes navbar sticky at top\n * @attr {boolean} floating - Makes navbar detached and floating\n * @attr {number} scroll-threshold - Scroll threshold for floating+sticky transition\n * @attr {string} breakpoint - CSS media query used for mobile mode\n * @attr {boolean} container-breakpoints - Evaluates parseable max-width breakpoints against container width\n * @attr {string} variant - Visual variant: 'flat' | 'solid' | 'bordered' | 'outline' | 'frost' | 'glass'\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {string} elevation - Shadow elevation: '0' | '1' | '2' | '3' | '4' | '5'\n *\n * @fires mobile-menu-change - Emitted when mobile menu open state changes. detail: { open: boolean }\n *\n * @slot logo - Brand/logo content rendered at the leading edge\n * @slot start - Content rendered in the left/start region\n * @slot - Center navigation content rendered between the start and end regions\n * @slot end - Content rendered in the right/end region\n * @slot mobile-menu - Controls and links rendered inside the mobile overflow panel\n *\n * @cssprop --navbar-height - Navbar bar height\n * @cssprop --navbar-width - Max width of the navbar content\n * @cssprop --navbar-offset - Horizontal offset for floating/sticky positioning\n * @cssprop --navbar-bg - Navbar background color\n * @cssprop --navbar-color - Navbar text color\n * @cssprop --navbar-border-color - Navbar border color\n * @cssprop --navbar-shadow - Navbar box shadow\n * @cssprop --navbar-radius - Border radius (floating/sticky modes)\n * @cssprop --navbar-backdrop-filter - Backdrop filter for blur effect\n * @cssprop --navbar-item-color - Nav item text color\n * @cssprop --navbar-item-hover-color - Nav item hover text color\n * @cssprop --navbar-item-hover-bg - Nav item hover background\n * @cssprop --navbar-item-active-color - Nav item active/current text color\n * @cssprop --navbar-item-active-bg - Nav item active/current background\n * @part nav - Outer navigation landmark\n * @part bar - Main navbar row container\n * @part logo - Logo slot container\n * @part start - Leading action/content region\n * @part center - Center content region\n * @part end - Trailing action/content region\n * @part mobile-toggle - Mobile menu toggle button\n * @part mobile-menu - Mobile overflow panel\n * @part item-icon - Leading icon inside navbar items\n * @part item-label - Label text inside navbar items\n * @part item-end - Trailing content inside navbar items\n * @part item - Clickable navbar item root\n * @example\n * ```html\n * <ore-navbar sticky elevation=\"1\">\n *   <a href=\"/\" slot=\"logo\"><strong>MyApp</strong></a>\n *   <ore-navbar-item href=\"/dashboard\">Dashboard</ore-navbar-item>\n *   <ore-navbar-item href=\"/docs\">Docs</ore-navbar-item>\n *   <ore-button slot=\"end\" variant=\"solid\" color=\"primary\" size=\"sm\">Sign in</ore-button>\n * </ore-navbar>\n * ```\n */\nexport const NAVBAR_TAG = 'ore-navbar' as const;\ndefine<OreNavbarProps>(NAVBAR_TAG, {\n  props: {\n    breakpoint: prop.string('(max-width: 768px)'),\n    color: prop.string<ThemeColor>(),\n    'container-breakpoints': prop.bool(false),\n    elevation: prop.number<ElevationLevel>(),\n    floating: prop.bool(false),\n    label: prop.string('Main navigation'),\n    'mobile-sidebar': prop.string(),\n    rounded: prop.string<RoundedSize>(),\n    'scroll-threshold': prop.number(80),\n    sticky: prop.bool(false),\n    variant: prop.string<'flat' | 'solid' | 'bordered' | 'outline' | 'frost'>(),\n  },\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreNavbarEvents>();\n    const slots = useSlots();\n\n    const hasLogo = slots.has('logo');\n    const mobileMenuElements = slots.elements('mobile-menu');\n    const hasMobileMenu = signal(false);\n    const mobileSidebarTarget = signal<MobileSidebarElement | null>(null);\n    const isExternalMobileMode = signal(false);\n    const isExternalMobileOpen = signal(false);\n    const isMobile = signal(false);\n    const isMobileMenuOpen = signal(false);\n    const isModeTransitioning = signal(false);\n    const isScrolled = signal(false);\n    const scrollBase = signal(0);\n    const mediaMatches = signal(false);\n    const sizeMatches = signal(false);\n    const maxWidthPx = signal<number | undefined>(parseMaxWidthPx(props.breakpoint.value));\n    const isPreviewMode = signal(false);\n\n    const getExternalSidebar = () => {\n      const selector = String(props['mobile-sidebar'].value ?? '').trim();\n\n      if (!selector) return null;\n\n      const root = el.getRootNode();\n      const scopedTarget =\n        root instanceof ShadowRoot || root instanceof Document\n          ? (root.querySelector(selector) as MobileSidebarElement | null)\n          : null;\n\n      return scopedTarget ?? (document.querySelector(selector) as MobileSidebarElement | null);\n    };\n\n    provide(NAVBAR_CTX, {\n      // Wrapped, not passed directly — `closeMobileMenu` (below) isn't defined yet at this point\n      // in `setup()`; by the time `ore-navbar-item` actually calls this (a later click), it is.\n      closeMobileMenu: () => closeMobileMenu(),\n      isMobile: computed(() => isMobile.value) as Readable<boolean>,\n      mobileMenuOpen: computed(() => isMobileMenuOpen.value) as Readable<boolean>,\n    });\n\n    const computeMode = (): NavbarMode | undefined => {\n      if (props.floating.value && props.sticky.value) {\n        return isScrolled.value ? 'sticky' : 'floating';\n      }\n\n      if (props.floating.value) return 'floating';\n\n      if (props.sticky.value) return 'sticky';\n\n      return undefined;\n    };\n\n    const setMobileMenu = (next: boolean) => {\n      const open = Boolean(next);\n\n      if (!hasMobileMenu.value) {\n        const target = mobileSidebarTarget.value ?? getExternalSidebar();\n\n        if (target) {\n          if (open) {\n            target.openMobile?.();\n          } else {\n            target.closeMobile?.();\n          }\n\n          return;\n        }\n      }\n\n      if (open && !hasMobileMenu.value) return;\n\n      if (isMobileMenuOpen.value === open) return;\n\n      isMobileMenuOpen.value = open;\n      emit('mobile-menu-change', { open });\n    };\n\n    const closeMobileMenu = () => setMobileMenu(false);\n    const openMobileMenu = () => setMobileMenu(true);\n    const toggleMobileMenu = () => {\n      if (!hasMobileMenu.value) {\n        const target = mobileSidebarTarget.value ?? getExternalSidebar();\n\n        if (target) {\n          if (typeof target.toggleMobile === 'function') {\n            target.toggleMobile();\n          } else if (typeof target.openMobile === 'function' && typeof target.closeMobile === 'function') {\n            const isOpen = target.hasAttribute('data-mobile-open');\n\n            if (isOpen) target.closeMobile();\n            else target.openMobile();\n          }\n\n          return;\n        }\n      }\n\n      setMobileMenu(!isMobileMenuOpen.value);\n    };\n\n    const syncMobileMode = () => {\n      const next =\n        (mobileSidebarTarget.value && !hasMobileMenu.value ? isExternalMobileMode.value : false) ||\n        mediaMatches.value ||\n        sizeMatches.value;\n\n      isMobile.value = next;\n\n      if (!next) closeMobileMenu();\n    };\n\n    const readScrollOffset = (scrollContainer: HTMLElement | null): number => {\n      if (scrollContainer) {\n        return scrollContainer.scrollTop || 0;\n      }\n\n      return window.scrollY || document.documentElement.scrollTop || 0;\n    };\n\n    const resetScrollBase = (scrollContainer: HTMLElement | null) => {\n      scrollBase.value = readScrollOffset(scrollContainer);\n    };\n\n    const updateScrolled = (scrollContainer: HTMLElement | null = null) => {\n      if (!(props.floating.value && props.sticky.value)) {\n        if (isScrolled.value) isScrolled.value = false;\n\n        return;\n      }\n\n      const threshold = Math.max(0, Number(props['scroll-threshold'].value) || 0);\n      const currentOffset = readScrollOffset(scrollContainer);\n      const delta = currentOffset - scrollBase.value;\n\n      isScrolled.value = delta > threshold;\n    };\n\n    bind({\n      attr: {\n        'data-mobile': () => (isMobile.value ? true : undefined),\n        'data-mobile-open': () => (isMobile.value && isMobileMenuOpen.value ? true : undefined),\n        'data-mode': () => computeMode() ?? null,\n        'data-mode-transitioning': () => (isModeTransitioning.value ? true : undefined),\n        'data-preview-mode': () => (isPreviewMode.value ? true : undefined),\n        'data-scrolled': () => (props.floating.value && props.sticky.value && isScrolled.value ? true : undefined),\n      },\n    });\n\n    onMounted(() => {\n      const navbarEl = el as NavbarElement;\n      const scrollContainer = findScrollContainer(el);\n\n      navbarEl.closeMobileMenu = closeMobileMenu;\n      navbarEl.openMobileMenu = openMobileMenu;\n      navbarEl.toggleMobileMenu = toggleMobileMenu;\n\n      const stopScroll = listen(\n        window,\n        'scroll',\n        () => {\n          updateScrolled(scrollContainer);\n        },\n        { passive: true },\n      );\n      const stopContainerScroll = scrollContainer\n        ? listen(\n            scrollContainer,\n            'scroll',\n            () => {\n              updateScrolled(scrollContainer);\n            },\n            { passive: true },\n          )\n        : undefined;\n      const stopEscape = listen(el, 'keydown', (event: KeyboardEvent) => {\n        if (event.key !== 'Escape' || !isMobileMenuOpen.value) return;\n\n        closeMobileMenu();\n      });\n\n      let mediaCleanup: (() => void) | undefined;\n      let mobileSidebarCleanup: (() => void) | undefined;\n      let modeTransitionTimeout: ReturnType<typeof setTimeout> | undefined;\n      let previousMode: NavbarMode | undefined;\n\n      const resolveMobileSidebarTarget = () => {\n        mobileSidebarCleanup?.();\n        mobileSidebarCleanup = undefined;\n        mobileSidebarTarget.value = null;\n        isExternalMobileMode.value = false;\n        isExternalMobileOpen.value = false;\n\n        if (!String(props['mobile-sidebar'].value ?? '').trim()) return;\n\n        const target = getExternalSidebar();\n\n        if (!target) {\n          const root = el.getRootNode();\n          const discoveryRoot = root instanceof Document || root instanceof ShadowRoot ? root : document;\n          const discoveryObserver = new MutationObserver(() => {\n            if (getExternalSidebar()) resolveMobileSidebarTarget();\n          });\n\n          discoveryObserver.observe(discoveryRoot, { childList: true, subtree: true });\n          mobileSidebarCleanup = () => discoveryObserver.disconnect();\n\n          return;\n        }\n\n        const syncTargetState = (event?: CustomEvent<{ open: boolean }>) => {\n          const hasBottomNav = target.hasAttribute('data-bottom-nav');\n          const hasMobileOpen = target.hasAttribute('data-mobile-open');\n\n          isExternalMobileMode.value = hasBottomNav;\n          isExternalMobileOpen.value = event?.detail ? event.detail.open : hasMobileOpen;\n\n          // If the sidebar is reporting it's open, it must be in bottom-nav mode\n          // (either natural or forced). We honor this to avoid race conditions\n          // where attributes haven't reflected yet.\n          if (isExternalMobileOpen.value && !isExternalMobileMode.value) {\n            isExternalMobileMode.value = true;\n          }\n\n          syncMobileMode();\n        };\n\n        const targetObserver = new MutationObserver(() => {\n          syncTargetState();\n        });\n\n        syncTargetState();\n        targetObserver.observe(target, {\n          attributeFilter: ['data-bottom-nav', 'data-mobile-open'],\n          attributes: true,\n        });\n        target.addEventListener('mobile-open-change', syncTargetState as EventListener);\n        mobileSidebarCleanup = () => {\n          targetObserver.disconnect();\n          target.removeEventListener('mobile-open-change', syncTargetState as EventListener);\n        };\n        mobileSidebarTarget.value = target;\n      };\n\n      const triggerModeTransition = () => {\n        isModeTransitioning.value = true;\n\n        if (modeTransitionTimeout != null) clearTimeout(modeTransitionTimeout);\n\n        modeTransitionTimeout = setTimeout(() => {\n          isModeTransitioning.value = false;\n          modeTransitionTimeout = undefined;\n        }, 220);\n      };\n\n      const stopModeWatch = watch(\n        computed(() => props.floating.value && props.sticky.value),\n        (enabled) => {\n          if (!enabled) {\n            if (isScrolled.value) isScrolled.value = false;\n\n            if (isModeTransitioning.value) isModeTransitioning.value = false;\n\n            previousMode = undefined;\n\n            if (modeTransitionTimeout != null) {\n              clearTimeout(modeTransitionTimeout);\n              modeTransitionTimeout = undefined;\n            }\n\n            return;\n          }\n\n          resetScrollBase(scrollContainer);\n          updateScrolled(scrollContainer);\n\n          const currentMode = computeMode();\n\n          previousMode = currentMode;\n        },\n        { immediate: true },\n      );\n\n      const stopMobileSidebarWatch = watch(\n        props['mobile-sidebar'],\n        () => {\n          resolveMobileSidebarTarget();\n        },\n        { immediate: true },\n      );\n\n      const stopModeTransitionWatch = watch(\n        computed(() => computeMode()),\n        (nextMode) => {\n          const comboEnabled = props.floating.value && props.sticky.value;\n\n          if (!comboEnabled) {\n            previousMode = nextMode ?? undefined;\n\n            return;\n          }\n\n          const next = nextMode ?? undefined;\n\n          if (previousMode && next && previousMode !== next) {\n            triggerModeTransition();\n          }\n\n          previousMode = next;\n        },\n        { immediate: true },\n      );\n\n      const stopMobileMenuSlotWatch = watch(\n        hasMobileMenu,\n        (hasContent) => {\n          if (!hasContent && isMobileMenuOpen.value) {\n            closeMobileMenu();\n          }\n        },\n        { immediate: true },\n      );\n      const syncMobileMenuContent = () => {\n        hasMobileMenu.value = mobileMenuElements.value.some(hasElementContent);\n      };\n      const stopMobileMenuElementsWatch = watch(mobileMenuElements, syncMobileMenuContent, { immediate: true });\n      const mobileMenuContentObserver = new MutationObserver(() => {\n        syncMobileMenuContent();\n      });\n\n      // Parser-created demo content can populate an already-assigned slot wrapper after this\n      // custom element connects; `slotchange` alone does not observe that nested content.\n      mobileMenuContentObserver.observe(el, { childList: true, subtree: true });\n\n      watch(\n        props.breakpoint,\n        (query) => {\n          // Untrack the callback body: the watch already tracks `props.breakpoint` via\n          // its internal `read()`. Without untrack, signals read inside (e.g.\n          // `mediaMatches` via `syncMobileMode()`) become dependencies of this watch\n          // effect. When the sentinel updates `mediaMatches` on a viewport change, the\n          // effect re-runs — `EffectNode.run()` disposes the previous scope (killing the\n          // mediaHandle and its MediaQueryList listener) but the callback is NOT invoked\n          // (source unchanged), so no new handle is created. The navbar is then deaf to\n          // further MQ changes and stays stuck in mobile mode after resizing back to\n          // desktop.\n          untrack(() => {\n            mediaCleanup?.();\n            mediaCleanup = undefined;\n\n            const mediaQuery = String(query ?? '').trim();\n\n            maxWidthPx.value = parseMaxWidthPx(mediaQuery);\n            mediaMatches.value = false;\n\n            const width = readContainerWidth(el);\n\n            sizeMatches.value = width > 0 && maxWidthPx.value != null ? width <= maxWidthPx.value : false;\n            syncMobileMode();\n\n            if (props['container-breakpoints'].value && maxWidthPx.value != null) {\n              return;\n            }\n\n            if (!mediaQuery) {\n              return;\n            }\n\n            try {\n              const mediaHandle = createMediaQuery(mediaQuery);\n              const syncMedia = (state: typeof mediaHandle.value) => {\n                if (state) {\n                  mediaMatches.value = state.matches;\n                  syncMobileMode();\n                }\n              };\n\n              syncMedia(mediaHandle.value);\n\n              const mediaCleanupFn = watch(mediaHandle, syncMedia);\n              mediaCleanup = () => {\n                mediaCleanupFn.dispose();\n                mediaHandle.dispose();\n              };\n            } catch (error) {\n              if (!(error instanceof SentinelUnavailableError)) throw error;\n            }\n          });\n        },\n        { immediate: true },\n      );\n\n      const stopResizeEffect =\n        typeof ResizeObserver === 'function'\n          ? (() => {\n              const hostSize = createElementSize(el);\n              onCleanup(() => hostSize.dispose());\n\n              const wrapperEl = el.parentElement;\n              const containerEl = resolveContainerElement(el);\n              const wrapperSize = wrapperEl ? createElementSize(wrapperEl) : undefined;\n              const parentSize = containerEl && containerEl !== wrapperEl ? createElementSize(containerEl) : undefined;\n\n              if (wrapperSize) {\n                onCleanup(() => wrapperSize.dispose());\n              }\n              if (parentSize) {\n                onCleanup(() => parentSize.dispose());\n              }\n\n              return watch(\n                computed(() => [\n                  hostSize.value?.width,\n                  hostSize.value?.height,\n                  wrapperSize?.value?.width,\n                  wrapperSize?.value?.height,\n                  parentSize?.value?.width,\n                  parentSize?.value?.height,\n                ]),\n                () => {\n                  const width = readContainerWidth(el);\n                  const parentWidth = resolveContainerElement(el)?.clientWidth ?? 0;\n\n                  sizeMatches.value = width > 0 && maxWidthPx.value != null ? width <= maxWidthPx.value : false;\n                  isPreviewMode.value = parentWidth > 0 && parentWidth < window.innerWidth;\n                  syncMobileMode();\n                },\n              );\n            })()\n          : undefined;\n\n      return () => {\n        stopEscape?.();\n        stopScroll?.();\n        stopContainerScroll?.();\n        stopModeWatch?.dispose();\n        stopModeTransitionWatch?.dispose();\n        stopMobileMenuSlotWatch?.dispose();\n        stopMobileMenuElementsWatch?.dispose();\n        stopMobileSidebarWatch?.dispose();\n        mobileMenuContentObserver.disconnect();\n        mediaCleanup?.();\n        mobileSidebarCleanup?.();\n        stopResizeEffect?.dispose();\n\n        if (modeTransitionTimeout != null) {\n          clearTimeout(modeTransitionTimeout);\n          modeTransitionTimeout = undefined;\n        }\n      };\n    });\n\n    return html`\n      <nav part=\"nav\" aria-label=\"${props.label}\">\n        <div class=\"navbar\" part=\"bar\">\n          <div class=\"navbar-logo\" part=\"logo\" ?hidden=${() => !hasLogo.value}>\n            <slot name=\"logo\"></slot>\n          </div>\n\n          <div class=\"navbar-start\" part=\"start\">\n            <slot name=\"start\"></slot>\n          </div>\n\n          <div class=\"navbar-center\" part=\"center\">\n            <slot></slot>\n          </div>\n\n          <div class=\"navbar-end\" part=\"end\">\n            <slot name=\"end\"></slot>\n          </div>\n\n          <button\n            class=\"mobile-toggle\"\n            part=\"mobile-toggle\"\n            type=\"button\"\n            aria-label=\"${() =>\n              hasMobileMenu.value\n                ? isMobileMenuOpen.value\n                  ? 'Close navigation menu'\n                  : 'Open navigation menu'\n                : isExternalMobileOpen.value\n                  ? 'Close navigation menu'\n                  : 'Open navigation menu'}\"\n            aria-controls=\"mobile-menu-panel\"\n            aria-expanded=\"${() => String(hasMobileMenu.value ? isMobileMenuOpen.value : isExternalMobileOpen.value)}\"\n            ?hidden=${() => !isMobile.value || (!hasMobileMenu.value && !mobileSidebarTarget.value)}\n            @click=\"${toggleMobileMenu}\">\n            <ore-icon\n              name=\"${() => ((hasMobileMenu.value ? isMobileMenuOpen.value : isExternalMobileOpen.value) ? 'x' : 'menu')}\"\n              size=\"18\"\n              stroke-width=\"2.5\"\n              aria-hidden=\"true\"></ore-icon>\n          </button>\n        </div>\n\n        <div\n          id=\"mobile-menu-panel\"\n          class=\"mobile-menu-panel\"\n          part=\"mobile-menu\"\n          role=\"navigation\"\n          aria-label=\"${() => `${props.label.value} mobile menu`}\"\n          ?hidden=${() => !isMobile.value || !isMobileMenuOpen.value || !hasMobileMenu.value}>\n          <slot name=\"mobile-menu\"></slot>\n        </div>\n      </nav>\n    `;\n  },\n  styles: [\n    colorThemeMixin,\n    elevationMixin,\n    roundedVariantMixin,\n    coarsePointerMixin,\n    reducedMotionMixin,\n    frostVariantMixin('.navbar'),\n    navbarStyles,\n  ],\n});\n\n/**\n * `ore-navbar-item` — Navigation item for navbar slots.\n *\n * Renders as an anchor when `href` is provided and item is not disabled.\n *\n * @element ore-navbar-item\n *\n * @attr {boolean} active - Marks item as the current active route\n * @attr {boolean} disabled - Disables interaction\n * @attr {string} href - Link URL; renders as `<a>` when set\n * @attr {boolean} icon-only - Compact, symmetric padding for items with no visible label\n * @attr {string} rel - Anchor `rel` attribute (links only)\n * @attr {string} target - Anchor `target` attribute (links only)\n *\n * @slot - Item label\n * @slot icon - Optional icon before the label\n *\n * @part item - Root clickable element (anchor or button).\n * @part item-icon - Leading icon container.\n * @part item-label - Label text container.\n * @part item-end - Trailing content container.\n *\n * @example\n * ```html\n * <ore-navbar-item href=\"/home\">Home</ore-navbar-item>\n * <ore-navbar-item href=\"/docs\" active>Docs</ore-navbar-item>\n * <ore-navbar-item href=\"/about\" target=\"_blank\" rel=\"noopener\">About</ore-navbar-item>\n * <ore-navbar-item disabled>Disabled</ore-navbar-item>\n * <ore-navbar-item icon-only aria-label=\"Search\"><ore-icon slot=\"icon\" name=\"search\"></ore-icon></ore-navbar-item>\n * ```\n */\nexport const NAVBAR_ITEM_TAG = 'ore-navbar-item' as const;\ndefine<OreNavbarItemProps>(NAVBAR_ITEM_TAG, {\n  props: {\n    active: prop.bool(false),\n    disabled: prop.bool(false),\n    href: prop.string(),\n    'icon-only': prop.bool(false),\n    rel: prop.string(),\n    target: prop.string(),\n  },\n  setup(props) {\n    const slots = useSlots();\n\n    const hasIcon = () => slots.has('icon').value;\n    const hasEnd = () => slots.has('end').value;\n    const navbarCtx = inject(NAVBAR_CTX);\n\n    bind({\n      attr: {\n        'navbar-mobile': () => (navbarCtx?.isMobile.value ? true : undefined),\n        'navbar-mobile-open': () => (navbarCtx?.mobileMenuOpen.value ? true : undefined),\n      },\n    });\n\n    const isLink = () => Boolean(props.href.value) && !props.disabled.value;\n\n    // Prevent reverse tabnapping: auto-inject noopener + noreferrer for _blank links.\n    const effectiveRel = computed(() => computeSafeRel(props.rel.value, props.target.value));\n\n    // Closes the mobile overflow panel when one of its items is activated — otherwise picking a\n    // destination (or firing any other action placed in the `mobile-menu` slot) leaves the panel\n    // open over the page until the user separately taps the toggle again. Only matters while\n    // actually in mobile mode; on desktop `navbarCtx.mobileMenuOpen` is never true to begin with,\n    // so `closeMobileMenu()` (idempotent — see `setMobileMenu`'s equality check) is a no-op there.\n    const closeMobileMenuIfOpen = (): void => {\n      if (navbarCtx?.mobileMenuOpen.value) navbarCtx.closeMobileMenu();\n    };\n\n    const renderItemContent = () => html`\n      <span class=\"item-icon\" part=\"item-icon\" ?hidden=${() => !hasIcon()} aria-hidden=\"true\">\n        <slot name=\"icon\"></slot>\n      </span>\n      <span class=\"item-label\" part=\"item-label\"><slot></slot></span>\n      <span class=\"item-end\" part=\"item-end\" ?hidden=${() => !hasEnd()}>\n        <slot name=\"end\"></slot>\n      </span>\n    `;\n\n    return html`\n      ${() => {\n        if (isLink()) {\n          return html`\n            <a\n              class=\"item\"\n              part=\"item\"\n              href=\"${props.href}\"\n              rel=\"${effectiveRel}\"\n              target=\"${props.target}\"\n              aria-current=\"${() => (props.active.value ? 'page' : null)}\"\n              @click=${closeMobileMenuIfOpen}>\n              ${renderItemContent()}\n            </a>\n          `;\n        }\n\n        if (props.disabled.value) {\n          return html`\n            <div class=\"item\" part=\"item\" tabindex=\"-1\" aria-disabled=\"true\">${renderItemContent()}</div>\n          `;\n        }\n\n        return html`\n          <button class=\"item\" part=\"item\" type=\"button\" @click=${closeMobileMenuIfOpen}>${renderItemContent()}</button>\n        `;\n      }}\n    `;\n  },\n  styles: [coarsePointerMixin, navbarStyles],\n});\n",".sidebar-logo[hidden] {\n  display: none;\n  min-width: 0;\n  min-height: 0;\n  margin: 0;\n}\n\n/*\n * Simplified and unified sidebar CSS:\n * - Grouped collapsed/expanded state rules\n * - Consistent use of CSS variables for spacing, color, and transitions\n * - Removed redundant or legacy rules\n * - Clarified variant handling\n */\n\n@layer refine.base {\n  :host {\n    --_sidebar-width: var(--sidebar-width, 16rem);\n    --_sidebar-collapsed-width: var(--sidebar-collapsed-width, 3.5rem);\n    --_sidebar-transition: var(--transition-normal);\n    --_panel-bg: var(--sidebar-bg, var(--color-canvas));\n    --_panel-blur: var(--sidebar-panel-blur, var(--blur-md));\n    --_panel-border-color: var(--sidebar-border-color, var(--color-divider));\n    --_panel-radius: var(--sidebar-radius, var(--rounded-lg));\n    --_panel-shadow: var(--sidebar-shadow, var(--shadow-md));\n\n    box-sizing: border-box;\n    display: block;\n    width: 100%;\n    min-width: var(--size-2xs);\n    max-width: var(--_sidebar-width);\n    height: 100%;\n    min-height: 0;\n    overflow: visible;\n    transition:\n      max-width var(--_sidebar-transition),\n      min-width var(--_sidebar-transition);\n    will-change: max-width;\n  }\n\n  :host > nav {\n    position: relative;\n    box-sizing: border-box;\n    display: flex;\n    flex-direction: column;\n    width: 100%;\n    height: 100%;\n    min-height: 0;\n    overflow: hidden;\n    background: var(--_panel-bg);\n    border-inline-end: var(--border) solid var(--_panel-border-color);\n    backdrop-filter: blur(var(--_panel-blur));\n  }\n\n  .mobile-backdrop {\n    position: absolute;\n    inset: 0;\n    z-index: calc(var(--z-sticky) + 1);\n    display: none;\n    width: 100%;\n    height: 100%;\n    background: color-mix(in oklch, var(--color-contrast-950) 36%, transparent);\n    border: 0;\n  }\n\n  :host([data-bottom-nav][data-mobile-open]) .mobile-backdrop {\n    position: fixed;\n    inset: 0;\n    z-index: calc(var(--z-sticky) + 1);\n    display: block;\n    width: 100vw;\n    height: 100dvh;\n  }\n\n  :host([data-preview-mode][data-bottom-nav][data-mobile-open]) .mobile-backdrop {\n    position: absolute;\n    inset: 0;\n    width: 100%;\n    height: 100%;\n  }\n\n  :host([data-no-transition]),\n  :host([data-no-transition]) > nav {\n    transition: none;\n  }\n\n  :host([data-collapsed]) {\n    min-width: var(--_sidebar-collapsed-width);\n    max-width: var(--_sidebar-collapsed-width);\n  }\n\n  :host([data-bottom-nav]) {\n    position: fixed;\n    inset-block-end: 0;\n    inset-inline: 0;\n    z-index: calc(var(--z-sticky) + 2);\n    width: 100%;\n    min-width: 0;\n    max-width: 100%;\n    height: var(--sidebar-bottom-nav-height, 3.75rem);\n    pointer-events: auto;\n  }\n\n  /* Preview mode: constrain bottom-nav to container bounds */\n  :host([data-preview-mode][data-bottom-nav]) {\n    position: absolute;\n    inset: 0;\n    width: auto;\n    height: auto;\n    pointer-events: none;\n  }\n\n  :host([data-bottom-nav]) > nav {\n    position: fixed;\n    inset-block: 0;\n    inset-inline-start: 0;\n    z-index: calc(var(--z-sticky) + 3);\n    width: min(var(--_sidebar-width), 85vw);\n    max-width: 85vw;\n    max-height: 100dvh;\n    transform: translateX(-104%);\n    transition: transform var(--transition-normal);\n  }\n\n  /* Preview mode: use absolute positioning so drawer stays within container */\n  :host([data-preview-mode][data-bottom-nav]) > nav {\n    position: absolute;\n    inset-block: 0;\n    inset-inline-start: 0;\n    z-index: calc(var(--z-sticky) + 3);\n    max-height: 100%;\n    pointer-events: auto;\n  }\n\n  :host(:dir(rtl)[data-bottom-nav]) > nav {\n    transform: translateX(104%);\n  }\n\n  :host([data-bottom-nav][data-mobile-open]) > nav {\n    transform: translateX(0);\n  }\n\n  .bottom-bar {\n    display: flex;\n    gap: var(--size-1);\n    align-items: stretch;\n    justify-content: space-around;\n    width: 100%;\n    height: 100%;\n    padding: var(--size-1);\n    pointer-events: none;\n    background: var(--_panel-bg);\n    border-top: var(--border) solid var(--_panel-border-color);\n    box-shadow: var(--shadow-sm);\n    opacity: 0;\n    backdrop-filter: blur(var(--_panel-blur));\n    transform: translateY(100%);\n    transition:\n      opacity var(--_sidebar-transition),\n      transform var(--_sidebar-transition),\n      display var(--_sidebar-transition) allow-discrete;\n  }\n\n  :host([data-bottom-nav]) .bottom-bar {\n    pointer-events: auto;\n    opacity: 1;\n    transform: translateY(0);\n  }\n\n  :host([data-preview-mode][data-bottom-nav]) .bottom-bar {\n    position: absolute;\n    inset-block-end: 0;\n    inset-inline: 0;\n    z-index: calc(var(--z-sticky) + 2);\n    height: var(--sidebar-bottom-nav-height, 3.75rem);\n  }\n\n  :host([data-bottom-nav][data-mobile-open]) .bottom-bar {\n    z-index: calc(var(--z-sticky) + 1);\n    pointer-events: none;\n    opacity: 0;\n    transform: translateY(100%);\n  }\n\n  .bottom-tab {\n    all: unset;\n    position: relative;\n    box-sizing: border-box;\n    display: flex;\n    flex: 1 1 0;\n    flex-direction: column;\n    gap: var(--size-0-5);\n    align-items: center;\n    justify-content: center;\n    min-width: 0;\n    padding: var(--size-1) var(--size-1-5);\n    color: var(--sidebar-item-color, var(--color-contrast-700));\n    text-decoration: none;\n    cursor: pointer;\n    border-radius: var(--rounded-md);\n    transition:\n      background var(--transition-fast),\n      color var(--transition-fast);\n  }\n\n  .bottom-tab:hover,\n  .bottom-tab:focus-visible {\n    color: var(--sidebar-item-hover-color, var(--color-contrast-900));\n    outline: var(--focus-ring);\n    outline-offset: 1px;\n    background: var(--sidebar-item-hover-bg, var(--color-contrast-100));\n  }\n\n  .bottom-tab:disabled {\n    color: var(--sidebar-item-disabled-color, var(--color-contrast-400));\n    cursor: not-allowed;\n    opacity: 0.7;\n  }\n\n  .bottom-tab-active,\n  .bottom-tab[data-active='true'] {\n    color: var(--sidebar-item-active-color, var(--color-primary));\n    background: var(\n      --sidebar-item-active-bg,\n      var(--color-primary-100, color-mix(in oklch, var(--color-primary) 12%, transparent))\n    );\n  }\n\n  .bottom-tab-active::before,\n  .bottom-tab[data-active='true']::before {\n    display: none;\n  }\n\n  .bottom-tab-icon {\n    display: inline-flex;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    width: var(--size-5);\n    height: var(--size-5);\n  }\n\n  .bottom-tab-label {\n    min-width: 0;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    font-size: var(--text-xs);\n    white-space: nowrap;\n  }\n\n  .sidebar-header {\n    display: flex;\n    gap: var(--size-2);\n    align-items: center;\n    justify-content: space-between;\n    min-height: var(--size-6);\n    padding: var(--size-4);\n    border-bottom: var(--border) solid var(--color-contrast-200);\n  }\n\n  .sidebar-header .sidebar-header-content {\n    display: block;\n    flex: 1 1 0%;\n    min-width: 0;\n    overflow: hidden;\n  }\n\n  :host([data-collapsed]) .sidebar-header {\n    flex-direction: column;\n    gap: var(--size-2);\n    align-items: center;\n    justify-content: flex-start;\n    min-height: unset;\n    padding-block: var(--size-2);\n    padding-inline: var(--size-2);\n  }\n\n  :host([data-collapsed]) .sidebar-header .sidebar-header-content {\n    display: none;\n  }\n\n  .sidebar-logo {\n    display: flex;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    min-width: var(--size-8);\n    min-height: var(--size-8);\n    margin-inline-end: var(--size-2);\n  }\n\n  .sidebar-logo:empty {\n    display: none;\n  }\n\n  :host([data-collapsed]) .sidebar-logo {\n    margin-block: var(--size-1);\n    margin-inline-end: 0;\n  }\n\n  .sidebar-content {\n    display: grid;\n    flex: 1;\n    grid-template-columns: minmax(0, 1fr);\n    gap: var(--size-2);\n    align-content: start;\n    min-width: 0;\n    padding: var(--size-4);\n    overflow: clip auto;\n    scrollbar-width: thin;\n  }\n\n  .sidebar-footer {\n    flex-shrink: 0;\n    padding: var(--size-4);\n    border-top: var(--border) solid var(--color-contrast-200);\n  }\n\n  .toggle-btn {\n    all: unset;\n    box-sizing: border-box;\n    display: inline-flex;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    width: var(--size-8);\n    height: var(--size-8);\n    color: var(--color-contrast-500);\n    cursor: pointer;\n    border-radius: var(--rounded-sm);\n    transition:\n      color var(--transition-fast),\n      background var(--transition-fast);\n  }\n\n  .toggle-btn:hover {\n    color: var(--color-contrast-800);\n    background: var(--color-contrast-200);\n  }\n\n  .toggle-btn:focus-visible {\n    outline: var(--focus-ring);\n  }\n\n  .toggle-icon {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    transition: var(--_motion-transition, transform var(--_sidebar-transition));\n  }\n\n  :host([data-collapsed]) .toggle-icon {\n    transform: rotate(180deg);\n  }\n\n  :host([data-bottom-nav]) .toggle-btn {\n    display: none;\n  }\n\n  :host(:not([dir='rtl'])[data-collapsed]) .toggle-icon,\n  :host(:dir(ltr)[data-collapsed]) .toggle-icon {\n    transform: rotate(180deg);\n  }\n\n  :host(:dir(rtl)) .toggle-icon {\n    transform: rotate(180deg);\n  }\n\n  :host(:dir(rtl)[data-collapsed]) .toggle-icon {\n    transform: rotate(0deg);\n  }\n}\n\n@layer refine.variants {\n  /* ── floating ── */\n  :host([variant='floating']) {\n    --_panel-radius: var(--rounded-lg);\n    height: calc(100% - var(--size-6));\n    margin: var(--size-3);\n  }\n\n  :host([variant='floating']) > nav {\n    border: var(--border) solid var(--_panel-border-color);\n    border-radius: var(--_panel-radius);\n  }\n\n  :host([variant='floating'][data-bottom-nav]) {\n    inset-block-end: var(--size-2);\n    inset-inline: var(--size-2);\n    width: auto;\n    max-width: none;\n  }\n\n  :host([variant='floating'][data-preview-mode][data-bottom-nav]) {\n    inset: calc(var(--size-1) * -1);\n  }\n\n  :host([variant='floating'][data-bottom-nav]) .bottom-bar {\n    border: var(--border) solid var(--_panel-border-color);\n    border-radius: var(--_panel-radius);\n    box-shadow: var(--_panel-shadow);\n  }\n\n  :host([variant='floating'][data-bottom-nav]) > nav {\n    inset-block-start: var(--size-2);\n    inset-inline-start: var(--size-2);\n  }\n\n  :host([variant='floating'][data-preview-mode][data-bottom-nav]) .bottom-bar {\n    inset-block-end: var(--size-2);\n    inset-inline: var(--size-2);\n    width: auto;\n  }\n\n  :host([variant='floating'][data-preview-mode][data-bottom-nav]) > nav {\n    inset-block-start: var(--size-1);\n    inset-inline-start: var(--size-1);\n  }\n\n  /* ── inset ── */\n  :host([variant='inset']) {\n    --_panel-bg: var(--color-contrast-50);\n    --_panel-shadow: none;\n    --_panel-border-color: transparent;\n  }\n}\n","/*\n * Simplified and unified sidebar-group CSS:\n * - Combined cursor and chevron logic for [collapsible] and :not([collapsible])\n * - Grouped hover/focus/active state rules\n * - Clarified collapsed mode label/chevron hiding\n */\n\n@layer refine.base {\n  :host {\n    display: block;\n    width: 100%;\n  }\n\n  :host([sidebar-bottom-nav]) {\n    display: none;\n  }\n\n  .group {\n    display: block;\n  }\n\n  .group-header {\n    all: unset;\n    position: relative;\n    box-sizing: border-box;\n    display: flex;\n    align-items: center;\n    justify-content: flex-start;\n    width: 100%;\n    min-height: var(--size-6);\n    padding: var(--size-1) var(--size-2);\n    margin-bottom: var(--size-2);\n    color: inherit;\n    user-select: none;\n    outline: none;\n    border-radius: var(--rounded-lg);\n    transition: background var(--transition-fast);\n  }\n\n  .group-header::-webkit-details-marker {\n    display: none;\n  }\n\n  /* Collapsible group: pointer, hover/focus, show chevron */\n  :host([collapsible]) .group-header {\n    cursor: pointer;\n  }\n\n  :host([collapsible]) .group-header:hover {\n    background: var(--color-contrast-100);\n  }\n\n  :host([collapsible]) .group-header:focus-visible {\n    outline: var(--focus-ring);\n  }\n\n  /* Non-collapsible group: default cursor, hide chevron */\n  :host(:not([collapsible])) .group-header {\n    cursor: default;\n  }\n\n  :host(:not([collapsible])) .chevron {\n    display: none;\n  }\n\n  .group-label {\n    flex-grow: 1;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    font-size: var(--text-xs);\n    font-weight: var(--font-semibold);\n    color: var(--color-contrast-500);\n    text-transform: uppercase;\n    letter-spacing: 0.06em;\n    white-space: nowrap;\n    transition: opacity var(--transition-fast);\n  }\n\n  .group-icon {\n    display: flex;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    color: var(--color-contrast-400);\n  }\n\n  .group-icon:empty {\n    display: none;\n  }\n\n  .chevron {\n    display: flex;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    color: var(--color-contrast-400);\n    transition: var(--_motion-transition, transform var(--transition-normal));\n  }\n\n  /* Chevron rotation for open group */\n  :host([collapsible]) .group[open] .chevron {\n    transform: rotate(90deg);\n  }\n\n  .group-items {\n    display: grid;\n    grid-template-columns: minmax(0, 1fr);\n    gap: var(--size-2);\n    min-width: 0;\n  }\n\n  /* Collapsed-sidebar: hide label text and chevron, center icon */\n  :host([sidebar-collapsed]) .group-label,\n  :host([sidebar-collapsed]) .chevron {\n    display: none;\n  }\n\n  :host([sidebar-collapsed]) .group-header {\n    display: none;\n    height: 0;\n    min-height: 0;\n    padding: 0;\n    margin: 0;\n  }\n\n  :host([sidebar-collapsed]) .group-badge {\n    position: static;\n    display: flex;\n    visibility: visible;\n    width: auto;\n    height: auto;\n    pointer-events: auto;\n    opacity: 1;\n  }\n\n  /* Collapsible group closed: hide items */\n  :host([collapsible]:not([open])) .group-items {\n    display: none;\n  }\n}\n","/*\n * Simplified and unified sidebar-item CSS:\n * - Unified badge overlay logic\n * - Grouped collapsed mode rules\n * - Combined state rules (active, disabled, hover, focus)\n * - Clarified selectors for maintainability\n */\n\n@layer refine.base {\n  :host {\n    display: block;\n    min-width: 0;\n    max-width: 100%;\n  }\n\n  .item {\n    position: relative;\n    box-sizing: border-box;\n    display: flex;\n    gap: var(--size-2);\n    align-items: center;\n    min-width: 0;\n    min-height: var(--_touch-target);\n    padding: var(--size-1-5) var(--size-2);\n    font-size: var(--sidebar-item-font-size, var(--text-sm));\n    font-weight: var(--font-medium);\n    color: var(--sidebar-item-color, var(--color-contrast-700));\n    text-decoration: none;\n    cursor: pointer;\n    user-select: none;\n    outline: none;\n    border-radius: var(--rounded-lg);\n    transition:\n      background var(--transition-fast),\n      color var(--transition-fast);\n  }\n\n  a.item {\n    text-decoration: none;\n  }\n\n  .item:hover,\n  .item:focus-visible {\n    color: var(--sidebar-item-hover-color, var(--color-contrast-900));\n    outline: var(--focus-ring);\n    outline-offset: 1px;\n    background: var(--sidebar-item-hover-bg, var(--color-contrast-100));\n  }\n\n  :host([active]) .item {\n    font-weight: var(--font-semibold);\n    color: var(--sidebar-item-active-color, var(--color-primary));\n    background: var(\n      --sidebar-item-active-bg,\n      var(--color-primary-100, color-mix(in oklch, var(--color-primary) 12%, transparent))\n    );\n  }\n\n  :host([active]) .item::before {\n    display: none;\n  }\n\n  :host([disabled]) .item,\n  :host([disabled]) .item:hover,\n  :host([disabled]) .item:focus-visible {\n    color: var(--sidebar-item-disabled-color, var(--color-contrast-300));\n    pointer-events: none;\n    cursor: not-allowed;\n    outline: none;\n    background: none;\n    opacity: 1;\n  }\n\n  :host([disabled]) .item-icon {\n    color: var(--sidebar-item-disabled-color, var(--color-contrast-300));\n  }\n\n  .item-icon {\n    display: flex;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    width: var(--size-5);\n    height: var(--size-5);\n    margin: 0 auto;\n  }\n\n  .item-label {\n    flex: 1;\n    min-width: 0;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n    transition: opacity var(--transition-fast);\n  }\n\n  .item-end {\n    display: flex;\n    flex-shrink: 0;\n    gap: var(--size-1);\n    align-items: center;\n    transition: opacity var(--transition-fast);\n  }\n\n  /* Collapsed sidebar: hide label text, adjust layout, overlay badge */\n  :host([sidebar-collapsed]) .item,\n  :host([sidebar-collapsed]) .item-icon {\n    position: relative;\n  }\n\n  :host([sidebar-collapsed]) .item-label {\n    width: 0;\n    overflow: hidden;\n    pointer-events: none;\n    opacity: 0;\n  }\n\n  :host([sidebar-collapsed]) .item {\n    gap: 0;\n    align-items: center;\n    justify-content: center;\n    width: 100%;\n    height: 100%;\n    min-height: 100%;\n    padding: 0;\n  }\n\n  :host([sidebar-collapsed]) .item::before {\n    inset-block: var(--size-2);\n  }\n\n  :host([sidebar-collapsed]) .item-icon {\n    width: var(--size-7);\n    height: var(--size-7);\n    padding: var(--size-1-5);\n    font-size: 1.5em;\n  }\n\n  :host([sidebar-collapsed][active]) .item {\n    background: none;\n  }\n\n  :host([sidebar-collapsed]) .item:hover {\n    background: none;\n  }\n\n  :host([sidebar-collapsed][active]) .item-icon {\n    background: var(\n      --sidebar-item-active-bg,\n      var(--color-primary-100, color-mix(in oklch, var(--color-primary) 12%, transparent))\n    );\n    border-radius: var(--rounded-full);\n  }\n\n  :host([sidebar-collapsed]) .item-icon:hover {\n    background: var(--color-contrast-100);\n    border-radius: var(--rounded-full);\n  }\n\n  /* Unified badge overlay logic for collapsed mode */\n  :host([sidebar-collapsed]) .item-end,\n  :host([sidebar-collapsed]) .item-icon .group-badge,\n  :host([sidebar-collapsed]) .item-icon ::slotted([slot='end']) {\n    position: absolute;\n    right: 0;\n    bottom: calc(var(--size-2) * -1);\n    z-index: 2;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    min-width: 1.25em;\n    min-height: 1.25em;\n    pointer-events: auto;\n    opacity: 1;\n    transform: translate(40%, -40%);\n  }\n\n  :host([dir='rtl'][sidebar-collapsed]) .item-end,\n  :host([dir='rtl'][sidebar-collapsed]) .item-icon .group-badge,\n  :host([dir='rtl'][sidebar-collapsed]) .item-icon ::slotted([slot='end']),\n  :host(:dir(rtl)[sidebar-collapsed]) .item-end,\n  :host(:dir(rtl)[sidebar-collapsed]) .item-icon .group-badge,\n  :host(:dir(rtl)[sidebar-collapsed]) .item-icon ::slotted([slot='end']) {\n    right: auto;\n    left: 0;\n    transform: translate(-40%, -40%);\n  }\n\n  :host([sidebar-collapsed]) .item-end .group-badge,\n  :host([sidebar-collapsed]) .item-end ::slotted([slot='end']) {\n    position: absolute;\n    top: 50%;\n    right: calc(var(--size-0-5) * -1);\n    z-index: 1;\n    transform: translateY(-50%);\n  }\n\n  :host([dir='rtl'][sidebar-collapsed]) .item-end .group-badge,\n  :host([dir='rtl'][sidebar-collapsed]) .item-end ::slotted([slot='end']),\n  :host(:dir(rtl)[sidebar-collapsed]) .item-end .group-badge,\n  :host(:dir(rtl)[sidebar-collapsed]) .item-end ::slotted([slot='end']) {\n    right: auto;\n    left: var(--size-2);\n  }\n\n  /* The bottom tab bar (`.bottom-bar` in sidebar.ts) renders its own promoted-item\n     buttons from the same data — the original <ore-sidebar-item> stays inside the\n     (visually off-screen while closed) <nav>, so it must be fully hidden here to\n     avoid a focusable/AT-visible duplicate of the bottom-bar entry. */\n  :host([sidebar-bottom-nav]) {\n    display: none;\n  }\n}\n","import {\n  bind,\n  createContext,\n  define,\n  getHost,\n  html,\n  inject,\n  onCleanup,\n  onMounted,\n  prop,\n  provide,\n  useEmit,\n  useSlots,\n} from '@vielzeug/ore';\nimport { computed, type Readable, signal, watch } from '@vielzeug/ripple';\nimport { createElementSize, createMediaQuery, SentinelUnavailableError } from '@vielzeug/sentinel';\n\nimport '../../content/icon/icon';\nimport { coarsePointerMixin, reducedMotionMixin } from '../../styles';\nimport { computeSafeRel } from '../../utils';\nimport sidebarStyles from './sidebar.css?inline';\nimport groupStyles from './sidebar-group.css?inline';\nimport itemStyles from './sidebar-item.css?inline';\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\ntype SidebarVariant = 'floating' | 'inset';\ntype SidebarCollapseSource = 'api' | 'responsive' | 'toggle';\ntype SidebarMobileSource = 'api' | 'responsive' | 'toggle';\ntype SidebarMode = 'bottom-nav' | 'collapsed' | 'default';\n\ntype BottomNavItem = {\n  active: boolean;\n  disabled: boolean;\n  href?: string;\n  iconName?: string;\n  label: string;\n  source: HTMLElement;\n};\n\nconst parseMaxWidthPx = (query: string | undefined): number | undefined => {\n  const value = String(query ?? '').trim();\n\n  if (!value) return undefined;\n\n  const match = /max-width\\s*:\\s*([0-9]+(?:\\.[0-9]+)?)px/i.exec(value);\n\n  if (!match) return undefined;\n\n  const parsed = Number.parseFloat(match[1]);\n\n  return Number.isFinite(parsed) ? parsed : undefined;\n};\n\nconst resolveContainerElement = (el: HTMLElement): HTMLElement | null => {\n  let container = el.parentElement;\n\n  while (container?.tagName.toLowerCase() === 'ore-grid-item') {\n    container = container.parentElement;\n  }\n\n  return container;\n};\n\nconst readContainerWidth = (el: HTMLElement): number => {\n  const parentWidth = resolveContainerElement(el)?.clientWidth ?? 0;\n\n  if (parentWidth > 0) return parentWidth;\n\n  return el.offsetWidth;\n};\n\n/** Context provided by `ore-sidebar` to its `ore-sidebar-group` and `ore-sidebar-item` children. */\nexport type SidebarContext = {\n  collapsed: Readable<boolean>;\n  mobileOpen: Readable<boolean>;\n  mode: Readable<SidebarMode>;\n  variant: Readable<SidebarVariant | undefined>;\n};\n\n/** Injection key for the sidebar context. */\nexport const SIDEBAR_CTX = createContext<SidebarContext>('SidebarContext');\n\n// ─── ore-sidebar styles ──────────────────────────────────────────────────────\n\n/** ore-sidebar element interface */\nexport type SidebarElement = HTMLElement &\n  OreSidebarProps & {\n    /** Close the drawer in bottom-nav mode. */\n    closeMobile(): void;\n    /** Open the drawer in bottom-nav mode. */\n    openMobile(): void;\n    /** Set collapsed state imperatively. */\n    setCollapsed(next: boolean): void;\n    /** Toggle between collapsed and expanded. */\n    toggle(): void;\n    /** Toggle the drawer in bottom-nav mode. */\n    toggleMobile(): void;\n  };\n\n/** Sidebar component properties */\n\nexport type OreSidebarEvents = {\n  'collapsed-change': { collapsed: boolean; source: SidebarCollapseSource };\n  'mobile-open-change': { open: boolean; source: SidebarMobileSource };\n};\n\nexport type OreSidebarGroupEvents = {\n  'open-change': { open: boolean };\n};\n\nexport type OreSidebarProps = {\n  /** CSS media query that switches the sidebar to bottom navigation mode */\n  'bottom-nav-at'?: string;\n  /** Controlled collapsed state */\n  collapsed?: boolean;\n  /** Whether the sidebar supports collapsing */\n  collapsible?: boolean;\n  /** Evaluate responsive and bottom-nav breakpoints against container width only. */\n  'container-breakpoints'?: boolean;\n  /** Initial collapsed state in uncontrolled mode */\n  'default-collapsed'?: boolean;\n  /**\n   * Accessible label for the navigation landmark.\n   * Use to distinguish multiple navigation regions on a page.\n   * @default 'Sidebar navigation'\n   */\n  label?: string;\n  /**\n   * CSS media query that, when it matches, automatically collapses the sidebar.\n   * Unset by default — no automatic collapse.\n   * @example 'responsive=\"(max-width: 768px)\"'\n   */\n  responsive?: string;\n  /** Visual style variant */\n  variant?: SidebarVariant;\n};\n\n/**\n * `ore-sidebar` — A collapsible navigation sidebar with group and item support.\n *\n * @element ore-sidebar\n * @element ore-sidebar-group - Labelled group of navigation items\n * @element ore-sidebar-item - Individual navigation link or button\n *\n * @attr {boolean} collapsed - Controlled collapsed state\n * @attr {boolean} default-collapsed - Initial collapsed state for uncontrolled sidebars\n * @attr {boolean} collapsible - Show the collapse toggle button\n * @attr {string} variant - Visual variant: 'floating' | 'inset'\n * @attr {string} label - Accessible aria-label for the nav landmark\n *\n * @fires collapsed-change - Fired when collapsed state changes. detail: { collapsed: boolean; source: string }\n * @fires mobile-open-change - Fired when mobile overlay open state changes. detail: { open: boolean; source: string }\n *\n * @slot header - Branding or logo content above the nav\n * @slot - Navigation content (ore-sidebar-group / ore-sidebar-item)\n * @slot footer - Footer content below the nav (user info, settings, etc.)\n *\n * @cssprop --sidebar-width - Expanded sidebar width (default: 16rem)\n * @cssprop --sidebar-collapsed-width - Collapsed sidebar width (default: 3.5rem)\n * @cssprop --sidebar-bg - Sidebar background color\n * @cssprop --sidebar-border-color - Border color\n *\n * @part mobile-backdrop - Backdrop shown for mobile overlays.\n * @part nav - Navigation container.\n * @part header - Header container.\n * @part toggle-btn - Shadow part for the `toggle-btn` element.\n * @part content - Content container.\n * @part footer - Footer container.\n * @part bottom-bar - Bottom bar container.\n * @part group - Group container.\n * @part group-header - Group header container.\n * @part group-icon - Group icon container.\n * @part group-label - Group label container.\n * @part group-items - Group items container.\n * @part item-icon - Leading item icon container.\n * @part item-label - Item label container.\n * @part item-end - Trailing item content container.\n * @part item - Item root element.\n * @example\n * ```html\n * <ore-sidebar collapsible label=\"App navigation\">\n *   <span slot=\"header\">My App</span>\n *   <ore-sidebar-group label=\"Main\">\n *     <ore-sidebar-item href=\"/dashboard\" active>Dashboard</ore-sidebar-item>\n *     <ore-sidebar-item href=\"/settings\">Settings</ore-sidebar-item>\n *   </ore-sidebar-group>\n * </ore-sidebar>\n *\n * <!-- Auto-collapse on mobile -->\n * <ore-sidebar collapsible responsive=\"(max-width: 768px)\">...</ore-sidebar>\n * ```\n */\nexport const SIDEBAR_TAG = 'ore-sidebar' as const;\ndefine<OreSidebarProps>(SIDEBAR_TAG, {\n  props: {\n    'bottom-nav-at': prop.string(),\n    collapsed: prop.bool(false),\n    collapsible: prop.bool(false),\n    'container-breakpoints': prop.bool(false),\n    'default-collapsed': prop.bool(false),\n    label: prop.string('Sidebar navigation'),\n    responsive: prop.string(),\n    variant: prop.string<SidebarVariant>(),\n  },\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreSidebarEvents>();\n    const slots = useSlots();\n\n    const hasHeader = () => slots.has('header').value;\n    const hasFooter = () => slots.has('footer').value;\n    const hasLogo = () => slots.has('logo').value;\n\n    const isControlled = signal(el.hasAttribute('collapsed'));\n    const collapsedState = signal(isControlled.value ? el.hasAttribute('collapsed') : props['default-collapsed'].value);\n    const isBottomNav = signal(false);\n    const isMobileOpen = signal(false);\n    const bottomNavItems = signal<BottomNavItem[]>([]);\n    const responsiveMediaMatches = signal(false);\n    const responsiveSizeMatches = signal(false);\n    const responsiveMaxWidthPx = signal<number | undefined>(parseMaxWidthPx(props.responsive.value));\n    const hasResponsiveQuery = signal(Boolean(String(props.responsive.value ?? '').trim()));\n    const bottomNavMediaMatches = signal(false);\n    const bottomNavSizeMatches = signal(false);\n    const bottomNavMaxWidthPx = signal<number | undefined>(parseMaxWidthPx(props['bottom-nav-at'].value));\n    const isPreviewMode = signal(false);\n\n    const isCollapsed = () => collapsedState.value;\n    const mode = computed<SidebarMode>(() => {\n      if (isBottomNav.value) return 'bottom-nav';\n\n      return collapsedState.value ? 'collapsed' : 'default';\n    });\n\n    const applyResponsiveState = () => {\n      const useContainerBreakpoints = props['container-breakpoints'].value;\n      const responsiveMatched = useContainerBreakpoints\n        ? responsiveSizeMatches.value\n        : responsiveMediaMatches.value || responsiveSizeMatches.value;\n      const bottomMatched = useContainerBreakpoints\n        ? bottomNavSizeMatches.value\n        : bottomNavMediaMatches.value || bottomNavSizeMatches.value;\n\n      // If the mobile drawer is currently open, stay in bottom-nav mode\n      // regardless of the responsive match. This prevents the drawer from\n      // disappearing mid-animation or if forced open via the API on desktop.\n      if (!isMobileOpen.value) {\n        isBottomNav.value = bottomMatched;\n      }\n\n      if (!bottomMatched && !isMobileOpen.value) {\n        setMobileOpen(false, 'responsive');\n      }\n\n      if (hasResponsiveQuery.value) {\n        setCollapsed(responsiveMatched, 'responsive');\n      }\n    };\n\n    const readBottomNavItems = () => {\n      const next = slots\n        .elements()\n        .value.filter(\n          (el): el is HTMLElement => el instanceof HTMLElement && el.tagName.toLowerCase() === 'ore-sidebar-item',\n        )\n        .map((el, index) => {\n          const iconSlotEl =\n            (el.querySelector(':scope > [slot=\"icon\"]') as HTMLElement | null) ??\n            (el.querySelector('[slot=\"icon\"]') as HTMLElement | null);\n          const directIconName =\n            iconSlotEl?.tagName.toLowerCase() === 'ore-icon' ? iconSlotEl.getAttribute('name') : null;\n          const nestedIconName = iconSlotEl?.querySelector('ore-icon')?.getAttribute('name') ?? null;\n          const rawLabel = (el.textContent ?? '').trim();\n\n          return {\n            active: el.hasAttribute('active'),\n            disabled: el.hasAttribute('disabled'),\n            href: el.getAttribute('href') ?? undefined,\n            iconName: directIconName ?? nestedIconName ?? undefined,\n            label: rawLabel || `Item ${index + 1}`,\n            source: el,\n          } satisfies BottomNavItem;\n        });\n\n      bottomNavItems.value = next;\n    };\n\n    provide(SIDEBAR_CTX, {\n      collapsed: computed(() => !isBottomNav.value && collapsedState.value) as Readable<boolean>,\n      mobileOpen: computed(() => isBottomNav.value && isMobileOpen.value) as Readable<boolean>,\n      mode: mode as Readable<SidebarMode>,\n      variant: props.variant,\n    });\n\n    const setCollapsed = (next: boolean, source: SidebarCollapseSource) => {\n      if (isCollapsed() === next) return;\n\n      if (!isControlled.value) {\n        collapsedState.value = next;\n      }\n\n      emit('collapsed-change', { collapsed: next, source });\n    };\n\n    const setMobileOpen = (next: boolean, source: SidebarMobileSource) => {\n      const open = Boolean(next);\n\n      if (open && !isBottomNav.value) {\n        isBottomNav.value = true;\n      }\n\n      if (!isBottomNav.value && !open) {\n        if (isMobileOpen.value) {\n          isMobileOpen.value = false;\n        }\n\n        return;\n      }\n\n      if (isMobileOpen.value === open) return;\n\n      isMobileOpen.value = open;\n\n      // If closing, re-evaluate responsive state to potentially exit forced bottom-nav mode\n      if (!open) {\n        applyResponsiveState();\n      }\n\n      emit('mobile-open-change', { open, source });\n    };\n\n    const doToggle = () => {\n      setCollapsed(!isCollapsed(), 'toggle');\n    };\n\n    const sidebarEl = el as SidebarElement;\n\n    sidebarEl.setCollapsed = (next) => setCollapsed(Boolean(next), 'api');\n    sidebarEl.toggle = doToggle;\n    sidebarEl.openMobile = () => setMobileOpen(true, 'api');\n    sidebarEl.closeMobile = () => setMobileOpen(false, 'api');\n    sidebarEl.toggleMobile = () => setMobileOpen(!isMobileOpen.value, 'toggle');\n\n    bind({\n      attr: {\n        'data-bottom-nav': () => (isBottomNav.value ? true : undefined),\n        'data-collapsed': () => (isCollapsed() && !isBottomNav.value ? true : undefined),\n        'data-mobile-open': () => (isBottomNav.value && isMobileOpen.value ? true : undefined),\n        'data-preview-mode': () => (isPreviewMode.value ? true : undefined),\n      },\n    });\n\n    onMounted(() => {\n      // Suppress transitions during initial layout so the sidebar doesn't\n      // animate from a collapsed/0 state before the first ResizeObserver fires.\n      el.setAttribute('data-no-transition', '');\n\n      let transitionUnlocked = false;\n      const unlockTransition = () => {\n        if (transitionUnlocked) return;\n\n        transitionUnlocked = true;\n        el.removeAttribute('data-no-transition');\n      };\n\n      // Fallback: unlock after two frames in case ResizeObserver doesn't fire.\n      requestAnimationFrame(() => requestAnimationFrame(unlockTransition));\n\n      let mediaCleanup: (() => void) | undefined;\n      let bottomNavCleanup: (() => void) | undefined;\n      const itemObservers = new Map<HTMLElement, MutationObserver>();\n      const observer = new MutationObserver(() => {\n        if (!el.hasAttribute('collapsed') && !isControlled.value) return;\n\n        isControlled.value = true;\n        collapsedState.value = el.hasAttribute('collapsed');\n      });\n\n      observer.observe(el, {\n        attributeFilter: ['collapsed'],\n        attributes: true,\n      });\n\n      watch(\n        props.responsive,\n        (query) => {\n          mediaCleanup?.();\n          mediaCleanup = undefined;\n\n          const mediaQuery = String(query ?? '').trim();\n\n          hasResponsiveQuery.value = Boolean(mediaQuery);\n          responsiveMaxWidthPx.value = parseMaxWidthPx(mediaQuery);\n          responsiveMediaMatches.value = false;\n\n          const width = readContainerWidth(el);\n\n          responsiveSizeMatches.value =\n            width > 0 && responsiveMaxWidthPx.value != null ? width <= responsiveMaxWidthPx.value : false;\n          applyResponsiveState();\n\n          // For parseable max-width queries, keep behavior container-driven.\n          // This avoids preview viewport controls being overridden by window width.\n          if (props['container-breakpoints'].value && responsiveMaxWidthPx.value != null) {\n            return;\n          }\n\n          if (!mediaQuery) {\n            return;\n          }\n\n          try {\n            const mediaHandle = createMediaQuery(mediaQuery);\n            const syncMedia = (state: typeof mediaHandle.value) => {\n              if (state) {\n                responsiveMediaMatches.value = state.matches;\n                applyResponsiveState();\n              }\n            };\n\n            syncMedia(mediaHandle.value);\n\n            const mediaCleanupFn = watch(mediaHandle, syncMedia);\n            mediaCleanup = () => {\n              mediaCleanupFn.dispose();\n              mediaHandle.dispose();\n            };\n          } catch (error) {\n            if (!(error instanceof SentinelUnavailableError)) throw error;\n          }\n        },\n        { immediate: true },\n      );\n\n      watch(\n        props['bottom-nav-at'],\n        (query) => {\n          bottomNavCleanup?.();\n          bottomNavCleanup = undefined;\n\n          const mediaQuery = String(query ?? '').trim();\n\n          bottomNavMaxWidthPx.value = parseMaxWidthPx(mediaQuery);\n          bottomNavMediaMatches.value = false;\n\n          const width = readContainerWidth(el);\n\n          bottomNavSizeMatches.value =\n            width > 0 && bottomNavMaxWidthPx.value != null ? width <= bottomNavMaxWidthPx.value : false;\n          applyResponsiveState();\n\n          // For parseable max-width queries, keep behavior container-driven.\n          // This avoids preview viewport controls being overridden by window width.\n          if (props['container-breakpoints'].value && bottomNavMaxWidthPx.value != null) {\n            return;\n          }\n\n          if (!mediaQuery) {\n            return;\n          }\n\n          try {\n            const mediaHandle = createMediaQuery(mediaQuery);\n            const syncMedia = (state: typeof mediaHandle.value) => {\n              if (state) {\n                bottomNavMediaMatches.value = state.matches;\n                applyResponsiveState();\n              }\n            };\n\n            syncMedia(mediaHandle.value);\n\n            const mediaCleanupFn = watch(mediaHandle, syncMedia);\n            bottomNavCleanup = () => {\n              mediaCleanupFn.dispose();\n              mediaHandle.dispose();\n            };\n          } catch (error) {\n            if (!(error instanceof SentinelUnavailableError)) throw error;\n          }\n        },\n        { immediate: true },\n      );\n\n      const stopResizeEffect =\n        typeof ResizeObserver === 'function'\n          ? (() => {\n              const hostSize = createElementSize(el);\n              onCleanup(() => hostSize.dispose());\n\n              const wrapperEl = el.parentElement;\n              const containerEl = resolveContainerElement(el);\n              const wrapperSize = wrapperEl ? createElementSize(wrapperEl) : undefined;\n              const parentSize = containerEl && containerEl !== wrapperEl ? createElementSize(containerEl) : undefined;\n\n              if (wrapperSize) {\n                onCleanup(() => wrapperSize.dispose());\n              }\n              if (parentSize) {\n                onCleanup(() => parentSize.dispose());\n              }\n\n              let rafId: number | undefined;\n\n              const onResize = () => {\n                if (rafId !== undefined) cancelAnimationFrame(rafId);\n\n                rafId = requestAnimationFrame(() => {\n                  const resolvedContainer = resolveContainerElement(el);\n                  const width = readContainerWidth(el);\n                  const responsiveWasMatched = responsiveSizeMatches.value;\n                  const bottomNavWasMatched = bottomNavSizeMatches.value;\n                  const parentWidth = resolvedContainer?.clientWidth ?? 0;\n\n                  isPreviewMode.value = parentWidth > 0 && parentWidth < window.innerWidth;\n\n                  responsiveSizeMatches.value =\n                    width > 0 && responsiveMaxWidthPx.value != null ? width <= responsiveMaxWidthPx.value : false;\n                  bottomNavSizeMatches.value =\n                    width > 0 && bottomNavMaxWidthPx.value != null ? width <= bottomNavMaxWidthPx.value : false;\n\n                  if (\n                    responsiveWasMatched !== responsiveSizeMatches.value ||\n                    bottomNavWasMatched !== bottomNavSizeMatches.value\n                  ) {\n                    applyResponsiveState();\n                  }\n\n                  unlockTransition();\n                });\n              };\n\n              return watch(\n                computed(() => [\n                  hostSize.value?.width,\n                  hostSize.value?.height,\n                  wrapperSize?.value?.width,\n                  wrapperSize?.value?.height,\n                  parentSize?.value?.width,\n                  parentSize?.value?.height,\n                ]),\n                onResize,\n              );\n            })()\n          : undefined;\n\n      const bindItemObservers = (items: HTMLElement[]) => {\n        const set = new Set(items);\n\n        for (const [item, cleanup] of itemObservers) {\n          if (set.has(item)) continue;\n\n          cleanup.disconnect();\n          itemObservers.delete(item);\n        }\n\n        for (const item of items) {\n          if (itemObservers.has(item)) continue;\n\n          const itemObserver = new MutationObserver(() => {\n            // Only update if in bottom-nav mode to minimize re-renders\n            if (isBottomNav.value) {\n              readBottomNavItems();\n            }\n          });\n\n          // Only watch attributes that affect bottom-nav rendering; skip childList/subtree/characterData\n          itemObserver.observe(item, {\n            attributeFilter: ['active', 'disabled', 'href'],\n            attributes: true,\n          });\n          itemObservers.set(item, itemObserver);\n        }\n      };\n\n      watch(\n        slots.elements(),\n        (elements) => {\n          const directItems = elements.filter(\n            (el): el is HTMLElement => el instanceof HTMLElement && el.tagName.toLowerCase() === 'ore-sidebar-item',\n          );\n\n          bindItemObservers(directItems);\n          readBottomNavItems();\n        },\n        { immediate: true },\n      );\n\n      return () => {\n        observer.disconnect();\n        mediaCleanup?.();\n        bottomNavCleanup?.();\n        stopResizeEffect?.dispose();\n\n        for (const itemObserver of itemObservers.values()) {\n          itemObserver.disconnect();\n        }\n\n        itemObservers.clear();\n      };\n    });\n\n    return html`\n      <button\n        class=\"mobile-backdrop\"\n        part=\"mobile-backdrop\"\n        type=\"button\"\n        aria-label=\"Close sidebar\"\n        ?hidden=${() => !isBottomNav.value || !isMobileOpen.value}\n        @click=${() => setMobileOpen(false, 'toggle')}></button>\n      <nav aria-label=\"${props.label}\" part=\"nav\">\n        <div class=\"sidebar-header\" part=\"header\" ?hidden=${() => !hasHeader() && !props.collapsible.value}>\n          <span class=\"sidebar-logo\" ?hidden=${() => !hasLogo()}>\n            <slot name=\"logo\"></slot>\n          </span>\n          <span class=\"sidebar-header-content\">\n            <slot name=\"header\"></slot>\n          </span>\n          <button\n            class=\"toggle-btn\"\n            part=\"toggle-btn\"\n            type=\"button\"\n            ?hidden=${() => !props.collapsible.value}\n            aria-label=\"${() => (isCollapsed() ? 'Expand sidebar' : 'Collapse sidebar')}\"\n            aria-expanded=\"${() => !isCollapsed()}\"\n            @click=\"${doToggle}\">\n            <span class=\"toggle-icon\" aria-hidden=\"true\">\n              <ore-icon name=\"chevron-left\" size=\"16\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n            </span>\n          </button>\n        </div>\n        <div class=\"sidebar-content\" part=\"content\">\n          <slot></slot>\n        </div>\n        <div class=\"sidebar-footer\" part=\"footer\" ?hidden=${() => !hasFooter()}>\n          <slot name=\"footer\"></slot>\n        </div>\n      </nav>\n\n      <div class=\"bottom-bar\" part=\"bottom-bar\" ?hidden=${() => !isBottomNav.value}>\n        ${() =>\n          bottomNavItems.value.map((item) => {\n            const className = `bottom-tab${item.active ? ' bottom-tab-active' : ''}`;\n\n            if (item.href && !item.disabled) {\n              return html`\n                <a\n                  class=\"${className}\"\n                  href=\"${item.href}\"\n                  aria-current=\"${item.active ? 'page' : null}\"\n                  data-active=\"${item.active ? 'true' : null}\">\n                  <span class=\"bottom-tab-icon\" aria-hidden=\"true\" ?hidden=${() => !item.iconName}>\n                    <ore-icon name=\"${item.iconName}\" size=\"18\" stroke-width=\"2\"></ore-icon>\n                  </span>\n                  <span class=\"bottom-tab-label\">${item.label}</span>\n                </a>\n              `;\n            }\n\n            return html`\n              <button\n                class=\"${className}\"\n                type=\"button\"\n                ?disabled=${item.disabled}\n                aria-current=\"${item.active ? 'page' : null}\"\n                data-active=\"${item.active ? 'true' : null}\"\n                @click=${() => item.source.click()}>\n                <span class=\"bottom-tab-icon\" aria-hidden=\"true\" ?hidden=${() => !item.iconName}>\n                  <ore-icon name=\"${item.iconName}\" size=\"18\" stroke-width=\"2\"></ore-icon>\n                </span>\n                <span class=\"bottom-tab-label\">${item.label}</span>\n              </button>\n            `;\n          })}\n      </div>\n    `;\n  },\n  styles: [coarsePointerMixin, reducedMotionMixin, sidebarStyles],\n});\n\n// ─── ore-sidebar-group styles ────────────────────────────────────────────────\n\n/** Sidebar group properties */\nexport type OreSidebarGroupProps = {\n  /** Whether this group can be collapsed */\n  collapsible?: boolean;\n  /** Initial open state in uncontrolled mode */\n  'default-open'?: boolean;\n  /** Accessible label for the group */\n  label?: string;\n  /** Controlled open state */\n  open?: boolean;\n};\n\n/**\n * `ore-sidebar-group` — A labelled section within `ore-sidebar`.\n *\n * @element ore-sidebar-group\n *\n * @attr {string} label - Group label text\n * @attr {boolean} collapsible - Whether this group can be toggled open/closed\n * @attr {boolean} open - Controlled expanded state\n * @attr {boolean} default-open - Initial expanded state in uncontrolled mode\n *\n * @fires open-change - Fired when the group open state changes (collapsible groups only). detail: { open: boolean }\n *\n * @slot - Navigation items (`ore-sidebar-item`)\n * @slot icon - Icon displayed before the label\n *\n * @example\n * ```html\n * <ore-sidebar-group label=\"Main\" collapsible open>\n *   <ore-sidebar-item href=\"/home\">Home</ore-sidebar-item>\n * </ore-sidebar-group>\n * ```\n */\nexport const SIDEBAR_GROUP_TAG = 'ore-sidebar-group' as const;\ndefine<OreSidebarGroupProps>(SIDEBAR_GROUP_TAG, {\n  props: {\n    collapsible: prop.bool(false),\n    'default-open': prop.bool(true),\n    label: prop.string(),\n    open: {\n      default: undefined as boolean | undefined,\n      parse: (value: string | null) => (value == null ? undefined : value === '' || value === 'true'),\n      reflect: false,\n    },\n  },\n  setup(props) {\n    const slots = useSlots();\n\n    const hasIcon = () => slots.has('icon').value;\n    const sidebarCtx = inject(SIDEBAR_CTX);\n\n    bind({\n      attr: {\n        'sidebar-bottom-nav': () =>\n          sidebarCtx?.mode.value === 'bottom-nav' && !sidebarCtx?.mobileOpen.value ? true : undefined,\n        'sidebar-collapsed': () => (sidebarCtx?.collapsed.value ? true : undefined),\n      },\n    });\n\n    const isControlled = () => props.open.value !== undefined;\n    const openState = signal(props['default-open'].value);\n    const isOpen = computed(() => {\n      if (!props.collapsible.value) return true;\n\n      if (isControlled()) return props.open.value ?? false;\n\n      return openState.value;\n    });\n\n    watch(props.open, (value) => {\n      if (value === undefined) return;\n\n      openState.value = value;\n    });\n\n    bind({\n      attr: {\n        open: () => (isOpen.value ? true : undefined),\n      },\n    });\n\n    return html`\n      <details class=\"group\" part=\"group\" ?open=${isOpen}>\n        <summary\n          class=\"group-header\"\n          part=\"group-header\"\n          aria-expanded=\"${() => (props.collapsible.value ? String(props.open.value) : null)}\"\n          @click=${(e: MouseEvent) => {\n            if (!props.collapsible.value) {\n              e.preventDefault();\n            }\n          }}>\n          <span class=\"group-icon\" part=\"group-icon\" ?hidden=${() => !hasIcon()} aria-hidden=\"true\">\n            <slot name=\"icon\"></slot>\n          </span>\n          <span class=\"group-label\" part=\"group-label\">${props.label}</span>\n          <span class=\"chevron\" ?hidden=${() => !props.collapsible.value} aria-hidden=\"true\">\n            <ore-icon name=\"chevron-right\" size=\"12\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n          </span>\n        </summary>\n        <div class=\"group-items\" part=\"group-items\" role=\"list\">\n          <slot></slot>\n        </div>\n      </details>\n    `;\n  },\n  styles: [reducedMotionMixin, groupStyles],\n});\n\n// ─── ore-sidebar-item styles ─────────────────────────────────────────────────\n\n/** Sidebar item properties */\nexport type OreSidebarItemProps = {\n  /** Whether this item represents the current page/section */\n  active?: boolean;\n  /** Whether this item is disabled */\n  disabled?: boolean;\n  /** Navigation href — renders an `<a>` when set, otherwise a `<button>` */\n  href?: string;\n  /**\n   * Relationship of the linked URL (`rel` attribute on the inner `<a>`).\n   * Only applies when `href` is set.\n   */\n  rel?: string;\n  /**\n   * Browsing context for the link (`target` attribute on the inner `<a>`).\n   * Only applies when `href` is set.\n   */\n  target?: string;\n};\n\n/**\n * `ore-sidebar-item` — An individual navigation item in a `ore-sidebar`.\n *\n * Renders as an `<a>` when `href` is provided, otherwise as a `<button>`.\n * Marks the active page via `aria-current=\"page\"` when the `active` attribute is set.\n *\n * @element ore-sidebar-item\n *\n * @attr {string} href - Link URL; renders an anchor when set\n * @attr {boolean} active - Marks the item as the current page\n * @attr {boolean} disabled - Disables the item\n * @attr {string} rel - Anchor `rel` attribute (links only)\n * @attr {string} target - Anchor `target` attribute (links only)\n *\n * @slot - Label text\n * @slot icon - Leading icon\n * @slot end - Trailing content (badge, shortcut, arrow, etc.)\n *\n * @cssprop --sidebar-item-color - Default text color\n * @cssprop --sidebar-item-hover-bg - Hover background\n * @cssprop --sidebar-item-hover-color - Hover text color\n * @cssprop --sidebar-item-active-bg - Active background\n * @cssprop --sidebar-item-active-color - Active text color\n * @cssprop --sidebar-item-indicator - Active indicator bar color\n *\n * @part item - The inner anchor or button element\n * @part item-icon - The icon wrapper\n * @part item-label - The label wrapper\n * @part item-end - The trailing content wrapper\n *\n * @example\n * ```html\n * <ore-sidebar-item href=\"/dashboard\" active>\n *   <span slot=\"icon\">🏠</span>\n *   Dashboard\n * </ore-sidebar-item>\n *\n * <ore-sidebar-item href=\"/users\">\n *   <span slot=\"icon\">👤</span>\n *   Users\n *   <ore-badge slot=\"end\" color=\"primary\">3</ore-badge>\n * </ore-sidebar-item>\n * ```\n */\nexport const SIDEBAR_ITEM_TAG = 'ore-sidebar-item' as const;\ndefine<OreSidebarItemProps>(SIDEBAR_ITEM_TAG, {\n  props: {\n    active: prop.bool(false),\n    disabled: prop.bool(false),\n    href: prop.string(),\n    rel: prop.string(),\n    target: prop.string(),\n  },\n  setup(props) {\n    const slots = useSlots();\n\n    const hasIcon = () => slots.has('icon').value;\n    const hasEnd = () => slots.has('end').value;\n    const sidebarCtx = inject(SIDEBAR_CTX);\n\n    bind({\n      attr: {\n        'sidebar-bottom-nav': () =>\n          sidebarCtx?.mode.value === 'bottom-nav' && !sidebarCtx?.mobileOpen.value ? true : undefined,\n        'sidebar-collapsed': () => (sidebarCtx?.collapsed.value ? true : undefined),\n      },\n    });\n\n    const isLink = () => !!props.href.value && !props.disabled.value;\n\n    // Prevent reverse tabnapping: auto-inject noopener + noreferrer for _blank links.\n    const effectiveRel = computed(() => computeSafeRel(props.rel.value, props.target.value));\n\n    const renderItemContent = () => html`\n      <span class=\"item-icon\" part=\"item-icon\" ?hidden=${() => !hasIcon()} aria-hidden=\"true\">\n        <slot name=\"icon\"></slot>\n      </span>\n      <span class=\"item-label\" part=\"item-label\"><slot></slot></span>\n      <span class=\"item-end\" part=\"item-end\" ?hidden=${() => !hasEnd()}>\n        <slot name=\"end\"></slot>\n      </span>\n    `;\n\n    return html`\n      ${() => {\n        if (isLink()) {\n          return html`\n            <a\n              class=\"item\"\n              part=\"item\"\n              href=\"${props.href}\"\n              rel=\"${effectiveRel}\"\n              target=\"${props.target}\"\n              aria-current=\"${() => (props.active.value ? 'page' : null)}\">\n              ${renderItemContent()}\n            </a>\n          `;\n        }\n\n        if (props.disabled.value) {\n          return html`\n            <div\n              class=\"item\"\n              part=\"item\"\n              aria-disabled=\"true\"\n              tabindex=\"-1\"\n              aria-current=\"${() => (props.active.value ? 'page' : null)}\">\n              ${renderItemContent()}\n            </div>\n          `;\n        }\n\n        return html`\n          <button\n            class=\"item\"\n            part=\"item\"\n            type=\"button\"\n            ?disabled=\"${props.disabled}\"\n            aria-current=\"${() => (props.active.value ? 'page' : null)}\">\n            ${renderItemContent()}\n          </button>\n        `;\n      }}\n    `;\n  },\n  styles: [coarsePointerMixin, itemStyles],\n});\n","export type { OreBoxProps } from './box/box';\nexport { BOX_TAG } from './box/box';\nexport type { OreGridProps } from './grid/grid';\nexport { GRID_TAG } from './grid/grid';\nexport type { OreGridItemProps } from './grid-item/grid-item';\nexport { GRID_ITEM_TAG } from './grid-item/grid-item';\nexport type {\n  NavbarContext,\n  NavbarElement,\n  OreNavbarEvents,\n  OreNavbarItemProps,\n  OreNavbarProps,\n} from './navbar/navbar';\nexport { NAVBAR_CTX, NAVBAR_ITEM_TAG, NAVBAR_TAG } from './navbar/navbar';\nexport type {\n  OreSidebarEvents,\n  OreSidebarGroupEvents,\n  OreSidebarGroupProps,\n  OreSidebarItemProps,\n  OreSidebarProps,\n  SidebarContext,\n  SidebarElement,\n} from './sidebar/sidebar';\nexport { SIDEBAR_CTX, SIDEBAR_GROUP_TAG, SIDEBAR_ITEM_TAG, SIDEBAR_TAG } from './sidebar/sidebar';\n","/**\n * Shared background-lock utility for overlay components (dialog, drawer, etc.).\n *\n * Uses a reference count so that multiple stacked overlays each call\n * lock / unlock independently without interfering with each other. The `inert`\n * attribute is applied once when the first overlay opens and removed once the\n * last one closes.\n *\n * The factory pattern (`createBackgroundLock`) provides test-isolated instances.\n * The module-level `lockBackground` / `unlockBackground` are the defaults used\n * by all runtime components.\n */\n\nexport type BackgroundLock = {\n  lock(host: Element): void;\n  unlock(): void;\n};\n\nexport function createBackgroundLock(): BackgroundLock {\n  let lockCount = 0;\n  let lockedEls: Element[] = [];\n\n  return {\n    lock(host: Element): void {\n      if (lockCount === 0) {\n        let ancestor: Element = host;\n\n        while (ancestor.parentElement && ancestor.parentElement !== document.body) {\n          ancestor = ancestor.parentElement;\n        }\n\n        lockedEls = Array.from(document.body.children).filter((el) => el !== ancestor && !el.hasAttribute('inert'));\n\n        for (const el of lockedEls) el.setAttribute('inert', '');\n      }\n\n      lockCount++;\n    },\n\n    unlock(): void {\n      lockCount = Math.max(0, lockCount - 1);\n\n      if (lockCount === 0) {\n        for (const el of lockedEls) el.removeAttribute('inert');\n        lockedEls = [];\n      }\n    },\n  };\n}\n\nconst _default = createBackgroundLock();\n\n/** Marks sibling elements as inert. Safe to call from multiple concurrent overlays. */\nexport const lockBackground = (host: Element): void => _default.lock(host);\n\n/** Releases the background lock. Removes inert when all overlays have closed. */\nexport const unlockBackground = (): void => _default.unlock();\n","import { type Readable, type Signal, signal, watch } from '@vielzeug/ripple';\n\nimport { createFocusManager, type DialogCloseReason, lifecycleSignal, type OverlayOpenReason } from '../../core';\nimport { awaitExit } from './await-exit';\nimport { createBackgroundLock } from './background-lock';\n\n// Invoker Commands API — not yet in lib.dom.d.ts\ninterface CommandEvent extends Event {\n  command: string;\n}\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type UseDialogOptions = {\n  /** Called after showModal() but before isOpen = true. Use to clear drag styles etc. */\n  beforeOpen?: (dialog: HTMLDialogElement) => void;\n  /** Extra properties merged into the `close-request` custom event detail. */\n  closeRequestDetail?: (reason: Exclude<DialogCloseReason, 'programmatic'>) => Record<string, unknown>;\n  /** Initial uncontrolled open state. Ignored when `openProp` is defined. */\n  defaultOpen: Readable<boolean | undefined>;\n  dialogRef: { value: HTMLDialogElement | null | undefined };\n  getPanelEl: () => HTMLElement | null | undefined;\n  host: HTMLElement;\n  initialFocus: Readable<string | undefined>;\n  isPersistent: () => boolean;\n  /** Cleanup registrar from the component setup ctx. Automatically called on disconnect. */\n  onCleanup: (fn: () => void) => void;\n  /**\n   * Scoped event listener registrar from the component setup ctx.\n   * Automatically removed on component disconnect.\n   */\n  onEvent: <K extends keyof HTMLElementEventMap>(\n    target: EventTarget | null | undefined,\n    event: K,\n    listener: (e: HTMLElementEventMap[K]) => void,\n    options?: AddEventListenerOptions,\n  ) => void;\n  /**\n   * Called after the native `close` event fires — after background unlock,\n   * isOpen reset, and focus restore. Use to emit component events.\n   */\n  onNativeClose?: (reason: DialogCloseReason) => void;\n  /** Called by the overlay on open. Use to emit events. */\n  onOpen?: (reason: OverlayOpenReason) => void;\n  /** Open prop from the component — drives programmatic open/close via watch. */\n  openProp: Readable<boolean | undefined>;\n  /**\n   * Called by the overlay when closing. Orchestrates the close animation.\n   * Default: `dialog.close()`. Override in dialog.ts to add the CSS exit animation.\n   */\n  performClose?: (dialog: HTMLDialogElement, reason: DialogCloseReason) => void;\n  returnFocus: Readable<boolean | undefined>;\n};\n\nexport type UseDialogHandle = {\n  closeWithAnimation: () => void;\n  /**\n   * Dispatch a cancelable `close-request` event on the host. Returns true when\n   * the close is allowed (event not prevented), false when it was cancelled.\n   */\n  dispatchCloseRequest: (reason: Exclude<DialogCloseReason, 'programmatic'>) => boolean;\n  handleBackdropClick: (e: MouseEvent) => void;\n  handleCancel: (e: Event) => void;\n  isOpen: Signal<boolean>;\n  /** The modal dialog controller — open/close/toggle/dispose. */\n  overlay: ModalDialogController;\n  /**\n   * Dispatch `close-request`; if allowed, call `overlay.close()`.\n   */\n  requestClose: (reason: Exclude<DialogCloseReason, 'programmatic'>) => void;\n  /**\n   * Registers the open-prop watcher AND standard click/cancel event listeners on\n   * the dialog element (backdrop click-to-close, Escape via the native `cancel`\n   * event). Use for components that need standard dialog behavior.\n   * Call inside `onMounted()`.\n   */\n  setupNativeListeners: () => void;\n  /**\n   * Registers only the open-prop watcher (without adding click/cancel listeners).\n   * Use for components like drawer that register their own event handlers.\n   * Call inside `onMounted()`.\n   */\n  watchOpenProp: () => void;\n};\n\ntype ModalDialogController = {\n  [Symbol.dispose](): void;\n  close(reason?: DialogCloseReason): void;\n  dispose(): void;\n  open(reason?: OverlayOpenReason): void;\n  toggle(openReason?: OverlayOpenReason, closeReason?: DialogCloseReason): void;\n};\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\n/**\n * Shared dialog-control composable for `ore-dialog` and `ore-drawer`.\n *\n * Owns: `isOpen`, close-reason tracking, focus management, `overlay`,\n * `requestClose`, background lock/unlock, and the `close` event handler.\n * Components supply only their unique behavior via callbacks and `onNativeClose`.\n */\nexport function useDialogControl(options: UseDialogOptions): UseDialogHandle {\n  const abortSignal = lifecycleSignal(options.onCleanup);\n  const isOpen = signal(false);\n  // Internal close-reason: set atomically before dialog.close() fires.\n  let pendingCloseReason: DialogCloseReason = 'programmatic';\n  const bgLock = createBackgroundLock();\n  let isClosing = false;\n\n  // ── Focus management ──────────────────────────────────────────────────────\n  const focus = createFocusManager({\n    getInitialFocusSelector: () => options.initialFocus.value,\n    getReturnFocus: () => options.returnFocus.value,\n    host: options.host,\n    signal: abortSignal,\n  });\n  // ─────────────────────────────────────────────────────────────────────────\n\n  const closeWithAnimation = (): void => {\n    const dialog = options.dialogRef.value;\n\n    if (!dialog?.open || isClosing) return;\n\n    isClosing = true;\n    dialog.classList.add('closing');\n\n    const finish = () => {\n      dialog.close();\n      // Do NOT remove 'closing' here — removing it while the native ::backdrop is\n      // still held in the top layer by the 'overlay allow-discrete' transition\n      // would revert its opacity to 1 and cause a visible flash. The class is\n      // cleaned up at the start of the next open cycle (see setOpen below).\n      isClosing = false;\n    };\n\n    const panel = options.getPanelEl();\n\n    if (panel) {\n      awaitExit(panel, finish, 'transition');\n    } else {\n      finish();\n    }\n  };\n\n  const dispatchCloseRequest = (reason: Exclude<DialogCloseReason, 'programmatic'>): boolean => {\n    return options.host.dispatchEvent(\n      new CustomEvent('close-request', {\n        bubbles: true,\n        cancelable: true,\n        composed: true,\n        detail: { reason, ...options.closeRequestDetail?.(reason) },\n      }),\n    );\n  };\n\n  const overlay: ModalDialogController = {\n    close(reason: DialogCloseReason = 'programmatic'): void {\n      if (!isOpen.value) return;\n\n      const dialog = options.dialogRef.value;\n\n      if (dialog?.open) {\n        pendingCloseReason = reason;\n        (options.performClose ?? ((element, _reason) => element.close()))(dialog, reason);\n      } else {\n        isOpen.value = false;\n      }\n    },\n    dispose(): void {\n      overlay.close('programmatic');\n    },\n    open(reason: OverlayOpenReason = 'programmatic'): void {\n      if (isOpen.value) return;\n\n      const dialog = options.dialogRef.value;\n\n      if (!dialog || dialog.open) return;\n\n      // Clean up any leftover 'closing' class from the previous close animation\n      // before opening so the entry @starting-style and transition work correctly.\n      dialog.classList.remove('closing');\n      focus.captureReturnFocus();\n      options.beforeOpen?.(dialog);\n      dialog.showModal();\n      bgLock.lock(options.host);\n      focus.applyInitialFocus();\n      isOpen.value = true;\n      options.onOpen?.(reason);\n    },\n    [Symbol.dispose](): void {\n      overlay.dispose();\n    },\n    toggle(openReason: OverlayOpenReason = 'click', closeReason: DialogCloseReason = 'trigger'): void {\n      if (isOpen.value) overlay.close(closeReason);\n      else overlay.open(openReason);\n    },\n  };\n\n  abortSignal.addEventListener('abort', overlay.dispose, { once: true });\n\n  const requestClose = (reason: Exclude<DialogCloseReason, 'programmatic'>): void => {\n    const allowed = dispatchCloseRequest(reason);\n\n    if (!allowed) return;\n\n    overlay.close(reason);\n  };\n\n  // Invoker Commands API — allows declarative open/close from outside the component:\n  //   <button commandfor=\"ore-dialog-id\" command=\"show-modal\">Open</button>\n  //   <button commandfor=\"ore-dialog-id\" command=\"close\">Close</button>\n  options.host.addEventListener(\n    'command',\n    (e: Event) => {\n      const cmd = (e as CommandEvent).command;\n\n      if (cmd === 'show-modal') overlay.open('trigger');\n      else if (cmd === 'close' || cmd === 'request-close') requestClose('trigger');\n    },\n    { signal: abortSignal },\n  );\n\n  // The native `<dialog>` element auto-closes on Escape via its own close-watcher, which\n  // dispatches a cancelable `cancel` event before `close`. Suppressing/redirecting that is the\n  // spec-correct hook — relying on `keydown`'s `preventDefault()` to stop the close-watcher is\n  // implementation-specific, not guaranteed across browsers.\n  const handleCancel = (e: Event): void => {\n    // See `handleNativeClose`'s comment: guard against a same-named bubbling event from a\n    // descendant field being misread as this dialog's own native event.\n    if (e.target !== options.dialogRef.value) return;\n\n    e.preventDefault();\n\n    if (options.isPersistent()) return;\n\n    requestClose('escape');\n  };\n\n  const handleBackdropClick = (e: MouseEvent): void => {\n    if (options.isPersistent()) return;\n\n    if (e.target === options.dialogRef.value) requestClose('outsideClick');\n  };\n\n  // ── Internal native close handler ─────────────────────────────────────────\n  // `e.target` must be checked against the native `<dialog>` itself, the same way\n  // `handleBackdropClick` already does: a bubbling `close`-named event fired by *any* descendant\n  // component reaches this listener too — regardless of that event's own `composed` flag, since\n  // slot-assignment-based event-path computation (a slotted descendant's \"parent\" is the `<slot>`\n  // projecting it) isn't gated by `composed` the way crossing back out of a shadow root is. Some\n  // fields nested here (`ore-select`, `ore-combobox`, …) emit their own public `close` event when\n  // *their* dropdown closes — without this check, selecting an option in one of those closes this\n  // dialog too, misreading the field's own event as this dialog's native close.\n  const handleNativeClose = (e?: Event): void => {\n    if (e && e.target !== options.dialogRef.value) return;\n\n    bgLock.unlock();\n    options.host.removeAttribute('open');\n    isOpen.value = false;\n    focus.restoreFocus();\n\n    const reason = pendingCloseReason;\n\n    pendingCloseReason = 'programmatic';\n    options.onNativeClose?.(reason);\n  };\n\n  const watchOpenProp = (): void => {\n    const dialog = options.dialogRef.value;\n\n    if (dialog) options.onEvent(dialog, 'close', handleNativeClose);\n\n    let initialized = false;\n\n    watch(\n      options.openProp,\n      (open) => {\n        if (open === undefined) {\n          if (!initialized) {\n            if (options.defaultOpen.value) overlay.open('programmatic');\n\n            initialized = true;\n\n            return;\n          }\n\n          overlay.close('programmatic');\n\n          return;\n        }\n\n        initialized = true;\n\n        if (open) {\n          overlay.open('programmatic');\n        } else {\n          overlay.close('programmatic');\n        }\n      },\n      { immediate: true },\n    );\n  };\n\n  const setupNativeListeners = (): void => {\n    const dialog = options.dialogRef.value;\n\n    if (!dialog) return;\n\n    watchOpenProp();\n    options.onEvent(dialog, 'click', handleBackdropClick);\n    options.onEvent(dialog, 'cancel', handleCancel);\n  };\n\n  return {\n    closeWithAnimation,\n    dispatchCloseRequest,\n    handleBackdropClick,\n    handleCancel,\n    isOpen,\n    overlay,\n    requestClose,\n    setupNativeListeners,\n    watchOpenProp,\n  };\n}\n","import type { CommandPaletteItem, CommandPaletteItemInput } from './command-palette.types';\n\n// ── Flat row model ────────────────────────────────────────────────────────────\n// Items are grouped by `group` (preserving first-seen order) and flattened into a\n// single list of rows so the listbox can render group headings inline while\n// keyboard navigation still walks a single, index-addressable sequence.\n\nexport type CommandPaletteRow =\n  | { group: string; type: 'group' }\n  | { idx: number; item: CommandPaletteItem; type: 'item' };\n\nexport function parseSlottedItems(elements: Element[]): CommandPaletteItem[] {\n  return elements\n    .filter((el) => el.localName === 'ore-command-palette-item')\n    .map((el) => ({\n      disabled: el.hasAttribute('disabled'),\n      group: el.getAttribute('group') ?? undefined,\n      icon: el.getAttribute('icon') ?? undefined,\n      keywords: (el.getAttribute('keywords') ?? '')\n        .split(',')\n        .map((term) => term.trim())\n        .filter(Boolean),\n      label:\n        el.getAttribute('label') ||\n        [...el.childNodes]\n          .filter((node) => node.nodeType === Node.TEXT_NODE)\n          .map((node) => node.textContent?.trim())\n          .filter(Boolean)\n          .join(' ') ||\n        '',\n      shortcut: el.getAttribute('shortcut') ?? undefined,\n      value: el.getAttribute('value') ?? '',\n    }));\n}\n\n/**\n * Splits a display-only shortcut hint into individual keys so each can be rendered in its\n * own `<kbd>`. Keys are separated with `+` (e.g. `\"⌘+N\"` → `[\"⌘\", \"N\"]`); a shortcut with no\n * `+` renders as a single key, unchanged. A literal `+` key can't be represented this way —\n * spell it out instead (e.g. `\"Ctrl+Plus\"`).\n */\nexport function splitShortcutKeys(shortcut: string): string[] {\n  return shortcut\n    .split('+')\n    .map((key) => key.trim())\n    .filter(Boolean);\n}\n\nexport function normalizeItem(input: CommandPaletteItemInput): CommandPaletteItem {\n  return {\n    disabled: Boolean(input.disabled),\n    group: input.group,\n    icon: input.icon,\n    keywords: input.keywords ?? [],\n    label: input.label ?? input.value,\n    shortcut: input.shortcut,\n    value: input.value,\n  };\n}\n\nexport function filterItems(items: CommandPaletteItem[], query: string, noFilter: boolean): CommandPaletteItem[] {\n  if (noFilter) return items;\n\n  const normalizedQuery = query.toLowerCase().trim();\n\n  if (!normalizedQuery) return items;\n\n  return items.filter(\n    (item) =>\n      item.label.toLowerCase().includes(normalizedQuery) ||\n      item.value.toLowerCase().includes(normalizedQuery) ||\n      item.keywords.some((keyword) => keyword.toLowerCase().includes(normalizedQuery)),\n  );\n}\n\n/** Groups items by `group` (first-seen order) and flattens into index-addressable rows. */\nexport function buildRows(items: CommandPaletteItem[]): CommandPaletteRow[] {\n  const groups = new Map<string | undefined, CommandPaletteItem[]>();\n\n  for (const item of items) {\n    const key = item.group;\n    let bucket = groups.get(key);\n\n    if (!bucket) {\n      bucket = [];\n      groups.set(key, bucket);\n    }\n\n    bucket.push(item);\n  }\n\n  const rows: CommandPaletteRow[] = [];\n  let idx = 0;\n\n  for (const [group, groupItems] of groups) {\n    if (group !== undefined) rows.push({ group, type: 'group' });\n\n    for (const item of groupItems) rows.push({ idx: idx++, item, type: 'item' });\n  }\n\n  return rows;\n}\n","@layer refine.base {\n  :host {\n    --_radius: var(--command-palette-radius, var(--rounded-lg));\n    --_max-width: var(--command-palette-max-width, 40rem);\n    --_backdrop-bg: var(--command-palette-backdrop, color-mix(in oklch, var(--color-canvas) 40%, transparent));\n    --_panel-bg: var(--command-palette-bg, var(--color-canvas));\n    --_panel-border-color: var(--command-palette-border-color, var(--color-divider));\n    --_option-hover-bg: var(--command-palette-option-hover-bg, var(--color-contrast-100));\n    --_option-focus-bg: var(\n      --command-palette-option-focus-bg,\n      color-mix(in oklch, var(--color-primary) 12%, var(--color-contrast-100))\n    );\n\n    display: contents;\n  }\n\n  /* =====================\n       Native <dialog> resets — see ore-dialog for the full rationale.\n       ===================== */\n\n  dialog {\n    all: unset;\n    position: fixed;\n    inset: 0;\n    box-sizing: border-box;\n    display: flex;\n    align-items: flex-start;\n    justify-content: center;\n    width: 100%;\n    max-width: 100%;\n    height: 100%;\n    max-height: 100%;\n    padding-block-start: min(14vh, var(--size-24));\n    margin: 0;\n    overflow: hidden;\n    pointer-events: none;\n    background: transparent;\n    border: none;\n    transition:\n      display 200ms allow-discrete,\n      overlay 200ms allow-discrete;\n  }\n\n  dialog:not([open]) {\n    display: none;\n  }\n\n  dialog:not([open]) .panel {\n    display: none;\n  }\n\n  dialog[open] {\n    pointer-events: auto;\n  }\n\n  dialog::backdrop {\n    background: var(--_backdrop-bg);\n    opacity: 1;\n    backdrop-filter: blur(var(--blur-xs));\n    transition:\n      opacity var(--transition-normal),\n      overlay var(--transition-normal) allow-discrete,\n      display var(--transition-normal) allow-discrete;\n\n    @starting-style {\n      opacity: 0;\n    }\n  }\n\n  dialog.closing::backdrop {\n    opacity: 0;\n  }\n\n  /* =====================\n       Panel\n       ===================== */\n\n  .panel {\n    position: relative;\n    box-sizing: border-box;\n    display: flex;\n    flex-direction: column;\n    width: var(--_max-width);\n    max-width: calc(100vw - var(--size-8));\n    max-height: min(28rem, calc(100dvh - var(--size-16)));\n    overflow: hidden;\n    background: var(--_panel-bg);\n    border: var(--border) solid var(--_panel-border-color);\n    border-radius: var(--_radius);\n    box-shadow: var(--command-palette-shadow, var(--shadow-2xl));\n    opacity: 1;\n    backdrop-filter: blur(var(--blur-md));\n    transform: scale(1) translateY(0);\n    transition:\n      opacity 200ms var(--ease-spring),\n      transform 200ms var(--ease-spring);\n\n    @starting-style {\n      opacity: 0;\n      transform: scale(var(--overlay-enter-scale-dialog)) translateY(-4px);\n    }\n  }\n\n  dialog.closing .panel {\n    opacity: 0;\n    transform: scale(var(--overlay-enter-scale-dialog)) translateY(-4px);\n    transition:\n      opacity 150ms var(--ease-spring),\n      transform 150ms var(--ease-spring);\n  }\n\n  @media (width <= 640px) {\n    .panel {\n      width: calc(100vw - var(--size-4));\n      max-width: calc(100vw - var(--size-4));\n    }\n\n    dialog {\n      padding-block-start: var(--size-4);\n    }\n  }\n\n  /* =====================\n       Search field\n       ===================== */\n\n  .search {\n    display: flex;\n    flex-shrink: 0;\n    gap: var(--size-2);\n    align-items: center;\n    padding: var(--size-3) var(--size-4);\n    border-block-end: var(--border) solid var(--color-contrast-100);\n  }\n\n  .search-icon {\n    display: inline-flex;\n    flex-shrink: 0;\n    color: var(--color-contrast-400);\n  }\n\n  .search-input {\n    flex: 1;\n    min-width: 0;\n    padding: 0;\n    font: inherit;\n    font-size: var(--text-md);\n    color: var(--color-contrast-900);\n    outline: none;\n    background: transparent;\n    border: none;\n  }\n\n  .search-input::placeholder {\n    color: var(--color-contrast-400);\n  }\n\n  .search-loader {\n    display: inline-flex;\n    flex-shrink: 0;\n    width: 1em;\n    height: 1em;\n    border: 2px solid var(--color-contrast-300);\n    border-inline-end-color: transparent;\n    border-radius: 50%;\n    animation: command-palette-spin var(--transition-loader) infinite;\n  }\n\n  .search-loader[hidden] {\n    display: none;\n  }\n\n  @keyframes command-palette-spin {\n    to {\n      transform: rotate(360deg);\n    }\n  }\n\n  /* =====================\n       Listbox\n       ===================== */\n\n  .listbox {\n    flex: 1;\n    padding: var(--size-1);\n    overflow-y: auto;\n    overscroll-behavior: contain;\n    scrollbar-width: thin;\n  }\n\n  .empty {\n    padding: var(--size-6) var(--size-3);\n    font-size: var(--text-sm);\n    color: var(--color-contrast-400);\n    text-align: center;\n  }\n\n  .group-heading {\n    padding: var(--size-2) var(--size-2-5) var(--size-1);\n    font-size: var(--text-xs);\n    font-weight: var(--font-semibold);\n    color: var(--color-contrast-500);\n    text-transform: uppercase;\n    letter-spacing: var(--tracking-wide, 0.05em);\n  }\n\n  .item {\n    display: flex;\n    gap: var(--size-2-5);\n    align-items: center;\n    padding: var(--size-2) var(--size-2-5);\n    font-size: var(--text-sm);\n    line-height: var(--leading-normal);\n    color: var(--color-contrast-800);\n    cursor: pointer;\n    border-radius: var(--rounded-md);\n    transition: background var(--transition-fast);\n  }\n\n  .item:hover:not([data-disabled]) {\n    background: var(--_option-hover-bg);\n  }\n\n  .item[data-focused]:not([data-disabled]) {\n    background: var(--_option-focus-bg);\n  }\n\n  .item[data-disabled] {\n    color: var(--color-contrast-400);\n    cursor: not-allowed;\n    opacity: 0.6;\n  }\n\n  .item-icon {\n    display: inline-flex;\n    flex-shrink: 0;\n    align-items: center;\n    color: var(--color-contrast-500);\n  }\n\n  .item-label {\n    flex: 1;\n    min-width: 0;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n  }\n\n  .item-shortcut {\n    display: inline-flex;\n    flex-shrink: 0;\n    gap: var(--size-1);\n  }\n\n  .item-shortcut kbd {\n    padding: var(--size-0-5) var(--size-1-5);\n    font-family: var(--font-mono, monospace);\n    font-size: var(--text-xs);\n    color: var(--color-contrast-500);\n    background: var(--color-contrast-100);\n    border: var(--border) solid var(--color-contrast-200);\n    border-bottom-width: calc(var(--border) + 1px);\n    border-radius: var(--rounded-sm);\n  }\n\n  /* =====================\n       Footer hints\n       ===================== */\n\n  .footer {\n    display: flex;\n    flex-shrink: 0;\n    gap: var(--size-4);\n    align-items: center;\n    padding: var(--size-2) var(--size-4);\n    font-size: var(--text-xs);\n    color: var(--color-contrast-500);\n    border-block-start: var(--border) solid var(--color-contrast-100);\n  }\n\n  .footer-hint {\n    display: inline-flex;\n    gap: var(--size-1);\n    align-items: center;\n  }\n\n  .footer kbd {\n    padding: var(--size-0-5) var(--size-1);\n    font-family: inherit;\n    font-size: var(--text-xs);\n    background: var(--color-contrast-100);\n    border: var(--border) solid var(--color-contrast-200);\n    border-bottom-width: calc(var(--border) + 1px);\n    border-radius: var(--rounded-sm);\n  }\n\n  /* Slotted item elements are pure data nodes — never rendered directly. */\n  ::slotted(ore-command-palette-item) {\n    display: none;\n  }\n}\n","import { createKeymap } from '@vielzeug/keymap';\nimport { define, getHost, html, onCleanup, onEvent, onMounted, prop, ref, useEmit } from '@vielzeug/ore';\nimport { computed, signal, watch } from '@vielzeug/ripple';\nimport { warn } from '../../_dev';\nimport { announce, createListControl, lifecycleSignal } from '../../core';\nimport { reducedMotionMixin } from '../../styles';\nimport { useDialogControl } from '../shared/use-dialog';\nimport type { CommandPaletteItem, OreCommandPaletteEvents, OreCommandPaletteProps } from './command-palette.types';\nimport { buildRows, filterItems, normalizeItem, parseSlottedItems, splitShortcutKeys } from './command-palette-items';\nimport '../../content/icon/icon';\nimport componentStyles from './command-palette.css?inline';\n\nexport type { OreCommandPaletteEvents, OreCommandPaletteProps } from './command-palette.types';\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n  value == null ? undefined : value === '' || value === 'true';\n\n/**\n * A pure data node describing one command. Never rendered directly — `ore-command-palette`\n * reads its attributes/text content and renders the visible row itself.\n *\n * @element ore-command-palette-item\n *\n * @attr {string} value - Value emitted by the `select` event and matched against the search query\n * @attr {string} label - Explicit label text; falls back to the element's text content\n * @attr {string} group - Group heading the item is clustered under\n * @attr {string} shortcut - Display-only keyboard hint rendered at the end of the row, one `<kbd>` per `+`-separated key (e.g. `\"⌘+S\"` renders two keycaps; a literal `+` key isn't representable — spell it out, e.g. `\"Ctrl+Plus\"`)\n * @attr {boolean} disabled - Excludes the item from keyboard navigation and selection\n *\n * @slot icon - Optional leading icon content\n *\n * @example\n * ```html\n * <ore-command-palette-item value=\"new-file\" group=\"File\" shortcut=\"⌘+N\">New File</ore-command-palette-item>\n * ```\n */\nexport const COMMAND_PALETTE_ITEM_TAG = 'ore-command-palette-item' as const;\ndefine(COMMAND_PALETTE_ITEM_TAG, {\n  setup() {\n    return html``;\n  },\n});\n\n/**\n * A searchable, keyboard-driven list of commands presented in a centered modal —\n * the \"⌘K\" pattern popularized by editors and productivity apps. Built on the\n * native `<dialog>` element (focus trap, top-layer stacking, `Escape`-to-close)\n * and `@vielzeug/keymap` for the global shortcut that opens it.\n *\n * @element ore-command-palette\n * @element ore-command-palette-item - Slotted command definition (place in default slot)\n *\n * @attr {boolean} open - Controls the open state of the palette\n * @attr {boolean} default-open - Initial uncontrolled open state\n * @attr {string} label - Accessible label for the dialog (screen-reader-only heading)\n * @attr {string} placeholder - Placeholder text for the search input\n * @attr {string} shortcut - Global keyboard shortcut (keymap syntax) that toggles the palette. Default `\"mod+k\"`; set to `\"\"` to disable\n * @attr {boolean} no-filter - Disable built-in client-side filtering (for server-driven search)\n * @attr {boolean} loading - Shows a loading row below the search input\n * @attr {string} empty-text - Message shown when no item matches the query\n * @attr {boolean} keep-open-on-select - Keep the palette open after an item is selected\n *\n * @fires open-change - Fired when the palette state changes. detail: `{ open, reason }`\n * @fires search - Fired on every keystroke in the search input. detail: `{ query }`\n * @fires select - Fired when a command is chosen (click or `Enter`). detail: `{ value, label, item }`\n *\n * @slot - `<ore-command-palette-item>` elements (alternative/supplement to the `items` prop)\n *\n * @cssprop --command-palette-bg - Panel background color\n * @cssprop --command-palette-border-color - Panel border color\n * @cssprop --command-palette-radius - Panel border radius\n * @cssprop --command-palette-shadow - Panel drop shadow\n * @cssprop --command-palette-max-width - Maximum panel width\n * @cssprop --command-palette-backdrop - Backdrop overlay color\n * @cssprop --command-palette-option-hover-bg - Item background on hover\n * @cssprop --command-palette-option-focus-bg - Item background when keyboard-focused\n *\n * @part dialog - Dialog root container\n * @part panel - Panel container\n * @part input - Search input\n * @part listbox - Listbox of matching commands\n *\n * @example\n * ```html\n * <ore-command-palette label=\"Command palette\" placeholder=\"Type a command…\">\n *   <ore-command-palette-item value=\"new-file\" group=\"File\" shortcut=\"⌘+N\">New File</ore-command-palette-item>\n *   <ore-command-palette-item value=\"open-file\" group=\"File\" shortcut=\"⌘+O\">Open File…</ore-command-palette-item>\n *   <ore-command-palette-item value=\"toggle-theme\" group=\"View\">Toggle Theme</ore-command-palette-item>\n * </ore-command-palette>\n * ```\n */\nexport const COMMAND_PALETTE_TAG = 'ore-command-palette' as const;\ndefine<OreCommandPaletteProps>(COMMAND_PALETTE_TAG, {\n  props: {\n    'default-open': prop.bool(false),\n    'empty-text': prop.string('No results found.'),\n    items: prop.data<OreCommandPaletteProps['items']>(),\n    'keep-open-on-select': prop.bool(false),\n    label: prop.string('Command palette'),\n    loading: prop.bool(false),\n    'no-filter': prop.bool(false),\n    open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n    placeholder: prop.string('Type a command or search…'),\n    shortcut: prop.string('mod+k'),\n  },\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreCommandPaletteEvents>();\n    const abortSignal = lifecycleSignal(onCleanup);\n\n    const dialogRef = ref<HTMLDialogElement>();\n    const searchInputRef = ref<HTMLInputElement>();\n    const listboxId = 'cmdk-listbox';\n\n    let listboxEl: HTMLElement | null = null;\n\n    const query = signal('');\n\n    // ── Items: slotted <ore-command-palette-item> elements, merged with the `items` prop ──\n    // Items are pure data nodes (see `ore-command-palette-item`'s own doc comment) — they're\n    // never projected through a `<slot>`, just read directly off the host's light DOM. That\n    // sidesteps `useSlots()`/`slotchange` entirely: a plain MutationObserver on the host\n    // already covers everything `slotchange` would (an item added or removed) *and* the case\n    // it can't — an already-assigned item's own text/attributes changing. For items written\n    // as static, inline HTML, the browser's parser can insert the last item before appending\n    // its text-node child; without watching `characterData`, that would permanently cache an\n    // empty label, since nothing else re-triggers once the element itself stops changing.\n    const slottedItems = signal<CommandPaletteItem[]>([]);\n\n    const reparseSlottedItems = (): void => {\n      slottedItems.value = parseSlottedItems([...el.children]);\n    };\n\n    reparseSlottedItems();\n\n    const lightDomObserver = new MutationObserver(reparseSlottedItems);\n\n    lightDomObserver.observe(el, { characterData: true, childList: true, subtree: true });\n    onCleanup(() => lightDomObserver.disconnect());\n\n    const allItems = computed<CommandPaletteItem[]>(() => {\n      const explicit = props.items.value;\n\n      return Array.isArray(explicit) ? explicit.map(normalizeItem) : slottedItems.value;\n    });\n\n    const filteredItems = computed(() => filterItems(allItems.value, query.value, Boolean(props['no-filter'].value)));\n    const rows = computed(() => buildRows(filteredItems.value));\n\n    // ── Keyboard navigation over the filtered list (Up/Down/Home/End) ──\n    const scrollFocusedIntoView = (): void => {\n      listboxEl?.querySelector<HTMLElement>('[data-focused]')?.scrollIntoView({ block: 'nearest' });\n    };\n\n    const list = createListControl<CommandPaletteItem>({\n      getItems: () => filteredItems.value,\n      isItemDisabled: (item) => item.disabled,\n      onNavigate: scrollFocusedIntoView,\n      signal: abortSignal,\n    });\n    const { focusedIndex } = list;\n\n    // ── Dialog chrome: native <dialog>, focus trap, Escape, backdrop click ──\n    const resetSearch = (): void => {\n      query.value = '';\n      list.reset();\n    };\n\n    const { closeWithAnimation, overlay, requestClose, setupNativeListeners } = useDialogControl({\n      defaultOpen: props['default-open'],\n      dialogRef,\n      getPanelEl: () => dialogRef.value?.querySelector<HTMLElement>('.panel'),\n      host: el,\n      initialFocus: computed(() => '.search-input'),\n      isPersistent: () => false,\n      onCleanup,\n      onEvent,\n      onNativeClose: (reason) => {\n        emit('open-change', { open: false, reason });\n        resetSearch();\n      },\n      onOpen: (reason) => {\n        emit('open-change', { open: true, reason });\n        list.navigate('first');\n      },\n      openProp: props.open,\n      performClose: () => closeWithAnimation(),\n      returnFocus: computed(() => true),\n    });\n\n    // ── Global keyboard shortcut (opens/closes the palette from anywhere) ──\n    const globalKeymap = createKeymap();\n\n    globalKeymap.mount(window);\n    onCleanup(() => globalKeymap.dispose());\n\n    let unbindShortcut: (() => void) | null = null;\n\n    watch(\n      props.shortcut,\n      (shortcutStr) => {\n        unbindShortcut?.();\n        unbindShortcut = null;\n\n        const trimmed = (shortcutStr ?? '').trim();\n\n        if (!trimmed) return;\n\n        try {\n          unbindShortcut = globalKeymap.bind(trimmed, () => {\n            overlay.toggle('keyboard', 'trigger');\n          });\n        } catch (error) {\n          warn(`invalid \"shortcut\" value \"${trimmed}\" — ${error instanceof Error ? error.message : String(error)}`);\n        }\n      },\n      { immediate: true },\n    );\n\n    onMounted(() => {\n      setupNativeListeners();\n    });\n\n    // ── Selection ────────────────────────────────────────────────────────────\n    function selectItem(item: CommandPaletteItem): void {\n      if (item.disabled) return;\n\n      emit('select', { item, label: item.label, value: item.value });\n\n      if (props['keep-open-on-select'].value) {\n        searchInputRef.value?.focus();\n      } else {\n        requestClose('trigger');\n      }\n    }\n\n    function handleInput(e: Event): void {\n      const value = (e.target as HTMLInputElement).value;\n\n      query.value = value;\n      list.navigate('first');\n      emit('search', { query: value });\n\n      const count = filteredItems.value.length;\n\n      announce(count === 0 ? props['empty-text'].value! : `${count} result${count === 1 ? '' : 's'} found`);\n    }\n\n    function handleKeydown(e: KeyboardEvent): void {\n      if (list.handleKeydown(e)) return;\n\n      if (e.key === 'Enter') {\n        // `list.navigate('first')` (called on open and on every keystroke) already keeps\n        // the focused row off a disabled item, so this fallback is only ever reached when\n        // nothing has been focused yet — but it mirrors `selectItem`'s own disabled guard\n        // rather than blindly grabbing index 0, in case that navigate-on-open wiring ever\n        // changes.\n        const active = list.getActiveItem() ?? filteredItems.value.find((item) => !item.disabled);\n\n        if (active) {\n          e.preventDefault();\n          selectItem(active);\n        }\n      }\n    }\n\n    return html`\n      <dialog ref=\"${dialogRef}\" class=\"dialog\" part=\"dialog\" aria-label=\"${props.label}\" aria-modal=\"true\">\n        <div class=\"panel\" part=\"panel\">\n          <div class=\"search\" part=\"search\">\n            <span class=\"search-icon\" aria-hidden=\"true\"><ore-icon name=\"search\" size=\"18\"></ore-icon></span>\n            <input\n              ref=\"${searchInputRef}\"\n              class=\"search-input\"\n              part=\"input\"\n              type=\"text\"\n              role=\"combobox\"\n              autocomplete=\"off\"\n              spellcheck=\"false\"\n              aria-expanded=\"true\"\n              aria-autocomplete=\"list\"\n              aria-controls=\"${listboxId}\"\n              aria-activedescendant=\"${() => (focusedIndex.value >= 0 ? `${listboxId}-opt-${focusedIndex.value}` : '')}\"\n              placeholder=\"${props.placeholder}\"\n              value=\"${query}\"\n              @input=\"${handleInput}\"\n              @keydown=\"${handleKeydown}\" />\n            <span class=\"search-loader\" ?hidden=\"${() => !props.loading.value}\" aria-hidden=\"true\"></span>\n          </div>\n          <div\n            class=\"listbox\"\n            part=\"listbox\"\n            role=\"listbox\"\n            id=\"${listboxId}\"\n            aria-label=\"Commands\"\n            ref=\"${(listEl: HTMLElement) => {\n              listboxEl = listEl;\n            }}\">\n            <div class=\"empty\" role=\"presentation\" ?hidden=\"${() => props.loading.value || rows.value.length > 0}\">\n              ${() => props['empty-text'].value}\n            </div>\n            ${() =>\n              rows.value.map((row) =>\n                row.type === 'group'\n                  ? html`\n                      <div class=\"group-heading\" role=\"presentation\">${row.group}</div>\n                    `\n                  : html`\n                      <div\n                        class=\"item\"\n                        part=\"item\"\n                        role=\"option\"\n                        id=\"${`${listboxId}-opt-${row.idx}`}\"\n                        aria-selected=\"${() => String(focusedIndex.value === row.idx)}\"\n                        aria-disabled=\"${() => String(row.item.disabled)}\"\n                        ?data-focused=\"${() => focusedIndex.value === row.idx}\"\n                        ?data-disabled=\"${() => row.item.disabled}\"\n                        @click=\"${(e: MouseEvent) => {\n                          e.stopPropagation();\n                          selectItem(row.item);\n                        }}\"\n                        @pointerenter=\"${() => {\n                          list.set(row.idx);\n                        }}\">\n                        ${\n                          row.item.icon\n                            ? html`\n                                <span class=\"item-icon\" aria-hidden=\"true\">\n                                  <ore-icon name=\"${row.item.icon}\" size=\"16\"></ore-icon>\n                                </span>\n                              `\n                            : ''\n                        }\n                        <span class=\"item-label\">${row.item.label}</span>\n                        ${\n                          row.item.shortcut\n                            ? html`\n                                <span class=\"item-shortcut\">\n                                  ${splitShortcutKeys(row.item.shortcut).map(\n                                    (key) => html`\n                                      <kbd>${key}</kbd>\n                                    `,\n                                  )}\n                                </span>\n                              `\n                            : ''\n                        }\n                      </div>\n                    `,\n              )}\n          </div>\n          <div class=\"footer\" part=\"footer\">\n            <span class=\"footer-hint\">\n              <kbd>↑</kbd>\n              <kbd>↓</kbd>\n              Navigate\n            </span>\n            <span class=\"footer-hint\">\n              <kbd>Enter</kbd>\n              Select\n            </span>\n            <span class=\"footer-hint\">\n              <kbd>Esc</kbd>\n              Close\n            </span>\n          </div>\n        </div>\n      </dialog>\n    `;\n  },\n  styles: [reducedMotionMixin, componentStyles],\n});\n","@layer refine.base {\n  :host {\n    --_radius: var(--dialog-radius, var(--rounded-lg));\n    --_padding: var(--dialog-padding, var(--size-4));\n    --_gap: var(--dialog-gap, var(--size-4));\n    --_max-width: var(--dialog-max-width, 32rem);\n    --_elevation: var(--shadow-xl);\n    --_backdrop-filter: none;\n    --_backdrop-bg: var(--dialog-backdrop, color-mix(in oklch, var(--color-canvas) 40%, transparent));\n    --_panel-bg: var(--dialog-bg, var(--color-canvas));\n    --_panel-blur: var(--dialog-panel-blur, var(--blur-md));\n    --_panel-border-color: var(--dialog-border-color, var(--color-divider));\n\n    display: contents;\n  }\n\n  /* =====================\n       Native <dialog> resets\n       ===================== */\n\n  dialog {\n    all: unset;\n    position: fixed;\n    inset: 0;\n    box-sizing: border-box;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: 100%;\n    max-width: 100%;\n    height: 100%;\n    max-height: 100%;\n    padding: 0;\n    margin: 0;\n    overflow: hidden;\n    pointer-events: none;\n    background: transparent;\n    border: none;\n\n    /* display + overlay allow-discrete hold the element in the top layer during exit\n       and let @starting-style fire on entry via showModal().\n       Use fixed 200ms — --transition-normal resolves to 'none' under reduced-motion\n       which makes the entire declaration syntactically invalid if used here. */\n    transition:\n      display 200ms allow-discrete,\n      overlay 200ms allow-discrete;\n  }\n\n  /* all:unset removes the UA stylesheet's dialog:not([open]){display:none} — restore it */\n  dialog:not([open]) {\n    display: none;\n  }\n\n  dialog:not([open]) .panel {\n    display: none;\n  }\n\n  dialog[open] {\n    pointer-events: auto;\n  }\n\n  dialog::backdrop {\n    background: var(--_backdrop-bg);\n    opacity: 1;\n    backdrop-filter: var(--_backdrop-filter);\n    transition:\n      opacity var(--transition-normal),\n      overlay var(--transition-normal) allow-discrete,\n      display var(--transition-normal) allow-discrete;\n\n    @starting-style {\n      opacity: 0;\n    }\n  }\n\n  dialog.closing::backdrop {\n    opacity: 0;\n    transition:\n      opacity 150ms var(--ease-in-out),\n      overlay 150ms allow-discrete,\n      display 150ms allow-discrete;\n  }\n\n  /* =====================\n       Panel (the visible dialog box)\n       ===================== */\n\n  .panel {\n    position: relative;\n    box-sizing: border-box;\n    display: flex;\n    flex-direction: column;\n    width: var(--_max-width);\n    max-width: calc(100vw - var(--size-8));\n    max-height: calc(100dvh - var(--size-8));\n    overflow: hidden;\n    background: var(--_panel-bg);\n    border: var(--border) solid var(--_panel-border-color);\n    border-radius: var(--_radius);\n    box-shadow: var(--dialog-shadow, var(--_elevation));\n    opacity: 1;\n    backdrop-filter: blur(var(--_panel-blur));\n    transform: scale(1) translateY(0);\n    transition:\n      opacity 200ms var(--ease-spring),\n      transform 200ms var(--ease-spring);\n\n    @starting-style {\n      opacity: 0;\n      transform: scale(var(--overlay-enter-scale-dialog)) translateY(4px);\n    }\n  }\n\n  dialog.closing .panel {\n    opacity: 0;\n    transform: scale(var(--overlay-enter-scale-dialog)) translateY(4px);\n    transition:\n      opacity 150ms var(--ease-spring),\n      transform 150ms var(--ease-spring);\n  }\n\n  /* =====================\n       Sizes\n       ===================== */\n\n  .panel[data-size='sm'] {\n    --_max-width: var(--dialog-max-width, 22rem);\n  }\n\n  .panel[data-size='md'] {\n    --_max-width: var(--dialog-max-width, 32rem);\n  }\n\n  .panel[data-size='lg'] {\n    --_max-width: var(--dialog-max-width, 48rem);\n  }\n\n  .panel[data-size='xl'] {\n    --_max-width: var(--dialog-max-width, 64rem);\n  }\n\n  .panel[data-size='full'] {\n    width: calc(100vw - var(--size-8));\n    max-width: calc(100vw - var(--size-8));\n    max-height: calc(100dvh - var(--size-8));\n  }\n\n  /* =====================\n       Header\n       ===================== */\n\n  .header {\n    display: flex;\n    flex-shrink: 0;\n    gap: var(--size-2);\n    align-items: center;\n    padding: var(--_padding);\n    padding-bottom: 0;\n  }\n\n  .header[hidden] {\n    display: none;\n  }\n\n  .title {\n    flex: 1;\n    font-size: var(--text-lg);\n    font-weight: var(--font-semibold);\n    line-height: var(--leading-tight);\n    color: var(--color-contrast-900);\n  }\n\n  .close {\n    display: inline-flex;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    width: var(--size-8);\n    min-width: var(--_touch-target);\n    height: var(--size-8);\n    min-height: var(--_touch-target);\n    padding: 0;\n    margin-inline-start: auto;\n    color: var(--color-contrast-500);\n    cursor: pointer;\n    background: transparent;\n    border: none;\n    border-radius: var(--rounded-md);\n    transition:\n      background var(--transition-fast),\n      color var(--transition-fast);\n  }\n\n  .close:hover {\n    color: var(--color-contrast-900);\n    background: var(--color-contrast-200);\n  }\n\n  .close:focus-visible {\n    outline: var(--border-2) solid var(--color-focus);\n    outline-offset: var(--border-2);\n  }\n\n  .close[hidden] {\n    display: none;\n  }\n\n  /* =====================\n       Body\n       ===================== */\n\n  .body {\n    flex: 1;\n    padding: var(--_padding);\n    overflow-y: auto;\n    overscroll-behavior: contain;\n    font-size: var(--text-sm);\n    line-height: var(--leading-relaxed);\n    color: var(--color-contrast-700);\n  }\n\n  /* =====================\n       Footer\n       ===================== */\n\n  .footer {\n    display: flex;\n    flex-shrink: 0;\n    flex-wrap: wrap;\n    gap: var(--_gap);\n    align-items: center;\n    justify-content: flex-end;\n    padding: var(--_padding);\n    padding-top: 0;\n  }\n\n  .footer[hidden] {\n    display: none;\n  }\n\n  /* =====================\n       Dividers when header/footer present\n       ===================== */\n\n  .header:not([hidden]) + .body {\n    padding-top: var(--size-4);\n  }\n\n  .body + .footer:not([hidden]) {\n    padding-top: var(--size-4);\n    border-top: var(--border) solid var(--color-contrast-100);\n  }\n\n  @media (width <= 640px) {\n    .panel,\n    .panel[data-size='sm'],\n    .panel[data-size='md'],\n    .panel[data-size='lg'],\n    .panel[data-size='xl'] {\n      width: calc(100vw - var(--size-4));\n      max-width: calc(100vw - var(--size-4));\n      max-height: calc(100dvh - var(--size-4));\n    }\n\n    .header,\n    .body,\n    .footer {\n      padding-inline: var(--size-3);\n    }\n  }\n}\n\n@layer refine.config {\n  :host([backdrop='blur']) {\n    --_backdrop-filter: blur(var(--blur-xs));\n  }\n\n  :host([backdrop='transparent']) {\n    --_backdrop-bg: transparent;\n  }\n\n  /* Panel elevation / shadow scale */\n  :host([elevation='none']) {\n    --_elevation: var(--shadow-none);\n  }\n\n  :host([elevation='sm']) {\n    --_elevation: var(--shadow-sm);\n  }\n\n  :host([elevation='md']) {\n    --_elevation: var(--shadow-md);\n  }\n\n  :host([elevation='lg']) {\n    --_elevation: var(--shadow-lg);\n  }\n\n  :host([elevation='xl']) {\n    --_elevation: var(--shadow-xl);\n  }\n\n  :host([elevation='2xl']) {\n    --_elevation: var(--shadow-2xl);\n  }\n\n  /* Padding scale */\n  :host([padding='none']) {\n    --_padding: var(--size-0);\n  }\n\n  :host([padding='sm']) {\n    --_padding: var(--size-3);\n  }\n\n  :host([padding='md']) {\n    --_padding: var(--size-4);\n  }\n\n  :host([padding='lg']) {\n    --_padding: var(--size-6);\n  }\n\n  :host([padding='xl']) {\n    --_padding: var(--size-8);\n  }\n}\n","import { define, getHost, html, onCleanup, onEvent, onMounted, prop, ref, useEmit, useSlots } from '@vielzeug/ore';\n\nimport type { OverlayOpenChangeDetail } from '../../core';\nimport { coarsePointerMixin, roundedVariantMixin } from '../../styles';\nimport type { PaddingSize, RoundedSize } from '../../types';\nimport { useDialogControl } from '../shared/use-dialog';\nimport '../../content/icon/icon';\nimport componentStyles from './dialog.css?inline';\n\ntype DialogSize = 'sm' | 'md' | 'lg' | 'xl' | 'full';\ntype DialogBackdrop = 'opaque' | 'blur' | 'transparent';\ntype DialogElevation = 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n  value == null ? undefined : value === '' || value === 'true';\n\n/** Dialog component properties */\n\nexport type OreDialogEvents = {\n  'open-change': OverlayOpenChangeDetail;\n};\n\nexport type OreDialogProps = {\n  /** Backdrop style — 'blur' (default): dark overlay + blur; 'opaque': dark overlay only; 'transparent': no overlay */\n  backdrop?: DialogBackdrop;\n  /** Initial uncontrolled open state. Ignored when `open` is set. */\n  'default-open'?: boolean;\n  /** Show a close (×) button in the header */\n  dismissible?: boolean;\n  /** Panel shadow elevation — defaults to 'xl' */\n  elevation?: DialogElevation;\n  /**\n   * CSS selector for the element inside the dialog that should receive focus when the dialog opens.\n   * Defaults to the first focusable element (browser default).\n   * @example 'input[name=\"email\"]' | '#confirm-btn'\n   */\n  'initial-focus'?: string;\n  /** Dialog title shown in the header (used as aria-label when no header slot) */\n  label?: string;\n  /** Controls the open state of the dialog */\n  open?: boolean;\n  /** Internal padding size */\n  padding?: PaddingSize;\n  /** When true, clicking the backdrop does not close the dialog */\n  persistent?: boolean;\n  /**\n   * When true (default), the focus returns to the element that triggered the dialog after it closes.\n   * Set to false if you want to manage focus manually.\n   */\n  'return-focus'?: boolean;\n  /** Border radius */\n  rounded?: RoundedSize | '';\n  /** Dialog size */\n  size?: DialogSize;\n};\n\n/**\n * A modal dialog that traps focus, blocks page interaction, and dismisses on\n * `Escape`. Built on the native `<dialog>` element for correct top-layer stacking\n * and browser-managed accessibility.\n *\n * @element ore-dialog\n *\n * @attr {boolean} open - Controlled open state\n * @attr {boolean} default-open - Initial uncontrolled open state\n * @attr {string} label - Dialog title (also used as aria-label)\n * @attr {string} size - Size: 'sm' | 'md' | 'lg' | 'xl' | 'full'\n * @attr {boolean} dismissible - Show a close (×) button in the header\n * @attr {boolean} persistent - Prevent backdrop-click from closing\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {string} backdrop - Backdrop style: 'opaque' (default) | 'blur' | 'transparent'\n * @attr {string} elevation - Panel shadow: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'\n * @attr {string} padding - Padding: 'none' | 'sm' | 'md' | 'lg' | 'xl'\n *\n * @fires open-change - Fired when the dialog state changes. detail: { open, reason }\n *\n * @slot - Dialog body content\n * @slot header - Custom header content (replaces the default title + close layout)\n * @slot footer - Action buttons or additional content at the bottom\n *\n * @cssprop --dialog-bg - Panel background color\n * @cssprop --dialog-border-color - Panel border color\n * @cssprop --dialog-radius - Panel border radius\n * @cssprop --dialog-shadow - Panel drop shadow\n * @cssprop --dialog-padding - Padding for header, body, and footer sections\n * @cssprop --dialog-gap - Gap between footer action buttons\n * @cssprop --dialog-backdrop - Backdrop overlay color\n * @cssprop --dialog-max-width - Maximum panel width (overridden by size prop)\n *\n * @part dialog - Dialog root container.\n * @part overlay - Overlay backdrop element.\n * @part panel - Panel container.\n * @part header - Header container.\n * @part title - Title text element.\n * @part close - Close action control.\n * @part body - Body content container.\n * @part footer - Footer container.\n * @example\n * ```html\n * <ore-dialog label=\"Confirm action\" dismissible>\n *   <p>Are you sure you want to delete this item?</p>\n *   <div slot=\"footer\">\n *     <ore-button variant=\"ghost\" id=\"cancel\">Cancel</ore-button>\n *     <ore-button color=\"error\" id=\"confirm\">Delete</ore-button>\n *   </div>\n * </ore-dialog>\n *\n * <script type=\"module\">\n *   import '@vielzeug/refine/dialog';\n *   const dialog = document.querySelector('ore-dialog');\n *   document.querySelector('#open-btn').addEventListener('click', () => {\n *     dialog.setAttribute('open', '');\n *   });\n *   document.querySelector('#cancel').addEventListener('click', () => {\n *     dialog.removeAttribute('open');\n *   });\n * </script>\n * ```\n */\n\nexport const DIALOG_TAG = 'ore-dialog' as const;\ndefine<OreDialogProps>(DIALOG_TAG, {\n  props: {\n    backdrop: prop.string<DialogBackdrop>(),\n    'default-open': prop.bool(false),\n    dismissible: prop.bool(false),\n    elevation: prop.string<DialogElevation>(),\n    'initial-focus': prop.string(),\n    label: prop.string(),\n    open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n    padding: prop.string<PaddingSize>(),\n    persistent: prop.bool(false),\n    'return-focus': prop.bool(true),\n    rounded: prop.string<RoundedSize | ''>(),\n    size: prop.oneOf(['sm', 'md', 'lg', 'xl', 'full'] as const, 'md'),\n  },\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreDialogEvents>();\n    const slots = useSlots();\n\n    const dialogRef = ref<HTMLDialogElement>();\n    const hasHeader = () => slots.has('header').value || !!props.label.value || props.dismissible.value;\n    const hasFooter = () => slots.has('footer').value;\n\n    const { closeWithAnimation, overlay, requestClose, setupNativeListeners } = useDialogControl({\n      defaultOpen: props['default-open'],\n      dialogRef,\n      getPanelEl: () => dialogRef.value?.querySelector<HTMLElement>('.panel'),\n      host: el,\n      initialFocus: props['initial-focus'],\n      isPersistent: () => Boolean(props.persistent.value),\n      onCleanup,\n      onEvent,\n      onNativeClose: (reason) => emit('open-change', { open: false, reason }),\n      onOpen: (reason) => emit('open-change', { open: true, reason }),\n      openProp: props.open,\n      performClose: () => {\n        closeWithAnimation();\n      },\n      returnFocus: props['return-focus'],\n    });\n\n    const handleDismiss = () => {\n      requestClose('trigger');\n    };\n\n    onMounted(() => {\n      const dialog = dialogRef.value;\n\n      if (!dialog) return;\n\n      setupNativeListeners();\n\n      return () => {\n        overlay.dispose();\n      };\n    });\n\n    return html`\n      <dialog ref=${dialogRef} class=\"dialog\" part=\"dialog\" aria-label=\"${props.label}\" aria-modal=\"true\">\n        <div class=\"overlay\" part=\"overlay\" aria-hidden=\"true\"></div>\n        <div class=\"panel\" part=\"panel\" data-size=\"${props.size}\">\n          <div class=\"header\" part=\"header\" ?hidden=${() => !hasHeader()}>\n            <slot name=\"header\">\n              <span class=\"title\" part=\"title\">${props.label}</span>\n            </slot>\n            <button\n              class=\"close\"\n              part=\"close\"\n              type=\"button\"\n              aria-label=\"Close dialog\"\n              ?hidden=${() => !props.dismissible.value}\n              @click=${handleDismiss}>\n              <ore-icon name=\"x\" size=\"16\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n            </button>\n          </div>\n          <div class=\"body\" part=\"body\">\n            <slot></slot>\n          </div>\n          <div class=\"footer\" part=\"footer\" ?hidden=${() => !hasFooter()}>\n            <slot name=\"footer\"></slot>\n          </div>\n        </div>\n      </dialog>\n    `;\n  },\n  styles: [roundedVariantMixin, coarsePointerMixin, componentStyles],\n});\n","@layer refine.base {\n  :host {\n    --_backdrop-bg: var(--drawer-backdrop-bg, color-mix(in oklch, var(--color-canvas) 40%, transparent));\n    --_backdrop-filter: none;\n    --_panel-bg: var(--drawer-bg, var(--color-canvas));\n    --_panel-blur: var(--drawer-panel-blur, var(--blur-md));\n    --_panel-shadow: var(--drawer-shadow, var(--shadow-xl));\n    --_panel-border-color: var(--color-divider);\n    --_panel-bleed: var(--size-8);\n    --_drag-handle-inset: calc(var(--size-1) * -1);\n\n    display: contents;\n  }\n\n  dialog {\n    all: unset;\n    position: fixed;\n    inset: 0;\n    box-sizing: border-box;\n    display: flex;\n    width: 100%;\n    max-width: 100%;\n    height: 100%;\n    max-height: 100%;\n    pointer-events: none;\n    transition:\n      display 200ms allow-discrete,\n      overlay 200ms allow-discrete;\n  }\n\n  dialog:not([open]) {\n    display: none;\n  }\n\n  dialog:not([open]) .panel {\n    display: none;\n  }\n\n  dialog[open] {\n    display: flex;\n    pointer-events: auto;\n  }\n\n  dialog::backdrop {\n    background: var(--_backdrop-bg);\n    opacity: 1;\n    backdrop-filter: var(--_backdrop-filter);\n    transition:\n      display 200ms allow-discrete,\n      overlay 200ms allow-discrete,\n      opacity var(--transition-normal),\n      backdrop-filter var(--transition-normal);\n\n    @starting-style {\n      opacity: 0;\n      backdrop-filter: blur(0);\n    }\n  }\n\n  dialog.closing::backdrop {\n    opacity: 0;\n    backdrop-filter: blur(0);\n    transition:\n      opacity 300ms var(--ease-in-out),\n      backdrop-filter 300ms var(--ease-in-out),\n      overlay 300ms allow-discrete,\n      display 300ms allow-discrete;\n  }\n\n  .panel {\n    position: absolute;\n    box-sizing: border-box;\n    display: flex;\n    flex-direction: column;\n    overflow: visible;\n    background: var(--_panel-bg);\n    border: var(--border) solid var(--_panel-border-color);\n    box-shadow: var(--_panel-shadow);\n    opacity: 1;\n    backdrop-filter: blur(var(--_panel-blur));\n    transform: translate3d(0, 0, 0);\n    transition:\n      opacity var(--transition-normal),\n      transform 300ms var(--ease-move);\n\n    @starting-style {\n      opacity: 0;\n      transform: var(--_panel-exit-transform, translate3d(0, 0, 0));\n    }\n  }\n\n  dialog.closing .panel {\n    opacity: 0;\n    transform: var(--_panel-exit-transform, translate3d(0, 0, 0));\n  }\n\n  /* left */\n  :host([placement='left']) .panel {\n    --_panel-exit-transform: translateX(calc(-100% - var(--_panel-bleed)));\n\n    inset-block: 0;\n    inset-inline-start: 0;\n    width: calc(var(--drawer-size, 20rem) + var(--_panel-bleed));\n    max-width: calc(100dvw + var(--_panel-bleed));\n    padding-inline-start: var(--_panel-bleed);\n    margin-inline-start: calc(var(--_panel-bleed) * -1);\n    border-block: none;\n    border-inline-start: none;\n  }\n\n  /* right (default) */\n  :host(:not([placement])) .panel,\n  :host([placement='right']) .panel {\n    --_panel-exit-transform: translateX(calc(100% + var(--_panel-bleed)));\n\n    inset-block: 0;\n    inset-inline-end: 0;\n    width: calc(var(--drawer-size, 20rem) + var(--_panel-bleed));\n    max-width: calc(100dvw + var(--_panel-bleed));\n    padding-inline-end: var(--_panel-bleed);\n    margin-inline-end: calc(var(--_panel-bleed) * -1);\n    border-block: none;\n    border-inline-end: none;\n  }\n\n  /* top */\n  :host([placement='top']) .panel {\n    --_panel-exit-transform: translateY(calc(-100% - var(--_panel-bleed)));\n\n    inset-block-start: 0;\n    inset-inline: 0;\n    height: calc(var(--drawer-size, 16rem) + var(--_panel-bleed));\n    max-height: calc(100dvh + var(--_panel-bleed));\n    padding-block-start: var(--_panel-bleed);\n    margin-block-start: calc(var(--_panel-bleed) * -1);\n    border-block-start: none;\n    border-inline: none;\n  }\n\n  /* bottom */\n  :host([placement='bottom']) .panel {\n    --_panel-exit-transform: translateY(calc(100% + var(--_panel-bleed)));\n\n    inset-block-end: 0;\n    inset-inline: 0;\n    height: calc(var(--drawer-size, 16rem) + var(--_panel-bleed));\n    max-height: calc(100dvh + var(--_panel-bleed));\n    padding-block-end: var(--_panel-bleed);\n    margin-block-end: calc(var(--_panel-bleed) * -1);\n    border-block-end: none;\n    border-inline: none;\n  }\n\n  /* RTL overrides */\n  :host(:dir(rtl)[placement='left']) .panel {\n    --_panel-exit-transform: translateX(calc(100% + var(--_panel-bleed)));\n  }\n\n  :host(:dir(rtl)[placement='right']) .panel,\n  :host(:dir(rtl):not([placement])) .panel {\n    --_panel-exit-transform: translateX(calc(-100% - var(--_panel-bleed)));\n  }\n\n  /* Size utilities */\n  :host([size='sm']) {\n    --drawer-size: 14rem;\n  }\n\n  :host([size='lg']) {\n    --drawer-size: 32rem;\n  }\n\n  :host([size='full']) {\n    --drawer-size: 100%;\n  }\n\n  :host([size='full']) .panel {\n    width: calc(100% + var(--_panel-bleed));\n    max-width: none;\n    height: calc(100% + var(--_panel-bleed));\n    max-height: none;\n    border: none;\n  }\n\n  /* Header / Body / Footer */\n  .header {\n    display: flex;\n    flex-shrink: 0;\n    gap: var(--size-2);\n    align-items: center;\n    padding: var(--size-4);\n    border-bottom: var(--border) solid var(--color-contrast-200);\n  }\n\n  .header-title {\n    flex: 1;\n    min-width: 0;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    font-size: var(--text-lg);\n    font-weight: var(--font-semibold);\n    white-space: nowrap;\n  }\n\n  .body {\n    flex: 1;\n    padding: var(--size-4);\n    overflow-y: auto;\n  }\n\n  .footer {\n    display: flex;\n    flex-shrink: 0;\n    gap: var(--size-2);\n    justify-content: flex-end;\n    padding: var(--size-4);\n    border-top: var(--border) solid var(--color-contrast-200);\n  }\n\n  .header[hidden],\n  .footer[hidden],\n  .close-btn[hidden] {\n    display: none;\n  }\n\n  .close-btn {\n    all: unset;\n    box-sizing: border-box;\n    display: inline-flex;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    width: var(--size-8);\n    height: var(--size-8);\n    margin-inline-start: auto;\n    color: var(--color-contrast-500);\n    cursor: pointer;\n    border-radius: var(--rounded-sm);\n    transition:\n      background var(--transition-fast),\n      color var(--transition-fast);\n  }\n\n  .close-btn:hover {\n    color: var(--color-contrast-800);\n    background: var(--color-contrast-200);\n  }\n\n  .close-btn:active {\n    opacity: 0.8;\n  }\n\n  /* Drag handle for mobile/touch swipe-to-close */\n  .drag-handle {\n    position: absolute;\n    z-index: 10;\n    pointer-events: all;\n    touch-action: none;\n    cursor: grab;\n  }\n\n  .drag-handle:active {\n    cursor: grabbing;\n  }\n\n  /* Horizontal drawers (left/right) — drag handle on the opposite edge */\n  :host([placement='left']) .drag-handle,\n  :host(:not([placement])) .drag-handle,\n  :host([placement='right']) .drag-handle {\n    top: 50%;\n    width: var(--_panel-bleed);\n    height: 3.5rem;\n    translate: 0 -50%;\n  }\n\n  /* Left drawer — handle on the right (opposite side) */\n  :host([placement='left']) .drag-handle {\n    right: calc(var(--_panel-bleed) * -1);\n  }\n\n  /* Right drawer (default) — handle on the left (opposite side) */\n  :host([placement='right']) .drag-handle,\n  :host(:not([placement])) .drag-handle {\n    left: calc(var(--_panel-bleed) * -1);\n  }\n\n  /* Vertical drawers (top/bottom) — drag handle on the opposite edge */\n  :host([placement='top']) .drag-handle,\n  :host([placement='bottom']) .drag-handle {\n    left: 50%;\n    width: 3.5rem;\n    height: var(--_panel-bleed);\n    translate: -50% 0;\n  }\n\n  /* Top drawer — handle at bottom (opposite side) */\n  :host([placement='top']) .drag-handle {\n    bottom: calc(var(--_panel-bleed) * -1);\n  }\n\n  /* Bottom drawer — handle at top (opposite side) */\n  :host([placement='bottom']) .drag-handle {\n    top: calc(var(--_panel-bleed) * -1);\n  }\n\n  /* Inset drag-handle placement keeps the handle fully inside the panel. */\n  :host([drag-handle-placement='inset'][placement='left']) .drag-handle {\n    right: var(--_drag-handle-inset);\n  }\n\n  :host([drag-handle-placement='inset'][placement='right']) .drag-handle,\n  :host([drag-handle-placement='inset']:not([placement])) .drag-handle {\n    left: var(--_drag-handle-inset);\n  }\n\n  :host([drag-handle-placement='inset'][placement='top']) .drag-handle {\n    bottom: var(--_drag-handle-inset);\n  }\n\n  :host([drag-handle-placement='inset'][placement='bottom']) .drag-handle {\n    top: var(--_drag-handle-inset);\n  }\n\n  /* Visual indicator — subtle bar in the center */\n  .drag-handle::before {\n    position: absolute;\n    inset: 50%;\n    content: '';\n    background: var(--color-contrast-400);\n    border-radius: var(--rounded-full);\n    opacity: 0.6;\n    translate: -50% -50%;\n    transition:\n      background var(--transition-fast),\n      opacity var(--transition-fast),\n      transform var(--transition-fast);\n  }\n\n  :host([placement='left']) .drag-handle::before,\n  :host([placement='right']) .drag-handle::before,\n  :host(:not([placement])) .drag-handle::before {\n    width: 5px;\n    height: 2.5rem;\n  }\n\n  :host([placement='top']) .drag-handle::before,\n  :host([placement='bottom']) .drag-handle::before {\n    width: 2.5rem;\n    height: 5px;\n  }\n\n  .drag-handle:hover::before {\n    background: var(--color-contrast-600);\n    opacity: 0.9;\n    transform: scale(1.15);\n  }\n\n  .close-btn:focus-visible {\n    outline: var(--focus-ring);\n  }\n\n  @media (width <= 640px) {\n    :host([placement='left']) .panel,\n    :host(:not([placement])) .panel,\n    :host([placement='right']) .panel {\n      width: calc(min(var(--drawer-size, 20rem), calc(100vw - var(--size-2))) + var(--_panel-bleed));\n      max-width: calc(100vw - var(--size-2) + var(--_panel-bleed));\n    }\n\n    :host([placement='top']) .panel,\n    :host([placement='bottom']) .panel {\n      height: calc(min(var(--drawer-size, 16rem), calc(100dvh - var(--size-2))) + var(--_panel-bleed));\n      max-height: calc(100dvh - var(--size-2) + var(--_panel-bleed));\n    }\n\n    .header,\n    .body,\n    .footer {\n      padding: var(--size-3);\n    }\n  }\n}\n\n@layer refine.config {\n  :host([backdrop='blur']) {\n    --_backdrop-filter: blur(var(--blur-xs));\n  }\n\n  :host([backdrop='transparent']) {\n    --_backdrop-bg: transparent;\n  }\n}\n","import { createPanGesture, type PanAxis, type PanGesture, type PanGestureEndDetail } from '@vielzeug/gesture';\nimport {\n  createStableId,\n  define,\n  getHost,\n  html,\n  onCleanup,\n  onEvent,\n  onMounted,\n  prop,\n  ref,\n  useEmit,\n  useSlots,\n} from '@vielzeug/ore';\nimport { signal } from '@vielzeug/ripple';\n\nimport type { OverlayOpenChangeDetail } from '../../core';\nimport '../../content/icon/icon';\nimport { coarsePointerMixin, forcedColorsMixin, reducedMotionMixin } from '../../styles';\nimport { useDialogControl } from '../shared/use-dialog';\nimport styles from './drawer.css?inline';\n\ntype DrawerPlacement = 'left' | 'right' | 'top' | 'bottom';\ntype DrawerSize = 'sm' | 'lg' | 'full';\ntype DrawerBackdrop = 'opaque' | 'blur' | 'transparent';\ntype DrawerDragHandlePlacement = 'outside' | 'inset';\ntype DrawerSwipeConfig = {\n  axis: PanAxis;\n  closingDistance: (distance: number) => number;\n  translate: (distance: number) => string;\n};\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n  value == null ? undefined : value === '' || value === 'true';\n\nconst drawerSwipeConfig: Record<DrawerPlacement, DrawerSwipeConfig> = {\n  bottom: {\n    axis: 'y',\n    closingDistance: (distance) => Math.max(0, distance),\n    translate: (distance) => `translateY(${distance}px)`,\n  },\n  left: {\n    axis: 'x',\n    closingDistance: (distance) => Math.max(0, -distance),\n    translate: (distance) => `translateX(${distance}px)`,\n  },\n  right: {\n    axis: 'x',\n    closingDistance: (distance) => Math.max(0, distance),\n    translate: (distance) => `translateX(${distance}px)`,\n  },\n  top: {\n    axis: 'y',\n    closingDistance: (distance) => Math.max(0, -distance),\n    translate: (distance) => `translateY(${distance}px)`,\n  },\n};\n\n/** Element interface exposing the imperative API for `ore-drawer`. */\nexport interface DrawerElement extends HTMLElement, Omit<OreDrawerProps, 'title'> {\n  /** Programmatically close the drawer with the exit animation. */\n  hide(): void;\n  /** Programmatically open the drawer. Equivalent to setting `open`. */\n  show(): void;\n}\n\n/** Drawer component properties */\n\nexport type OreDrawerEvents = {\n  'open-change': OverlayOpenChangeDetail;\n};\n\nexport type OreDrawerProps = {\n  /** Backdrop style — 'opaque' (default), 'blur', or 'transparent' */\n  backdrop?: DrawerBackdrop;\n  /** Initial uncontrolled open state. Ignored when `open` is set. */\n  'default-open'?: boolean;\n  /** Show the close (×) button in the header (default: true) */\n  dismissible?: boolean;\n  /** Drag handle position used for swipe-to-close gestures */\n  'drag-handle-placement'?: DrawerDragHandlePlacement;\n  /**\n   * CSS selector for the element inside the drawer that should receive focus on open.\n   * Defaults to native dialog focus management (first focusable element).\n   * @example '#submit-btn' | 'input[name=\"email\"]'\n   */\n  'initial-focus'?: string;\n  /**\n   * Invisible accessible label for the dialog (`aria-label`).\n   * Use when the drawer has no visible title (e.g. image-only content).\n   * When omitted, `aria-labelledby` points to the visible header title instead.\n   */\n  label?: string;\n  /** Controlled open state */\n  open?: boolean;\n  /** When true, backdrop clicks do not close the drawer (default: false) */\n  persistent?: boolean;\n  /** Side from which the drawer slides in */\n  placement?: DrawerPlacement;\n  /**\n   * When true (default), focus returns to the triggering element after the drawer closes.\n   * Set to false to manage focus manually.\n   */\n  'return-focus'?: boolean;\n  /** Drawer width/height preset */\n  size?: DrawerSize;\n  /**\n   * Visible title text rendered inside the header.\n   * Used as the dialog's accessible label via `aria-labelledby` when `label` is not set.\n   */\n  title?: string;\n};\n\n/**\n * A panel that slides in from any edge of the screen, built on the native `<dialog>` element.\n *\n * @element ore-drawer\n *\n * @attr {boolean} open - Controlled open state\n * @attr {boolean} default-open - Initial uncontrolled open state\n * @attr {string} placement - 'left' | 'right' (default) | 'top' | 'bottom'\n * @attr {string} size - 'sm' | 'lg' | 'full'\n * @attr {string} title - Visible header title text\n * @attr {string} label - Invisible aria-label (for drawers without a visible title)\n * @attr {boolean} dismissible - Show the close (×) button (default: true)\n * @attr {string} drag-handle-placement - 'outside' (default) | 'inset'\n * @attr {string} backdrop - Backdrop style: 'opaque' (default) | 'blur' | 'transparent'\n * @attr {boolean} persistent - Prevent backdrop-click from closing (default: false)\n *\n * @fires open-change - When the drawer state changes. detail: { open, reason }\n *\n * @slot header - Drawer header content\n * @slot - Main body content\n * @slot footer - Drawer footer content\n *\n * @cssprop --drawer-backdrop-bg - Backdrop background color\n * @cssprop --drawer-bg - Panel background color\n * @cssprop --drawer-size - Panel width (horizontal) or height (vertical)\n * @cssprop --drawer-shadow - Panel box-shadow\n * @cssprop --drawer-panel-blur - Panel backdrop blur amount\n *\n * @part drag-handle - Drawer drag handle.\n * @part panel - Panel container.\n * @part header - Header container.\n * @part close-btn - Close button.\n * @part body - Body content container.\n * @part footer - Footer container.\n * @example\n * ```html\n * <!-- With visible title -->\n * <ore-drawer open title=\"Settings\" placement=\"right\">\n *   <p>Settings content here.</p>\n * </ore-drawer>\n *\n * <!-- With custom header slot -->\n * <ore-drawer open placement=\"right\">\n *   <span slot=\"header\">Settings</span>\n *   <p>Settings content here.</p>\n * </ore-drawer>\n * ```\n */\n\nexport const DRAWER_TAG = 'ore-drawer' as const;\ndefine<OreDrawerProps>(DRAWER_TAG, {\n  props: {\n    backdrop: prop.string<DrawerBackdrop>(),\n    'default-open': prop.bool(false),\n    dismissible: prop.bool(true),\n    'drag-handle-placement': prop.oneOf(['outside', 'inset'] as const, 'outside'),\n    'initial-focus': prop.string(),\n    label: prop.string(),\n    open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n    persistent: prop.bool(false),\n    placement: prop.oneOf(['left', 'right', 'top', 'bottom'] as const, 'right'),\n    'return-focus': prop.bool(true),\n    size: prop.string<DrawerSize>(),\n    title: prop.string(),\n  },\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreDrawerEvents>();\n    const slots = useSlots();\n\n    const drawerLabelId = createStableId('drawer-label');\n    const dialogRef = ref<HTMLDialogElement>();\n    const panelRef = ref<HTMLDivElement>();\n\n    // Drag-to-close state\n    const isSwipeClosing = signal(false);\n    let swipe: PanGesture | undefined;\n    let swipeCloseTimer: ReturnType<typeof setTimeout> | undefined;\n\n    const getHeaderText = () => props.label.value ?? props.title.value ?? '';\n    const hasHeaderTitle = () => slots.has('header').value || !!getHeaderText();\n\n    // Header is visible when there is slot content, a text label, or a close button.\n    const hasHeader = () => hasHeaderTitle() || props.dismissible.value;\n    const hasFooter = () => slots.has('footer').value;\n\n    const getPlacement = (): DrawerPlacement => props.placement.value || 'right';\n\n    const getSwipeConfig = (): DrawerSwipeConfig => drawerSwipeConfig[getPlacement()];\n\n    const getSnapThreshold = (panel: HTMLElement, axis: PanAxis) => {\n      const panelSize = axis === 'x' ? panel.offsetWidth : panel.offsetHeight;\n\n      return Math.min(96, Math.max(36, panelSize * 0.18));\n    };\n\n    const shouldCommitSwipeClose = (distance: number, threshold: number) => {\n      return getSwipeConfig().closingDistance(distance) >= threshold;\n    };\n\n    const finalizeSwipeClose = (panel: HTMLElement) => {\n      if (!isSwipeClosing.value) return;\n\n      if (swipeCloseTimer) {\n        clearTimeout(swipeCloseTimer);\n        swipeCloseTimer = undefined;\n      }\n\n      const dialog = dialogRef.value;\n\n      if (!dialog) {\n        isSwipeClosing.value = false;\n\n        return;\n      }\n\n      dialog.style.transition = 'none';\n      panel.style.opacity = '0';\n      panel.style.visibility = 'hidden';\n      void dialog.offsetWidth;\n\n      requestClose('swipe');\n    };\n\n    const startSwipeClose = (panel: HTMLElement, swipe: DrawerSwipeConfig, committedDistance: number) => {\n      if (isSwipeClosing.value) return;\n\n      isSwipeClosing.value = true;\n\n      const panelSize = swipe.axis === 'x' ? panel.offsetWidth : panel.offsetHeight;\n      // Preserve overshoot so closing continues from the dragged position instead of snapping back.\n      const exitDistance =\n        committedDistance >= 0 ? Math.max(committedDistance, panelSize) : Math.min(committedDistance, -panelSize);\n      const exitTransform = swipe.translate(exitDistance);\n\n      // Commit the current drag position first so the magnetic snap continues\n      // from the finger instead of jumping back to rest.\n      panel.style.transition = 'transform 180ms cubic-bezier(0.2, 0.9, 0.2, 1), opacity 180ms ease-out';\n      void panel.offsetWidth;\n\n      const onExitTransitionEnd = (ev: TransitionEvent) => {\n        if (ev.target !== panel || ev.propertyName !== 'transform') return;\n\n        panel.removeEventListener('transitionend', onExitTransitionEnd);\n        finalizeSwipeClose(panel);\n      };\n\n      panel.addEventListener('transitionend', onExitTransitionEnd);\n\n      const durationMs = parseFloat(getComputedStyle(panel).transitionDuration) * 1000;\n\n      swipeCloseTimer = setTimeout(() => {\n        panel.removeEventListener('transitionend', onExitTransitionEnd);\n        finalizeSwipeClose(panel);\n      }, durationMs + 50);\n\n      panel.style.transform = exitTransform;\n      panel.style.opacity = '0.2';\n    };\n\n    const resetPanelDragStyles = (panel: HTMLElement) => {\n      if (swipeCloseTimer) {\n        clearTimeout(swipeCloseTimer);\n        swipeCloseTimer = undefined;\n      }\n\n      // Re-enable transitions so the snap-back or exit animates.\n      panel.style.transition = '';\n      panel.style.transform = '';\n      panel.style.opacity = '';\n      panel.style.visibility = '';\n      isSwipeClosing.value = false;\n    };\n\n    const handleSwipeEnd = ({ distance, reason }: PanGestureEndDetail): void => {\n      const panel = panelRef.value;\n\n      if (!panel) return;\n\n      const threshold = getSnapThreshold(panel, getSwipeConfig().axis);\n\n      if (reason === 'release' && shouldCommitSwipeClose(distance, threshold)) {\n        startSwipeClose(panel, getSwipeConfig(), distance);\n\n        return;\n      }\n\n      resetPanelDragStyles(panel);\n    };\n\n    // ────────────────────────────────────────────────────────────────\n    // Overlay State Management\n    // ────────────────────────────────────────────────────────────────\n\n    const { closeWithAnimation, handleCancel, overlay, requestClose, watchOpenProp } = useDialogControl({\n      beforeOpen: (dialog) => {\n        // Clear any inline drag styles from a previous swipe-close so the CSS\n        // entry animation starts from the correct base state.\n        const panel = panelRef.value;\n\n        if (panel) resetPanelDragStyles(panel);\n\n        void dialog;\n      },\n      closeRequestDetail: (_reason) => ({ placement: props.placement.value ?? 'right' }),\n      defaultOpen: props['default-open'],\n      dialogRef,\n      getPanelEl: () => panelRef.value,\n      host: el,\n      initialFocus: props['initial-focus'],\n      isPersistent: () => Boolean(props.persistent.value),\n      onCleanup,\n      onEvent,\n      onNativeClose: (reason) => {\n        const panelEl = panelRef.value;\n\n        // For swipe-close, keep the panel hidden and off-screen until the next\n        // open cycle — resetting inline styles during native close can produce\n        // a visible frame at the rest position on some browsers.\n        if (panelEl && reason !== 'swipe') resetPanelDragStyles(panelEl);\n\n        const dialog = dialogRef.value;\n\n        if (dialog) dialog.style.transition = '';\n\n        emit('open-change', { open: false, reason });\n      },\n      onOpen: (reason) => emit('open-change', { open: true, reason }),\n      openProp: props.open,\n      performClose: (dialog, reason) => {\n        if (reason === 'swipe') {\n          dialog.close();\n        } else {\n          closeWithAnimation();\n        }\n      },\n      returnFocus: props['return-focus'],\n    });\n\n    const handleCloseButtonClick = () => {\n      requestClose('trigger');\n    };\n\n    // ────────────────────────────────────────────────────────────────\n    // Lifecycle: Setup Drawer Integration\n    // ────────────────────────────────────────────────────────────────\n\n    onMounted(() => {\n      const dialog = dialogRef.value;\n\n      if (!dialog) return;\n\n      // Expose imperative API\n      const drawerEl = el as DrawerElement;\n\n      drawerEl.show = () => {\n        overlay.open('programmatic');\n      };\n\n      drawerEl.hide = () => {\n        overlay.close('programmatic');\n      };\n\n      // ────────────────────────────────────────────────────────────\n      // Event Handlers: Cancel, Backdrop Click\n      // ────────────────────────────────────────────────────────────\n      // `handleCancel` (Escape via the native `cancel` event) is provided by\n      // `useDialogControl` above — drawer only needs its own backdrop-click\n      // handler since it has swipe-to-dismiss logic the shared dialog helper\n      // doesn't know about.\n\n      const handleBackdropClick = (e: MouseEvent) => {\n        if (props.persistent.value) return;\n\n        if (swipe?.active || isSwipeClosing.value) return;\n\n        if (e.target !== dialog) return; // Click inside panel\n\n        requestClose('outsideClick');\n      };\n\n      watchOpenProp();\n\n      onEvent(dialog, 'cancel', handleCancel);\n      onEvent(dialog, 'click', handleBackdropClick);\n\n      // Drag-to-close handlers — scoped to the handle element only so interactions\n      // with panel content don't accidentally start a drag.\n      const panel = panelRef.value;\n      const dragHandleEl = panel?.querySelector<HTMLElement>('[part=\"drag-handle\"]');\n\n      if (dragHandleEl) {\n        swipe = createPanGesture(dragHandleEl, {\n          axis: () => getSwipeConfig().axis,\n          disabled: () => isSwipeClosing.value,\n          onEnd: handleSwipeEnd,\n          onMove: ({ distance }) => {\n            const currentPanel = panelRef.value;\n\n            if (!currentPanel) return;\n\n            const swipeConfig = getSwipeConfig();\n            const threshold = getSnapThreshold(currentPanel, swipeConfig.axis);\n            const closingDistance = swipeConfig.closingDistance(distance);\n            const progress = Math.min(closingDistance / threshold, 1);\n\n            currentPanel.style.transition = 'none';\n            currentPanel.style.transform = swipeConfig.translate(distance);\n            currentPanel.style.opacity = String(1 - progress * 0.4);\n          },\n        });\n      }\n\n      return () => {\n        swipe?.dispose();\n        swipe = undefined;\n        overlay.dispose();\n      };\n    });\n\n    return html`\n      <dialog\n        ref=${dialogRef}\n        aria-modal=\"true\"\n        aria-label=\"${() => props.label.value ?? null}\"\n        aria-labelledby=\"${() => (!props.label.value ? drawerLabelId : null)}\">\n        <div class=\"panel\" part=\"panel\" ref=${panelRef}>\n          <div class=\"drag-handle\" part=\"drag-handle\" aria-label=\"Drag to close\" role=\"button\"></div>\n          <div class=\"header\" part=\"header\" ?hidden=${() => !hasHeader()}>\n            <span class=\"header-title\" id=\"${drawerLabelId}\" ?hidden=${() => !hasHeaderTitle()}>\n              <slot name=\"header\">${() => getHeaderText()}</slot>\n            </span>\n            <button\n              class=\"close-btn\"\n              part=\"close-btn\"\n              type=\"button\"\n              aria-label=\"Close\"\n              ?hidden=${() => !props.dismissible.value}\n              @click=${handleCloseButtonClick}>\n              <ore-icon name=\"x\" size=\"16\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n            </button>\n          </div>\n          <div class=\"body\" part=\"body\">\n            <slot></slot>\n          </div>\n          <div class=\"footer\" part=\"footer\" ?hidden=${() => !hasFooter()}>\n            <slot name=\"footer\"></slot>\n          </div>\n        </div>\n      </dialog>\n    `;\n  },\n  styles: [forcedColorsMixin, coarsePointerMixin, reducedMotionMixin, styles],\n});\n","@layer refine.base {\n  :host {\n    --_menu-panel-bg: var(--menu-panel-bg, var(--color-canvas));\n    --_menu-panel-border-color: var(--menu-panel-border-color, var(--color-divider));\n    --_menu-panel-blur: var(--menu-panel-blur, var(--blur-md));\n    --_menu-panel-shadow: var(--menu-panel-shadow, var(--shadow-xl));\n\n    position: relative;\n    display: inline-block;\n  }\n\n  /* ========================================\n       Menu Panel\n       ======================================== */\n\n  .menu-panel {\n    position: fixed;\n    inset-inline-start: 0;\n    top: 0;\n    z-index: calc(var(--z-popover) + 1);\n    box-sizing: border-box;\n    min-width: var(--menu-panel-min-width, 10rem);\n    max-height: var(--menu-panel-max-height, min(70vh, 32rem));\n    padding: var(--_panel-padding, var(--size-1));\n    margin: 0;\n    overflow-y: auto;\n    pointer-events: none;\n    background: var(--_menu-panel-bg);\n    border: var(--border) solid var(--_menu-panel-border-color);\n    border-radius: var(--menu-panel-radius, var(--rounded-lg));\n    box-shadow: var(--_menu-panel-shadow);\n    opacity: 0;\n    backdrop-filter: blur(var(--_menu-panel-blur));\n    transform: translateY(var(--overlay-enter-translate-y)) scale(var(--overlay-enter-scale));\n    transform-origin: top left;\n    transition:\n      opacity 100ms var(--ease-spring),\n      transform 100ms var(--ease-spring),\n      display 100ms allow-discrete,\n      overlay 100ms allow-discrete;\n  }\n\n  .menu-panel[data-placement='top-start'],\n  .menu-panel[data-placement='top'],\n  .menu-panel[data-placement='top-end'] {\n    transform-origin: bottom left;\n  }\n\n  .menu-panel[data-placement='bottom-end'],\n  .menu-panel[data-placement='right-start'],\n  .menu-panel[data-placement='right'] {\n    transform-origin: top right;\n  }\n\n  .menu-panel[data-open] {\n    pointer-events: auto;\n    opacity: 1;\n    transform: translateY(0) scale(1);\n    transition:\n      opacity 150ms var(--ease-spring),\n      transform 150ms var(--ease-spring),\n      display 150ms allow-discrete,\n      overlay 150ms allow-discrete;\n\n    @starting-style {\n      opacity: 0;\n      transform: translateY(var(--overlay-enter-translate-y)) scale(var(--overlay-enter-scale));\n    }\n  }\n\n  /* ========================================\n       Menu Items (slotted ore-menu-item)\n       ======================================== */\n\n  ::slotted(ore-menu-item) {\n    display: block;\n  }\n\n  ::slotted(ore-menu-separator) {\n    display: block;\n  }\n}\n","@layer refine.base {\n  :host {\n    --_menu-color: var(--menu-item-color, var(--_theme-base, var(--color-primary)));\n    --_hover-bg: var(--menu-item-hover-bg, var(--color-contrast-100));\n    --_focus-color: var(--menu-item-focus-color, var(--_menu-color));\n    --_focus-bg: var(--menu-item-focus-bg, color-mix(in oklch, var(--_menu-color) 12%, var(--color-contrast-100)));\n    --_selection-bg: var(\n      --menu-item-selection-bg,\n      color-mix(in oklch, var(--color-contrast-900) 5%, var(--color-canvas))\n    );\n    --_checked-color: var(--menu-item-checked-color, var(--_menu-color));\n    --_checked-bg: var(--menu-item-checked-bg, color-mix(in oklch, var(--_menu-color) 18%, var(--color-canvas)));\n\n    display: block;\n    outline: none;\n  }\n\n  .item {\n    display: flex;\n    gap: var(--_gap, var(--size-2));\n    align-items: center;\n    padding: var(--_item-padding, var(--size-1-5) var(--size-3));\n    font-size: var(--_font-size, var(--text-sm));\n    line-height: var(--leading-normal);\n    white-space: nowrap;\n    cursor: pointer;\n    user-select: none;\n    border-radius: 0;\n    transition:\n      background var(--transition-fast),\n      color var(--transition-fast);\n  }\n\n  :host(:first-of-type) .item {\n    border-radius: var(--rounded-sm) var(--rounded-sm) 0 0;\n  }\n\n  :host(:last-child) .item {\n    border-radius: 0 0 var(--rounded-sm) var(--rounded-sm);\n  }\n\n  :host(:first-of-type:last-child) .item {\n    border-radius: var(--rounded-sm);\n  }\n\n  :host(:not([disabled])) .item:hover {\n    background: var(--_hover-bg);\n  }\n\n  :host(:focus-visible) .item {\n    color: var(--_focus-color);\n    background: var(--_focus-bg);\n  }\n\n  .item.is-checked {\n    font-weight: var(--font-medium);\n    color: var(--_checked-color);\n  }\n\n  :host([disabled]) .item {\n    color: var(--color-contrast-400);\n    pointer-events: none;\n    cursor: not-allowed;\n    opacity: 0.6;\n  }\n\n  .icon-slot {\n    display: contents;\n  }\n\n  .item-check {\n    display: inline-flex;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    width: 1.25rem;\n    color: currentcolor;\n  }\n\n  /* CSS-based check/radio indicator — no Unicode characters */\n  .item-check::before {\n    display: block;\n    width: 0.875rem;\n    height: 0.875rem;\n    content: '';\n    border: 1.5px solid currentcolor;\n    transition:\n      background var(--transition-fast),\n      border-color var(--transition-fast);\n  }\n\n  .item.is-checkbox .item-check::before {\n    border-radius: 2px;\n  }\n\n  .item.is-radio .item-check::before {\n    border-radius: 50%;\n  }\n\n  .item.is-checked .item-check::before {\n    background: currentcolor;\n  }\n\n  /* Radio checked: filled dot via inset box-shadow */\n  .item.is-radio.is-checked .item-check::before {\n    background: transparent;\n    box-shadow: inset 0 0 0 3px currentcolor;\n  }\n\n  .item-label {\n    flex: 1;\n    min-width: 0;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n  }\n}\n\n@media (pointer: coarse) {\n  .item {\n    padding: var(--size-2-5) var(--size-3);\n  }\n}\n","@layer refine.base {\n  :host {\n    display: block;\n    margin: var(--_separator-margin, var(--size-1)) 0;\n    border-top: var(--border) solid var(--color-contrast-200);\n  }\n}\n","import { restoreFocus } from '@vielzeug/focus';\nimport type { Placement } from '@vielzeug/orbit';\nimport {\n  bind,\n  createStableId,\n  define,\n  getHost,\n  html,\n  onCleanup,\n  onMounted,\n  prop,\n  useEmit,\n  useSlots,\n  watchEffect,\n} from '@vielzeug/ore';\nimport { computed, watch as rippleWatch, signal } from '@vielzeug/ripple';\nimport {\n  createDropdownPositioner,\n  createInteraction,\n  createListControl,\n  createOutsidePointerDismissal,\n  type DropdownCloseReason,\n  lifecycleSignal,\n  type OverlayOpenChangeDetail,\n  type OverlayOpenReason,\n} from '../../core';\nimport { disablableBundle, MENU_SIZE_PRESET, sizableBundle } from '../../shared';\nimport { colorThemeMixin, forcedColorsMixin, sizeVariantMixin } from '../../styles';\nimport type { ComponentSize } from '../../types';\nimport componentStyles from './menu.css?inline';\nimport menuItemStyles from './menu-item.css?inline';\nimport menuSeparatorStyles from './menu-separator.css?inline';\n\n// ── Types ─────────────────────────────────────────────────────────────\n\nexport interface MenuSelectDetail {\n  checked?: boolean;\n  value: string;\n}\n\nexport type OreMenuItemType = 'checkbox' | 'radio';\n\nexport type OreMenuEvents = {\n  'open-change': OverlayOpenChangeDetail;\n  select: MenuSelectDetail;\n};\n\nexport type OreMenuItemProps = {\n  checked?: boolean;\n  disabled?: boolean;\n  type?: OreMenuItemType;\n  value?: string;\n};\n\nexport type OreMenuProps = {\n  /** Initial uncontrolled open state. Ignored when `open` is set. */\n  'default-open'?: boolean;\n  disabled?: boolean;\n  /** Controlled open state. */\n  open?: boolean;\n  placement?: 'bottom' | 'bottom-start' | 'bottom-end' | 'top' | 'top-start' | 'top-end';\n  size?: ComponentSize;\n};\n\n// ── Styles ─────────────────────────────────────────────────────────────\n\n// ── Menu Item Component ─────────────────────────────────────────────────────────────\n\n/**\n * A selectable action item used inside `<ore-menu>`.\n *\n * @element ore-menu-item\n *\n * @attr {boolean} checked - Checked state for `checkbox` and `radio` item types\n * @attr {boolean} disabled - Disables selection and pointer interaction\n * @attr {'checkbox'|'radio'} type - Optional checkable menu item mode\n * @attr {string} value - Value emitted by parent menu on selection\n *\n * @slot - Item label/content\n * @slot icon - Optional leading icon content\n *\n * @cssprop --menu-item-hover-bg - Background on hover\n * @cssprop --menu-item-focus-color - Text color when keyboard-focused\n * @cssprop --menu-item-focus-bg - Background when keyboard-focused\n * @cssprop --menu-item-selection-bg - Background for checkbox/radio items (unselected)\n * @cssprop --menu-item-checked-color - Text color when checked\n * @cssprop --menu-item-checked-bg - Background when checked\n *\n * @part item - Root item container element.\n * @part item-label - Label text container.\n * @part icon-slot - Leading icon slot container.\n *\n * @example\n * ```html\n * <ore-menu-item value=\"edit\">Edit</ore-menu-item>\n * <ore-menu-item value=\"delete\" disabled>Delete</ore-menu-item>\n * <ore-menu-item type=\"checkbox\" value=\"wrap\" checked>Word wrap</ore-menu-item>\n * <ore-menu-item type=\"radio\" value=\"left\">Align left</ore-menu-item>\n * ```\n */\nexport const MENU_ITEM_TAG = 'ore-menu-item' as const;\ndefine<OreMenuItemProps>(MENU_ITEM_TAG, {\n  props: {\n    checked: prop.bool(false),\n    disabled: prop.bool(false),\n    type: prop.string<OreMenuItemType>(),\n    value: prop.string(),\n  },\n  setup(props) {\n    const isCheckable = () => props.type.value === 'checkbox' || props.type.value === 'radio';\n    const isChecked = () => isCheckable() && props.checked.value;\n    const itemRole = () => {\n      if (props.type.value === 'checkbox') return 'menuitemcheckbox';\n\n      if (props.type.value === 'radio') return 'menuitemradio';\n\n      return 'menuitem';\n    };\n    const itemClass = () => {\n      const type = props.type.value;\n\n      return [\n        'item',\n        type === 'checkbox' ? 'is-checkbox' : '',\n        type === 'radio' ? 'is-radio' : '',\n        isChecked() ? 'is-checked' : '',\n      ]\n        .filter(Boolean)\n        .join(' ');\n    };\n\n    return isCheckable()\n      ? html`\n          <div\n            class=\"${itemClass}\"\n            tabindex=\"-1\"\n            role=\"${itemRole}\"\n            aria-checked=\"${() => String(isChecked())}\"\n            aria-disabled=\"${props.disabled}\">\n            <span class=\"item-check\" aria-hidden=\"true\"></span>\n            <span class=\"icon-slot\"><slot name=\"icon\"></slot></span>\n            <span class=\"item-label\"><slot></slot></span>\n          </div>\n        `\n      : html`\n          <div class=\"item\" tabindex=\"-1\" role=\"menuitem\" aria-disabled=\"${props.disabled}\">\n            <span class=\"icon-slot\"><slot name=\"icon\"></slot></span>\n            <span class=\"item-label\"><slot></slot></span>\n          </div>\n        `;\n  },\n  styles: [colorThemeMixin, menuItemStyles],\n});\n\n// ── Menu Separator ─────────────────────────────────────────────────────────────\n\n/**\n * Visual separator used to group menu items inside `<ore-menu>`.\n *\n * @element ore-menu-separator\n *\n * @example\n * ```html\n * <ore-menu-item value=\"cut\">Cut</ore-menu-item>\n * <ore-menu-separator></ore-menu-separator>\n * <ore-menu-item value=\"paste\">Paste</ore-menu-item>\n * ```\n */\nexport const SEPARATOR_TAG = 'ore-menu-separator' as const;\ndefine(SEPARATOR_TAG, {\n  setup() {\n    return html``;\n  },\n  styles: [menuSeparatorStyles],\n});\n\n// ── Menu Component ─────────────────────────────────────────────────────────────\n\nconst isCheckableItemType = (value: string | null): value is OreMenuItemType =>\n  value === 'checkbox' || value === 'radio';\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n  value == null ? undefined : value === '' || value === 'true';\n\n/**\n * Action dropdown menu triggered by a slotted trigger element.\n *\n * @element ore-menu\n * @element ore-menu-item - Clickable menu option (place in default slot)\n * @element ore-menu-separator - Visual divider between menu groups\n *\n * @attr {boolean} disabled - Disables opening and keyboard interaction\n * @attr {boolean} open - Controlled open state\n * @attr {boolean} default-open - Initial uncontrolled open state\n * @attr {string} placement - Panel placement: 'bottom' | 'bottom-start' | 'bottom-end' | 'top' | 'top-start' | 'top-end' (default: 'bottom-start')\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n *\n * @fires open-change - Fired when the menu state changes. detail: { open, reason }\n * @fires select - Fired when an item is selected. detail: { value: string, checked?: boolean }\n *\n * @slot trigger - Trigger element that toggles menu visibility\n * @slot - Menu content (`<ore-menu-item>` and `<ore-menu-separator>`)\n *\n * @part panel - Floating menu panel container\n *\n * @cssprop --menu-panel-bg - Background of the floating panel\n * @cssprop --menu-panel-border-color - Border color of the floating panel\n * @cssprop --menu-panel-shadow - Box shadow of the floating panel\n * @cssprop --menu-panel-blur - Backdrop blur amount for the floating panel\n * @cssprop --menu-panel-min-width - Minimum width of the floating panel\n * @cssprop --menu-panel-max-height - Maximum height of the floating panel before it scrolls\n * @cssprop --menu-panel-radius - Border radius of the floating panel\n *\n * @example\n * ```html\n * <ore-menu>\n *   <button slot=\"trigger\">Actions</button>\n *   <ore-menu-item value=\"edit\">Edit</ore-menu-item>\n *   <ore-menu-item value=\"delete\">Delete</ore-menu-item>\n * </ore-menu>\n * ```\n */\nexport const MENU_TAG = 'ore-menu' as const;\ndefine<OreMenuProps>(MENU_TAG, {\n  props: {\n    ...sizableBundle,\n    ...disablableBundle,\n    'default-open': prop.bool(false),\n    open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n    placement: prop.oneOf(\n      ['bottom', 'bottom-start', 'bottom-end', 'top', 'top-start', 'top-end'] as const,\n      'bottom-start',\n    ),\n  },\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreMenuEvents>();\n    const slots = useSlots();\n    const watch = watchEffect;\n\n    const menuId = createStableId('menu');\n    const isDisabled = computed(() => Boolean(props.disabled.value));\n    const abortSignal = lifecycleSignal(onCleanup);\n    let triggerEl: HTMLElement | null = null;\n    let panelEl: HTMLElement | null = null;\n    let cleanupTrigger: (() => void) | null = null;\n\n    // ── Helpers ───────────────────────────────────────────────────────────────\n    function getItems(): HTMLElement[] {\n      return Array.from(el.querySelectorAll<HTMLElement>('ore-menu-item:not([disabled])'));\n    }\n\n    function getItemFocusable(item: HTMLElement | null | undefined): HTMLElement | null {\n      if (!item) return null;\n\n      return item.shadowRoot?.querySelector<HTMLElement>('[role^=\"menuitem\"]') ?? item;\n    }\n\n    function getFocusedItemIndex(): number {\n      const items = getItems();\n\n      return items.findIndex((item) => {\n        const focusable = getItemFocusable(item);\n\n        return item === document.activeElement || focusable === document.activeElement;\n      });\n    }\n\n    const isOpenSignal = signal(false);\n    let stopPositioning: (() => void) | null = null;\n    const positioner = createDropdownPositioner({\n      getFloating: () => panelEl,\n      getPlacement: () => (props.placement.value ?? 'bottom-start') as Placement,\n      getReference: () => triggerEl,\n      matchWidth: false,\n      offsetPx: 4,\n      padding: 6,\n    });\n    const list = createListControl<HTMLElement>({\n      disabled: computed(() => !isOpenSignal.value),\n      getItems: getItems,\n      isItemDisabled: (item) => item.hasAttribute('disabled'),\n      onNavigate: ({ item }) => {\n        getItemFocusable(item)?.focus();\n      },\n      signal: abortSignal,\n    });\n\n    const close = (reason: DropdownCloseReason = 'programmatic', shouldRestoreFocus = true): void => {\n      if (!isOpenSignal.value) return;\n\n      isOpenSignal.value = false;\n      list.reset();\n      stopPositioning?.();\n      stopPositioning = null;\n\n      if (shouldRestoreFocus) restoreFocus(() => triggerEl);\n\n      emit('open-change', { open: false, reason });\n    };\n\n    const open = (reason: OverlayOpenReason = 'programmatic'): void => {\n      if (isDisabled.value || isOpenSignal.value) return;\n\n      isOpenSignal.value = true;\n      positioner.update();\n      stopPositioning = positioner.startAutoUpdate?.() ?? null;\n      emit('open-change', { open: true, reason });\n    };\n\n    const toggle = (): void => {\n      if (isOpenSignal.value) close('trigger');\n      else open('click');\n    };\n\n    createOutsidePointerDismissal({\n      getTargets: () => [el, panelEl],\n      isActive: () => isOpenSignal.value,\n      onDismiss: () => close('outsideClick'),\n      signal: abortSignal,\n    });\n\n    let initialized = false;\n\n    rippleWatch(\n      props.open,\n      (value) => {\n        if (value === undefined) {\n          if (!initialized) {\n            if (props['default-open'].value) open('programmatic');\n          } else {\n            close('programmatic');\n          }\n        } else if (value) {\n          open('programmatic');\n        } else {\n          close('programmatic');\n        }\n\n        initialized = true;\n      },\n      { immediate: true },\n    );\n    abortSignal.addEventListener(\n      'abort',\n      () => {\n        if (!isOpenSignal.value) return;\n\n        isOpenSignal.value = false;\n        list.reset();\n        stopPositioning?.();\n        stopPositioning = null;\n      },\n      { once: true },\n    );\n\n    const activateItem = (item: HTMLElement): void => {\n      const type = item.getAttribute('type');\n      const isCheckable = isCheckableItemType(type);\n\n      if (type === 'checkbox') {\n        item.toggleAttribute('checked', !item.hasAttribute('checked'));\n      } else if (type === 'radio') {\n        for (const radio of el.querySelectorAll<HTMLElement>('ore-menu-item[type=\"radio\"]')) {\n          radio.toggleAttribute('checked', radio === item);\n        }\n      }\n\n      const value = item.getAttribute('value') ?? '';\n      const checked = isCheckable ? item.hasAttribute('checked') : undefined;\n\n      emit('select', { checked, value });\n\n      if (!isCheckable) {\n        close('programmatic');\n      }\n    };\n\n    const openFromKeyboardPress = createInteraction({\n      keys: ['Enter', ' ', 'ArrowDown'],\n      onPress: () => {\n        open('keyboard');\n        requestAnimationFrame(() => list.set(0));\n      },\n    });\n\n    const activateFocusedFromKeyboardPress = createInteraction({\n      onPress: () => {\n        const focused = list.getActiveItem();\n\n        if (focused) activateItem(focused);\n      },\n    });\n\n    // ── Keyboard Navigation ───────────────────────────────────────────────────\n    function handleMenuKeydown(e: KeyboardEvent) {\n      if (isDisabled.value) return;\n\n      const open = isOpenSignal.value;\n\n      // When closed: open on Enter / Space / ArrowDown\n      if (!open) {\n        openFromKeyboardPress.handleKeydown(e);\n\n        return;\n      }\n\n      const currentFocusedIndex = getFocusedItemIndex();\n\n      if (currentFocusedIndex >= 0) list.set(currentFocusedIndex);\n\n      if (e.key === 'Escape') {\n        e.preventDefault();\n        close('escape');\n\n        return;\n      }\n\n      if (list.handleKeydown(e)) return;\n\n      // When open: navigate and activate\n      if (e.key === ' ' || e.key === 'Enter') {\n        activateFocusedFromKeyboardPress.handleKeydown(e);\n\n        return;\n      }\n\n      if (e.key === 'Tab') {\n        close('programmatic');\n      }\n    }\n\n    // ── Lifecycle ─────────────────────────────────────────────────────────────\n    bind({\n      on: {\n        click: (e: MouseEvent) => {\n          const path = e.composedPath();\n\n          if (!isOpenSignal.value) return;\n\n          const itemFromPath = path.find(\n            (node): node is HTMLElement => node instanceof HTMLElement && node.tagName === 'ORE-MENU-ITEM',\n          );\n          const item = itemFromPath ?? (e.target as HTMLElement | null)?.closest<HTMLElement>('ore-menu-item') ?? null;\n\n          if (!item || item.hasAttribute('disabled')) return;\n\n          activateItem(item);\n        },\n      },\n    });\n\n    watch(() => {\n      const open = isOpenSignal.value;\n\n      if (!panelEl) return;\n\n      panelEl.toggleAttribute('data-open', open);\n    });\n\n    function resolveTrigger() {\n      cleanupTrigger?.();\n      cleanupTrigger = null;\n\n      const assigned = slots.elements('trigger').value;\n\n      triggerEl = (assigned?.[0] as HTMLElement | undefined) ?? null;\n\n      if (!triggerEl) return;\n\n      const cleanups: Array<() => void> = [];\n      const removeAria = bind(\n        {\n          aria: {\n            controls: () => menuId,\n            disabled: () => isDisabled.value,\n            expanded: () => String(isOpenSignal.value),\n            haspopup: 'menu',\n          },\n        },\n        { target: triggerEl },\n      );\n\n      const onTriggerClick = (event: MouseEvent) => {\n        event.stopPropagation();\n\n        if (isDisabled.value) return;\n\n        toggle();\n      };\n      const onTriggerKeydown = (event: KeyboardEvent) => {\n        handleMenuKeydown(event);\n      };\n\n      triggerEl.addEventListener('click', onTriggerClick);\n      triggerEl.addEventListener('keydown', onTriggerKeydown);\n      cleanups.push(() => triggerEl?.removeEventListener('click', onTriggerClick));\n      cleanups.push(() => triggerEl?.removeEventListener('keydown', onTriggerKeydown));\n\n      cleanupTrigger = () => {\n        removeAria();\n\n        for (const cleanup of cleanups) cleanup();\n      };\n    }\n\n    rippleWatch(slots.elements('trigger'), resolveTrigger, { immediate: true });\n\n    onMounted(() => {\n      resolveTrigger();\n\n      return () => {\n        cleanupTrigger?.();\n        cleanupTrigger = null;\n      };\n    });\n\n    return html`\n      <slot name=\"trigger\"></slot>\n      <div\n        class=\"menu-panel\"\n        part=\"panel\"\n        id=\"${menuId}\"\n        role=\"menu\"\n        aria-orientation=\"vertical\"\n        @keydown=\"${handleMenuKeydown}\"\n        ref=\"${(el: HTMLElement | null) => {\n          panelEl = el;\n          panelEl?.toggleAttribute('data-open', isOpenSignal.value);\n        }}\">\n        <slot></slot>\n      </div>\n    `;\n  },\n  styles: [componentStyles, sizeVariantMixin(MENU_SIZE_PRESET), forcedColorsMixin],\n});\n","@layer refine.base {\n  :host {\n    --_panel-bg: var(--navigation-menu-bg, var(--color-canvas));\n    --_panel-border: var(--navigation-menu-border-color, var(--color-divider));\n    --_panel-shadow: var(--navigation-menu-shadow, var(--shadow-xl));\n\n    position: relative;\n    display: inline-block;\n  }\n\n  .triggers {\n    display: flex;\n    gap: var(--navigation-menu-trigger-gap, var(--size-1));\n    align-items: center;\n  }\n}\n","@layer refine.base {\n  :host {\n    display: inline-flex;\n  }\n\n  .trigger {\n    all: unset;\n    box-sizing: border-box;\n    display: inline-flex;\n    gap: var(--size-1);\n    align-items: center;\n    min-height: var(--_touch-target, var(--size-9));\n    padding: var(--size-1-5) var(--size-2-5);\n    font-size: var(--text-sm);\n    font-weight: var(--font-medium);\n    color: var(--navbar-item-color, var(--color-contrast-700));\n    cursor: pointer;\n    border-radius: var(--rounded-md);\n  }\n\n  .trigger:hover,\n  .trigger[aria-expanded='true'] {\n    color: var(--color-primary);\n    background: var(--color-contrast-100);\n  }\n\n  .trigger:focus-visible {\n    outline: var(--focus-ring);\n    outline-offset: var(--size-0-5);\n  }\n\n  .trigger:disabled {\n    cursor: not-allowed;\n    opacity: 0.6;\n  }\n\n  ::slotted(ore-icon) {\n    flex: none;\n    transition: transform var(--transition-fast);\n  }\n\n  :host([aria-expanded='true']) ::slotted(ore-icon) {\n    transform: rotate(180deg);\n  }\n}\n","@layer refine.base {\n  :host {\n    position: fixed;\n    inset: unset;\n    z-index: var(--z-popover);\n    box-sizing: border-box;\n    display: none;\n    width: min(var(--navigation-menu-panel-width, 48rem), calc(100vw - var(--size-8)));\n    max-height: min(var(--navigation-menu-panel-max-height, 42rem), calc(100dvh - var(--size-12)));\n    margin: 0;\n    overflow: auto;\n    overscroll-behavior: contain;\n    background: var(--navigation-menu-bg, var(--color-canvas));\n    border: var(--border) solid var(--navigation-menu-border-color, var(--color-divider));\n    border-radius: var(--navigation-menu-radius, var(--rounded-lg));\n    box-shadow: var(--navigation-menu-shadow, var(--shadow-xl));\n    backdrop-filter: blur(var(--navigation-menu-backdrop-blur, var(--blur-xl))) saturate(180%);\n  }\n\n  :host([hidden]) {\n    display: none;\n  }\n\n  :host(:popover-open),\n  :host([data-open]) {\n    display: block;\n  }\n\n  .content {\n    display: grid;\n    grid-template-columns: repeat(var(--navigation-menu-panel-columns, 2), minmax(0, 1fr));\n    grid-auto-rows: max-content;\n    gap: var(--size-3);\n    align-content: start;\n    padding: var(--size-5);\n  }\n\n  .footer[hidden] {\n    display: none;\n  }\n\n  ::slotted(a) {\n    min-width: 0;\n    padding: var(--size-3);\n    font-size: var(--text-sm);\n    line-height: var(--leading-normal);\n    color: var(--color-contrast-700);\n    text-decoration: none;\n    border-radius: var(--rounded-md);\n    transition:\n      background var(--transition-fast),\n      color var(--transition-fast);\n  }\n\n  ::slotted(a:hover),\n  ::slotted(a:focus-visible) {\n    color: var(--color-primary);\n    background: var(--color-contrast-100);\n  }\n\n  ::slotted(a:focus-visible) {\n    outline: var(--focus-ring);\n    outline-offset: var(--size-0-5);\n  }\n\n  ::slotted(a[slot='footer']) {\n    display: flex;\n    gap: var(--size-2);\n    align-items: center;\n    justify-content: space-between;\n    padding: var(--size-3) var(--size-5);\n    font-size: var(--text-sm);\n    font-weight: var(--font-medium);\n    color: var(--color-primary);\n    text-decoration: none;\n    border-top: var(--border) solid var(--color-divider);\n  }\n\n  ::slotted(a[slot='footer']:hover),\n  ::slotted(a[slot='footer']:focus-visible) {\n    background: var(--color-contrast-100);\n  }\n}\n","import { createStableId, define, getHost, html, onCleanup, onMounted, prop, useEmit, useSlots } from '@vielzeug/ore';\nimport { computed, signal, watch } from '@vielzeug/ripple';\n\nimport type { OverlayOpenChangeDetail } from '../../core';\n\nimport { createDropdownPositioner, createOutsidePointerDismissal, lifecycleSignal } from '../../core';\nimport { disablableBundle } from '../../shared';\nimport { reducedMotionMixin } from '../../styles';\nimport hostStyles from './navigation-menu.css?inline';\nimport itemStyles from './navigation-menu-item.css?inline';\nimport panelStyles from './navigation-menu-panel.css?inline';\n\nexport type OreNavigationMenuEvents = {\n  'open-change': OverlayOpenChangeDetail & { value: string | null };\n  select: NavigationMenuSelectDetail;\n};\n\nexport type NavigationMenuSelectDetail = {\n  href: string;\n  value: string;\n};\n\nexport type OreNavigationMenuItemProps = {\n  disabled?: boolean;\n  value: string;\n};\n\nexport type OreNavigationMenuProps = {\n  /** Close after activating a panel link. */\n  'close-on-select'?: boolean;\n  columns?: number;\n  'default-open'?: string;\n  disabled?: boolean;\n  /** Accessible label for the trigger region. */\n  label?: string;\n  open?: string;\n  placement?: 'bottom-end' | 'bottom-start';\n};\n\nconst parseOptionalString = (value: string | null): string | undefined => value ?? undefined;\n\n/**\n * A trigger for an associated navigation menu panel.\n *\n * @element ore-navigation-menu-item\n *\n * @attr {boolean} disabled - Disables panel activation\n * @attr {string} value - Unique value matched by a panel's `for` attribute\n *\n * @slot - Trigger label and optional icon\n */\nexport const NAVIGATION_MENU_ITEM_TAG = 'ore-navigation-menu-item' as const;\ndefine<OreNavigationMenuItemProps>(NAVIGATION_MENU_ITEM_TAG, {\n  props: { disabled: prop.bool(false), value: prop.string('') },\n  setup(props) {\n    return html`\n      <button class=\"trigger\" type=\"button\" ?disabled=${props.disabled}><slot></slot></button>\n    `;\n  },\n  styles: [itemStyles],\n});\n\n/**\n * An anchored navigation menu panel associated with an item.\n *\n * @element ore-navigation-menu-panel\n *\n * @attr {string} for - Value of the associated navigation menu item\n *\n * @slot - Panel content\n * @slot footer - Optional panel footer\n *\n * @part content - Grid container for panel content\n * @part footer - Container for optional footer content\n */\nexport const NAVIGATION_MENU_PANEL_TAG = 'ore-navigation-menu-panel' as const;\ndefine<{ for?: string }>(NAVIGATION_MENU_PANEL_TAG, {\n  props: { for: prop.string() },\n  setup() {\n    const slots = useSlots();\n\n    return html`\n      <div class=\"content\" part=\"content\"><slot></slot></div>\n      <div class=\"footer\" part=\"footer\" ?hidden=${() => !slots.has('footer').value}><slot name=\"footer\"></slot></div>\n    `;\n  },\n  styles: [panelStyles],\n});\n\n/**\n * A horizontal set of triggers with anchored, non-modal navigation panels.\n *\n * @element ore-navigation-menu\n *\n * @attr {string} open - Controlled active trigger value\n * @attr {string} default-open - Initial uncontrolled active trigger value\n * @attr {boolean} close-on-select - Closes after activating a panel link\n * @attr {number} columns - Number of panel content columns\n * @attr {boolean} disabled - Disables all triggers\n * @attr {string} label - Accessible navigation region label\n * @attr {'bottom-start'|'bottom-end'} placement - Panel placement relative to its trigger\n *\n * @slot - Navigation menu items and panels\n *\n * @event open-change - Requested active panel change\n * @event select - A panel link was activated\n *\n * @cssprop --navigation-menu-panel-width - Maximum panel width\n * @cssprop --navigation-menu-panel-columns - Fallback number of panel content columns\n * @cssprop --navigation-menu-backdrop-blur - Frosted panel backdrop blur\n */\nexport const NAVIGATION_MENU_TAG = 'ore-navigation-menu' as const;\ndefine<OreNavigationMenuProps>(NAVIGATION_MENU_TAG, {\n  props: {\n    ...disablableBundle,\n    'close-on-select': prop.bool(true),\n    columns: prop.number(),\n    'default-open': prop.string(),\n    label: prop.string('Navigation menu'),\n    open: { default: undefined as string | undefined, parse: parseOptionalString },\n    placement: prop.oneOf(['bottom-end', 'bottom-start'] as const, 'bottom-start'),\n  },\n  setup(props) {\n    const host = getHost();\n    const emit = useEmit<OreNavigationMenuEvents>();\n    const abortSignal = lifecycleSignal(onCleanup);\n    const panelId = createStableId('navigation-menu');\n    const isDisabled = computed(() => props.disabled.value);\n    const activeValue = signal<string | null>(null);\n    let activeTrigger: HTMLElement | null = null;\n    let activePanel: HTMLElement | null = null;\n    let stopPositioning: (() => void) | null = null;\n\n    const items = () => Array.from(host.querySelectorAll<HTMLElement>(`${NAVIGATION_MENU_ITEM_TAG}:not([disabled])`));\n    const valueOf = (item: HTMLElement) => item.getAttribute('value') ?? '';\n    const panels = () => Array.from(host.querySelectorAll<HTMLElement>(NAVIGATION_MENU_PANEL_TAG));\n    const panelFor = (value: string) => panels().find((panel) => panel.getAttribute('for') === value) ?? null;\n    const isControlled = () => props.open.value !== undefined;\n    const panelIdFor = (panel: HTMLElement) => (panel.id ||= createStableId('navigation-menu-panel'));\n\n    const positioner = createDropdownPositioner({\n      getFloating: () => activePanel,\n      getPlacement: () => props.placement.value ?? 'bottom-start',\n      getReference: () => activeTrigger?.shadowRoot?.querySelector<HTMLElement>('.trigger') ?? activeTrigger,\n      matchWidth: false,\n      offsetPx: 8,\n      useClippingAncestor: false,\n    });\n\n    const panelColumns = (): number | undefined => {\n      const columns = props.columns.value;\n\n      return columns === undefined ? undefined : Math.max(1, Math.trunc(columns));\n    };\n\n    const showPanel = (panel: HTMLElement): void => {\n      panel.hidden = false;\n      panel.dataset.open = '';\n\n      if ('showPopover' in panel) {\n        try {\n          if (!panel.matches(':popover-open')) panel.showPopover();\n        } catch {\n          // Sandboxed documents can reject the Popover API; data-open remains the fixed-position fallback.\n        }\n      }\n    };\n\n    const hidePanel = (panel: HTMLElement): void => {\n      delete panel.dataset.open;\n\n      if ('hidePopover' in panel) {\n        try {\n          if (panel.matches(':popover-open')) panel.hidePopover();\n        } catch {\n          // The fallback visibility state is still cleared below.\n        }\n      }\n\n      panel.hidden = true;\n    };\n\n    const applyActive = (value: string | null): void => {\n      const nextPanel = value === null ? null : panelFor(value);\n\n      stopPositioning?.();\n      stopPositioning = null;\n      activeValue.value = value;\n      activeTrigger = value ? (items().find((item) => valueOf(item) === value) ?? null) : null;\n      activePanel = nextPanel;\n\n      for (const item of items()) {\n        const expanded = valueOf(item) === value;\n        const trigger = item.shadowRoot?.querySelector<HTMLElement>('.trigger');\n\n        item.setAttribute('aria-expanded', String(expanded));\n        trigger?.setAttribute('aria-expanded', String(expanded));\n      }\n      for (const panel of panels()) {\n        if (panel !== nextPanel) hidePanel(panel);\n      }\n\n      if (nextPanel) {\n        const columns = panelColumns();\n\n        if (columns !== undefined) nextPanel.style.setProperty('--navigation-menu-panel-columns', String(columns));\n\n        nextPanel.setAttribute('aria-labelledby', activeTrigger?.id ?? '');\n        showPanel(nextPanel);\n        positioner.update();\n        stopPositioning = positioner.startAutoUpdate?.() ?? null;\n      }\n    };\n\n    const requestActive = (value: string | null, reason: OverlayOpenChangeDetail['reason']): void => {\n      if (isDisabled.value || activeValue.value === value) return;\n\n      if (value !== null && !panelFor(value)) return;\n\n      if (!isControlled()) applyActive(value);\n\n      emit('open-change', { open: value !== null, reason, value });\n    };\n\n    onCleanup(() => {\n      stopPositioning?.();\n\n      for (const panel of panels()) hidePanel(panel);\n    });\n\n    createOutsidePointerDismissal({\n      getTargets: () => [host, activePanel],\n      isActive: () => activeValue.value !== null,\n      onDismiss: () => requestActive(null, 'outsideClick'),\n      signal: abortSignal,\n    });\n\n    onMounted(() => {\n      const values = new Set<string>();\n\n      for (const panel of panels()) {\n        panel.setAttribute('popover', 'manual');\n        panel.setAttribute('role', 'region');\n        panelIdFor(panel);\n        hidePanel(panel);\n\n        panel.addEventListener(\n          'click',\n          (event) => {\n            const link = event.target instanceof Element ? event.target.closest<HTMLAnchorElement>('a[href]') : null;\n\n            if (!link || !panel.contains(link)) return;\n\n            const value = activeValue.value;\n\n            if (!value) return;\n\n            emit('select', { href: link.href, value });\n\n            if (props['close-on-select'].value && !link.closest('[data-navigation-menu-keep-open]')) {\n              requestActive(null, 'select');\n            }\n          },\n          { signal: abortSignal },\n        );\n      }\n\n      document.addEventListener(\n        'keydown',\n        (event) => {\n          if (event.key !== 'Escape' || activeValue.value === null) return;\n\n          event.preventDefault();\n          requestActive(null, 'escape');\n          activeTrigger?.shadowRoot?.querySelector<HTMLElement>('.trigger')?.focus();\n        },\n        { signal: abortSignal },\n      );\n\n      for (const item of items()) {\n        const value = valueOf(item);\n        const panel = panelFor(value);\n\n        if (!value || values.has(value) || !panel) continue;\n\n        values.add(value);\n        item.id ||= createStableId('navigation-menu-trigger');\n\n        const trigger = item.shadowRoot?.querySelector<HTMLButtonElement>('.trigger');\n\n        if (!trigger) continue;\n\n        trigger.setAttribute('aria-controls', panelIdFor(panel));\n        trigger.setAttribute('aria-haspopup', 'true');\n        trigger.setAttribute('aria-expanded', 'false');\n        item.setAttribute('aria-expanded', 'false');\n        trigger.addEventListener('click', () => requestActive(activeValue.value === value ? null : value, 'click'), {\n          signal: abortSignal,\n        });\n        trigger.addEventListener(\n          'keydown',\n          (event) => {\n            const all = items();\n            const index = all.indexOf(item);\n\n            if (\n              event.key === 'ArrowLeft' ||\n              event.key === 'ArrowRight' ||\n              event.key === 'Home' ||\n              event.key === 'End'\n            ) {\n              event.preventDefault();\n\n              const next =\n                event.key === 'Home'\n                  ? all[0]\n                  : event.key === 'End'\n                    ? all.at(-1)\n                    : all[(index + (event.key === 'ArrowRight' ? 1 : all.length - 1)) % all.length];\n\n              next?.shadowRoot?.querySelector<HTMLElement>('.trigger')?.focus();\n            } else if (event.key === 'ArrowDown') {\n              event.preventDefault();\n              requestActive(value, 'keyboard');\n              requestAnimationFrame(() =>\n                activePanel?.querySelector<HTMLElement>('a, button, input, [tabindex]:not([tabindex=\"-1\"])')?.focus(),\n              );\n            }\n          },\n          { signal: abortSignal },\n        );\n      }\n\n      if (props.open.value !== undefined) applyActive(props.open.value);\n      else if (props['default-open'].value) applyActive(props['default-open'].value);\n    });\n\n    watch(props.open, (value) => {\n      if (value !== undefined) applyActive(value);\n    });\n\n    watch(props.disabled, (disabled) => {\n      if (disabled) applyActive(null);\n    });\n\n    return html`\n      <nav class=\"triggers\" aria-label=\"${props.label}\" id=\"${panelId}\"><slot></slot></nav>\n      <slot name=\"panel\"></slot>\n      <slot name=\"footer\"></slot>\n    `;\n  },\n  styles: [reducedMotionMixin, hostStyles],\n});\n","/* ========================================\n   Popover UA resets — unlayered so they unconditionally beat\n   the browser's [popover] UA stylesheet (padding / inset / border / margin).\n   Must NOT be inside @layer; unlayered author rules win over every layer and\n   every UA default.\n   ======================================== */\n.tooltip {\n  inset: unset;\n  padding: calc(var(--size-0-5) / 2) var(--size-2) var(--size-0-5);\n  margin: 0;\n  overflow: visible;\n  border: var(--_tooltip-border-width, var(--border-0)) solid var(--_tooltip-border-color, transparent);\n  transform-origin: center;\n}\n\n@layer refine.base {\n  :host {\n    position: relative;\n    display: inline-block;\n  }\n\n  .tooltip {\n    --_tooltip-fg: var(--color-contrast-100);\n    --_tooltip-bg: color-mix(in oklch, var(--color-contrast-900) 80%, transparent);\n    --_tooltip-border-width: var(--border);\n    --_tooltip-border-color: color-mix(in oklch, var(--color-contrast-100) 12%, transparent);\n    --_tooltip-shadow: var(--shadow-md);\n    --_tooltip-closed-transform: translateY(4px) scale(0.98);\n\n    /* Positioning — JS sets top/left inline */\n    position: fixed;\n    max-width: var(--tooltip-max-width, var(--size-72));\n    font-size: var(--text-xs);\n    font-weight: var(--font-medium);\n    line-height: var(--leading-normal);\n    color: var(--_tooltip-fg);\n    word-break: auto-phrase;\n    white-space: normal;\n    pointer-events: none;\n    background: var(--_tooltip-bg);\n    border-radius: var(--tooltip-radius, var(--rounded-lg));\n    box-shadow: var(--_tooltip-shadow);\n\n    /* Hidden by default (also serves as exit state) */\n    opacity: 0;\n    backdrop-filter: blur(var(--blur-sm));\n    transform: var(--_tooltip-closed-transform);\n    transition:\n      opacity var(--transition-fast),\n      transform var(--transition-fast),\n      display var(--transition-fast) allow-discrete,\n      overlay var(--transition-fast) allow-discrete;\n  }\n\n  @media (prefers-color-scheme: dark) {\n    .tooltip {\n      --_tooltip-fg: var(--color-contrast-900);\n      --_tooltip-bg: color-mix(in oklch, var(--color-contrast-100) 80%, transparent);\n      --_tooltip-border-color: color-mix(in oklch, var(--color-contrast-900) 12%, transparent);\n    }\n  }\n\n  .tooltip-text {\n    display: block;\n    white-space: pre-line;\n  }\n\n  .tooltip[data-placement='top'] {\n    --_tooltip-closed-transform: translateY(4px) scale(var(--overlay-enter-scale-dialog));\n  }\n\n  .tooltip[data-placement='bottom'] {\n    --_tooltip-closed-transform: translateY(-4px) scale(var(--overlay-enter-scale-dialog));\n  }\n\n  .tooltip[data-placement='left'] {\n    --_tooltip-closed-transform: translateX(4px) scale(var(--overlay-enter-scale-dialog));\n  }\n\n  .tooltip[data-placement='right'] {\n    --_tooltip-closed-transform: translateX(-4px) scale(var(--overlay-enter-scale-dialog));\n  }\n\n  .tooltip[data-open] {\n    display: block;\n  }\n\n  /* Entry animation via @starting-style */\n  .tooltip:popover-open,\n  .tooltip[data-open] {\n    opacity: 1;\n    transform: translate(0, 0) scale(1);\n    transition:\n      opacity var(--transition-normal),\n      transform var(--transition-spring),\n      display var(--transition-normal) allow-discrete,\n      overlay var(--transition-normal) allow-discrete;\n    will-change: opacity, transform;\n\n    @starting-style {\n      opacity: 0;\n      transform: var(--_tooltip-closed-transform);\n    }\n  }\n}\n\n@layer refine.variants {\n  /* Light tooltip */\n  :host([variant='light']) .tooltip {\n    --_tooltip-fg: var(--color-contrast-900);\n    --_tooltip-bg: color-mix(in oklch, var(--color-contrast-100) 80%, transparent);\n    --_tooltip-border-color: color-mix(in oklch, var(--color-contrast-900) 12%, transparent);\n    --_tooltip-shadow: var(--shadow-md);\n  }\n\n  @media (prefers-color-scheme: dark) {\n    :host([variant='light']) .tooltip {\n      --_tooltip-fg: var(--color-contrast-100);\n      --_tooltip-bg: color-mix(in oklch, var(--color-contrast-900) 80%, transparent);\n      --_tooltip-border-color: color-mix(in oklch, var(--color-contrast-100) 12%, transparent);\n    }\n  }\n}\n\n@layer refine.utilities {\n  :host([size='sm']) .tooltip {\n    font-size: var(--text-xs);\n  }\n\n  :host([size='lg']) .tooltip {\n    font-size: var(--text-base);\n  }\n}\n","import type { Placement } from '@vielzeug/orbit';\n\nimport {\n  bind,\n  createStableId,\n  define,\n  getHost,\n  html,\n  onCleanup,\n  onMounted,\n  prop,\n  useEmit,\n  useSlots,\n} from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { type OverlayOpenChangeDetail, type OverlayOpenReason, parseStringTriggers } from '../../core';\nimport { disablableBundle, sizableBundle } from '../../shared';\nimport { forcedColorsMixin } from '../../styles';\nimport type { ComponentSize } from '../../types';\nimport { useFloatingTrigger } from '../shared/use-floating-trigger';\nimport styles from './tooltip.css?inline';\n\ntype TooltipPlacement = 'top' | 'bottom' | 'left' | 'right';\ntype TooltipTrigger = 'click' | 'focus' | 'hover';\n\nconst LEFT_GAP_COMPENSATION = 4;\nconst DEFAULT_TOOLTIP_TRIGGERS: TooltipTrigger[] = ['hover', 'focus'];\nconst VALID_TOOLTIP_TRIGGERS = new Set<TooltipTrigger>(['click', 'focus', 'hover']);\n\nconst parseDelayMs = (value: string | null): number => {\n  if (value == null || value.trim() === '') return 0;\n\n  const parsed = Number(value);\n\n  return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;\n};\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n  value == null ? undefined : value === '' || value === 'true';\n\nconst normalizeTriggers = (value: string | null | undefined): TooltipTrigger[] =>\n  parseStringTriggers(value, VALID_TOOLTIP_TRIGGERS, DEFAULT_TOOLTIP_TRIGGERS);\n\n/** Tooltip component properties */\nexport type OreTooltipEvents = {\n  'open-change': OverlayOpenChangeDetail;\n};\n\nexport type OreTooltipProps = {\n  /** Hide delay in ms */\n  'close-delay'?: number;\n  /** Tooltip text content */\n  content?: string;\n  /** Initial uncontrolled open state. Ignored when `open` is set. */\n  'default-open'?: boolean;\n  /** Show delay in ms */\n  delay?: number;\n  /** Disable the tooltip */\n  disabled?: boolean;\n  /** Controlled open state */\n  open?: boolean;\n  /** Preferred placement relative to trigger */\n  placement?: TooltipPlacement;\n  /** Tooltip size */\n  size?: ComponentSize;\n  /** Which trigger(s) show/hide the tooltip */\n  trigger?: string;\n  /** Visual variant */\n  variant?: 'dark' | 'light';\n};\n\n/**\n * A lightweight tooltip shown on hover/focus/click relative to the slotted trigger.\n *\n * @element ore-tooltip\n *\n * @attr {string} content - Tooltip text content\n * @attr {string} placement - 'top' | 'bottom' | 'left' | 'right' (default: 'top')\n * @attr {string} trigger - 'hover' | 'focus' | 'click' or comma-separated combination\n * @attr {number} delay - Show delay in milliseconds (default: 0)\n * @attr {boolean} open - Controlled open state\n * @attr {boolean} default-open - Initial uncontrolled open state\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n * @attr {string} variant - 'dark' (default) | 'light'\n * @attr {boolean} disabled - Disable the tooltip\n *\n * @slot - Trigger element that the tooltip is anchored to\n * @slot content - Complex tooltip content (overrides the `content` attribute)\n * @fires open-change - Fired when the tooltip state changes. detail: { open, reason }\n *\n * @cssprop --tooltip-max-width - Max width of the tooltip bubble\n *\n * @part tooltip - Tooltip container.\n * @example\n * ```html\n * <!-- Simple text tooltip -->\n * <ore-tooltip content=\"Copy to clipboard\">\n *   <button>Copy</button>\n * </ore-tooltip>\n *\n * <!-- Placement and delay -->\n * <ore-tooltip content=\"Save your work\" placement=\"right\" delay=\"300\">\n *   <ore-icon name=\"save\"></ore-icon>\n * </ore-tooltip>\n *\n * <!-- Hover + focus trigger -->\n * <ore-tooltip content=\"Required field\" trigger=\"hover,focus\" placement=\"top\">\n *   <ore-input label=\"Email\" type=\"email\"></ore-input>\n * </ore-tooltip>\n *\n * <!-- Rich content slot -->\n * <ore-tooltip>\n *   <ore-button>Help</ore-button>\n *   <div slot=\"content\">\n *     <strong>Keyboard shortcuts</strong>\n *     <p>Press Ctrl+S to save.</p>\n *   </div>\n * </ore-tooltip>\n * ```\n */\nexport const TOOLTIP_TAG = 'ore-tooltip' as const;\ndefine<OreTooltipProps>(TOOLTIP_TAG, {\n  props: {\n    ...sizableBundle,\n    ...disablableBundle,\n    'close-delay': { default: 0, parse: parseDelayMs },\n    content: prop.string(),\n    'default-open': prop.bool(false),\n    delay: { default: 0, parse: parseDelayMs },\n    open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n    placement: prop.oneOf(['top', 'bottom', 'left', 'right'] as const, 'top'),\n    trigger: prop.string('hover,focus'),\n    variant: prop.string<'dark' | 'light'>(),\n  },\n  setup(props) {\n    const el = getHost();\n    const emit = useEmit<OreTooltipEvents>();\n    const slots = useSlots();\n\n    const shadowRoot = el.shadowRoot;\n    const isDisabled = computed(() => Boolean(props.disabled.value));\n    const isControlled = computed(() => props.open.value !== undefined);\n    const activePlacement = signal<TooltipPlacement>('top');\n    const tooltipId = createStableId('tooltip');\n    const triggers = computed<TooltipTrigger[]>(() => normalizeTriggers(props.trigger.value));\n    let tooltipEl: HTMLElement | null = null;\n    let showTimer: ReturnType<typeof setTimeout> | null = null;\n    let hideTimer: ReturnType<typeof setTimeout> | null = null;\n\n    const clearShowTimer = (): void => {\n      if (!showTimer) return;\n\n      clearTimeout(showTimer);\n      showTimer = null;\n    };\n    const clearHideTimer = (): void => {\n      if (!hideTimer) return;\n\n      clearTimeout(hideTimer);\n      hideTimer = null;\n    };\n\n    const floating = useFloatingTrigger({\n      bindTriggerAria: (triggerEl) => bind({ aria: { describedby: () => tooltipId } }, { target: triggerEl }),\n      defaultOpen: props['default-open'],\n      disabled: isDisabled,\n      getPanel: () => tooltipEl,\n      offset: 8,\n      onCleanup,\n      onClose: (reason) => emit('open-change', { open: false, reason }),\n      onOpen: (reason) => emit('open-change', { open: true, reason }),\n      onPlacementChange: (p) => {\n        const side = p.split('-')[0] as TooltipPlacement;\n\n        activePlacement.value = side;\n\n        if (side === 'left' && tooltipEl) {\n          tooltipEl.style.left = `${parseFloat(tooltipEl.style.left) - LEFT_GAP_COMPENSATION}px`;\n        }\n      },\n      openProp: props.open as typeof props.open & { value: boolean | undefined },\n      placement: computed(() => props.placement.value as Placement),\n      slot: () => shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])') ?? null,\n      slotElements: slots.elements(),\n      triggers: computed(() => [] as TooltipTrigger[]),\n    });\n\n    function show(reason: OverlayOpenReason = 'hover'): void {\n      if (isControlled.value) return;\n\n      if (isDisabled.value || (!props.content.value && !slots.has('content').value)) return;\n\n      clearHideTimer();\n      clearShowTimer();\n\n      const delay = Number(props.delay.value) || 0;\n\n      if (delay > 0) {\n        showTimer = setTimeout(() => {\n          showTimer = null;\n          floating.open(reason);\n          floating.updatePosition();\n        }, delay);\n      } else {\n        floating.open(reason);\n        floating.updatePosition();\n      }\n    }\n\n    function hide(): void {\n      if (isControlled.value) return;\n\n      clearShowTimer();\n\n      const closeDelay = Number(props['close-delay'].value) || 0;\n\n      if (closeDelay > 0) {\n        clearHideTimer();\n        hideTimer = setTimeout(() => {\n          hideTimer = null;\n          floating.close('trigger');\n        }, closeDelay);\n      } else {\n        floating.close('trigger');\n      }\n    }\n\n    onMounted(() => {\n      // Manually bind trigger events so we can wrap show/hide with delay timers.\n      // useFloatingTrigger handles ARIA, positioning, controlled mode, and keyboard dismiss.\n      const triggerSlot = shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n      let eventCleanups: Array<() => void> = [];\n\n      const addEvent = (target: EventTarget, event: string, handler: EventListener): void => {\n        target.addEventListener(event, handler);\n        eventCleanups.push(() => target.removeEventListener(event, handler));\n      };\n\n      const bindTriggerEvents = (): void => {\n        for (const cleanup of eventCleanups) cleanup();\n        eventCleanups = [];\n\n        const triggerEl = triggerSlot?.assignedElements({ flatten: true })[0] as HTMLElement | undefined;\n\n        if (!triggerEl) return;\n\n        const t = triggers.value;\n\n        if (t.includes('hover')) {\n          addEvent(triggerEl, 'pointerenter', () => show('hover'));\n          addEvent(triggerEl, 'pointerleave', hide);\n        }\n\n        if (t.includes('focus')) {\n          addEvent(triggerEl, 'focusin', () => show('focus'));\n          addEvent(triggerEl, 'focusout', hide);\n        }\n\n        if (t.includes('click')) {\n          addEvent(triggerEl, 'click', () => (floating.visible.value ? hide() : show('click')));\n        }\n      };\n\n      triggerSlot?.addEventListener('slotchange', bindTriggerEvents);\n      bindTriggerEvents();\n\n      const destroyFloating = floating.mount();\n\n      return () => {\n        triggerSlot?.removeEventListener('slotchange', bindTriggerEvents);\n        for (const cleanup of eventCleanups) cleanup();\n        clearShowTimer();\n        clearHideTimer();\n        destroyFloating();\n      };\n    });\n\n    return html`\n      <slot></slot>\n      <div\n        class=\"tooltip\"\n        part=\"tooltip\"\n        id=\"${tooltipId}\"\n        role=\"tooltip\"\n        popover=\"manual\"\n        ref=${(ref: HTMLElement) => {\n          tooltipEl = ref;\n        }}\n        data-placement=\"${activePlacement}\"\n        aria-hidden=\"${() => String(!floating.visible.value)}\">\n        <slot name=\"content\"><span class=\"tooltip-text\">${props.content}</span></slot>\n      </div>\n    `;\n  },\n  styles: [forcedColorsMixin, styles],\n});\n","export { COMMAND_PALETTE_ITEM_TAG, COMMAND_PALETTE_TAG } from './command-palette/command-palette';\nexport type {\n  CommandPaletteItem,\n  CommandPaletteItemInput,\n  CommandPaletteSelectDetail,\n  OreCommandPaletteEvents,\n  OreCommandPaletteItemProps,\n  OreCommandPaletteProps,\n} from './command-palette/command-palette.types';\nexport type { OreDialogEvents, OreDialogProps } from './dialog/dialog';\nexport { DIALOG_TAG } from './dialog/dialog';\nexport type { DrawerElement, OreDrawerEvents, OreDrawerProps } from './drawer/drawer';\nexport { DRAWER_TAG } from './drawer/drawer';\nexport type { MenuSelectDetail, OreMenuEvents, OreMenuItemProps, OreMenuItemType, OreMenuProps } from './menu/menu';\nexport { MENU_ITEM_TAG, MENU_TAG } from './menu/menu';\nexport type {\n  OreNavigationMenuEvents,\n  OreNavigationMenuItemProps,\n  OreNavigationMenuProps,\n} from './navigation-menu/navigation-menu';\nexport {\n  NAVIGATION_MENU_ITEM_TAG,\n  NAVIGATION_MENU_PANEL_TAG,\n  NAVIGATION_MENU_TAG,\n} from './navigation-menu/navigation-menu';\nexport type { OrePopoverEvents, OrePopoverProps } from './popover/popover';\nexport { POPOVER_TAG } from './popover/popover';\nexport type { OreTooltipEvents, OreTooltipProps } from './tooltip/tooltip';\nexport { TOOLTIP_TAG } from './tooltip/tooltip';\n","/**\n * Internal all-components entry used by the standalone bundle and docs theme.\n *\n * Applications register components through explicit subpaths; the IIFE bundle\n * is the intentional all-components distribution for script-tag consumers.\n */\nimport * as content from './content';\nimport * as disclosure from './disclosure';\nimport * as feedback from './feedback';\nimport * as inputs from './inputs';\nimport * as layout from './layout';\nimport * as overlay from './overlay';\n\n// Exporting the namespaces makes every registration module part of the standalone bundle.\nexport const components = { content, disclosure, feedback, inputs, layout, overlay };\n"],"mappings":"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"}