@opendata-ai/openchart-vue 8.7.0 → 8.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +4 -2
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/styles.css.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BarListSpec, ThemeConfig, DarkMode, ChartSpec, LayerSpec, GraphSpec, ElementRef, MarkEvent, Annotation, TextAnnotation, AnnotationOffset, ElementEdit, GeoMapSpec, ChartLayout, TableSpec, SortState, SankeySpec, TileMapSpec, VizSpec } from '@opendata-ai/openchart-core';
|
|
2
2
|
export * from '@opendata-ai/openchart-core';
|
|
3
|
-
import { MountOptions, ChartInstance, CameraFlightOptions, GraphFlyTarget, GraphCamera, GraphHighlightTarget, GraphLegendData, GraphInstance, TableInstance, TableState, TableMountOptions, GeoMapMarkEvent, GraphTooltipFormatter } from '@opendata-ai/openchart-vanilla';
|
|
3
|
+
import { MountOptions, ChartInstance, CameraFlightOptions, GraphFlyTarget, GraphCamera, GraphHighlightTarget, GraphLegendData, GraphInstance, TableInstance, TableState, TableMountOptions, GeoMapMarkEvent, Camera, GraphTooltipFormatter } from '@opendata-ai/openchart-vanilla';
|
|
4
4
|
export { JPGExportOptions, PNGExportOptions, SVGExportOptions, SpecSequenceOptions, exportCSV, exportJPG, exportPNG, exportSVG, exportSVGWithFonts, exportSpecSequence } from '@opendata-ai/openchart-vanilla';
|
|
5
5
|
export { ChartRenderer, CompileResult, CompiledGraphEdge, CompiledGraphNode, GraphCompilation, NormalizedBarListSpec, NormalizedChartSpec, NormalizedChrome, NormalizedGeoMapSpec, NormalizedGraphSpec, NormalizedSankeySpec, NormalizedSpec, NormalizedTableSpec, NormalizedTileMapSpec, SimulationConfig, ValidationError, ValidationErrorCode, ValidationResult, clearRenderers, compile, compileBarList, compileChart, compileGeoMap, compileGraph, compileSankey, compileTable, compileTileMap, getChartRenderer, normalizeSpec, registerChartRenderer, validateSpec } from '@opendata-ai/openchart-engine';
|
|
6
6
|
import * as vue from 'vue';
|
|
@@ -650,6 +650,7 @@ declare const GeoMap: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
650
650
|
}>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
|
|
651
651
|
'mark-click': (_event: GeoMapMarkEvent) => true;
|
|
652
652
|
'mark-hover': (_event: GeoMapMarkEvent | null) => true;
|
|
653
|
+
'camera-change': (_camera: Camera) => true;
|
|
653
654
|
}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
|
|
654
655
|
spec: {
|
|
655
656
|
type: PropType<GeoMapSpec>;
|
|
@@ -674,6 +675,7 @@ declare const GeoMap: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
674
675
|
}>> & Readonly<{
|
|
675
676
|
"onMark-click"?: ((_event: GeoMapMarkEvent) => any) | undefined;
|
|
676
677
|
"onMark-hover"?: ((_event: GeoMapMarkEvent | null) => any) | undefined;
|
|
678
|
+
"onCamera-change"?: ((_camera: Camera) => any) | undefined;
|
|
677
679
|
}>, {
|
|
678
680
|
theme: ThemeConfig;
|
|
679
681
|
darkMode: DarkMode;
|
|
@@ -793,6 +795,7 @@ declare const Graph: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
793
795
|
};
|
|
794
796
|
}>> & Readonly<{
|
|
795
797
|
"onLegend-toggle"?: ((_activeValues: string[]) => any) | undefined;
|
|
798
|
+
"onCamera-change"?: ((_camera: GraphCamera) => any) | undefined;
|
|
796
799
|
"onNode-click"?: ((_node: Record<string, unknown>) => any) | undefined;
|
|
797
800
|
"onNode-double-click"?: ((_node: Record<string, unknown>) => any) | undefined;
|
|
798
801
|
"onNode-hover"?: ((_node: Record<string, unknown> | null) => any) | undefined;
|
|
@@ -803,7 +806,6 @@ declare const Graph: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
803
806
|
value: string;
|
|
804
807
|
} | null) => any) | undefined;
|
|
805
808
|
"onHighlight-change"?: ((_nodeIds: string[] | null) => any) | undefined;
|
|
806
|
-
"onCamera-change"?: ((_camera: GraphCamera) => any) | undefined;
|
|
807
809
|
}>, {
|
|
808
810
|
theme: ThemeConfig;
|
|
809
811
|
darkMode: DarkMode;
|
package/dist/index.js
CHANGED
|
@@ -928,7 +928,8 @@ var GeoMap = defineComponent5({
|
|
|
928
928
|
},
|
|
929
929
|
emits: {
|
|
930
930
|
"mark-click": (_event) => true,
|
|
931
|
-
"mark-hover": (_event) => true
|
|
931
|
+
"mark-hover": (_event) => true,
|
|
932
|
+
"camera-change": (_camera) => true
|
|
932
933
|
},
|
|
933
934
|
setup(props, { emit, expose }) {
|
|
934
935
|
const containerRef = ref10(null);
|
|
@@ -950,6 +951,7 @@ var GeoMap = defineComponent5({
|
|
|
950
951
|
darkMode: resolveDarkMode(),
|
|
951
952
|
onMarkClick: (feature) => emit("mark-click", feature),
|
|
952
953
|
onMarkHover: (feature) => emit("mark-hover", feature),
|
|
954
|
+
onCameraChange: (camera) => emit("camera-change", camera),
|
|
953
955
|
responsive: true
|
|
954
956
|
};
|
|
955
957
|
instance = createGeoMap(container, props.spec, options);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/BarList.ts","../src/context.ts","../src/Chart.ts","../src/ChartStory.ts","../src/composables/useChart.ts","../src/composables/useDarkMode.ts","../src/composables/useGraph.ts","../src/composables/useTable.ts","../src/composables/useTableState.ts","../src/DataTable.ts","../src/GeoMap.ts","../src/Graph.ts","../src/Sankey.ts","../src/ThemeProvider.ts","../src/TileMap.ts","../src/Visualization.ts"],"sourcesContent":["/**\n * @opendata-ai/openchart-vue\n *\n * Vue 3 adapter for openchart. Provides <Chart />, <DataTable />, <Graph />,\n * and <VizThemeProvider /> components that wrap the vanilla adapter with\n * Vue lifecycle management.\n *\n * Re-exports the full core type system and utilities so Vue consumers\n * only need a single @opendata-ai/openchart-vue dependency.\n */\n\n// ---------------------------------------------------------------------------\n// Core: full type system, theme, colors, locale, accessibility, helpers\n// ---------------------------------------------------------------------------\n\nexport * from '@opendata-ai/openchart-core';\n\n// ---------------------------------------------------------------------------\n// Vanilla: export utilities (SVG/PNG/JPG/CSV)\n// ---------------------------------------------------------------------------\n\nexport type {\n JPGExportOptions,\n PNGExportOptions,\n SpecSequenceOptions,\n SVGExportOptions,\n} from '@opendata-ai/openchart-vanilla';\nexport {\n exportCSV,\n exportJPG,\n exportPNG,\n exportSpecSequence,\n exportSVG,\n exportSVGWithFonts,\n} from '@opendata-ai/openchart-vanilla';\n\n// ---------------------------------------------------------------------------\n// Engine: compile API and types not covered by core\n// ---------------------------------------------------------------------------\n\nexport type {\n ChartRenderer,\n CompiledGraphEdge,\n CompiledGraphNode,\n CompileResult,\n GraphCompilation,\n NormalizedBarListSpec,\n NormalizedChartSpec,\n NormalizedChrome,\n NormalizedGeoMapSpec,\n NormalizedGraphSpec,\n NormalizedSankeySpec,\n NormalizedSpec,\n NormalizedTableSpec,\n NormalizedTileMapSpec,\n SimulationConfig,\n ValidationError,\n ValidationErrorCode,\n ValidationResult,\n} from '@opendata-ai/openchart-engine';\nexport {\n clearRenderers,\n compile,\n compileBarList,\n compileChart,\n compileGeoMap,\n compileGraph,\n compileSankey,\n compileTable,\n compileTileMap,\n getChartRenderer,\n normalizeSpec,\n registerChartRenderer,\n validateSpec,\n} from '@opendata-ai/openchart-engine';\nexport type { BarListProps, BarListRowEvent } from './BarList';\nexport { BarList } from './BarList';\n// Components\nexport type { ChartProps } from './Chart';\nexport { Chart } from './Chart';\nexport type { ChartStoryProps } from './ChartStory';\n// Scrollytelling\nexport { ChartStory } from './ChartStory';\n// Composables\nexport type { UseChartOptions, UseChartReturn } from './composables/useChart';\nexport { useChart } from './composables/useChart';\nexport { useDarkMode } from './composables/useDarkMode';\nexport type { GraphHandle, UseGraphReturn } from './composables/useGraph';\nexport { useGraph } from './composables/useGraph';\nexport type { UseTableReturn } from './composables/useTable';\nexport { useTable } from './composables/useTable';\nexport type { UseTableStateOptions, UseTableStateReturn } from './composables/useTableState';\nexport { useTableState } from './composables/useTableState';\n// Context (injection keys and composables)\nexport { useVizDarkMode, useVizTheme, VizDarkModeKey, VizThemeKey } from './context';\nexport type { DataTableProps } from './DataTable';\nexport { DataTable } from './DataTable';\nexport type { GeoMapProps } from './GeoMap';\nexport { GeoMap } from './GeoMap';\nexport type { GraphProps } from './Graph';\nexport { Graph } from './Graph';\nexport type { SankeyProps } from './Sankey';\nexport { Sankey } from './Sankey';\nexport type { VizThemeProviderProps } from './ThemeProvider';\nexport { VizThemeProvider } from './ThemeProvider';\nexport type { TileMapProps } from './TileMap';\nexport { TileMap } from './TileMap';\nexport type { VisualizationProps } from './Visualization';\nexport { Visualization } from './Visualization';\n","/**\n * Vue BarList component: thin wrapper around the vanilla adapter.\n */\n\nimport type { BarListSpec, DarkMode, ThemeConfig } from '@opendata-ai/openchart-core';\nimport {\n type BarListInstance,\n type BarListMountOptions,\n createBarList,\n} from '@opendata-ai/openchart-vanilla';\nimport {\n type CSSProperties,\n defineComponent,\n h,\n inject,\n onMounted,\n onUnmounted,\n type PropType,\n ref,\n watch,\n} from 'vue';\nimport { VizDarkModeKey, VizThemeKey } from './context';\n\nexport interface BarListRowEvent {\n label: string;\n value: number;\n data: Record<string, unknown>;\n}\n\nexport interface BarListProps {\n spec: BarListSpec;\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n class?: string;\n style?: string | CSSProperties;\n}\n\nexport const BarList = defineComponent({\n name: 'BarList',\n props: {\n spec: {\n type: Object as PropType<BarListSpec>,\n required: true,\n },\n theme: {\n type: Object as PropType<ThemeConfig>,\n default: undefined,\n },\n darkMode: {\n type: String as PropType<DarkMode>,\n default: undefined,\n },\n class: {\n type: String,\n default: undefined,\n },\n style: {\n type: [String, Object] as PropType<string | CSSProperties>,\n default: undefined,\n },\n },\n emits: {\n 'row-click': (_row: BarListRowEvent) => true,\n 'row-hover': (_row: BarListRowEvent | null) => true,\n },\n setup(props, { emit, expose }) {\n const containerRef = ref<HTMLDivElement | null>(null);\n let instance: BarListInstance | null = null;\n let prevSpec = '';\n\n const contextTheme = inject(VizThemeKey, undefined);\n const contextDarkMode = inject(VizDarkModeKey, undefined);\n\n function resolveTheme(): ThemeConfig | undefined {\n return props.theme ?? contextTheme?.value;\n }\n\n function resolveDarkMode(): DarkMode | undefined {\n return props.darkMode ?? contextDarkMode?.value;\n }\n\n function mountBarList() {\n const container = containerRef.value;\n if (!container) return;\n\n const options: BarListMountOptions = {\n theme: resolveTheme(),\n darkMode: resolveDarkMode(),\n onRowClick: (row: BarListRowEvent) => emit('row-click', row),\n onRowHover: (row: BarListRowEvent | null) => emit('row-hover', row),\n responsive: true,\n };\n\n instance = createBarList(container, props.spec, options);\n prevSpec = JSON.stringify(props.spec);\n }\n\n function destroyBarList() {\n instance?.destroy();\n instance = null;\n prevSpec = '';\n }\n\n expose({\n get instance() {\n return instance;\n },\n });\n\n onMounted(() => {\n mountBarList();\n });\n\n onUnmounted(() => {\n destroyBarList();\n });\n\n watch(\n () => JSON.stringify(props.spec),\n (newVal) => {\n if (!instance) return;\n if (newVal !== prevSpec) {\n prevSpec = newVal;\n instance.update(props.spec);\n }\n },\n );\n\n watch(\n [\n () => props.theme,\n () => props.darkMode,\n () => contextTheme?.value,\n () => contextDarkMode?.value,\n ],\n () => {\n if (!containerRef.value) return;\n destroyBarList();\n mountBarList();\n },\n );\n\n const rootClass = () => {\n const base = 'oc-barlist-root';\n return props.class ? `${base} ${props.class}` : base;\n };\n\n return () =>\n h('div', {\n ref: containerRef,\n class: rootClass(),\n style: props.style,\n });\n },\n});\n","/**\n * Theme injection context for Vue.\n *\n * Provides typed injection keys and composables for accessing theme\n * and dark mode from any descendant component within a VizThemeProvider.\n */\n\nimport type { DarkMode, ThemeConfig } from '@opendata-ai/openchart-core';\nimport { type ComputedRef, computed, type InjectionKey, inject, type Ref } from 'vue';\n\n/** Injection key for the theme config ref. */\nexport const VizThemeKey: InjectionKey<Ref<ThemeConfig | undefined>> = Symbol('VizTheme');\n\n/** Injection key for the dark mode ref. */\nexport const VizDarkModeKey: InjectionKey<Ref<DarkMode | undefined>> = Symbol('VizDarkMode');\n\n/**\n * Read the current theme from the nearest VizThemeProvider.\n * Returns a computed ref that stays reactive to provider changes.\n */\nexport function useVizTheme(): ComputedRef<ThemeConfig | undefined> {\n const theme = inject(VizThemeKey, undefined);\n return computed(() => theme?.value);\n}\n\n/**\n * Read the current dark mode preference from the nearest VizThemeProvider.\n * Returns a computed ref that stays reactive to provider changes.\n */\nexport function useVizDarkMode(): ComputedRef<DarkMode | undefined> {\n const darkMode = inject(VizDarkModeKey, undefined);\n return computed(() => darkMode?.value);\n}\n","/**\n * Vue Chart component: thin wrapper around the vanilla adapter.\n *\n * Mounts a chart instance on render, updates when spec changes,\n * and cleans up on unmount. All heavy lifting is done by the vanilla\n * createChart() function.\n */\n\nimport type {\n Annotation,\n AnnotationOffset,\n ChartSpec,\n DarkMode,\n ElementEdit,\n ElementRef,\n GraphSpec,\n LayerSpec,\n MarkEvent,\n TextAnnotation,\n ThemeConfig,\n} from '@opendata-ai/openchart-core';\nimport { type ChartInstance, createChart, type MountOptions } from '@opendata-ai/openchart-vanilla';\nimport {\n type CSSProperties,\n defineComponent,\n getCurrentInstance,\n h,\n inject,\n onMounted,\n onUnmounted,\n type PropType,\n ref,\n watch,\n} from 'vue';\nimport { VizDarkModeKey, VizThemeKey } from './context';\n\nexport interface ChartProps {\n spec: ChartSpec | LayerSpec | GraphSpec;\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n /** Rendering backend for point marks; see the vanilla `MountOptions.renderer`. */\n renderer?: 'auto' | 'svg' | 'canvas';\n class?: string;\n style?: string | CSSProperties;\n}\n\nexport const Chart = defineComponent({\n name: 'Chart',\n props: {\n spec: {\n type: Object as PropType<ChartSpec | LayerSpec | GraphSpec>,\n required: true,\n },\n theme: {\n type: Object as PropType<ThemeConfig>,\n default: undefined,\n },\n darkMode: {\n type: String as PropType<DarkMode>,\n default: undefined,\n },\n renderer: {\n type: String as PropType<'auto' | 'svg' | 'canvas'>,\n default: undefined,\n },\n class: {\n type: String,\n default: undefined,\n },\n style: {\n type: [String, Object] as PropType<string | CSSProperties>,\n default: undefined,\n },\n selectedElement: {\n type: Object as PropType<ElementRef>,\n default: undefined,\n },\n highlight: {\n type: [Array, null] as unknown as PropType<string[] | null>,\n default: undefined,\n },\n editable: {\n type: Boolean as PropType<boolean>,\n default: undefined,\n },\n },\n emits: {\n 'mark-click': (_event: MarkEvent) => true,\n 'mark-hover': (_event: MarkEvent) => true,\n 'mark-leave': () => true,\n 'legend-toggle': (_series: string, _visible: boolean) => true,\n 'annotation-click': (_annotation: Annotation, _event: MouseEvent) => true,\n 'annotation-edit': (_annotation: TextAnnotation, _updatedOffset: AnnotationOffset) => true,\n edit: (_edit: ElementEdit) => true,\n select: (_element: ElementRef) => true,\n deselect: (_element: ElementRef) => true,\n 'text-edit': (_element: ElementRef, _oldText: string, _newText: string) => true,\n 'data-point-click': (_data: Record<string, unknown>) => true,\n },\n setup(props, { emit, expose }) {\n const containerRef = ref<HTMLDivElement | null>(null);\n let instance: ChartInstance | null = null;\n let prevSpec = '';\n\n // Inject theme/darkMode from provider as fallbacks\n const contextTheme = inject(VizThemeKey, undefined);\n const contextDarkMode = inject(VizDarkModeKey, undefined);\n\n // Check which event listeners are bound by the parent.\n // Vue 3 passes listeners as onXxx props on the component vnode.\n // We cache this at setup time since it won't change.\n const vm = getCurrentInstance();\n const vnodeProps = vm?.vnode.props ?? {};\n const hasAnnotationEditListener =\n 'onAnnotation-edit' in vnodeProps || 'onAnnotationEdit' in vnodeProps;\n const hasEditListener = 'onEdit' in vnodeProps;\n const hasSelectListener = 'onSelect' in vnodeProps;\n const hasDeselectListener = 'onDeselect' in vnodeProps;\n const hasTextEditListener = 'onText-edit' in vnodeProps || 'onTextEdit' in vnodeProps;\n\n function resolveTheme(): ThemeConfig | undefined {\n return props.theme ?? contextTheme?.value;\n }\n\n function resolveDarkMode(): DarkMode | undefined {\n return props.darkMode ?? contextDarkMode?.value;\n }\n\n function mountChart() {\n const container = containerRef.value;\n if (!container) return;\n\n const options: MountOptions = {\n theme: resolveTheme(),\n darkMode: resolveDarkMode(),\n renderer: props.renderer,\n onDataPointClick: (data: Record<string, unknown>) => emit('data-point-click', data),\n onMarkClick: (event: MarkEvent) => emit('mark-click', event),\n onMarkHover: (event: MarkEvent) => emit('mark-hover', event),\n onMarkLeave: () => emit('mark-leave'),\n onLegendToggle: (series: string, visible: boolean) =>\n emit('legend-toggle', series, visible),\n onAnnotationClick: (annotation: Annotation, event: MouseEvent) =>\n emit('annotation-click', annotation, event),\n // Only include editing callbacks when the parent binds a listener.\n // Without this gate, every chart gets drag editing wired up.\n ...(hasAnnotationEditListener\n ? {\n onAnnotationEdit: (annotation: TextAnnotation, updatedOffset: AnnotationOffset) =>\n emit('annotation-edit', annotation, updatedOffset),\n }\n : {}),\n ...(hasEditListener ? { onEdit: (edit: ElementEdit) => emit('edit', edit) } : {}),\n ...(hasSelectListener\n ? { onSelect: (element: ElementRef) => emit('select', element) }\n : {}),\n ...(hasDeselectListener\n ? { onDeselect: (element: ElementRef) => emit('deselect', element) }\n : {}),\n ...(hasTextEditListener\n ? {\n onTextEdit: (element: ElementRef, oldText: string, newText: string) =>\n emit('text-edit', element, oldText, newText),\n }\n : {}),\n ...(props.editable != null ? { editable: props.editable } : {}),\n ...(props.selectedElement ? { selectedElement: props.selectedElement } : {}),\n responsive: true,\n };\n\n instance = createChart(container, props.spec, options);\n prevSpec = JSON.stringify(props.spec);\n if (props.highlight !== undefined) {\n instance.setHighlight(props.highlight ?? null);\n }\n }\n\n function destroyChart() {\n instance?.destroy();\n instance = null;\n prevSpec = '';\n }\n\n // Expose imperative methods for parent ref access\n expose({\n getSelectedElement(): ElementRef | null {\n return instance?.getSelectedElement() ?? null;\n },\n select(elementRef: ElementRef): void {\n instance?.select(elementRef);\n },\n deselect(): void {\n instance?.deselect();\n },\n get instance() {\n return instance;\n },\n });\n\n onMounted(() => {\n mountChart();\n });\n\n onUnmounted(() => {\n destroyChart();\n });\n\n // Watch spec changes: update if only spec changed, recreate if theme/darkMode changed\n watch(\n () => JSON.stringify(props.spec),\n (newVal) => {\n if (!instance) return;\n if (newVal !== prevSpec) {\n prevSpec = newVal;\n instance.update(props.spec, { selectedElement: props.selectedElement });\n }\n },\n );\n\n // Watch selectedElement prop changes\n watch(\n () => props.selectedElement,\n (newVal) => {\n if (!instance) return;\n if (newVal) {\n instance.select(newVal);\n } else {\n instance.deselect();\n }\n },\n );\n\n // Watch highlight prop changes\n watch(\n () => props.highlight,\n (newVal) => {\n if (!instance) return;\n instance.setHighlight(newVal ?? null);\n },\n );\n\n // Recreate chart when theme, darkMode, renderer, or editable change\n watch(\n [\n () => props.theme,\n () => props.darkMode,\n () => props.renderer,\n () => props.editable,\n () => contextTheme?.value,\n () => contextDarkMode?.value,\n ],\n () => {\n if (!containerRef.value) return;\n destroyChart();\n mountChart();\n },\n );\n\n const rootClass = () => {\n const base = 'oc-chart-root';\n return props.class ? `${base} ${props.class}` : base;\n };\n\n return () =>\n h('div', {\n ref: containerRef,\n class: rootClass(),\n style: props.style,\n });\n },\n});\n","/**\n * Vue scrollytelling shell around the vanilla `createChartStory`.\n *\n * Mirrors the React `<ChartStory>`: a sticky chart panel plus a scrolling\n * narrative column whose blocks advance the story. The vanilla driver owns\n * cumulative patch application, mark morphing, crossfade, and camera; this\n * component owns only Vue lifecycle and the sticky layout.\n *\n * Narrative is provided as the default slot's children (one root node per\n * step) or via the `narrative` prop (an array of vnodes/strings). Pass `step`\n * to drive it externally; omit for self-driving scroll.\n */\n\nimport type { ChartSpec, GeoMapSpec, GraphSpec, LayerSpec } from '@opendata-ai/openchart-core';\nimport type { MountOptions } from '@opendata-ai/openchart-vanilla';\nimport {\n type ChartStoryInstance,\n type ChartStoryOptions,\n createChartStory,\n} from '@opendata-ai/openchart-vanilla/story';\nimport {\n type CSSProperties,\n defineComponent,\n h,\n onMounted,\n onUnmounted,\n type PropType,\n ref,\n type VNode,\n watch,\n} from 'vue';\n\nexport interface ChartStoryProps {\n spec: ChartSpec | LayerSpec | GraphSpec | GeoMapSpec;\n steps: ChartStoryOptions['steps'];\n narrative?: VNode[];\n step?: number;\n triggerPosition?: number;\n cameraMode?: 'step' | 'scrub';\n mountOptions?: MountOptions;\n}\n\nconst sectionStyle: CSSProperties = {\n position: 'relative',\n display: 'grid',\n gridTemplateColumns: 'minmax(0, 26rem) minmax(0, 1fr)',\n gap: '3rem',\n alignItems: 'start',\n};\n\nconst stepStyle: CSSProperties = {\n minHeight: '80vh',\n display: 'flex',\n alignItems: 'center',\n};\n\nconst panelStyle: CSSProperties = {\n position: 'sticky',\n top: '2rem',\n height: 'calc(100vh - 4rem)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n};\n\nexport const ChartStory = defineComponent({\n name: 'ChartStory',\n props: {\n spec: {\n type: Object as PropType<ChartSpec | LayerSpec | GraphSpec | GeoMapSpec>,\n required: true,\n },\n steps: {\n type: Array as PropType<ChartStoryOptions['steps']>,\n required: true,\n },\n narrative: {\n type: Array as PropType<VNode[]>,\n default: undefined,\n },\n step: {\n type: Number,\n default: undefined,\n },\n triggerPosition: {\n type: Number,\n default: undefined,\n },\n cameraMode: {\n type: String as PropType<'step' | 'scrub'>,\n default: undefined,\n },\n mountOptions: {\n type: Object as PropType<MountOptions>,\n default: undefined,\n },\n },\n setup(props, { slots, expose }) {\n const sectionRef = ref<HTMLElement | null>(null);\n const mountRef = ref<HTMLDivElement | null>(null);\n const stepEls = ref<Array<HTMLElement | null>>([]);\n let story: ChartStoryInstance | null = null;\n\n onMounted(() => {\n const mount = mountRef.value;\n if (!mount) return;\n\n const blocks = props.narrative ?? [];\n if (blocks.length > 0 && blocks.length !== props.steps.length) {\n console.warn(\n `[openchart] ChartStory: narrative length (${blocks.length}) does not match steps length (${props.steps.length}). Each step should have a corresponding narrative element.`,\n );\n }\n\n story = createChartStory(\n mount,\n {\n spec: props.spec,\n steps: props.steps,\n triggerPosition: props.triggerPosition,\n cameraMode: props.cameraMode,\n },\n props.mountOptions,\n );\n if (sectionRef.value) story.setContainer(sectionRef.value);\n stepEls.value.forEach((el, i) => {\n if (el) story?.registerStep(i, el);\n });\n if (props.step !== undefined) story.goTo(props.step);\n });\n\n watch(\n () => props.step,\n (next) => {\n if (next !== undefined) story?.goTo(next);\n },\n );\n\n onUnmounted(() => {\n story?.destroy();\n story = null;\n });\n\n expose({\n goTo(index: number) {\n story?.goTo(index);\n },\n get instance() {\n return story;\n },\n });\n\n return () => {\n // Prefer the `narrative` prop; fall back to default slot children so\n // consumers can author steps as template markup.\n const blocks = props.narrative ?? slots.default?.() ?? [];\n return h('section', { ref: sectionRef, style: sectionStyle }, [\n h(\n 'div',\n { style: { position: 'relative' } },\n blocks.map((content, i) =>\n h(\n 'div',\n {\n // Steps are a fixed ordered list, so the index is the stable\n // identity. Do not reorder or splice narrative entries at runtime\n // (that would remap step refs to the wrong content); rebuild the\n // whole story instead.\n key: i,\n ref: (el: unknown) => {\n stepEls.value[i] = el as HTMLElement | null;\n },\n 'data-oc-story-step': i,\n style: stepStyle,\n },\n [h('div', { style: { maxWidth: '36rem' } }, [content])],\n ),\n ),\n ),\n h('div', { style: panelStyle }, [h('div', { ref: mountRef, style: { width: '100%' } })]),\n ]);\n };\n },\n});\n","/**\n * useChart: composable for manual chart lifecycle control.\n *\n * Provides a template ref to attach to a container div. The chart\n * mounts automatically and updates when the spec changes.\n */\n\nimport type {\n ChartLayout,\n ChartSpec,\n DarkMode,\n GraphSpec,\n LayerSpec,\n ThemeConfig,\n} from '@opendata-ai/openchart-core';\nimport { type ChartInstance, createChart, type MountOptions } from '@opendata-ai/openchart-vanilla';\nimport { onMounted, onUnmounted, type Ref, ref, type ShallowRef, shallowRef, watch } from 'vue';\n\nexport interface UseChartOptions {\n /** Theme overrides. */\n theme?: ThemeConfig;\n /** Dark mode setting. */\n darkMode?: DarkMode;\n /** Data point click handler. */\n onDataPointClick?: MountOptions['onDataPointClick'];\n /** Enable responsive resizing. Defaults to true. */\n responsive?: boolean;\n /** Rendering backend for point marks; see the vanilla `MountOptions.renderer`. */\n renderer?: MountOptions['renderer'];\n}\n\nexport interface UseChartReturn {\n /** Template ref to attach to the container div. */\n containerRef: Ref<HTMLDivElement | null>;\n /** The chart instance (null until mounted). */\n chart: ShallowRef<ChartInstance | null>;\n /** The current compiled layout (null until mounted). */\n layout: ShallowRef<ChartLayout | null>;\n}\n\n/**\n * Composable for manual chart lifecycle control.\n *\n * Attach the returned containerRef to a container div via `ref=\"containerRef\"`.\n * The chart mounts automatically and updates when the spec changes.\n */\nexport function useChart(\n spec: Ref<ChartSpec | LayerSpec | GraphSpec>,\n options?: UseChartOptions,\n): UseChartReturn {\n const containerRef = ref<HTMLDivElement | null>(null);\n const chart = shallowRef<ChartInstance | null>(null);\n const layout = shallowRef<ChartLayout | null>(null);\n\n function mount() {\n const container = containerRef.value;\n if (!container) return;\n\n const mountOpts: MountOptions = {\n theme: options?.theme,\n darkMode: options?.darkMode,\n onDataPointClick: options?.onDataPointClick,\n responsive: options?.responsive,\n renderer: options?.renderer,\n };\n\n const instance = createChart(container, spec.value, mountOpts);\n chart.value = instance;\n layout.value = instance.layout;\n }\n\n function destroy() {\n chart.value?.destroy();\n chart.value = null;\n layout.value = null;\n }\n\n onMounted(() => {\n mount();\n });\n\n onUnmounted(() => {\n destroy();\n });\n\n // Update on spec change\n watch(spec, (newSpec) => {\n const instance = chart.value;\n if (!instance) return;\n instance.update(newSpec);\n layout.value = instance.layout;\n });\n\n return {\n containerRef,\n chart,\n layout,\n };\n}\n","/**\n * useDarkMode: composable that resolves a DarkMode preference to a boolean.\n *\n * - \"force\" -> true\n * - \"off\" -> false\n * - \"auto\" -> matches system preference (reactive to changes)\n */\n\nimport type { DarkMode } from '@opendata-ai/openchart-core';\nimport { onUnmounted, type Ref, ref, watch } from 'vue';\n\n/**\n * Resolve a DarkMode preference to a reactive boolean.\n *\n * For \"auto\" mode, watches the system `prefers-color-scheme` media query\n * and updates reactively when the user changes their OS theme.\n */\nexport function useDarkMode(mode: Ref<DarkMode | undefined>): Ref<boolean> {\n const isDark = ref(resolveInitial(mode.value));\n let cleanup: (() => void) | null = null;\n\n function setup(currentMode: DarkMode | undefined) {\n // Clean up previous listener\n cleanup?.();\n cleanup = null;\n\n if (currentMode !== 'auto') {\n isDark.value = currentMode === 'force';\n return;\n }\n\n if (typeof window === 'undefined' || !window.matchMedia) {\n isDark.value = false;\n return;\n }\n\n const mq = window.matchMedia('(prefers-color-scheme: dark)');\n isDark.value = mq.matches;\n\n const handler = (e: MediaQueryListEvent) => {\n isDark.value = e.matches;\n };\n mq.addEventListener('change', handler);\n cleanup = () => mq.removeEventListener('change', handler);\n }\n\n // Run setup for initial value\n setup(mode.value);\n\n // React to mode changes\n watch(mode, (newMode) => {\n setup(newMode);\n });\n\n onUnmounted(() => {\n cleanup?.();\n cleanup = null;\n });\n\n return isDark;\n}\n\nfunction resolveInitial(mode?: DarkMode): boolean {\n if (mode === 'force') return true;\n if (mode === 'off' || mode === undefined) return false;\n // \"auto\"\n if (typeof window !== 'undefined' && window.matchMedia) {\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\n }\n return false;\n}\n","/**\n * useGraph: composable for imperative graph control.\n *\n * Provides a template ref to pass to <Graph /> and exposes graph methods\n * (search, zoom, select, fly, highlight) for programmatic control of the\n * graph instance. The full vanilla GraphInstance API is threaded through.\n */\n\nimport type { GraphSpec } from '@opendata-ai/openchart-core';\nimport type {\n CameraFlightOptions,\n GraphCamera,\n GraphFlyTarget,\n GraphHighlightTarget,\n GraphInstance,\n GraphLegendData,\n} from '@opendata-ai/openchart-vanilla';\nimport { type Ref, ref } from 'vue';\n\n// Re-exported rather than redeclared so the 3D pose fields (`position`,\n// `target`) stay visible to typed consumers of the Vue wrapper.\nexport type { GraphCamera, GraphFlyTarget } from '@opendata-ai/openchart-vanilla';\n\n/** Handle exposed by Graph component via expose(). */\nexport interface GraphHandle {\n search: (query: string) => void;\n clearSearch: () => void;\n getSearchMatches: () => string[];\n zoomToFit: (opts?: CameraFlightOptions & { padding?: number }) => void;\n zoomToNode: (nodeId: string, opts?: CameraFlightOptions & { scale?: number }) => void;\n flyTo: (target: GraphFlyTarget, opts?: CameraFlightOptions) => void;\n centerAt: (x: number, y: number, opts?: CameraFlightOptions) => void;\n getCamera: () => GraphCamera;\n selectNode: (nodeId: string, opts?: { fly?: boolean } & CameraFlightOptions) => void;\n getSelectedNodes: () => string[];\n highlight: (target: GraphHighlightTarget, opts?: { dimOpacity?: number }) => void;\n clearHighlight: () => void;\n getHighlight: () => string[] | null;\n getLegend: () => GraphLegendData | null;\n setActiveCategories: (values: string[]) => void;\n getActiveCategories: () => string[];\n /** Re-compile encoding/legend/chrome without restarting the simulation. */\n updateVisuals: (spec: GraphSpec) => void;\n /** The underlying GraphInstance from the vanilla adapter. */\n instance: GraphInstance | null;\n}\n\nexport interface UseGraphReturn {\n /** Template ref to pass to <Graph ref={graphRef} />. */\n graphRef: Ref<GraphHandle | null>;\n /** Search for nodes matching a query string. */\n search: (query: string) => void;\n /** Clear the current search. */\n clearSearch: () => void;\n /** Node ids currently matching the active search query. */\n getSearchMatches: () => string[];\n /** Zoom to fit all nodes in view. Animated by default; `{ duration: 0 }` snaps. */\n zoomToFit: (opts?: CameraFlightOptions & { padding?: number }) => void;\n /** Fly to a node and zoom in (default scale 2). */\n zoomToNode: (nodeId: string, opts?: CameraFlightOptions & { scale?: number }) => void;\n /** Fly the camera to a graph-space target. */\n flyTo: (target: GraphFlyTarget, opts?: CameraFlightOptions) => void;\n /** Center the camera on a graph-space point (keeps current zoom). */\n centerAt: (x: number, y: number, opts?: CameraFlightOptions) => void;\n /** Current camera transform. */\n getCamera: () => GraphCamera;\n /** Select a node by id; `{ fly: true }` also flies to it. */\n selectNode: (nodeId: string, opts?: { fly?: boolean } & CameraFlightOptions) => void;\n /** Get the currently selected node ids. */\n getSelectedNodes: () => string[];\n /**\n * Emphasize a set of nodes; eased via the focus model. Layers over the\n * standing category filter rather than replacing it.\n */\n highlight: (target: GraphHighlightTarget, opts?: { dimOpacity?: number }) => void;\n /**\n * Clear the transient highlight, returning to the standing category filter.\n * Does NOT clear that filter — use `setActiveCategories([])`.\n */\n clearHighlight: () => void;\n /** The effective highlighted node ids, or null when nothing is highlighted. */\n getHighlight: () => string[] | null;\n /** Headless snapshot of the legend. */\n getLegend: () => GraphLegendData | null;\n /** Set the active category filter declaratively (replaces legend toggle state). */\n setActiveCategories: (values: string[]) => void;\n /** Current active category values (empty = all active, no filter). */\n getActiveCategories: () => string[];\n}\n\n/**\n * Composable for imperative graph control.\n *\n * Usage:\n * ```vue\n * <script setup>\n * const { graphRef, search, zoomToFit } = useGraph();\n * </script>\n * <template>\n * <Graph ref=\"graphRef\" :spec=\"spec\" />\n * </template>\n * ```\n */\nexport function useGraph(): UseGraphReturn {\n const graphRef = ref<GraphHandle | null>(null);\n\n function search(query: string) {\n graphRef.value?.search(query);\n }\n\n function clearSearch() {\n graphRef.value?.clearSearch();\n }\n\n function getSearchMatches(): string[] {\n return graphRef.value?.getSearchMatches() ?? [];\n }\n\n function zoomToFit(opts?: CameraFlightOptions & { padding?: number }) {\n graphRef.value?.zoomToFit(opts);\n }\n\n function zoomToNode(nodeId: string, opts?: CameraFlightOptions & { scale?: number }) {\n graphRef.value?.zoomToNode(nodeId, opts);\n }\n\n function flyTo(target: GraphFlyTarget, opts?: CameraFlightOptions) {\n graphRef.value?.flyTo(target, opts);\n }\n\n function centerAt(x: number, y: number, opts?: CameraFlightOptions) {\n graphRef.value?.centerAt(x, y, opts);\n }\n\n function getCamera(): GraphCamera {\n return graphRef.value?.getCamera() ?? { x: 0, y: 0, k: 1 };\n }\n\n function selectNode(nodeId: string, opts?: { fly?: boolean } & CameraFlightOptions) {\n graphRef.value?.selectNode(nodeId, opts);\n }\n\n function getSelectedNodes(): string[] {\n return graphRef.value?.getSelectedNodes() ?? [];\n }\n\n function highlight(target: GraphHighlightTarget, opts?: { dimOpacity?: number }) {\n graphRef.value?.highlight(target, opts);\n }\n\n function clearHighlight() {\n graphRef.value?.clearHighlight();\n }\n\n function getHighlight(): string[] | null {\n return graphRef.value?.getHighlight() ?? null;\n }\n\n function getLegend(): GraphLegendData | null {\n return graphRef.value?.getLegend() ?? null;\n }\n\n function setActiveCategories(values: string[]) {\n graphRef.value?.setActiveCategories(values);\n }\n\n function getActiveCategories(): string[] {\n return graphRef.value?.getActiveCategories() ?? [];\n }\n\n return {\n graphRef,\n search,\n clearSearch,\n getSearchMatches,\n zoomToFit,\n zoomToNode,\n flyTo,\n centerAt,\n getCamera,\n selectNode,\n getSelectedNodes,\n highlight,\n clearHighlight,\n getHighlight,\n getLegend,\n setActiveCategories,\n getActiveCategories,\n };\n}\n","/**\n * useTable: composable for manual table lifecycle control.\n *\n * Attaches to a container ref, mounts a vanilla table instance,\n * and exposes the instance and current state.\n */\n\nimport type { TableSpec } from '@opendata-ai/openchart-core';\nimport {\n createTable,\n type TableInstance,\n type TableMountOptions,\n type TableState,\n} from '@opendata-ai/openchart-vanilla';\nimport { onMounted, onUnmounted, type Ref, ref, type ShallowRef, shallowRef, watch } from 'vue';\n\nexport interface UseTableReturn {\n /** Template ref to attach to the container div. */\n containerRef: Ref<HTMLDivElement | null>;\n /** The table instance (null until mounted). */\n table: ShallowRef<TableInstance | null>;\n /** The current table state (sort, search, page). */\n state: Ref<TableState>;\n}\n\n/**\n * Composable for manual table lifecycle control.\n *\n * Attach the returned containerRef to a container div via `ref=\"containerRef\"`.\n * The table mounts automatically and updates when the spec changes.\n */\nexport function useTable(spec: Ref<TableSpec>, options?: TableMountOptions): UseTableReturn {\n const containerRef = ref<HTMLDivElement | null>(null);\n const table = shallowRef<TableInstance | null>(null);\n const state = ref<TableState>({\n sort: null,\n search: '',\n page: 0,\n });\n\n const originalOnStateChange = options?.onStateChange;\n\n function handleStateChange(newState: TableState) {\n state.value = newState;\n originalOnStateChange?.(newState);\n }\n\n function mount() {\n const container = containerRef.value;\n if (!container) return;\n\n const mountOpts: TableMountOptions = {\n ...options,\n onStateChange: handleStateChange,\n };\n\n const instance = createTable(container, spec.value, mountOpts);\n table.value = instance;\n state.value = instance.getState();\n }\n\n function destroy() {\n table.value?.destroy();\n table.value = null;\n }\n\n onMounted(() => {\n mount();\n });\n\n onUnmounted(() => {\n destroy();\n });\n\n // Update on spec change\n watch(spec, (newSpec) => {\n const instance = table.value;\n if (!instance) return;\n instance.update(newSpec);\n state.value = instance.getState();\n });\n\n return {\n containerRef,\n table,\n state,\n };\n}\n","/**\n * useTableState: managed state composable for controlled table usage.\n *\n * Provides individual sort/search/page state with setters and a\n * resetState function to return to initial values.\n */\n\nimport type { SortState } from '@opendata-ai/openchart-core';\nimport { type Ref, ref } from 'vue';\n\nexport interface UseTableStateReturn {\n sort: Ref<SortState | null>;\n setSort: (sort: SortState | null) => void;\n search: Ref<string>;\n setSearch: (query: string) => void;\n page: Ref<number>;\n setPage: (page: number) => void;\n resetState: () => void;\n}\n\nexport interface UseTableStateOptions {\n sort?: SortState | null;\n search?: string;\n page?: number;\n}\n\n/**\n * Composable for managing table state (sort, search, page).\n *\n * Use with the DataTable component's controlled props:\n * ```vue\n * <script setup>\n * const { sort, search, page, setSort, setSearch, setPage } = useTableState();\n * </script>\n * <template>\n * <DataTable\n * :spec=\"spec\"\n * :sort=\"sort\"\n * :search=\"search\"\n * :page=\"page\"\n * @update:sort=\"setSort\"\n * @update:search=\"setSearch\"\n * @update:page=\"setPage\"\n * />\n * </template>\n * ```\n */\nexport function useTableState(initialState?: UseTableStateOptions): UseTableStateReturn {\n const sort = ref<SortState | null>(initialState?.sort ?? null);\n const search = ref(initialState?.search ?? '');\n const page = ref(initialState?.page ?? 0);\n\n function setSort(newSort: SortState | null) {\n sort.value = newSort;\n }\n\n function setSearch(query: string) {\n search.value = query;\n }\n\n function setPage(newPage: number) {\n page.value = newPage;\n }\n\n function resetState() {\n sort.value = initialState?.sort ?? null;\n search.value = initialState?.search ?? '';\n page.value = initialState?.page ?? 0;\n }\n\n return {\n sort,\n setSort,\n search,\n setSearch,\n page,\n setPage,\n resetState,\n };\n}\n","/**\n * DataTable component: Vue wrapper around the vanilla table adapter.\n *\n * Mounts a table instance on render, updates when spec changes,\n * and cleans up on unmount. Supports both controlled and uncontrolled modes\n * for sort, search, and pagination state.\n */\n\nimport type { DarkMode, SortState, TableSpec, ThemeConfig } from '@opendata-ai/openchart-core';\nimport {\n createTable,\n type TableInstance,\n type TableMountOptions,\n} from '@opendata-ai/openchart-vanilla';\nimport {\n type CSSProperties,\n defineComponent,\n h,\n inject,\n onMounted,\n onUnmounted,\n type PropType,\n ref,\n watch,\n} from 'vue';\nimport { VizDarkModeKey, VizThemeKey } from './context';\n\nexport interface DataTableProps {\n spec: TableSpec;\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n class?: string;\n style?: string | CSSProperties;\n sort?: SortState | null;\n search?: string;\n page?: number;\n}\n\nexport const DataTable = defineComponent({\n name: 'DataTable',\n props: {\n spec: {\n type: Object as PropType<TableSpec>,\n required: true,\n },\n theme: {\n type: Object as PropType<ThemeConfig>,\n default: undefined,\n },\n darkMode: {\n type: String as PropType<DarkMode>,\n default: undefined,\n },\n class: {\n type: String,\n default: undefined,\n },\n style: {\n type: [String, Object] as PropType<string | CSSProperties>,\n default: undefined,\n },\n sort: {\n type: [Object, null] as PropType<SortState | null>,\n default: undefined,\n },\n search: {\n type: String,\n default: undefined,\n },\n page: {\n type: Number,\n default: undefined,\n },\n },\n emits: {\n 'row-click': (_row: Record<string, unknown>) => true,\n 'update:sort': (_sort: SortState | null) => true,\n 'update:search': (_query: string) => true,\n 'update:page': (_page: number) => true,\n },\n setup(props, { emit }) {\n const containerRef = ref<HTMLDivElement | null>(null);\n let instance: TableInstance | null = null;\n\n // Inject theme/darkMode from provider as fallbacks\n const contextTheme = inject(VizThemeKey, undefined);\n const contextDarkMode = inject(VizDarkModeKey, undefined);\n\n function resolveTheme(): ThemeConfig | undefined {\n return props.theme ?? contextTheme?.value;\n }\n\n function resolveDarkMode(): DarkMode | undefined {\n return props.darkMode ?? contextDarkMode?.value;\n }\n\n function isControlled(): boolean {\n return props.sort !== undefined || props.search !== undefined || props.page !== undefined;\n }\n\n let prevSpec = '';\n\n function mountTable() {\n const container = containerRef.value;\n if (!container) return;\n\n const mountOptions: TableMountOptions = {\n theme: resolveTheme(),\n darkMode: resolveDarkMode(),\n onRowClick: (row: Record<string, unknown>) => emit('row-click', row),\n responsive: true,\n onStateChange: (state) => {\n if (state.sort !== undefined) emit('update:sort', state.sort);\n if (state.search !== undefined) emit('update:search', state.search);\n if (state.page !== undefined) emit('update:page', state.page);\n },\n };\n\n if (isControlled()) {\n mountOptions.externalState = {\n sort: props.sort ?? null,\n search: props.search ?? '',\n page: props.page ?? 0,\n };\n }\n\n instance = createTable(container, props.spec, mountOptions);\n prevSpec = JSON.stringify(props.spec);\n }\n\n function destroyTable() {\n instance?.destroy();\n instance = null;\n prevSpec = '';\n }\n\n onMounted(() => {\n mountTable();\n });\n\n onUnmounted(() => {\n destroyTable();\n });\n\n // Watch spec changes via JSON.stringify comparison (consistent with Chart/Graph)\n watch(\n () => JSON.stringify(props.spec),\n (newVal) => {\n if (!instance) return;\n if (newVal !== prevSpec) {\n prevSpec = newVal;\n instance.update(props.spec);\n }\n },\n );\n\n // Recreate when theme or darkMode change\n watch(\n [\n () => props.theme,\n () => props.darkMode,\n () => contextTheme?.value,\n () => contextDarkMode?.value,\n ],\n () => {\n if (!containerRef.value) return;\n destroyTable();\n mountTable();\n },\n );\n\n // Sync controlled state without remounting\n watch([() => props.sort, () => props.search, () => props.page], () => {\n if (!instance || !isControlled()) return;\n instance.setState({\n sort: props.sort ?? null,\n search: props.search ?? '',\n page: props.page ?? 0,\n });\n });\n\n const rootClass = () => {\n const base = 'oc-table-root';\n return props.class ? `${base} ${props.class}` : base;\n };\n\n return () =>\n h('div', {\n ref: containerRef,\n class: rootClass(),\n style: props.style,\n });\n },\n});\n","/**\n * Vue Map component: thin wrapper around the vanilla adapter.\n *\n * Mounts a map instance on render, updates when spec changes,\n * and cleans up on unmount. All heavy lifting is done by the vanilla\n * createGeoMap() function.\n */\n\nimport type { DarkMode, GeoMapSpec, ThemeConfig } from '@opendata-ai/openchart-core';\nimport {\n createGeoMap,\n type GeoMapInstance,\n type GeoMapMarkEvent,\n type GeoMapMountOptions,\n} from '@opendata-ai/openchart-vanilla';\nimport {\n type CSSProperties,\n defineComponent,\n h,\n inject,\n onMounted,\n onUnmounted,\n type PropType,\n ref,\n watch,\n} from 'vue';\nimport { VizDarkModeKey, VizThemeKey } from './context';\n\nexport interface GeoMapProps {\n spec: GeoMapSpec;\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n class?: string;\n style?: string | CSSProperties;\n}\n\nexport const GeoMap = defineComponent({\n name: 'GeoMap',\n props: {\n spec: {\n type: Object as PropType<GeoMapSpec>,\n required: true,\n },\n theme: {\n type: Object as PropType<ThemeConfig>,\n default: undefined,\n },\n darkMode: {\n type: String as PropType<DarkMode>,\n default: undefined,\n },\n class: {\n type: String,\n default: undefined,\n },\n style: {\n type: [String, Object] as PropType<string | CSSProperties>,\n default: undefined,\n },\n },\n emits: {\n 'mark-click': (_event: GeoMapMarkEvent) => true,\n 'mark-hover': (_event: GeoMapMarkEvent | null) => true,\n },\n setup(props, { emit, expose }) {\n const containerRef = ref<HTMLDivElement | null>(null);\n let instance: GeoMapInstance | null = null;\n let prevSpec = '';\n\n // Inject theme/darkMode from provider as fallbacks\n const contextTheme = inject(VizThemeKey, undefined);\n const contextDarkMode = inject(VizDarkModeKey, undefined);\n\n function resolveTheme(): ThemeConfig | undefined {\n return props.theme ?? contextTheme?.value;\n }\n\n function resolveDarkMode(): DarkMode | undefined {\n return props.darkMode ?? contextDarkMode?.value;\n }\n\n function mountMap() {\n const container = containerRef.value;\n if (!container) return;\n\n const options: GeoMapMountOptions = {\n theme: resolveTheme(),\n darkMode: resolveDarkMode(),\n onMarkClick: (feature) => emit('mark-click', feature),\n onMarkHover: (feature) => emit('mark-hover', feature),\n responsive: true,\n };\n\n instance = createGeoMap(container, props.spec, options);\n prevSpec = JSON.stringify(props.spec);\n }\n\n function destroyMap() {\n instance?.destroy();\n instance = null;\n prevSpec = '';\n }\n\n // Expose imperative access to the instance\n expose({\n get instance() {\n return instance;\n },\n });\n\n onMounted(() => {\n mountMap();\n });\n\n onUnmounted(() => {\n destroyMap();\n });\n\n // Watch spec changes\n watch(\n () => JSON.stringify(props.spec),\n (newVal) => {\n if (!instance) return;\n if (newVal !== prevSpec) {\n prevSpec = newVal;\n instance.update(props.spec);\n }\n },\n );\n\n // Recreate map when theme or darkMode change\n watch(\n [\n () => props.theme,\n () => props.darkMode,\n () => contextTheme?.value,\n () => contextDarkMode?.value,\n ],\n () => {\n if (!containerRef.value) return;\n destroyMap();\n mountMap();\n },\n );\n\n const rootClass = () => {\n const base = 'oc-map-root';\n return props.class ? `${base} ${props.class}` : base;\n };\n\n return () =>\n h('div', {\n ref: containerRef,\n class: rootClass(),\n style: props.style,\n });\n },\n});\n","/**\n * Vue Graph component: thin wrapper around the vanilla adapter.\n *\n * Mounts a graph instance on render, updates when spec changes,\n * and cleans up on unmount. All heavy lifting is done by the vanilla\n * createGraph() function.\n *\n * Exposes imperative methods via defineExpose for use with useGraph().\n */\n\nimport type { DarkMode, GraphSpec, ThemeConfig } from '@opendata-ai/openchart-core';\nimport {\n createGraph,\n type GraphCamera,\n type GraphInstance,\n type GraphMountOptions,\n type GraphTooltipFormatter,\n} from '@opendata-ai/openchart-vanilla';\nimport {\n type CSSProperties,\n defineComponent,\n h,\n inject,\n onMounted,\n onUnmounted,\n type PropType,\n ref,\n watch,\n} from 'vue';\nimport { VizDarkModeKey, VizThemeKey } from './context';\n\n/** Tooltip prop: `false` off, `true` default, or an object with a formatter. */\nexport type GraphTooltipProp = boolean | { formatter?: GraphTooltipFormatter };\n/** Legend prop: `false` off, `true` default, or an object toggling interactivity/counts. */\nexport type GraphLegendProp = boolean | { interactive?: boolean; counts?: boolean };\n\nexport interface GraphProps {\n spec: GraphSpec;\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n tooltip?: GraphTooltipProp;\n legend?: GraphLegendProp;\n fitOnLoad?: boolean;\n /** How much closer than the fit the opening camera sits: a multiplier on the fit (2 = twice as close), not an absolute zoom level. Default 1. Read once at mount; `zoomToFit()` still frames the whole graph. */\n initialZoom?: number;\n class?: string;\n style?: string | CSSProperties;\n}\n\n/** True when the tooltip is on (only the on/off decision gates recreation). */\nfunction tooltipOn(tooltip: GraphTooltipProp | undefined): boolean {\n return tooltip !== false;\n}\n\nexport const Graph = defineComponent({\n name: 'Graph',\n props: {\n spec: {\n type: Object as PropType<GraphSpec>,\n required: true,\n },\n theme: {\n type: Object as PropType<ThemeConfig>,\n default: undefined,\n },\n darkMode: {\n type: String as PropType<DarkMode>,\n default: undefined,\n },\n tooltip: {\n type: [Boolean, Object] as PropType<GraphTooltipProp>,\n default: undefined,\n },\n legend: {\n type: [Boolean, Object] as PropType<GraphLegendProp>,\n default: undefined,\n },\n fitOnLoad: {\n type: Boolean,\n default: undefined,\n },\n initialZoom: {\n type: Number,\n default: undefined,\n },\n class: {\n type: String,\n default: undefined,\n },\n style: {\n type: [String, Object] as PropType<string | CSSProperties>,\n default: undefined,\n },\n },\n emits: {\n 'node-click': (_node: Record<string, unknown>) => true,\n 'node-double-click': (_node: Record<string, unknown>) => true,\n 'node-hover': (_node: Record<string, unknown> | null) => true,\n 'edge-hover': (_edge: Record<string, unknown> | null) => true,\n 'selection-change': (_nodeIds: string[]) => true,\n 'legend-hover': (_entry: { field: string; value: string } | null) => true,\n 'legend-toggle': (_activeValues: string[]) => true,\n 'highlight-change': (_nodeIds: string[] | null) => true,\n 'camera-change': (_camera: GraphCamera) => true,\n },\n setup(props, { emit, expose }) {\n const containerRef = ref<HTMLDivElement | null>(null);\n let instance: GraphInstance | null = null;\n let prevSpec = '';\n // First mount plays the entrance; theme/darkMode-only recreations suppress it.\n let mountedOnce = false;\n\n // Inject theme/darkMode from provider as fallbacks\n const contextTheme = inject(VizThemeKey, undefined);\n const contextDarkMode = inject(VizDarkModeKey, undefined);\n\n function resolveTheme(): ThemeConfig | undefined {\n return props.theme ?? contextTheme?.value;\n }\n\n function resolveDarkMode(): DarkMode | undefined {\n return props.darkMode ?? contextDarkMode?.value;\n }\n\n // Stable tooltip formatter wrapper. Vue props are reactive, so reading\n // `props.tooltip` at CALL time always sees the latest formatter — no stale\n // closure, no recreation when the formatter changes. When the tooltip is on\n // we always hand the vanilla layer this wrapper (falling back to defaults),\n // so a formatter can be added or swapped per-render without a remount.\n const stableTooltipFormatter: GraphTooltipFormatter = (item, defaults) => {\n const t = props.tooltip;\n const fn = t && typeof t === 'object' ? t.formatter : undefined;\n return fn ? fn(item, defaults) : defaults;\n };\n\n // `playEntrance` is set only by the dimension remount: 2D and 3D are\n // different renderers, so the new one should play its entrance instead of\n // being suppressed the way a theme-only recreation is.\n function mountGraph(playEntrance = false) {\n const container = containerRef.value;\n if (!container) return;\n\n const tooltipOption: GraphMountOptions['tooltip'] = tooltipOn(props.tooltip)\n ? { formatter: stableTooltipFormatter }\n : false;\n\n const options: GraphMountOptions = {\n theme: resolveTheme(),\n darkMode: resolveDarkMode(),\n tooltip: tooltipOption,\n legend: props.legend,\n fitOnLoad: props.fitOnLoad,\n initialZoom: props.initialZoom,\n onNodeClick: (node) => emit('node-click', node),\n onNodeDoubleClick: (node) => emit('node-double-click', node),\n onNodeHover: (node) => emit('node-hover', node),\n onEdgeHover: (edge) => emit('edge-hover', edge),\n onSelectionChange: (nodeIds) => emit('selection-change', nodeIds),\n onLegendHover: (entry) => emit('legend-hover', entry),\n onLegendToggle: (activeValues) => emit('legend-toggle', activeValues),\n onHighlightChange: (nodeIds) => emit('highlight-change', nodeIds),\n onCameraChange: (camera) => emit('camera-change', camera),\n responsive: true,\n suppressEntrance: mountedOnce && !playEntrance,\n };\n\n instance = createGraph(container, props.spec, options);\n prevSpec = JSON.stringify(props.spec);\n mountedOnce = true;\n }\n\n function destroyGraph() {\n instance?.destroy();\n instance = null;\n prevSpec = '';\n }\n\n // Expose imperative methods for useGraph() composable. Every method forwards\n // opts to the underlying instance so consumers get the full vanilla API.\n expose({\n search(query: string) {\n instance?.search(query);\n },\n clearSearch() {\n instance?.clearSearch();\n },\n getSearchMatches(): string[] {\n return instance?.getSearchMatches() ?? [];\n },\n zoomToFit(opts?: Parameters<GraphInstance['zoomToFit']>[0]) {\n instance?.zoomToFit(opts);\n },\n zoomToNode(nodeId: string, opts?: Parameters<GraphInstance['zoomToNode']>[1]) {\n instance?.zoomToNode(nodeId, opts);\n },\n flyTo(\n target: Parameters<GraphInstance['flyTo']>[0],\n opts?: Parameters<GraphInstance['flyTo']>[1],\n ) {\n instance?.flyTo(target, opts);\n },\n centerAt(x: number, y: number, opts?: Parameters<GraphInstance['centerAt']>[2]) {\n instance?.centerAt(x, y, opts);\n },\n getCamera() {\n return instance?.getCamera() ?? { x: 0, y: 0, k: 1 };\n },\n selectNode(nodeId: string, opts?: Parameters<GraphInstance['selectNode']>[1]) {\n instance?.selectNode(nodeId, opts);\n },\n getSelectedNodes(): string[] {\n return instance?.getSelectedNodes() ?? [];\n },\n highlight(\n target: Parameters<GraphInstance['highlight']>[0],\n opts?: Parameters<GraphInstance['highlight']>[1],\n ) {\n instance?.highlight(target, opts);\n },\n clearHighlight() {\n instance?.clearHighlight();\n },\n getHighlight() {\n return instance?.getHighlight() ?? null;\n },\n getLegend() {\n return instance?.getLegend() ?? null;\n },\n setActiveCategories(values: string[]) {\n instance?.setActiveCategories(values);\n },\n getActiveCategories(): string[] {\n return instance?.getActiveCategories() ?? [];\n },\n updateVisuals(spec: GraphSpec) {\n instance?.updateVisuals(spec);\n },\n get instance() {\n return instance;\n },\n });\n\n onMounted(() => {\n mountGraph();\n });\n\n onUnmounted(() => {\n destroyGraph();\n });\n\n // A dimension change picks a different renderer, and the renderer is chosen\n // once, at mount — so it is a remount, not an update(). Registered before\n // the spec watcher so the remount runs first; mountGraph refreshes prevSpec,\n // and the spec watcher then finds nothing to apply.\n watch(\n () => props.spec.dimensions ?? 2,\n () => {\n if (!containerRef.value) return;\n destroyGraph();\n mountGraph(true);\n },\n );\n\n // Watch spec changes\n watch(\n () => JSON.stringify(props.spec),\n (newVal) => {\n if (!instance) return;\n if (newVal !== prevSpec) {\n prevSpec = newVal;\n instance.update(props.spec);\n }\n },\n );\n\n // Recreate graph when theme or darkMode change (spec unchanged). mountedOnce\n // is already true here, so mountGraph passes suppressEntrance: true and the\n // entrance does not replay.\n watch(\n [\n () => props.theme,\n () => props.darkMode,\n () => contextTheme?.value,\n () => contextDarkMode?.value,\n ],\n () => {\n if (!containerRef.value) return;\n destroyGraph();\n mountGraph();\n },\n );\n\n const rootClass = () => {\n const base = 'oc-graph-root';\n return props.class ? `${base} ${props.class}` : base;\n };\n\n return () =>\n h('div', {\n ref: containerRef,\n class: rootClass(),\n style: props.style,\n });\n },\n});\n","/**\n * Vue Sankey component: thin wrapper around the vanilla adapter.\n *\n * Mounts a sankey instance on render, updates when spec changes,\n * and cleans up on unmount. All heavy lifting is done by the vanilla\n * createSankey() function.\n */\n\nimport type { DarkMode, SankeySpec, ThemeConfig } from '@opendata-ai/openchart-core';\nimport {\n createSankey,\n type SankeyInstance,\n type SankeyMountOptions,\n} from '@opendata-ai/openchart-vanilla';\nimport {\n type CSSProperties,\n defineComponent,\n h,\n inject,\n onMounted,\n onUnmounted,\n type PropType,\n ref,\n watch,\n} from 'vue';\nimport { VizDarkModeKey, VizThemeKey } from './context';\n\nexport interface SankeyProps {\n spec: SankeySpec;\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n class?: string;\n style?: string | CSSProperties;\n}\n\nexport const Sankey = defineComponent({\n name: 'Sankey',\n props: {\n spec: {\n type: Object as PropType<SankeySpec>,\n required: true,\n },\n theme: {\n type: Object as PropType<ThemeConfig>,\n default: undefined,\n },\n darkMode: {\n type: String as PropType<DarkMode>,\n default: undefined,\n },\n class: {\n type: String,\n default: undefined,\n },\n style: {\n type: [String, Object] as PropType<string | CSSProperties>,\n default: undefined,\n },\n },\n emits: {\n 'node-click': (_node: Record<string, unknown>) => true,\n 'link-click': (_link: Record<string, unknown>) => true,\n 'node-hover': (_node: Record<string, unknown> | null) => true,\n 'link-hover': (_link: Record<string, unknown> | null) => true,\n },\n setup(props, { emit, expose }) {\n const containerRef = ref<HTMLDivElement | null>(null);\n let instance: SankeyInstance | null = null;\n let prevSpec = '';\n\n // Inject theme/darkMode from provider as fallbacks\n const contextTheme = inject(VizThemeKey, undefined);\n const contextDarkMode = inject(VizDarkModeKey, undefined);\n\n function resolveTheme(): ThemeConfig | undefined {\n return props.theme ?? contextTheme?.value;\n }\n\n function resolveDarkMode(): DarkMode | undefined {\n return props.darkMode ?? contextDarkMode?.value;\n }\n\n function mountSankey() {\n const container = containerRef.value;\n if (!container) return;\n\n const options: SankeyMountOptions = {\n theme: resolveTheme(),\n darkMode: resolveDarkMode(),\n onNodeClick: (node: Record<string, unknown>) => emit('node-click', node),\n onLinkClick: (link: Record<string, unknown>) => emit('link-click', link),\n onNodeHover: (node: Record<string, unknown> | null) => emit('node-hover', node),\n onLinkHover: (link: Record<string, unknown> | null) => emit('link-hover', link),\n responsive: true,\n };\n\n instance = createSankey(container, props.spec, options);\n prevSpec = JSON.stringify(props.spec);\n }\n\n function destroySankey() {\n instance?.destroy();\n instance = null;\n prevSpec = '';\n }\n\n // Expose imperative access to the instance\n expose({\n get instance() {\n return instance;\n },\n });\n\n onMounted(() => {\n mountSankey();\n });\n\n onUnmounted(() => {\n destroySankey();\n });\n\n // Watch spec changes\n watch(\n () => JSON.stringify(props.spec),\n (newVal) => {\n if (!instance) return;\n if (newVal !== prevSpec) {\n prevSpec = newVal;\n instance.update(props.spec);\n }\n },\n );\n\n // Recreate sankey when theme or darkMode change\n watch(\n [\n () => props.theme,\n () => props.darkMode,\n () => contextTheme?.value,\n () => contextDarkMode?.value,\n ],\n () => {\n if (!containerRef.value) return;\n destroySankey();\n mountSankey();\n },\n );\n\n const rootClass = () => {\n const base = 'oc-sankey-root';\n return props.class ? `${base} ${props.class}` : base;\n };\n\n return () =>\n h('div', {\n ref: containerRef,\n class: rootClass(),\n style: props.style,\n });\n },\n});\n","/**\n * VizThemeProvider: provides a theme and dark mode preference to all\n * descendant Chart, DataTable, and Graph components without prop drilling.\n *\n * Components use the context values as fallbacks when no explicit\n * `theme` or `darkMode` prop is passed.\n */\n\nimport type { DarkMode, ThemeConfig } from '@opendata-ai/openchart-core';\nimport { computed, defineComponent, type PropType, provide } from 'vue';\nimport { VizDarkModeKey, VizThemeKey } from './context';\n\nexport interface VizThemeProviderProps {\n theme: ThemeConfig | undefined;\n darkMode?: DarkMode;\n}\n\nexport const VizThemeProvider = defineComponent({\n name: 'VizThemeProvider',\n props: {\n theme: {\n type: Object as PropType<ThemeConfig | undefined>,\n default: undefined,\n },\n darkMode: {\n type: String as PropType<DarkMode>,\n default: undefined,\n },\n },\n setup(props, { slots }) {\n // Wrap in computed() so changes to props propagate reactively\n // through the injection system.\n const themeRef = computed(() => props.theme);\n const darkModeRef = computed(() => props.darkMode);\n\n provide(VizThemeKey, themeRef);\n provide(VizDarkModeKey, darkModeRef);\n\n return () => slots.default?.();\n },\n});\n","/**\n * Vue TileMap component: thin wrapper around the vanilla adapter.\n *\n * Mounts a tilemap instance on render, updates when spec changes,\n * and cleans up on unmount. All heavy lifting is done by the vanilla\n * createTileMap() function.\n */\n\nimport type { DarkMode, ThemeConfig, TileMapSpec } from '@opendata-ai/openchart-core';\nimport {\n createTileMap,\n type TileMapInstance,\n type TileMapMountOptions,\n} from '@opendata-ai/openchart-vanilla';\nimport {\n type CSSProperties,\n defineComponent,\n h,\n inject,\n onMounted,\n onUnmounted,\n type PropType,\n ref,\n watch,\n} from 'vue';\nimport { VizDarkModeKey, VizThemeKey } from './context';\n\nexport interface TileMapTileEvent {\n stateCode: string;\n stateName: string;\n value: number | null;\n data: Record<string, unknown>;\n}\n\nexport interface TileMapProps {\n spec: TileMapSpec;\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n class?: string;\n style?: string | CSSProperties;\n}\n\nexport const TileMap = defineComponent({\n name: 'TileMap',\n props: {\n spec: {\n type: Object as PropType<TileMapSpec>,\n required: true,\n },\n theme: {\n type: Object as PropType<ThemeConfig>,\n default: undefined,\n },\n darkMode: {\n type: String as PropType<DarkMode>,\n default: undefined,\n },\n class: {\n type: String,\n default: undefined,\n },\n style: {\n type: [String, Object] as PropType<string | CSSProperties>,\n default: undefined,\n },\n },\n emits: {\n 'tile-click': (_tile: TileMapTileEvent) => true,\n 'tile-hover': (_tile: TileMapTileEvent | null) => true,\n },\n setup(props, { emit, expose }) {\n const containerRef = ref<HTMLDivElement | null>(null);\n let instance: TileMapInstance | null = null;\n let prevSpec = '';\n\n // Inject theme/darkMode from provider as fallbacks\n const contextTheme = inject(VizThemeKey, undefined);\n const contextDarkMode = inject(VizDarkModeKey, undefined);\n\n function resolveTheme(): ThemeConfig | undefined {\n return props.theme ?? contextTheme?.value;\n }\n\n function resolveDarkMode(): DarkMode | undefined {\n return props.darkMode ?? contextDarkMode?.value;\n }\n\n function mountTileMap() {\n const container = containerRef.value;\n if (!container) return;\n\n const options: TileMapMountOptions = {\n theme: resolveTheme(),\n darkMode: resolveDarkMode(),\n onTileClick: (tile: TileMapTileEvent) => emit('tile-click', tile),\n onTileHover: (tile: TileMapTileEvent | null) => emit('tile-hover', tile),\n responsive: true,\n };\n\n instance = createTileMap(container, props.spec, options);\n prevSpec = JSON.stringify(props.spec);\n }\n\n function destroyTileMap() {\n instance?.destroy();\n instance = null;\n prevSpec = '';\n }\n\n // Expose imperative access to the instance\n expose({\n get instance() {\n return instance;\n },\n });\n\n onMounted(() => {\n mountTileMap();\n });\n\n onUnmounted(() => {\n destroyTileMap();\n });\n\n // Watch spec changes\n watch(\n () => JSON.stringify(props.spec),\n (newVal) => {\n if (!instance) return;\n if (newVal !== prevSpec) {\n prevSpec = newVal;\n instance.update(props.spec);\n }\n },\n );\n\n // Recreate tilemap when theme or darkMode change\n watch(\n [\n () => props.theme,\n () => props.darkMode,\n () => contextTheme?.value,\n () => contextDarkMode?.value,\n ],\n () => {\n if (!containerRef.value) return;\n destroyTileMap();\n mountTileMap();\n },\n );\n\n const rootClass = () => {\n const base = 'oc-tilemap-root';\n return props.class ? `${base} ${props.class}` : base;\n };\n\n return () =>\n h('div', {\n ref: containerRef,\n class: rootClass(),\n style: props.style,\n });\n },\n});\n","/**\n * Visualization routing component: renders Chart, DataTable, or Graph\n * based on the spec type. Use this when rendering arbitrary VizSpec values.\n *\n * For event handlers, use the specific component (Chart, DataTable, Graph) directly.\n */\n\nimport type { DarkMode, ThemeConfig, VizSpec } from '@opendata-ai/openchart-core';\nimport {\n isBarListSpec,\n isGeoMapSpec,\n isGraphSpec,\n isSankeySpec,\n isTableSpec,\n isTileMapSpec,\n} from '@opendata-ai/openchart-core';\nimport { type CSSProperties, defineComponent, h, type PropType } from 'vue';\nimport { BarList } from './BarList';\nimport { Chart } from './Chart';\nimport { DataTable } from './DataTable';\nimport { GeoMap } from './GeoMap';\nimport { Graph } from './Graph';\nimport { Sankey } from './Sankey';\nimport { TileMap } from './TileMap';\n\nexport interface VisualizationProps {\n spec: VizSpec;\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n class?: string;\n style?: string | CSSProperties;\n}\n\nexport const Visualization = defineComponent({\n name: 'Visualization',\n props: {\n spec: {\n type: Object as PropType<VizSpec>,\n required: true,\n },\n theme: {\n type: Object as PropType<ThemeConfig>,\n default: undefined,\n },\n darkMode: {\n type: String as PropType<DarkMode>,\n default: undefined,\n },\n class: {\n type: String,\n default: undefined,\n },\n style: {\n type: [String, Object] as PropType<string | CSSProperties>,\n default: undefined,\n },\n },\n setup(props) {\n return () => {\n const { spec, theme, darkMode, class: className, style } = props;\n const sharedProps = { theme, darkMode, class: className, style };\n\n if (isTableSpec(spec)) {\n return h(DataTable, { ...sharedProps, spec });\n }\n if (isGraphSpec(spec)) {\n return h(Graph, { ...sharedProps, spec });\n }\n if (isSankeySpec(spec)) {\n return h(Sankey, { ...sharedProps, spec });\n }\n if (isTileMapSpec(spec)) {\n return h(TileMap, { ...sharedProps, spec });\n }\n if (isBarListSpec(spec)) {\n return h(BarList, { ...sharedProps, spec });\n }\n if (isGeoMapSpec(spec)) {\n return h(GeoMap, { ...sharedProps, spec });\n }\n return h(Chart, { ...sharedProps, spec });\n };\n },\n});\n"],"mappings":"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","names":["inject","inject","defineComponent","h","inject","onMounted","onUnmounted","ref","watch","defineComponent","ref","inject","onMounted","onUnmounted","watch","h","defineComponent","h","onMounted","onUnmounted","ref","watch","createChart","onMounted","onUnmounted","ref","watch","onUnmounted","ref","watch","ref","onMounted","onUnmounted","ref","shallowRef","watch","ref","createTable","defineComponent","h","inject","onMounted","onUnmounted","ref","watch","defineComponent","ref","inject","createTable","onMounted","onUnmounted","watch","h","defineComponent","h","inject","onMounted","onUnmounted","ref","watch","defineComponent","ref","inject","onMounted","onUnmounted","watch","h","defineComponent","h","inject","onMounted","onUnmounted","ref","watch","defineComponent","ref","inject","onMounted","onUnmounted","watch","h","defineComponent","h","inject","onMounted","onUnmounted","ref","watch","defineComponent","ref","inject","onMounted","onUnmounted","watch","h","computed","defineComponent","defineComponent","computed","defineComponent","h","inject","onMounted","onUnmounted","ref","watch","defineComponent","ref","inject","onMounted","onUnmounted","watch","h","defineComponent","h","defineComponent","h"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/BarList.ts","../src/context.ts","../src/Chart.ts","../src/ChartStory.ts","../src/composables/useChart.ts","../src/composables/useDarkMode.ts","../src/composables/useGraph.ts","../src/composables/useTable.ts","../src/composables/useTableState.ts","../src/DataTable.ts","../src/GeoMap.ts","../src/Graph.ts","../src/Sankey.ts","../src/ThemeProvider.ts","../src/TileMap.ts","../src/Visualization.ts"],"sourcesContent":["/**\n * @opendata-ai/openchart-vue\n *\n * Vue 3 adapter for openchart. Provides <Chart />, <DataTable />, <Graph />,\n * and <VizThemeProvider /> components that wrap the vanilla adapter with\n * Vue lifecycle management.\n *\n * Re-exports the full core type system and utilities so Vue consumers\n * only need a single @opendata-ai/openchart-vue dependency.\n */\n\n// ---------------------------------------------------------------------------\n// Core: full type system, theme, colors, locale, accessibility, helpers\n// ---------------------------------------------------------------------------\n\nexport * from '@opendata-ai/openchart-core';\n\n// ---------------------------------------------------------------------------\n// Vanilla: export utilities (SVG/PNG/JPG/CSV)\n// ---------------------------------------------------------------------------\n\nexport type {\n JPGExportOptions,\n PNGExportOptions,\n SpecSequenceOptions,\n SVGExportOptions,\n} from '@opendata-ai/openchart-vanilla';\nexport {\n exportCSV,\n exportJPG,\n exportPNG,\n exportSpecSequence,\n exportSVG,\n exportSVGWithFonts,\n} from '@opendata-ai/openchart-vanilla';\n\n// ---------------------------------------------------------------------------\n// Engine: compile API and types not covered by core\n// ---------------------------------------------------------------------------\n\nexport type {\n ChartRenderer,\n CompiledGraphEdge,\n CompiledGraphNode,\n CompileResult,\n GraphCompilation,\n NormalizedBarListSpec,\n NormalizedChartSpec,\n NormalizedChrome,\n NormalizedGeoMapSpec,\n NormalizedGraphSpec,\n NormalizedSankeySpec,\n NormalizedSpec,\n NormalizedTableSpec,\n NormalizedTileMapSpec,\n SimulationConfig,\n ValidationError,\n ValidationErrorCode,\n ValidationResult,\n} from '@opendata-ai/openchart-engine';\nexport {\n clearRenderers,\n compile,\n compileBarList,\n compileChart,\n compileGeoMap,\n compileGraph,\n compileSankey,\n compileTable,\n compileTileMap,\n getChartRenderer,\n normalizeSpec,\n registerChartRenderer,\n validateSpec,\n} from '@opendata-ai/openchart-engine';\nexport type { BarListProps, BarListRowEvent } from './BarList';\nexport { BarList } from './BarList';\n// Components\nexport type { ChartProps } from './Chart';\nexport { Chart } from './Chart';\nexport type { ChartStoryProps } from './ChartStory';\n// Scrollytelling\nexport { ChartStory } from './ChartStory';\n// Composables\nexport type { UseChartOptions, UseChartReturn } from './composables/useChart';\nexport { useChart } from './composables/useChart';\nexport { useDarkMode } from './composables/useDarkMode';\nexport type { GraphHandle, UseGraphReturn } from './composables/useGraph';\nexport { useGraph } from './composables/useGraph';\nexport type { UseTableReturn } from './composables/useTable';\nexport { useTable } from './composables/useTable';\nexport type { UseTableStateOptions, UseTableStateReturn } from './composables/useTableState';\nexport { useTableState } from './composables/useTableState';\n// Context (injection keys and composables)\nexport { useVizDarkMode, useVizTheme, VizDarkModeKey, VizThemeKey } from './context';\nexport type { DataTableProps } from './DataTable';\nexport { DataTable } from './DataTable';\nexport type { GeoMapProps } from './GeoMap';\nexport { GeoMap } from './GeoMap';\nexport type { GraphProps } from './Graph';\nexport { Graph } from './Graph';\nexport type { SankeyProps } from './Sankey';\nexport { Sankey } from './Sankey';\nexport type { VizThemeProviderProps } from './ThemeProvider';\nexport { VizThemeProvider } from './ThemeProvider';\nexport type { TileMapProps } from './TileMap';\nexport { TileMap } from './TileMap';\nexport type { VisualizationProps } from './Visualization';\nexport { Visualization } from './Visualization';\n","/**\n * Vue BarList component: thin wrapper around the vanilla adapter.\n */\n\nimport type { BarListSpec, DarkMode, ThemeConfig } from '@opendata-ai/openchart-core';\nimport {\n type BarListInstance,\n type BarListMountOptions,\n createBarList,\n} from '@opendata-ai/openchart-vanilla';\nimport {\n type CSSProperties,\n defineComponent,\n h,\n inject,\n onMounted,\n onUnmounted,\n type PropType,\n ref,\n watch,\n} from 'vue';\nimport { VizDarkModeKey, VizThemeKey } from './context';\n\nexport interface BarListRowEvent {\n label: string;\n value: number;\n data: Record<string, unknown>;\n}\n\nexport interface BarListProps {\n spec: BarListSpec;\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n class?: string;\n style?: string | CSSProperties;\n}\n\nexport const BarList = defineComponent({\n name: 'BarList',\n props: {\n spec: {\n type: Object as PropType<BarListSpec>,\n required: true,\n },\n theme: {\n type: Object as PropType<ThemeConfig>,\n default: undefined,\n },\n darkMode: {\n type: String as PropType<DarkMode>,\n default: undefined,\n },\n class: {\n type: String,\n default: undefined,\n },\n style: {\n type: [String, Object] as PropType<string | CSSProperties>,\n default: undefined,\n },\n },\n emits: {\n 'row-click': (_row: BarListRowEvent) => true,\n 'row-hover': (_row: BarListRowEvent | null) => true,\n },\n setup(props, { emit, expose }) {\n const containerRef = ref<HTMLDivElement | null>(null);\n let instance: BarListInstance | null = null;\n let prevSpec = '';\n\n const contextTheme = inject(VizThemeKey, undefined);\n const contextDarkMode = inject(VizDarkModeKey, undefined);\n\n function resolveTheme(): ThemeConfig | undefined {\n return props.theme ?? contextTheme?.value;\n }\n\n function resolveDarkMode(): DarkMode | undefined {\n return props.darkMode ?? contextDarkMode?.value;\n }\n\n function mountBarList() {\n const container = containerRef.value;\n if (!container) return;\n\n const options: BarListMountOptions = {\n theme: resolveTheme(),\n darkMode: resolveDarkMode(),\n onRowClick: (row: BarListRowEvent) => emit('row-click', row),\n onRowHover: (row: BarListRowEvent | null) => emit('row-hover', row),\n responsive: true,\n };\n\n instance = createBarList(container, props.spec, options);\n prevSpec = JSON.stringify(props.spec);\n }\n\n function destroyBarList() {\n instance?.destroy();\n instance = null;\n prevSpec = '';\n }\n\n expose({\n get instance() {\n return instance;\n },\n });\n\n onMounted(() => {\n mountBarList();\n });\n\n onUnmounted(() => {\n destroyBarList();\n });\n\n watch(\n () => JSON.stringify(props.spec),\n (newVal) => {\n if (!instance) return;\n if (newVal !== prevSpec) {\n prevSpec = newVal;\n instance.update(props.spec);\n }\n },\n );\n\n watch(\n [\n () => props.theme,\n () => props.darkMode,\n () => contextTheme?.value,\n () => contextDarkMode?.value,\n ],\n () => {\n if (!containerRef.value) return;\n destroyBarList();\n mountBarList();\n },\n );\n\n const rootClass = () => {\n const base = 'oc-barlist-root';\n return props.class ? `${base} ${props.class}` : base;\n };\n\n return () =>\n h('div', {\n ref: containerRef,\n class: rootClass(),\n style: props.style,\n });\n },\n});\n","/**\n * Theme injection context for Vue.\n *\n * Provides typed injection keys and composables for accessing theme\n * and dark mode from any descendant component within a VizThemeProvider.\n */\n\nimport type { DarkMode, ThemeConfig } from '@opendata-ai/openchart-core';\nimport { type ComputedRef, computed, type InjectionKey, inject, type Ref } from 'vue';\n\n/** Injection key for the theme config ref. */\nexport const VizThemeKey: InjectionKey<Ref<ThemeConfig | undefined>> = Symbol('VizTheme');\n\n/** Injection key for the dark mode ref. */\nexport const VizDarkModeKey: InjectionKey<Ref<DarkMode | undefined>> = Symbol('VizDarkMode');\n\n/**\n * Read the current theme from the nearest VizThemeProvider.\n * Returns a computed ref that stays reactive to provider changes.\n */\nexport function useVizTheme(): ComputedRef<ThemeConfig | undefined> {\n const theme = inject(VizThemeKey, undefined);\n return computed(() => theme?.value);\n}\n\n/**\n * Read the current dark mode preference from the nearest VizThemeProvider.\n * Returns a computed ref that stays reactive to provider changes.\n */\nexport function useVizDarkMode(): ComputedRef<DarkMode | undefined> {\n const darkMode = inject(VizDarkModeKey, undefined);\n return computed(() => darkMode?.value);\n}\n","/**\n * Vue Chart component: thin wrapper around the vanilla adapter.\n *\n * Mounts a chart instance on render, updates when spec changes,\n * and cleans up on unmount. All heavy lifting is done by the vanilla\n * createChart() function.\n */\n\nimport type {\n Annotation,\n AnnotationOffset,\n ChartSpec,\n DarkMode,\n ElementEdit,\n ElementRef,\n GraphSpec,\n LayerSpec,\n MarkEvent,\n TextAnnotation,\n ThemeConfig,\n} from '@opendata-ai/openchart-core';\nimport { type ChartInstance, createChart, type MountOptions } from '@opendata-ai/openchart-vanilla';\nimport {\n type CSSProperties,\n defineComponent,\n getCurrentInstance,\n h,\n inject,\n onMounted,\n onUnmounted,\n type PropType,\n ref,\n watch,\n} from 'vue';\nimport { VizDarkModeKey, VizThemeKey } from './context';\n\nexport interface ChartProps {\n spec: ChartSpec | LayerSpec | GraphSpec;\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n /** Rendering backend for point marks; see the vanilla `MountOptions.renderer`. */\n renderer?: 'auto' | 'svg' | 'canvas';\n class?: string;\n style?: string | CSSProperties;\n}\n\nexport const Chart = defineComponent({\n name: 'Chart',\n props: {\n spec: {\n type: Object as PropType<ChartSpec | LayerSpec | GraphSpec>,\n required: true,\n },\n theme: {\n type: Object as PropType<ThemeConfig>,\n default: undefined,\n },\n darkMode: {\n type: String as PropType<DarkMode>,\n default: undefined,\n },\n renderer: {\n type: String as PropType<'auto' | 'svg' | 'canvas'>,\n default: undefined,\n },\n class: {\n type: String,\n default: undefined,\n },\n style: {\n type: [String, Object] as PropType<string | CSSProperties>,\n default: undefined,\n },\n selectedElement: {\n type: Object as PropType<ElementRef>,\n default: undefined,\n },\n highlight: {\n type: [Array, null] as unknown as PropType<string[] | null>,\n default: undefined,\n },\n editable: {\n type: Boolean as PropType<boolean>,\n default: undefined,\n },\n },\n emits: {\n 'mark-click': (_event: MarkEvent) => true,\n 'mark-hover': (_event: MarkEvent) => true,\n 'mark-leave': () => true,\n 'legend-toggle': (_series: string, _visible: boolean) => true,\n 'annotation-click': (_annotation: Annotation, _event: MouseEvent) => true,\n 'annotation-edit': (_annotation: TextAnnotation, _updatedOffset: AnnotationOffset) => true,\n edit: (_edit: ElementEdit) => true,\n select: (_element: ElementRef) => true,\n deselect: (_element: ElementRef) => true,\n 'text-edit': (_element: ElementRef, _oldText: string, _newText: string) => true,\n 'data-point-click': (_data: Record<string, unknown>) => true,\n },\n setup(props, { emit, expose }) {\n const containerRef = ref<HTMLDivElement | null>(null);\n let instance: ChartInstance | null = null;\n let prevSpec = '';\n\n // Inject theme/darkMode from provider as fallbacks\n const contextTheme = inject(VizThemeKey, undefined);\n const contextDarkMode = inject(VizDarkModeKey, undefined);\n\n // Check which event listeners are bound by the parent.\n // Vue 3 passes listeners as onXxx props on the component vnode.\n // We cache this at setup time since it won't change.\n const vm = getCurrentInstance();\n const vnodeProps = vm?.vnode.props ?? {};\n const hasAnnotationEditListener =\n 'onAnnotation-edit' in vnodeProps || 'onAnnotationEdit' in vnodeProps;\n const hasEditListener = 'onEdit' in vnodeProps;\n const hasSelectListener = 'onSelect' in vnodeProps;\n const hasDeselectListener = 'onDeselect' in vnodeProps;\n const hasTextEditListener = 'onText-edit' in vnodeProps || 'onTextEdit' in vnodeProps;\n\n function resolveTheme(): ThemeConfig | undefined {\n return props.theme ?? contextTheme?.value;\n }\n\n function resolveDarkMode(): DarkMode | undefined {\n return props.darkMode ?? contextDarkMode?.value;\n }\n\n function mountChart() {\n const container = containerRef.value;\n if (!container) return;\n\n const options: MountOptions = {\n theme: resolveTheme(),\n darkMode: resolveDarkMode(),\n renderer: props.renderer,\n onDataPointClick: (data: Record<string, unknown>) => emit('data-point-click', data),\n onMarkClick: (event: MarkEvent) => emit('mark-click', event),\n onMarkHover: (event: MarkEvent) => emit('mark-hover', event),\n onMarkLeave: () => emit('mark-leave'),\n onLegendToggle: (series: string, visible: boolean) =>\n emit('legend-toggle', series, visible),\n onAnnotationClick: (annotation: Annotation, event: MouseEvent) =>\n emit('annotation-click', annotation, event),\n // Only include editing callbacks when the parent binds a listener.\n // Without this gate, every chart gets drag editing wired up.\n ...(hasAnnotationEditListener\n ? {\n onAnnotationEdit: (annotation: TextAnnotation, updatedOffset: AnnotationOffset) =>\n emit('annotation-edit', annotation, updatedOffset),\n }\n : {}),\n ...(hasEditListener ? { onEdit: (edit: ElementEdit) => emit('edit', edit) } : {}),\n ...(hasSelectListener\n ? { onSelect: (element: ElementRef) => emit('select', element) }\n : {}),\n ...(hasDeselectListener\n ? { onDeselect: (element: ElementRef) => emit('deselect', element) }\n : {}),\n ...(hasTextEditListener\n ? {\n onTextEdit: (element: ElementRef, oldText: string, newText: string) =>\n emit('text-edit', element, oldText, newText),\n }\n : {}),\n ...(props.editable != null ? { editable: props.editable } : {}),\n ...(props.selectedElement ? { selectedElement: props.selectedElement } : {}),\n responsive: true,\n };\n\n instance = createChart(container, props.spec, options);\n prevSpec = JSON.stringify(props.spec);\n if (props.highlight !== undefined) {\n instance.setHighlight(props.highlight ?? null);\n }\n }\n\n function destroyChart() {\n instance?.destroy();\n instance = null;\n prevSpec = '';\n }\n\n // Expose imperative methods for parent ref access\n expose({\n getSelectedElement(): ElementRef | null {\n return instance?.getSelectedElement() ?? null;\n },\n select(elementRef: ElementRef): void {\n instance?.select(elementRef);\n },\n deselect(): void {\n instance?.deselect();\n },\n get instance() {\n return instance;\n },\n });\n\n onMounted(() => {\n mountChart();\n });\n\n onUnmounted(() => {\n destroyChart();\n });\n\n // Watch spec changes: update if only spec changed, recreate if theme/darkMode changed\n watch(\n () => JSON.stringify(props.spec),\n (newVal) => {\n if (!instance) return;\n if (newVal !== prevSpec) {\n prevSpec = newVal;\n instance.update(props.spec, { selectedElement: props.selectedElement });\n }\n },\n );\n\n // Watch selectedElement prop changes\n watch(\n () => props.selectedElement,\n (newVal) => {\n if (!instance) return;\n if (newVal) {\n instance.select(newVal);\n } else {\n instance.deselect();\n }\n },\n );\n\n // Watch highlight prop changes\n watch(\n () => props.highlight,\n (newVal) => {\n if (!instance) return;\n instance.setHighlight(newVal ?? null);\n },\n );\n\n // Recreate chart when theme, darkMode, renderer, or editable change\n watch(\n [\n () => props.theme,\n () => props.darkMode,\n () => props.renderer,\n () => props.editable,\n () => contextTheme?.value,\n () => contextDarkMode?.value,\n ],\n () => {\n if (!containerRef.value) return;\n destroyChart();\n mountChart();\n },\n );\n\n const rootClass = () => {\n const base = 'oc-chart-root';\n return props.class ? `${base} ${props.class}` : base;\n };\n\n return () =>\n h('div', {\n ref: containerRef,\n class: rootClass(),\n style: props.style,\n });\n },\n});\n","/**\n * Vue scrollytelling shell around the vanilla `createChartStory`.\n *\n * Mirrors the React `<ChartStory>`: a sticky chart panel plus a scrolling\n * narrative column whose blocks advance the story. The vanilla driver owns\n * cumulative patch application, mark morphing, crossfade, and camera; this\n * component owns only Vue lifecycle and the sticky layout.\n *\n * Narrative is provided as the default slot's children (one root node per\n * step) or via the `narrative` prop (an array of vnodes/strings). Pass `step`\n * to drive it externally; omit for self-driving scroll.\n */\n\nimport type { ChartSpec, GeoMapSpec, GraphSpec, LayerSpec } from '@opendata-ai/openchart-core';\nimport type { MountOptions } from '@opendata-ai/openchart-vanilla';\nimport {\n type ChartStoryInstance,\n type ChartStoryOptions,\n createChartStory,\n} from '@opendata-ai/openchart-vanilla/story';\nimport {\n type CSSProperties,\n defineComponent,\n h,\n onMounted,\n onUnmounted,\n type PropType,\n ref,\n type VNode,\n watch,\n} from 'vue';\n\nexport interface ChartStoryProps {\n spec: ChartSpec | LayerSpec | GraphSpec | GeoMapSpec;\n steps: ChartStoryOptions['steps'];\n narrative?: VNode[];\n step?: number;\n triggerPosition?: number;\n cameraMode?: 'step' | 'scrub';\n mountOptions?: MountOptions;\n}\n\nconst sectionStyle: CSSProperties = {\n position: 'relative',\n display: 'grid',\n gridTemplateColumns: 'minmax(0, 26rem) minmax(0, 1fr)',\n gap: '3rem',\n alignItems: 'start',\n};\n\nconst stepStyle: CSSProperties = {\n minHeight: '80vh',\n display: 'flex',\n alignItems: 'center',\n};\n\nconst panelStyle: CSSProperties = {\n position: 'sticky',\n top: '2rem',\n height: 'calc(100vh - 4rem)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n};\n\nexport const ChartStory = defineComponent({\n name: 'ChartStory',\n props: {\n spec: {\n type: Object as PropType<ChartSpec | LayerSpec | GraphSpec | GeoMapSpec>,\n required: true,\n },\n steps: {\n type: Array as PropType<ChartStoryOptions['steps']>,\n required: true,\n },\n narrative: {\n type: Array as PropType<VNode[]>,\n default: undefined,\n },\n step: {\n type: Number,\n default: undefined,\n },\n triggerPosition: {\n type: Number,\n default: undefined,\n },\n cameraMode: {\n type: String as PropType<'step' | 'scrub'>,\n default: undefined,\n },\n mountOptions: {\n type: Object as PropType<MountOptions>,\n default: undefined,\n },\n },\n setup(props, { slots, expose }) {\n const sectionRef = ref<HTMLElement | null>(null);\n const mountRef = ref<HTMLDivElement | null>(null);\n const stepEls = ref<Array<HTMLElement | null>>([]);\n let story: ChartStoryInstance | null = null;\n\n onMounted(() => {\n const mount = mountRef.value;\n if (!mount) return;\n\n const blocks = props.narrative ?? [];\n if (blocks.length > 0 && blocks.length !== props.steps.length) {\n console.warn(\n `[openchart] ChartStory: narrative length (${blocks.length}) does not match steps length (${props.steps.length}). Each step should have a corresponding narrative element.`,\n );\n }\n\n story = createChartStory(\n mount,\n {\n spec: props.spec,\n steps: props.steps,\n triggerPosition: props.triggerPosition,\n cameraMode: props.cameraMode,\n },\n props.mountOptions,\n );\n if (sectionRef.value) story.setContainer(sectionRef.value);\n stepEls.value.forEach((el, i) => {\n if (el) story?.registerStep(i, el);\n });\n if (props.step !== undefined) story.goTo(props.step);\n });\n\n watch(\n () => props.step,\n (next) => {\n if (next !== undefined) story?.goTo(next);\n },\n );\n\n onUnmounted(() => {\n story?.destroy();\n story = null;\n });\n\n expose({\n goTo(index: number) {\n story?.goTo(index);\n },\n get instance() {\n return story;\n },\n });\n\n return () => {\n // Prefer the `narrative` prop; fall back to default slot children so\n // consumers can author steps as template markup.\n const blocks = props.narrative ?? slots.default?.() ?? [];\n return h('section', { ref: sectionRef, style: sectionStyle }, [\n h(\n 'div',\n { style: { position: 'relative' } },\n blocks.map((content, i) =>\n h(\n 'div',\n {\n // Steps are a fixed ordered list, so the index is the stable\n // identity. Do not reorder or splice narrative entries at runtime\n // (that would remap step refs to the wrong content); rebuild the\n // whole story instead.\n key: i,\n ref: (el: unknown) => {\n stepEls.value[i] = el as HTMLElement | null;\n },\n 'data-oc-story-step': i,\n style: stepStyle,\n },\n [h('div', { style: { maxWidth: '36rem' } }, [content])],\n ),\n ),\n ),\n h('div', { style: panelStyle }, [h('div', { ref: mountRef, style: { width: '100%' } })]),\n ]);\n };\n },\n});\n","/**\n * useChart: composable for manual chart lifecycle control.\n *\n * Provides a template ref to attach to a container div. The chart\n * mounts automatically and updates when the spec changes.\n */\n\nimport type {\n ChartLayout,\n ChartSpec,\n DarkMode,\n GraphSpec,\n LayerSpec,\n ThemeConfig,\n} from '@opendata-ai/openchart-core';\nimport { type ChartInstance, createChart, type MountOptions } from '@opendata-ai/openchart-vanilla';\nimport { onMounted, onUnmounted, type Ref, ref, type ShallowRef, shallowRef, watch } from 'vue';\n\nexport interface UseChartOptions {\n /** Theme overrides. */\n theme?: ThemeConfig;\n /** Dark mode setting. */\n darkMode?: DarkMode;\n /** Data point click handler. */\n onDataPointClick?: MountOptions['onDataPointClick'];\n /** Enable responsive resizing. Defaults to true. */\n responsive?: boolean;\n /** Rendering backend for point marks; see the vanilla `MountOptions.renderer`. */\n renderer?: MountOptions['renderer'];\n}\n\nexport interface UseChartReturn {\n /** Template ref to attach to the container div. */\n containerRef: Ref<HTMLDivElement | null>;\n /** The chart instance (null until mounted). */\n chart: ShallowRef<ChartInstance | null>;\n /** The current compiled layout (null until mounted). */\n layout: ShallowRef<ChartLayout | null>;\n}\n\n/**\n * Composable for manual chart lifecycle control.\n *\n * Attach the returned containerRef to a container div via `ref=\"containerRef\"`.\n * The chart mounts automatically and updates when the spec changes.\n */\nexport function useChart(\n spec: Ref<ChartSpec | LayerSpec | GraphSpec>,\n options?: UseChartOptions,\n): UseChartReturn {\n const containerRef = ref<HTMLDivElement | null>(null);\n const chart = shallowRef<ChartInstance | null>(null);\n const layout = shallowRef<ChartLayout | null>(null);\n\n function mount() {\n const container = containerRef.value;\n if (!container) return;\n\n const mountOpts: MountOptions = {\n theme: options?.theme,\n darkMode: options?.darkMode,\n onDataPointClick: options?.onDataPointClick,\n responsive: options?.responsive,\n renderer: options?.renderer,\n };\n\n const instance = createChart(container, spec.value, mountOpts);\n chart.value = instance;\n layout.value = instance.layout;\n }\n\n function destroy() {\n chart.value?.destroy();\n chart.value = null;\n layout.value = null;\n }\n\n onMounted(() => {\n mount();\n });\n\n onUnmounted(() => {\n destroy();\n });\n\n // Update on spec change\n watch(spec, (newSpec) => {\n const instance = chart.value;\n if (!instance) return;\n instance.update(newSpec);\n layout.value = instance.layout;\n });\n\n return {\n containerRef,\n chart,\n layout,\n };\n}\n","/**\n * useDarkMode: composable that resolves a DarkMode preference to a boolean.\n *\n * - \"force\" -> true\n * - \"off\" -> false\n * - \"auto\" -> matches system preference (reactive to changes)\n */\n\nimport type { DarkMode } from '@opendata-ai/openchart-core';\nimport { onUnmounted, type Ref, ref, watch } from 'vue';\n\n/**\n * Resolve a DarkMode preference to a reactive boolean.\n *\n * For \"auto\" mode, watches the system `prefers-color-scheme` media query\n * and updates reactively when the user changes their OS theme.\n */\nexport function useDarkMode(mode: Ref<DarkMode | undefined>): Ref<boolean> {\n const isDark = ref(resolveInitial(mode.value));\n let cleanup: (() => void) | null = null;\n\n function setup(currentMode: DarkMode | undefined) {\n // Clean up previous listener\n cleanup?.();\n cleanup = null;\n\n if (currentMode !== 'auto') {\n isDark.value = currentMode === 'force';\n return;\n }\n\n if (typeof window === 'undefined' || !window.matchMedia) {\n isDark.value = false;\n return;\n }\n\n const mq = window.matchMedia('(prefers-color-scheme: dark)');\n isDark.value = mq.matches;\n\n const handler = (e: MediaQueryListEvent) => {\n isDark.value = e.matches;\n };\n mq.addEventListener('change', handler);\n cleanup = () => mq.removeEventListener('change', handler);\n }\n\n // Run setup for initial value\n setup(mode.value);\n\n // React to mode changes\n watch(mode, (newMode) => {\n setup(newMode);\n });\n\n onUnmounted(() => {\n cleanup?.();\n cleanup = null;\n });\n\n return isDark;\n}\n\nfunction resolveInitial(mode?: DarkMode): boolean {\n if (mode === 'force') return true;\n if (mode === 'off' || mode === undefined) return false;\n // \"auto\"\n if (typeof window !== 'undefined' && window.matchMedia) {\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\n }\n return false;\n}\n","/**\n * useGraph: composable for imperative graph control.\n *\n * Provides a template ref to pass to <Graph /> and exposes graph methods\n * (search, zoom, select, fly, highlight) for programmatic control of the\n * graph instance. The full vanilla GraphInstance API is threaded through.\n */\n\nimport type { GraphSpec } from '@opendata-ai/openchart-core';\nimport type {\n CameraFlightOptions,\n GraphCamera,\n GraphFlyTarget,\n GraphHighlightTarget,\n GraphInstance,\n GraphLegendData,\n} from '@opendata-ai/openchart-vanilla';\nimport { type Ref, ref } from 'vue';\n\n// Re-exported rather than redeclared so the 3D pose fields (`position`,\n// `target`) stay visible to typed consumers of the Vue wrapper.\nexport type { GraphCamera, GraphFlyTarget } from '@opendata-ai/openchart-vanilla';\n\n/** Handle exposed by Graph component via expose(). */\nexport interface GraphHandle {\n search: (query: string) => void;\n clearSearch: () => void;\n getSearchMatches: () => string[];\n zoomToFit: (opts?: CameraFlightOptions & { padding?: number }) => void;\n zoomToNode: (nodeId: string, opts?: CameraFlightOptions & { scale?: number }) => void;\n flyTo: (target: GraphFlyTarget, opts?: CameraFlightOptions) => void;\n centerAt: (x: number, y: number, opts?: CameraFlightOptions) => void;\n getCamera: () => GraphCamera;\n selectNode: (nodeId: string, opts?: { fly?: boolean } & CameraFlightOptions) => void;\n getSelectedNodes: () => string[];\n highlight: (target: GraphHighlightTarget, opts?: { dimOpacity?: number }) => void;\n clearHighlight: () => void;\n getHighlight: () => string[] | null;\n getLegend: () => GraphLegendData | null;\n setActiveCategories: (values: string[]) => void;\n getActiveCategories: () => string[];\n /** Re-compile encoding/legend/chrome without restarting the simulation. */\n updateVisuals: (spec: GraphSpec) => void;\n /** The underlying GraphInstance from the vanilla adapter. */\n instance: GraphInstance | null;\n}\n\nexport interface UseGraphReturn {\n /** Template ref to pass to <Graph ref={graphRef} />. */\n graphRef: Ref<GraphHandle | null>;\n /** Search for nodes matching a query string. */\n search: (query: string) => void;\n /** Clear the current search. */\n clearSearch: () => void;\n /** Node ids currently matching the active search query. */\n getSearchMatches: () => string[];\n /** Zoom to fit all nodes in view. Animated by default; `{ duration: 0 }` snaps. */\n zoomToFit: (opts?: CameraFlightOptions & { padding?: number }) => void;\n /** Fly to a node and zoom in (default scale 2). */\n zoomToNode: (nodeId: string, opts?: CameraFlightOptions & { scale?: number }) => void;\n /** Fly the camera to a graph-space target. */\n flyTo: (target: GraphFlyTarget, opts?: CameraFlightOptions) => void;\n /** Center the camera on a graph-space point (keeps current zoom). */\n centerAt: (x: number, y: number, opts?: CameraFlightOptions) => void;\n /** Current camera transform. */\n getCamera: () => GraphCamera;\n /** Select a node by id; `{ fly: true }` also flies to it. */\n selectNode: (nodeId: string, opts?: { fly?: boolean } & CameraFlightOptions) => void;\n /** Get the currently selected node ids. */\n getSelectedNodes: () => string[];\n /**\n * Emphasize a set of nodes; eased via the focus model. Layers over the\n * standing category filter rather than replacing it.\n */\n highlight: (target: GraphHighlightTarget, opts?: { dimOpacity?: number }) => void;\n /**\n * Clear the transient highlight, returning to the standing category filter.\n * Does NOT clear that filter — use `setActiveCategories([])`.\n */\n clearHighlight: () => void;\n /** The effective highlighted node ids, or null when nothing is highlighted. */\n getHighlight: () => string[] | null;\n /** Headless snapshot of the legend. */\n getLegend: () => GraphLegendData | null;\n /** Set the active category filter declaratively (replaces legend toggle state). */\n setActiveCategories: (values: string[]) => void;\n /** Current active category values (empty = all active, no filter). */\n getActiveCategories: () => string[];\n}\n\n/**\n * Composable for imperative graph control.\n *\n * Usage:\n * ```vue\n * <script setup>\n * const { graphRef, search, zoomToFit } = useGraph();\n * </script>\n * <template>\n * <Graph ref=\"graphRef\" :spec=\"spec\" />\n * </template>\n * ```\n */\nexport function useGraph(): UseGraphReturn {\n const graphRef = ref<GraphHandle | null>(null);\n\n function search(query: string) {\n graphRef.value?.search(query);\n }\n\n function clearSearch() {\n graphRef.value?.clearSearch();\n }\n\n function getSearchMatches(): string[] {\n return graphRef.value?.getSearchMatches() ?? [];\n }\n\n function zoomToFit(opts?: CameraFlightOptions & { padding?: number }) {\n graphRef.value?.zoomToFit(opts);\n }\n\n function zoomToNode(nodeId: string, opts?: CameraFlightOptions & { scale?: number }) {\n graphRef.value?.zoomToNode(nodeId, opts);\n }\n\n function flyTo(target: GraphFlyTarget, opts?: CameraFlightOptions) {\n graphRef.value?.flyTo(target, opts);\n }\n\n function centerAt(x: number, y: number, opts?: CameraFlightOptions) {\n graphRef.value?.centerAt(x, y, opts);\n }\n\n function getCamera(): GraphCamera {\n return graphRef.value?.getCamera() ?? { x: 0, y: 0, k: 1 };\n }\n\n function selectNode(nodeId: string, opts?: { fly?: boolean } & CameraFlightOptions) {\n graphRef.value?.selectNode(nodeId, opts);\n }\n\n function getSelectedNodes(): string[] {\n return graphRef.value?.getSelectedNodes() ?? [];\n }\n\n function highlight(target: GraphHighlightTarget, opts?: { dimOpacity?: number }) {\n graphRef.value?.highlight(target, opts);\n }\n\n function clearHighlight() {\n graphRef.value?.clearHighlight();\n }\n\n function getHighlight(): string[] | null {\n return graphRef.value?.getHighlight() ?? null;\n }\n\n function getLegend(): GraphLegendData | null {\n return graphRef.value?.getLegend() ?? null;\n }\n\n function setActiveCategories(values: string[]) {\n graphRef.value?.setActiveCategories(values);\n }\n\n function getActiveCategories(): string[] {\n return graphRef.value?.getActiveCategories() ?? [];\n }\n\n return {\n graphRef,\n search,\n clearSearch,\n getSearchMatches,\n zoomToFit,\n zoomToNode,\n flyTo,\n centerAt,\n getCamera,\n selectNode,\n getSelectedNodes,\n highlight,\n clearHighlight,\n getHighlight,\n getLegend,\n setActiveCategories,\n getActiveCategories,\n };\n}\n","/**\n * useTable: composable for manual table lifecycle control.\n *\n * Attaches to a container ref, mounts a vanilla table instance,\n * and exposes the instance and current state.\n */\n\nimport type { TableSpec } from '@opendata-ai/openchart-core';\nimport {\n createTable,\n type TableInstance,\n type TableMountOptions,\n type TableState,\n} from '@opendata-ai/openchart-vanilla';\nimport { onMounted, onUnmounted, type Ref, ref, type ShallowRef, shallowRef, watch } from 'vue';\n\nexport interface UseTableReturn {\n /** Template ref to attach to the container div. */\n containerRef: Ref<HTMLDivElement | null>;\n /** The table instance (null until mounted). */\n table: ShallowRef<TableInstance | null>;\n /** The current table state (sort, search, page). */\n state: Ref<TableState>;\n}\n\n/**\n * Composable for manual table lifecycle control.\n *\n * Attach the returned containerRef to a container div via `ref=\"containerRef\"`.\n * The table mounts automatically and updates when the spec changes.\n */\nexport function useTable(spec: Ref<TableSpec>, options?: TableMountOptions): UseTableReturn {\n const containerRef = ref<HTMLDivElement | null>(null);\n const table = shallowRef<TableInstance | null>(null);\n const state = ref<TableState>({\n sort: null,\n search: '',\n page: 0,\n });\n\n const originalOnStateChange = options?.onStateChange;\n\n function handleStateChange(newState: TableState) {\n state.value = newState;\n originalOnStateChange?.(newState);\n }\n\n function mount() {\n const container = containerRef.value;\n if (!container) return;\n\n const mountOpts: TableMountOptions = {\n ...options,\n onStateChange: handleStateChange,\n };\n\n const instance = createTable(container, spec.value, mountOpts);\n table.value = instance;\n state.value = instance.getState();\n }\n\n function destroy() {\n table.value?.destroy();\n table.value = null;\n }\n\n onMounted(() => {\n mount();\n });\n\n onUnmounted(() => {\n destroy();\n });\n\n // Update on spec change\n watch(spec, (newSpec) => {\n const instance = table.value;\n if (!instance) return;\n instance.update(newSpec);\n state.value = instance.getState();\n });\n\n return {\n containerRef,\n table,\n state,\n };\n}\n","/**\n * useTableState: managed state composable for controlled table usage.\n *\n * Provides individual sort/search/page state with setters and a\n * resetState function to return to initial values.\n */\n\nimport type { SortState } from '@opendata-ai/openchart-core';\nimport { type Ref, ref } from 'vue';\n\nexport interface UseTableStateReturn {\n sort: Ref<SortState | null>;\n setSort: (sort: SortState | null) => void;\n search: Ref<string>;\n setSearch: (query: string) => void;\n page: Ref<number>;\n setPage: (page: number) => void;\n resetState: () => void;\n}\n\nexport interface UseTableStateOptions {\n sort?: SortState | null;\n search?: string;\n page?: number;\n}\n\n/**\n * Composable for managing table state (sort, search, page).\n *\n * Use with the DataTable component's controlled props:\n * ```vue\n * <script setup>\n * const { sort, search, page, setSort, setSearch, setPage } = useTableState();\n * </script>\n * <template>\n * <DataTable\n * :spec=\"spec\"\n * :sort=\"sort\"\n * :search=\"search\"\n * :page=\"page\"\n * @update:sort=\"setSort\"\n * @update:search=\"setSearch\"\n * @update:page=\"setPage\"\n * />\n * </template>\n * ```\n */\nexport function useTableState(initialState?: UseTableStateOptions): UseTableStateReturn {\n const sort = ref<SortState | null>(initialState?.sort ?? null);\n const search = ref(initialState?.search ?? '');\n const page = ref(initialState?.page ?? 0);\n\n function setSort(newSort: SortState | null) {\n sort.value = newSort;\n }\n\n function setSearch(query: string) {\n search.value = query;\n }\n\n function setPage(newPage: number) {\n page.value = newPage;\n }\n\n function resetState() {\n sort.value = initialState?.sort ?? null;\n search.value = initialState?.search ?? '';\n page.value = initialState?.page ?? 0;\n }\n\n return {\n sort,\n setSort,\n search,\n setSearch,\n page,\n setPage,\n resetState,\n };\n}\n","/**\n * DataTable component: Vue wrapper around the vanilla table adapter.\n *\n * Mounts a table instance on render, updates when spec changes,\n * and cleans up on unmount. Supports both controlled and uncontrolled modes\n * for sort, search, and pagination state.\n */\n\nimport type { DarkMode, SortState, TableSpec, ThemeConfig } from '@opendata-ai/openchart-core';\nimport {\n createTable,\n type TableInstance,\n type TableMountOptions,\n} from '@opendata-ai/openchart-vanilla';\nimport {\n type CSSProperties,\n defineComponent,\n h,\n inject,\n onMounted,\n onUnmounted,\n type PropType,\n ref,\n watch,\n} from 'vue';\nimport { VizDarkModeKey, VizThemeKey } from './context';\n\nexport interface DataTableProps {\n spec: TableSpec;\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n class?: string;\n style?: string | CSSProperties;\n sort?: SortState | null;\n search?: string;\n page?: number;\n}\n\nexport const DataTable = defineComponent({\n name: 'DataTable',\n props: {\n spec: {\n type: Object as PropType<TableSpec>,\n required: true,\n },\n theme: {\n type: Object as PropType<ThemeConfig>,\n default: undefined,\n },\n darkMode: {\n type: String as PropType<DarkMode>,\n default: undefined,\n },\n class: {\n type: String,\n default: undefined,\n },\n style: {\n type: [String, Object] as PropType<string | CSSProperties>,\n default: undefined,\n },\n sort: {\n type: [Object, null] as PropType<SortState | null>,\n default: undefined,\n },\n search: {\n type: String,\n default: undefined,\n },\n page: {\n type: Number,\n default: undefined,\n },\n },\n emits: {\n 'row-click': (_row: Record<string, unknown>) => true,\n 'update:sort': (_sort: SortState | null) => true,\n 'update:search': (_query: string) => true,\n 'update:page': (_page: number) => true,\n },\n setup(props, { emit }) {\n const containerRef = ref<HTMLDivElement | null>(null);\n let instance: TableInstance | null = null;\n\n // Inject theme/darkMode from provider as fallbacks\n const contextTheme = inject(VizThemeKey, undefined);\n const contextDarkMode = inject(VizDarkModeKey, undefined);\n\n function resolveTheme(): ThemeConfig | undefined {\n return props.theme ?? contextTheme?.value;\n }\n\n function resolveDarkMode(): DarkMode | undefined {\n return props.darkMode ?? contextDarkMode?.value;\n }\n\n function isControlled(): boolean {\n return props.sort !== undefined || props.search !== undefined || props.page !== undefined;\n }\n\n let prevSpec = '';\n\n function mountTable() {\n const container = containerRef.value;\n if (!container) return;\n\n const mountOptions: TableMountOptions = {\n theme: resolveTheme(),\n darkMode: resolveDarkMode(),\n onRowClick: (row: Record<string, unknown>) => emit('row-click', row),\n responsive: true,\n onStateChange: (state) => {\n if (state.sort !== undefined) emit('update:sort', state.sort);\n if (state.search !== undefined) emit('update:search', state.search);\n if (state.page !== undefined) emit('update:page', state.page);\n },\n };\n\n if (isControlled()) {\n mountOptions.externalState = {\n sort: props.sort ?? null,\n search: props.search ?? '',\n page: props.page ?? 0,\n };\n }\n\n instance = createTable(container, props.spec, mountOptions);\n prevSpec = JSON.stringify(props.spec);\n }\n\n function destroyTable() {\n instance?.destroy();\n instance = null;\n prevSpec = '';\n }\n\n onMounted(() => {\n mountTable();\n });\n\n onUnmounted(() => {\n destroyTable();\n });\n\n // Watch spec changes via JSON.stringify comparison (consistent with Chart/Graph)\n watch(\n () => JSON.stringify(props.spec),\n (newVal) => {\n if (!instance) return;\n if (newVal !== prevSpec) {\n prevSpec = newVal;\n instance.update(props.spec);\n }\n },\n );\n\n // Recreate when theme or darkMode change\n watch(\n [\n () => props.theme,\n () => props.darkMode,\n () => contextTheme?.value,\n () => contextDarkMode?.value,\n ],\n () => {\n if (!containerRef.value) return;\n destroyTable();\n mountTable();\n },\n );\n\n // Sync controlled state without remounting\n watch([() => props.sort, () => props.search, () => props.page], () => {\n if (!instance || !isControlled()) return;\n instance.setState({\n sort: props.sort ?? null,\n search: props.search ?? '',\n page: props.page ?? 0,\n });\n });\n\n const rootClass = () => {\n const base = 'oc-table-root';\n return props.class ? `${base} ${props.class}` : base;\n };\n\n return () =>\n h('div', {\n ref: containerRef,\n class: rootClass(),\n style: props.style,\n });\n },\n});\n","/**\n * Vue Map component: thin wrapper around the vanilla adapter.\n *\n * Mounts a map instance on render, updates when spec changes,\n * and cleans up on unmount. All heavy lifting is done by the vanilla\n * createGeoMap() function.\n */\n\nimport type { DarkMode, GeoMapSpec, ThemeConfig } from '@opendata-ai/openchart-core';\nimport {\n type Camera,\n createGeoMap,\n type GeoMapInstance,\n type GeoMapMarkEvent,\n type GeoMapMountOptions,\n} from '@opendata-ai/openchart-vanilla';\nimport {\n type CSSProperties,\n defineComponent,\n h,\n inject,\n onMounted,\n onUnmounted,\n type PropType,\n ref,\n watch,\n} from 'vue';\nimport { VizDarkModeKey, VizThemeKey } from './context';\n\nexport interface GeoMapProps {\n spec: GeoMapSpec;\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n class?: string;\n style?: string | CSSProperties;\n}\n\nexport const GeoMap = defineComponent({\n name: 'GeoMap',\n props: {\n spec: {\n type: Object as PropType<GeoMapSpec>,\n required: true,\n },\n theme: {\n type: Object as PropType<ThemeConfig>,\n default: undefined,\n },\n darkMode: {\n type: String as PropType<DarkMode>,\n default: undefined,\n },\n class: {\n type: String,\n default: undefined,\n },\n style: {\n type: [String, Object] as PropType<string | CSSProperties>,\n default: undefined,\n },\n },\n emits: {\n 'mark-click': (_event: GeoMapMarkEvent) => true,\n 'mark-hover': (_event: GeoMapMarkEvent | null) => true,\n 'camera-change': (_camera: Camera) => true,\n },\n setup(props, { emit, expose }) {\n const containerRef = ref<HTMLDivElement | null>(null);\n let instance: GeoMapInstance | null = null;\n let prevSpec = '';\n\n // Inject theme/darkMode from provider as fallbacks\n const contextTheme = inject(VizThemeKey, undefined);\n const contextDarkMode = inject(VizDarkModeKey, undefined);\n\n function resolveTheme(): ThemeConfig | undefined {\n return props.theme ?? contextTheme?.value;\n }\n\n function resolveDarkMode(): DarkMode | undefined {\n return props.darkMode ?? contextDarkMode?.value;\n }\n\n function mountMap() {\n const container = containerRef.value;\n if (!container) return;\n\n const options: GeoMapMountOptions = {\n theme: resolveTheme(),\n darkMode: resolveDarkMode(),\n onMarkClick: (feature) => emit('mark-click', feature),\n onMarkHover: (feature) => emit('mark-hover', feature),\n onCameraChange: (camera) => emit('camera-change', camera),\n responsive: true,\n };\n\n instance = createGeoMap(container, props.spec, options);\n prevSpec = JSON.stringify(props.spec);\n }\n\n function destroyMap() {\n instance?.destroy();\n instance = null;\n prevSpec = '';\n }\n\n // Expose imperative access to the instance\n expose({\n get instance() {\n return instance;\n },\n });\n\n onMounted(() => {\n mountMap();\n });\n\n onUnmounted(() => {\n destroyMap();\n });\n\n // Watch spec changes\n watch(\n () => JSON.stringify(props.spec),\n (newVal) => {\n if (!instance) return;\n if (newVal !== prevSpec) {\n prevSpec = newVal;\n instance.update(props.spec);\n }\n },\n );\n\n // Recreate map when theme or darkMode change\n watch(\n [\n () => props.theme,\n () => props.darkMode,\n () => contextTheme?.value,\n () => contextDarkMode?.value,\n ],\n () => {\n if (!containerRef.value) return;\n destroyMap();\n mountMap();\n },\n );\n\n const rootClass = () => {\n const base = 'oc-map-root';\n return props.class ? `${base} ${props.class}` : base;\n };\n\n return () =>\n h('div', {\n ref: containerRef,\n class: rootClass(),\n style: props.style,\n });\n },\n});\n","/**\n * Vue Graph component: thin wrapper around the vanilla adapter.\n *\n * Mounts a graph instance on render, updates when spec changes,\n * and cleans up on unmount. All heavy lifting is done by the vanilla\n * createGraph() function.\n *\n * Exposes imperative methods via defineExpose for use with useGraph().\n */\n\nimport type { DarkMode, GraphSpec, ThemeConfig } from '@opendata-ai/openchart-core';\nimport {\n createGraph,\n type GraphCamera,\n type GraphInstance,\n type GraphMountOptions,\n type GraphTooltipFormatter,\n} from '@opendata-ai/openchart-vanilla';\nimport {\n type CSSProperties,\n defineComponent,\n h,\n inject,\n onMounted,\n onUnmounted,\n type PropType,\n ref,\n watch,\n} from 'vue';\nimport { VizDarkModeKey, VizThemeKey } from './context';\n\n/** Tooltip prop: `false` off, `true` default, or an object with a formatter. */\nexport type GraphTooltipProp = boolean | { formatter?: GraphTooltipFormatter };\n/** Legend prop: `false` off, `true` default, or an object toggling interactivity/counts. */\nexport type GraphLegendProp = boolean | { interactive?: boolean; counts?: boolean };\n\nexport interface GraphProps {\n spec: GraphSpec;\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n tooltip?: GraphTooltipProp;\n legend?: GraphLegendProp;\n fitOnLoad?: boolean;\n /** How much closer than the fit the opening camera sits: a multiplier on the fit (2 = twice as close), not an absolute zoom level. Default 1. Read once at mount; `zoomToFit()` still frames the whole graph. */\n initialZoom?: number;\n class?: string;\n style?: string | CSSProperties;\n}\n\n/** True when the tooltip is on (only the on/off decision gates recreation). */\nfunction tooltipOn(tooltip: GraphTooltipProp | undefined): boolean {\n return tooltip !== false;\n}\n\nexport const Graph = defineComponent({\n name: 'Graph',\n props: {\n spec: {\n type: Object as PropType<GraphSpec>,\n required: true,\n },\n theme: {\n type: Object as PropType<ThemeConfig>,\n default: undefined,\n },\n darkMode: {\n type: String as PropType<DarkMode>,\n default: undefined,\n },\n tooltip: {\n type: [Boolean, Object] as PropType<GraphTooltipProp>,\n default: undefined,\n },\n legend: {\n type: [Boolean, Object] as PropType<GraphLegendProp>,\n default: undefined,\n },\n fitOnLoad: {\n type: Boolean,\n default: undefined,\n },\n initialZoom: {\n type: Number,\n default: undefined,\n },\n class: {\n type: String,\n default: undefined,\n },\n style: {\n type: [String, Object] as PropType<string | CSSProperties>,\n default: undefined,\n },\n },\n emits: {\n 'node-click': (_node: Record<string, unknown>) => true,\n 'node-double-click': (_node: Record<string, unknown>) => true,\n 'node-hover': (_node: Record<string, unknown> | null) => true,\n 'edge-hover': (_edge: Record<string, unknown> | null) => true,\n 'selection-change': (_nodeIds: string[]) => true,\n 'legend-hover': (_entry: { field: string; value: string } | null) => true,\n 'legend-toggle': (_activeValues: string[]) => true,\n 'highlight-change': (_nodeIds: string[] | null) => true,\n 'camera-change': (_camera: GraphCamera) => true,\n },\n setup(props, { emit, expose }) {\n const containerRef = ref<HTMLDivElement | null>(null);\n let instance: GraphInstance | null = null;\n let prevSpec = '';\n // First mount plays the entrance; theme/darkMode-only recreations suppress it.\n let mountedOnce = false;\n\n // Inject theme/darkMode from provider as fallbacks\n const contextTheme = inject(VizThemeKey, undefined);\n const contextDarkMode = inject(VizDarkModeKey, undefined);\n\n function resolveTheme(): ThemeConfig | undefined {\n return props.theme ?? contextTheme?.value;\n }\n\n function resolveDarkMode(): DarkMode | undefined {\n return props.darkMode ?? contextDarkMode?.value;\n }\n\n // Stable tooltip formatter wrapper. Vue props are reactive, so reading\n // `props.tooltip` at CALL time always sees the latest formatter — no stale\n // closure, no recreation when the formatter changes. When the tooltip is on\n // we always hand the vanilla layer this wrapper (falling back to defaults),\n // so a formatter can be added or swapped per-render without a remount.\n const stableTooltipFormatter: GraphTooltipFormatter = (item, defaults) => {\n const t = props.tooltip;\n const fn = t && typeof t === 'object' ? t.formatter : undefined;\n return fn ? fn(item, defaults) : defaults;\n };\n\n // `playEntrance` is set only by the dimension remount: 2D and 3D are\n // different renderers, so the new one should play its entrance instead of\n // being suppressed the way a theme-only recreation is.\n function mountGraph(playEntrance = false) {\n const container = containerRef.value;\n if (!container) return;\n\n const tooltipOption: GraphMountOptions['tooltip'] = tooltipOn(props.tooltip)\n ? { formatter: stableTooltipFormatter }\n : false;\n\n const options: GraphMountOptions = {\n theme: resolveTheme(),\n darkMode: resolveDarkMode(),\n tooltip: tooltipOption,\n legend: props.legend,\n fitOnLoad: props.fitOnLoad,\n initialZoom: props.initialZoom,\n onNodeClick: (node) => emit('node-click', node),\n onNodeDoubleClick: (node) => emit('node-double-click', node),\n onNodeHover: (node) => emit('node-hover', node),\n onEdgeHover: (edge) => emit('edge-hover', edge),\n onSelectionChange: (nodeIds) => emit('selection-change', nodeIds),\n onLegendHover: (entry) => emit('legend-hover', entry),\n onLegendToggle: (activeValues) => emit('legend-toggle', activeValues),\n onHighlightChange: (nodeIds) => emit('highlight-change', nodeIds),\n onCameraChange: (camera) => emit('camera-change', camera),\n responsive: true,\n suppressEntrance: mountedOnce && !playEntrance,\n };\n\n instance = createGraph(container, props.spec, options);\n prevSpec = JSON.stringify(props.spec);\n mountedOnce = true;\n }\n\n function destroyGraph() {\n instance?.destroy();\n instance = null;\n prevSpec = '';\n }\n\n // Expose imperative methods for useGraph() composable. Every method forwards\n // opts to the underlying instance so consumers get the full vanilla API.\n expose({\n search(query: string) {\n instance?.search(query);\n },\n clearSearch() {\n instance?.clearSearch();\n },\n getSearchMatches(): string[] {\n return instance?.getSearchMatches() ?? [];\n },\n zoomToFit(opts?: Parameters<GraphInstance['zoomToFit']>[0]) {\n instance?.zoomToFit(opts);\n },\n zoomToNode(nodeId: string, opts?: Parameters<GraphInstance['zoomToNode']>[1]) {\n instance?.zoomToNode(nodeId, opts);\n },\n flyTo(\n target: Parameters<GraphInstance['flyTo']>[0],\n opts?: Parameters<GraphInstance['flyTo']>[1],\n ) {\n instance?.flyTo(target, opts);\n },\n centerAt(x: number, y: number, opts?: Parameters<GraphInstance['centerAt']>[2]) {\n instance?.centerAt(x, y, opts);\n },\n getCamera() {\n return instance?.getCamera() ?? { x: 0, y: 0, k: 1 };\n },\n selectNode(nodeId: string, opts?: Parameters<GraphInstance['selectNode']>[1]) {\n instance?.selectNode(nodeId, opts);\n },\n getSelectedNodes(): string[] {\n return instance?.getSelectedNodes() ?? [];\n },\n highlight(\n target: Parameters<GraphInstance['highlight']>[0],\n opts?: Parameters<GraphInstance['highlight']>[1],\n ) {\n instance?.highlight(target, opts);\n },\n clearHighlight() {\n instance?.clearHighlight();\n },\n getHighlight() {\n return instance?.getHighlight() ?? null;\n },\n getLegend() {\n return instance?.getLegend() ?? null;\n },\n setActiveCategories(values: string[]) {\n instance?.setActiveCategories(values);\n },\n getActiveCategories(): string[] {\n return instance?.getActiveCategories() ?? [];\n },\n updateVisuals(spec: GraphSpec) {\n instance?.updateVisuals(spec);\n },\n get instance() {\n return instance;\n },\n });\n\n onMounted(() => {\n mountGraph();\n });\n\n onUnmounted(() => {\n destroyGraph();\n });\n\n // A dimension change picks a different renderer, and the renderer is chosen\n // once, at mount — so it is a remount, not an update(). Registered before\n // the spec watcher so the remount runs first; mountGraph refreshes prevSpec,\n // and the spec watcher then finds nothing to apply.\n watch(\n () => props.spec.dimensions ?? 2,\n () => {\n if (!containerRef.value) return;\n destroyGraph();\n mountGraph(true);\n },\n );\n\n // Watch spec changes\n watch(\n () => JSON.stringify(props.spec),\n (newVal) => {\n if (!instance) return;\n if (newVal !== prevSpec) {\n prevSpec = newVal;\n instance.update(props.spec);\n }\n },\n );\n\n // Recreate graph when theme or darkMode change (spec unchanged). mountedOnce\n // is already true here, so mountGraph passes suppressEntrance: true and the\n // entrance does not replay.\n watch(\n [\n () => props.theme,\n () => props.darkMode,\n () => contextTheme?.value,\n () => contextDarkMode?.value,\n ],\n () => {\n if (!containerRef.value) return;\n destroyGraph();\n mountGraph();\n },\n );\n\n const rootClass = () => {\n const base = 'oc-graph-root';\n return props.class ? `${base} ${props.class}` : base;\n };\n\n return () =>\n h('div', {\n ref: containerRef,\n class: rootClass(),\n style: props.style,\n });\n },\n});\n","/**\n * Vue Sankey component: thin wrapper around the vanilla adapter.\n *\n * Mounts a sankey instance on render, updates when spec changes,\n * and cleans up on unmount. All heavy lifting is done by the vanilla\n * createSankey() function.\n */\n\nimport type { DarkMode, SankeySpec, ThemeConfig } from '@opendata-ai/openchart-core';\nimport {\n createSankey,\n type SankeyInstance,\n type SankeyMountOptions,\n} from '@opendata-ai/openchart-vanilla';\nimport {\n type CSSProperties,\n defineComponent,\n h,\n inject,\n onMounted,\n onUnmounted,\n type PropType,\n ref,\n watch,\n} from 'vue';\nimport { VizDarkModeKey, VizThemeKey } from './context';\n\nexport interface SankeyProps {\n spec: SankeySpec;\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n class?: string;\n style?: string | CSSProperties;\n}\n\nexport const Sankey = defineComponent({\n name: 'Sankey',\n props: {\n spec: {\n type: Object as PropType<SankeySpec>,\n required: true,\n },\n theme: {\n type: Object as PropType<ThemeConfig>,\n default: undefined,\n },\n darkMode: {\n type: String as PropType<DarkMode>,\n default: undefined,\n },\n class: {\n type: String,\n default: undefined,\n },\n style: {\n type: [String, Object] as PropType<string | CSSProperties>,\n default: undefined,\n },\n },\n emits: {\n 'node-click': (_node: Record<string, unknown>) => true,\n 'link-click': (_link: Record<string, unknown>) => true,\n 'node-hover': (_node: Record<string, unknown> | null) => true,\n 'link-hover': (_link: Record<string, unknown> | null) => true,\n },\n setup(props, { emit, expose }) {\n const containerRef = ref<HTMLDivElement | null>(null);\n let instance: SankeyInstance | null = null;\n let prevSpec = '';\n\n // Inject theme/darkMode from provider as fallbacks\n const contextTheme = inject(VizThemeKey, undefined);\n const contextDarkMode = inject(VizDarkModeKey, undefined);\n\n function resolveTheme(): ThemeConfig | undefined {\n return props.theme ?? contextTheme?.value;\n }\n\n function resolveDarkMode(): DarkMode | undefined {\n return props.darkMode ?? contextDarkMode?.value;\n }\n\n function mountSankey() {\n const container = containerRef.value;\n if (!container) return;\n\n const options: SankeyMountOptions = {\n theme: resolveTheme(),\n darkMode: resolveDarkMode(),\n onNodeClick: (node: Record<string, unknown>) => emit('node-click', node),\n onLinkClick: (link: Record<string, unknown>) => emit('link-click', link),\n onNodeHover: (node: Record<string, unknown> | null) => emit('node-hover', node),\n onLinkHover: (link: Record<string, unknown> | null) => emit('link-hover', link),\n responsive: true,\n };\n\n instance = createSankey(container, props.spec, options);\n prevSpec = JSON.stringify(props.spec);\n }\n\n function destroySankey() {\n instance?.destroy();\n instance = null;\n prevSpec = '';\n }\n\n // Expose imperative access to the instance\n expose({\n get instance() {\n return instance;\n },\n });\n\n onMounted(() => {\n mountSankey();\n });\n\n onUnmounted(() => {\n destroySankey();\n });\n\n // Watch spec changes\n watch(\n () => JSON.stringify(props.spec),\n (newVal) => {\n if (!instance) return;\n if (newVal !== prevSpec) {\n prevSpec = newVal;\n instance.update(props.spec);\n }\n },\n );\n\n // Recreate sankey when theme or darkMode change\n watch(\n [\n () => props.theme,\n () => props.darkMode,\n () => contextTheme?.value,\n () => contextDarkMode?.value,\n ],\n () => {\n if (!containerRef.value) return;\n destroySankey();\n mountSankey();\n },\n );\n\n const rootClass = () => {\n const base = 'oc-sankey-root';\n return props.class ? `${base} ${props.class}` : base;\n };\n\n return () =>\n h('div', {\n ref: containerRef,\n class: rootClass(),\n style: props.style,\n });\n },\n});\n","/**\n * VizThemeProvider: provides a theme and dark mode preference to all\n * descendant Chart, DataTable, and Graph components without prop drilling.\n *\n * Components use the context values as fallbacks when no explicit\n * `theme` or `darkMode` prop is passed.\n */\n\nimport type { DarkMode, ThemeConfig } from '@opendata-ai/openchart-core';\nimport { computed, defineComponent, type PropType, provide } from 'vue';\nimport { VizDarkModeKey, VizThemeKey } from './context';\n\nexport interface VizThemeProviderProps {\n theme: ThemeConfig | undefined;\n darkMode?: DarkMode;\n}\n\nexport const VizThemeProvider = defineComponent({\n name: 'VizThemeProvider',\n props: {\n theme: {\n type: Object as PropType<ThemeConfig | undefined>,\n default: undefined,\n },\n darkMode: {\n type: String as PropType<DarkMode>,\n default: undefined,\n },\n },\n setup(props, { slots }) {\n // Wrap in computed() so changes to props propagate reactively\n // through the injection system.\n const themeRef = computed(() => props.theme);\n const darkModeRef = computed(() => props.darkMode);\n\n provide(VizThemeKey, themeRef);\n provide(VizDarkModeKey, darkModeRef);\n\n return () => slots.default?.();\n },\n});\n","/**\n * Vue TileMap component: thin wrapper around the vanilla adapter.\n *\n * Mounts a tilemap instance on render, updates when spec changes,\n * and cleans up on unmount. All heavy lifting is done by the vanilla\n * createTileMap() function.\n */\n\nimport type { DarkMode, ThemeConfig, TileMapSpec } from '@opendata-ai/openchart-core';\nimport {\n createTileMap,\n type TileMapInstance,\n type TileMapMountOptions,\n} from '@opendata-ai/openchart-vanilla';\nimport {\n type CSSProperties,\n defineComponent,\n h,\n inject,\n onMounted,\n onUnmounted,\n type PropType,\n ref,\n watch,\n} from 'vue';\nimport { VizDarkModeKey, VizThemeKey } from './context';\n\nexport interface TileMapTileEvent {\n stateCode: string;\n stateName: string;\n value: number | null;\n data: Record<string, unknown>;\n}\n\nexport interface TileMapProps {\n spec: TileMapSpec;\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n class?: string;\n style?: string | CSSProperties;\n}\n\nexport const TileMap = defineComponent({\n name: 'TileMap',\n props: {\n spec: {\n type: Object as PropType<TileMapSpec>,\n required: true,\n },\n theme: {\n type: Object as PropType<ThemeConfig>,\n default: undefined,\n },\n darkMode: {\n type: String as PropType<DarkMode>,\n default: undefined,\n },\n class: {\n type: String,\n default: undefined,\n },\n style: {\n type: [String, Object] as PropType<string | CSSProperties>,\n default: undefined,\n },\n },\n emits: {\n 'tile-click': (_tile: TileMapTileEvent) => true,\n 'tile-hover': (_tile: TileMapTileEvent | null) => true,\n },\n setup(props, { emit, expose }) {\n const containerRef = ref<HTMLDivElement | null>(null);\n let instance: TileMapInstance | null = null;\n let prevSpec = '';\n\n // Inject theme/darkMode from provider as fallbacks\n const contextTheme = inject(VizThemeKey, undefined);\n const contextDarkMode = inject(VizDarkModeKey, undefined);\n\n function resolveTheme(): ThemeConfig | undefined {\n return props.theme ?? contextTheme?.value;\n }\n\n function resolveDarkMode(): DarkMode | undefined {\n return props.darkMode ?? contextDarkMode?.value;\n }\n\n function mountTileMap() {\n const container = containerRef.value;\n if (!container) return;\n\n const options: TileMapMountOptions = {\n theme: resolveTheme(),\n darkMode: resolveDarkMode(),\n onTileClick: (tile: TileMapTileEvent) => emit('tile-click', tile),\n onTileHover: (tile: TileMapTileEvent | null) => emit('tile-hover', tile),\n responsive: true,\n };\n\n instance = createTileMap(container, props.spec, options);\n prevSpec = JSON.stringify(props.spec);\n }\n\n function destroyTileMap() {\n instance?.destroy();\n instance = null;\n prevSpec = '';\n }\n\n // Expose imperative access to the instance\n expose({\n get instance() {\n return instance;\n },\n });\n\n onMounted(() => {\n mountTileMap();\n });\n\n onUnmounted(() => {\n destroyTileMap();\n });\n\n // Watch spec changes\n watch(\n () => JSON.stringify(props.spec),\n (newVal) => {\n if (!instance) return;\n if (newVal !== prevSpec) {\n prevSpec = newVal;\n instance.update(props.spec);\n }\n },\n );\n\n // Recreate tilemap when theme or darkMode change\n watch(\n [\n () => props.theme,\n () => props.darkMode,\n () => contextTheme?.value,\n () => contextDarkMode?.value,\n ],\n () => {\n if (!containerRef.value) return;\n destroyTileMap();\n mountTileMap();\n },\n );\n\n const rootClass = () => {\n const base = 'oc-tilemap-root';\n return props.class ? `${base} ${props.class}` : base;\n };\n\n return () =>\n h('div', {\n ref: containerRef,\n class: rootClass(),\n style: props.style,\n });\n },\n});\n","/**\n * Visualization routing component: renders Chart, DataTable, or Graph\n * based on the spec type. Use this when rendering arbitrary VizSpec values.\n *\n * For event handlers, use the specific component (Chart, DataTable, Graph) directly.\n */\n\nimport type { DarkMode, ThemeConfig, VizSpec } from '@opendata-ai/openchart-core';\nimport {\n isBarListSpec,\n isGeoMapSpec,\n isGraphSpec,\n isSankeySpec,\n isTableSpec,\n isTileMapSpec,\n} from '@opendata-ai/openchart-core';\nimport { type CSSProperties, defineComponent, h, type PropType } from 'vue';\nimport { BarList } from './BarList';\nimport { Chart } from './Chart';\nimport { DataTable } from './DataTable';\nimport { GeoMap } from './GeoMap';\nimport { Graph } from './Graph';\nimport { Sankey } from './Sankey';\nimport { TileMap } from './TileMap';\n\nexport interface VisualizationProps {\n spec: VizSpec;\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n class?: string;\n style?: string | CSSProperties;\n}\n\nexport const Visualization = defineComponent({\n name: 'Visualization',\n props: {\n spec: {\n type: Object as PropType<VizSpec>,\n required: true,\n },\n theme: {\n type: Object as PropType<ThemeConfig>,\n default: undefined,\n },\n darkMode: {\n type: String as PropType<DarkMode>,\n default: undefined,\n },\n class: {\n type: String,\n default: undefined,\n },\n style: {\n type: [String, Object] as PropType<string | CSSProperties>,\n default: undefined,\n },\n },\n setup(props) {\n return () => {\n const { spec, theme, darkMode, class: className, style } = props;\n const sharedProps = { theme, darkMode, class: className, style };\n\n if (isTableSpec(spec)) {\n return h(DataTable, { ...sharedProps, spec });\n }\n if (isGraphSpec(spec)) {\n return h(Graph, { ...sharedProps, spec });\n }\n if (isSankeySpec(spec)) {\n return h(Sankey, { ...sharedProps, spec });\n }\n if (isTileMapSpec(spec)) {\n return h(TileMap, { ...sharedProps, spec });\n }\n if (isBarListSpec(spec)) {\n return h(BarList, { ...sharedProps, spec });\n }\n if (isGeoMapSpec(spec)) {\n return h(GeoMap, { ...sharedProps, spec });\n }\n return h(Chart, { ...sharedProps, spec });\n };\n },\n});\n"],"mappings":"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","names":["inject","inject","defineComponent","h","inject","onMounted","onUnmounted","ref","watch","defineComponent","ref","inject","onMounted","onUnmounted","watch","h","defineComponent","h","onMounted","onUnmounted","ref","watch","createChart","onMounted","onUnmounted","ref","watch","onUnmounted","ref","watch","ref","onMounted","onUnmounted","ref","shallowRef","watch","ref","createTable","defineComponent","h","inject","onMounted","onUnmounted","ref","watch","defineComponent","ref","inject","createTable","onMounted","onUnmounted","watch","h","defineComponent","h","inject","onMounted","onUnmounted","ref","watch","defineComponent","ref","inject","onMounted","onUnmounted","watch","h","defineComponent","h","inject","onMounted","onUnmounted","ref","watch","defineComponent","ref","inject","onMounted","onUnmounted","watch","h","defineComponent","h","inject","onMounted","onUnmounted","ref","watch","defineComponent","ref","inject","onMounted","onUnmounted","watch","h","computed","defineComponent","defineComponent","computed","defineComponent","h","inject","onMounted","onUnmounted","ref","watch","defineComponent","ref","inject","onMounted","onUnmounted","watch","h","defineComponent","h","defineComponent","h"]}
|
package/dist/styles.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
@layer oc.tokens{.oc-root,.oc-chart-root,.oc-table-wrapper,.oc-table-root,.oc-graph-wrapper,.oc-graph-root,.oc-sankey-root,.oc-tilemap-root,.oc-barlist-root,.oc-map-root{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;--oc-font-family:"Inter Variable", Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;--oc-font-mono:"JetBrains Mono", "Fira Code", "Cascadia Code", monospace;--oc-ease-smooth:linear(0, .157, .438, .64, .766, .85, .906, .941, .964, .978, .988, .994, .998, 1);--oc-ease-snappy:linear(0, .012, .048, .108, .194, .302, .426, .559, .69, .808, .905, .973, 1.013, 1.028, 1.023, 1.006, .984, .966, .957, .957, .964, .975, .986, .995, 1, 1.003, 1.002, 1, .998, .998, .999, 1);--oc-animation-duration:.45s;--oc-animation-stagger:30ms;--oc-annotation-delay:.15s;--oc-title-size:26px;--oc-title-weight:600;--oc-title-tracking:-.022em;--oc-subtitle-size:14px;--oc-subtitle-weight:400;--oc-source-size:11px;--oc-source-weight:400;--oc-body-size:13px;--oc-eyebrow-size:11px;--oc-eyebrow-weight:500;--oc-eyebrow-tracking:.08em;--oc-bg:#fff;--oc-card:#fff;--oc-secondary:#f4f4f5;--oc-text:#09090b;--oc-text-secondary:#3f3f46;--oc-text-muted:#71717a;--oc-text-faint:#d4d4d8;--oc-gray-100:#f0f0f0;--oc-gray-200:#e1e1e2;--oc-gray-300:#c9c9c9;--oc-gray-400:#9d9d9d;--oc-gray-600:#787879;--oc-gray-800:#474748;--oc-gridline:rgba(0,0,0,.08);--oc-axis:rgba(0,0,0,.14);--oc-border:rgba(0,0,0,.08);--oc-border-radius:8px;--oc-radius-sm:2px;--oc-radius-md:6px;--oc-radius-lg:var(--oc-border-radius);--oc-radius-full:999px;--oc-accent:#06b6d4;--oc-accent-strong:#0891b2;--oc-positive:#15803d;--oc-negative:#dc2626;--oc-positive-tint:color-mix(in srgb, var(--oc-positive) 10%, var(--oc-bg));--oc-negative-tint:color-mix(in srgb, var(--oc-negative) 10%, var(--oc-bg));--oc-focus:#3b82f6;--oc-focus-ring:rgba(59,130,246,.1);--oc-focus-ring-strong:rgba(59,130,246,.25);--oc-editable-hover:rgba(79,70,229,.35);--oc-space-2:8px;--oc-space-4:16px;--oc-hover-dim:.3;--oc-hover-duration:.14s;--oc-map-hover-dim:.75;--oc-hover-bg:rgba(0,0,0,.024);--oc-tooltip-bg:rgba(255,255,255,.88);--oc-tooltip-border:rgba(0,0,0,.08);--oc-tooltip-shadow:0 2px 8px rgba(0,0,0,.08), 0 0 1px rgba(0,0,0,.12);--oc-tooltip-text:#09090b;--oc-legend-text:#3f3f46}.oc-dark{--oc-bg:#09090b;--oc-card:#111113;--oc-secondary:#27272a;--oc-text:#f7f8f8;--oc-text-secondary:#d0d6e0;--oc-text-muted:#a1a1aa;--oc-text-faint:#52525b;--oc-gridline:rgba(255,255,255,.06);--oc-axis:rgba(255,255,255,.14);--oc-border:rgba(255,255,255,.1);--oc-accent:#06b6d4;--oc-accent-strong:#06b6d4;--oc-positive:#4ade80;--oc-negative:#f87171;--oc-focus:#60a5fa;--oc-hover-bg:rgba(255,255,255,.05);--oc-tooltip-bg:rgba(17,17,19,.92);--oc-tooltip-border:rgba(255,255,255,.08);--oc-tooltip-shadow:0 2px 8px rgba(0,0,0,.3), 0 0 1px rgba(0,0,0,.4);--oc-tooltip-text:#f7f8f8;--oc-legend-text:#d0d6e0}}@layer oc.base{.oc-chart-root,.oc-table-root,.oc-graph-root,.oc-sankey-root,.oc-barlist-root,.oc-tilemap-root,.oc-map-root{width:100%;height:100%}.oc-table-root{overflow:auto}.oc-chart{font-family:var(--oc-font-family);font-variant-numeric:tabular-nums;width:100%;display:block}.oc-tilemap,.oc-map{width:100%;height:auto;display:block}.oc-map-feature{transition:opacity var(--oc-hover-duration) ease-out, stroke-width .14s ease-out}.oc-barlist{width:100%;display:block}.oc-sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:clip}.oc-editable-hover{outline:1.5px solid var(--oc-editable-hover);outline-offset:2px;border-radius:var(--oc-radius-sm)}.oc-root:focus-visible{outline:2px solid var(--oc-focus);outline-offset:2px}.oc-mark-focused{outline:2px solid var(--oc-focus);outline-offset:1px;border-radius:var(--oc-radius-sm)}}@layer oc.components{.oc-chrome{font-family:var(--oc-font-family)}.oc-eyebrow{font-size:var(--oc-eyebrow-size);font-weight:var(--oc-eyebrow-weight);letter-spacing:var(--oc-eyebrow-tracking);text-transform:uppercase;fill:var(--oc-accent)}.oc-title{font-size:var(--oc-title-size);font-weight:var(--oc-title-weight);letter-spacing:var(--oc-title-tracking);fill:var(--oc-text)}.oc-subtitle{font-size:var(--oc-subtitle-size);font-weight:var(--oc-subtitle-weight);fill:var(--oc-text-muted)}.oc-source,.oc-byline,.oc-footer{font-size:var(--oc-source-size);font-weight:var(--oc-source-weight);fill:var(--oc-text-muted)}.oc-brand{letter-spacing:.02em;fill:var(--oc-text-faint);font-size:11px;font-weight:500}.oc-eyebrow-dot{fill:var(--oc-accent)}.oc-metrics{font-family:var(--oc-font-family)}.oc-metric-label{letter-spacing:.06em;text-transform:uppercase;fill:var(--oc-text-muted);font-size:11px;font-weight:500}.oc-metric-value{letter-spacing:-.02em;fill:var(--oc-text);font-variant-numeric:tabular-nums;font-size:22px;font-weight:600}.oc-metric-delta-up{fill:var(--oc-positive);font-size:12px;font-weight:500}.oc-metric-delta-down{fill:var(--oc-negative);font-size:12px;font-weight:500}.oc-metric-secondary{fill:var(--oc-text-muted);font-size:12px;font-weight:400}.oc-axis-tick-inline{fill:var(--oc-text-muted);font-size:11px;font-weight:400}.oc-endpoint-labels{font-family:var(--oc-font-family)}.oc-endpoint-label{fill:var(--oc-endpoint-label-color,var(--oc-text))}.oc-endpoint-value{fill:var(--oc-endpoint-value-color,var(--oc-text-muted))}.oc-endpoint-leader{stroke:var(--oc-endpoint-leader-color,currentColor)}.oc-annotation-subtitle{fill:var(--oc-annotation-subtitle-color,var(--oc-text-muted))}.oc-table-footer-row{align-items:baseline;gap:16px;padding:16px 16px 4px;display:flex}.oc-chrome-footer{padding-top:0}.oc-table-footer-row .oc-table-ref{text-align:right;flex-shrink:0;margin-left:auto}.oc-tooltip{pointer-events:none;z-index:1000;background:var(--oc-tooltip-bg);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);border:1px solid var(--oc-tooltip-border);border-radius:var(--oc-radius-lg);box-shadow:var(--oc-tooltip-shadow);color:var(--oc-tooltip-text);font-family:var(--oc-font-family);min-width:140px;max-width:280px;padding:0;font-size:12px;line-height:1.4;transition:left .1s ease-in-out,top .1s ease-in-out;animation:.12s ease-out oc-tooltip-in;display:none;position:absolute}.oc-tooltip .oc-tooltip-header{align-items:center;gap:8px;padding:8px 10px 6px;display:flex}.oc-tooltip .oc-tooltip-dot{border-radius:50%;flex-shrink:0;width:8px;height:8px}.oc-tooltip .oc-tooltip-title{letter-spacing:.04em;text-transform:uppercase;color:var(--oc-text-muted);white-space:nowrap;text-overflow:ellipsis;font-size:11px;font-weight:600;overflow:hidden}.oc-tooltip .oc-tooltip-body{border-top:1px solid var(--oc-tooltip-border);padding:6px 10px 8px}.oc-tooltip .oc-tooltip-body:first-child{border-top:none;padding-top:10px}.oc-tooltip .oc-tooltip-row{justify-content:space-between;align-items:baseline;gap:16px;padding:2px 0;display:flex}.oc-tooltip .oc-tooltip-row-swatch{border-radius:50%;flex-shrink:0;width:8px;height:8px;margin-right:6px;display:inline-block;transform:translateY(-1px)}.oc-tooltip .oc-tooltip-label{color:var(--oc-text-secondary);white-space:nowrap;flex-shrink:0;align-items:center;font-size:12px;font-weight:400;display:inline-flex}.oc-tooltip .oc-tooltip-value{font-variant-numeric:tabular-nums;color:var(--oc-tooltip-text);text-align:right;text-overflow:ellipsis;white-space:nowrap;font-size:12px;font-weight:500;overflow:hidden}.oc-tooltip .oc-tooltip-row--emphasis .oc-tooltip-label{color:var(--oc-tooltip-text);font-weight:600}.oc-tooltip .oc-tooltip-row--emphasis .oc-tooltip-value{font-weight:600}.oc-tooltip .oc-tooltip-row--total{border-top:1px solid var(--oc-tooltip-border);margin-top:4px;padding-top:5px}.oc-tooltip .oc-tooltip-row--total .oc-tooltip-label{color:var(--oc-tooltip-text);font-weight:500}.oc-tooltip .oc-tooltip-row--total .oc-tooltip-value{font-weight:600}.oc-crosshair{pointer-events:none;transition:x1 50ms ease-in-out,x2 50ms ease-in-out}.oc-snap-dots circle{pointer-events:none;transition:cx 50ms ease-in-out,cy 50ms ease-in-out}.oc-legend{font-family:var(--oc-font-family)}.oc-legend-entry{cursor:default}.oc-marks.oc-hover-active .oc-mark--dim:not([opacity="0"]){opacity:var(--oc-hover-dim)}.oc-marks.oc-hover-active .oc-mark-rect.oc-mark--hover>*,.oc-marks.oc-hover-active .oc-mark-arc.oc-mark--hover>*,.oc-marks.oc-hover-active circle.oc-mark-point.oc-mark--hover{stroke:var(--oc-text);stroke-width:1px}.oc-chart:not(.oc-animate):not(.oc-transitioning) .oc-marks .oc-mark{transition:opacity var(--oc-hover-duration) ease-out}.oc-legend-entry--dim .oc-legend-swatch-line,.oc-legend-entry--dim .oc-legend-swatch-rect,.oc-legend-entry--dim>circle{opacity:var(--oc-hover-dim);transition:opacity var(--oc-hover-duration) ease-out}.oc-legend-hit{fill:transparent}.oc-legend-entry:focus{outline:none}.oc-legend-entry:focus-visible .oc-legend-hit{stroke:var(--oc-focus);stroke-width:2px}.oc-endpoint-label-entry{cursor:default}.oc-map-feature--hover{stroke:var(--oc-text);stroke-width:1.5px;vector-effect:non-scaling-stroke}.oc-map-features[data-hover] .oc-map-feature{transition:opacity var(--oc-hover-duration) ease-out}.oc-map-features[data-hover="0"] .oc-map-feature:not([data-bin-index="0"]),.oc-map-features[data-hover="1"] .oc-map-feature:not([data-bin-index="1"]),.oc-map-features[data-hover="2"] .oc-map-feature:not([data-bin-index="2"]),.oc-map-features[data-hover="3"] .oc-map-feature:not([data-bin-index="3"]),.oc-map-features[data-hover="4"] .oc-map-feature:not([data-bin-index="4"]),.oc-map-features[data-hover="5"] .oc-map-feature:not([data-bin-index="5"]),.oc-map-features[data-hover="6"] .oc-map-feature:not([data-bin-index="6"]),.oc-map-features[data-hover="7"] .oc-map-feature:not([data-bin-index="7"]),.oc-map-features[data-hover="8"] .oc-map-feature:not([data-bin-index="8"]),.oc-map-features[data-hover="9"] .oc-map-feature:not([data-bin-index="9"]),.oc-map-features[data-hover="10"] .oc-map-feature:not([data-bin-index="10"]),.oc-map-features[data-hover="11"] .oc-map-feature:not([data-bin-index="11"]){opacity:var(--oc-map-hover-dim)}.oc-legend-bin{cursor:default}.oc-tilemap-tiles.oc-hover-active .oc-tilemap-tile{transition:opacity var(--oc-hover-duration) ease-out}.oc-tilemap-tiles.oc-hover-active .oc-tilemap-tile:not(.oc-tilemap-tile--hover){opacity:var(--oc-hover-dim)}.oc-tilemap-tile--hover>rect{stroke:var(--oc-text);stroke-width:1.5px}.oc-series-search{font-family:var(--oc-font-family);z-index:10;justify-content:flex-end;align-items:center;gap:8px;display:flex;position:absolute}.oc-series-search-chips{scrollbar-width:none;align-items:center;gap:6px;min-width:0;display:flex;overflow-x:auto}.oc-series-search-chips::-webkit-scrollbar{display:none}.oc-series-search-chip{border:1px solid var(--oc-border);border-radius:var(--oc-radius-full);background:var(--oc-secondary);color:var(--oc-text-secondary);white-space:nowrap;align-items:center;gap:4px;padding:3px 4px 3px 10px;font-size:12px;font-weight:500;line-height:16px;display:inline-flex}.oc-series-search-chip-remove{width:16px;height:16px;color:var(--oc-text-muted);cursor:pointer;background:0 0;border:none;border-radius:50%;justify-content:center;align-items:center;margin:-4px -2px -4px -4px;padding:4px;transition:color .15s,background-color .15s;display:inline-flex}.oc-series-search-chip-remove:hover{color:var(--oc-text);background:var(--oc-hover-bg)}.oc-series-search-chip-remove:focus-visible{outline:2px solid var(--oc-focus);outline-offset:1px}.oc-series-search-chip-remove svg{display:block}.oc-series-search-box{flex:0 220px;min-width:120px;position:relative}.oc-series-search-icon{color:var(--oc-text-muted);pointer-events:none;position:absolute;top:50%;left:9px;transform:translateY(-50%)}.oc-series-search-input{height:32px;padding:0 10px 0 28px}.oc-series-search-listbox{border:1px solid var(--oc-border);border-radius:var(--oc-radius-lg);background:var(--oc-card);min-width:100%;max-height:240px;box-shadow:var(--oc-tooltip-shadow);z-index:20;margin:0;padding:4px;list-style:none;position:absolute;top:calc(100% + 4px);right:0;overflow-y:auto}.oc-series-search-option{border-radius:var(--oc-radius-sm);color:var(--oc-text);cursor:pointer;white-space:nowrap;text-overflow:ellipsis;padding:6px 10px;font-size:13px;overflow:hidden}.oc-series-search-option[aria-selected=true],.oc-series-search-option:hover{background:var(--oc-hover-bg)}.oc-series-search-match{font-weight:600}.oc-series-search-empty{color:var(--oc-text-muted);padding:6px 10px;font-size:12px}.oc-ydi-region{opacity:.35;transition:opacity .4s}.oc-ydi-region[data-ydi-hidden=true]{opacity:0}.oc-ydi-boundary{stroke:var(--oc-text-muted);stroke-width:1px;stroke-dasharray:3 3;stroke-opacity:.6}.oc-ydi-guess{stroke:var(--oc-focus);stroke-width:2.5px;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:1 6}.oc-ydi-comparison{stroke:var(--oc-text-muted);stroke-width:1.5px;stroke-opacity:.5;stroke-dasharray:4 4}.oc-ydi-clip-rect.oc-ydi-clip-animate{transition:width .7s cubic-bezier(.22,1,.36,1)}.oc-ydi-controls{pointer-events:none;font-family:var(--oc-font-family);box-sizing:border-box;z-index:10;flex-direction:column;justify-content:space-between;align-items:flex-end;padding:8px;display:flex}.oc-ydi-prompt{border-radius:var(--oc-radius-md);background:var(--oc-card);border:1px solid var(--oc-border);max-width:100%;color:var(--oc-text-secondary);text-align:center;box-shadow:var(--oc-tooltip-shadow);align-self:center;padding:6px 12px;font-size:13px;font-weight:500;line-height:16px}.oc-ydi-controls.oc-ydi-revealed .oc-ydi-prompt{display:none}.oc-ydi-actions{pointer-events:none;flex-wrap:wrap;justify-content:flex-end;gap:8px;display:flex}.oc-ydi-reveal-button,.oc-ydi-reset-button{pointer-events:auto;border:1px solid var(--oc-border);border-radius:var(--oc-radius-md);background:var(--oc-bg);color:var(--oc-text);white-space:nowrap;cursor:pointer;box-shadow:var(--oc-tooltip-shadow);justify-content:center;align-items:center;padding:6px 14px;font-family:inherit;font-size:13px;font-weight:500;transition:background-color .15s,border-color .15s;display:inline-flex}.oc-ydi-reset-button[hidden]{display:none}.oc-ydi-reveal-button:hover,.oc-ydi-reset-button:hover{background:var(--oc-hover-bg)}.oc-ydi-reveal-button:focus-visible{outline:2px solid var(--oc-focus);outline-offset:2px}.oc-ydi-reset-button:focus-visible{outline:2px solid var(--oc-focus);outline-offset:2px}.oc-ydi-reveal-button:disabled{opacity:.5;cursor:default}.oc-table-wrapper{font-family:var(--oc-font-family);color:var(--oc-text);background:var(--oc-bg)}.oc-table-wrapper>.oc-chrome{margin-bottom:16px;padding-left:16px;padding-right:16px}.oc-table-wrapper>.oc-chrome:first-child{padding-top:4px}.oc-table-wrapper table{border-collapse:collapse;width:100%}.oc-table-wrapper th{text-align:left;border-bottom:1px solid var(--oc-border);box-sizing:border-box;padding:12px 16px;line-height:24px}.oc-table-wrapper td{text-align:left;border-bottom:1px solid var(--oc-border);box-sizing:border-box;padding:12px 16px;line-height:24px}.oc-table-wrapper th{text-transform:uppercase;letter-spacing:.04em;color:var(--oc-text-muted);font-variant-numeric:tabular-nums;white-space:nowrap;font-size:12px;font-weight:500}.oc-table-wrapper thead{z-index:2;background:var(--oc-bg);position:sticky;top:0}.oc-table-wrapper thead th{border-bottom-width:1px}.oc-table-wrapper td{font-variant-numeric:tabular-nums;font-size:14px}.oc-table-wrapper th:focus{outline:2px solid var(--oc-focus);outline-offset:-2px}.oc-table-wrapper tbody:focus{outline:none}.oc-table-title{font-size:var(--oc-title-computed-size,var(--oc-title-size));font-weight:var(--oc-title-computed-weight,var(--oc-title-weight));color:var(--oc-title-computed-color,var(--oc-text));margin-bottom:4px}.oc-table-subtitle{font-size:var(--oc-subtitle-computed-size,var(--oc-subtitle-size));font-weight:var(--oc-subtitle-computed-weight,var(--oc-subtitle-weight));color:var(--oc-subtitle-computed-color,var(--oc-text-secondary));margin-bottom:8px}.oc-table-source{font-size:var(--oc-source-computed-size,var(--oc-source-size));color:var(--oc-source-computed-color,var(--oc-text-muted))}.oc-table-footer-text{font-size:var(--oc-footer-computed-size,var(--oc-source-size));color:var(--oc-footer-computed-color,var(--oc-text-muted))}.oc-table-scroll{overflow-x:auto}.oc-table--sticky th:first-child{z-index:1;background:var(--oc-bg);position:sticky;left:0}.oc-table--sticky td:first-child{z-index:1;background:var(--oc-bg);position:sticky;left:0}.oc-table-sort-btn{cursor:pointer;vertical-align:middle;background:0 0;border:none;flex-direction:column;align-items:center;gap:2px;margin-left:6px;padding:2px;display:inline-flex}.oc-table-sort-btn:before{content:"";border-left:5px solid transparent;border-right:5px solid transparent;width:0;height:0;transition:opacity .15s,border-color .15s;display:block}.oc-table-sort-btn:after{content:"";border-left:5px solid transparent;border-right:5px solid transparent;width:0;height:0;transition:opacity .15s,border-color .15s;display:block}.oc-table-sort-btn:before{border-bottom:4.5px solid var(--oc-text-secondary);opacity:.35}.oc-table-sort-btn:after{border-top:4.5px solid var(--oc-text-secondary);opacity:.35}.oc-table-sort-btn:hover:before{opacity:.75}.oc-table-sort-btn:hover:after{opacity:.75}th[aria-sort=ascending] .oc-table-sort-btn:before{opacity:1;border-bottom-color:var(--oc-text)}th[aria-sort=ascending] .oc-table-sort-btn:after{opacity:.15}th[aria-sort=descending] .oc-table-sort-btn:after{opacity:1;border-top-color:var(--oc-text)}th[aria-sort=descending] .oc-table-sort-btn:before{opacity:.15}.oc-table-search input,.oc-series-search-input{border:1px solid var(--oc-border);border-radius:var(--oc-radius-md);background:var(--oc-bg);width:100%;color:var(--oc-text);box-sizing:border-box;font-family:inherit;font-size:13px;transition:border-color .15s}.oc-table-search input::-ms-input-placeholder{color:var(--oc-text-muted);font-size:13px}.oc-table-search input::placeholder{color:var(--oc-text-muted);font-size:13px}.oc-series-search-input::-ms-input-placeholder{color:var(--oc-text-muted);font-size:13px}.oc-series-search-input::placeholder{color:var(--oc-text-muted);font-size:13px}.oc-table-search input:focus,.oc-series-search-input:focus{border-color:var(--oc-focus);box-shadow:0 0 0 3px var(--oc-focus-ring);outline:none}.oc-table-search{padding:8px 0}.oc-table-search input{padding:8px 12px}.oc-table-pagination{color:var(--oc-text-secondary);justify-content:space-between;align-items:center;padding:12px 0 4px;font-size:13px;display:flex}.oc-table-pagination button{border:1px solid var(--oc-border);border-radius:var(--oc-radius-md);background:var(--oc-bg);color:var(--oc-text);cursor:pointer;padding:6px 14px;font-family:inherit;font-size:13px;transition:background .15s,border-color .15s}.oc-table-pagination button:disabled{opacity:.35;cursor:not-allowed}.oc-table-pagination button:hover:not(:disabled){background:var(--oc-hover-bg);border-color:var(--oc-axis)}.oc-table-pagination button:focus-visible{outline:2px solid var(--oc-focus);outline-offset:1px}.oc-table-pagination-info{font-variant-numeric:tabular-nums}.oc-table-pagination-btns{gap:8px;display:flex}.oc-table-bar{position:relative}.oc-table-bar-fill{border-radius:var(--oc-radius-sm);opacity:.18;pointer-events:none;position:absolute;top:8px;bottom:8px;left:0}.oc-table-bar-value{z-index:1;position:relative}.oc-table-sparkline{width:100%;display:block;position:relative}.oc-table-sparkline svg{width:100%;display:block;overflow:visible}.oc-table-sparkline-dot{border-radius:50%;width:5px;height:5px;position:absolute}.oc-table-sparkline-labels{justify-content:space-between;font-size:11px;line-height:1;display:flex}.oc-table-image{vertical-align:middle;display:inline-block}.oc-table-image img{object-fit:cover}.oc-table-image-rounded img{border-radius:50%}.oc-table-flag{font-size:1.2em}:is(.oc-table--condensed,.oc-table--compact) th{padding:8px 12px;font-size:13px;line-height:24px}:is(.oc-table--condensed,.oc-table--compact) td{padding:8px 12px;font-size:13px;line-height:24px}:is(.oc-table--condensed,.oc-table--compact) th{font-size:11px}:is(.oc-table--condensed,.oc-table--compact) .oc-table-bar-fill{top:5px;bottom:5px}.oc-table--relaxed th{padding:16px 20px;line-height:24px}.oc-table--relaxed td{padding:16px 20px;line-height:24px}.oc-table--relaxed .oc-table-bar-fill{top:12px;bottom:12px}.oc-table--striped tbody tr:nth-child(2n){background:color-mix(in srgb, var(--oc-text) 3%, transparent)}.oc-table-delta{border-radius:var(--oc-radius-md);font-variant-numeric:tabular-nums;align-items:baseline;gap:4px;padding:2px 8px;font-weight:500;line-height:16px;display:inline-flex}.oc-table-delta-arrow{font-size:.8em;line-height:1}.oc-table-delta--positive{color:var(--oc-positive);background:var(--oc-positive-tint)}.oc-table-delta--negative{color:var(--oc-negative);background:var(--oc-negative-tint)}.oc-table-delta--neutral{color:var(--oc-text-muted);background:color-mix(in srgb, var(--oc-text) 6%, transparent)}.oc-table-chip{border-radius:var(--oc-radius-full);white-space:nowrap;align-items:center;gap:6px;padding:2px 8px;font-size:12px;font-weight:500;line-height:16px;display:inline-flex}.oc-table-chip-dot{border-radius:50%;flex:none;width:6px;height:6px}tfoot.oc-table-total{z-index:2;background:var(--oc-bg);position:sticky;bottom:0}tfoot.oc-table-total td{border-bottom:none;border-top:1px solid var(--oc-border);font-weight:600}.oc-table--cards .oc-table-scroll{overflow-x:hidden}.oc-table--cards table{table-layout:fixed}.oc-table--cards thead{clip-path:inset(50%);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}.oc-table--cards tbody tr{border-bottom:1px solid var(--oc-border);grid-template-columns:repeat(2,minmax(0,1fr));align-items:baseline;gap:2px 12px;padding:10px 12px;display:grid}.oc-table--cards tfoot tr{border-bottom:1px solid var(--oc-border);grid-template-columns:repeat(2,minmax(0,1fr));align-items:baseline;gap:2px 12px;padding:10px 12px;display:grid}.oc-table--cards td{overflow-wrap:anywhere;text-align:right;border-bottom:none;width:auto;max-width:100%;padding:0;display:block}.oc-table--cards td:before{content:attr(data-label);letter-spacing:.04em;text-transform:uppercase;color:var(--oc-text-muted);text-align:left;font-size:11px;font-weight:500;display:block}.oc-table--cards td[data-label=""]:before{content:none}.oc-table--cards td[data-priority="1"]{text-align:left;grid-column:1/-1;font-size:15px;font-weight:600}.oc-table--cards td[data-priority="1"]:before{content:none}.oc-table--cards td[data-priority="3"]{display:none}.oc-table--cards .oc-table-sparkline{width:100%}.oc-table--clickable tbody tr{cursor:pointer}.oc-table--clickable tbody tr:hover{background:var(--oc-hover-bg)}.oc-table-cell-focus{outline:2px solid var(--oc-focus);outline-offset:-2px}.oc-table-empty{text-align:center;color:var(--oc-text-secondary);padding:32px 16px;font-size:14px;font-style:italic}.oc-graph-wrapper{background:var(--oc-bg);font-family:var(--oc-font-family);width:100%;height:100%;position:relative;overflow:hidden}.oc-graph-canvas{cursor:grab;width:100%;height:100%;display:block}.oc-graph-canvas--dragging{cursor:grabbing}.oc-graph-3d,.oc-graph-3d .scene-container{width:100%;height:100%;display:block}.oc-graph-3d{cursor:grab}.oc-graph-3d .scene-container canvas{width:100%;height:100%;display:block}.oc-graph-chrome{z-index:2;pointer-events:none;padding:16px 16px 8px;position:absolute;top:0;left:0;right:0}.oc-graph-chrome .oc-title{font-size:var(--oc-title-size);font-weight:var(--oc-title-weight);letter-spacing:var(--oc-title-tracking);color:var(--oc-text);--_stroke:color-mix(in srgb, var(--oc-bg) 80%, transparent);text-shadow:-2px -2px 0 var(--_stroke), 2px -2px 0 var(--_stroke), -2px 2px 0 var(--_stroke), 2px 2px 0 var(--_stroke), 0 -2px 0 var(--_stroke), 0 2px 0 var(--_stroke), -2px 0 0 var(--_stroke), 2px 0 0 var(--_stroke);margin:0 0 4px}.oc-graph-chrome .oc-subtitle{font-size:var(--oc-subtitle-size);color:var(--oc-text-secondary);--_stroke:color-mix(in srgb, var(--oc-bg) 80%, transparent);text-shadow:-1px -1px 0 var(--_stroke), 1px -1px 0 var(--_stroke), -1px 1px 0 var(--_stroke), 1px 1px 0 var(--_stroke);margin:0}.oc-graph-legend{background:color-mix(in srgb, var(--oc-bg) 88%, transparent);border:1px solid var(--oc-border);border-radius:var(--oc-radius-lg);color:var(--oc-text-secondary);max-height:200px;padding:8px 12px;font-size:12px;position:absolute;top:12px;right:12px;overflow-y:auto}.oc-graph-legend-item{width:100%;font:inherit;color:inherit;text-align:left;cursor:default;background:0 0;border:none;align-items:center;gap:6px;margin:0;padding:2px 0;display:flex}button.oc-graph-legend-item{cursor:pointer;border-radius:var(--oc-radius-sm)}button.oc-graph-legend-item:hover{background:var(--oc-focus-ring)}button.oc-graph-legend-item:focus-visible{outline:2px solid var(--oc-focus);outline-offset:1px}.oc-graph-legend-item--inactive{opacity:.45}.oc-graph-legend-label{flex:auto}.oc-graph-legend-count{color:var(--oc-text-secondary);font-variant-numeric:tabular-nums;margin-left:auto;padding-left:8px}.oc-graph-legend-swatch{border-radius:50%;flex-shrink:0;width:10px;height:10px}.oc-graph-legend-swatch--line{border-radius:1px;width:12px;height:3px}.oc-graph-search{position:absolute;top:12px;left:12px}.oc-graph-search input{font-family:var(--oc-font-family);font-size:var(--oc-body-size);border:1px solid var(--oc-border);border-radius:var(--oc-radius-md);background:color-mix(in srgb, var(--oc-bg) 88%, transparent);color:var(--oc-text);outline:none;padding:6px 10px}.oc-graph-search input:focus{border-color:var(--oc-focus);box-shadow:0 0 0 2px var(--oc-focus-ring-strong)}.oc-sankey:not(.oc-animate) .oc-sankey-link path{transition:fill-opacity var(--oc-hover-duration) ease-out}.oc-sankey:not(.oc-animate) .oc-sankey-node,.oc-sankey:not(.oc-animate) .oc-sankey-label{transition:opacity var(--oc-hover-duration) ease-out}.oc-sankey-label{pointer-events:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}.oc-chart[data-display=sparkline]{margin:0;padding:0;display:block}.oc-chart[data-display=sparkline] .oc-pulse{animation:.6s ease-out oc-pulse}@media (prefers-reduced-motion:reduce){.oc-chart[data-display=sparkline] .oc-pulse{animation:none}}}@layer oc.animation{.oc-table-wrapper.oc-animate>.oc-chrome{animation:oc-enter-fade calc(var(--oc-animation-duration) * .6) var(--oc-animation-ease,var(--oc-ease-smooth)) both}.oc-table-wrapper.oc-animate thead{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .4) var(--oc-animation-ease,var(--oc-ease-smooth)) both}.oc-table-wrapper.oc-animate tbody tr{animation:oc-table-enter-row var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-row-index,0))}.oc-table-wrapper.oc-animate tbody td{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .5) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-row-index,0))}.oc-table-wrapper.oc-animate td.oc-table-heatmap{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .7) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-row-index,0) + var(--oc-animation-duration) * .3)}.oc-table-wrapper.oc-animate td.oc-table-category{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .7) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-row-index,0) + var(--oc-animation-duration) * .3)}.oc-table-wrapper.oc-animate .oc-table-bar-fill{animation:oc-table-enter-bar-fill calc(var(--oc-animation-duration) * .8) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-row-index,0) + var(--oc-animation-duration) * .3)}.oc-table-wrapper.oc-animate .oc-table-sparkline>svg{animation:oc-enter-line calc(var(--oc-animation-duration) * .8) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-row-index,0) + var(--oc-animation-duration) * .4)}.oc-table-wrapper.oc-animate .oc-table-sparkline-dot{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .3) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-row-index,0) + var(--oc-animation-duration) * .8)}.oc-table-wrapper.oc-animate .oc-table-sparkline-labels{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .3) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-row-index,0) + var(--oc-animation-duration) * .8)}.oc-table-wrapper.oc-animate .oc-table-search{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .5) var(--oc-animation-ease,var(--oc-ease-smooth)) both}.oc-table-wrapper.oc-animate .oc-table-pagination{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .5) var(--oc-animation-ease,var(--oc-ease-smooth)) both}@keyframes oc-enter-bar{0%{clip-path:inset(100% 0 0);opacity:0}75%{opacity:1}to{clip-path:inset(0);opacity:1}}@keyframes oc-enter-bar-h{0%{clip-path:inset(0 100% 0 0);opacity:0}75%{opacity:1}to{clip-path:inset(0);opacity:1}}@keyframes oc-enter-line{0%{clip-path:inset(0 100% 0 0);opacity:0}15%{opacity:1}to{clip-path:inset(0);opacity:1}}@keyframes oc-enter-point{0%{opacity:0;transform:scale(.3)}to{opacity:1;transform:scale(1)}}@keyframes oc-enter-map-fill{0%{fill:var(--oc-secondary);opacity:0}to{fill:var(--oc-feature-fill);opacity:var(--oc-feature-target-opacity,1)}}@keyframes oc-enter-map-point{0%{opacity:0;transform:scale(.75)}to{opacity:1;transform:scale(1)}}@keyframes oc-enter-fade-only{0%{opacity:0}to{opacity:1}}@keyframes oc-enter-fade{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}@keyframes oc-table-enter-row{0%{transform:translateY(6px)}to{transform:translateY(0)}}@keyframes oc-table-enter-bar-fill{0%{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0)}}@keyframes oc-pulse{0%{r:var(--oc-pulse-r,4px);fill-opacity:1}45%{r:calc(var(--oc-pulse-r,4px) * 1.8);fill-opacity:.5}to{r:var(--oc-pulse-r,4px);fill-opacity:1}}@keyframes oc-tooltip-in{0%{opacity:0;transform:translateY(2px)}to{opacity:1;transform:translateY(0)}}.oc-animate .oc-mark-rect :is(rect,path){animation:oc-enter-bar var(--oc-animation-duration) var(--oc-ease-smooth) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-bar :is(rect,path){animation:oc-enter-bar var(--oc-animation-duration) var(--oc-ease-smooth) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-rect[data-orient=horizontal] :is(rect,path){animation-name:oc-enter-bar-h}.oc-animate .oc-mark-bar[data-orient=horizontal] :is(rect,path){animation-name:oc-enter-bar-h}.oc-animate .oc-mark-rect[data-stack-pos] :is(rect,path){animation-duration:var(--oc-stack-segment-duration,.15s);animation-timing-function:linear;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0) + var(--oc-stack-pos,0) * var(--oc-stack-segment-duration,.15s))}.oc-animate .oc-mark-line{animation:oc-enter-line var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-area{animation:oc-enter-line var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-arc{animation:oc-enter-fade-only var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate circle.oc-mark-point{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .4) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate circle.oc-mark-circle{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .4) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-line~circle.oc-mark-point{animation-delay:calc(var(--oc-animation-duration) * .35 + var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-area~circle.oc-mark-point{animation-delay:calc(var(--oc-animation-duration) * .35 + var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-text text{animation:oc-enter-fade calc(var(--oc-animation-duration) * .6) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-rule line{animation:oc-enter-fade calc(var(--oc-animation-duration) * .5) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-tick line{animation:oc-enter-fade calc(var(--oc-animation-duration) * .5) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-label{animation:oc-enter-fade .25s var(--oc-ease-smooth) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0) + var(--oc-animation-duration) * .7)}.oc-animate .oc-annotation{animation:oc-enter-fade .3s var(--oc-ease-smooth) both;animation-delay:calc(var(--oc-animation-duration) + var(--oc-annotation-delay,.15s))}.oc-animate .oc-tilemap-tile{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .35) ease-in both;animation-delay:var(--oc-tile-delay,0s)}.oc-animate .oc-map-feature{animation:oc-enter-map-fill var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:var(--oc-map-delay,0s)}.oc-animate .oc-map-features[data-bulk-animate]{animation:oc-enter-fade-only var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both}.oc-animate .oc-map-features[data-bulk-animate] .oc-map-feature{animation:none}.oc-animate .oc-map-borders path{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .4) ease-in both;animation-delay:calc(var(--oc-animation-duration) * .7)}.oc-animate .oc-map-point{animation:oc-enter-map-point calc(var(--oc-animation-duration) * .4) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-duration) * .8 + var(--oc-mark-index,0) * var(--oc-point-stagger,60ms))}.oc-animate .oc-sankey-node rect{animation:oc-enter-fade-only var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-sankey-link path{animation:oc-enter-fade-only var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-duration) * .3 + var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-barlist-row{animation:oc-enter-fade calc(var(--oc-animation-duration) * .6) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:var(--oc-row-delay,0s)}.oc-animate .oc-barlist-bar{animation:oc-enter-bar-h var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:var(--oc-row-delay,0s)}.oc-animate[data-display=sparkline] .oc-mark-line,.oc-animate[data-display=sparkline] .oc-mark-area{animation-timing-function:cubic-bezier(.16,1,.3,1)}}@layer oc.reduced-motion{@media (prefers-reduced-motion:reduce){:is(.oc-root,.oc-chart-root,.oc-table-wrapper,.oc-table-root,.oc-graph-wrapper,.oc-graph-root,.oc-sankey-root,.oc-tilemap-root,.oc-barlist-root,.oc-map-root){transition:none;animation:none}:is(.oc-root,.oc-chart-root,.oc-table-wrapper,.oc-table-root,.oc-graph-wrapper,.oc-graph-root,.oc-sankey-root,.oc-tilemap-root,.oc-barlist-root,.oc-map-root) *{transition:none;animation:none}:is(.oc-root,.oc-chart-root,.oc-table-wrapper,.oc-table-root,.oc-graph-wrapper,.oc-graph-root,.oc-sankey-root,.oc-tilemap-root,.oc-barlist-root,.oc-map-root) :before{transition:none;animation:none}:is(.oc-root,.oc-chart-root,.oc-table-wrapper,.oc-table-root,.oc-graph-wrapper,.oc-graph-root,.oc-sankey-root,.oc-tilemap-root,.oc-barlist-root,.oc-map-root) :after{transition:none;animation:none}}}
|
|
1
|
+
@layer oc.tokens{.oc-root,.oc-chart-root,.oc-table-wrapper,.oc-table-root,.oc-graph-wrapper,.oc-graph-root,.oc-sankey-root,.oc-tilemap-root,.oc-barlist-root,.oc-map-root{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;--oc-font-family:"Inter Variable", Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;--oc-font-mono:"JetBrains Mono", "Fira Code", "Cascadia Code", monospace;--oc-ease-smooth:linear(0, .157, .438, .64, .766, .85, .906, .941, .964, .978, .988, .994, .998, 1);--oc-ease-snappy:linear(0, .012, .048, .108, .194, .302, .426, .559, .69, .808, .905, .973, 1.013, 1.028, 1.023, 1.006, .984, .966, .957, .957, .964, .975, .986, .995, 1, 1.003, 1.002, 1, .998, .998, .999, 1);--oc-animation-duration:.45s;--oc-animation-stagger:30ms;--oc-annotation-delay:.15s;--oc-title-size:26px;--oc-title-weight:600;--oc-title-tracking:-.022em;--oc-subtitle-size:14px;--oc-subtitle-weight:400;--oc-source-size:11px;--oc-source-weight:400;--oc-body-size:13px;--oc-eyebrow-size:11px;--oc-eyebrow-weight:500;--oc-eyebrow-tracking:.08em;--oc-bg:#fff;--oc-card:#fff;--oc-secondary:#f4f4f5;--oc-text:#09090b;--oc-text-secondary:#3f3f46;--oc-text-muted:#71717a;--oc-text-faint:#d4d4d8;--oc-gray-100:#f0f0f0;--oc-gray-200:#e1e1e2;--oc-gray-300:#c9c9c9;--oc-gray-400:#9d9d9d;--oc-gray-600:#787879;--oc-gray-800:#474748;--oc-gridline:rgba(0,0,0,.08);--oc-axis:rgba(0,0,0,.14);--oc-border:rgba(0,0,0,.08);--oc-border-radius:8px;--oc-radius-sm:2px;--oc-radius-md:6px;--oc-radius-lg:var(--oc-border-radius);--oc-radius-full:999px;--oc-accent:#06b6d4;--oc-accent-strong:#0891b2;--oc-positive:#15803d;--oc-negative:#dc2626;--oc-positive-tint:color-mix(in srgb, var(--oc-positive) 10%, var(--oc-bg));--oc-negative-tint:color-mix(in srgb, var(--oc-negative) 10%, var(--oc-bg));--oc-focus:#3b82f6;--oc-focus-ring:rgba(59,130,246,.1);--oc-focus-ring-strong:rgba(59,130,246,.25);--oc-editable-hover:rgba(79,70,229,.35);--oc-space-2:8px;--oc-space-4:16px;--oc-hover-dim:.3;--oc-hover-duration:.14s;--oc-map-hover-dim:.75;--oc-hover-bg:rgba(0,0,0,.024);--oc-tooltip-bg:rgba(255,255,255,.88);--oc-tooltip-border:rgba(0,0,0,.08);--oc-tooltip-shadow:0 2px 8px rgba(0,0,0,.08), 0 0 1px rgba(0,0,0,.12);--oc-tooltip-text:#09090b;--oc-legend-text:#3f3f46}.oc-dark{--oc-bg:#09090b;--oc-card:#111113;--oc-secondary:#27272a;--oc-text:#f7f8f8;--oc-text-secondary:#d0d6e0;--oc-text-muted:#a1a1aa;--oc-text-faint:#52525b;--oc-gridline:rgba(255,255,255,.06);--oc-axis:rgba(255,255,255,.14);--oc-border:rgba(255,255,255,.1);--oc-accent:#06b6d4;--oc-accent-strong:#06b6d4;--oc-positive:#4ade80;--oc-negative:#f87171;--oc-focus:#60a5fa;--oc-hover-bg:rgba(255,255,255,.05);--oc-tooltip-bg:rgba(17,17,19,.92);--oc-tooltip-border:rgba(255,255,255,.08);--oc-tooltip-shadow:0 2px 8px rgba(0,0,0,.3), 0 0 1px rgba(0,0,0,.4);--oc-tooltip-text:#f7f8f8;--oc-legend-text:#d0d6e0}}@layer oc.base{.oc-chart-root,.oc-table-root,.oc-graph-root,.oc-sankey-root,.oc-barlist-root,.oc-tilemap-root,.oc-map-root{width:100%;height:100%}.oc-table-root{overflow:auto}.oc-chart{font-family:var(--oc-font-family);font-variant-numeric:tabular-nums;width:100%;display:block}.oc-tilemap,.oc-map{width:100%;height:auto;display:block}.oc-map-feature{transition:opacity var(--oc-hover-duration) ease-out, stroke-width .14s ease-out}.oc-barlist{width:100%;display:block}.oc-sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:clip}.oc-editable-hover{outline:1.5px solid var(--oc-editable-hover);outline-offset:2px;border-radius:var(--oc-radius-sm)}.oc-root:focus-visible{outline:2px solid var(--oc-focus);outline-offset:2px}.oc-mark-focused{outline:2px solid var(--oc-focus);outline-offset:1px;border-radius:var(--oc-radius-sm)}}@layer oc.components{.oc-chrome{font-family:var(--oc-font-family)}.oc-eyebrow{font-size:var(--oc-eyebrow-size);font-weight:var(--oc-eyebrow-weight);letter-spacing:var(--oc-eyebrow-tracking);text-transform:uppercase;fill:var(--oc-accent)}.oc-title{font-size:var(--oc-title-size);font-weight:var(--oc-title-weight);letter-spacing:var(--oc-title-tracking);fill:var(--oc-text)}.oc-subtitle{font-size:var(--oc-subtitle-size);font-weight:var(--oc-subtitle-weight);fill:var(--oc-text-muted)}.oc-source,.oc-byline,.oc-footer{font-size:var(--oc-source-size);font-weight:var(--oc-source-weight);fill:var(--oc-text-muted)}.oc-brand{letter-spacing:.02em;fill:var(--oc-text-faint);font-size:11px;font-weight:500}.oc-eyebrow-dot{fill:var(--oc-accent)}.oc-metrics{font-family:var(--oc-font-family)}.oc-metric-label{letter-spacing:.06em;text-transform:uppercase;fill:var(--oc-text-muted);font-size:11px;font-weight:500}.oc-metric-value{letter-spacing:-.02em;fill:var(--oc-text);font-variant-numeric:tabular-nums;font-size:22px;font-weight:600}.oc-metric-delta-up{fill:var(--oc-positive);font-size:12px;font-weight:500}.oc-metric-delta-down{fill:var(--oc-negative);font-size:12px;font-weight:500}.oc-metric-secondary{fill:var(--oc-text-muted);font-size:12px;font-weight:400}.oc-axis-tick-inline{fill:var(--oc-text-muted);font-size:11px;font-weight:400}.oc-endpoint-labels{font-family:var(--oc-font-family)}.oc-endpoint-label{fill:var(--oc-endpoint-label-color,var(--oc-text))}.oc-endpoint-value{fill:var(--oc-endpoint-value-color,var(--oc-text-muted))}.oc-endpoint-leader{stroke:var(--oc-endpoint-leader-color,currentColor)}.oc-annotation-subtitle{fill:var(--oc-annotation-subtitle-color,var(--oc-text-muted))}.oc-table-footer-row{align-items:baseline;gap:16px;padding:16px 16px 4px;display:flex}.oc-chrome-footer{padding-top:0}.oc-table-footer-row .oc-table-ref{text-align:right;flex-shrink:0;margin-left:auto}.oc-tooltip{pointer-events:none;z-index:1000;background:var(--oc-tooltip-bg);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);border:1px solid var(--oc-tooltip-border);border-radius:var(--oc-radius-lg);box-shadow:var(--oc-tooltip-shadow);color:var(--oc-tooltip-text);font-family:var(--oc-font-family);min-width:140px;max-width:280px;padding:0;font-size:12px;line-height:1.4;transition:left .1s ease-in-out,top .1s ease-in-out;animation:.12s ease-out oc-tooltip-in;display:none;position:absolute}.oc-tooltip .oc-tooltip-header{align-items:center;gap:8px;padding:8px 10px 6px;display:flex}.oc-tooltip .oc-tooltip-dot{border-radius:50%;flex-shrink:0;width:8px;height:8px}.oc-tooltip .oc-tooltip-title{letter-spacing:.04em;text-transform:uppercase;color:var(--oc-text-muted);white-space:nowrap;text-overflow:ellipsis;font-size:11px;font-weight:600;overflow:hidden}.oc-tooltip .oc-tooltip-body{border-top:1px solid var(--oc-tooltip-border);padding:6px 10px 8px}.oc-tooltip .oc-tooltip-body:first-child{border-top:none;padding-top:10px}.oc-tooltip .oc-tooltip-row{justify-content:space-between;align-items:baseline;gap:16px;padding:2px 0;display:flex}.oc-tooltip .oc-tooltip-row-swatch{border-radius:50%;flex-shrink:0;width:8px;height:8px;margin-right:6px;display:inline-block;transform:translateY(-1px)}.oc-tooltip .oc-tooltip-label{color:var(--oc-text-secondary);white-space:nowrap;flex-shrink:0;align-items:center;font-size:12px;font-weight:400;display:inline-flex}.oc-tooltip .oc-tooltip-value{font-variant-numeric:tabular-nums;color:var(--oc-tooltip-text);text-align:right;text-overflow:ellipsis;white-space:nowrap;font-size:12px;font-weight:500;overflow:hidden}.oc-tooltip .oc-tooltip-row--emphasis .oc-tooltip-label{color:var(--oc-tooltip-text);font-weight:600}.oc-tooltip .oc-tooltip-row--emphasis .oc-tooltip-value{font-weight:600}.oc-tooltip .oc-tooltip-row--total{border-top:1px solid var(--oc-tooltip-border);margin-top:4px;padding-top:5px}.oc-tooltip .oc-tooltip-row--total .oc-tooltip-label{color:var(--oc-tooltip-text);font-weight:500}.oc-tooltip .oc-tooltip-row--total .oc-tooltip-value{font-weight:600}.oc-crosshair{pointer-events:none;transition:x1 50ms ease-in-out,x2 50ms ease-in-out}.oc-snap-dots circle{pointer-events:none;transition:cx 50ms ease-in-out,cy 50ms ease-in-out}.oc-legend{font-family:var(--oc-font-family)}.oc-legend-entry{cursor:default}.oc-marks.oc-hover-active .oc-mark--dim:not([opacity="0"]){opacity:var(--oc-hover-dim)}.oc-marks.oc-hover-active .oc-mark-rect.oc-mark--hover>*,.oc-marks.oc-hover-active .oc-mark-arc.oc-mark--hover>*,.oc-marks.oc-hover-active circle.oc-mark-point.oc-mark--hover{stroke:var(--oc-text);stroke-width:1px}.oc-chart:not(.oc-animate):not(.oc-transitioning) .oc-marks .oc-mark{transition:opacity var(--oc-hover-duration) ease-out}.oc-legend-entry--dim .oc-legend-swatch-line,.oc-legend-entry--dim .oc-legend-swatch-rect,.oc-legend-entry--dim>circle{opacity:var(--oc-hover-dim);transition:opacity var(--oc-hover-duration) ease-out}.oc-legend-hit{fill:transparent}.oc-legend-entry:focus{outline:none}.oc-legend-entry:focus-visible .oc-legend-hit{stroke:var(--oc-focus);stroke-width:2px}.oc-endpoint-label-entry{cursor:default}.oc-map-feature--hover{stroke:var(--oc-text);stroke-width:1.5px;vector-effect:non-scaling-stroke}.oc-map-features[data-hover] .oc-map-feature{transition:opacity var(--oc-hover-duration) ease-out}.oc-map-features[data-hover="0"] .oc-map-feature:not([data-bin-index="0"]),.oc-map-features[data-hover="1"] .oc-map-feature:not([data-bin-index="1"]),.oc-map-features[data-hover="2"] .oc-map-feature:not([data-bin-index="2"]),.oc-map-features[data-hover="3"] .oc-map-feature:not([data-bin-index="3"]),.oc-map-features[data-hover="4"] .oc-map-feature:not([data-bin-index="4"]),.oc-map-features[data-hover="5"] .oc-map-feature:not([data-bin-index="5"]),.oc-map-features[data-hover="6"] .oc-map-feature:not([data-bin-index="6"]),.oc-map-features[data-hover="7"] .oc-map-feature:not([data-bin-index="7"]),.oc-map-features[data-hover="8"] .oc-map-feature:not([data-bin-index="8"]),.oc-map-features[data-hover="9"] .oc-map-feature:not([data-bin-index="9"]),.oc-map-features[data-hover="10"] .oc-map-feature:not([data-bin-index="10"]),.oc-map-features[data-hover="11"] .oc-map-feature:not([data-bin-index="11"]){opacity:var(--oc-map-hover-dim)}.oc-legend-bin{cursor:default}.oc-tilemap-tiles.oc-hover-active .oc-tilemap-tile{transition:opacity var(--oc-hover-duration) ease-out}.oc-tilemap-tiles.oc-hover-active .oc-tilemap-tile:not(.oc-tilemap-tile--hover){opacity:var(--oc-hover-dim)}.oc-tilemap-tile--hover>rect{stroke:var(--oc-text);stroke-width:1.5px}.oc-series-search{font-family:var(--oc-font-family);z-index:10;justify-content:flex-end;align-items:center;gap:8px;display:flex;position:absolute}.oc-series-search-chips{scrollbar-width:none;align-items:center;gap:6px;min-width:0;display:flex;overflow-x:auto}.oc-series-search-chips::-webkit-scrollbar{display:none}.oc-series-search-chip{border:1px solid var(--oc-border);border-radius:var(--oc-radius-full);background:var(--oc-secondary);color:var(--oc-text-secondary);white-space:nowrap;align-items:center;gap:4px;padding:3px 4px 3px 10px;font-size:12px;font-weight:500;line-height:16px;display:inline-flex}.oc-series-search-chip-remove{width:16px;height:16px;color:var(--oc-text-muted);cursor:pointer;background:0 0;border:none;border-radius:50%;justify-content:center;align-items:center;margin:-4px -2px -4px -4px;padding:4px;transition:color .15s,background-color .15s;display:inline-flex}.oc-series-search-chip-remove:hover{color:var(--oc-text);background:var(--oc-hover-bg)}.oc-series-search-chip-remove:focus-visible{outline:2px solid var(--oc-focus);outline-offset:1px}.oc-series-search-chip-remove svg{display:block}.oc-series-search-box{flex:0 220px;min-width:120px;position:relative}.oc-series-search-icon{color:var(--oc-text-muted);pointer-events:none;position:absolute;top:50%;left:9px;transform:translateY(-50%)}.oc-series-search-input{height:32px;padding:0 10px 0 28px}.oc-series-search-listbox{border:1px solid var(--oc-border);border-radius:var(--oc-radius-lg);background:var(--oc-card);min-width:100%;max-height:240px;box-shadow:var(--oc-tooltip-shadow);z-index:20;margin:0;padding:4px;list-style:none;position:absolute;top:calc(100% + 4px);right:0;overflow-y:auto}.oc-series-search-option{border-radius:var(--oc-radius-sm);color:var(--oc-text);cursor:pointer;white-space:nowrap;text-overflow:ellipsis;padding:6px 10px;font-size:13px;overflow:hidden}.oc-series-search-option[aria-selected=true],.oc-series-search-option:hover{background:var(--oc-hover-bg)}.oc-series-search-match{font-weight:600}.oc-series-search-empty{color:var(--oc-text-muted);padding:6px 10px;font-size:12px}.oc-ydi-region{opacity:.35;transition:opacity .4s}.oc-ydi-region[data-ydi-hidden=true]{opacity:0}.oc-ydi-boundary{stroke:var(--oc-text-muted);stroke-width:1px;stroke-dasharray:3 3;stroke-opacity:.6}.oc-ydi-guess{stroke:var(--oc-focus);stroke-width:2.5px;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:1 6}.oc-ydi-comparison{stroke:var(--oc-text-muted);stroke-width:1.5px;stroke-opacity:.5;stroke-dasharray:4 4}.oc-ydi-clip-rect.oc-ydi-clip-animate{transition:width .7s cubic-bezier(.22,1,.36,1)}.oc-ydi-controls{pointer-events:none;font-family:var(--oc-font-family);box-sizing:border-box;z-index:10;flex-direction:column;justify-content:space-between;align-items:flex-end;padding:8px;display:flex}.oc-ydi-prompt{border-radius:var(--oc-radius-md);background:var(--oc-card);border:1px solid var(--oc-border);max-width:100%;color:var(--oc-text-secondary);text-align:center;box-shadow:var(--oc-tooltip-shadow);align-self:center;padding:6px 12px;font-size:13px;font-weight:500;line-height:16px}.oc-ydi-controls.oc-ydi-revealed .oc-ydi-prompt{display:none}.oc-ydi-actions{pointer-events:none;flex-wrap:wrap;justify-content:flex-end;gap:8px;display:flex}.oc-ydi-reveal-button,.oc-ydi-reset-button{pointer-events:auto;border:1px solid var(--oc-border);border-radius:var(--oc-radius-md);background:var(--oc-bg);color:var(--oc-text);white-space:nowrap;cursor:pointer;box-shadow:var(--oc-tooltip-shadow);justify-content:center;align-items:center;padding:6px 14px;font-family:inherit;font-size:13px;font-weight:500;transition:background-color .15s,border-color .15s;display:inline-flex}.oc-ydi-reset-button[hidden]{display:none}.oc-ydi-reveal-button:hover,.oc-ydi-reset-button:hover{background:var(--oc-hover-bg)}.oc-ydi-reveal-button:focus-visible{outline:2px solid var(--oc-focus);outline-offset:2px}.oc-ydi-reset-button:focus-visible{outline:2px solid var(--oc-focus);outline-offset:2px}.oc-ydi-reveal-button:disabled{opacity:.5;cursor:default}.oc-table-wrapper{font-family:var(--oc-font-family);color:var(--oc-text);background:var(--oc-bg)}.oc-table-wrapper>.oc-chrome{margin-bottom:16px;padding-left:16px;padding-right:16px}.oc-table-wrapper>.oc-chrome:first-child{padding-top:4px}.oc-table-wrapper table{border-collapse:collapse;width:100%}.oc-table-wrapper th{text-align:left;border-bottom:1px solid var(--oc-border);box-sizing:border-box;padding:12px 16px;line-height:24px}.oc-table-wrapper td{text-align:left;border-bottom:1px solid var(--oc-border);box-sizing:border-box;padding:12px 16px;line-height:24px}.oc-table-wrapper th{text-transform:uppercase;letter-spacing:.04em;color:var(--oc-text-muted);font-variant-numeric:tabular-nums;white-space:nowrap;font-size:12px;font-weight:500}.oc-table-wrapper thead{z-index:2;background:var(--oc-bg);position:sticky;top:0}.oc-table-wrapper thead th{border-bottom-width:1px}.oc-table-wrapper td{font-variant-numeric:tabular-nums;font-size:14px}.oc-table-wrapper th:focus{outline:2px solid var(--oc-focus);outline-offset:-2px}.oc-table-wrapper tbody:focus{outline:none}.oc-table-title{font-size:var(--oc-title-computed-size,var(--oc-title-size));font-weight:var(--oc-title-computed-weight,var(--oc-title-weight));color:var(--oc-title-computed-color,var(--oc-text));margin-bottom:4px}.oc-table-subtitle{font-size:var(--oc-subtitle-computed-size,var(--oc-subtitle-size));font-weight:var(--oc-subtitle-computed-weight,var(--oc-subtitle-weight));color:var(--oc-subtitle-computed-color,var(--oc-text-secondary));margin-bottom:8px}.oc-table-source{font-size:var(--oc-source-computed-size,var(--oc-source-size));color:var(--oc-source-computed-color,var(--oc-text-muted))}.oc-table-footer-text{font-size:var(--oc-footer-computed-size,var(--oc-source-size));color:var(--oc-footer-computed-color,var(--oc-text-muted))}.oc-table-scroll{overflow-x:auto}.oc-table--sticky th:first-child{z-index:1;background:var(--oc-bg);position:sticky;left:0}.oc-table--sticky td:first-child{z-index:1;background:var(--oc-bg);position:sticky;left:0}.oc-table-sort-btn{cursor:pointer;vertical-align:middle;background:0 0;border:none;flex-direction:column;align-items:center;gap:2px;margin-left:6px;padding:2px;display:inline-flex}.oc-table-sort-btn:before{content:"";border-left:5px solid transparent;border-right:5px solid transparent;width:0;height:0;transition:opacity .15s,border-color .15s;display:block}.oc-table-sort-btn:after{content:"";border-left:5px solid transparent;border-right:5px solid transparent;width:0;height:0;transition:opacity .15s,border-color .15s;display:block}.oc-table-sort-btn:before{border-bottom:4.5px solid var(--oc-text-secondary);opacity:.35}.oc-table-sort-btn:after{border-top:4.5px solid var(--oc-text-secondary);opacity:.35}.oc-table-sort-btn:hover:before{opacity:.75}.oc-table-sort-btn:hover:after{opacity:.75}th[aria-sort=ascending] .oc-table-sort-btn:before{opacity:1;border-bottom-color:var(--oc-text)}th[aria-sort=ascending] .oc-table-sort-btn:after{opacity:.15}th[aria-sort=descending] .oc-table-sort-btn:after{opacity:1;border-top-color:var(--oc-text)}th[aria-sort=descending] .oc-table-sort-btn:before{opacity:.15}.oc-table-search input,.oc-series-search-input{border:1px solid var(--oc-border);border-radius:var(--oc-radius-md);background:var(--oc-bg);width:100%;color:var(--oc-text);box-sizing:border-box;font-family:inherit;font-size:13px;transition:border-color .15s}.oc-table-search input::-ms-input-placeholder{color:var(--oc-text-muted);font-size:13px}.oc-table-search input::placeholder{color:var(--oc-text-muted);font-size:13px}.oc-series-search-input::-ms-input-placeholder{color:var(--oc-text-muted);font-size:13px}.oc-series-search-input::placeholder{color:var(--oc-text-muted);font-size:13px}.oc-table-search input:focus,.oc-series-search-input:focus{border-color:var(--oc-focus);box-shadow:0 0 0 3px var(--oc-focus-ring);outline:none}.oc-table-search{padding:8px 0}.oc-table-search input{padding:8px 12px}.oc-table-pagination{color:var(--oc-text-secondary);justify-content:space-between;align-items:center;padding:12px 0 4px;font-size:13px;display:flex}.oc-table-pagination button{border:1px solid var(--oc-border);border-radius:var(--oc-radius-md);background:var(--oc-bg);color:var(--oc-text);cursor:pointer;padding:6px 14px;font-family:inherit;font-size:13px;transition:background .15s,border-color .15s}.oc-table-pagination button:disabled{opacity:.35;cursor:not-allowed}.oc-table-pagination button:hover:not(:disabled){background:var(--oc-hover-bg);border-color:var(--oc-axis)}.oc-table-pagination button:focus-visible{outline:2px solid var(--oc-focus);outline-offset:1px}.oc-table-pagination-info{font-variant-numeric:tabular-nums}.oc-table-pagination-btns{gap:8px;display:flex}.oc-table-bar{position:relative}.oc-table-bar-fill{border-radius:var(--oc-radius-sm);opacity:.18;pointer-events:none;position:absolute;top:8px;bottom:8px;left:0}.oc-table-bar-value{z-index:1;position:relative}.oc-table-sparkline{width:100%;display:block;position:relative}.oc-table-sparkline svg{width:100%;display:block;overflow:visible}.oc-table-sparkline-dot{border-radius:50%;width:5px;height:5px;position:absolute}.oc-table-sparkline-labels{justify-content:space-between;font-size:11px;line-height:1;display:flex}.oc-table-image{vertical-align:middle;display:inline-block}.oc-table-image img{object-fit:cover}.oc-table-image-rounded img{border-radius:50%}.oc-table-flag{font-size:1.2em}:is(.oc-table--condensed,.oc-table--compact) th{padding:8px 12px;font-size:13px;line-height:24px}:is(.oc-table--condensed,.oc-table--compact) td{padding:8px 12px;font-size:13px;line-height:24px}:is(.oc-table--condensed,.oc-table--compact) th{font-size:11px}:is(.oc-table--condensed,.oc-table--compact) .oc-table-bar-fill{top:5px;bottom:5px}.oc-table--relaxed th{padding:16px 20px;line-height:24px}.oc-table--relaxed td{padding:16px 20px;line-height:24px}.oc-table--relaxed .oc-table-bar-fill{top:12px;bottom:12px}.oc-table--striped tbody tr:nth-child(2n){background:color-mix(in srgb, var(--oc-text) 3%, transparent)}.oc-table-delta{border-radius:var(--oc-radius-md);font-variant-numeric:tabular-nums;align-items:baseline;gap:4px;padding:2px 8px;font-weight:500;line-height:16px;display:inline-flex}.oc-table-delta-arrow{font-size:.8em;line-height:1}.oc-table-delta--positive{color:var(--oc-positive);background:var(--oc-positive-tint)}.oc-table-delta--negative{color:var(--oc-negative);background:var(--oc-negative-tint)}.oc-table-delta--neutral{color:var(--oc-text-muted);background:color-mix(in srgb, var(--oc-text) 6%, transparent)}.oc-table-chip{border-radius:var(--oc-radius-full);white-space:nowrap;align-items:center;gap:6px;padding:2px 8px;font-size:12px;font-weight:500;line-height:16px;display:inline-flex}.oc-table-chip-dot{border-radius:50%;flex:none;width:6px;height:6px}tfoot.oc-table-total{z-index:2;background:var(--oc-bg);position:sticky;bottom:0}tfoot.oc-table-total td{border-bottom:none;border-top:1px solid var(--oc-border);font-weight:600}.oc-table--cards .oc-table-scroll{overflow-x:hidden}.oc-table--cards table{table-layout:fixed}.oc-table--cards thead{clip-path:inset(50%);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}.oc-table--cards tbody tr{border-bottom:1px solid var(--oc-border);grid-template-columns:repeat(2,minmax(0,1fr));align-items:baseline;gap:2px 12px;padding:10px 12px;display:grid}.oc-table--cards tfoot tr{border-bottom:1px solid var(--oc-border);grid-template-columns:repeat(2,minmax(0,1fr));align-items:baseline;gap:2px 12px;padding:10px 12px;display:grid}.oc-table--cards td{overflow-wrap:anywhere;text-align:right;border-bottom:none;width:auto;max-width:100%;padding:0;display:block}.oc-table--cards td:before{content:attr(data-label);letter-spacing:.04em;text-transform:uppercase;color:var(--oc-text-muted);text-align:left;font-size:11px;font-weight:500;display:block}.oc-table--cards td[data-label=""]:before{content:none}.oc-table--cards td[data-priority="1"]{text-align:left;grid-column:1/-1;font-size:15px;font-weight:600}.oc-table--cards td[data-priority="1"]:before{content:none}.oc-table--cards td[data-priority="3"]{display:none}.oc-table--cards .oc-table-sparkline{width:100%}.oc-table--clickable tbody tr{cursor:pointer}.oc-table--clickable tbody tr:hover{background:var(--oc-hover-bg)}.oc-table-cell-focus{outline:2px solid var(--oc-focus);outline-offset:-2px}.oc-table-empty{text-align:center;color:var(--oc-text-secondary);padding:32px 16px;font-size:14px;font-style:italic}.oc-table--priority table{table-layout:auto;width:100%}.oc-table--priority [hidden]{display:none}.oc-table--priority th{padding-left:8px;padding-right:8px;width:auto!important}.oc-table--priority td{padding-left:8px;padding-right:8px;width:auto!important}.oc-table--priority th{white-space:normal;min-height:44px;padding-right:20px;position:relative}.oc-table--priority .oc-table-sort-btn{justify-content:center;align-items:flex-end;width:100%;height:100%;margin:0;padding-right:4px;position:absolute;top:0;bottom:0;left:0;right:0}.oc-table--priority .oc-table-details{white-space:normal}.oc-table--priority summary{cursor:pointer;align-items:center;min-height:44px;font-size:12px;display:flex}.oc-table--priority details[open]{min-width:110px}.oc-table--priority dl{margin:4px 0 12px;font-size:12px}.oc-table--priority dt{color:var(--oc-text-secondary);margin-top:8px}.oc-table--priority dd{margin:4px 0 0}.oc-graph-wrapper{background:var(--oc-bg);font-family:var(--oc-font-family);width:100%;height:100%;position:relative;overflow:hidden}.oc-graph-canvas{cursor:grab;width:100%;height:100%;display:block}.oc-graph-canvas--dragging{cursor:grabbing}.oc-graph-3d,.oc-graph-3d .scene-container{width:100%;height:100%;display:block}.oc-graph-3d{cursor:grab}.oc-graph-3d .scene-container canvas{width:100%;height:100%;display:block}.oc-graph-chrome{z-index:2;pointer-events:none;padding:16px 16px 8px;position:absolute;top:0;left:0;right:0}.oc-graph-chrome .oc-title{font-size:var(--oc-title-size);font-weight:var(--oc-title-weight);letter-spacing:var(--oc-title-tracking);color:var(--oc-text);--_stroke:color-mix(in srgb, var(--oc-bg) 80%, transparent);text-shadow:-2px -2px 0 var(--_stroke), 2px -2px 0 var(--_stroke), -2px 2px 0 var(--_stroke), 2px 2px 0 var(--_stroke), 0 -2px 0 var(--_stroke), 0 2px 0 var(--_stroke), -2px 0 0 var(--_stroke), 2px 0 0 var(--_stroke);margin:0 0 4px}.oc-graph-chrome .oc-subtitle{font-size:var(--oc-subtitle-size);color:var(--oc-text-secondary);--_stroke:color-mix(in srgb, var(--oc-bg) 80%, transparent);text-shadow:-1px -1px 0 var(--_stroke), 1px -1px 0 var(--_stroke), -1px 1px 0 var(--_stroke), 1px 1px 0 var(--_stroke);margin:0}.oc-graph-legend{background:color-mix(in srgb, var(--oc-bg) 88%, transparent);border:1px solid var(--oc-border);border-radius:var(--oc-radius-lg);color:var(--oc-text-secondary);max-height:200px;padding:8px 12px;font-size:12px;position:absolute;top:12px;right:12px;overflow-y:auto}.oc-graph-legend-item{width:100%;font:inherit;color:inherit;text-align:left;cursor:default;background:0 0;border:none;align-items:center;gap:6px;margin:0;padding:2px 0;display:flex}button.oc-graph-legend-item{cursor:pointer;border-radius:var(--oc-radius-sm)}button.oc-graph-legend-item:hover{background:var(--oc-focus-ring)}button.oc-graph-legend-item:focus-visible{outline:2px solid var(--oc-focus);outline-offset:1px}.oc-graph-legend-item--inactive{opacity:.45}.oc-graph-legend-label{flex:auto}.oc-graph-legend-count{color:var(--oc-text-secondary);font-variant-numeric:tabular-nums;margin-left:auto;padding-left:8px}.oc-graph-legend-swatch{border-radius:50%;flex-shrink:0;width:10px;height:10px}.oc-graph-legend-swatch--line{border-radius:1px;width:12px;height:3px}.oc-graph-search{position:absolute;top:12px;left:12px}.oc-graph-search input{font-family:var(--oc-font-family);font-size:var(--oc-body-size);border:1px solid var(--oc-border);border-radius:var(--oc-radius-md);background:color-mix(in srgb, var(--oc-bg) 88%, transparent);color:var(--oc-text);outline:none;padding:6px 10px}.oc-graph-search input:focus{border-color:var(--oc-focus);box-shadow:0 0 0 2px var(--oc-focus-ring-strong)}.oc-sankey:not(.oc-animate) .oc-sankey-link path{transition:fill-opacity var(--oc-hover-duration) ease-out}.oc-sankey:not(.oc-animate) .oc-sankey-node,.oc-sankey:not(.oc-animate) .oc-sankey-label{transition:opacity var(--oc-hover-duration) ease-out}.oc-sankey-label{pointer-events:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}.oc-map-zoom{pointer-events:none;z-index:2;position:absolute}.oc-map-zoom-controls{pointer-events:auto;background:var(--oc-tooltip-bg);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);border:1px solid var(--oc-tooltip-border);border-radius:var(--oc-radius-md);box-shadow:var(--oc-tooltip-shadow);flex-direction:column;display:flex;position:absolute;top:8px;right:8px;overflow:hidden}.oc-map-zoom-btn{width:28px;height:28px;color:var(--oc-text);font:inherit;cursor:pointer;transition:background var(--oc-hover-duration) ease-out, opacity var(--oc-hover-duration) ease-out;background:0 0;border:none;justify-content:center;align-items:center;margin:0;padding:0;display:flex}.oc-map-zoom-btn+.oc-map-zoom-btn{border-top:1px solid var(--oc-tooltip-border)}.oc-map-zoom-btn:hover:not(:disabled){background:var(--oc-focus-ring)}.oc-map-zoom-btn:focus-visible{outline:2px solid var(--oc-focus);outline-offset:-2px}.oc-map-zoom-btn:disabled{cursor:default;opacity:.35}.oc-map-zoom-hint{background:var(--oc-tooltip-bg);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);border:1px solid var(--oc-tooltip-border);border-radius:var(--oc-radius-md);max-width:calc(100% - 32px);box-shadow:var(--oc-tooltip-shadow);color:var(--oc-tooltip-text);font-family:var(--oc-font-family);text-align:center;opacity:0;padding:8px 12px;font-size:13px;line-height:1.3;transition:opacity .2s ease-out;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.oc-map-zoom-hint[data-visible]{opacity:1}.oc-map:focus{outline:none}.oc-map:focus-visible{outline:2px solid var(--oc-focus);outline-offset:2px}.oc-map[data-oc-zoomed]{cursor:grab}.oc-map--panning{cursor:grabbing}.oc-chart[data-display=sparkline]{margin:0;padding:0;display:block}.oc-chart[data-display=sparkline] .oc-pulse{animation:.6s ease-out oc-pulse}@media (prefers-reduced-motion:reduce){.oc-chart[data-display=sparkline] .oc-pulse{animation:none}}}@layer oc.animation{.oc-table-wrapper.oc-animate>.oc-chrome{animation:oc-enter-fade calc(var(--oc-animation-duration) * .6) var(--oc-animation-ease,var(--oc-ease-smooth)) both}.oc-table-wrapper.oc-animate thead{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .4) var(--oc-animation-ease,var(--oc-ease-smooth)) both}.oc-table-wrapper.oc-animate tbody tr{animation:oc-table-enter-row var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-row-index,0))}.oc-table-wrapper.oc-animate tbody td{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .5) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-row-index,0))}.oc-table-wrapper.oc-animate td.oc-table-heatmap{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .7) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-row-index,0) + var(--oc-animation-duration) * .3)}.oc-table-wrapper.oc-animate td.oc-table-category{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .7) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-row-index,0) + var(--oc-animation-duration) * .3)}.oc-table-wrapper.oc-animate .oc-table-bar-fill{animation:oc-table-enter-bar-fill calc(var(--oc-animation-duration) * .8) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-row-index,0) + var(--oc-animation-duration) * .3)}.oc-table-wrapper.oc-animate .oc-table-sparkline>svg{animation:oc-enter-line calc(var(--oc-animation-duration) * .8) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-row-index,0) + var(--oc-animation-duration) * .4)}.oc-table-wrapper.oc-animate .oc-table-sparkline-dot{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .3) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-row-index,0) + var(--oc-animation-duration) * .8)}.oc-table-wrapper.oc-animate .oc-table-sparkline-labels{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .3) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-row-index,0) + var(--oc-animation-duration) * .8)}.oc-table-wrapper.oc-animate .oc-table-search{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .5) var(--oc-animation-ease,var(--oc-ease-smooth)) both}.oc-table-wrapper.oc-animate .oc-table-pagination{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .5) var(--oc-animation-ease,var(--oc-ease-smooth)) both}@keyframes oc-enter-bar{0%{clip-path:inset(100% 0 0);opacity:0}75%{opacity:1}to{clip-path:inset(0);opacity:1}}@keyframes oc-enter-bar-h{0%{clip-path:inset(0 100% 0 0);opacity:0}75%{opacity:1}to{clip-path:inset(0);opacity:1}}@keyframes oc-enter-line{0%{clip-path:inset(0 100% 0 0);opacity:0}15%{opacity:1}to{clip-path:inset(0);opacity:1}}@keyframes oc-enter-point{0%{opacity:0;transform:scale(.3)}to{opacity:1;transform:scale(1)}}@keyframes oc-enter-map-fill{0%{fill:var(--oc-secondary);opacity:0}to{fill:var(--oc-feature-fill);opacity:var(--oc-feature-target-opacity,1)}}@keyframes oc-enter-map-point{0%{opacity:0;transform:scale(.75)}to{opacity:1;transform:scale(1)}}@keyframes oc-enter-fade-only{0%{opacity:0}to{opacity:1}}@keyframes oc-enter-fade{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}@keyframes oc-table-enter-row{0%{transform:translateY(6px)}to{transform:translateY(0)}}@keyframes oc-table-enter-bar-fill{0%{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0)}}@keyframes oc-pulse{0%{r:var(--oc-pulse-r,4px);fill-opacity:1}45%{r:calc(var(--oc-pulse-r,4px) * 1.8);fill-opacity:.5}to{r:var(--oc-pulse-r,4px);fill-opacity:1}}@keyframes oc-tooltip-in{0%{opacity:0;transform:translateY(2px)}to{opacity:1;transform:translateY(0)}}.oc-animate .oc-mark-rect :is(rect,path){animation:oc-enter-bar var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-bar :is(rect,path){animation:oc-enter-bar var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-rect[data-orient=horizontal] :is(rect,path){animation-name:oc-enter-bar-h}.oc-animate .oc-mark-bar[data-orient=horizontal] :is(rect,path){animation-name:oc-enter-bar-h}.oc-animate .oc-mark-rect[data-stack-pos] :is(rect,path){animation-duration:var(--oc-stack-segment-duration,.15s);animation-timing-function:linear;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0) + var(--oc-stack-pos,0) * var(--oc-stack-segment-duration,.15s))}.oc-animate .oc-stack-reveal{animation:oc-enter-bar var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both}.oc-animate .oc-stack-reveal[data-orient=horizontal]{animation-name:oc-enter-bar-h}.oc-animate .oc-stack-reveal .oc-mark-rect :is(rect,path){animation:none}.oc-animate .oc-mark-line{animation:oc-enter-line var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-area{animation:oc-enter-line var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-arc{animation:oc-enter-fade-only var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate circle.oc-mark-point{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .4) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate circle.oc-mark-circle{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .4) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-line~circle.oc-mark-point{animation-delay:calc(var(--oc-animation-duration) * .35 + var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-area~circle.oc-mark-point{animation-delay:calc(var(--oc-animation-duration) * .35 + var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-text text{animation:oc-enter-fade calc(var(--oc-animation-duration) * .6) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-rule line{animation:oc-enter-fade calc(var(--oc-animation-duration) * .5) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-tick line{animation:oc-enter-fade calc(var(--oc-animation-duration) * .5) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-mark-label{animation:oc-enter-fade .25s var(--oc-ease-smooth) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0) + var(--oc-animation-duration) * .7)}.oc-animate .oc-annotation{animation:oc-enter-fade .3s var(--oc-ease-smooth) both;animation-delay:calc(var(--oc-animation-duration) + var(--oc-annotation-delay,.15s))}.oc-animate .oc-tilemap-tile{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .35) ease-in both;animation-delay:var(--oc-tile-delay,0s)}.oc-animate .oc-map-feature{animation:oc-enter-map-fill var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:var(--oc-map-delay,0s)}.oc-animate .oc-map-features[data-bulk-animate]{animation:oc-enter-fade-only var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both}.oc-animate .oc-map-features[data-bulk-animate] .oc-map-feature{animation:none}.oc-animate .oc-map-borders path{animation:oc-enter-fade-only calc(var(--oc-animation-duration) * .4) ease-in both;animation-delay:calc(var(--oc-animation-duration) * .7)}.oc-animate .oc-map-point{animation:oc-enter-map-point calc(var(--oc-animation-duration) * .4) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-duration) * .8 + var(--oc-mark-index,0) * var(--oc-point-stagger,60ms))}.oc-animate .oc-sankey-node rect{animation:oc-enter-fade-only var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-sankey-link path{animation:oc-enter-fade-only var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:calc(var(--oc-animation-duration) * .3 + var(--oc-animation-stagger) * var(--oc-mark-index,0))}.oc-animate .oc-barlist-row{animation:oc-enter-fade calc(var(--oc-animation-duration) * .6) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:var(--oc-row-delay,0s)}.oc-animate .oc-barlist-bar{animation:oc-enter-bar-h var(--oc-animation-duration) var(--oc-animation-ease,var(--oc-ease-smooth)) both;animation-delay:var(--oc-row-delay,0s)}.oc-animate[data-display=sparkline] .oc-mark-line,.oc-animate[data-display=sparkline] .oc-mark-area{animation-timing-function:cubic-bezier(.16,1,.3,1)}}@layer oc.reduced-motion{@media (prefers-reduced-motion:reduce){:is(.oc-root,.oc-chart-root,.oc-table-wrapper,.oc-table-root,.oc-graph-wrapper,.oc-graph-root,.oc-sankey-root,.oc-tilemap-root,.oc-barlist-root,.oc-map-root){transition:none;animation:none}:is(.oc-root,.oc-chart-root,.oc-table-wrapper,.oc-table-root,.oc-graph-wrapper,.oc-graph-root,.oc-sankey-root,.oc-tilemap-root,.oc-barlist-root,.oc-map-root) *{transition:none;animation:none}:is(.oc-root,.oc-chart-root,.oc-table-wrapper,.oc-table-root,.oc-graph-wrapper,.oc-graph-root,.oc-sankey-root,.oc-tilemap-root,.oc-barlist-root,.oc-map-root) :before{transition:none;animation:none}:is(.oc-root,.oc-chart-root,.oc-table-wrapper,.oc-table-root,.oc-graph-wrapper,.oc-graph-root,.oc-sankey-root,.oc-tilemap-root,.oc-barlist-root,.oc-map-root) :after{transition:none;animation:none}}}
|
|
2
2
|
/*# sourceMappingURL=styles.css.map */
|
package/dist/styles.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"mappings":"AAWA,iBCEE,mzEGFA,6lBJAF,eONE,mIAeA,6BAQA,uGAWA,yDAOA,iGAMA,qCAWA,8IAgBA,qHAcA,4EAQA,yGP1FF,qBUNE,6CAIA,2KAQA,wIAOA,+GAMA,+HAQA,wFAOA,sCAQA,8CAIA,wHAQA,4HAQA,2EAMA,6EAQA,8EAWA,8EAgBA,sDAIA,sEAMA,4EAIA,wEAaA,sFAUA,sFASA,gCAMA,mFG9JA,4fAsBE,4FAOA,iFAOA,gMAWA,gGAMA,0EAKA,mHAQA,yJAUA,oKAUA,uMAYA,qGAKA,wEAMA,gHAMA,kGAKA,qEAWF,qFAOA,4FE1IA,6CAIA,gCCAA,uFAOA,sNAaA,0HAWA,wMAOA,gCAIA,oCAMA,sFASA,wCAcA,iGAUA,kGAIA,w6BAeA,8BAYA,wGAIA,4GAIA,sEC1HA,kJAaA,iHASA,wDAIA,sSAeA,6RAoBA,uFAKA,iGAKA,gDAMA,qEAMA,oIAWA,0DAKA,2SAiBA,yLAWA,0GAMA,wCAIA,mFftIA,kDAKA,+CAKA,qGASA,wHAUA,yGAWA,qFAKA,0MAYA,oSAeA,6DAKA,iGAWA,2aAsBA,0CAIA,qFAKA,yFAAA,wFAMA,yDIrIA,iGAKE,qFAMA,yDAIA,4DAKA,uIAAA,uIAcA,kLAUA,gFASA,mDAIA,sEAKA,iFAKA,2CAKF,sNAOA,kPAOA,2IAKA,gJAKA,iCASE,0FAAA,0FAaF,oLAYE,mLAAA,kLAaA,yFAKA,qFAKA,4CAAA,2CAOA,+FAKA,6DAMA,4FAKA,+DAaF,iQAaA,wFAAA,8EAAA,yFAAA,+EAMA,+IAOA,+BAGE,wCASF,oJAQE,6PAaE,oEAKA,2GAKA,+FAOJ,4DAIA,+CASA,gCAIA,iIAUA,gDASA,+DAKE,kEAOF,iFAOA,mGAWA,2DAIE,qCAKF,8CAQA,+BAaE,iGAAA,iGAOA,+DAIA,mFAOA,yDAAA,yDAMA,2DAUF,wGAQA,sLAWA,mDAKA,sFAKA,sFAKA,kHAMA,qLAYA,oEAWA,gFAME,iGAiBA,oDAIA,0CAIA,sHASA,kLAAA,kLAaA,iIAUA,0LAYA,uDAKA,uGAOA,2DAIA,oDAIA,gDAUA,6CAIA,kEASF,2EASA,oHMzkBA,qIASA,kEAOA,2CAQA,gFAOA,yBAIA,0EAMA,4GASE,8bAkBA,2RAaF,wRAgBA,qLAiBA,6EAIE,kEAIA,+FAOF,4CAIA,iCAIA,0HAOA,+EAQA,sEAMA,sDAKE,2QAUE,2GTrKJ,2GAIA,8IAOA,oGEdA,mEAYA,4EAIA,uCACE,6DLhBJ,oBSJI,4JAMA,4JAOA,8NAOA,yOAOA,wRAAA,yRAcA,4RAaA,uRAYA,4RAAA,+RAaA,uKAAA,2KD/EF,8GAgBA,kHAgBA,iHAeA,4FAoBA,8IAaA,iGAaA,yDAUA,sGAaA,uFAWA,yFAaA,iKAgBA,sGGzJE,mMAAA,kMAOA,+FAAA,8FASA,8RAYA,8MAOA,8MASA,kNAUA,qOAAA,sOAQA,+JAAA,+JAWA,8NAOA,8NAOA,8NAOA,kMAWA,uKAOA,wJAQA,gLASA,8JAKA,+EAKA,2KAQA,mQAYA,0NAQA,8PAYA,uLAMA,6KAeF,wJXvMF,yBcDE,uCACE,6LAAA,+LAAA,qMAAA","sources":["../src/styles/index.css","../src/styles/tokens.css","../src/styles/sankey.css","../src/styles/you-draw-it.css","../src/styles/dark.css","../src/styles/sparkline.css","../src/styles/table.css","../src/styles/base.css","../src/styles/keyframes.css","../src/styles/table-animation.css","../src/styles/chrome.css","../src/styles/animation.css","../src/styles/graph.css","../src/styles/tooltip.css","../src/styles/reduced-motion.css","../src/styles/legend.css","../src/styles/series-search.css","../src/styles/interaction.css"],"sourcesContent":["/**\n * @opendata-ai/openchart-core styles\n *\n * CSS with oc- prefix for all class names.\n * CSS custom properties for theme overrides.\n * Dark mode via .oc-dark class on the container.\n * Cascade layers: oc.tokens, oc.base, oc.components, oc.animation, oc.reduced-motion.\n */\n\n/* For optimal typography, load Inter: https://fonts.google.com/specimen/Inter */\n\n@layer oc.tokens, oc.base, oc.components, oc.animation, oc.reduced-motion;\n\n@import \"./tokens.css\";\n@import \"./dark.css\";\n@import \"./base.css\";\n@import \"./chrome.css\";\n@import \"./tooltip.css\";\n@import \"./legend.css\";\n@import \"./interaction.css\";\n@import \"./series-search.css\";\n@import \"./you-draw-it.css\";\n@import \"./table.css\";\n@import \"./table-animation.css\";\n@import \"./graph.css\";\n@import \"./sankey.css\";\n@import \"./sparkline.css\";\n@import \"./keyframes.css\";\n@import \"./animation.css\";\n@import \"./reduced-motion.css\";\n","/* GENERATED FILE — do not edit. Source: packages/core/src/styles/token-definitions.ts. Regenerate: bun run generate:tokens */\n\n@layer oc.tokens {\n /* ---------------------------------------------------------------------------\n * Custom properties (light mode defaults)\n *\n * These are FALLBACK defaults. At runtime, the JS theme engine stamps the\n * resolved theme as inline --oc-* custom properties on each .oc-root\n * container (see packages/vanilla/src/theme-tokens.ts). These CSS values\n * serve as fallbacks for contexts where JS hasn't mounted yet (SSR, static\n * HTML examples).\n * --------------------------------------------------------------------------- */\n\n .oc-root,\n .oc-chart-root,\n .oc-table-wrapper,\n .oc-table-root,\n .oc-graph-wrapper,\n .oc-graph-root,\n .oc-sankey-root,\n .oc-tilemap-root,\n .oc-barlist-root,\n .oc-map-root {\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n\n /* Opt out of iOS text auto-inflation so measured widths match rendered text. */\n -webkit-text-size-adjust: 100%;\n text-size-adjust: 100%;\n\n --oc-font-family:\n \"Inter Variable\", Inter, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n --oc-font-mono: \"JetBrains Mono\", \"Fira Code\", \"Cascadia Code\", monospace;\n\n /* Animation easing presets via CSS linear() */\n --oc-ease-smooth: linear(\n 0,\n 0.157,\n 0.438,\n 0.64,\n 0.766,\n 0.85,\n 0.906,\n 0.941,\n 0.964,\n 0.978,\n 0.988,\n 0.994,\n 0.998,\n 1\n );\n --oc-ease-snappy: linear(\n 0,\n 0.012,\n 0.048,\n 0.108,\n 0.194,\n 0.302,\n 0.426,\n 0.559,\n 0.69,\n 0.808,\n 0.905,\n 0.973,\n 1.013,\n 1.028,\n 1.023,\n 1.006,\n 0.984,\n 0.966,\n 0.957,\n 0.957,\n 0.964,\n 0.975,\n 0.986,\n 0.995,\n 1,\n 1.003,\n 1.002,\n 1,\n 0.998,\n 0.998,\n 0.999,\n 1\n );\n\n /* Animation timing defaults */\n --oc-animation-duration: 450ms;\n --oc-animation-stagger: 30ms;\n --oc-annotation-delay: 150ms;\n\n /* Typography scale (editorial design system) */\n --oc-title-size: 26px;\n --oc-title-weight: 600; /* one ladder: 400 regular / 500 medium / 600 semibold / 700 bold */\n --oc-title-tracking: -0.022em;\n --oc-subtitle-size: 14px;\n --oc-subtitle-weight: 400;\n --oc-source-size: 11px;\n --oc-source-weight: 400;\n --oc-body-size: 13px;\n --oc-eyebrow-size: 11px;\n --oc-eyebrow-weight: 500;\n --oc-eyebrow-tracking: 0.08em;\n\n /* Surfaces (light mode defaults) */\n --oc-bg: #ffffff;\n --oc-card: #ffffff;\n --oc-secondary: #f4f4f5; /* zinc-100, raised surface */\n\n /*\n * Text levels. Names invert across modes: in light mode \"muted\" sits at\n * a lighter zinc step than \"subtle\" because both are picked relative to\n * the active background, not from a fixed lightness ladder. The intent\n * is \"muted = first step away from primary text\"; \"subtle = next step\n * down\"; etc.\n *\n * Light mode: text=zinc-950, secondary=zinc-700, muted=zinc-500,\n * subtle=zinc-400, faint=zinc-300\n * Dark mode (dark.css): inverts the surface tokens but keeps the same\n * muted -> subtle -> faint progression away from primary.\n */\n --oc-text: #09090b;\n --oc-text-secondary: #3f3f46;\n --oc-text-muted: #71717a;\n --oc-text-faint: #d4d4d8;\n\n /*\n * Derived neutral ramp. Named by the share of *text* in a text-toward-\n * background mix: 100 is nearly the background, 800 is nearly the text.\n * These static values are the mix against the default surfaces; mounts\n * restamp them from ResolvedTheme.colors.neutral, which a custom warm or\n * cool theme derives from its own text/background pair.\n */\n --oc-gray-100: #f0f0f0;\n --oc-gray-200: #e1e1e2;\n --oc-gray-300: #c9c9c9;\n --oc-gray-400: #9d9d9d;\n --oc-gray-600: #787879;\n --oc-gray-800: #474748;\n\n /* Lines */\n --oc-gridline: rgba(0, 0, 0, 0.08);\n --oc-axis: rgba(0, 0, 0, 0.14); /* hairline = theme.colors.hairline, not the tick-label ink */\n --oc-border: rgba(0, 0, 0, 0.08);\n --oc-border-radius: 8px; /* containers and tooltips; marks use --oc-radius-sm */\n\n /* Radius ladder */\n --oc-radius-sm: 2px;\n --oc-radius-md: 6px;\n --oc-radius-lg: var(--oc-border-radius);\n --oc-radius-full: 999px;\n\n /* Brand and semantic */\n --oc-accent: #06b6d4;\n --oc-accent-strong: #0891b2; /* darker cyan for line strokes on light bg */\n /* kept equal to DEFAULT_THEME.colors.positive (token-theme-parity test) */\n --oc-positive: #15803d;\n --oc-negative: #dc2626;\n /* delta chip background */\n --oc-positive-tint: color-mix(in srgb, var(--oc-positive) 10%, var(--oc-bg));\n --oc-negative-tint: color-mix(in srgb, var(--oc-negative) 10%, var(--oc-bg));\n --oc-focus: #3b82f6;\n /* static, intentionally NOT derived from --oc-focus and NOT flipped in dark mode */\n --oc-focus-ring: rgba(59, 130, 246, 0.1);\n --oc-focus-ring-strong: rgba(59, 130, 246, 0.25);\n --oc-editable-hover: rgba(79, 70, 229, 0.35); /* edit-mode hover outline, indigo one-off */\n\n /* Spacing scale (4px base) — only --oc-space-2/4 are consumed (JS-stamped) */\n --oc-space-2: 8px;\n --oc-space-4: 16px;\n\n /*\n * Hover language. The hovered element goes to full ink; the rest of its\n * group drops to --oc-hover-dim over --oc-hover-duration. Maps override the\n * dim locally (3000 county paths at 0.3 reads as a blackout, not a hint).\n */\n --oc-hover-dim: 0.3;\n --oc-hover-duration: 140ms;\n --oc-map-hover-dim: 0.75;\n\n /* Interactive states */\n --oc-hover-bg: rgba(0, 0, 0, 0.025);\n --oc-tooltip-bg: rgba(255, 255, 255, 0.88);\n --oc-tooltip-border: rgba(0, 0, 0, 0.08);\n --oc-tooltip-shadow: 0 2px 8px rgba(0, 0, 0, 0.08), 0 0 1px rgba(0, 0, 0, 0.12);\n --oc-tooltip-text: #09090b;\n --oc-legend-text: #3f3f46;\n }\n}\n","@layer oc.components {\n /* ---------------------------------------------------------------------------\n * Sankey\n *\n * Hovering a node (or a link) traces the whole path through it: everything\n * upstream and everything downstream stays lit, the rest drops back. The mount\n * writes the opacities; this file only owns how they move, using the shared\n * hover duration so a sankey fades on the same clock as a bar chart.\n *\n * The transitions are switched off during the entrance (`.oc-animate`), where\n * the keyframes own opacity and a competing transition would smear them.\n * --------------------------------------------------------------------------- */\n\n .oc-sankey:not(.oc-animate) .oc-sankey-link path {\n transition: fill-opacity var(--oc-hover-duration) ease-out;\n }\n\n .oc-sankey:not(.oc-animate) .oc-sankey-node,\n .oc-sankey:not(.oc-animate) .oc-sankey-label {\n transition: opacity var(--oc-hover-duration) ease-out;\n }\n\n /* Labels are decoration over the flow: never a text cursor, never a selection\n * drag that eats the hover. */\n .oc-sankey-label {\n pointer-events: none;\n user-select: none;\n }\n}\n","@layer oc.components {\n /* ---------------------------------------------------------------------------\n * You draw it (youDrawIt)\n *\n * NYT-style draw-then-reveal. SVG-space elements (hatched region, guess path,\n * reveal clip) render inside the chart SVG; the prompt + skip-to-reveal button\n * are an absolutely-positioned HTML overlay the vanilla adapter sizes over the\n * drawing region (inline left/top/width/height). All colors come from --oc-*\n * tokens so they flip in .oc-dark.\n * --------------------------------------------------------------------------- */\n\n /* Hatched \"draw here\" region. Fill comes from an SVG <pattern> (line color =\n * the target series color); this only governs overall opacity + fade-out. */\n .oc-ydi-region {\n opacity: 0.35;\n transition: opacity 0.4s ease;\n }\n\n .oc-ydi-region[data-ydi-hidden=\"true\"] {\n opacity: 0;\n }\n\n /* The vertical rule at `from` where drawing begins. */\n .oc-ydi-boundary {\n stroke: var(--oc-text-muted);\n stroke-width: 1;\n stroke-dasharray: 3 3;\n stroke-opacity: 0.6;\n }\n\n /* Reader's guess: a distinct pen-like stroke that reads as \"yours\" against the\n * solid real line. Dashed + focus-blue so it stays legible in both modes. */\n .oc-ydi-guess {\n stroke: var(--oc-focus);\n stroke-width: 2.5;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-dasharray: 1 6;\n }\n\n /* Host-supplied comparison line (\"what everyone else guessed\"). Muted so it\n * sits behind the reader's guess and the real line. */\n .oc-ydi-comparison {\n stroke: var(--oc-text-muted);\n stroke-width: 1.5;\n stroke-opacity: 0.5;\n stroke-dasharray: 4 4;\n }\n\n /* Reveal clip rect: the width animates from the `from` boundary to the full\n * area on reveal, wiping the real line in left-to-right. The vanilla adapter\n * adds .oc-ydi-clip-animate right before setting the final width; reduced\n * motion skips the class so the width snaps. */\n .oc-ydi-clip-rect.oc-ydi-clip-animate {\n transition: width 0.7s cubic-bezier(0.22, 1, 0.36, 1);\n }\n\n /* HTML controls overlay: prompt (top) + reveal button (bottom-right). */\n .oc-ydi-controls {\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n align-items: flex-end;\n pointer-events: none;\n font-family: var(--oc-font-family);\n padding: 8px;\n box-sizing: border-box;\n z-index: 10;\n }\n\n .oc-ydi-prompt {\n align-self: center;\n max-width: 100%;\n padding: 6px 12px;\n border-radius: var(--oc-radius-md);\n background: var(--oc-card);\n border: 1px solid var(--oc-border);\n color: var(--oc-text-secondary);\n font-size: 13px;\n font-weight: 500;\n line-height: 16px;\n text-align: center;\n box-shadow: var(--oc-tooltip-shadow);\n }\n\n .oc-ydi-controls.oc-ydi-revealed .oc-ydi-prompt {\n display: none;\n }\n\n /* Clear + reveal buttons, side by side at the bottom-right. */\n .oc-ydi-actions {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: 8px;\n pointer-events: none;\n }\n\n /* Skip-to-reveal and clear buttons. pointer-events re-enabled (the overlay\n * disables it) so they stay clickable and keyboard-reachable. Min height\n * enforced inline by the adapter (>= 24px effective touch target). */\n .oc-ydi-reveal-button,\n .oc-ydi-reset-button {\n pointer-events: auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 6px 14px;\n border: 1px solid var(--oc-border);\n border-radius: var(--oc-radius-md);\n background: var(--oc-bg);\n color: var(--oc-text);\n font-family: inherit;\n font-size: 13px;\n font-weight: 500;\n white-space: nowrap;\n cursor: pointer;\n box-shadow: var(--oc-tooltip-shadow);\n transition:\n background-color 0.15s,\n border-color 0.15s;\n }\n\n .oc-ydi-reset-button[hidden] {\n display: none;\n }\n\n .oc-ydi-reveal-button:hover,\n .oc-ydi-reset-button:hover {\n background: var(--oc-hover-bg);\n }\n\n .oc-ydi-reveal-button:focus-visible,\n .oc-ydi-reset-button:focus-visible {\n outline: 2px solid var(--oc-focus);\n outline-offset: 2px;\n }\n\n .oc-ydi-reveal-button:disabled {\n opacity: 0.5;\n cursor: default;\n }\n}\n","/* GENERATED FILE — do not edit. Source: packages/core/src/styles/token-definitions.ts. Regenerate: bun run generate:tokens */\n\n@layer oc.tokens {\n /* ---------------------------------------------------------------------------\n * Dark mode overrides (fallback defaults)\n *\n * At runtime, the JS theme engine stamps dark-adapted --oc-* custom\n * properties on each .oc-root container. These CSS values serve as\n * fallbacks for contexts where JS hasn't mounted yet.\n * --------------------------------------------------------------------------- */\n\n .oc-dark {\n /* Surfaces (zinc-based achromatic ramp) */\n --oc-bg: #09090b;\n --oc-card: #111113;\n --oc-secondary: #27272a;\n\n /* Text levels — see tokens.css for the cross-mode naming rationale */\n --oc-text: #f7f8f8;\n --oc-text-secondary: #d0d6e0;\n --oc-text-muted: #a1a1aa;\n --oc-text-faint: #52525b;\n\n /* Lines */\n --oc-gridline: rgba(255, 255, 255, 0.06);\n --oc-axis: rgba(255, 255, 255, 0.14);\n --oc-border: rgba(255, 255, 255, 0.1);\n\n /* Brand and semantic — accent stays cyan (no darkening on dark bg) */\n --oc-accent: #06b6d4;\n --oc-accent-strong: #06b6d4;\n --oc-positive: #4ade80;\n --oc-negative: #f87171;\n --oc-focus: #60a5fa;\n\n /* Interactive states */\n --oc-hover-bg: rgba(255, 255, 255, 0.05);\n --oc-tooltip-bg: rgba(17, 17, 19, 0.92);\n --oc-tooltip-border: rgba(255, 255, 255, 0.08);\n --oc-tooltip-shadow: 0 2px 8px rgba(0, 0, 0, 0.3), 0 0 1px rgba(0, 0, 0, 0.4);\n --oc-tooltip-text: #f7f8f8;\n --oc-legend-text: #d0d6e0;\n }\n}\n","@layer oc.components {\n /**\n * Sparkline display mode.\n *\n * Stamped on the SVG root as data-display=\"sparkline\" by the renderer when\n * the spec sets display: 'sparkline'. Strips any inherited padding/margin\n * so the mark renders truly edge-to-edge in tight container layouts (KPI\n * cards, table cells, dashboard tiles).\n */\n\n .oc-chart[data-display=\"sparkline\"] {\n display: block;\n margin: 0;\n padding: 0;\n }\n\n /**\n * Data-arrival pulse. The update driver stamps `oc-pulse` on the sparkline's\n * terminator dot when a transition finishes and strips it 600ms later.\n * Deliberately not scoped under `.oc-animate`: that class only exists during\n * the entrance window, and this fires on updates.\n */\n .oc-chart[data-display=\"sparkline\"] .oc-pulse {\n animation: oc-pulse 600ms ease-out;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .oc-chart[data-display=\"sparkline\"] .oc-pulse {\n animation: none;\n }\n }\n}\n","@layer oc.components {\n /* ---------------------------------------------------------------------------\n * Table base\n * --------------------------------------------------------------------------- */\n\n .oc-table-wrapper {\n font-family: var(--oc-font-family);\n color: var(--oc-text);\n background: var(--oc-bg);\n\n & > .oc-chrome {\n margin-bottom: 16px;\n padding-left: 16px;\n padding-right: 16px;\n }\n\n & > .oc-chrome:first-child {\n padding-top: 4px;\n }\n\n & table {\n width: 100%;\n border-collapse: collapse;\n }\n\n & th,\n & td {\n /* 12 + 24 + 12 = 48px rows. Condensed and relaxed keep the same\n line box and change only the padding, so the ladder is 40/48/56. */\n padding: 12px 16px;\n line-height: 24px;\n text-align: left;\n border-bottom: 1px solid var(--oc-border);\n /* Column widths from the engine already sum to the container width;\n without border-box the padding pushes each cell wider than its\n computed width and auto layout rescales the whole row. */\n box-sizing: border-box;\n }\n\n & th {\n font-weight: 500;\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--oc-text-muted);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n }\n\n & thead {\n position: sticky;\n top: 0;\n z-index: 2;\n background: var(--oc-bg);\n }\n\n /* A hairline, like every other rule in the table. The old 2px header rule\n was the heaviest line on the page and drew the eye away from the data. */\n & thead th {\n border-bottom-width: 1px;\n }\n\n & td {\n font-size: 14px;\n font-variant-numeric: tabular-nums;\n }\n\n & th:focus {\n outline: 2px solid var(--oc-focus);\n outline-offset: -2px;\n }\n\n & tbody:focus {\n outline: none;\n }\n }\n\n .oc-table-title {\n margin-bottom: 4px;\n font-size: var(--oc-title-computed-size, var(--oc-title-size));\n font-weight: var(--oc-title-computed-weight, var(--oc-title-weight));\n color: var(--oc-title-computed-color, var(--oc-text));\n }\n\n .oc-table-subtitle {\n margin-bottom: 8px;\n font-size: var(--oc-subtitle-computed-size, var(--oc-subtitle-size));\n font-weight: var(--oc-subtitle-computed-weight, var(--oc-subtitle-weight));\n color: var(--oc-subtitle-computed-color, var(--oc-text-secondary));\n }\n\n .oc-table-source {\n font-size: var(--oc-source-computed-size, var(--oc-source-size));\n color: var(--oc-source-computed-color, var(--oc-text-muted));\n }\n\n .oc-table-footer-text {\n font-size: var(--oc-footer-computed-size, var(--oc-source-size));\n color: var(--oc-footer-computed-color, var(--oc-text-muted));\n }\n\n .oc-table-scroll {\n overflow-x: auto;\n }\n\n /* ---------------------------------------------------------------------------\n * Sticky first column\n * --------------------------------------------------------------------------- */\n\n .oc-table--sticky {\n & th:first-child,\n & td:first-child {\n position: sticky;\n left: 0;\n z-index: 1;\n background: var(--oc-bg);\n }\n }\n\n /* ---------------------------------------------------------------------------\n * Sort controls\n * --------------------------------------------------------------------------- */\n\n .oc-table-sort-btn {\n background: none;\n border: none;\n cursor: pointer;\n padding: 2px;\n margin-left: 6px;\n display: inline-flex;\n flex-direction: column;\n align-items: center;\n vertical-align: middle;\n gap: 2px;\n\n &::before,\n &::after {\n content: \"\";\n display: block;\n width: 0;\n height: 0;\n border-left: 5px solid transparent;\n border-right: 5px solid transparent;\n transition:\n opacity 0.15s,\n border-color 0.15s;\n }\n\n &::before {\n border-bottom: 4.5px solid var(--oc-text-secondary);\n opacity: 0.35;\n }\n\n &::after {\n border-top: 4.5px solid var(--oc-text-secondary);\n opacity: 0.35;\n }\n\n &:hover::before,\n &:hover::after {\n opacity: 0.75;\n }\n }\n\n th[aria-sort=\"ascending\"] .oc-table-sort-btn {\n &::before {\n opacity: 1;\n border-bottom-color: var(--oc-text);\n }\n\n &::after {\n opacity: 0.15;\n }\n }\n\n th[aria-sort=\"descending\"] .oc-table-sort-btn {\n &::after {\n opacity: 1;\n border-top-color: var(--oc-text);\n }\n\n &::before {\n opacity: 0.15;\n }\n }\n\n /* ---------------------------------------------------------------------------\n * Search\n * --------------------------------------------------------------------------- */\n\n /* Shared search-input skin (table + series-search).\n Padding excluded: it diverges (table: 8px 12px; series: 0 10px 0 28px)\n and series-search.css is imported before table.css — a padding declaration\n here would beat the series-search override by source order. */\n .oc-table-search input,\n .oc-series-search-input {\n width: 100%;\n border: 1px solid var(--oc-border);\n border-radius: var(--oc-radius-md);\n font-size: 13px;\n font-family: inherit;\n background: var(--oc-bg);\n color: var(--oc-text);\n box-sizing: border-box;\n transition: border-color 0.15s;\n }\n\n .oc-table-search input::placeholder,\n .oc-series-search-input::placeholder {\n color: var(--oc-text-muted);\n font-size: 13px;\n }\n\n .oc-table-search input:focus,\n .oc-series-search-input:focus {\n outline: none;\n border-color: var(--oc-focus);\n box-shadow: 0 0 0 3px var(--oc-focus-ring);\n }\n\n .oc-table-search {\n padding: 8px 0;\n\n & input {\n padding: 8px 12px;\n }\n }\n\n /* ---------------------------------------------------------------------------\n * Pagination\n * --------------------------------------------------------------------------- */\n\n .oc-table-pagination {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 0 4px;\n font-size: 13px;\n color: var(--oc-text-secondary);\n\n & button {\n padding: 6px 14px;\n border: 1px solid var(--oc-border);\n border-radius: var(--oc-radius-md);\n background: var(--oc-bg);\n color: var(--oc-text);\n cursor: pointer;\n font-size: 13px;\n font-family: inherit;\n transition:\n background 0.15s,\n border-color 0.15s;\n\n &:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n }\n\n &:hover:not(:disabled) {\n background: var(--oc-hover-bg);\n border-color: var(--oc-axis);\n }\n\n &:focus-visible {\n outline: 2px solid var(--oc-focus);\n outline-offset: 1px;\n }\n }\n }\n\n .oc-table-pagination-info {\n font-variant-numeric: tabular-nums;\n }\n\n .oc-table-pagination-btns {\n display: flex;\n gap: 8px;\n }\n\n /* ---------------------------------------------------------------------------\n * Bar cells\n * --------------------------------------------------------------------------- */\n\n .oc-table-bar {\n position: relative;\n }\n\n .oc-table-bar-fill {\n position: absolute;\n top: 8px;\n left: 0;\n bottom: 8px;\n border-radius: var(--oc-radius-sm);\n opacity: 0.18;\n pointer-events: none;\n }\n\n .oc-table-bar-value {\n position: relative;\n z-index: 1;\n }\n\n /* ---------------------------------------------------------------------------\n * Sparkline cells\n * --------------------------------------------------------------------------- */\n\n .oc-table-sparkline {\n display: block;\n width: 100%;\n position: relative;\n\n & svg {\n display: block;\n width: 100%;\n overflow: visible;\n }\n }\n\n .oc-table-sparkline-dot {\n position: absolute;\n border-radius: 50%;\n width: 5px;\n height: 5px;\n }\n\n .oc-table-sparkline-labels {\n display: flex;\n justify-content: space-between;\n font-size: 11px;\n line-height: 1;\n }\n\n /* ---------------------------------------------------------------------------\n * Image cells\n * --------------------------------------------------------------------------- */\n\n .oc-table-image {\n display: inline-block;\n vertical-align: middle;\n\n & img {\n object-fit: cover;\n }\n }\n\n .oc-table-image-rounded img {\n border-radius: 50%;\n }\n\n /* ---------------------------------------------------------------------------\n * Flag cells\n * --------------------------------------------------------------------------- */\n\n .oc-table-flag {\n font-size: 1.2em;\n }\n\n /* ---------------------------------------------------------------------------\n * Density\n *\n * regular 48px rows (base), condensed 40px, relaxed 56px. `.oc-table--compact`\n * is the deprecated alias for condensed, kept one release.\n * --------------------------------------------------------------------------- */\n\n .oc-table--condensed,\n .oc-table--compact {\n & th,\n & td {\n padding: 8px 12px;\n line-height: 24px;\n font-size: 13px;\n }\n\n & th {\n font-size: 11px;\n }\n\n & .oc-table-bar-fill {\n top: 5px;\n bottom: 5px;\n }\n }\n\n .oc-table--relaxed {\n & th,\n & td {\n padding: 16px 20px;\n line-height: 24px;\n }\n\n & .oc-table-bar-fill {\n top: 12px;\n bottom: 12px;\n }\n }\n\n /* ---------------------------------------------------------------------------\n * Striping\n * --------------------------------------------------------------------------- */\n\n .oc-table--striped tbody tr:nth-child(even) {\n background: color-mix(in srgb, var(--oc-text) 3%, transparent);\n }\n\n /* ---------------------------------------------------------------------------\n * Delta chips\n * --------------------------------------------------------------------------- */\n\n .oc-table-delta {\n display: inline-flex;\n align-items: baseline;\n gap: 4px;\n padding: 2px 8px;\n border-radius: var(--oc-radius-md);\n font-weight: 500;\n font-variant-numeric: tabular-nums;\n line-height: 16px;\n }\n\n .oc-table-delta-arrow {\n font-size: 0.8em;\n line-height: 1;\n }\n\n .oc-table-delta--positive {\n color: var(--oc-positive);\n background: var(--oc-positive-tint);\n }\n\n .oc-table-delta--negative {\n color: var(--oc-negative);\n background: var(--oc-negative-tint);\n }\n\n .oc-table-delta--neutral {\n color: var(--oc-text-muted);\n background: color-mix(in srgb, var(--oc-text) 6%, transparent);\n }\n\n /* Category chips: the engine supplies the tint, ink and dot color inline. */\n .oc-table-chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 2px 8px;\n border-radius: var(--oc-radius-full);\n font-size: 12px;\n font-weight: 500;\n line-height: 16px;\n white-space: nowrap;\n }\n\n .oc-table-chip-dot {\n flex: none;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n }\n\n /* ---------------------------------------------------------------------------\n * Totals footer\n * --------------------------------------------------------------------------- */\n\n tfoot.oc-table-total {\n position: sticky;\n bottom: 0;\n z-index: 2;\n background: var(--oc-bg);\n\n & td {\n font-weight: 600;\n border-bottom: none;\n border-top: 1px solid var(--oc-border);\n }\n }\n\n /* ---------------------------------------------------------------------------\n * Cards mode (below 400px)\n *\n * Rows become two-column grids with the header printed per cell. `display:\n * grid` drops the implicit table roles, so the renderer stamps explicit ARIA\n * roles on every element; `display: contents` is deliberately NOT used —\n * it removes the row box the grid needs and breaks the semantics further.\n * --------------------------------------------------------------------------- */\n\n .oc-table--cards {\n & .oc-table-scroll {\n overflow-x: hidden;\n }\n\n & table {\n table-layout: fixed;\n }\n\n & thead {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n }\n\n & tbody tr,\n & tfoot tr {\n display: grid;\n /* Two equal halves keep every label/value pair the same width; an\n auto first column makes the third cell in a row narrower than the\n second and the card reads ragged. */\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 2px 12px;\n align-items: baseline;\n padding: 10px 12px;\n border-bottom: 1px solid var(--oc-border);\n }\n\n & td {\n display: block;\n width: auto;\n max-width: 100%;\n padding: 0;\n border-bottom: none;\n overflow-wrap: anywhere;\n text-align: right;\n }\n\n & td::before {\n content: attr(data-label);\n display: block;\n font-size: 11px;\n font-weight: 500;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--oc-text-muted);\n text-align: left;\n }\n\n /* A column with no header (flags, logos) prints no label either. */\n & td[data-label=\"\"]::before {\n content: none;\n }\n\n /* Priority 1 leads the card on its own line, label suppressed. */\n & td[data-priority=\"1\"] {\n grid-column: 1 / -1;\n font-size: 15px;\n font-weight: 600;\n text-align: left;\n }\n\n & td[data-priority=\"1\"]::before {\n content: none;\n }\n\n & td[data-priority=\"3\"] {\n display: none;\n }\n\n & .oc-table-sparkline {\n width: 100%;\n }\n }\n\n /* ---------------------------------------------------------------------------\n * Row hover (when onRowClick is set)\n * --------------------------------------------------------------------------- */\n\n .oc-table--clickable tbody {\n & tr {\n cursor: pointer;\n }\n\n & tr:hover {\n background: var(--oc-hover-bg);\n }\n }\n\n /* ---------------------------------------------------------------------------\n * Keyboard cell focus indicator\n * --------------------------------------------------------------------------- */\n\n .oc-table-cell-focus {\n outline: 2px solid var(--oc-focus);\n outline-offset: -2px;\n }\n\n /* ---------------------------------------------------------------------------\n * Empty state\n * --------------------------------------------------------------------------- */\n\n .oc-table-empty {\n padding: 32px 16px;\n text-align: center;\n color: var(--oc-text-secondary);\n font-size: 14px;\n font-style: italic;\n }\n}\n","@layer oc.base {\n /* ---------------------------------------------------------------------------\n * Wrapper roots\n * --------------------------------------------------------------------------- */\n\n .oc-chart-root {\n width: 100%;\n height: 100%;\n }\n\n .oc-table-root,\n .oc-graph-root,\n .oc-sankey-root,\n .oc-barlist-root,\n .oc-tilemap-root,\n .oc-map-root {\n width: 100%;\n height: 100%;\n }\n\n .oc-table-root {\n overflow: auto;\n }\n\n /* ---------------------------------------------------------------------------\n * Chart container\n * --------------------------------------------------------------------------- */\n\n .oc-chart {\n font-family: var(--oc-font-family);\n font-variant-numeric: tabular-nums;\n display: block;\n width: 100%;\n }\n\n /* ---------------------------------------------------------------------------\n * BarList SVG container\n * --------------------------------------------------------------------------- */\n\n .oc-tilemap,\n .oc-map {\n display: block;\n width: 100%;\n height: auto;\n }\n\n .oc-map-feature {\n transition:\n opacity var(--oc-hover-duration) ease-out,\n stroke-width 140ms ease-out;\n }\n\n .oc-barlist {\n display: block;\n width: 100%;\n }\n\n /* ---------------------------------------------------------------------------\n * Screen reader only utility\n * --------------------------------------------------------------------------- */\n\n /* `overflow: clip`, not `hidden` — see applySrOnlyStyles in\n packages/vanilla/src/dom-helpers.ts for why. Keep the two in sync. */\n .oc-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: clip;\n clip-path: inset(50%);\n white-space: nowrap;\n border-width: 0;\n }\n\n /* ---------------------------------------------------------------------------\n * Editable hover feedback\n * --------------------------------------------------------------------------- */\n\n .oc-editable-hover {\n outline: 1.5px solid var(--oc-editable-hover);\n outline-offset: 2px;\n border-radius: var(--oc-radius-sm);\n }\n\n /* ---------------------------------------------------------------------------\n * Keyboard focus indicators\n *\n * --oc-focus carries a light value in tokens.css and a dark value in\n * dark.css, so both rings stay visible in either mode.\n * --------------------------------------------------------------------------- */\n\n /* Container ring when the chart itself receives keyboard focus. */\n .oc-root:focus-visible {\n outline: 2px solid var(--oc-focus);\n outline-offset: 2px;\n }\n\n /* Mark ring during arrow-key navigation (see wireKeyboardNav). Outline on\n * SVG elements draws around the mark's bounding box, same technique as\n * .oc-editable-hover above. */\n .oc-mark-focused {\n outline: 2px solid var(--oc-focus);\n outline-offset: 1px;\n border-radius: var(--oc-radius-sm);\n }\n}\n","@layer oc.animation {\n /* ---------------------------------------------------------------------------\n * Animation keyframes\n * --------------------------------------------------------------------------- */\n\n /* Bar entrance: clip-path reveal bottom-to-top + fade in (vertical columns).\n Bars grow upward from baseline with a soft opacity fade. */\n @keyframes oc-enter-bar {\n from {\n clip-path: inset(100% 0 0 0);\n opacity: 0;\n }\n 75% {\n opacity: 1;\n }\n to {\n clip-path: inset(0 0 0 0);\n opacity: 1;\n }\n }\n\n /* Bar entrance: clip-path reveal left-to-right + fade in (horizontal bars).\n Bars grow rightward from axis with a soft opacity fade. */\n @keyframes oc-enter-bar-h {\n from {\n clip-path: inset(0 100% 0 0);\n opacity: 0;\n }\n 75% {\n opacity: 1;\n }\n to {\n clip-path: inset(0 0 0 0);\n opacity: 1;\n }\n }\n\n /* Line/area entrance: clip-path reveal left-to-right + fade in.\n Lines draw in following reading direction with a soft lead-in. */\n @keyframes oc-enter-line {\n from {\n clip-path: inset(0 100% 0 0);\n opacity: 0;\n }\n 15% {\n opacity: 1;\n }\n to {\n clip-path: inset(0 0 0 0);\n opacity: 1;\n }\n }\n\n /* Point/arc entrance: scale up + fade in from center */\n @keyframes oc-enter-point {\n from {\n opacity: 0;\n transform: scale(0.3);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n }\n\n /* Map feature entrance: fade in while transitioning fill from a neutral base\n to the data-driven color stored in --oc-feature-fill. The target opacity is\n --oc-feature-target-opacity (default 1) so features under a focus dim\n animate straight to their dimmed rest opacity instead of hitting 1 and then\n snapping down when the dim is applied post-animation.\n Non-interpolable fills (the url(#pattern) hatch on no-data features) do not\n transition: the browser holds the neutral and flips to the pattern when the\n eased progress passes 50%, so those features fade in rather than\n cross-fade. */\n @keyframes oc-enter-map-fill {\n from {\n fill: var(--oc-secondary);\n opacity: 0;\n }\n to {\n fill: var(--oc-feature-fill);\n opacity: var(--oc-feature-target-opacity, 1);\n }\n }\n\n /* Map point pop-in: gentle scale from 0.75 + fade. Uses transform-origin to\n scale from the circle's own center (cx/cy) rather than the SVG origin. */\n @keyframes oc-enter-map-point {\n from {\n opacity: 0;\n transform: scale(0.75);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n }\n\n /* Pure opacity fade (no transform). Safe for elements with existing transforms\n like arc groups that use translate() for positioning. */\n @keyframes oc-enter-fade-only {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n\n /* Fade + subtle slide up for text, rule, tick, annotations */\n @keyframes oc-enter-fade {\n from {\n opacity: 0;\n transform: translateY(4px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n /* Table row entrance: slide up only, no opacity (cells fade independently\n to avoid opacity compounding between row and cell animations) */\n @keyframes oc-table-enter-row {\n from {\n transform: translateY(6px);\n }\n to {\n transform: translateY(0);\n }\n }\n\n /* Table bar fill entrance: clip-path grow only, no opacity\n (preserves resting opacity: 0.15 from table.css) */\n @keyframes oc-table-enter-bar-fill {\n from {\n clip-path: inset(0 100% 0 0);\n }\n to {\n clip-path: inset(0 0 0 0);\n }\n }\n\n /* Live-tile pulse: the terminator dot of a sparkline swells once when new\n data lands, so a glance at a wall of tiles catches which one just moved.\n `r` is animated as a presentation attribute (SVG geometry properties are\n animatable in CSS); the fallback is simply no swell. */\n @keyframes oc-pulse {\n 0% {\n r: var(--oc-pulse-r, 4px);\n fill-opacity: 1;\n }\n 45% {\n r: calc(var(--oc-pulse-r, 4px) * 1.8);\n fill-opacity: 0.5;\n }\n 100% {\n r: var(--oc-pulse-r, 4px);\n fill-opacity: 1;\n }\n }\n\n /* Tooltip entrance */\n @keyframes oc-tooltip-in {\n from {\n opacity: 0;\n transform: translateY(2px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n}\n","@layer oc.animation {\n /* ---------------------------------------------------------------------------\n * Table entrance animations (.oc-table-wrapper.oc-animate)\n * --------------------------------------------------------------------------- */\n\n .oc-table-wrapper.oc-animate {\n /* Chrome (title/subtitle): fade + slide up */\n & > .oc-chrome {\n animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.6)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n }\n\n /* Table header: quick fade before rows start */\n & thead {\n animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.4)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n }\n\n /* Row entrance: slide up only, no opacity (cells handle their own fading\n to avoid opacity compounding between row and cell animations) */\n & tbody tr {\n animation: oc-table-enter-row var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-row-index, 0));\n }\n\n /* Cell text: fade in synced with row slide */\n & tbody td {\n animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.5)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-row-index, 0));\n }\n\n /* Heatmap/category cell backgrounds: longer fade, delayed after row appears */\n & td.oc-table-heatmap,\n & td.oc-table-category {\n animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.7)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(\n var(--oc-animation-stagger) *\n var(--oc-row-index, 0) +\n var(--oc-animation-duration) *\n 0.3\n );\n }\n\n /* Bar fill: clip-path grow only (no opacity change to preserve resting\n opacity: 0.15 from table.css) */\n & .oc-table-bar-fill {\n animation: oc-table-enter-bar-fill calc(var(--oc-animation-duration) * 0.8)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(\n var(--oc-animation-stagger) *\n var(--oc-row-index, 0) +\n var(--oc-animation-duration) *\n 0.3\n );\n }\n\n /* Sparkline SVG: clip-path reveal left-to-right. Targets the SVG directly\n (not the wrapper) to avoid clipping absolutely-positioned dots and labels. */\n & .oc-table-sparkline > svg {\n animation: oc-enter-line calc(var(--oc-animation-duration) * 0.8)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(\n var(--oc-animation-stagger) *\n var(--oc-row-index, 0) +\n var(--oc-animation-duration) *\n 0.4\n );\n }\n\n /* Sparkline dots and labels: fade in after the line draws through */\n & .oc-table-sparkline-dot,\n & .oc-table-sparkline-labels {\n animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.3)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(\n var(--oc-animation-stagger) *\n var(--oc-row-index, 0) +\n var(--oc-animation-duration) *\n 0.8\n );\n }\n\n /* Search and pagination: quick fade on mount */\n & .oc-table-search,\n & .oc-table-pagination {\n animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.5)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n }\n }\n}\n","@layer oc.components {\n /* ---------------------------------------------------------------------------\n * Chrome (eyebrow, title, subtitle, source, byline, footer, brand)\n * --------------------------------------------------------------------------- */\n\n .oc-chrome {\n font-family: var(--oc-font-family);\n }\n\n .oc-eyebrow {\n font-size: var(--oc-eyebrow-size);\n font-weight: var(--oc-eyebrow-weight);\n letter-spacing: var(--oc-eyebrow-tracking);\n text-transform: uppercase;\n fill: var(--oc-accent);\n }\n\n .oc-title {\n font-size: var(--oc-title-size);\n font-weight: var(--oc-title-weight);\n letter-spacing: var(--oc-title-tracking);\n fill: var(--oc-text);\n }\n\n .oc-subtitle {\n font-size: var(--oc-subtitle-size);\n font-weight: var(--oc-subtitle-weight);\n fill: var(--oc-text-muted);\n }\n\n .oc-source,\n .oc-byline,\n .oc-footer {\n font-size: var(--oc-source-size);\n font-weight: var(--oc-source-weight);\n fill: var(--oc-text-muted);\n }\n\n .oc-brand {\n font-size: 11px;\n font-weight: 500;\n letter-spacing: 0.02em;\n fill: var(--oc-text-faint);\n }\n\n .oc-eyebrow-dot {\n fill: var(--oc-accent);\n }\n\n /* ---------------------------------------------------------------------------\n * Metric bar (.oc-metrics) — optional row of label/value cells above chart\n * --------------------------------------------------------------------------- */\n\n .oc-metrics {\n font-family: var(--oc-font-family);\n }\n\n .oc-metric-label {\n font-size: 11px;\n font-weight: 500;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n fill: var(--oc-text-muted);\n }\n\n .oc-metric-value {\n font-size: 22px;\n font-weight: 600;\n letter-spacing: -0.02em;\n fill: var(--oc-text);\n font-variant-numeric: tabular-nums;\n }\n\n .oc-metric-delta-up {\n fill: var(--oc-positive);\n font-size: 12px;\n font-weight: 500;\n }\n\n .oc-metric-delta-down {\n fill: var(--oc-negative);\n font-size: 12px;\n font-weight: 500;\n }\n\n /* A multiplier or a run-rate is context, not a positive signal: the green\n that belonged here made every secondary read as good news. */\n .oc-metric-secondary {\n fill: var(--oc-text-muted);\n font-size: 12px;\n font-weight: 400;\n }\n\n /* ---------------------------------------------------------------------------\n * Axis tick labels — inline variant sits above each gridline at the\n * chart-area left edge (no left gutter). Used by line/area y-axes.\n * --------------------------------------------------------------------------- */\n\n .oc-axis-tick-inline {\n font-size: 11px;\n font-weight: 400;\n fill: var(--oc-text-muted);\n }\n\n /* ---------------------------------------------------------------------------\n * Endpoint labels (right-side per-series column for line/area charts)\n *\n * Swatch idiom: a thicker colored stroke segment with an optional thinner\n * lighter strip below. Mirrors the refreshed traditional legend swatch so a\n * single chart never shows two swatch idioms (mock-2 alignment). Per-series\n * color is stamped inline by the renderer; CSS tokens here cover the muted\n * value text and the leader line so theme overrides flow through naturally.\n * --------------------------------------------------------------------------- */\n\n .oc-endpoint-labels {\n font-family: var(--oc-font-family);\n }\n\n .oc-endpoint-label {\n /* Color set inline per series; this fallback only kicks in if the renderer\n ever omits the inline fill. */\n fill: var(--oc-endpoint-label-color, var(--oc-text));\n }\n\n .oc-endpoint-value {\n fill: var(--oc-endpoint-value-color, var(--oc-text-muted));\n }\n\n .oc-endpoint-leader {\n stroke: var(--oc-endpoint-leader-color, currentColor);\n }\n\n /* .oc-endpoint-marker — fill/stroke set inline (open-ring style: bg fill, series stroke). */\n /* .oc-endpoint-swatch — color set inline per series. */\n\n /* ---------------------------------------------------------------------------\n * Annotation dot + subtitle (text-annotation extensions)\n * --------------------------------------------------------------------------- */\n\n /* .oc-annotation-dot — fill/stroke resolved by the engine (open-ring default = bg fill, series stroke). */\n\n .oc-annotation-subtitle {\n fill: var(--oc-annotation-subtitle-color, var(--oc-text-muted));\n }\n\n /* ---------------------------------------------------------------------------\n * Table footer chrome\n * --------------------------------------------------------------------------- */\n\n /* Footer row: source/footer text on the left, brand watermark on the right,\n * sharing a single baseline. gap keeps them apart if the row gets narrow. */\n .oc-table-footer-row {\n display: flex;\n align-items: baseline;\n gap: 16px;\n padding: 16px 16px 4px;\n }\n\n /* Chrome block sits inside the flex row now, so it no longer owns the\n * footer's top padding or horizontal inset (the row provides both). */\n .oc-chrome-footer {\n padding-top: 0;\n }\n\n /* Brand watermark: pushed to the right edge (margin-left:auto holds it there\n * even when the source text is absent), never shrinks below its own text. */\n .oc-table-footer-row .oc-table-ref {\n margin-left: auto;\n flex-shrink: 0;\n text-align: right;\n }\n}\n","@layer oc.animation {\n /* ---------------------------------------------------------------------------\n * Animation scoped rules (.oc-animate enables animation on the chart root)\n * --------------------------------------------------------------------------- */\n\n .oc-animate {\n /* Vertical bars (default): smooth ease-out, no overshoot.\n oc-mark-bar is reserved for future mark type aliases.\n A bar with a value-end radius draws as <path> rather than <rect>\n (SVG rx rounds all four corners or none), so both shapes match. */\n & .oc-mark-rect :is(rect, path),\n & .oc-mark-bar :is(rect, path) {\n animation: oc-enter-bar var(--oc-animation-duration) var(--oc-ease-smooth) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));\n }\n\n /* Horizontal bars (data-orient is on the mark group, not the SVG root) */\n & .oc-mark-rect[data-orient=\"horizontal\"] :is(rect, path),\n & .oc-mark-bar[data-orient=\"horizontal\"] :is(rect, path) {\n animation-name: oc-enter-bar-h;\n }\n\n /* Stacked bar/column segments: chain sequentially so each segment starts\n right when the previous one finishes, creating one fluid reveal.\n Uses linear easing so handoffs between segments are seamless (no\n deceleration/acceleration stutter at segment boundaries). */\n & .oc-mark-rect[data-stack-pos] :is(rect, path) {\n animation-duration: var(--oc-stack-segment-duration, 150ms);\n animation-timing-function: linear;\n animation-delay: calc(\n var(--oc-animation-stagger) *\n var(--oc-mark-index, 0) +\n var(--oc-stack-pos, 0) *\n var(--oc-stack-segment-duration, 150ms)\n );\n }\n\n /* Line marks: entire group clips left-to-right (no WAAPI needed) */\n & .oc-mark-line {\n animation: oc-enter-line var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));\n }\n\n /* Area marks: entire group clips left-to-right + fades in */\n & .oc-mark-area {\n animation: oc-enter-line var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));\n }\n\n /* Arc marks (pie/donut slices): simple fade in.\n Scale transforms break arc positioning because arcs use translate()\n on parent groups. A clean fade is more elegant for pie/donut anyway. */\n & .oc-mark-arc {\n animation: oc-enter-fade-only var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));\n }\n\n /* Point marks (scatter, dot).\n Points render as bare <circle> elements with class oc-mark-point directly,\n not wrapped in a group, so we target circle.oc-mark-point (not descendant).\n Duration is 40% of the configured duration (quick pop-in relative to other marks). */\n & circle.oc-mark-point,\n & circle.oc-mark-circle {\n animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.4)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));\n }\n\n /* Points on line/area charts: delay so they pop in as the line draws through. */\n & .oc-mark-line ~ circle.oc-mark-point,\n & .oc-mark-area ~ circle.oc-mark-point {\n animation-delay: calc(\n var(--oc-animation-duration) *\n 0.35 +\n var(--oc-animation-stagger) *\n var(--oc-mark-index, 0)\n );\n }\n\n /* Text marks: fade + slight slide up */\n & .oc-mark-text text {\n animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.6)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));\n }\n\n /* Rule marks: fade in */\n & .oc-mark-rule line {\n animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.5)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));\n }\n\n /* Tick marks: fade in */\n & .oc-mark-tick line {\n animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.5)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));\n }\n\n /* Data labels: fade after their parent mark */\n & .oc-mark-label {\n animation: oc-enter-fade 250ms var(--oc-ease-smooth) both;\n animation-delay: calc(\n var(--oc-animation-stagger) *\n var(--oc-mark-index, 0) +\n var(--oc-animation-duration) *\n 0.7\n );\n }\n\n /* Annotations: fade in after marks finish */\n & .oc-annotation {\n animation: oc-enter-fade 300ms var(--oc-ease-smooth) both;\n animation-delay: calc(var(--oc-animation-duration) + var(--oc-annotation-delay, 150ms));\n }\n\n /* Tilemap tiles: fade in with jittered stagger for organic feel.\n Per-tile delay is computed in the renderer with pseudo-random variation. */\n & .oc-tilemap-tile {\n animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.35) ease-in both;\n animation-delay: var(--oc-tile-delay, 0ms);\n }\n\n /* Map features: fill color reveal with shuffled stagger.\n Per-feature --oc-map-delay is computed in the renderer via a seeded\n Fisher-Yates shuffle so features pop in organically. */\n & .oc-map-feature {\n animation: oc-enter-map-fill var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: var(--oc-map-delay, 0ms);\n }\n\n /* Bulk mode: high feature counts (counties, ~3k+) get a single group\n fade instead of per-feature fill animations. opacity is GPU-compositable\n so this stays smooth regardless of child count. */\n & .oc-map-features[data-bulk-animate] {\n animation: oc-enter-fade-only var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n }\n\n & .oc-map-features[data-bulk-animate] .oc-map-feature {\n animation: none;\n }\n\n /* Map borders: fade in near the end of the feature sweep */\n & .oc-map-borders path {\n animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.4) ease-in both;\n animation-delay: calc(var(--oc-animation-duration) * 0.7);\n }\n\n /* Map points: gentle scale (0.75->1) + fade pop-in after borders.\n transform-origin set per-circle in the renderer so scale happens\n around each circle's own center, not the SVG origin. */\n & .oc-map-point {\n animation: oc-enter-map-point calc(var(--oc-animation-duration) * 0.4)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(\n var(--oc-animation-duration) *\n 0.8 +\n var(--oc-mark-index, 0) *\n var(--oc-point-stagger, 60ms)\n );\n }\n\n /* Sankey nodes: fade in with stagger by column depth (left-to-right) */\n & .oc-sankey-node rect {\n animation: oc-enter-fade-only var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));\n }\n\n /* Sankey links: fade in after nodes, with stagger.\n Links delay by 30% of duration so nodes appear first, then links flow in. */\n & .oc-sankey-link path {\n animation: oc-enter-fade-only var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(\n var(--oc-animation-duration) *\n 0.3 +\n var(--oc-animation-stagger) *\n var(--oc-mark-index, 0)\n );\n }\n\n /* Barlist rows: fade + slide up per row, bars grow left-to-right */\n & .oc-barlist-row {\n animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.6)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: var(--oc-row-delay, 0ms);\n }\n\n & .oc-barlist-bar {\n animation: oc-enter-bar-h var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: var(--oc-row-delay, 0ms);\n }\n }\n\n /* ---------------------------------------------------------------------------\n * Sparkline mode: pair the line/area reveal with a stronger ease-out so it\n * doesn't read as a uniform left-to-right swipe. cubic-bezier(0.16, 1, 0.3, 1)\n * is \"expo-out\" — fast initial draw that decelerates noticeably at the end,\n * giving the trend a hand-drawn feel. Duration is bumped via the engine\n * (compile.ts) so the cleanup timer stays in sync.\n * --------------------------------------------------------------------------- */\n\n .oc-animate[data-display=\"sparkline\"] .oc-mark-line,\n .oc-animate[data-display=\"sparkline\"] .oc-mark-area {\n animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);\n }\n}\n","@layer oc.components {\n /* ---------------------------------------------------------------------------\n * Graph\n * --------------------------------------------------------------------------- */\n\n .oc-graph-wrapper {\n position: relative;\n overflow: hidden;\n background: var(--oc-bg);\n font-family: var(--oc-font-family);\n width: 100%;\n height: 100%;\n }\n\n .oc-graph-canvas {\n display: block;\n width: 100%;\n height: 100%;\n cursor: grab;\n }\n\n .oc-graph-canvas--dragging {\n cursor: grabbing;\n }\n\n /* 3D surface. 3d-force-graph builds its own `div.scene-container` inside the\n * element it is handed and sizes the WebGL canvas imperatively, so the slot\n * has to fill the same box the 2D canvas fills or the first measurement is\n * zero-height. */\n .oc-graph-3d,\n .oc-graph-3d .scene-container {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n .oc-graph-3d {\n cursor: grab;\n }\n\n .oc-graph-3d .scene-container canvas {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n .oc-graph-chrome {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n z-index: 2;\n padding: 16px 16px 8px;\n pointer-events: none;\n\n & .oc-title {\n font-size: var(--oc-title-size);\n font-weight: var(--oc-title-weight);\n letter-spacing: var(--oc-title-tracking);\n color: var(--oc-text);\n margin: 0 0 4px;\n --_stroke: color-mix(in srgb, var(--oc-bg) 80%, transparent);\n text-shadow:\n -2px -2px 0 var(--_stroke),\n 2px -2px 0 var(--_stroke),\n -2px 2px 0 var(--_stroke),\n 2px 2px 0 var(--_stroke),\n 0 -2px 0 var(--_stroke),\n 0 2px 0 var(--_stroke),\n -2px 0 0 var(--_stroke),\n 2px 0 0 var(--_stroke);\n }\n\n & .oc-subtitle {\n font-size: var(--oc-subtitle-size);\n color: var(--oc-text-secondary);\n margin: 0;\n --_stroke: color-mix(in srgb, var(--oc-bg) 80%, transparent);\n text-shadow:\n -1px -1px 0 var(--_stroke),\n 1px -1px 0 var(--_stroke),\n -1px 1px 0 var(--_stroke),\n 1px 1px 0 var(--_stroke);\n }\n }\n\n .oc-graph-legend {\n position: absolute;\n top: 12px;\n right: 12px;\n /* Slightly translucent so the graph reads as continuous underneath, in\n * whatever surface the mount stamped on the wrapper. */\n background: color-mix(in srgb, var(--oc-bg) 88%, transparent);\n border: 1px solid var(--oc-border);\n border-radius: var(--oc-radius-lg);\n padding: 8px 12px;\n font-size: 12px;\n color: var(--oc-text-secondary);\n max-height: 200px;\n overflow-y: auto;\n }\n\n .oc-graph-legend-item {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 2px 0;\n /* Button reset for interactive rows (rendered as <button>). */\n width: 100%;\n margin: 0;\n background: none;\n border: none;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: default;\n }\n\n /* Interactive legend rows are buttons; give them affordance + a focus ring. */\n button.oc-graph-legend-item {\n cursor: pointer;\n border-radius: var(--oc-radius-sm);\n\n &:hover {\n background: var(--oc-focus-ring);\n }\n\n &:focus-visible {\n outline: 2px solid var(--oc-focus);\n outline-offset: 1px;\n }\n }\n\n /* De-emphasized (toggled-off) category. */\n .oc-graph-legend-item--inactive {\n opacity: 0.45;\n }\n\n .oc-graph-legend-label {\n flex: 1 1 auto;\n }\n\n .oc-graph-legend-count {\n color: var(--oc-text-secondary);\n font-variant-numeric: tabular-nums;\n margin-left: auto;\n padding-left: 8px;\n }\n\n .oc-graph-legend-swatch {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n /* Edge-legend swatches render as a short line, not a dot. */\n .oc-graph-legend-swatch--line {\n width: 12px;\n height: 3px;\n border-radius: 1px;\n }\n\n .oc-graph-search {\n position: absolute;\n top: 12px;\n left: 12px;\n\n & input {\n font-family: var(--oc-font-family);\n font-size: var(--oc-body-size);\n padding: 6px 10px;\n border: 1px solid var(--oc-border);\n border-radius: var(--oc-radius-md);\n background: color-mix(in srgb, var(--oc-bg) 88%, transparent);\n color: var(--oc-text);\n outline: none;\n\n &:focus {\n border-color: var(--oc-focus);\n box-shadow: 0 0 0 2px var(--oc-focus-ring-strong);\n }\n }\n }\n\n /*\n * No dark-mode canvas override lives here. graph-mount stamps the resolved\n * theme surface on the wrapper (--oc-bg), so dark graphs sit on the same\n * --oc-bg the rest of the library uses instead of a private GitHub-dark hex,\n * and the legend/search panels mix against whatever that surface is.\n */\n}\n","@layer oc.components {\n /* ---------------------------------------------------------------------------\n * Tooltip\n * Editorial card matching the new design system: zinc surface, cyan accent,\n * Inter Variable, mono numerics. Sized for a slice tooltip that lists every\n * series at the snapped x.\n * --------------------------------------------------------------------------- */\n\n .oc-tooltip {\n position: absolute;\n display: none;\n pointer-events: none;\n z-index: 1000;\n background: var(--oc-tooltip-bg);\n backdrop-filter: blur(14px);\n border: 1px solid var(--oc-tooltip-border);\n border-radius: var(--oc-radius-lg);\n box-shadow: var(--oc-tooltip-shadow);\n color: var(--oc-tooltip-text);\n font-family: var(--oc-font-family);\n font-size: 12px;\n padding: 0;\n max-width: 280px;\n min-width: 140px;\n line-height: 1.4;\n animation: oc-tooltip-in 120ms ease-out;\n transition:\n left 100ms ease-in-out,\n top 100ms ease-in-out;\n\n & .oc-tooltip-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px 6px;\n }\n\n & .oc-tooltip-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n & .oc-tooltip-title {\n font-weight: 600;\n font-size: 11px;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--oc-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n & .oc-tooltip-body {\n padding: 6px 10px 8px;\n border-top: 1px solid var(--oc-tooltip-border);\n }\n\n /* No separator when body is the only child */\n & .oc-tooltip-body:first-child {\n border-top: none;\n padding-top: 10px;\n }\n\n & .oc-tooltip-row {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 16px;\n padding: 2px 0;\n }\n\n & .oc-tooltip-row-swatch {\n display: inline-block;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n margin-right: 6px;\n flex-shrink: 0;\n transform: translateY(-1px);\n }\n\n & .oc-tooltip-label {\n color: var(--oc-text-secondary);\n font-size: 12px;\n font-weight: 400;\n white-space: nowrap;\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n }\n\n & .oc-tooltip-value {\n font-weight: 500;\n font-size: 12px;\n font-variant-numeric: tabular-nums;\n color: var(--oc-tooltip-text);\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n /* The series the pointer is nearest to in a shared tooltip. */\n & .oc-tooltip-row--emphasis .oc-tooltip-label {\n color: var(--oc-tooltip-text);\n font-weight: 600;\n }\n\n & .oc-tooltip-row--emphasis .oc-tooltip-value {\n font-weight: 600;\n }\n\n /* Stack sum, set below a hairline so it reads as a summary of the rows\n * above rather than one more series. */\n & .oc-tooltip-row--total {\n margin-top: 4px;\n padding-top: 5px;\n border-top: 1px solid var(--oc-tooltip-border);\n }\n\n & .oc-tooltip-row--total .oc-tooltip-label {\n color: var(--oc-tooltip-text);\n font-weight: 500;\n }\n\n & .oc-tooltip-row--total .oc-tooltip-value {\n font-weight: 600;\n }\n }\n\n /* ---------------------------------------------------------------------------\n * Crosshair guideline + per-series snap dots (line/area charts)\n * Animate the snap between adjacent points so the indicator slides instead\n * of jumping. ~50ms ease-in-out keeps the motion crisp without lagging.\n * --------------------------------------------------------------------------- */\n\n .oc-crosshair {\n pointer-events: none;\n transition:\n x1 50ms ease-in-out,\n x2 50ms ease-in-out;\n }\n\n .oc-snap-dots circle {\n pointer-events: none;\n transition:\n cx 50ms ease-in-out,\n cy 50ms ease-in-out;\n }\n}\n","/* ---------------------------------------------------------------------------\n * Reduced motion\n *\n * Catch-all: last-declared layer beats every earlier layer regardless of\n * specificity. No !important, no hand-maintained selector mirror.\n *\n * Selector list matches CSS_TOKEN_ROOT_SELECTORS in token-definitions.ts.\n * --------------------------------------------------------------------------- */\n\n@layer oc.reduced-motion {\n @media (prefers-reduced-motion: reduce) {\n :is(\n .oc-root,\n .oc-chart-root,\n .oc-table-wrapper,\n .oc-table-root,\n .oc-graph-wrapper,\n .oc-graph-root,\n .oc-sankey-root,\n .oc-tilemap-root,\n .oc-barlist-root,\n .oc-map-root\n ),\n :is(\n .oc-root,\n .oc-chart-root,\n .oc-table-wrapper,\n .oc-table-root,\n .oc-graph-wrapper,\n .oc-graph-root,\n .oc-sankey-root,\n .oc-tilemap-root,\n .oc-barlist-root,\n .oc-map-root\n )\n *,\n :is(\n .oc-root,\n .oc-chart-root,\n .oc-table-wrapper,\n .oc-table-root,\n .oc-graph-wrapper,\n .oc-graph-root,\n .oc-sankey-root,\n .oc-tilemap-root,\n .oc-barlist-root,\n .oc-map-root\n )\n *::before,\n :is(\n .oc-root,\n .oc-chart-root,\n .oc-table-wrapper,\n .oc-table-root,\n .oc-graph-wrapper,\n .oc-graph-root,\n .oc-sankey-root,\n .oc-tilemap-root,\n .oc-barlist-root,\n .oc-map-root\n )\n *::after {\n animation: none;\n transition: none;\n }\n }\n}\n","@layer oc.components {\n /* ---------------------------------------------------------------------------\n * Legend\n * --------------------------------------------------------------------------- */\n\n /* Font size and text fill are set inline by the renderer's applyTextStyle\n * from the engine-computed legend layout, which is authoritative (11px).\n * Only the family, which nothing computes per-entry, lives here. */\n .oc-legend {\n font-family: var(--oc-font-family);\n }\n\n .oc-legend-entry {\n cursor: default;\n }\n}\n","@layer oc.components {\n /* ---------------------------------------------------------------------------\n * Series search (seriesSearch)\n *\n * DOM combobox overlaid on the SVG band the engine reserves below chrome.\n * The wrapper is absolutely positioned by the vanilla adapter (inline\n * left/top/width/height), so everything here is visual only. All colors come\n * from --oc-* tokens, which flip in .oc-dark.\n * --------------------------------------------------------------------------- */\n\n .oc-series-search {\n position: absolute;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 8px;\n font-family: var(--oc-font-family);\n z-index: 10;\n }\n\n /* Chips: removable filter tokens for the current selection. They flow to the\n * left of the input and scroll horizontally rather than wrapping over the\n * chart when a reader picks many series. */\n .oc-series-search-chips {\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n .oc-series-search-chips::-webkit-scrollbar {\n display: none;\n }\n\n .oc-series-search-chip {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 4px 3px 10px;\n border: 1px solid var(--oc-border);\n border-radius: var(--oc-radius-full);\n background: var(--oc-secondary);\n color: var(--oc-text-secondary);\n font-size: 12px;\n font-weight: 500;\n line-height: 16px;\n white-space: nowrap;\n }\n\n .oc-series-search-chip-remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n /* 16px glyph, but a >=24px hit area (WCAG 2.5.5 target size) via padding\n pulled back with negative margin so the chip layout stays tight. */\n width: 16px;\n height: 16px;\n padding: 4px;\n margin: -4px -2px -4px -4px;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: var(--oc-text-muted);\n cursor: pointer;\n transition:\n color 0.15s,\n background-color 0.15s;\n }\n\n .oc-series-search-chip-remove:hover {\n color: var(--oc-text);\n background: var(--oc-hover-bg);\n }\n\n .oc-series-search-chip-remove:focus-visible {\n outline: 2px solid var(--oc-focus);\n outline-offset: 1px;\n }\n\n .oc-series-search-chip-remove svg {\n display: block;\n }\n\n /* Combobox: input + popup listbox. Styling matches the table search input\n * (border, radius, focus ring) so the two search surfaces read as one system. */\n .oc-series-search-box {\n position: relative;\n flex: 0 1 220px;\n min-width: 120px;\n }\n\n .oc-series-search-icon {\n position: absolute;\n left: 9px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--oc-text-muted);\n pointer-events: none;\n }\n\n /* Shared skin provided by the grouped rule in table.css.\n Only divergent props live here. */\n .oc-series-search-input {\n height: 32px;\n padding: 0 10px 0 28px;\n }\n\n .oc-series-search-listbox {\n position: absolute;\n top: calc(100% + 4px);\n right: 0;\n min-width: 100%;\n max-height: 240px;\n overflow-y: auto;\n margin: 0;\n padding: 4px;\n list-style: none;\n border: 1px solid var(--oc-border);\n border-radius: var(--oc-radius-lg);\n background: var(--oc-card);\n box-shadow: var(--oc-tooltip-shadow);\n z-index: 20;\n }\n\n .oc-series-search-option {\n padding: 6px 10px;\n border-radius: var(--oc-radius-sm);\n font-size: 13px;\n color: var(--oc-text);\n cursor: pointer;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .oc-series-search-option[aria-selected=\"true\"],\n .oc-series-search-option:hover {\n background: var(--oc-hover-bg);\n }\n\n /* The typed substring within each suggestion. */\n .oc-series-search-match {\n font-weight: 600;\n }\n\n .oc-series-search-empty {\n padding: 6px 10px;\n font-size: 12px;\n color: var(--oc-text-muted);\n }\n}\n","@layer oc.components {\n /* ---------------------------------------------------------------------------\n * Hover language\n *\n * One vocabulary for mark hover, legend hover and the crosshair. Emphasis is\n * always a CLASS, never an inline style: a class beats the renderer's\n * `opacity` attributes (suppressed points under endpoint markers keep their\n * opacity=\"0\") and loses to the transition driver's per-frame inline\n * `style.opacity`, which is exactly the precedence a hover during a data\n * update needs.\n * --------------------------------------------------------------------------- */\n\n .oc-marks.oc-hover-active .oc-mark--dim:not([opacity=\"0\"]) {\n opacity: var(--oc-hover-dim);\n }\n\n /* Single-series register: outline the hovered mark instead of dimming eleven\n * others. Scoped per mark type -- an inherited stroke on a line or area group\n * would repaint the series in the text color. */\n .oc-marks.oc-hover-active .oc-mark-rect.oc-mark--hover > *,\n .oc-marks.oc-hover-active .oc-mark-arc.oc-mark--hover > *,\n .oc-marks.oc-hover-active circle.oc-mark-point.oc-mark--hover {\n stroke: var(--oc-text);\n stroke-width: 1;\n }\n\n /* The fade is switched off while the rAF transition driver owns opacity: an\n * unscoped 140ms transition would smear every frame of an update tween.\n * `.oc-animate` is excluded for the same reason during the entrance.\n *\n * It is NOT scoped to `.oc-hover-active`: dropping the class on mouseleave\n * would drop the transition with it, so the dim faded in and snapped back. */\n .oc-chart:not(.oc-animate):not(.oc-transitioning) .oc-marks .oc-mark {\n transition: opacity var(--oc-hover-duration) ease-out;\n }\n\n /* ---------------------------------------------------------------------------\n * Legend hover-link\n *\n * The swatch dims; the label text stays at full contrast so the list is still\n * readable while one series is raised.\n * --------------------------------------------------------------------------- */\n\n .oc-legend-entry--dim .oc-legend-swatch-line,\n .oc-legend-entry--dim .oc-legend-swatch-rect,\n .oc-legend-entry--dim > circle {\n opacity: var(--oc-hover-dim);\n transition: opacity var(--oc-hover-duration) ease-out;\n }\n\n .oc-legend-hit {\n fill: transparent;\n }\n\n .oc-legend-entry:focus {\n outline: none;\n }\n\n /* Focus ring on the 24px hit rect, drawn as a stroke: `outline` on an SVG\n * group is inconsistent across browsers, a stroke is not. */\n .oc-legend-entry:focus-visible .oc-legend-hit {\n stroke: var(--oc-focus);\n stroke-width: 2;\n }\n\n /* ---------------------------------------------------------------------------\n * Endpoint-label hover-link\n * --------------------------------------------------------------------------- */\n\n .oc-endpoint-label-entry {\n cursor: default;\n }\n\n /* ---------------------------------------------------------------------------\n * Map hover\n *\n * Feature hover is outline + raise, never dim-the-rest: toggling opacity on\n * three thousand county paths every time the pointer crosses a border is a\n * repaint storm, and the wave of fades reads as a flicker. Datawrapper and the\n * FT outline too. `non-scaling-stroke` keeps the outline 1.5px through the\n * camera's zoom transform, which otherwise scales stroke width with geometry.\n * --------------------------------------------------------------------------- */\n\n .oc-map-feature--hover {\n stroke: var(--oc-text);\n stroke-width: 1.5;\n vector-effect: non-scaling-stroke;\n }\n\n /* Legend-bin hover IS where dim-the-rest belongs: pointing at one class is a\n * deliberate \"show me these\" gesture, and the answer is the set of features in\n * that class. Static rules per class index keep it to one attribute write on\n * the group rather than a class toggle per feature. */\n .oc-map-features[data-hover] .oc-map-feature {\n transition: opacity var(--oc-hover-duration) ease-out;\n }\n\n .oc-map-features[data-hover=\"0\"] .oc-map-feature:not([data-bin-index=\"0\"]),\n .oc-map-features[data-hover=\"1\"] .oc-map-feature:not([data-bin-index=\"1\"]),\n .oc-map-features[data-hover=\"2\"] .oc-map-feature:not([data-bin-index=\"2\"]),\n .oc-map-features[data-hover=\"3\"] .oc-map-feature:not([data-bin-index=\"3\"]),\n .oc-map-features[data-hover=\"4\"] .oc-map-feature:not([data-bin-index=\"4\"]),\n .oc-map-features[data-hover=\"5\"] .oc-map-feature:not([data-bin-index=\"5\"]),\n .oc-map-features[data-hover=\"6\"] .oc-map-feature:not([data-bin-index=\"6\"]),\n .oc-map-features[data-hover=\"7\"] .oc-map-feature:not([data-bin-index=\"7\"]),\n .oc-map-features[data-hover=\"8\"] .oc-map-feature:not([data-bin-index=\"8\"]),\n .oc-map-features[data-hover=\"9\"] .oc-map-feature:not([data-bin-index=\"9\"]),\n .oc-map-features[data-hover=\"10\"] .oc-map-feature:not([data-bin-index=\"10\"]),\n .oc-map-features[data-hover=\"11\"] .oc-map-feature:not([data-bin-index=\"11\"]) {\n opacity: var(--oc-map-hover-dim);\n }\n\n .oc-legend-bin {\n cursor: default;\n }\n\n /* ---------------------------------------------------------------------------\n * Tile hover\n *\n * A tile grid is 51 rects, not 3000 paths, and every tile is the same size --\n * so here the full hover language applies: the hovered tile takes an outline\n * and the rest drop back.\n * --------------------------------------------------------------------------- */\n\n .oc-tilemap-tiles.oc-hover-active .oc-tilemap-tile {\n transition: opacity var(--oc-hover-duration) ease-out;\n }\n\n .oc-tilemap-tiles.oc-hover-active .oc-tilemap-tile:not(.oc-tilemap-tile--hover) {\n opacity: var(--oc-hover-dim);\n }\n\n .oc-tilemap-tile--hover > rect {\n stroke: var(--oc-text);\n stroke-width: 1.5;\n }\n}\n"],"names":[]}
|
|
1
|
+
{"version":3,"mappings":"AAWA,iBCEE,mzEGFA,6lBJAF,eQNE,mIAeA,6BAQA,uGAWA,yDAOA,iGAMA,qCAWA,8IAgBA,qHAcA,4EAQA,yGR1FF,qBWNE,6CAIA,2KAQA,wIAOA,+GAMA,+HAQA,wFAOA,sCAQA,8CAIA,wHAQA,4HAQA,2EAMA,6EAQA,8EAWA,8EAgBA,sDAIA,sEAMA,4EAIA,wEAaA,sFAUA,sFASA,gCAMA,mFI9JA,4fAsBE,4FAOA,iFAOA,gMAWA,gGAMA,0EAKA,mHAQA,yJAUA,oKAUA,uMAYA,qGAKA,wEAMA,gHAMA,kGAKA,qEAWF,qFAOA,4FD1IA,6CAIA,gCGAA,uFAOA,sNAaA,0HAWA,wMAOA,gCAIA,oCAMA,sFASA,wCAcA,iGAUA,kGAIA,w6BAeA,8BAYA,wGAIA,4GAIA,sEC1HA,kJAaA,iHASA,wDAIA,sSAeA,6RAoBA,uFAKA,iGAKA,gDAMA,qEAMA,oIAWA,0DAKA,2SAiBA,yLAWA,0GAMA,wCAIA,mFhBtIA,kDAKA,+CAKA,qGASA,wHAUA,yGAWA,qFAKA,0MAYA,oSAeA,6DAKA,iGAWA,2aAsBA,0CAIA,qFAKA,yFAAA,wFAMA,yDIrIA,iGAKE,qFAMA,yDAIA,4DAKA,uIAAA,uIAcA,kLAUA,gFASA,mDAIA,sEAKA,iFAKA,2CAKF,sNAOA,kPAOA,2IAKA,gJAKA,iCASE,0FAAA,0FAaF,oLAYE,mLAAA,kLAaA,yFAKA,qFAKA,4CAAA,2CAOA,+FAKA,6DAMA,4FAKA,+DAaF,iQAaA,wFAAA,8EAAA,yFAAA,+EAMA,+IAOA,+BAGE,wCASF,oJAQE,6PAaE,oEAKA,2GAKA,+FAOJ,4DAIA,+CASA,gCAIA,iIAUA,gDASA,+DAKE,kEAOF,iFAOA,mGAWA,2DAIE,qCAKF,8CAQA,+BAaE,iGAAA,iGAOA,+DAIA,mFAOA,yDAAA,yDAMA,2DAUF,wGAQA,sLAWA,mDAKA,sFAKA,sFAKA,kHAMA,qLAYA,oEAWA,gFAME,iGAiBA,oDAIA,0CAIA,sHASA,kLAAA,kLAaA,iIAUA,0LAYA,uDAKA,uGAOA,2DAIA,oDAIA,gDAUA,6CAIA,kEASF,2EASA,oHAWE,uDAIA,0CAGA,+EAAA,+EAMA,+FAMA,qLAUA,yDAGA,0GAOA,kDAGA,wDAIA,qEAIA,sCGtoBF,qIASA,kEAOA,2CAQA,gFAOA,yBAIA,0EAMA,4GASE,8bAkBA,2RAaF,wRAgBA,qLAiBA,6EAIE,kEAIA,+FAOF,4CAIA,iCAIA,0HAOA,+EAQA,sEAMA,sDAKE,2QAUE,2GGrKJ,2GAIA,8IAOA,oGTfA,6DAMA,+UAeA,iSAiBE,gFAIA,sEAIA,qFAKA,qDAOF,yeAoBE,0CAMF,2BAIA,2EAKA,oCAKA,iCIjGA,mEAYA,4EAIA,uCACE,6DPhBJ,oBKJI,4JAMA,4JAOA,8NAOA,yOAOA,wRAAA,yRAcA,4RAaA,uRAYA,4RAAA,+RAaA,uKAAA,2KK/EF,8GAgBA,kHAgBA,iHAeA,4FAoBA,8IAaA,iGAaA,yDAUA,sGAaA,uFAWA,yFAaA,iKAgBA,sGGzJE,4NAAA,2NAQA,+FAAA,8FASA,8RAWA,qIAIA,mFAGA,yEAKA,8MAOA,8MASA,kNAUA,qOAAA,sOAQA,+JAAA,+JAWA,8NAOA,8NAOA,8NAOA,kMAWA,uKAOA,wJAQA,gLASA,8JAKA,+EAKA,2KAQA,mQAYA,0NAQA,8PAYA,uLAMA,6KAeF,wJbnNF,yBgBDE,uCACE,6LAAA,+LAAA,qMAAA","sources":["../src/styles/index.css","../src/styles/tokens.css","../src/styles/you-draw-it.css","../src/styles/map-zoom.css","../src/styles/dark.css","../src/styles/table-animation.css","../src/styles/table.css","../src/styles/sparkline.css","../src/styles/base.css","../src/styles/graph.css","../src/styles/keyframes.css","../src/styles/chrome.css","../src/styles/sankey.css","../src/styles/animation.css","../src/styles/legend.css","../src/styles/interaction.css","../src/styles/reduced-motion.css","../src/styles/series-search.css","../src/styles/tooltip.css"],"sourcesContent":["/**\n * @opendata-ai/openchart-core styles\n *\n * CSS with oc- prefix for all class names.\n * CSS custom properties for theme overrides.\n * Dark mode via .oc-dark class on the container.\n * Cascade layers: oc.tokens, oc.base, oc.components, oc.animation, oc.reduced-motion.\n */\n\n/* For optimal typography, load Inter: https://fonts.google.com/specimen/Inter */\n\n@layer oc.tokens, oc.base, oc.components, oc.animation, oc.reduced-motion;\n\n@import \"./tokens.css\";\n@import \"./dark.css\";\n@import \"./base.css\";\n@import \"./chrome.css\";\n@import \"./tooltip.css\";\n@import \"./legend.css\";\n@import \"./interaction.css\";\n@import \"./series-search.css\";\n@import \"./you-draw-it.css\";\n@import \"./table.css\";\n@import \"./table-animation.css\";\n@import \"./graph.css\";\n@import \"./sankey.css\";\n@import \"./map-zoom.css\";\n@import \"./sparkline.css\";\n@import \"./keyframes.css\";\n@import \"./animation.css\";\n@import \"./reduced-motion.css\";\n","/* GENERATED FILE — do not edit. Source: packages/core/src/styles/token-definitions.ts. Regenerate: bun run generate:tokens */\n\n@layer oc.tokens {\n /* ---------------------------------------------------------------------------\n * Custom properties (light mode defaults)\n *\n * These are FALLBACK defaults. At runtime, the JS theme engine stamps the\n * resolved theme as inline --oc-* custom properties on each .oc-root\n * container (see packages/vanilla/src/theme-tokens.ts). These CSS values\n * serve as fallbacks for contexts where JS hasn't mounted yet (SSR, static\n * HTML examples).\n * --------------------------------------------------------------------------- */\n\n .oc-root,\n .oc-chart-root,\n .oc-table-wrapper,\n .oc-table-root,\n .oc-graph-wrapper,\n .oc-graph-root,\n .oc-sankey-root,\n .oc-tilemap-root,\n .oc-barlist-root,\n .oc-map-root {\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n\n /* Opt out of iOS text auto-inflation so measured widths match rendered text. */\n -webkit-text-size-adjust: 100%;\n text-size-adjust: 100%;\n\n --oc-font-family:\n \"Inter Variable\", Inter, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n --oc-font-mono: \"JetBrains Mono\", \"Fira Code\", \"Cascadia Code\", monospace;\n\n /* Animation easing presets via CSS linear() */\n --oc-ease-smooth: linear(\n 0,\n 0.157,\n 0.438,\n 0.64,\n 0.766,\n 0.85,\n 0.906,\n 0.941,\n 0.964,\n 0.978,\n 0.988,\n 0.994,\n 0.998,\n 1\n );\n --oc-ease-snappy: linear(\n 0,\n 0.012,\n 0.048,\n 0.108,\n 0.194,\n 0.302,\n 0.426,\n 0.559,\n 0.69,\n 0.808,\n 0.905,\n 0.973,\n 1.013,\n 1.028,\n 1.023,\n 1.006,\n 0.984,\n 0.966,\n 0.957,\n 0.957,\n 0.964,\n 0.975,\n 0.986,\n 0.995,\n 1,\n 1.003,\n 1.002,\n 1,\n 0.998,\n 0.998,\n 0.999,\n 1\n );\n\n /* Animation timing defaults */\n --oc-animation-duration: 450ms;\n --oc-animation-stagger: 30ms;\n --oc-annotation-delay: 150ms;\n\n /* Typography scale (editorial design system) */\n --oc-title-size: 26px;\n --oc-title-weight: 600; /* one ladder: 400 regular / 500 medium / 600 semibold / 700 bold */\n --oc-title-tracking: -0.022em;\n --oc-subtitle-size: 14px;\n --oc-subtitle-weight: 400;\n --oc-source-size: 11px;\n --oc-source-weight: 400;\n --oc-body-size: 13px;\n --oc-eyebrow-size: 11px;\n --oc-eyebrow-weight: 500;\n --oc-eyebrow-tracking: 0.08em;\n\n /* Surfaces (light mode defaults) */\n --oc-bg: #ffffff;\n --oc-card: #ffffff;\n --oc-secondary: #f4f4f5; /* zinc-100, raised surface */\n\n /*\n * Text levels. Names invert across modes: in light mode \"muted\" sits at\n * a lighter zinc step than \"subtle\" because both are picked relative to\n * the active background, not from a fixed lightness ladder. The intent\n * is \"muted = first step away from primary text\"; \"subtle = next step\n * down\"; etc.\n *\n * Light mode: text=zinc-950, secondary=zinc-700, muted=zinc-500,\n * subtle=zinc-400, faint=zinc-300\n * Dark mode (dark.css): inverts the surface tokens but keeps the same\n * muted -> subtle -> faint progression away from primary.\n */\n --oc-text: #09090b;\n --oc-text-secondary: #3f3f46;\n --oc-text-muted: #71717a;\n --oc-text-faint: #d4d4d8;\n\n /*\n * Derived neutral ramp. Named by the share of *text* in a text-toward-\n * background mix: 100 is nearly the background, 800 is nearly the text.\n * These static values are the mix against the default surfaces; mounts\n * restamp them from ResolvedTheme.colors.neutral, which a custom warm or\n * cool theme derives from its own text/background pair.\n */\n --oc-gray-100: #f0f0f0;\n --oc-gray-200: #e1e1e2;\n --oc-gray-300: #c9c9c9;\n --oc-gray-400: #9d9d9d;\n --oc-gray-600: #787879;\n --oc-gray-800: #474748;\n\n /* Lines */\n --oc-gridline: rgba(0, 0, 0, 0.08);\n --oc-axis: rgba(0, 0, 0, 0.14); /* hairline = theme.colors.hairline, not the tick-label ink */\n --oc-border: rgba(0, 0, 0, 0.08);\n --oc-border-radius: 8px; /* containers and tooltips; marks use --oc-radius-sm */\n\n /* Radius ladder */\n --oc-radius-sm: 2px;\n --oc-radius-md: 6px;\n --oc-radius-lg: var(--oc-border-radius);\n --oc-radius-full: 999px;\n\n /* Brand and semantic */\n --oc-accent: #06b6d4;\n --oc-accent-strong: #0891b2; /* darker cyan for line strokes on light bg */\n /* kept equal to DEFAULT_THEME.colors.positive (token-theme-parity test) */\n --oc-positive: #15803d;\n --oc-negative: #dc2626;\n /* delta chip background */\n --oc-positive-tint: color-mix(in srgb, var(--oc-positive) 10%, var(--oc-bg));\n --oc-negative-tint: color-mix(in srgb, var(--oc-negative) 10%, var(--oc-bg));\n --oc-focus: #3b82f6;\n /* static, intentionally NOT derived from --oc-focus and NOT flipped in dark mode */\n --oc-focus-ring: rgba(59, 130, 246, 0.1);\n --oc-focus-ring-strong: rgba(59, 130, 246, 0.25);\n --oc-editable-hover: rgba(79, 70, 229, 0.35); /* edit-mode hover outline, indigo one-off */\n\n /* Spacing scale (4px base) — only --oc-space-2/4 are consumed (JS-stamped) */\n --oc-space-2: 8px;\n --oc-space-4: 16px;\n\n /*\n * Hover language. The hovered element goes to full ink; the rest of its\n * group drops to --oc-hover-dim over --oc-hover-duration. Maps override the\n * dim locally (3000 county paths at 0.3 reads as a blackout, not a hint).\n */\n --oc-hover-dim: 0.3;\n --oc-hover-duration: 140ms;\n --oc-map-hover-dim: 0.75;\n\n /* Interactive states */\n --oc-hover-bg: rgba(0, 0, 0, 0.025);\n --oc-tooltip-bg: rgba(255, 255, 255, 0.88);\n --oc-tooltip-border: rgba(0, 0, 0, 0.08);\n --oc-tooltip-shadow: 0 2px 8px rgba(0, 0, 0, 0.08), 0 0 1px rgba(0, 0, 0, 0.12);\n --oc-tooltip-text: #09090b;\n --oc-legend-text: #3f3f46;\n }\n}\n","@layer oc.components {\n /* ---------------------------------------------------------------------------\n * You draw it (youDrawIt)\n *\n * NYT-style draw-then-reveal. SVG-space elements (hatched region, guess path,\n * reveal clip) render inside the chart SVG; the prompt + skip-to-reveal button\n * are an absolutely-positioned HTML overlay the vanilla adapter sizes over the\n * drawing region (inline left/top/width/height). All colors come from --oc-*\n * tokens so they flip in .oc-dark.\n * --------------------------------------------------------------------------- */\n\n /* Hatched \"draw here\" region. Fill comes from an SVG <pattern> (line color =\n * the target series color); this only governs overall opacity + fade-out. */\n .oc-ydi-region {\n opacity: 0.35;\n transition: opacity 0.4s ease;\n }\n\n .oc-ydi-region[data-ydi-hidden=\"true\"] {\n opacity: 0;\n }\n\n /* The vertical rule at `from` where drawing begins. */\n .oc-ydi-boundary {\n stroke: var(--oc-text-muted);\n stroke-width: 1;\n stroke-dasharray: 3 3;\n stroke-opacity: 0.6;\n }\n\n /* Reader's guess: a distinct pen-like stroke that reads as \"yours\" against the\n * solid real line. Dashed + focus-blue so it stays legible in both modes. */\n .oc-ydi-guess {\n stroke: var(--oc-focus);\n stroke-width: 2.5;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-dasharray: 1 6;\n }\n\n /* Host-supplied comparison line (\"what everyone else guessed\"). Muted so it\n * sits behind the reader's guess and the real line. */\n .oc-ydi-comparison {\n stroke: var(--oc-text-muted);\n stroke-width: 1.5;\n stroke-opacity: 0.5;\n stroke-dasharray: 4 4;\n }\n\n /* Reveal clip rect: the width animates from the `from` boundary to the full\n * area on reveal, wiping the real line in left-to-right. The vanilla adapter\n * adds .oc-ydi-clip-animate right before setting the final width; reduced\n * motion skips the class so the width snaps. */\n .oc-ydi-clip-rect.oc-ydi-clip-animate {\n transition: width 0.7s cubic-bezier(0.22, 1, 0.36, 1);\n }\n\n /* HTML controls overlay: prompt (top) + reveal button (bottom-right). */\n .oc-ydi-controls {\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n align-items: flex-end;\n pointer-events: none;\n font-family: var(--oc-font-family);\n padding: 8px;\n box-sizing: border-box;\n z-index: 10;\n }\n\n .oc-ydi-prompt {\n align-self: center;\n max-width: 100%;\n padding: 6px 12px;\n border-radius: var(--oc-radius-md);\n background: var(--oc-card);\n border: 1px solid var(--oc-border);\n color: var(--oc-text-secondary);\n font-size: 13px;\n font-weight: 500;\n line-height: 16px;\n text-align: center;\n box-shadow: var(--oc-tooltip-shadow);\n }\n\n .oc-ydi-controls.oc-ydi-revealed .oc-ydi-prompt {\n display: none;\n }\n\n /* Clear + reveal buttons, side by side at the bottom-right. */\n .oc-ydi-actions {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: 8px;\n pointer-events: none;\n }\n\n /* Skip-to-reveal and clear buttons. pointer-events re-enabled (the overlay\n * disables it) so they stay clickable and keyboard-reachable. Min height\n * enforced inline by the adapter (>= 24px effective touch target). */\n .oc-ydi-reveal-button,\n .oc-ydi-reset-button {\n pointer-events: auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 6px 14px;\n border: 1px solid var(--oc-border);\n border-radius: var(--oc-radius-md);\n background: var(--oc-bg);\n color: var(--oc-text);\n font-family: inherit;\n font-size: 13px;\n font-weight: 500;\n white-space: nowrap;\n cursor: pointer;\n box-shadow: var(--oc-tooltip-shadow);\n transition:\n background-color 0.15s,\n border-color 0.15s;\n }\n\n .oc-ydi-reset-button[hidden] {\n display: none;\n }\n\n .oc-ydi-reveal-button:hover,\n .oc-ydi-reset-button:hover {\n background: var(--oc-hover-bg);\n }\n\n .oc-ydi-reveal-button:focus-visible,\n .oc-ydi-reset-button:focus-visible {\n outline: 2px solid var(--oc-focus);\n outline-offset: 2px;\n }\n\n .oc-ydi-reveal-button:disabled {\n opacity: 0.5;\n cursor: default;\n }\n}\n","@layer oc.components {\n /* ---------------------------------------------------------------------------\n * Map reader zoom (geo.zoom)\n * The overlay is pinned to the map area (left/top/width/height stamped in %\n * by vanilla/src/map-zoom.ts) and passes pointer events through, so only the\n * buttons are hit targets. Surfaces reuse the tooltip tokens: a translucent\n * card that reads over any fill, light or dark.\n * --------------------------------------------------------------------------- */\n\n .oc-map-zoom {\n position: absolute;\n pointer-events: none;\n z-index: 2;\n }\n\n .oc-map-zoom-controls {\n position: absolute;\n top: 8px;\n right: 8px;\n display: flex;\n flex-direction: column;\n pointer-events: auto;\n background: var(--oc-tooltip-bg);\n backdrop-filter: blur(14px);\n border: 1px solid var(--oc-tooltip-border);\n border-radius: var(--oc-radius-md);\n box-shadow: var(--oc-tooltip-shadow);\n overflow: hidden;\n }\n\n .oc-map-zoom-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n margin: 0;\n padding: 0;\n border: none;\n background: none;\n color: var(--oc-text);\n font: inherit;\n cursor: pointer;\n transition:\n background var(--oc-hover-duration) ease-out,\n opacity var(--oc-hover-duration) ease-out;\n\n & + & {\n border-top: 1px solid var(--oc-tooltip-border);\n }\n\n &:hover:not(:disabled) {\n background: var(--oc-focus-ring);\n }\n\n &:focus-visible {\n outline: 2px solid var(--oc-focus);\n outline-offset: -2px;\n }\n\n &:disabled {\n cursor: default;\n opacity: 0.35;\n }\n }\n\n /* Short-lived \"use ctrl/cmd + scroll\" hint after a plain wheel over the map. */\n .oc-map-zoom-hint {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n max-width: calc(100% - 32px);\n padding: 8px 12px;\n background: var(--oc-tooltip-bg);\n backdrop-filter: blur(14px);\n border: 1px solid var(--oc-tooltip-border);\n border-radius: var(--oc-radius-md);\n box-shadow: var(--oc-tooltip-shadow);\n color: var(--oc-tooltip-text);\n font-family: var(--oc-font-family);\n font-size: 13px;\n line-height: 1.3;\n text-align: center;\n opacity: 0;\n transition: opacity 200ms ease-out;\n\n &[data-visible] {\n opacity: 1;\n }\n }\n\n /* The SVG is focusable while zoom is on (keyboard: + - arrows 0). */\n .oc-map:focus {\n outline: none;\n }\n\n .oc-map:focus-visible {\n outline: 2px solid var(--oc-focus);\n outline-offset: 2px;\n }\n\n .oc-map[data-oc-zoomed] {\n cursor: grab;\n }\n\n /* The SVG holds pointer capture during a drag, so its cursor is the one shown. */\n .oc-map--panning {\n cursor: grabbing;\n }\n}\n","/* GENERATED FILE — do not edit. Source: packages/core/src/styles/token-definitions.ts. Regenerate: bun run generate:tokens */\n\n@layer oc.tokens {\n /* ---------------------------------------------------------------------------\n * Dark mode overrides (fallback defaults)\n *\n * At runtime, the JS theme engine stamps dark-adapted --oc-* custom\n * properties on each .oc-root container. These CSS values serve as\n * fallbacks for contexts where JS hasn't mounted yet.\n * --------------------------------------------------------------------------- */\n\n .oc-dark {\n /* Surfaces (zinc-based achromatic ramp) */\n --oc-bg: #09090b;\n --oc-card: #111113;\n --oc-secondary: #27272a;\n\n /* Text levels — see tokens.css for the cross-mode naming rationale */\n --oc-text: #f7f8f8;\n --oc-text-secondary: #d0d6e0;\n --oc-text-muted: #a1a1aa;\n --oc-text-faint: #52525b;\n\n /* Lines */\n --oc-gridline: rgba(255, 255, 255, 0.06);\n --oc-axis: rgba(255, 255, 255, 0.14);\n --oc-border: rgba(255, 255, 255, 0.1);\n\n /* Brand and semantic — accent stays cyan (no darkening on dark bg) */\n --oc-accent: #06b6d4;\n --oc-accent-strong: #06b6d4;\n --oc-positive: #4ade80;\n --oc-negative: #f87171;\n --oc-focus: #60a5fa;\n\n /* Interactive states */\n --oc-hover-bg: rgba(255, 255, 255, 0.05);\n --oc-tooltip-bg: rgba(17, 17, 19, 0.92);\n --oc-tooltip-border: rgba(255, 255, 255, 0.08);\n --oc-tooltip-shadow: 0 2px 8px rgba(0, 0, 0, 0.3), 0 0 1px rgba(0, 0, 0, 0.4);\n --oc-tooltip-text: #f7f8f8;\n --oc-legend-text: #d0d6e0;\n }\n}\n","@layer oc.animation {\n /* ---------------------------------------------------------------------------\n * Table entrance animations (.oc-table-wrapper.oc-animate)\n * --------------------------------------------------------------------------- */\n\n .oc-table-wrapper.oc-animate {\n /* Chrome (title/subtitle): fade + slide up */\n & > .oc-chrome {\n animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.6)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n }\n\n /* Table header: quick fade before rows start */\n & thead {\n animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.4)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n }\n\n /* Row entrance: slide up only, no opacity (cells handle their own fading\n to avoid opacity compounding between row and cell animations) */\n & tbody tr {\n animation: oc-table-enter-row var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-row-index, 0));\n }\n\n /* Cell text: fade in synced with row slide */\n & tbody td {\n animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.5)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-row-index, 0));\n }\n\n /* Heatmap/category cell backgrounds: longer fade, delayed after row appears */\n & td.oc-table-heatmap,\n & td.oc-table-category {\n animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.7)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(\n var(--oc-animation-stagger) *\n var(--oc-row-index, 0) +\n var(--oc-animation-duration) *\n 0.3\n );\n }\n\n /* Bar fill: clip-path grow only (no opacity change to preserve resting\n opacity: 0.15 from table.css) */\n & .oc-table-bar-fill {\n animation: oc-table-enter-bar-fill calc(var(--oc-animation-duration) * 0.8)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(\n var(--oc-animation-stagger) *\n var(--oc-row-index, 0) +\n var(--oc-animation-duration) *\n 0.3\n );\n }\n\n /* Sparkline SVG: clip-path reveal left-to-right. Targets the SVG directly\n (not the wrapper) to avoid clipping absolutely-positioned dots and labels. */\n & .oc-table-sparkline > svg {\n animation: oc-enter-line calc(var(--oc-animation-duration) * 0.8)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(\n var(--oc-animation-stagger) *\n var(--oc-row-index, 0) +\n var(--oc-animation-duration) *\n 0.4\n );\n }\n\n /* Sparkline dots and labels: fade in after the line draws through */\n & .oc-table-sparkline-dot,\n & .oc-table-sparkline-labels {\n animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.3)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(\n var(--oc-animation-stagger) *\n var(--oc-row-index, 0) +\n var(--oc-animation-duration) *\n 0.8\n );\n }\n\n /* Search and pagination: quick fade on mount */\n & .oc-table-search,\n & .oc-table-pagination {\n animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.5)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n }\n }\n}\n","@layer oc.components {\n /* ---------------------------------------------------------------------------\n * Table base\n * --------------------------------------------------------------------------- */\n\n .oc-table-wrapper {\n font-family: var(--oc-font-family);\n color: var(--oc-text);\n background: var(--oc-bg);\n\n & > .oc-chrome {\n margin-bottom: 16px;\n padding-left: 16px;\n padding-right: 16px;\n }\n\n & > .oc-chrome:first-child {\n padding-top: 4px;\n }\n\n & table {\n width: 100%;\n border-collapse: collapse;\n }\n\n & th,\n & td {\n /* 12 + 24 + 12 = 48px rows. Condensed and relaxed keep the same\n line box and change only the padding, so the ladder is 40/48/56. */\n padding: 12px 16px;\n line-height: 24px;\n text-align: left;\n border-bottom: 1px solid var(--oc-border);\n /* Column widths from the engine already sum to the container width;\n without border-box the padding pushes each cell wider than its\n computed width and auto layout rescales the whole row. */\n box-sizing: border-box;\n }\n\n & th {\n font-weight: 500;\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--oc-text-muted);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n }\n\n & thead {\n position: sticky;\n top: 0;\n z-index: 2;\n background: var(--oc-bg);\n }\n\n /* A hairline, like every other rule in the table. The old 2px header rule\n was the heaviest line on the page and drew the eye away from the data. */\n & thead th {\n border-bottom-width: 1px;\n }\n\n & td {\n font-size: 14px;\n font-variant-numeric: tabular-nums;\n }\n\n & th:focus {\n outline: 2px solid var(--oc-focus);\n outline-offset: -2px;\n }\n\n & tbody:focus {\n outline: none;\n }\n }\n\n .oc-table-title {\n margin-bottom: 4px;\n font-size: var(--oc-title-computed-size, var(--oc-title-size));\n font-weight: var(--oc-title-computed-weight, var(--oc-title-weight));\n color: var(--oc-title-computed-color, var(--oc-text));\n }\n\n .oc-table-subtitle {\n margin-bottom: 8px;\n font-size: var(--oc-subtitle-computed-size, var(--oc-subtitle-size));\n font-weight: var(--oc-subtitle-computed-weight, var(--oc-subtitle-weight));\n color: var(--oc-subtitle-computed-color, var(--oc-text-secondary));\n }\n\n .oc-table-source {\n font-size: var(--oc-source-computed-size, var(--oc-source-size));\n color: var(--oc-source-computed-color, var(--oc-text-muted));\n }\n\n .oc-table-footer-text {\n font-size: var(--oc-footer-computed-size, var(--oc-source-size));\n color: var(--oc-footer-computed-color, var(--oc-text-muted));\n }\n\n .oc-table-scroll {\n overflow-x: auto;\n }\n\n /* ---------------------------------------------------------------------------\n * Sticky first column\n * --------------------------------------------------------------------------- */\n\n .oc-table--sticky {\n & th:first-child,\n & td:first-child {\n position: sticky;\n left: 0;\n z-index: 1;\n background: var(--oc-bg);\n }\n }\n\n /* ---------------------------------------------------------------------------\n * Sort controls\n * --------------------------------------------------------------------------- */\n\n .oc-table-sort-btn {\n background: none;\n border: none;\n cursor: pointer;\n padding: 2px;\n margin-left: 6px;\n display: inline-flex;\n flex-direction: column;\n align-items: center;\n vertical-align: middle;\n gap: 2px;\n\n &::before,\n &::after {\n content: \"\";\n display: block;\n width: 0;\n height: 0;\n border-left: 5px solid transparent;\n border-right: 5px solid transparent;\n transition:\n opacity 0.15s,\n border-color 0.15s;\n }\n\n &::before {\n border-bottom: 4.5px solid var(--oc-text-secondary);\n opacity: 0.35;\n }\n\n &::after {\n border-top: 4.5px solid var(--oc-text-secondary);\n opacity: 0.35;\n }\n\n &:hover::before,\n &:hover::after {\n opacity: 0.75;\n }\n }\n\n th[aria-sort=\"ascending\"] .oc-table-sort-btn {\n &::before {\n opacity: 1;\n border-bottom-color: var(--oc-text);\n }\n\n &::after {\n opacity: 0.15;\n }\n }\n\n th[aria-sort=\"descending\"] .oc-table-sort-btn {\n &::after {\n opacity: 1;\n border-top-color: var(--oc-text);\n }\n\n &::before {\n opacity: 0.15;\n }\n }\n\n /* ---------------------------------------------------------------------------\n * Search\n * --------------------------------------------------------------------------- */\n\n /* Shared search-input skin (table + series-search).\n Padding excluded: it diverges (table: 8px 12px; series: 0 10px 0 28px)\n and series-search.css is imported before table.css — a padding declaration\n here would beat the series-search override by source order. */\n .oc-table-search input,\n .oc-series-search-input {\n width: 100%;\n border: 1px solid var(--oc-border);\n border-radius: var(--oc-radius-md);\n font-size: 13px;\n font-family: inherit;\n background: var(--oc-bg);\n color: var(--oc-text);\n box-sizing: border-box;\n transition: border-color 0.15s;\n }\n\n .oc-table-search input::placeholder,\n .oc-series-search-input::placeholder {\n color: var(--oc-text-muted);\n font-size: 13px;\n }\n\n .oc-table-search input:focus,\n .oc-series-search-input:focus {\n outline: none;\n border-color: var(--oc-focus);\n box-shadow: 0 0 0 3px var(--oc-focus-ring);\n }\n\n .oc-table-search {\n padding: 8px 0;\n\n & input {\n padding: 8px 12px;\n }\n }\n\n /* ---------------------------------------------------------------------------\n * Pagination\n * --------------------------------------------------------------------------- */\n\n .oc-table-pagination {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 0 4px;\n font-size: 13px;\n color: var(--oc-text-secondary);\n\n & button {\n padding: 6px 14px;\n border: 1px solid var(--oc-border);\n border-radius: var(--oc-radius-md);\n background: var(--oc-bg);\n color: var(--oc-text);\n cursor: pointer;\n font-size: 13px;\n font-family: inherit;\n transition:\n background 0.15s,\n border-color 0.15s;\n\n &:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n }\n\n &:hover:not(:disabled) {\n background: var(--oc-hover-bg);\n border-color: var(--oc-axis);\n }\n\n &:focus-visible {\n outline: 2px solid var(--oc-focus);\n outline-offset: 1px;\n }\n }\n }\n\n .oc-table-pagination-info {\n font-variant-numeric: tabular-nums;\n }\n\n .oc-table-pagination-btns {\n display: flex;\n gap: 8px;\n }\n\n /* ---------------------------------------------------------------------------\n * Bar cells\n * --------------------------------------------------------------------------- */\n\n .oc-table-bar {\n position: relative;\n }\n\n .oc-table-bar-fill {\n position: absolute;\n top: 8px;\n left: 0;\n bottom: 8px;\n border-radius: var(--oc-radius-sm);\n opacity: 0.18;\n pointer-events: none;\n }\n\n .oc-table-bar-value {\n position: relative;\n z-index: 1;\n }\n\n /* ---------------------------------------------------------------------------\n * Sparkline cells\n * --------------------------------------------------------------------------- */\n\n .oc-table-sparkline {\n display: block;\n width: 100%;\n position: relative;\n\n & svg {\n display: block;\n width: 100%;\n overflow: visible;\n }\n }\n\n .oc-table-sparkline-dot {\n position: absolute;\n border-radius: 50%;\n width: 5px;\n height: 5px;\n }\n\n .oc-table-sparkline-labels {\n display: flex;\n justify-content: space-between;\n font-size: 11px;\n line-height: 1;\n }\n\n /* ---------------------------------------------------------------------------\n * Image cells\n * --------------------------------------------------------------------------- */\n\n .oc-table-image {\n display: inline-block;\n vertical-align: middle;\n\n & img {\n object-fit: cover;\n }\n }\n\n .oc-table-image-rounded img {\n border-radius: 50%;\n }\n\n /* ---------------------------------------------------------------------------\n * Flag cells\n * --------------------------------------------------------------------------- */\n\n .oc-table-flag {\n font-size: 1.2em;\n }\n\n /* ---------------------------------------------------------------------------\n * Density\n *\n * regular 48px rows (base), condensed 40px, relaxed 56px. `.oc-table--compact`\n * is the deprecated alias for condensed, kept one release.\n * --------------------------------------------------------------------------- */\n\n .oc-table--condensed,\n .oc-table--compact {\n & th,\n & td {\n padding: 8px 12px;\n line-height: 24px;\n font-size: 13px;\n }\n\n & th {\n font-size: 11px;\n }\n\n & .oc-table-bar-fill {\n top: 5px;\n bottom: 5px;\n }\n }\n\n .oc-table--relaxed {\n & th,\n & td {\n padding: 16px 20px;\n line-height: 24px;\n }\n\n & .oc-table-bar-fill {\n top: 12px;\n bottom: 12px;\n }\n }\n\n /* ---------------------------------------------------------------------------\n * Striping\n * --------------------------------------------------------------------------- */\n\n .oc-table--striped tbody tr:nth-child(even) {\n background: color-mix(in srgb, var(--oc-text) 3%, transparent);\n }\n\n /* ---------------------------------------------------------------------------\n * Delta chips\n * --------------------------------------------------------------------------- */\n\n .oc-table-delta {\n display: inline-flex;\n align-items: baseline;\n gap: 4px;\n padding: 2px 8px;\n border-radius: var(--oc-radius-md);\n font-weight: 500;\n font-variant-numeric: tabular-nums;\n line-height: 16px;\n }\n\n .oc-table-delta-arrow {\n font-size: 0.8em;\n line-height: 1;\n }\n\n .oc-table-delta--positive {\n color: var(--oc-positive);\n background: var(--oc-positive-tint);\n }\n\n .oc-table-delta--negative {\n color: var(--oc-negative);\n background: var(--oc-negative-tint);\n }\n\n .oc-table-delta--neutral {\n color: var(--oc-text-muted);\n background: color-mix(in srgb, var(--oc-text) 6%, transparent);\n }\n\n /* Category chips: the engine supplies the tint, ink and dot color inline. */\n .oc-table-chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 2px 8px;\n border-radius: var(--oc-radius-full);\n font-size: 12px;\n font-weight: 500;\n line-height: 16px;\n white-space: nowrap;\n }\n\n .oc-table-chip-dot {\n flex: none;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n }\n\n /* ---------------------------------------------------------------------------\n * Totals footer\n * --------------------------------------------------------------------------- */\n\n tfoot.oc-table-total {\n position: sticky;\n bottom: 0;\n z-index: 2;\n background: var(--oc-bg);\n\n & td {\n font-weight: 600;\n border-bottom: none;\n border-top: 1px solid var(--oc-border);\n }\n }\n\n /* ---------------------------------------------------------------------------\n * Cards mode (below 400px)\n *\n * Rows become two-column grids with the header printed per cell. `display:\n * grid` drops the implicit table roles, so the renderer stamps explicit ARIA\n * roles on every element; `display: contents` is deliberately NOT used —\n * it removes the row box the grid needs and breaks the semantics further.\n * --------------------------------------------------------------------------- */\n\n .oc-table--cards {\n & .oc-table-scroll {\n overflow-x: hidden;\n }\n\n & table {\n table-layout: fixed;\n }\n\n & thead {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n }\n\n & tbody tr,\n & tfoot tr {\n display: grid;\n /* Two equal halves keep every label/value pair the same width; an\n auto first column makes the third cell in a row narrower than the\n second and the card reads ragged. */\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 2px 12px;\n align-items: baseline;\n padding: 10px 12px;\n border-bottom: 1px solid var(--oc-border);\n }\n\n & td {\n display: block;\n width: auto;\n max-width: 100%;\n padding: 0;\n border-bottom: none;\n overflow-wrap: anywhere;\n text-align: right;\n }\n\n & td::before {\n content: attr(data-label);\n display: block;\n font-size: 11px;\n font-weight: 500;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--oc-text-muted);\n text-align: left;\n }\n\n /* A column with no header (flags, logos) prints no label either. */\n & td[data-label=\"\"]::before {\n content: none;\n }\n\n /* Priority 1 leads the card on its own line, label suppressed. */\n & td[data-priority=\"1\"] {\n grid-column: 1 / -1;\n font-size: 15px;\n font-weight: 600;\n text-align: left;\n }\n\n & td[data-priority=\"1\"]::before {\n content: none;\n }\n\n & td[data-priority=\"3\"] {\n display: none;\n }\n\n & .oc-table-sparkline {\n width: 100%;\n }\n }\n\n /* ---------------------------------------------------------------------------\n * Row hover (when onRowClick is set)\n * --------------------------------------------------------------------------- */\n\n .oc-table--clickable tbody {\n & tr {\n cursor: pointer;\n }\n\n & tr:hover {\n background: var(--oc-hover-bg);\n }\n }\n\n /* ---------------------------------------------------------------------------\n * Keyboard cell focus indicator\n * --------------------------------------------------------------------------- */\n\n .oc-table-cell-focus {\n outline: 2px solid var(--oc-focus);\n outline-offset: -2px;\n }\n\n /* ---------------------------------------------------------------------------\n * Empty state\n * --------------------------------------------------------------------------- */\n\n .oc-table-empty {\n padding: 32px 16px;\n text-align: center;\n color: var(--oc-text-secondary);\n font-size: 14px;\n font-style: italic;\n }\n}\n\n@layer oc.components {\n .oc-table--priority {\n & table {\n width: 100%;\n table-layout: auto;\n }\n & [hidden] {\n display: none;\n }\n & th,\n & td {\n /* biome-ignore lint/complexity/noImportantStyles: responsive mode overrides authored desktop inline column widths. */\n width: auto !important;\n padding-inline: 8px;\n }\n & th {\n position: relative;\n white-space: normal;\n padding-right: 20px;\n min-height: 44px;\n }\n & .oc-table-sort-btn {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n margin: 0;\n padding-right: 4px;\n align-items: flex-end;\n justify-content: center;\n }\n & .oc-table-details {\n white-space: normal;\n }\n & summary {\n cursor: pointer;\n min-height: 44px;\n display: flex;\n align-items: center;\n font-size: 12px;\n }\n & details[open] {\n min-width: 110px;\n }\n & dl {\n margin: 4px 0 12px;\n font-size: 12px;\n }\n & dt {\n margin-top: 8px;\n color: var(--oc-text-secondary);\n }\n & dd {\n margin: 4px 0 0;\n }\n }\n}\n","@layer oc.components {\n /**\n * Sparkline display mode.\n *\n * Stamped on the SVG root as data-display=\"sparkline\" by the renderer when\n * the spec sets display: 'sparkline'. Strips any inherited padding/margin\n * so the mark renders truly edge-to-edge in tight container layouts (KPI\n * cards, table cells, dashboard tiles).\n */\n\n .oc-chart[data-display=\"sparkline\"] {\n display: block;\n margin: 0;\n padding: 0;\n }\n\n /**\n * Data-arrival pulse. The update driver stamps `oc-pulse` on the sparkline's\n * terminator dot when a transition finishes and strips it 600ms later.\n * Deliberately not scoped under `.oc-animate`: that class only exists during\n * the entrance window, and this fires on updates.\n */\n .oc-chart[data-display=\"sparkline\"] .oc-pulse {\n animation: oc-pulse 600ms ease-out;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .oc-chart[data-display=\"sparkline\"] .oc-pulse {\n animation: none;\n }\n }\n}\n","@layer oc.base {\n /* ---------------------------------------------------------------------------\n * Wrapper roots\n * --------------------------------------------------------------------------- */\n\n .oc-chart-root {\n width: 100%;\n height: 100%;\n }\n\n .oc-table-root,\n .oc-graph-root,\n .oc-sankey-root,\n .oc-barlist-root,\n .oc-tilemap-root,\n .oc-map-root {\n width: 100%;\n height: 100%;\n }\n\n .oc-table-root {\n overflow: auto;\n }\n\n /* ---------------------------------------------------------------------------\n * Chart container\n * --------------------------------------------------------------------------- */\n\n .oc-chart {\n font-family: var(--oc-font-family);\n font-variant-numeric: tabular-nums;\n display: block;\n width: 100%;\n }\n\n /* ---------------------------------------------------------------------------\n * BarList SVG container\n * --------------------------------------------------------------------------- */\n\n .oc-tilemap,\n .oc-map {\n display: block;\n width: 100%;\n height: auto;\n }\n\n .oc-map-feature {\n transition:\n opacity var(--oc-hover-duration) ease-out,\n stroke-width 140ms ease-out;\n }\n\n .oc-barlist {\n display: block;\n width: 100%;\n }\n\n /* ---------------------------------------------------------------------------\n * Screen reader only utility\n * --------------------------------------------------------------------------- */\n\n /* `overflow: clip`, not `hidden` — see applySrOnlyStyles in\n packages/vanilla/src/dom-helpers.ts for why. Keep the two in sync. */\n .oc-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: clip;\n clip-path: inset(50%);\n white-space: nowrap;\n border-width: 0;\n }\n\n /* ---------------------------------------------------------------------------\n * Editable hover feedback\n * --------------------------------------------------------------------------- */\n\n .oc-editable-hover {\n outline: 1.5px solid var(--oc-editable-hover);\n outline-offset: 2px;\n border-radius: var(--oc-radius-sm);\n }\n\n /* ---------------------------------------------------------------------------\n * Keyboard focus indicators\n *\n * --oc-focus carries a light value in tokens.css and a dark value in\n * dark.css, so both rings stay visible in either mode.\n * --------------------------------------------------------------------------- */\n\n /* Container ring when the chart itself receives keyboard focus. */\n .oc-root:focus-visible {\n outline: 2px solid var(--oc-focus);\n outline-offset: 2px;\n }\n\n /* Mark ring during arrow-key navigation (see wireKeyboardNav). Outline on\n * SVG elements draws around the mark's bounding box, same technique as\n * .oc-editable-hover above. */\n .oc-mark-focused {\n outline: 2px solid var(--oc-focus);\n outline-offset: 1px;\n border-radius: var(--oc-radius-sm);\n }\n}\n","@layer oc.components {\n /* ---------------------------------------------------------------------------\n * Graph\n * --------------------------------------------------------------------------- */\n\n .oc-graph-wrapper {\n position: relative;\n overflow: hidden;\n background: var(--oc-bg);\n font-family: var(--oc-font-family);\n width: 100%;\n height: 100%;\n }\n\n .oc-graph-canvas {\n display: block;\n width: 100%;\n height: 100%;\n cursor: grab;\n }\n\n .oc-graph-canvas--dragging {\n cursor: grabbing;\n }\n\n /* 3D surface. 3d-force-graph builds its own `div.scene-container` inside the\n * element it is handed and sizes the WebGL canvas imperatively, so the slot\n * has to fill the same box the 2D canvas fills or the first measurement is\n * zero-height. */\n .oc-graph-3d,\n .oc-graph-3d .scene-container {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n .oc-graph-3d {\n cursor: grab;\n }\n\n .oc-graph-3d .scene-container canvas {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n .oc-graph-chrome {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n z-index: 2;\n padding: 16px 16px 8px;\n pointer-events: none;\n\n & .oc-title {\n font-size: var(--oc-title-size);\n font-weight: var(--oc-title-weight);\n letter-spacing: var(--oc-title-tracking);\n color: var(--oc-text);\n margin: 0 0 4px;\n --_stroke: color-mix(in srgb, var(--oc-bg) 80%, transparent);\n text-shadow:\n -2px -2px 0 var(--_stroke),\n 2px -2px 0 var(--_stroke),\n -2px 2px 0 var(--_stroke),\n 2px 2px 0 var(--_stroke),\n 0 -2px 0 var(--_stroke),\n 0 2px 0 var(--_stroke),\n -2px 0 0 var(--_stroke),\n 2px 0 0 var(--_stroke);\n }\n\n & .oc-subtitle {\n font-size: var(--oc-subtitle-size);\n color: var(--oc-text-secondary);\n margin: 0;\n --_stroke: color-mix(in srgb, var(--oc-bg) 80%, transparent);\n text-shadow:\n -1px -1px 0 var(--_stroke),\n 1px -1px 0 var(--_stroke),\n -1px 1px 0 var(--_stroke),\n 1px 1px 0 var(--_stroke);\n }\n }\n\n .oc-graph-legend {\n position: absolute;\n top: 12px;\n right: 12px;\n /* Slightly translucent so the graph reads as continuous underneath, in\n * whatever surface the mount stamped on the wrapper. */\n background: color-mix(in srgb, var(--oc-bg) 88%, transparent);\n border: 1px solid var(--oc-border);\n border-radius: var(--oc-radius-lg);\n padding: 8px 12px;\n font-size: 12px;\n color: var(--oc-text-secondary);\n max-height: 200px;\n overflow-y: auto;\n }\n\n .oc-graph-legend-item {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 2px 0;\n /* Button reset for interactive rows (rendered as <button>). */\n width: 100%;\n margin: 0;\n background: none;\n border: none;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: default;\n }\n\n /* Interactive legend rows are buttons; give them affordance + a focus ring. */\n button.oc-graph-legend-item {\n cursor: pointer;\n border-radius: var(--oc-radius-sm);\n\n &:hover {\n background: var(--oc-focus-ring);\n }\n\n &:focus-visible {\n outline: 2px solid var(--oc-focus);\n outline-offset: 1px;\n }\n }\n\n /* De-emphasized (toggled-off) category. */\n .oc-graph-legend-item--inactive {\n opacity: 0.45;\n }\n\n .oc-graph-legend-label {\n flex: 1 1 auto;\n }\n\n .oc-graph-legend-count {\n color: var(--oc-text-secondary);\n font-variant-numeric: tabular-nums;\n margin-left: auto;\n padding-left: 8px;\n }\n\n .oc-graph-legend-swatch {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n /* Edge-legend swatches render as a short line, not a dot. */\n .oc-graph-legend-swatch--line {\n width: 12px;\n height: 3px;\n border-radius: 1px;\n }\n\n .oc-graph-search {\n position: absolute;\n top: 12px;\n left: 12px;\n\n & input {\n font-family: var(--oc-font-family);\n font-size: var(--oc-body-size);\n padding: 6px 10px;\n border: 1px solid var(--oc-border);\n border-radius: var(--oc-radius-md);\n background: color-mix(in srgb, var(--oc-bg) 88%, transparent);\n color: var(--oc-text);\n outline: none;\n\n &:focus {\n border-color: var(--oc-focus);\n box-shadow: 0 0 0 2px var(--oc-focus-ring-strong);\n }\n }\n }\n\n /*\n * No dark-mode canvas override lives here. graph-mount stamps the resolved\n * theme surface on the wrapper (--oc-bg), so dark graphs sit on the same\n * --oc-bg the rest of the library uses instead of a private GitHub-dark hex,\n * and the legend/search panels mix against whatever that surface is.\n */\n}\n","@layer oc.animation {\n /* ---------------------------------------------------------------------------\n * Animation keyframes\n * --------------------------------------------------------------------------- */\n\n /* Bar entrance: clip-path reveal bottom-to-top + fade in (vertical columns).\n Bars grow upward from baseline with a soft opacity fade. */\n @keyframes oc-enter-bar {\n from {\n clip-path: inset(100% 0 0 0);\n opacity: 0;\n }\n 75% {\n opacity: 1;\n }\n to {\n clip-path: inset(0 0 0 0);\n opacity: 1;\n }\n }\n\n /* Bar entrance: clip-path reveal left-to-right + fade in (horizontal bars).\n Bars grow rightward from axis with a soft opacity fade. */\n @keyframes oc-enter-bar-h {\n from {\n clip-path: inset(0 100% 0 0);\n opacity: 0;\n }\n 75% {\n opacity: 1;\n }\n to {\n clip-path: inset(0 0 0 0);\n opacity: 1;\n }\n }\n\n /* Line/area entrance: clip-path reveal left-to-right + fade in.\n Lines draw in following reading direction with a soft lead-in. */\n @keyframes oc-enter-line {\n from {\n clip-path: inset(0 100% 0 0);\n opacity: 0;\n }\n 15% {\n opacity: 1;\n }\n to {\n clip-path: inset(0 0 0 0);\n opacity: 1;\n }\n }\n\n /* Point/arc entrance: scale up + fade in from center */\n @keyframes oc-enter-point {\n from {\n opacity: 0;\n transform: scale(0.3);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n }\n\n /* Map feature entrance: fade in while transitioning fill from a neutral base\n to the data-driven color stored in --oc-feature-fill. The target opacity is\n --oc-feature-target-opacity (default 1) so features under a focus dim\n animate straight to their dimmed rest opacity instead of hitting 1 and then\n snapping down when the dim is applied post-animation.\n Non-interpolable fills (the url(#pattern) hatch on no-data features) do not\n transition: the browser holds the neutral and flips to the pattern when the\n eased progress passes 50%, so those features fade in rather than\n cross-fade. */\n @keyframes oc-enter-map-fill {\n from {\n fill: var(--oc-secondary);\n opacity: 0;\n }\n to {\n fill: var(--oc-feature-fill);\n opacity: var(--oc-feature-target-opacity, 1);\n }\n }\n\n /* Map point pop-in: gentle scale from 0.75 + fade. Uses transform-origin to\n scale from the circle's own center (cx/cy) rather than the SVG origin. */\n @keyframes oc-enter-map-point {\n from {\n opacity: 0;\n transform: scale(0.75);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n }\n\n /* Pure opacity fade (no transform). Safe for elements with existing transforms\n like arc groups that use translate() for positioning. */\n @keyframes oc-enter-fade-only {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n\n /* Fade + subtle slide up for text, rule, tick, annotations */\n @keyframes oc-enter-fade {\n from {\n opacity: 0;\n transform: translateY(4px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n /* Table row entrance: slide up only, no opacity (cells fade independently\n to avoid opacity compounding between row and cell animations) */\n @keyframes oc-table-enter-row {\n from {\n transform: translateY(6px);\n }\n to {\n transform: translateY(0);\n }\n }\n\n /* Table bar fill entrance: clip-path grow only, no opacity\n (preserves resting opacity: 0.15 from table.css) */\n @keyframes oc-table-enter-bar-fill {\n from {\n clip-path: inset(0 100% 0 0);\n }\n to {\n clip-path: inset(0 0 0 0);\n }\n }\n\n /* Live-tile pulse: the terminator dot of a sparkline swells once when new\n data lands, so a glance at a wall of tiles catches which one just moved.\n `r` is animated as a presentation attribute (SVG geometry properties are\n animatable in CSS); the fallback is simply no swell. */\n @keyframes oc-pulse {\n 0% {\n r: var(--oc-pulse-r, 4px);\n fill-opacity: 1;\n }\n 45% {\n r: calc(var(--oc-pulse-r, 4px) * 1.8);\n fill-opacity: 0.5;\n }\n 100% {\n r: var(--oc-pulse-r, 4px);\n fill-opacity: 1;\n }\n }\n\n /* Tooltip entrance */\n @keyframes oc-tooltip-in {\n from {\n opacity: 0;\n transform: translateY(2px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n}\n","@layer oc.components {\n /* ---------------------------------------------------------------------------\n * Chrome (eyebrow, title, subtitle, source, byline, footer, brand)\n * --------------------------------------------------------------------------- */\n\n .oc-chrome {\n font-family: var(--oc-font-family);\n }\n\n .oc-eyebrow {\n font-size: var(--oc-eyebrow-size);\n font-weight: var(--oc-eyebrow-weight);\n letter-spacing: var(--oc-eyebrow-tracking);\n text-transform: uppercase;\n fill: var(--oc-accent);\n }\n\n .oc-title {\n font-size: var(--oc-title-size);\n font-weight: var(--oc-title-weight);\n letter-spacing: var(--oc-title-tracking);\n fill: var(--oc-text);\n }\n\n .oc-subtitle {\n font-size: var(--oc-subtitle-size);\n font-weight: var(--oc-subtitle-weight);\n fill: var(--oc-text-muted);\n }\n\n .oc-source,\n .oc-byline,\n .oc-footer {\n font-size: var(--oc-source-size);\n font-weight: var(--oc-source-weight);\n fill: var(--oc-text-muted);\n }\n\n .oc-brand {\n font-size: 11px;\n font-weight: 500;\n letter-spacing: 0.02em;\n fill: var(--oc-text-faint);\n }\n\n .oc-eyebrow-dot {\n fill: var(--oc-accent);\n }\n\n /* ---------------------------------------------------------------------------\n * Metric bar (.oc-metrics) — optional row of label/value cells above chart\n * --------------------------------------------------------------------------- */\n\n .oc-metrics {\n font-family: var(--oc-font-family);\n }\n\n .oc-metric-label {\n font-size: 11px;\n font-weight: 500;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n fill: var(--oc-text-muted);\n }\n\n .oc-metric-value {\n font-size: 22px;\n font-weight: 600;\n letter-spacing: -0.02em;\n fill: var(--oc-text);\n font-variant-numeric: tabular-nums;\n }\n\n .oc-metric-delta-up {\n fill: var(--oc-positive);\n font-size: 12px;\n font-weight: 500;\n }\n\n .oc-metric-delta-down {\n fill: var(--oc-negative);\n font-size: 12px;\n font-weight: 500;\n }\n\n /* A multiplier or a run-rate is context, not a positive signal: the green\n that belonged here made every secondary read as good news. */\n .oc-metric-secondary {\n fill: var(--oc-text-muted);\n font-size: 12px;\n font-weight: 400;\n }\n\n /* ---------------------------------------------------------------------------\n * Axis tick labels — inline variant sits above each gridline at the\n * chart-area left edge (no left gutter). Used by line/area y-axes.\n * --------------------------------------------------------------------------- */\n\n .oc-axis-tick-inline {\n font-size: 11px;\n font-weight: 400;\n fill: var(--oc-text-muted);\n }\n\n /* ---------------------------------------------------------------------------\n * Endpoint labels (right-side per-series column for line/area charts)\n *\n * Swatch idiom: a thicker colored stroke segment with an optional thinner\n * lighter strip below. Mirrors the refreshed traditional legend swatch so a\n * single chart never shows two swatch idioms (mock-2 alignment). Per-series\n * color is stamped inline by the renderer; CSS tokens here cover the muted\n * value text and the leader line so theme overrides flow through naturally.\n * --------------------------------------------------------------------------- */\n\n .oc-endpoint-labels {\n font-family: var(--oc-font-family);\n }\n\n .oc-endpoint-label {\n /* Color set inline per series; this fallback only kicks in if the renderer\n ever omits the inline fill. */\n fill: var(--oc-endpoint-label-color, var(--oc-text));\n }\n\n .oc-endpoint-value {\n fill: var(--oc-endpoint-value-color, var(--oc-text-muted));\n }\n\n .oc-endpoint-leader {\n stroke: var(--oc-endpoint-leader-color, currentColor);\n }\n\n /* .oc-endpoint-marker — fill/stroke set inline (open-ring style: bg fill, series stroke). */\n /* .oc-endpoint-swatch — color set inline per series. */\n\n /* ---------------------------------------------------------------------------\n * Annotation dot + subtitle (text-annotation extensions)\n * --------------------------------------------------------------------------- */\n\n /* .oc-annotation-dot — fill/stroke resolved by the engine (open-ring default = bg fill, series stroke). */\n\n .oc-annotation-subtitle {\n fill: var(--oc-annotation-subtitle-color, var(--oc-text-muted));\n }\n\n /* ---------------------------------------------------------------------------\n * Table footer chrome\n * --------------------------------------------------------------------------- */\n\n /* Footer row: source/footer text on the left, brand watermark on the right,\n * sharing a single baseline. gap keeps them apart if the row gets narrow. */\n .oc-table-footer-row {\n display: flex;\n align-items: baseline;\n gap: 16px;\n padding: 16px 16px 4px;\n }\n\n /* Chrome block sits inside the flex row now, so it no longer owns the\n * footer's top padding or horizontal inset (the row provides both). */\n .oc-chrome-footer {\n padding-top: 0;\n }\n\n /* Brand watermark: pushed to the right edge (margin-left:auto holds it there\n * even when the source text is absent), never shrinks below its own text. */\n .oc-table-footer-row .oc-table-ref {\n margin-left: auto;\n flex-shrink: 0;\n text-align: right;\n }\n}\n","@layer oc.components {\n /* ---------------------------------------------------------------------------\n * Sankey\n *\n * Hovering a node (or a link) traces the whole path through it: everything\n * upstream and everything downstream stays lit, the rest drops back. The mount\n * writes the opacities; this file only owns how they move, using the shared\n * hover duration so a sankey fades on the same clock as a bar chart.\n *\n * The transitions are switched off during the entrance (`.oc-animate`), where\n * the keyframes own opacity and a competing transition would smear them.\n * --------------------------------------------------------------------------- */\n\n .oc-sankey:not(.oc-animate) .oc-sankey-link path {\n transition: fill-opacity var(--oc-hover-duration) ease-out;\n }\n\n .oc-sankey:not(.oc-animate) .oc-sankey-node,\n .oc-sankey:not(.oc-animate) .oc-sankey-label {\n transition: opacity var(--oc-hover-duration) ease-out;\n }\n\n /* Labels are decoration over the flow: never a text cursor, never a selection\n * drag that eats the hover. */\n .oc-sankey-label {\n pointer-events: none;\n user-select: none;\n }\n}\n","@layer oc.animation {\n /* ---------------------------------------------------------------------------\n * Animation scoped rules (.oc-animate enables animation on the chart root)\n * --------------------------------------------------------------------------- */\n\n .oc-animate {\n /* Vertical bars (default): smooth ease-out, no overshoot.\n oc-mark-bar is reserved for future mark type aliases.\n A bar with a value-end radius draws as <path> rather than <rect>\n (SVG rx rounds all four corners or none), so both shapes match. */\n & .oc-mark-rect :is(rect, path),\n & .oc-mark-bar :is(rect, path) {\n animation: oc-enter-bar var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));\n }\n\n /* Horizontal bars (data-orient is on the mark group, not the SVG root) */\n & .oc-mark-rect[data-orient=\"horizontal\"] :is(rect, path),\n & .oc-mark-bar[data-orient=\"horizontal\"] :is(rect, path) {\n animation-name: oc-enter-bar-h;\n }\n\n /* Stacked bar/column segments: chain sequentially so each segment starts\n right when the previous one finishes, creating one fluid reveal.\n Uses linear easing so handoffs between segments are seamless (no\n deceleration/acceleration stutter at segment boundaries). */\n & .oc-mark-rect[data-stack-pos] :is(rect, path) {\n animation-duration: var(--oc-stack-segment-duration, 150ms);\n animation-timing-function: linear;\n animation-delay: calc(\n var(--oc-animation-stagger) *\n var(--oc-mark-index, 0) +\n var(--oc-stack-pos, 0) *\n var(--oc-stack-segment-duration, 150ms)\n );\n }\n\n & .oc-stack-reveal {\n animation: oc-enter-bar var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n }\n & .oc-stack-reveal[data-orient=\"horizontal\"] {\n animation-name: oc-enter-bar-h;\n }\n & .oc-stack-reveal .oc-mark-rect :is(rect, path) {\n animation: none;\n }\n\n /* Line marks: entire group clips left-to-right (no WAAPI needed) */\n & .oc-mark-line {\n animation: oc-enter-line var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));\n }\n\n /* Area marks: entire group clips left-to-right + fades in */\n & .oc-mark-area {\n animation: oc-enter-line var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));\n }\n\n /* Arc marks (pie/donut slices): simple fade in.\n Scale transforms break arc positioning because arcs use translate()\n on parent groups. A clean fade is more elegant for pie/donut anyway. */\n & .oc-mark-arc {\n animation: oc-enter-fade-only var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));\n }\n\n /* Point marks (scatter, dot).\n Points render as bare <circle> elements with class oc-mark-point directly,\n not wrapped in a group, so we target circle.oc-mark-point (not descendant).\n Duration is 40% of the configured duration (quick pop-in relative to other marks). */\n & circle.oc-mark-point,\n & circle.oc-mark-circle {\n animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.4)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));\n }\n\n /* Points on line/area charts: delay so they pop in as the line draws through. */\n & .oc-mark-line ~ circle.oc-mark-point,\n & .oc-mark-area ~ circle.oc-mark-point {\n animation-delay: calc(\n var(--oc-animation-duration) *\n 0.35 +\n var(--oc-animation-stagger) *\n var(--oc-mark-index, 0)\n );\n }\n\n /* Text marks: fade + slight slide up */\n & .oc-mark-text text {\n animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.6)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));\n }\n\n /* Rule marks: fade in */\n & .oc-mark-rule line {\n animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.5)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));\n }\n\n /* Tick marks: fade in */\n & .oc-mark-tick line {\n animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.5)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));\n }\n\n /* Data labels: fade after their parent mark */\n & .oc-mark-label {\n animation: oc-enter-fade 250ms var(--oc-ease-smooth) both;\n animation-delay: calc(\n var(--oc-animation-stagger) *\n var(--oc-mark-index, 0) +\n var(--oc-animation-duration) *\n 0.7\n );\n }\n\n /* Annotations: fade in after marks finish */\n & .oc-annotation {\n animation: oc-enter-fade 300ms var(--oc-ease-smooth) both;\n animation-delay: calc(var(--oc-animation-duration) + var(--oc-annotation-delay, 150ms));\n }\n\n /* Tilemap tiles: fade in with jittered stagger for organic feel.\n Per-tile delay is computed in the renderer with pseudo-random variation. */\n & .oc-tilemap-tile {\n animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.35) ease-in both;\n animation-delay: var(--oc-tile-delay, 0ms);\n }\n\n /* Map features: fill color reveal with shuffled stagger.\n Per-feature --oc-map-delay is computed in the renderer via a seeded\n Fisher-Yates shuffle so features pop in organically. */\n & .oc-map-feature {\n animation: oc-enter-map-fill var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: var(--oc-map-delay, 0ms);\n }\n\n /* Bulk mode: high feature counts (counties, ~3k+) get a single group\n fade instead of per-feature fill animations. opacity is GPU-compositable\n so this stays smooth regardless of child count. */\n & .oc-map-features[data-bulk-animate] {\n animation: oc-enter-fade-only var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n }\n\n & .oc-map-features[data-bulk-animate] .oc-map-feature {\n animation: none;\n }\n\n /* Map borders: fade in near the end of the feature sweep */\n & .oc-map-borders path {\n animation: oc-enter-fade-only calc(var(--oc-animation-duration) * 0.4) ease-in both;\n animation-delay: calc(var(--oc-animation-duration) * 0.7);\n }\n\n /* Map points: gentle scale (0.75->1) + fade pop-in after borders.\n transform-origin set per-circle in the renderer so scale happens\n around each circle's own center, not the SVG origin. */\n & .oc-map-point {\n animation: oc-enter-map-point calc(var(--oc-animation-duration) * 0.4)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(\n var(--oc-animation-duration) *\n 0.8 +\n var(--oc-mark-index, 0) *\n var(--oc-point-stagger, 60ms)\n );\n }\n\n /* Sankey nodes: fade in with stagger by column depth (left-to-right) */\n & .oc-sankey-node rect {\n animation: oc-enter-fade-only var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(var(--oc-animation-stagger) * var(--oc-mark-index, 0));\n }\n\n /* Sankey links: fade in after nodes, with stagger.\n Links delay by 30% of duration so nodes appear first, then links flow in. */\n & .oc-sankey-link path {\n animation: oc-enter-fade-only var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: calc(\n var(--oc-animation-duration) *\n 0.3 +\n var(--oc-animation-stagger) *\n var(--oc-mark-index, 0)\n );\n }\n\n /* Barlist rows: fade + slide up per row, bars grow left-to-right */\n & .oc-barlist-row {\n animation: oc-enter-fade calc(var(--oc-animation-duration) * 0.6)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: var(--oc-row-delay, 0ms);\n }\n\n & .oc-barlist-bar {\n animation: oc-enter-bar-h var(--oc-animation-duration)\n var(--oc-animation-ease, var(--oc-ease-smooth)) both;\n animation-delay: var(--oc-row-delay, 0ms);\n }\n }\n\n /* ---------------------------------------------------------------------------\n * Sparkline mode: pair the line/area reveal with a stronger ease-out so it\n * doesn't read as a uniform left-to-right swipe. cubic-bezier(0.16, 1, 0.3, 1)\n * is \"expo-out\" — fast initial draw that decelerates noticeably at the end,\n * giving the trend a hand-drawn feel. Duration is bumped via the engine\n * (compile.ts) so the cleanup timer stays in sync.\n * --------------------------------------------------------------------------- */\n\n .oc-animate[data-display=\"sparkline\"] .oc-mark-line,\n .oc-animate[data-display=\"sparkline\"] .oc-mark-area {\n animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);\n }\n}\n","@layer oc.components {\n /* ---------------------------------------------------------------------------\n * Legend\n * --------------------------------------------------------------------------- */\n\n /* Font size and text fill are set inline by the renderer's applyTextStyle\n * from the engine-computed legend layout, which is authoritative (11px).\n * Only the family, which nothing computes per-entry, lives here. */\n .oc-legend {\n font-family: var(--oc-font-family);\n }\n\n .oc-legend-entry {\n cursor: default;\n }\n}\n","@layer oc.components {\n /* ---------------------------------------------------------------------------\n * Hover language\n *\n * One vocabulary for mark hover, legend hover and the crosshair. Emphasis is\n * always a CLASS, never an inline style: a class beats the renderer's\n * `opacity` attributes (suppressed points under endpoint markers keep their\n * opacity=\"0\") and loses to the transition driver's per-frame inline\n * `style.opacity`, which is exactly the precedence a hover during a data\n * update needs.\n * --------------------------------------------------------------------------- */\n\n .oc-marks.oc-hover-active .oc-mark--dim:not([opacity=\"0\"]) {\n opacity: var(--oc-hover-dim);\n }\n\n /* Single-series register: outline the hovered mark instead of dimming eleven\n * others. Scoped per mark type -- an inherited stroke on a line or area group\n * would repaint the series in the text color. */\n .oc-marks.oc-hover-active .oc-mark-rect.oc-mark--hover > *,\n .oc-marks.oc-hover-active .oc-mark-arc.oc-mark--hover > *,\n .oc-marks.oc-hover-active circle.oc-mark-point.oc-mark--hover {\n stroke: var(--oc-text);\n stroke-width: 1;\n }\n\n /* The fade is switched off while the rAF transition driver owns opacity: an\n * unscoped 140ms transition would smear every frame of an update tween.\n * `.oc-animate` is excluded for the same reason during the entrance.\n *\n * It is NOT scoped to `.oc-hover-active`: dropping the class on mouseleave\n * would drop the transition with it, so the dim faded in and snapped back. */\n .oc-chart:not(.oc-animate):not(.oc-transitioning) .oc-marks .oc-mark {\n transition: opacity var(--oc-hover-duration) ease-out;\n }\n\n /* ---------------------------------------------------------------------------\n * Legend hover-link\n *\n * The swatch dims; the label text stays at full contrast so the list is still\n * readable while one series is raised.\n * --------------------------------------------------------------------------- */\n\n .oc-legend-entry--dim .oc-legend-swatch-line,\n .oc-legend-entry--dim .oc-legend-swatch-rect,\n .oc-legend-entry--dim > circle {\n opacity: var(--oc-hover-dim);\n transition: opacity var(--oc-hover-duration) ease-out;\n }\n\n .oc-legend-hit {\n fill: transparent;\n }\n\n .oc-legend-entry:focus {\n outline: none;\n }\n\n /* Focus ring on the 24px hit rect, drawn as a stroke: `outline` on an SVG\n * group is inconsistent across browsers, a stroke is not. */\n .oc-legend-entry:focus-visible .oc-legend-hit {\n stroke: var(--oc-focus);\n stroke-width: 2;\n }\n\n /* ---------------------------------------------------------------------------\n * Endpoint-label hover-link\n * --------------------------------------------------------------------------- */\n\n .oc-endpoint-label-entry {\n cursor: default;\n }\n\n /* ---------------------------------------------------------------------------\n * Map hover\n *\n * Feature hover is outline + raise, never dim-the-rest: toggling opacity on\n * three thousand county paths every time the pointer crosses a border is a\n * repaint storm, and the wave of fades reads as a flicker. Datawrapper and the\n * FT outline too. `non-scaling-stroke` keeps the outline 1.5px through the\n * camera's zoom transform, which otherwise scales stroke width with geometry.\n * --------------------------------------------------------------------------- */\n\n .oc-map-feature--hover {\n stroke: var(--oc-text);\n stroke-width: 1.5;\n vector-effect: non-scaling-stroke;\n }\n\n /* Legend-bin hover IS where dim-the-rest belongs: pointing at one class is a\n * deliberate \"show me these\" gesture, and the answer is the set of features in\n * that class. Static rules per class index keep it to one attribute write on\n * the group rather than a class toggle per feature. */\n .oc-map-features[data-hover] .oc-map-feature {\n transition: opacity var(--oc-hover-duration) ease-out;\n }\n\n .oc-map-features[data-hover=\"0\"] .oc-map-feature:not([data-bin-index=\"0\"]),\n .oc-map-features[data-hover=\"1\"] .oc-map-feature:not([data-bin-index=\"1\"]),\n .oc-map-features[data-hover=\"2\"] .oc-map-feature:not([data-bin-index=\"2\"]),\n .oc-map-features[data-hover=\"3\"] .oc-map-feature:not([data-bin-index=\"3\"]),\n .oc-map-features[data-hover=\"4\"] .oc-map-feature:not([data-bin-index=\"4\"]),\n .oc-map-features[data-hover=\"5\"] .oc-map-feature:not([data-bin-index=\"5\"]),\n .oc-map-features[data-hover=\"6\"] .oc-map-feature:not([data-bin-index=\"6\"]),\n .oc-map-features[data-hover=\"7\"] .oc-map-feature:not([data-bin-index=\"7\"]),\n .oc-map-features[data-hover=\"8\"] .oc-map-feature:not([data-bin-index=\"8\"]),\n .oc-map-features[data-hover=\"9\"] .oc-map-feature:not([data-bin-index=\"9\"]),\n .oc-map-features[data-hover=\"10\"] .oc-map-feature:not([data-bin-index=\"10\"]),\n .oc-map-features[data-hover=\"11\"] .oc-map-feature:not([data-bin-index=\"11\"]) {\n opacity: var(--oc-map-hover-dim);\n }\n\n .oc-legend-bin {\n cursor: default;\n }\n\n /* ---------------------------------------------------------------------------\n * Tile hover\n *\n * A tile grid is 51 rects, not 3000 paths, and every tile is the same size --\n * so here the full hover language applies: the hovered tile takes an outline\n * and the rest drop back.\n * --------------------------------------------------------------------------- */\n\n .oc-tilemap-tiles.oc-hover-active .oc-tilemap-tile {\n transition: opacity var(--oc-hover-duration) ease-out;\n }\n\n .oc-tilemap-tiles.oc-hover-active .oc-tilemap-tile:not(.oc-tilemap-tile--hover) {\n opacity: var(--oc-hover-dim);\n }\n\n .oc-tilemap-tile--hover > rect {\n stroke: var(--oc-text);\n stroke-width: 1.5;\n }\n}\n","/* ---------------------------------------------------------------------------\n * Reduced motion\n *\n * Catch-all: last-declared layer beats every earlier layer regardless of\n * specificity. No !important, no hand-maintained selector mirror.\n *\n * Selector list matches CSS_TOKEN_ROOT_SELECTORS in token-definitions.ts.\n * --------------------------------------------------------------------------- */\n\n@layer oc.reduced-motion {\n @media (prefers-reduced-motion: reduce) {\n :is(\n .oc-root,\n .oc-chart-root,\n .oc-table-wrapper,\n .oc-table-root,\n .oc-graph-wrapper,\n .oc-graph-root,\n .oc-sankey-root,\n .oc-tilemap-root,\n .oc-barlist-root,\n .oc-map-root\n ),\n :is(\n .oc-root,\n .oc-chart-root,\n .oc-table-wrapper,\n .oc-table-root,\n .oc-graph-wrapper,\n .oc-graph-root,\n .oc-sankey-root,\n .oc-tilemap-root,\n .oc-barlist-root,\n .oc-map-root\n )\n *,\n :is(\n .oc-root,\n .oc-chart-root,\n .oc-table-wrapper,\n .oc-table-root,\n .oc-graph-wrapper,\n .oc-graph-root,\n .oc-sankey-root,\n .oc-tilemap-root,\n .oc-barlist-root,\n .oc-map-root\n )\n *::before,\n :is(\n .oc-root,\n .oc-chart-root,\n .oc-table-wrapper,\n .oc-table-root,\n .oc-graph-wrapper,\n .oc-graph-root,\n .oc-sankey-root,\n .oc-tilemap-root,\n .oc-barlist-root,\n .oc-map-root\n )\n *::after {\n animation: none;\n transition: none;\n }\n }\n}\n","@layer oc.components {\n /* ---------------------------------------------------------------------------\n * Series search (seriesSearch)\n *\n * DOM combobox overlaid on the SVG band the engine reserves below chrome.\n * The wrapper is absolutely positioned by the vanilla adapter (inline\n * left/top/width/height), so everything here is visual only. All colors come\n * from --oc-* tokens, which flip in .oc-dark.\n * --------------------------------------------------------------------------- */\n\n .oc-series-search {\n position: absolute;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 8px;\n font-family: var(--oc-font-family);\n z-index: 10;\n }\n\n /* Chips: removable filter tokens for the current selection. They flow to the\n * left of the input and scroll horizontally rather than wrapping over the\n * chart when a reader picks many series. */\n .oc-series-search-chips {\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n .oc-series-search-chips::-webkit-scrollbar {\n display: none;\n }\n\n .oc-series-search-chip {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 4px 3px 10px;\n border: 1px solid var(--oc-border);\n border-radius: var(--oc-radius-full);\n background: var(--oc-secondary);\n color: var(--oc-text-secondary);\n font-size: 12px;\n font-weight: 500;\n line-height: 16px;\n white-space: nowrap;\n }\n\n .oc-series-search-chip-remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n /* 16px glyph, but a >=24px hit area (WCAG 2.5.5 target size) via padding\n pulled back with negative margin so the chip layout stays tight. */\n width: 16px;\n height: 16px;\n padding: 4px;\n margin: -4px -2px -4px -4px;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: var(--oc-text-muted);\n cursor: pointer;\n transition:\n color 0.15s,\n background-color 0.15s;\n }\n\n .oc-series-search-chip-remove:hover {\n color: var(--oc-text);\n background: var(--oc-hover-bg);\n }\n\n .oc-series-search-chip-remove:focus-visible {\n outline: 2px solid var(--oc-focus);\n outline-offset: 1px;\n }\n\n .oc-series-search-chip-remove svg {\n display: block;\n }\n\n /* Combobox: input + popup listbox. Styling matches the table search input\n * (border, radius, focus ring) so the two search surfaces read as one system. */\n .oc-series-search-box {\n position: relative;\n flex: 0 1 220px;\n min-width: 120px;\n }\n\n .oc-series-search-icon {\n position: absolute;\n left: 9px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--oc-text-muted);\n pointer-events: none;\n }\n\n /* Shared skin provided by the grouped rule in table.css.\n Only divergent props live here. */\n .oc-series-search-input {\n height: 32px;\n padding: 0 10px 0 28px;\n }\n\n .oc-series-search-listbox {\n position: absolute;\n top: calc(100% + 4px);\n right: 0;\n min-width: 100%;\n max-height: 240px;\n overflow-y: auto;\n margin: 0;\n padding: 4px;\n list-style: none;\n border: 1px solid var(--oc-border);\n border-radius: var(--oc-radius-lg);\n background: var(--oc-card);\n box-shadow: var(--oc-tooltip-shadow);\n z-index: 20;\n }\n\n .oc-series-search-option {\n padding: 6px 10px;\n border-radius: var(--oc-radius-sm);\n font-size: 13px;\n color: var(--oc-text);\n cursor: pointer;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .oc-series-search-option[aria-selected=\"true\"],\n .oc-series-search-option:hover {\n background: var(--oc-hover-bg);\n }\n\n /* The typed substring within each suggestion. */\n .oc-series-search-match {\n font-weight: 600;\n }\n\n .oc-series-search-empty {\n padding: 6px 10px;\n font-size: 12px;\n color: var(--oc-text-muted);\n }\n}\n","@layer oc.components {\n /* ---------------------------------------------------------------------------\n * Tooltip\n * Editorial card matching the new design system: zinc surface, cyan accent,\n * Inter Variable, mono numerics. Sized for a slice tooltip that lists every\n * series at the snapped x.\n * --------------------------------------------------------------------------- */\n\n .oc-tooltip {\n position: absolute;\n display: none;\n pointer-events: none;\n z-index: 1000;\n background: var(--oc-tooltip-bg);\n backdrop-filter: blur(14px);\n border: 1px solid var(--oc-tooltip-border);\n border-radius: var(--oc-radius-lg);\n box-shadow: var(--oc-tooltip-shadow);\n color: var(--oc-tooltip-text);\n font-family: var(--oc-font-family);\n font-size: 12px;\n padding: 0;\n max-width: 280px;\n min-width: 140px;\n line-height: 1.4;\n animation: oc-tooltip-in 120ms ease-out;\n transition:\n left 100ms ease-in-out,\n top 100ms ease-in-out;\n\n & .oc-tooltip-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px 6px;\n }\n\n & .oc-tooltip-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n & .oc-tooltip-title {\n font-weight: 600;\n font-size: 11px;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--oc-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n & .oc-tooltip-body {\n padding: 6px 10px 8px;\n border-top: 1px solid var(--oc-tooltip-border);\n }\n\n /* No separator when body is the only child */\n & .oc-tooltip-body:first-child {\n border-top: none;\n padding-top: 10px;\n }\n\n & .oc-tooltip-row {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 16px;\n padding: 2px 0;\n }\n\n & .oc-tooltip-row-swatch {\n display: inline-block;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n margin-right: 6px;\n flex-shrink: 0;\n transform: translateY(-1px);\n }\n\n & .oc-tooltip-label {\n color: var(--oc-text-secondary);\n font-size: 12px;\n font-weight: 400;\n white-space: nowrap;\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n }\n\n & .oc-tooltip-value {\n font-weight: 500;\n font-size: 12px;\n font-variant-numeric: tabular-nums;\n color: var(--oc-tooltip-text);\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n /* The series the pointer is nearest to in a shared tooltip. */\n & .oc-tooltip-row--emphasis .oc-tooltip-label {\n color: var(--oc-tooltip-text);\n font-weight: 600;\n }\n\n & .oc-tooltip-row--emphasis .oc-tooltip-value {\n font-weight: 600;\n }\n\n /* Stack sum, set below a hairline so it reads as a summary of the rows\n * above rather than one more series. */\n & .oc-tooltip-row--total {\n margin-top: 4px;\n padding-top: 5px;\n border-top: 1px solid var(--oc-tooltip-border);\n }\n\n & .oc-tooltip-row--total .oc-tooltip-label {\n color: var(--oc-tooltip-text);\n font-weight: 500;\n }\n\n & .oc-tooltip-row--total .oc-tooltip-value {\n font-weight: 600;\n }\n }\n\n /* ---------------------------------------------------------------------------\n * Crosshair guideline + per-series snap dots (line/area charts)\n * Animate the snap between adjacent points so the indicator slides instead\n * of jumping. ~50ms ease-in-out keeps the motion crisp without lagging.\n * --------------------------------------------------------------------------- */\n\n .oc-crosshair {\n pointer-events: none;\n transition:\n x1 50ms ease-in-out,\n x2 50ms ease-in-out;\n }\n\n .oc-snap-dots circle {\n pointer-events: none;\n transition:\n cx 50ms ease-in-out,\n cy 50ms ease-in-out;\n }\n}\n"],"names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opendata-ai/openchart-vue",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.9.0",
|
|
4
4
|
"description": "Vue 3 components for openchart: <Chart />, <DataTable />, <Graph />, <VizThemeProvider />",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Riley Hilliard",
|
|
@@ -53,9 +53,9 @@
|
|
|
53
53
|
"typecheck": "tsc --noEmit"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@opendata-ai/openchart-core": "8.
|
|
57
|
-
"@opendata-ai/openchart-engine": "8.
|
|
58
|
-
"@opendata-ai/openchart-vanilla": "8.
|
|
56
|
+
"@opendata-ai/openchart-core": "8.9.0",
|
|
57
|
+
"@opendata-ai/openchart-engine": "8.9.0",
|
|
58
|
+
"@opendata-ai/openchart-vanilla": "8.9.0"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
61
|
"vue": ">=3.3.0"
|