@opendata-ai/openchart-core 8.0.0-rc.2 → 8.0.0-rc.4
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 +61 -6
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/styles.css.map +1 -1
- package/package.json +1 -1
- package/src/styles/animation.css +9 -0
- package/src/styles/keyframes.css +17 -1
- package/src/types/index.ts +2 -0
- package/src/types/layout.ts +33 -0
- package/src/types/spec.ts +29 -5
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:.5s;--oc-animation-stagger:80ms;--oc-annotation-delay:.2s;--oc-title-size:26px;--oc-title-weight:590;--oc-title-tracking:-.022em;--oc-subtitle-size:14px;--oc-subtitle-weight:450;--oc-source-size:11px;--oc-source-weight:450;--oc-body-size:13px;--oc-eyebrow-size:11px;--oc-eyebrow-weight:550;--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-gridline:rgba(0,0,0,.1);--oc-axis:rgba(0,0,0,.1);--oc-border:rgba(0,0,0,.08);--oc-border-radius:2px;--oc-accent:#06b6d4;--oc-accent-strong:#0891b2;--oc-positive:#10b981;--oc-negative:#e11d48;--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-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,.05);--oc-axis:rgba(255,255,255,.1);--oc-border:rgba(255,255,255,.1);--oc-accent:#06b6d4;--oc-accent-strong:#06b6d4;--oc-positive:#34d399;--oc-negative:#fb7185;--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);width:100%;display:block}.oc-tilemap,.oc-map{width:100%;height:auto;display:block}.oc-map-feature{transition:opacity .4s}.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:hidden}.oc-editable-hover{outline:1.5px solid var(--oc-editable-hover);outline-offset:2px;border-radius:2px}.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:2px}}@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:510}.oc-brand-dot,.oc-eyebrow-dot{fill:var(--oc-accent)}.oc-metrics{font-family:var(--oc-font-family)}.oc-metric-label{letter-spacing:.08em;text-transform:uppercase;fill:var(--oc-text-muted);font-size:10px;font-weight:510}.oc-metric-value{letter-spacing:-.01em;fill:var(--oc-text);font-variant-numeric:tabular-nums;font-size:22px;font-weight:510}.oc-metric-delta-up{fill:var(--oc-positive);font-size:12px;font-weight:510}.oc-metric-delta-down{fill:var(--oc-negative);font-size:12px;font-weight:510}.oc-metric-secondary{fill:var(--oc-positive);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-border-radius,2px);box-shadow:var(--oc-tooltip-shadow);color:var(--oc-tooltip-text);font-family:var(--oc-font-family);min-width:160px;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 12px 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:590;overflow:hidden}.oc-tooltip .oc-tooltip-body{border-top:1px solid var(--oc-tooltip-border);padding:6px 12px 10px}.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:510;overflow:hidden}.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);font-size:var(--oc-body-size)}.oc-legend-entry{cursor:default}.oc-legend text{fill:var(--oc-legend-text)}.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);background:var(--oc-secondary);color:var(--oc-text-secondary);white-space:nowrap;border-radius:999px;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);background:var(--oc-card);min-width:100%;max-height:240px;box-shadow:var(--oc-tooltip-shadow);z-index:20;border-radius:8px;margin:0;padding:4px;list-style:none;position:absolute;top:calc(100% + 4px);right:0;overflow-y:auto}.oc-series-search-option{color:var(--oc-text);cursor:pointer;white-space:nowrap;text-overflow:ellipsis;border-radius:4px;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{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);border-radius:6px;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-reveal-button{pointer-events:auto;border:1px solid var(--oc-border);background:var(--oc-bg);color:var(--oc-text);cursor:pointer;box-shadow:var(--oc-tooltip-shadow);border-radius:6px;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-reveal-button:hover{background:var(--oc-hover-bg)}.oc-ydi-reveal-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);padding:10px 16px}.oc-table-wrapper td{text-align:left;border-bottom:1px solid var(--oc-border);padding:10px 16px}.oc-table-wrapper th{text-transform:uppercase;letter-spacing:.05em;color:var(--oc-text-secondary);white-space:nowrap;font-size:12px;font-weight:600}.oc-table-wrapper thead{z-index:2;background:var(--oc-bg);position:sticky;top:0}.oc-table-wrapper thead th{border-bottom-width:2px}.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:.45}.oc-table-sort-btn:after{border-top:4.5px solid var(--oc-text-secondary);opacity:.45}.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);background:var(--oc-bg);width:100%;color:var(--oc-text);box-sizing:border-box;border-radius:6px;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);background:var(--oc-bg);color:var(--oc-text);cursor:pointer;border-radius:6px;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{opacity:.15;pointer-events:none;border-radius:2px;position:absolute;top:6px;bottom:6px;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}.oc-table--compact th{padding:4px 8px;font-size:13px}.oc-table--compact td{padding:4px 8px;font-size:13px}.oc-table--compact th{font-size:11px}.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-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:var(--oc-bg);border:1px solid var(--oc-border);border-radius:var(--oc-border-radius);color:var(--oc-text-secondary);max-height:200px;padding:8px 12px;font-size:12px;position:absolute;top:8px;right:8px;overflow-y:auto}.oc-graph-legend-item{align-items:center;gap:6px;padding:2px 0;display:flex}.oc-graph-legend-swatch{border-radius:50%;flex-shrink:0;width:10px;height:10px}.oc-graph-search{position:absolute;top:8px;left:8px}.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-border-radius);background:var(--oc-bg);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-dark .oc-graph-wrapper,.oc-graph-wrapper.oc-dark{--oc-bg:#0d1117}.oc-dark .oc-graph-legend,.oc-dark.oc-graph-wrapper .oc-graph-legend,.oc-dark .oc-graph-search input{border-color:var(--oc-border);background:rgba(13,17,23,.85)}.oc-chart[data-display=sparkline]{margin:0;padding:0;display:block}}@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: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-tooltip-in{0%{opacity:0;transform:translateY(2px)}to{opacity:1;transform:translateY(0)}}.oc-animate .oc-mark-rect rect{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 rect{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] rect{animation-name:oc-enter-bar-h}.oc-animate .oc-mark-bar[data-orient=horizontal] rect{animation-name:oc-enter-bar-h}.oc-animate .oc-mark-rect[data-stack-pos] rect{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 .3s 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 .4s var(--oc-ease-smooth) both;animation-delay:calc(var(--oc-animation-duration) + var(--oc-annotation-delay,.2s))}.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-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:.5s;--oc-animation-stagger:80ms;--oc-annotation-delay:.2s;--oc-title-size:26px;--oc-title-weight:590;--oc-title-tracking:-.022em;--oc-subtitle-size:14px;--oc-subtitle-weight:450;--oc-source-size:11px;--oc-source-weight:450;--oc-body-size:13px;--oc-eyebrow-size:11px;--oc-eyebrow-weight:550;--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-gridline:rgba(0,0,0,.1);--oc-axis:rgba(0,0,0,.1);--oc-border:rgba(0,0,0,.08);--oc-border-radius:2px;--oc-accent:#06b6d4;--oc-accent-strong:#0891b2;--oc-positive:#10b981;--oc-negative:#e11d48;--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-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,.05);--oc-axis:rgba(255,255,255,.1);--oc-border:rgba(255,255,255,.1);--oc-accent:#06b6d4;--oc-accent-strong:#06b6d4;--oc-positive:#34d399;--oc-negative:#fb7185;--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);width:100%;display:block}.oc-tilemap,.oc-map{width:100%;height:auto;display:block}.oc-map-feature{transition:opacity .4s}.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:hidden}.oc-editable-hover{outline:1.5px solid var(--oc-editable-hover);outline-offset:2px;border-radius:2px}.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:2px}}@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:510}.oc-brand-dot,.oc-eyebrow-dot{fill:var(--oc-accent)}.oc-metrics{font-family:var(--oc-font-family)}.oc-metric-label{letter-spacing:.08em;text-transform:uppercase;fill:var(--oc-text-muted);font-size:10px;font-weight:510}.oc-metric-value{letter-spacing:-.01em;fill:var(--oc-text);font-variant-numeric:tabular-nums;font-size:22px;font-weight:510}.oc-metric-delta-up{fill:var(--oc-positive);font-size:12px;font-weight:510}.oc-metric-delta-down{fill:var(--oc-negative);font-size:12px;font-weight:510}.oc-metric-secondary{fill:var(--oc-positive);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-border-radius,2px);box-shadow:var(--oc-tooltip-shadow);color:var(--oc-tooltip-text);font-family:var(--oc-font-family);min-width:160px;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 12px 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:590;overflow:hidden}.oc-tooltip .oc-tooltip-body{border-top:1px solid var(--oc-tooltip-border);padding:6px 12px 10px}.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:510;overflow:hidden}.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);font-size:var(--oc-body-size)}.oc-legend-entry{cursor:default}.oc-legend text{fill:var(--oc-legend-text)}.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);background:var(--oc-secondary);color:var(--oc-text-secondary);white-space:nowrap;border-radius:999px;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);background:var(--oc-card);min-width:100%;max-height:240px;box-shadow:var(--oc-tooltip-shadow);z-index:20;border-radius:8px;margin:0;padding:4px;list-style:none;position:absolute;top:calc(100% + 4px);right:0;overflow-y:auto}.oc-series-search-option{color:var(--oc-text);cursor:pointer;white-space:nowrap;text-overflow:ellipsis;border-radius:4px;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{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);border-radius:6px;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-reveal-button{pointer-events:auto;border:1px solid var(--oc-border);background:var(--oc-bg);color:var(--oc-text);cursor:pointer;box-shadow:var(--oc-tooltip-shadow);border-radius:6px;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-reveal-button:hover{background:var(--oc-hover-bg)}.oc-ydi-reveal-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);padding:10px 16px}.oc-table-wrapper td{text-align:left;border-bottom:1px solid var(--oc-border);padding:10px 16px}.oc-table-wrapper th{text-transform:uppercase;letter-spacing:.05em;color:var(--oc-text-secondary);white-space:nowrap;font-size:12px;font-weight:600}.oc-table-wrapper thead{z-index:2;background:var(--oc-bg);position:sticky;top:0}.oc-table-wrapper thead th{border-bottom-width:2px}.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:.45}.oc-table-sort-btn:after{border-top:4.5px solid var(--oc-text-secondary);opacity:.45}.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);background:var(--oc-bg);width:100%;color:var(--oc-text);box-sizing:border-box;border-radius:6px;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);background:var(--oc-bg);color:var(--oc-text);cursor:pointer;border-radius:6px;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{opacity:.15;pointer-events:none;border-radius:2px;position:absolute;top:6px;bottom:6px;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}.oc-table--compact th{padding:4px 8px;font-size:13px}.oc-table--compact td{padding:4px 8px;font-size:13px}.oc-table--compact th{font-size:11px}.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-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:var(--oc-bg);border:1px solid var(--oc-border);border-radius:var(--oc-border-radius);color:var(--oc-text-secondary);max-height:200px;padding:8px 12px;font-size:12px;position:absolute;top:8px;right:8px;overflow-y:auto}.oc-graph-legend-item{align-items:center;gap:6px;padding:2px 0;display:flex}.oc-graph-legend-swatch{border-radius:50%;flex-shrink:0;width:10px;height:10px}.oc-graph-search{position:absolute;top:8px;left:8px}.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-border-radius);background:var(--oc-bg);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-dark .oc-graph-wrapper,.oc-graph-wrapper.oc-dark{--oc-bg:#0d1117}.oc-dark .oc-graph-legend,.oc-dark.oc-graph-wrapper .oc-graph-legend,.oc-dark .oc-graph-search input{border-color:var(--oc-border);background:rgba(13,17,23,.85)}.oc-chart[data-display=sparkline]{margin:0;padding:0;display:block}}@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-tooltip-in{0%{opacity:0;transform:translateY(2px)}to{opacity:1;transform:translateY(0)}}.oc-animate .oc-mark-rect rect{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 rect{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] rect{animation-name:oc-enter-bar-h}.oc-animate .oc-mark-bar[data-orient=horizontal] rect{animation-name:oc-enter-bar-h}.oc-animate .oc-mark-rect[data-stack-pos] rect{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 .3s 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 .4s var(--oc-ease-smooth) both;animation-delay:calc(var(--oc-animation-duration) + var(--oc-annotation-delay,.2s))}.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) * 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,62DEFA,4lBHAF,eKNE,mIAeA,6BAQA,qEAUA,yDAOA,uCAIA,qCASA,gJAgBA,qGAcA,4EAQA,yFLrFF,qBINE,6CAIA,2KAQA,wIAOA,+GAMA,+HAQA,wFAOA,oDAYA,8CAIA,wHAQA,4HAQA,2EAMA,6EAMA,4EAWA,8EAgBA,sDAIA,sEAMA,4EAIA,wEAaA,sFAUA,sFASA,gCAMA,mFIhKA,ogBAsBE,4FAOA,iFAOA,gMAWA,iGAMA,0EAKA,mHAQA,yJAUA,oKAUA,uMAkBF,qFAOA,4FDlHA,2EAKA,gCAIA,2CEJA,kJAaA,iHASA,wDAIA,sRAeA,6RAoBA,uFAKA,iGAKA,gDAMA,qEAMA,oIAWA,0DAKA,2RAiBA,yKAWA,0GAMA,wCAIA,mFPtIA,kDAKA,+CAKA,qGASA,wHAUA,yGAWA,qFAKA,0MAYA,oRAeA,6DAOA,mXAoBA,0DAIA,yFAKA,yDIpHA,iGAKE,qFAMA,yDAIA,4DAKA,gGAAA,gGAOA,oJASA,gFAOA,mDAIA,sEAKA,iFAKA,2CAKF,sNAOA,kPAOA,2IAKA,gJAKA,iCASE,0FAAA,0FAaF,oLAYE,mLAAA,kLAaA,yFAKA,qFAKA,4CAAA,2CAOA,+FAKA,6DAMA,4FAKA,+DAaF,iPAaA,wFAAA,8EAAA,yFAAA,+EAMA,+IAOA,+BAGE,wCASF,oJAQE,6OAaE,oEAKA,2GAKA,+FAOJ,4DAIA,+CASA,gCAIA,iHAUA,gDASA,+DAKE,kEAOF,iFAOA,mGAWA,2DAIE,qCAKF,8CAQA,+BASE,qDAAA,qDAMA,qCAUA,6CAIA,kEASF,2EASA,oHMjYA,qIASA,kEAOA,2CAIA,4GASE,8bAkBA,2RAaF,qPAcA,4EAOA,+EAOA,oDAKE,0OAUE,2GAQJ,qEAYA,iKDtHA,oEXCF,oBUJI,4JAMA,4JAOA,8NAOA,yOAOA,wRAAA,yRAcA,4RAaA,uRAYA,4RAAA,+RAaA,uKAAA,2KK/EF,8GAgBA,kHAgBA,iHAeA,4FAaA,6GAaA,yDAUA,sGAaA,uFAWA,yFAUA,sGFpHE,yLAAA,wLAOA,qFAAA,oFASA,oRAYA,8MAOA,8MASA,kNAUA,qOAAA,sOAQA,+JAAA,+JAWA,8NAOA,8NAOA,8NAOA,iMAWA,sKAOA,wJAQA,gLASA,8JAKA,+EAKA,2KAMA,0NAQA,8PAYA,uLAMA,6KAeF,wJbvLF,yBcDE,uCACE,6LAAA,+LAAA,qMAAA","sources":["../src/styles/index.css","../src/styles/tokens.css","../src/styles/you-draw-it.css","../src/styles/dark.css","../src/styles/chrome.css","../src/styles/base.css","../src/styles/table.css","../src/styles/legend.css","../src/styles/tooltip.css","../src/styles/series-search.css","../src/styles/table-animation.css","../src/styles/sparkline.css","../src/styles/graph.css","../src/styles/animation.css","../src/styles/reduced-motion.css","../src/styles/keyframes.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 \"./series-search.css\";\n@import \"./you-draw-it.css\";\n@import \"./table.css\";\n@import \"./table-animation.css\";\n@import \"./graph.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: 500ms;\n --oc-animation-stagger: 80ms;\n --oc-annotation-delay: 200ms;\n\n /* Typography scale (editorial design system) */\n --oc-title-size: 26px;\n --oc-title-weight: 590;\n --oc-title-tracking: -0.022em;\n --oc-subtitle-size: 14px;\n --oc-subtitle-weight: 450;\n --oc-source-size: 11px;\n --oc-source-weight: 450;\n --oc-body-size: 13px;\n --oc-eyebrow-size: 11px;\n --oc-eyebrow-weight: 550;\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 /* Lines */\n --oc-gridline: rgba(0, 0, 0, 0.1);\n --oc-axis: rgba(0, 0, 0, 0.1);\n --oc-border: rgba(0, 0, 0, 0.08);\n --oc-border-radius: 2px;\n\n /* Brand and semantic */\n --oc-accent: #06b6d4;\n --oc-accent-strong: #0891b2; /* darker cyan for line strokes on light bg */\n --oc-positive: #10b981;\n --oc-negative: #e11d48;\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 /* 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: 6px;\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 /* Skip-to-reveal button. pointer-events re-enabled (the overlay disables it)\n * so it stays clickable and keyboard-reachable. Min height enforced inline by\n * the adapter (>= 24px effective touch target). */\n .oc-ydi-reveal-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: 6px;\n background: var(--oc-bg);\n color: var(--oc-text);\n font-family: inherit;\n font-size: 13px;\n font-weight: 500;\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-reveal-button:hover {\n background: var(--oc-hover-bg);\n }\n\n .oc-ydi-reveal-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.05);\n --oc-axis: rgba(255, 255, 255, 0.1);\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: #34d399;\n --oc-negative: #fb7185;\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 * 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: 510;\n letter-spacing: 0.02em;\n fill: var(--oc-text-faint);\n }\n\n .oc-brand-dot {\n fill: var(--oc-accent);\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: 10px;\n font-weight: 510;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n fill: var(--oc-text-muted);\n }\n\n .oc-metric-value {\n font-size: 22px;\n font-weight: 510;\n letter-spacing: -0.01em;\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: 510;\n }\n\n .oc-metric-delta-down {\n fill: var(--oc-negative);\n font-size: 12px;\n font-weight: 510;\n }\n\n .oc-metric-secondary {\n fill: var(--oc-positive);\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.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 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: opacity 400ms ease;\n }\n\n .oc-barlist {\n display: block;\n width: 100%;\n }\n\n /* ---------------------------------------------------------------------------\n * Screen reader only utility\n * --------------------------------------------------------------------------- */\n\n .oc-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\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: 2px;\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: 2px;\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 padding: 10px 16px;\n text-align: left;\n border-bottom: 1px solid var(--oc-border);\n }\n\n & th {\n font-weight: 600;\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--oc-text-secondary);\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 & thead th {\n border-bottom-width: 2px;\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.45;\n }\n\n &::after {\n border-top: 4.5px solid var(--oc-text-secondary);\n opacity: 0.45;\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: 6px;\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: 6px;\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: 6px;\n left: 0;\n bottom: 6px;\n border-radius: 2px;\n opacity: 0.15;\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 * Compact mode\n * --------------------------------------------------------------------------- */\n\n .oc-table--compact {\n & th,\n & td {\n padding: 4px 8px;\n font-size: 13px;\n }\n\n & th {\n font-size: 11px;\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.components {\n /* ---------------------------------------------------------------------------\n * Legend\n * --------------------------------------------------------------------------- */\n\n .oc-legend {\n font-family: var(--oc-font-family);\n font-size: var(--oc-body-size);\n }\n\n .oc-legend-entry {\n cursor: default;\n }\n\n .oc-legend text {\n fill: var(--oc-legend-text);\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-border-radius, 2px);\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: 160px;\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 12px 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: 590;\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 12px 10px;\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: 510;\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\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","@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: 999px;\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: 8px;\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: 4px;\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.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 * 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","@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 .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: 8px;\n right: 8px;\n background: var(--oc-bg);\n border: 1px solid var(--oc-border);\n border-radius: var(--oc-border-radius);\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 }\n\n .oc-graph-legend-swatch {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n .oc-graph-search {\n position: absolute;\n top: 8px;\n left: 8px;\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-border-radius);\n background: var(--oc-bg);\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 /* Dark mode graph overrides (darker bg for canvas-based rendering) */\n .oc-dark .oc-graph-wrapper,\n .oc-graph-wrapper.oc-dark {\n /* GitHub-dark canvas background, intentionally not a token */\n --oc-bg: #0d1117;\n }\n\n /*\n * graph-mount.ts stamps .oc-dark on both .oc-graph-wrapper and\n * .oc-graph-container simultaneously, so the self-variant\n * (.oc-dark.oc-graph-wrapper) and descendant variant\n * (.oc-dark .oc-graph-legend) resolve identically.\n */\n .oc-dark .oc-graph-legend,\n .oc-dark.oc-graph-wrapper .oc-graph-legend,\n .oc-dark .oc-graph-search input {\n background: rgba(13, 17, 23, 0.85);\n border-color: var(--oc-border);\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 & .oc-mark-rect rect,\n & .oc-mark-bar rect {\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\"] rect,\n & .oc-mark-bar[data-orient=\"horizontal\"] rect {\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] rect {\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 300ms 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 400ms var(--oc-ease-smooth) both;\n animation-delay: calc(var(--oc-animation-duration) + var(--oc-annotation-delay, 200ms));\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 /* 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","/* ---------------------------------------------------------------------------\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.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. */\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: 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 /* 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"],"names":[]}
|
|
1
|
+
{"version":3,"mappings":"AAWA,iBCEE,62DEFA,4lBHAF,eONE,mIAeA,6BAQA,qEAUA,yDAOA,uCAIA,qCASA,gJAgBA,qGAcA,4EAQA,yFPrFF,qBINE,6CAIA,2KAQA,wIAOA,+GAMA,+HAQA,wFAOA,oDAYA,8CAIA,wHAQA,4HAQA,2EAMA,6EAMA,4EAWA,8EAgBA,sDAIA,sEAMA,4EAIA,wEAaA,sFAUA,sFASA,gCAMA,mFIhKA,ogBAsBE,4FAOA,iFAOA,gMAWA,iGAMA,0EAKA,mHAQA,yJAUA,oKAUA,uMAkBF,qFAOA,4FHlHA,2EAKA,gCAIA,2CIJA,kJAaA,iHASA,wDAIA,sRAeA,6RAoBA,uFAKA,iGAKA,gDAMA,qEAMA,oIAWA,0DAKA,2RAiBA,yKAWA,0GAMA,wCAIA,mFPtIA,kDAKA,+CAKA,qGASA,wHAUA,yGAWA,qFAKA,0MAYA,oRAeA,6DAOA,mXAoBA,0DAIA,yFAKA,yDIpHA,iGAKE,qFAMA,yDAIA,4DAKA,gGAAA,gGAOA,oJASA,gFAOA,mDAIA,sEAKA,iFAKA,2CAKF,sNAOA,kPAOA,2IAKA,gJAKA,iCASE,0FAAA,0FAaF,oLAYE,mLAAA,kLAaA,yFAKA,qFAKA,4CAAA,2CAOA,+FAKA,6DAMA,4FAKA,+DAaF,iPAaA,wFAAA,8EAAA,yFAAA,+EAMA,+IAOA,+BAGE,wCASF,oJAQE,6OAaE,oEAKA,2GAKA,+FAOJ,4DAIA,+CASA,gCAIA,iHAUA,gDASA,+DAKE,kEAOF,iFAOA,mGAWA,2DAIE,qCAKF,8CAQA,+BASE,qDAAA,qDAMA,qCAUA,6CAIA,kEASF,2EASA,oHQjYA,qIASA,kEAOA,2CAIA,4GASE,8bAkBA,2RAaF,qPAcA,4EAOA,+EAOA,oDAKE,0OAUE,2GAQJ,qEAYA,iKHtHA,oEXCF,oBUJI,4JAMA,4JAOA,8NAOA,yOAOA,wRAAA,yRAcA,4RAaA,uRAYA,4RAAA,+RAaA,uKAAA,2KG/EF,8GAgBA,kHAgBA,iHAeA,4FAgBA,8IAaA,iGAaA,yDAUA,sGAaA,uFAWA,yFAUA,sGDpIE,yLAAA,wLAOA,qFAAA,oFASA,oRAYA,8MAOA,8MASA,kNAUA,qOAAA,sOAQA,+JAAA,+JAWA,8NAOA,8NAOA,8NAOA,iMAWA,sKAOA,wJAQA,gLASA,8JAKA,+EAKA,2KAQA,2OAOA,0NAQA,8PAYA,uLAMA,6KAeF,wJZhMF,yBeDE,uCACE,6LAAA,+LAAA,qMAAA","sources":["../src/styles/index.css","../src/styles/tokens.css","../src/styles/you-draw-it.css","../src/styles/dark.css","../src/styles/chrome.css","../src/styles/legend.css","../src/styles/table.css","../src/styles/base.css","../src/styles/tooltip.css","../src/styles/series-search.css","../src/styles/table-animation.css","../src/styles/sparkline.css","../src/styles/graph.css","../src/styles/keyframes.css","../src/styles/reduced-motion.css","../src/styles/animation.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 \"./series-search.css\";\n@import \"./you-draw-it.css\";\n@import \"./table.css\";\n@import \"./table-animation.css\";\n@import \"./graph.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: 500ms;\n --oc-animation-stagger: 80ms;\n --oc-annotation-delay: 200ms;\n\n /* Typography scale (editorial design system) */\n --oc-title-size: 26px;\n --oc-title-weight: 590;\n --oc-title-tracking: -0.022em;\n --oc-subtitle-size: 14px;\n --oc-subtitle-weight: 450;\n --oc-source-size: 11px;\n --oc-source-weight: 450;\n --oc-body-size: 13px;\n --oc-eyebrow-size: 11px;\n --oc-eyebrow-weight: 550;\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 /* Lines */\n --oc-gridline: rgba(0, 0, 0, 0.1);\n --oc-axis: rgba(0, 0, 0, 0.1);\n --oc-border: rgba(0, 0, 0, 0.08);\n --oc-border-radius: 2px;\n\n /* Brand and semantic */\n --oc-accent: #06b6d4;\n --oc-accent-strong: #0891b2; /* darker cyan for line strokes on light bg */\n --oc-positive: #10b981;\n --oc-negative: #e11d48;\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 /* 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: 6px;\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 /* Skip-to-reveal button. pointer-events re-enabled (the overlay disables it)\n * so it stays clickable and keyboard-reachable. Min height enforced inline by\n * the adapter (>= 24px effective touch target). */\n .oc-ydi-reveal-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: 6px;\n background: var(--oc-bg);\n color: var(--oc-text);\n font-family: inherit;\n font-size: 13px;\n font-weight: 500;\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-reveal-button:hover {\n background: var(--oc-hover-bg);\n }\n\n .oc-ydi-reveal-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.05);\n --oc-axis: rgba(255, 255, 255, 0.1);\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: #34d399;\n --oc-negative: #fb7185;\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 * 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: 510;\n letter-spacing: 0.02em;\n fill: var(--oc-text-faint);\n }\n\n .oc-brand-dot {\n fill: var(--oc-accent);\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: 10px;\n font-weight: 510;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n fill: var(--oc-text-muted);\n }\n\n .oc-metric-value {\n font-size: 22px;\n font-weight: 510;\n letter-spacing: -0.01em;\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: 510;\n }\n\n .oc-metric-delta-down {\n fill: var(--oc-negative);\n font-size: 12px;\n font-weight: 510;\n }\n\n .oc-metric-secondary {\n fill: var(--oc-positive);\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 * Legend\n * --------------------------------------------------------------------------- */\n\n .oc-legend {\n font-family: var(--oc-font-family);\n font-size: var(--oc-body-size);\n }\n\n .oc-legend-entry {\n cursor: default;\n }\n\n .oc-legend text {\n fill: var(--oc-legend-text);\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 padding: 10px 16px;\n text-align: left;\n border-bottom: 1px solid var(--oc-border);\n }\n\n & th {\n font-weight: 600;\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--oc-text-secondary);\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 & thead th {\n border-bottom-width: 2px;\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.45;\n }\n\n &::after {\n border-top: 4.5px solid var(--oc-text-secondary);\n opacity: 0.45;\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: 6px;\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: 6px;\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: 6px;\n left: 0;\n bottom: 6px;\n border-radius: 2px;\n opacity: 0.15;\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 * Compact mode\n * --------------------------------------------------------------------------- */\n\n .oc-table--compact {\n & th,\n & td {\n padding: 4px 8px;\n font-size: 13px;\n }\n\n & th {\n font-size: 11px;\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 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: opacity 400ms ease;\n }\n\n .oc-barlist {\n display: block;\n width: 100%;\n }\n\n /* ---------------------------------------------------------------------------\n * Screen reader only utility\n * --------------------------------------------------------------------------- */\n\n .oc-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\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: 2px;\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: 2px;\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-border-radius, 2px);\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: 160px;\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 12px 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: 590;\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 12px 10px;\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: 510;\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\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","@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: 999px;\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: 8px;\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: 4px;\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.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 * 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","@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 .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: 8px;\n right: 8px;\n background: var(--oc-bg);\n border: 1px solid var(--oc-border);\n border-radius: var(--oc-border-radius);\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 }\n\n .oc-graph-legend-swatch {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n .oc-graph-search {\n position: absolute;\n top: 8px;\n left: 8px;\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-border-radius);\n background: var(--oc-bg);\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 /* Dark mode graph overrides (darker bg for canvas-based rendering) */\n .oc-dark .oc-graph-wrapper,\n .oc-graph-wrapper.oc-dark {\n /* GitHub-dark canvas background, intentionally not a token */\n --oc-bg: #0d1117;\n }\n\n /*\n * graph-mount.ts stamps .oc-dark on both .oc-graph-wrapper and\n * .oc-graph-container simultaneously, so the self-variant\n * (.oc-dark.oc-graph-wrapper) and descendant variant\n * (.oc-dark .oc-graph-legend) resolve identically.\n */\n .oc-dark .oc-graph-legend,\n .oc-dark.oc-graph-wrapper .oc-graph-legend,\n .oc-dark .oc-graph-search input {\n background: rgba(13, 17, 23, 0.85);\n border-color: var(--oc-border);\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 @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 /* 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","/* ---------------------------------------------------------------------------\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.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 & .oc-mark-rect rect,\n & .oc-mark-bar rect {\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\"] rect,\n & .oc-mark-bar[data-orient=\"horizontal\"] rect {\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] rect {\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 300ms 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 400ms var(--oc-ease-smooth) both;\n animation-delay: calc(var(--oc-animation-duration) + var(--oc-annotation-delay, 200ms));\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(var(--oc-animation-duration) * 0.8 + var(--oc-mark-index, 0) * 60ms);\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"],"names":[]}
|
package/package.json
CHANGED
package/src/styles/animation.css
CHANGED
|
@@ -150,6 +150,15 @@
|
|
|
150
150
|
animation-delay: calc(var(--oc-animation-duration) * 0.7);
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
+
/* Map points: gentle scale (0.75->1) + fade pop-in after borders.
|
|
154
|
+
transform-origin set per-circle in the renderer so scale happens
|
|
155
|
+
around each circle's own center, not the SVG origin. */
|
|
156
|
+
& .oc-map-point {
|
|
157
|
+
animation: oc-enter-map-point calc(var(--oc-animation-duration) * 0.4)
|
|
158
|
+
var(--oc-animation-ease, var(--oc-ease-smooth)) both;
|
|
159
|
+
animation-delay: calc(var(--oc-animation-duration) * 0.8 + var(--oc-mark-index, 0) * 60ms);
|
|
160
|
+
}
|
|
161
|
+
|
|
153
162
|
/* Sankey nodes: fade in with stagger by column depth (left-to-right) */
|
|
154
163
|
& .oc-sankey-node rect {
|
|
155
164
|
animation: oc-enter-fade-only var(--oc-animation-duration)
|
package/src/styles/keyframes.css
CHANGED
|
@@ -64,7 +64,10 @@
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
/* Map feature entrance: fade in while transitioning fill from a neutral base
|
|
67
|
-
to the data-driven color stored in --oc-feature-fill.
|
|
67
|
+
to the data-driven color stored in --oc-feature-fill. The target opacity is
|
|
68
|
+
--oc-feature-target-opacity (default 1) so features under a focus dim
|
|
69
|
+
animate straight to their dimmed rest opacity instead of hitting 1 and then
|
|
70
|
+
snapping down when the dim is applied post-animation. */
|
|
68
71
|
@keyframes oc-enter-map-fill {
|
|
69
72
|
from {
|
|
70
73
|
fill: var(--oc-secondary);
|
|
@@ -72,7 +75,20 @@
|
|
|
72
75
|
}
|
|
73
76
|
to {
|
|
74
77
|
fill: var(--oc-feature-fill);
|
|
78
|
+
opacity: var(--oc-feature-target-opacity, 1);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* Map point pop-in: gentle scale from 0.75 + fade. Uses transform-origin to
|
|
83
|
+
scale from the circle's own center (cx/cy) rather than the SVG origin. */
|
|
84
|
+
@keyframes oc-enter-map-point {
|
|
85
|
+
from {
|
|
86
|
+
opacity: 0;
|
|
87
|
+
transform: scale(0.75);
|
|
88
|
+
}
|
|
89
|
+
to {
|
|
75
90
|
opacity: 1;
|
|
91
|
+
transform: scale(1);
|
|
76
92
|
}
|
|
77
93
|
}
|
|
78
94
|
|
package/src/types/index.ts
CHANGED
|
@@ -69,6 +69,7 @@ export type {
|
|
|
69
69
|
MapFeatureMark,
|
|
70
70
|
MapFocusLayout,
|
|
71
71
|
MapLayout,
|
|
72
|
+
MapPointMark,
|
|
72
73
|
Margins,
|
|
73
74
|
Mark,
|
|
74
75
|
MarkAria,
|
|
@@ -188,6 +189,7 @@ export type {
|
|
|
188
189
|
MapEncoding,
|
|
189
190
|
MapFocus,
|
|
190
191
|
MapGeo,
|
|
192
|
+
MapPointsLayer,
|
|
191
193
|
MapProjection,
|
|
192
194
|
MapSpec,
|
|
193
195
|
MapSpecWithoutData,
|
package/src/types/layout.ts
CHANGED
|
@@ -1749,6 +1749,33 @@ export interface MapFeatureMark {
|
|
|
1749
1749
|
centroid: [number, number];
|
|
1750
1750
|
}
|
|
1751
1751
|
|
|
1752
|
+
/** A resolved map point mark with projected coordinates and visual properties. */
|
|
1753
|
+
export interface MapPointMark {
|
|
1754
|
+
type: 'map-point';
|
|
1755
|
+
/** Projected center x in map-local coordinates. */
|
|
1756
|
+
cx: number;
|
|
1757
|
+
/** Projected center y in map-local coordinates. */
|
|
1758
|
+
cy: number;
|
|
1759
|
+
/** Radius in pixels (base radius before camera counter-scaling). */
|
|
1760
|
+
r: number;
|
|
1761
|
+
/** CSS fill color. */
|
|
1762
|
+
fill: string;
|
|
1763
|
+
/** CSS stroke color. */
|
|
1764
|
+
stroke: string;
|
|
1765
|
+
/** Stroke width in px. */
|
|
1766
|
+
strokeWidth: number;
|
|
1767
|
+
/** Fill opacity (0-1). */
|
|
1768
|
+
fillOpacity: number;
|
|
1769
|
+
/** Stable key for events. */
|
|
1770
|
+
key: string;
|
|
1771
|
+
/** Original data row. */
|
|
1772
|
+
data: Record<string, unknown>;
|
|
1773
|
+
/** Accessibility attributes. */
|
|
1774
|
+
aria: MarkAria;
|
|
1775
|
+
/** Index for stagger animation ordering. */
|
|
1776
|
+
animationIndex: number;
|
|
1777
|
+
}
|
|
1778
|
+
|
|
1752
1779
|
/** Border paths for the map (interior borders and coastline/outline). */
|
|
1753
1780
|
export interface MapBorders {
|
|
1754
1781
|
/** SVG path `d` for interior borders between features. */
|
|
@@ -1777,6 +1804,12 @@ export interface MapLayout {
|
|
|
1777
1804
|
features: MapFeatureMark[];
|
|
1778
1805
|
/** Border paths (interior mesh and outline). */
|
|
1779
1806
|
borders: MapBorders;
|
|
1807
|
+
/** Resolved point marks for the symbol layer (empty array if no points layer). */
|
|
1808
|
+
pointMarks: MapPointMark[];
|
|
1809
|
+
/** Categorical legend for the point color channel (null if no point color). */
|
|
1810
|
+
pointCategoricalLegend: CategoricalLegendLayout | null;
|
|
1811
|
+
/** Continuous legend for the point color channel (null if no point color). */
|
|
1812
|
+
pointContinuousLegend: ContinuousLegendLayout | null;
|
|
1780
1813
|
/** Continuous color legend for quantitative mode (null if hidden or categorical). */
|
|
1781
1814
|
continuousLegend: ContinuousLegendLayout | null;
|
|
1782
1815
|
/** Categorical swatch legend for nominal mode (null if hidden or quantitative). */
|
package/src/types/spec.ts
CHANGED
|
@@ -2309,14 +2309,34 @@ export interface MapGeo {
|
|
|
2309
2309
|
|
|
2310
2310
|
/** Encoding channels specific to map visualizations. */
|
|
2311
2311
|
export interface MapEncoding {
|
|
2312
|
-
/** Join key field in the data
|
|
2313
|
-
key
|
|
2314
|
-
/** Color encoding (
|
|
2315
|
-
color
|
|
2312
|
+
/** Join key field in the data. Required for choropleth; optional in basemap-only mode (points layer with empty data). */
|
|
2313
|
+
key?: EncodingChannel;
|
|
2314
|
+
/** Color encoding (quantitative or nominal). Drives fill color of features. Optional when a points layer is present (basemap-only mode). */
|
|
2315
|
+
color?: EncodingChannel;
|
|
2316
2316
|
/** Tooltip encoding (optional). */
|
|
2317
2317
|
tooltip?: EncodingChannel | EncodingChannel[];
|
|
2318
2318
|
}
|
|
2319
2319
|
|
|
2320
|
+
/** Point/symbol layer rendered above choropleth features. */
|
|
2321
|
+
export interface MapPointsLayer {
|
|
2322
|
+
/** Tabular data for the points. Independent of the choropleth data join. */
|
|
2323
|
+
data: DataRow[];
|
|
2324
|
+
/** Field holding longitude (x coordinate). */
|
|
2325
|
+
longitude: EncodingChannel;
|
|
2326
|
+
/** Field holding latitude (y coordinate). */
|
|
2327
|
+
latitude: EncodingChannel;
|
|
2328
|
+
/** Optional quantitative size encoding. Area-proportional: r proportional to sqrt(value). No size legend is rendered in v1; explain the scale in chrome.subtitle if needed. */
|
|
2329
|
+
size?: EncodingChannel;
|
|
2330
|
+
/** Optional color encoding (nominal or quantitative). Independent scale from choropleth. */
|
|
2331
|
+
color?: EncodingChannel;
|
|
2332
|
+
/** Tooltip channel(s), same shape as MapEncoding.tooltip. */
|
|
2333
|
+
tooltip?: EncodingChannel | EncodingChannel[];
|
|
2334
|
+
/** Stable id for event callbacks. Data-update transitions for points are not yet supported. */
|
|
2335
|
+
key?: EncodingChannel;
|
|
2336
|
+
/** Fill opacity for point circles. Default 0.65. Range 0-1. */
|
|
2337
|
+
opacity?: number;
|
|
2338
|
+
}
|
|
2339
|
+
|
|
2320
2340
|
export interface MapSpec {
|
|
2321
2341
|
/** Discriminant: always "map". */
|
|
2322
2342
|
type: 'map';
|
|
@@ -2336,6 +2356,8 @@ export interface MapSpec {
|
|
|
2336
2356
|
darkMode?: DarkMode;
|
|
2337
2357
|
/** Whether to show the tryOpenData.ai watermark. Defaults to true. */
|
|
2338
2358
|
watermark?: boolean;
|
|
2359
|
+
/** Optional point/symbol layer rendered above choropleth features. */
|
|
2360
|
+
points?: MapPointsLayer;
|
|
2339
2361
|
/** Animation configuration for entrance animations. */
|
|
2340
2362
|
animation?: AnimationSpec;
|
|
2341
2363
|
/**
|
|
@@ -2441,7 +2463,9 @@ export type SankeySpecWithoutData = Omit<SankeySpec, 'data'>;
|
|
|
2441
2463
|
/** TileMap spec without runtime data, for persistence/storage. */
|
|
2442
2464
|
export type TileMapSpecWithoutData = Omit<TileMapSpec, 'data'>;
|
|
2443
2465
|
/** Map spec without runtime data, for persistence/storage. */
|
|
2444
|
-
export type MapSpecWithoutData = Omit<MapSpec, 'data'
|
|
2466
|
+
export type MapSpecWithoutData = Omit<MapSpec, 'data' | 'points'> & {
|
|
2467
|
+
points?: Omit<MapPointsLayer, 'data'>;
|
|
2468
|
+
};
|
|
2445
2469
|
/** BarList spec without runtime data, for persistence/storage. */
|
|
2446
2470
|
export type BarListSpecWithoutData = Omit<BarListSpec, 'data'>;
|
|
2447
2471
|
/** Union of data-stripped spec types for persistence/storage. */
|