@digithings-ai/ui 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -2
- package/package.json +143 -4
- package/src/components/NavShell.tsx +776 -0
- package/src/components/SocialRow.tsx +87 -0
- package/src/components/Spinner.tsx +27 -0
- package/src/components/StackLogo.tsx +40 -0
- package/src/components/Terminal.tsx +110 -0
- package/src/components/TerminalManifest.tsx +212 -0
- package/src/components/ThemeProvider.tsx +271 -0
- package/src/components/account/AuthCard.tsx +309 -0
- package/src/components/assistant-ui/elements/mermaid-diagram.aui.tsx +63 -0
- package/src/components/assistant-ui/elements/mermaid-diagram.tsx +340 -0
- package/src/components/brand/BrandWordmark.tsx +32 -0
- package/src/components/changelog/ReleaseRail.tsx +81 -0
- package/src/components/changelog/index.ts +1 -0
- package/src/components/chat/ChatCodeBlock.tsx +67 -0
- package/src/components/chat/ChatMarkdown.tsx +66 -0
- package/src/components/chat/ChatMarkdownSource.tsx +203 -0
- package/src/components/chat/ChatMermaidBlock.tsx +202 -0
- package/src/components/chat/ChatMessage.tsx +77 -0
- package/src/components/chat/ChatPlayback.tsx +422 -0
- package/src/components/chat/ChatStreamCursor.tsx +25 -0
- package/src/components/chat/ChatThinking.tsx +113 -0
- package/src/components/chat/ChatToolCall.tsx +190 -0
- package/src/components/chat/ChatTranscript.tsx +60 -0
- package/src/components/chat/ChatWidgetFrame.tsx +107 -0
- package/src/components/chat/DigichatBootLoader.tsx +683 -0
- package/src/components/chat/DigichatLauncher.tsx +361 -0
- package/src/components/chat/DigichatThread.tsx +118 -0
- package/src/components/chat/DigichatThreadList.tsx +54 -0
- package/src/components/chat/DigichatWordmark.tsx +24 -0
- package/src/components/chat/DotMatrix.tsx +650 -0
- package/src/components/chat/boot-lab.tsx +766 -0
- package/src/components/chat/boot-signal.ts +144 -0
- package/src/components/chat/chat-surfaces.ts +52 -0
- package/src/components/chat/connection-status.ts +40 -0
- package/src/components/chat/digichat-wordmark.ts +355 -0
- package/src/components/chat/disclosure-chevron.tsx +49 -0
- package/src/components/chat/followable-href.ts +9 -0
- package/src/components/chat/gallery-thread/action-icons.tsx +25 -0
- package/src/components/chat/gallery-thread/attachment.aui.tsx +262 -0
- package/src/components/chat/gallery-thread/block-caret.tsx +439 -0
- package/src/components/chat/gallery-thread/cn.ts +1 -0
- package/src/components/chat/gallery-thread/composer-keyboard.ts +106 -0
- package/src/components/chat/gallery-thread/composer-trigger-popover.aui.tsx +235 -0
- package/src/components/chat/gallery-thread/css.d.ts +6 -0
- package/src/components/chat/gallery-thread/file.tsx +238 -0
- package/src/components/chat/gallery-thread/follow-up-suggestions.aui.tsx +92 -0
- package/src/components/chat/gallery-thread/format-json-dump.ts +112 -0
- package/src/components/chat/gallery-thread/hooks/use-attachment-src.ts +46 -0
- package/src/components/chat/gallery-thread/hooks/use-copy-to-clipboard.ts +9 -0
- package/src/components/chat/gallery-thread/image.tsx +519 -0
- package/src/components/chat/gallery-thread/markdown-text.tsx +278 -0
- package/src/components/chat/gallery-thread/message-error.aui.tsx +105 -0
- package/src/components/chat/gallery-thread/message-timing.aui.tsx +143 -0
- package/src/components/chat/gallery-thread/private-work-step.tsx +188 -0
- package/src/components/chat/gallery-thread/reasoning.tsx +332 -0
- package/src/components/chat/gallery-thread/scroll-mode.ts +174 -0
- package/src/components/chat/gallery-thread/source.tsx +76 -0
- package/src/components/chat/gallery-thread/thread.aui.tsx +1619 -0
- package/src/components/chat/gallery-thread/tooltip-icon-button.tsx +53 -0
- package/src/components/chat/gallery-thread/typed-welcome-copy.tsx +18 -0
- package/src/components/chat/gallery-thread/ui/tooltip.tsx +22 -0
- package/src/components/chat/gallery-thread/work-chain-summary.tsx +48 -0
- package/src/components/chat/gallery-thread/work-chain.tsx +110 -0
- package/src/components/chat/gallery-thread/work-status.ts +66 -0
- package/src/components/chat/overlay-scrollbar.tsx +86 -0
- package/src/components/chat/sanitize-mermaid-svg.ts +38 -0
- package/src/components/chat/skins/SOURCE.md +36 -0
- package/src/components/chat/skins/base/attachment.aui.tsx +287 -0
- package/src/components/chat/skins/base/aui-default/README.md +45 -0
- package/src/components/chat/skins/base/aui-default/collapsible-root.tsx +19 -0
- package/src/components/chat/skins/base/aui-default/collapsible.tsx +21 -0
- package/src/components/chat/skins/base/aui-default/reasoning.aui.tsx +120 -0
- package/src/components/chat/skins/base/aui-default/reasoning.tsx +331 -0
- package/src/components/chat/skins/base/aui-default/surfaces.ts +7 -0
- package/src/components/chat/skins/base/aui-default/tool-fallback.aui.tsx +772 -0
- package/src/components/chat/skins/base/aui-default/tool-group.aui.tsx +241 -0
- package/src/components/chat/skins/base/docs-model-options.ts +6 -0
- package/src/components/chat/skins/base/elements/assistant-trace.aui.tsx +169 -0
- package/src/components/chat/skins/base/elements/composer-trigger-popover.aui.tsx +271 -0
- package/src/components/chat/skins/base/elements/directive-text.aui.tsx +29 -0
- package/src/components/chat/skins/base/elements/directive-text.tsx +76 -0
- package/src/components/chat/skins/base/elements/message-timing.aui.tsx +104 -0
- package/src/components/chat/skins/base/elements/model-selector.aui.tsx +140 -0
- package/src/components/chat/skins/base/elements/model-selector.tsx +720 -0
- package/src/components/chat/skins/base/elements/quote.aui.tsx +290 -0
- package/src/components/chat/skins/base/elements/work-chain.tsx +100 -0
- package/src/components/chat/skins/base/markdown-text.tsx +294 -0
- package/src/components/chat/skins/base/model.ts +1 -0
- package/src/components/chat/skins/base/thread.tsx +1050 -0
- package/src/components/chat/skins/base/tooltip-icon-button.tsx +56 -0
- package/src/components/chat/skins/base/ui/avatar.tsx +115 -0
- package/src/components/chat/skins/base/ui/badge.tsx +51 -0
- package/src/components/chat/skins/base/ui/button.tsx +67 -0
- package/src/components/chat/skins/base/ui/command.tsx +185 -0
- package/src/components/chat/skins/base/ui/dialog.tsx +168 -0
- package/src/components/chat/skins/base/ui/dot-matrix.tsx +267 -0
- package/src/components/chat/skins/base/ui/popover.tsx +97 -0
- package/src/components/chat/skins/base/ui/skeleton.tsx +20 -0
- package/src/components/chat/skins/base/ui/textarea.tsx +24 -0
- package/src/components/chat/skins/base/ui/tooltip.tsx +73 -0
- package/src/components/chat/skins/base-assistant-ui/config-provider.tsx +90 -0
- package/src/components/chat/skins/base-assistant-ui/defaults.ts +419 -0
- package/src/components/chat/skins/base-assistant-ui/index.tsx +44 -0
- package/src/components/chat/skins/chatgpt.tsx +448 -0
- package/src/components/chat/skins/claude.tsx +380 -0
- package/src/components/chat/skins/digichat-composer-toolbar.tsx +151 -0
- package/src/components/chat/skins/digichat-context-meter-shares.ts +158 -0
- package/src/components/chat/skins/digichat-context-meter.tsx +243 -0
- package/src/components/chat/skins/digichat-meter-tone.ts +26 -0
- package/src/components/chat/skins/digichat-usage-meter.tsx +103 -0
- package/src/components/chat/skins/digichat.tsx +144 -0
- package/src/components/chat/skins/expo-react-native.tsx +29 -0
- package/src/components/chat/skins/gemini.tsx +322 -0
- package/src/components/chat/skins/grok-icon.tsx +34 -0
- package/src/components/chat/skins/grok.tsx +369 -0
- package/src/components/chat/skins/index.ts +46 -0
- package/src/components/chat/skins/perplexity.tsx +462 -0
- package/src/components/chat/skins/product-page-assistant/assistant-modal.tsx +73 -0
- package/src/components/chat/skins/product-page-assistant/index.tsx +19 -0
- package/src/components/chat/skins/product-page-assistant/product-dashboard.tsx +164 -0
- package/src/components/chat/skins/react-ink.tsx +97 -0
- package/src/components/chat/skins/thread-skin-host-contract.ts +102 -0
- package/src/components/chat/skins/thread-skin-view.tsx +156 -0
- package/src/components/chat/skins/thread-skins.ts +143 -0
- package/src/components/chat/skins/tooltip-icon-button.tsx +35 -0
- package/src/components/chat/skins/ui/dropdown-menu.tsx +272 -0
- package/src/components/chat/skins/webpage-assistant/assistant-config.ts +238 -0
- package/src/components/chat/skins/webpage-assistant/assistant-modal.tsx +78 -0
- package/src/components/chat/skins/webpage-assistant/config-provider.tsx +132 -0
- package/src/components/chat/skins/webpage-assistant/docs-app.tsx +106 -0
- package/src/components/chat/skins/webpage-assistant/docs-article.tsx +109 -0
- package/src/components/chat/skins/webpage-assistant/docs-assistant.tsx +73 -0
- package/src/components/chat/skins/webpage-assistant/docs-nav.tsx +81 -0
- package/src/components/chat/skins/webpage-assistant/host-ui.ts +79 -0
- package/src/components/chat/skins/webpage-assistant/index.tsx +12 -0
- package/src/components/chat/skins/webpage-assistant/markdown-page.tsx +11 -0
- package/src/components/chat/skins/webpage-assistant/pages.ts +9 -0
- package/src/components/chat/skins/webpage-assistant/types.ts +178 -0
- package/src/components/chat/skins/webpage-assistant/use-mobile.ts +19 -0
- package/src/components/chat/stock/SOURCE.md +90 -0
- package/src/components/chat/stock/artifacts-panel.tsx +305 -0
- package/src/components/chat/stock/attachment.aui.tsx +280 -0
- package/src/components/chat/stock/chat-notice.tsx +143 -0
- package/src/components/chat/stock/chat-private-mode.tsx +64 -0
- package/src/components/chat/stock/deploy-ui-context.tsx +89 -0
- package/src/components/chat/stock/embed-chat-prefs.tsx +471 -0
- package/src/components/chat/stock/file.tsx +265 -0
- package/src/components/chat/stock/follow-up-suggestions.aui.tsx +83 -0
- package/src/components/chat/stock/image.tsx +531 -0
- package/src/components/chat/stock/index.ts +129 -0
- package/src/components/chat/stock/json-view.tsx +140 -0
- package/src/components/chat/stock/markdown-text.tsx +319 -0
- package/src/components/chat/stock/message-error.aui.tsx +96 -0
- package/src/components/chat/stock/message-export-menu.tsx +156 -0
- package/src/components/chat/stock/palette-row-preview.tsx +26 -0
- package/src/components/chat/stock/reasoning.aui.tsx +120 -0
- package/src/components/chat/stock/reasoning.tsx +335 -0
- package/src/components/chat/stock/skin-chrome.tsx +81 -0
- package/src/components/chat/stock/skin-credit.tsx +63 -0
- package/src/components/chat/stock/skin-palette-bridge.tsx +235 -0
- package/src/components/chat/stock/skin-palette-context.ts +16 -0
- package/src/components/chat/stock/skin-runtime.tsx +52 -0
- package/src/components/chat/stock/skin-slash-palette.tsx +393 -0
- package/src/components/chat/stock/skin-types.ts +217 -0
- package/src/components/chat/stock/stock-chat-prefs-host.tsx +501 -0
- package/src/components/chat/stock/stock-send-gate.tsx +94 -0
- package/src/components/chat/stock/stock-shape.tsx +39 -0
- package/src/components/chat/stock/thread.aui.tsx +645 -0
- package/src/components/chat/stock/tool-display.ts +6 -0
- package/src/components/chat/stock/tool-fallback.aui.tsx +866 -0
- package/src/components/chat/stock/tool-group.aui.tsx +244 -0
- package/src/components/chat/stock/tool-surface.ts +120 -0
- package/src/components/chat/stock/tooltip-icon-button.tsx +49 -0
- package/src/components/chat/stock/ui/avatar.tsx +108 -0
- package/src/components/chat/stock/ui/button.tsx +81 -0
- package/src/components/chat/stock/ui/collapsible.tsx +21 -0
- package/src/components/chat/stock/ui/dialog.tsx +163 -0
- package/src/components/chat/stock/ui/skeleton.tsx +13 -0
- package/src/components/chat/stock/ui/textarea.tsx +20 -0
- package/src/components/chat/stock/ui/tooltip.tsx +68 -0
- package/src/components/chat/stock/use-attachment-src.ts +42 -0
- package/src/components/chat/stock/use-copy-to-clipboard.ts +29 -0
- package/src/components/chat/strip-model-boilerplate.ts +42 -0
- package/src/components/chat/suggestion-cycle.tsx +230 -0
- package/src/components/chat/suggestion-scroll-row.tsx +81 -0
- package/src/components/chat/trace-grouping/chain-group-by.ts +44 -0
- package/src/components/chat/trace-grouping/chain-state.ts +141 -0
- package/src/components/chat/trace-grouping/index.ts +32 -0
- package/src/components/chat/trace-grouping/tool-row.ts +74 -0
- package/src/components/chat/trace-grouping/use-deploy-work-disclosure.ts +35 -0
- package/src/components/chat/trace-grouping/use-work-chain.ts +103 -0
- package/src/components/chat/trace-i18n/core.ts +48 -0
- package/src/components/chat/trace-i18n/index.tsx +23 -0
- package/src/components/chat/trace-i18n/locales/en.ts +24 -0
- package/src/components/chat/trace-i18n/locales/fr.ts +28 -0
- package/src/components/chat/trace-i18n/types.ts +35 -0
- package/src/components/chat/trace-spacing.ts +249 -0
- package/src/components/chat/transcript/activity-view.ts +375 -0
- package/src/components/chat/transcript/chat-export.ts +133 -0
- package/src/components/chat/transcript/index.ts +10 -0
- package/src/components/chat/transcript/save-file.ts +209 -0
- package/src/components/chat/transcript/transcript-markdown.ts +428 -0
- package/src/components/chat/transcript/types.ts +81 -0
- package/src/components/chat/turn-outcome.ts +52 -0
- package/src/components/chat/use-warmup-phase.ts +18 -0
- package/src/components/chat/work-status-lead.tsx +49 -0
- package/src/components/chrome.tsx +264 -0
- package/src/components/command-palette/CommandPalette.tsx +404 -0
- package/src/components/command-palette/index.ts +6 -0
- package/src/components/contact/ContactMailto.tsx +112 -0
- package/src/components/contact/index.ts +5 -0
- package/src/components/conviction/ConvictionMeter.tsx +40 -0
- package/src/components/conviction/SignedConvictionBadge.tsx +26 -0
- package/src/components/conviction/index.ts +7 -0
- package/src/components/data-layout/BentoGrid.tsx +52 -0
- package/src/components/data-layout/CardRail.tsx +150 -0
- package/src/components/data-layout/DotMatrixStat.tsx +65 -0
- package/src/components/data-layout/FeatureCell.tsx +80 -0
- package/src/components/data-layout/MediaFrame.tsx +125 -0
- package/src/components/data-layout/ModuleGrid.tsx +735 -0
- package/src/components/data-layout/Odometer.tsx +149 -0
- package/src/components/data-layout/ProductFrame.tsx +79 -0
- package/src/components/data-layout/TestimonialWall.tsx +139 -0
- package/src/components/data-layout/index.ts +19 -0
- package/src/components/data-layout/treemap.ts +368 -0
- package/src/components/deck/DeckStack.tsx +243 -0
- package/src/components/desk/DataTable.tsx +373 -0
- package/src/components/desk/KpiGrid.tsx +80 -0
- package/src/components/desk/Sparkline.tsx +63 -0
- package/src/components/desk/StateBlock.tsx +132 -0
- package/src/components/desk/index.ts +18 -0
- package/src/components/diagrams/ArchitectureDiagram.tsx +350 -0
- package/src/components/diagrams/ArchitectureTour.tsx +912 -0
- package/src/components/diagrams/TerminalSchematic.tsx +192 -0
- package/src/components/diagrams/architecture-svg.tsx +384 -0
- package/src/components/diagrams/index.ts +30 -0
- package/src/components/diagrams/mermaid-theme.ts +115 -0
- package/src/components/diagrams/tour-camera.ts +171 -0
- package/src/components/docs/CodeTabs.tsx +90 -0
- package/src/components/docs/CopyCommand.tsx +151 -0
- package/src/components/docs/DocsLayout.tsx +197 -0
- package/src/components/docs/DocsSearch.tsx +97 -0
- package/src/components/docs/Endpoint.tsx +135 -0
- package/src/components/document/DocumentFrame.tsx +43 -0
- package/src/components/document/GlyphList.tsx +51 -0
- package/src/components/document/PageTitle.tsx +44 -0
- package/src/components/document/Prose.tsx +38 -0
- package/src/components/document/Section.tsx +55 -0
- package/src/components/document/index.ts +13 -0
- package/src/components/effects-chrome/AnnouncementBar.tsx +88 -0
- package/src/components/effects-chrome/HorizontalScrollTrack.tsx +461 -0
- package/src/components/effects-chrome/Pipeline.tsx +226 -0
- package/src/components/effects-chrome/RotatingPrompts.tsx +116 -0
- package/src/components/effects-chrome/StackingPanels.tsx +101 -0
- package/src/components/effects-chrome/TabStrip.tsx +232 -0
- package/src/components/effects-chrome/ToastStack.tsx +201 -0
- package/src/components/effects-chrome/horizontal-track-core.ts +70 -0
- package/src/components/effects-chrome/index.ts +35 -0
- package/src/components/emblems.tsx +188 -0
- package/src/components/faviconTheme.ts +23 -0
- package/src/components/figure/Figure.tsx +38 -0
- package/src/components/figure/index.ts +2 -0
- package/src/components/finance-charts/DrawdownPlot.tsx +76 -0
- package/src/components/finance-charts/EquityCurve.tsx +71 -0
- package/src/components/finance-charts/PriceChart.tsx +119 -0
- package/src/components/finance-charts/chart-host.tsx +236 -0
- package/src/components/finance-charts/chart-scale.ts +93 -0
- package/src/components/finance-charts/demo-data.ts +88 -0
- package/src/components/finance-charts/index.ts +46 -0
- package/src/components/finance-charts/lw-chart.tsx +292 -0
- package/src/components/finance-composites/MarketBar.tsx +243 -0
- package/src/components/finance-composites/OrderBook.tsx +133 -0
- package/src/components/finance-composites/PerformanceDashboard.tsx +185 -0
- package/src/components/finance-composites/SortableTable.tsx +144 -0
- package/src/components/finance-composites/StockTicker.tsx +65 -0
- package/src/components/finance-composites/SyncedTearsheet.tsx +226 -0
- package/src/components/finance-composites/index.ts +28 -0
- package/src/components/finance-tearsheet/KpiStrip.tsx +49 -0
- package/src/components/finance-tearsheet/LiveBadge.tsx +29 -0
- package/src/components/finance-tearsheet/ReturnsMatrix.tsx +321 -0
- package/src/components/finance-tearsheet/StrategyTearsheet.tsx +99 -0
- package/src/components/finance-tearsheet/TearsheetCard.tsx +54 -0
- package/src/components/finance-tearsheet/TradeLogTable.tsx +73 -0
- package/src/components/finance-tearsheet/charts.tsx +2624 -0
- package/src/components/finance-tearsheet/demo-data.ts +177 -0
- package/src/components/finance-tearsheet/format.ts +41 -0
- package/src/components/finance-tearsheet/index.ts +120 -0
- package/src/components/finance-tearsheet/print.ts +52 -0
- package/src/components/finance-tearsheet/risk-bands.ts +48 -0
- package/src/components/finance-tearsheet/stats.ts +35 -0
- package/src/components/finance-tearsheet/strategy-sheet-model.ts +238 -0
- package/src/components/finance-tearsheet/types.ts +58 -0
- package/src/components/footer/FooterCells.tsx +109 -0
- package/src/components/footer/index.ts +6 -0
- package/src/components/graph.tsx +158 -0
- package/src/components/icons.tsx +98 -0
- package/src/components/landing/PixelWordmark.tsx +36 -0
- package/src/components/logos.ts +39 -0
- package/src/components/marquee/Marquee.tsx +204 -0
- package/src/components/metrics/PerfMetrics.tsx +68 -0
- package/src/components/metrics/StatCounter.tsx +104 -0
- package/src/components/page-geometry.tsx +177 -0
- package/src/components/pricing/Pricing.tsx +174 -0
- package/src/components/pricing/PricingMatrix.tsx +219 -0
- package/src/components/prose/index.ts +2 -0
- package/src/components/prose/prose.tsx +86 -0
- package/src/components/repo-activity/RepoActivity.tsx +599 -0
- package/src/components/repo-activity/RepoHeatmap.tsx +225 -0
- package/src/components/repo-activity/demo.ts +201 -0
- package/src/components/repo-activity/fetch.ts +211 -0
- package/src/components/repo-activity/heatmap.ts +123 -0
- package/src/components/repo-activity/index.ts +28 -0
- package/src/components/repo-activity/types.ts +99 -0
- package/src/components/stages/NumberedStages.tsx +116 -0
- package/src/components/symbols/marks.tsx +116 -0
- package/src/components/symbols/terminal-lockup.tsx +136 -0
- package/src/components/symbols/terminal-marks.tsx +226 -0
- package/src/components/terminal/ChatResponseLoader.tsx +67 -0
- package/src/components/terminal/ContainerBootLoader.tsx +82 -0
- package/src/components/terminal/TerminalStepCaret.tsx +202 -0
- package/src/components/themeInit.ts +24 -0
- package/src/components/typography/MotionReveal.tsx +108 -0
- package/src/components/typography/TypewriterReveal.tsx +101 -0
- package/src/components/typography/WordReveal.tsx +143 -0
- package/src/data/modules.ts +378 -0
- package/src/data/subsystems.ts +101 -0
- package/src/index.ts +587 -0
- package/src/lib/base-path.ts +60 -0
- package/src/lib/cx.ts +25 -0
- package/src/lib/gloomberb.ts +69 -0
- package/src/lib/record.ts +19 -0
- package/src/lib/stub-payload.ts +183 -0
- package/src/lib/useBodyScrollLock.ts +44 -0
- package/src/lib/utils.ts +6 -0
- package/src/motion/primitives.tsx +105 -0
- package/src/motion/scroll-glide.ts +62 -0
- package/src/motion/scrolly-core.ts +38 -0
- package/src/motion/scrolly.tsx +95 -0
- package/src/navigation/HashScrollManager.tsx +167 -0
- package/src/navigation/hashScroll.ts +78 -0
- package/src/replay/browser.ts +280 -0
- package/src/replay/chat-export-run.ts +121 -0
- package/src/replay/export-format.ts +25 -0
- package/src/replay/export-mount.ts +32 -0
- package/src/replay/filename.ts +54 -0
- package/src/replay/index.ts +21 -0
- package/src/replay/redact-dom.ts +178 -0
- package/src/replay/redact.ts +113 -0
- package/src/replay/snapshot.ts +659 -0
- package/src/styles/account-auth.css +339 -0
- package/src/styles/brand-wordmark.css +11 -0
- package/src/styles/card-rail.css +120 -0
- package/src/styles/chat-aui.css +1143 -0
- package/src/styles/chat-core.css +469 -0
- package/src/styles/chat-digichat.css +2531 -0
- package/src/styles/chat-math.css +70 -0
- package/src/styles/chat-skin-palette.css +138 -0
- package/src/styles/chat-stock-menu.css +37 -0
- package/src/styles/chat-widgets.css +190 -0
- package/src/styles/command-palette.css +372 -0
- package/src/styles/controls-core.css +2261 -0
- package/src/styles/controls-overlay.css +603 -0
- package/src/styles/data-layout.css +288 -0
- package/src/styles/deck.css +141 -0
- package/src/styles/diagrams.css +1860 -0
- package/src/styles/digichat-app-theme.css +250 -0
- package/src/styles/digichat-boot-loader.css +487 -0
- package/src/styles/digichat-launcher.css +377 -0
- package/src/styles/docs.css +165 -0
- package/src/styles/effects-chrome.css +888 -0
- package/src/styles/finance-composites.css +214 -0
- package/src/styles/finance-tearsheet-overlay.css +90 -0
- package/src/styles/finance-tearsheet.css +945 -0
- package/src/styles/marquee.css +168 -0
- package/src/styles/metrics.css +82 -0
- package/src/styles/nav-shell.css +551 -0
- package/src/styles/pricing.css +79 -0
- package/src/styles/repo-activity.css +575 -0
- package/src/styles/stages.css +69 -0
- package/src/styles/terminal-loaders.css +122 -0
- package/src/styles/terminal-manifest.css +228 -0
- package/src/styles/web-theme.css +1007 -0
- package/src/styles/word-reveal.css +204 -0
- package/src/theme/apply-theme.ts +214 -0
- package/src/theme/index.ts +27 -0
- package/src/theme/palette-registry.ts +855 -0
- package/src/theme/tui-prefs.ts +64 -0
- package/src/ui/alert.tsx +78 -0
- package/src/ui/avatar.tsx +104 -0
- package/src/ui/badge.tsx +75 -0
- package/src/ui/breadcrumb.tsx +61 -0
- package/src/ui/button.tsx +67 -0
- package/src/ui/card.tsx +139 -0
- package/src/ui/checkbox.tsx +27 -0
- package/src/ui/collapsible.tsx +32 -0
- package/src/ui/date-pager.tsx +325 -0
- package/src/ui/dialog.tsx +157 -0
- package/src/ui/dropdown-menu.tsx +267 -0
- package/src/ui/empty-state.tsx +165 -0
- package/src/ui/field.tsx +104 -0
- package/src/ui/form.tsx +36 -0
- package/src/ui/icon-button.tsx +36 -0
- package/src/ui/index.ts +34 -0
- package/src/ui/input.tsx +33 -0
- package/src/ui/kbd.tsx +30 -0
- package/src/ui/label.tsx +32 -0
- package/src/ui/pager.tsx +119 -0
- package/src/ui/pagination.tsx +126 -0
- package/src/ui/radio-group.tsx +51 -0
- package/src/ui/search-bar.tsx +85 -0
- package/src/ui/segmented-control.tsx +76 -0
- package/src/ui/select.tsx +257 -0
- package/src/ui/separator.tsx +24 -0
- package/src/ui/sheet.tsx +141 -0
- package/src/ui/skeleton.tsx +76 -0
- package/src/ui/slider.tsx +76 -0
- package/src/ui/switch.tsx +31 -0
- package/src/ui/table.tsx +179 -0
- package/src/ui/tabs.tsx +89 -0
- package/src/ui/tags-input.tsx +168 -0
- package/src/ui/textarea.tsx +17 -0
- package/src/ui/tooltip.tsx +71 -0
|
@@ -0,0 +1,1007 @@
|
|
|
1
|
+
/* ==========================================================================
|
|
2
|
+
@digithings-ai/ui — THE Tailwind v4 token bridge. One definition, every app.
|
|
3
|
+
Bridges the [data-theme] semantic tokens (from @digithings-ai/design/tokens.css)
|
|
4
|
+
to Tailwind color/font utilities. Import order in an app's globals.css:
|
|
5
|
+
@import "tailwindcss";
|
|
6
|
+
@import "@digithings-ai/design/tokens.css";
|
|
7
|
+
@import "@digithings-ai/ui/styles/web-theme.css";
|
|
8
|
+
|
|
9
|
+
`@theme inline` (not plain `@theme`) is load-bearing: utilities emit
|
|
10
|
+
`var(--token)` at the use site (`text-ink` → `color: var(--ink)`), so a
|
|
11
|
+
scoped livery (`.accent-digiquant { --accent: … }`) or a `data-theme` flip
|
|
12
|
+
re-resolves inside every utility. Plain `@theme` freezes the var at :root
|
|
13
|
+
and scoped overrides never reach the utility. Apps must not declare their
|
|
14
|
+
own bridge — extend this one.
|
|
15
|
+
========================================================================== */
|
|
16
|
+
|
|
17
|
+
/* Overlay state variants — the kit's Collapsible/Dialog/Sheet/Menu emit
|
|
18
|
+
`data-open`/`data-closed` (Base UI attrs, Radix `data-state`). Declared on
|
|
19
|
+
the bridge so consumers need no local copy. */
|
|
20
|
+
@custom-variant data-open (&:where([data-state="open"], [data-open]:not([data-open="false"])));
|
|
21
|
+
|
|
22
|
+
@custom-variant data-closed (&:where([data-state="closed"], [data-closed]:not([data-closed="false"])));
|
|
23
|
+
|
|
24
|
+
/* Skeleton shimmer (#4306, batch K1) — the kit <Skeleton/> rides the stock
|
|
25
|
+
sk-* sweep; the keyframes live on the bridge so every consumer that imports
|
|
26
|
+
web-theme gets them, with no controls-core.css dependency. */
|
|
27
|
+
@keyframes sk-shimmer {
|
|
28
|
+
to {
|
|
29
|
+
transform: translateX(100%);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@theme inline {
|
|
34
|
+
--color-bg: var(--bg);
|
|
35
|
+
--color-surface: var(--surface);
|
|
36
|
+
--color-surface-2: var(--surface-2);
|
|
37
|
+
--color-hair: var(--hair);
|
|
38
|
+
--color-hair-2: var(--hair-2);
|
|
39
|
+
|
|
40
|
+
--color-ink: var(--ink);
|
|
41
|
+
--color-ink-soft: var(--ink-soft);
|
|
42
|
+
--color-ink-mute: var(--ink-mute);
|
|
43
|
+
|
|
44
|
+
--color-accent: var(--accent);
|
|
45
|
+
--color-accent-weak: var(--accent-weak);
|
|
46
|
+
--color-on-accent: var(--on-accent);
|
|
47
|
+
|
|
48
|
+
--color-up: var(--up);
|
|
49
|
+
--color-down: var(--down);
|
|
50
|
+
--color-warn: var(--warn);
|
|
51
|
+
--color-danger: var(--danger);
|
|
52
|
+
--color-heat-ink: var(--heat-ink);
|
|
53
|
+
--color-heat-ink-strong: var(--heat-ink-strong);
|
|
54
|
+
|
|
55
|
+
--color-term-bg: var(--term-bg);
|
|
56
|
+
--color-term-ink: var(--term-ink);
|
|
57
|
+
--color-term-hair: var(--term-hair);
|
|
58
|
+
--color-term-fill: var(--term-fill);
|
|
59
|
+
--color-term-mute: var(--term-mute);
|
|
60
|
+
|
|
61
|
+
--font-sans: var(--font-sans);
|
|
62
|
+
--font-mono: var(--font-mono);
|
|
63
|
+
--font-display: var(--font-display);
|
|
64
|
+
|
|
65
|
+
--ease-brand: cubic-bezier(0.22, 1, 0.36, 1);
|
|
66
|
+
|
|
67
|
+
/* shadcn/ui token contract — Base UI base, lyra preset.
|
|
68
|
+
See docs/superpowers/specs/2026-09-16-shadcn-migration-design.md §3.2 */
|
|
69
|
+
--color-background: var(--bg);
|
|
70
|
+
--color-foreground: var(--ink);
|
|
71
|
+
--color-card: var(--surface);
|
|
72
|
+
--color-card-foreground: var(--ink);
|
|
73
|
+
--color-popover: var(--surface-2);
|
|
74
|
+
--color-popover-foreground: var(--ink);
|
|
75
|
+
--color-primary: var(--ink);
|
|
76
|
+
--color-primary-foreground: var(--bg);
|
|
77
|
+
--color-secondary: var(--surface-2);
|
|
78
|
+
--color-secondary-foreground: var(--ink);
|
|
79
|
+
--color-muted: var(--surface);
|
|
80
|
+
--color-muted-foreground: var(--ink-soft);
|
|
81
|
+
/* Brand --color-accent is intentionally held (owned by the row at the top of
|
|
82
|
+
this block); shadcn's subtle accent role + brand-alias rename defer to the
|
|
83
|
+
Wave 2/3 alias sweep. */
|
|
84
|
+
--color-accent-foreground: var(--on-accent);
|
|
85
|
+
--color-destructive: var(--danger);
|
|
86
|
+
--color-border: var(--hair);
|
|
87
|
+
--color-input: var(--hair);
|
|
88
|
+
--color-ring: color-mix(in srgb, var(--accent) 40%, transparent);
|
|
89
|
+
--color-input-background: var(--surface);
|
|
90
|
+
--color-chart-1: var(--ink);
|
|
91
|
+
--color-chart-2: var(--accent);
|
|
92
|
+
--color-chart-3: var(--ink-soft);
|
|
93
|
+
--color-chart-4: var(--up);
|
|
94
|
+
--color-chart-5: var(--warn);
|
|
95
|
+
--radius-sm: 0;
|
|
96
|
+
--radius-md: 0;
|
|
97
|
+
--radius-lg: 0;
|
|
98
|
+
--radius-xl: 0;
|
|
99
|
+
|
|
100
|
+
/* Collapsible height animation. The Base UI panel exposes
|
|
101
|
+
--collapsible-panel-height (the kit's Collapsible); the Radix var stays
|
|
102
|
+
first for Radix consumers. Caveat: tw-animate-css declares the same
|
|
103
|
+
keyframes WITHOUT the Base UI var, so an app importing it after this
|
|
104
|
+
bridge (reference, digichat) still needs its local copy to win. */
|
|
105
|
+
@keyframes collapsible-down {
|
|
106
|
+
from { height: 0; }
|
|
107
|
+
to { height: var(--radix-collapsible-content-height, var(--collapsible-panel-height, auto)); }
|
|
108
|
+
}
|
|
109
|
+
@keyframes collapsible-up {
|
|
110
|
+
from { height: var(--radix-collapsible-content-height, var(--collapsible-panel-height, auto)); }
|
|
111
|
+
to { height: 0; }
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* Entrance choreography (D1, #4429) — the staged hero reveal. Declared in
|
|
115
|
+
THIS block rather than a second one: web-theme.test.ts pins exactly one
|
|
116
|
+
`@theme inline`, because a second is how a token bridge drifts. */
|
|
117
|
+
--animate-appear: kit-appear 0.6s forwards ease-out;
|
|
118
|
+
--animate-appear-zoom: kit-appear-zoom 0.6s forwards ease-out;
|
|
119
|
+
--line-width: 1px;
|
|
120
|
+
|
|
121
|
+
@keyframes kit-appear {
|
|
122
|
+
0% { opacity: 0; transform: translateY(1rem); filter: blur(0.5rem); }
|
|
123
|
+
50% { filter: blur(0); }
|
|
124
|
+
100% { opacity: 1; transform: translateY(0); filter: blur(0); }
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
@keyframes kit-appear-zoom {
|
|
128
|
+
0% { opacity: 0; transform: scale(0.5); }
|
|
129
|
+
100% { opacity: 1; transform: scale(1); }
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/* Base element defaults shared by the React apps.
|
|
134
|
+
Utilitarian v0.1: mono is the default voice (claims, body, chrome). */
|
|
135
|
+
body {
|
|
136
|
+
background: var(--bg);
|
|
137
|
+
color: var(--ink);
|
|
138
|
+
font-family: var(--font-mono);
|
|
139
|
+
line-height: 1.55;
|
|
140
|
+
letter-spacing: -0.015em;
|
|
141
|
+
-webkit-font-smoothing: antialiased;
|
|
142
|
+
text-rendering: optimizeLegibility;
|
|
143
|
+
/* Theme flip only — color/background, not layout properties. */
|
|
144
|
+
transition: background 0.4s var(--ease), color 0.4s var(--ease);
|
|
145
|
+
}
|
|
146
|
+
::selection { background: var(--accent); color: var(--on-accent); }
|
|
147
|
+
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 0; }
|
|
148
|
+
|
|
149
|
+
/* ── stack logos / chips ─────────────────────────────────────────────── */
|
|
150
|
+
.stack-row { display: flex; flex-wrap: wrap; gap: 0.45rem; margin-top: 0.6rem; }
|
|
151
|
+
.stack-chip { display: inline-flex; align-items: center; gap: 0.4rem; border: 1px solid var(--hair); background: var(--surface); border-radius: 0; padding: 0.32rem 0.6rem; font-family: var(--font-mono); font-size: 0.74rem; color: var(--ink-soft); transition: border-color .18s var(--ease), color .18s var(--ease); }
|
|
152
|
+
.stack-chip:hover { border-color: var(--hair-2); color: var(--ink); }
|
|
153
|
+
.stack-ico { color: var(--ink-mute); transition: color .18s var(--ease); }
|
|
154
|
+
.stack-chip:hover .stack-ico { color: var(--brand, var(--accent)); }
|
|
155
|
+
.stack-mono { display: inline-grid; place-items: center; min-width: 0.9375rem; height: 0.9375rem; font-size: 0.6rem; font-weight: 600; color: var(--ink-mute); border: 1px solid var(--hair-2); border-radius: 0; padding: 0 0.125rem; }
|
|
156
|
+
.stack-row.compact .stack-name { display: none; }
|
|
157
|
+
.stack-row.compact .stack-chip { padding: 0.3rem; }
|
|
158
|
+
|
|
159
|
+
/* ── module cards ────────────────────────────────────────────────────── */
|
|
160
|
+
.mod-card { display: flex; flex-direction: column; gap: 0.3rem; background: var(--surface); border: 1px solid var(--hair); border-radius: var(--r-md); padding: 1.4rem 1.3rem; transition: transform .3s var(--ease), border-color .3s var(--ease); position: relative; overflow: hidden; }
|
|
161
|
+
.mod-card::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 0.125rem; background: var(--accent); transform: scaleX(0); transform-origin: left; transition: transform .32s var(--ease); }
|
|
162
|
+
/* transform-origin has no logical keyword — fill from the inline-start edge */
|
|
163
|
+
[dir="rtl"] .mod-card::before { transform-origin: right; }
|
|
164
|
+
.mod-card:hover { transform: translateY(-4px); border-color: var(--hair-2); }
|
|
165
|
+
.mod-card:hover::before { transform: scaleX(1); }
|
|
166
|
+
.mod-card-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.3rem; }
|
|
167
|
+
.mod-card h3 { font-size: 1.14rem; font-weight: 600; letter-spacing: -0.02em; }
|
|
168
|
+
.mod-card .role { font-size: 0.8rem; color: var(--ink-soft); }
|
|
169
|
+
.dg-tier { font-family: var(--font-mono); font-size: 0.6rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-mute); border: 1px solid var(--hair); border-radius: 0; padding: 0.16rem 0.5rem; }
|
|
170
|
+
/* .dg-tier.t-roadmap reads --warn as small text; the light --warn token was
|
|
171
|
+
raised to #8F6220 in tokens.css (canon-audit S2) so this needs no local
|
|
172
|
+
override — dark stays #E0B341. */
|
|
173
|
+
.dg-tier.t-core { color: var(--accent); border-color: var(--accent-weak); }
|
|
174
|
+
.dg-tier.t-roadmap { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, transparent); }
|
|
175
|
+
|
|
176
|
+
/* ── scrollytelling graph ────────────────────────────────────────────── */
|
|
177
|
+
.dg-track { position: relative; }
|
|
178
|
+
.dg-stage { position: sticky; top: 0; height: 100vh; display: flex; flex-direction: column; justify-content: center; }
|
|
179
|
+
/* minmax(0,...) locks both tracks: content (long stack rows, docker cmds)
|
|
180
|
+
can never expand a column, so the graph + panel never shift while scrolling. */
|
|
181
|
+
.dg-stage-grid { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.78fr); gap: clamp(1.5rem, 4vw, 3.5rem); align-items: center; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); width: 100%; }
|
|
182
|
+
.dg-graph { width: 100%; height: auto; max-height: 70vh; }
|
|
183
|
+
.dg-graph-wrap { min-width: 0; }
|
|
184
|
+
.dg-edge { stroke: var(--hair-2); stroke-width: 1.4; fill: none; opacity: 0.5; transition: stroke .25s var(--ease), opacity .25s var(--ease); }
|
|
185
|
+
.dg-edge.has-active { opacity: 0.12; }
|
|
186
|
+
.dg-edge.on { opacity: 0.95; stroke: var(--accent); stroke-width: 2; }
|
|
187
|
+
.dg-node { cursor: pointer; }
|
|
188
|
+
.dg-node .halo { fill: var(--accent); opacity: 0; transition: opacity .25s var(--ease); }
|
|
189
|
+
.dg-node .node { fill: color-mix(in srgb, var(--accent) 20%, var(--surface)); stroke: var(--accent); stroke-width: 1.6; transition: stroke-width .25s var(--ease); }
|
|
190
|
+
.dg-node.hub .node { fill: color-mix(in srgb, var(--accent) 30%, var(--surface)); stroke-width: 2; }
|
|
191
|
+
.dg-node .label { fill: var(--ink-soft); font-family: var(--font-mono); font-size: var(--text-sm); text-anchor: middle; font-weight: 500; }
|
|
192
|
+
.dg-node.hub .label { fill: var(--ink); font-size: 0.875rem; }
|
|
193
|
+
.dg-node.on .halo { opacity: 0.22; } .dg-node.on .node { stroke-width: 2.6; } .dg-node.on .label { fill: var(--ink); }
|
|
194
|
+
.dg-node.dim { opacity: 0.32; }
|
|
195
|
+
.dg-rail { --rail-dot: 0.375rem; --rail-dot-gap: var(--space-2); position: absolute; inset-inline-end: clamp(1rem, 3vw, 2rem); top: 50%; transform: translateY(-50%); display: flex; flex-direction: column; gap: var(--rail-dot-gap); }
|
|
196
|
+
.dg-tick { width: var(--rail-dot); height: var(--rail-dot); border-radius: 50%; background: var(--hair-2); transition: background .2s var(--ease), transform .2s var(--ease); }
|
|
197
|
+
.dg-tick.on { background: var(--accent); transform: scale(1.5); }
|
|
198
|
+
|
|
199
|
+
/* fixed min-height + top alignment so the box never grows/shrinks per module;
|
|
200
|
+
only the text inside changes. */
|
|
201
|
+
.dg-panel { background: var(--surface); border: 1px solid var(--hair); border-radius: var(--r-lg); padding: clamp(1.4rem, 2.5vw, 2rem); min-height: 26rem; min-width: 0; }
|
|
202
|
+
.dg-panel .dg-tag { min-height: 3.2em; }
|
|
203
|
+
.dg-panel-head { display: flex; align-items: center; gap: 0.9rem; }
|
|
204
|
+
.dg-panel-head h3 { font-family: var(--font-display); font-weight: 400; font-size: 1.9rem; letter-spacing: -0.01em; }
|
|
205
|
+
.dg-tag { color: var(--ink-soft); margin: 0.7rem 0 0.4rem; }
|
|
206
|
+
.dg-docker { font-family: var(--font-mono); font-size: 0.9rem; color: var(--term-ink); background: var(--term-bg); border: 1px solid var(--term-hair); border-radius: 0; padding: 0.5rem 0.7rem; margin-top: 0.8rem; overflow-x: auto; white-space: nowrap; }
|
|
207
|
+
.dg-docker .prompt { color: var(--accent); }
|
|
208
|
+
.dg-more { display: inline-block; margin-top: 0.9rem; font-family: var(--font-mono); font-size: 0.82rem; color: var(--accent); }
|
|
209
|
+
|
|
210
|
+
/* code block (module init snippet) */
|
|
211
|
+
.codeblock { background: var(--term-bg); border: 1px solid var(--term-hair); border-radius: 0; padding: 1.1rem 1.3rem; font-family: var(--font-mono); font-size: 0.82rem; line-height: 1.9; color: var(--term-ink); overflow-x: auto; white-space: pre-wrap; }
|
|
212
|
+
|
|
213
|
+
/* ── the flat module grid (ModuleGrid, v13 stage 4) ────────────────────────
|
|
214
|
+
The angular sibling of the SVG graph: every module is a square-ish cell in
|
|
215
|
+
one grid for the whole run, the focused cell is the one the scroll selects,
|
|
216
|
+
and the detail sits in a flat panel beside it. No radius anywhere — this is
|
|
217
|
+
the canon's flat-corner grammar, where the graph above is the rounded one.
|
|
218
|
+
The grid is sized so all modules fit one viewport without an internal
|
|
219
|
+
scrollbar (12 cells at 4 columns = 3 rows). */
|
|
220
|
+
/* ── mosaic v4: a fixed order that only resizes ────────────────────────────
|
|
221
|
+
No rail, no side panel, no per-cell logo or tier colour. Three fixed rows of
|
|
222
|
+
flat tiles; the focused tile grows in place and reveals its detail, so the
|
|
223
|
+
whole story stays in a single view.
|
|
224
|
+
|
|
225
|
+
The order is decided at module scope (`ROW_SIZES`), never by the layout
|
|
226
|
+
engine, because the owner's rule is that the tiles keep their places and only
|
|
227
|
+
the sizes move. v3 packed them widest-first to make the rows flush, which
|
|
228
|
+
silently made reading order a function of tile size — and it re-solved on
|
|
229
|
+
every focus step, so the tiles swapped places as the scroll advanced.
|
|
230
|
+
|
|
231
|
+
Both levels resize with `flex-grow`, which interpolates natively; a grid
|
|
232
|
+
`span` does not, so v3 could only jump. The rows are flex items of a column
|
|
233
|
+
container and the tiles are flex items of their row, so a row's width is
|
|
234
|
+
always exactly its parent's and the rows are flush by construction — the
|
|
235
|
+
property v3 needed a backtracking partition to reach. */
|
|
236
|
+
.dg-mosaic--rows {
|
|
237
|
+
display: block;
|
|
238
|
+
position: relative;
|
|
239
|
+
/* Rail-bounded (#4429): the mosaic spans rail to rail — never the full
|
|
240
|
+
viewport — with one page-pad of air inside each rail, the same grammar
|
|
241
|
+
every section uses (Tailwind preflight is border-box, so the padding
|
|
242
|
+
insets inside the max-width). Tiles size against the frame width, not
|
|
243
|
+
the window.
|
|
244
|
+
Always-full (v16): the mosaic fills the stage at every scroll position —
|
|
245
|
+
landing, walk, and release. There is no height transition because height
|
|
246
|
+
no longer changes.
|
|
247
|
+
Packing box (v17): the tiles are absolutely positioned rects solved by
|
|
248
|
+
the squarified treemap in `ModuleGrid` (areas ∝ LOC, no fixed rows), so
|
|
249
|
+
the container is a plain relative box, not a flex column. Motion eases
|
|
250
|
+
each tile's translate/width/height between solves. On viewports taller
|
|
251
|
+
than the cap the grid stops growing instead of going cavernous (owner:
|
|
252
|
+
if the page gets too large the sections below should still come into
|
|
253
|
+
view). */
|
|
254
|
+
width: 100%;
|
|
255
|
+
max-width: calc(var(--frame-w) + 2 * var(--page-pad));
|
|
256
|
+
margin-inline: auto;
|
|
257
|
+
padding-inline: var(--page-pad);
|
|
258
|
+
height: 100%;
|
|
259
|
+
max-height: 64rem;
|
|
260
|
+
overflow: hidden;
|
|
261
|
+
}
|
|
262
|
+
/* Packed tiles are positioned by inline rects (left/top/width/height from the
|
|
263
|
+
treemap solve), so they leave normal flow here. Scoped to the mosaic face:
|
|
264
|
+
the stacked face keeps its flow tiles. The focus walk's size morph eases on
|
|
265
|
+
the brand curve — the treemap re-solves areas and CSS carries each tile to
|
|
266
|
+
its new rect. Opacity starts hidden until the first solve lands: the box is
|
|
267
|
+
measured one effect-tick after mount, and unpositioned tiles must not flash
|
|
268
|
+
piled at the corner (visibility, not opacity, so rest/focus/hover fading
|
|
269
|
+
stays untouched). */
|
|
270
|
+
.dg-mosaic--rows .dg-cell {
|
|
271
|
+
position: absolute;
|
|
272
|
+
inset-block-start: 0;
|
|
273
|
+
left: 0; /* physical: the tile's translate is the treemap's physical x */
|
|
274
|
+
transition:
|
|
275
|
+
transform 0.5s var(--ease),
|
|
276
|
+
width 0.5s var(--ease),
|
|
277
|
+
height 0.5s var(--ease),
|
|
278
|
+
opacity 0.25s var(--ease),
|
|
279
|
+
background 0.25s var(--ease),
|
|
280
|
+
box-shadow 0.25s var(--ease);
|
|
281
|
+
}
|
|
282
|
+
/* Load and resize are layout, not motion (ModuleGrid sets both hooks): the
|
|
283
|
+
mosaic is unseen until its box has settled once, then fades in whole, and a
|
|
284
|
+
box change places tiles without easing them. Opacity on the container,
|
|
285
|
+
because visibility on a tile does not hide descendants that set their own. */
|
|
286
|
+
.dg-mosaic--rows {
|
|
287
|
+
transition: opacity 0.4s var(--ease);
|
|
288
|
+
}
|
|
289
|
+
.dg-mosaic--rows:not([data-settled]) {
|
|
290
|
+
opacity: 0;
|
|
291
|
+
}
|
|
292
|
+
.dg-mosaic--rows:not([data-settled]) .dg-cell,
|
|
293
|
+
.dg-mosaic--rows[data-resizing] .dg-cell {
|
|
294
|
+
transition:
|
|
295
|
+
opacity 0.25s var(--ease),
|
|
296
|
+
background 0.25s var(--ease),
|
|
297
|
+
box-shadow 0.25s var(--ease);
|
|
298
|
+
}
|
|
299
|
+
/* The mosaic's own stage sits below the pinned top bar — never behind it —
|
|
300
|
+
so the walk plays in the remaining viewport, vertically centred. Scoped
|
|
301
|
+
to the mosaic; the tour keeps the fullscreen stage. */
|
|
302
|
+
.dg-stage--mosaic {
|
|
303
|
+
top: var(--dq-nav-h, 3.875rem);
|
|
304
|
+
height: calc(100dvh - var(--dq-nav-h, 3.875rem));
|
|
305
|
+
/* Dock padding (owner choreography): the grid breathes below the bar and
|
|
306
|
+
above the viewport bottom instead of sticking to either edge. Scoped to
|
|
307
|
+
the mosaic stage only; box-sizing keeps the padding inside the height. */
|
|
308
|
+
padding-block: clamp(1rem, 3vh, 2.5rem);
|
|
309
|
+
box-sizing: border-box;
|
|
310
|
+
/* Centred: the mosaic is full-height in every state that matters, so this
|
|
311
|
+
only binds on viewports taller than its cap — the grid sits mid-stage
|
|
312
|
+
instead of sticking to the hero. */
|
|
313
|
+
justify-content: center;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/* Extreme zoom-out (very tall viewport): once the mosaic hits its height cap,
|
|
317
|
+
centring leaves cavernous gaps above and below. Top-align it instead so it
|
|
318
|
+
enters the view with the section that follows, rather than floating in the
|
|
319
|
+
middle of an empty screen. */
|
|
320
|
+
@media (min-height: 1400px) {
|
|
321
|
+
.dg-stage--mosaic {
|
|
322
|
+
justify-content: flex-start;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/* The stacked face — the same boxes on a phone, one per row.
|
|
327
|
+
There is no pinned track here, so the column is in normal flow and grows with
|
|
328
|
+
its content. Every tile is open: the tile under the reader's eye only lights
|
|
329
|
+
(`.dg-cell.on`, paint only), because opening one in flow would push the rest
|
|
330
|
+
of the page down under a moving thumb. The wrap carries the page's own
|
|
331
|
+
gutter because there is no stage to centre it. */
|
|
332
|
+
.dg-stack-wrap {
|
|
333
|
+
padding-inline: var(--page-pad);
|
|
334
|
+
/* Breathing room below the section's top separator: the first card must sit
|
|
335
|
+
a step down from the line-t rule, not touch it. */
|
|
336
|
+
padding-block: clamp(1rem, 3vh, 2rem);
|
|
337
|
+
}
|
|
338
|
+
.dg-mosaic--stack { height: auto; gap: var(--space-2); }
|
|
339
|
+
.dg-mosaic--stack .dg-mosaic-row { flex: 0 0 auto; transition: none; }
|
|
340
|
+
/* The slide-up entrance wrapper (kit Reveal) is the row's flex child, not the
|
|
341
|
+
tile — so it carries the tile's flex share and stretches the tile to fill
|
|
342
|
+
it. Without this the wrapper would size to content and the tile would never
|
|
343
|
+
fill the row width. */
|
|
344
|
+
.dg-mosaic--stack .dg-stack-reveal { flex: 1 1 auto; min-width: 0; display: flex; }
|
|
345
|
+
.dg-mosaic--stack .dg-stack-reveal > .dg-cell { flex: 1 1 auto; }
|
|
346
|
+
/* One tile per row, so the tile fills the row's width. `flex: 0 0 auto` here
|
|
347
|
+
would size the tile to its own max-content — which measured 760px on a 420px
|
|
348
|
+
viewport and pushed the whole page sideways. Height is content-driven because
|
|
349
|
+
the row is `flex: 0 0 auto` inside the column. */
|
|
350
|
+
.dg-mosaic--stack .dg-cell { flex: 1 1 auto; min-width: 0; opacity: 0.72; transition: opacity .25s var(--ease), background .25s var(--ease), box-shadow .25s var(--ease); }
|
|
351
|
+
.dg-mosaic--stack .dg-cell.on { opacity: 1; }
|
|
352
|
+
.dg-mosaic-row { display: flex; flex: 1 1 0; min-height: 0; gap: var(--space-2); /* Stacked face only: the mosaic face has no rows since v17 (treemap). No size transition here in either face — the mosaic morph is motion `animate` on the tiles, the stack is content-driven. CSS keeps only the paint transitions below. */ }
|
|
353
|
+
|
|
354
|
+
.dg-cell { --dg-cell-pad-block: 0.85rem; --dg-cell-pad-inline: 0.95rem; --dg-cell-gap: var(--space-2); position: relative; display: flex; flex-direction: column; gap: var(--dg-cell-gap); flex: 1 1 0; min-width: 0; min-height: 0; padding: var(--dg-cell-pad-block) var(--dg-cell-pad-inline); margin: 0; background: var(--surface); border: 1px solid var(--hair); border-radius: 0; text-align: left; cursor: pointer; overflow: hidden; opacity: 0.55; transition: opacity .25s var(--ease), background .25s var(--ease), box-shadow .25s var(--ease); }
|
|
355
|
+
.dg-cell:hover { opacity: 0.85; }
|
|
356
|
+
.dg-cell.on { opacity: 1; background: var(--surface-2, var(--surface)); box-shadow: inset 0 0 0 1px var(--accent); cursor: default; overflow: hidden; scrollbar-width: none; }
|
|
357
|
+
.dg-cell, .dg-mosaic, .dg-mosaic-stack { scrollbar-width: none; }
|
|
358
|
+
.dg-cell::-webkit-scrollbar, .dg-mosaic::-webkit-scrollbar, .dg-mosaic-stack::-webkit-scrollbar { display: none; width: 0; height: 0; }
|
|
359
|
+
|
|
360
|
+
/* Name left, version right: the tile's identity line. The version sits in the
|
|
361
|
+
top-right corner where a reader scanning the mosaic can compare releases down
|
|
362
|
+
a column. The head wraps, and the version carries `margin-left: auto` so it
|
|
363
|
+
keeps its right edge on the line it lands on — both halves are `nowrap`, so
|
|
364
|
+
without the wrap a narrow tile had its name run underneath it. */
|
|
365
|
+
.dg-mosaic-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 0.25rem 0.6rem; min-width: 0; }
|
|
366
|
+
.dg-mosaic-version { margin-left: auto; text-align: right; }
|
|
367
|
+
.dg-mosaic-link {
|
|
368
|
+
margin-left: 0.35rem;
|
|
369
|
+
flex: 0 0 auto;
|
|
370
|
+
font-family: var(--font-mono);
|
|
371
|
+
font-size: 0.95rem;
|
|
372
|
+
line-height: 1;
|
|
373
|
+
color: var(--ink-mute);
|
|
374
|
+
text-decoration: none;
|
|
375
|
+
transition: color 0.2s var(--ease);
|
|
376
|
+
}
|
|
377
|
+
.dg-mosaic-link:hover,
|
|
378
|
+
.dg-mosaic-link:focus-visible { color: var(--ink); }
|
|
379
|
+
.dg-mosaic-name { font-family: var(--font-mono); font-size: 1.35rem; font-weight: 500; letter-spacing: -0.01em; color: var(--ink); min-width: 0; overflow-wrap: anywhere; }
|
|
380
|
+
/* Mini tiles step the name down a notch instead of clipping it: the full
|
|
381
|
+
name still shows (never an abbreviation), just set smaller next to the
|
|
382
|
+
version, so the head fits ~135px with padding. */
|
|
383
|
+
.dg-cell[data-tier="mini"] .dg-mosaic-name { font-size: 1.1rem; }
|
|
384
|
+
/* A hero-banner mark in place of the text name (10 cells tall); tiles narrow it by tier. */
|
|
385
|
+
.dg-mosaic-mark { display: block; flex: 0 1 auto; width: min(100%, 11rem); }
|
|
386
|
+
.dg-cell[data-tier="mini"] .dg-mosaic-mark { width: min(100%, 8.5rem); }
|
|
387
|
+
|
|
388
|
+
/* The whole tile is the focus target, but the focused tile also owns real
|
|
389
|
+
controls (copy the compose command, ask digichat). A <button> cannot contain
|
|
390
|
+
another button, so the focus action is a transparent overlay *under* the body
|
|
391
|
+
rather than the body's parent; the body re-enables pointer events only on its
|
|
392
|
+
own controls, so every other click falls through to the overlay. The overlay
|
|
393
|
+
lives inside an `overflow: hidden` tile, so the global `:focus-visible`
|
|
394
|
+
outline (drawn outside the box) would be clipped — the ring is drawn just
|
|
395
|
+
inside the edge instead. */
|
|
396
|
+
.dg-cell-focus { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; margin: 0; padding: 0; border: 0; background: transparent; cursor: pointer; }
|
|
397
|
+
.dg-cell.on .dg-cell-focus { cursor: default; }
|
|
398
|
+
.dg-cell-focus:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
|
|
399
|
+
.dg-cell-body { position: relative; z-index: 1; display: flex; flex-direction: column; gap: var(--dg-cell-gap); flex: 1 1 auto; min-height: 0; pointer-events: none; }
|
|
400
|
+
.dg-cell-body button { pointer-events: auto; }
|
|
401
|
+
|
|
402
|
+
/* The three stated facts — lines of code, endpoints, MCP tools — stacked under
|
|
403
|
+
the name in every tile, focused or resting, so the box is a constant the
|
|
404
|
+
reader learns once. A label/value row each in the same `.dg-loc` mono
|
|
405
|
+
micro-type the corner figures used; the value is right-aligned with
|
|
406
|
+
`tabular-nums` so the column compares cleanly down the mosaic. */
|
|
407
|
+
.dg-mosaic-facts { font-family: var(--font-mono); font-size: 0.86rem; line-height: 1.5; letter-spacing: 0.01em; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
|
|
408
|
+
/* The packages sit at the foot of every tile, expanded or resting. `margin-top:
|
|
409
|
+
auto` pins them to the bottom so the boxes line up whether or not the tile is
|
|
410
|
+
open; the chips print their names, because the owner asked for the packages to
|
|
411
|
+
be readable "in the non-expanded view". On the focused tile they pack to the
|
|
412
|
+
right, directly above the compose line. */
|
|
413
|
+
.dg-mosaic-stack { display: block; margin-top: auto; min-width: 0; }
|
|
414
|
+
.dg-mosaic-stack .stack-row { margin-top: 0; }
|
|
415
|
+
/* Focused tiles: the chips shrink to their own width and sit in the bottom-right,
|
|
416
|
+
just above the compose line. The cap wraps a long row into that corner
|
|
417
|
+
instead of stretching it across the card. */
|
|
418
|
+
.dg-cell.on .dg-mosaic-stack { align-self: stretch; width: 100%; max-width: 100%; }
|
|
419
|
+
.dg-cell.on .dg-mosaic-stack .stack-row { justify-content: flex-start; }
|
|
420
|
+
/* Package chips wrap inside the tile. A single nowrap row used to scroll
|
|
421
|
+
out of the cell while the mosaic was resizing. */
|
|
422
|
+
.dg-mosaic-stack .stack-row,
|
|
423
|
+
.dg-mosaic-stack .stack-row.compact {
|
|
424
|
+
flex-wrap: wrap;
|
|
425
|
+
overflow: hidden;
|
|
426
|
+
max-width: 100%;
|
|
427
|
+
}
|
|
428
|
+
.dg-mosaic-stack .stack-chip { min-width: 0; max-width: 100%; }
|
|
429
|
+
.dg-mosaic-role { font-family: var(--font-mono); font-size: 0.9rem; line-height: 1.5; color: var(--ink-mute); }
|
|
430
|
+
.dg-cell.on .dg-mosaic-role { color: var(--ink-soft); }
|
|
431
|
+
.dg-mosaic-detail { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 0.4rem; min-width: 0; }
|
|
432
|
+
/* The one part of the focused tile allowed to shrink. The tile is one row tall,
|
|
433
|
+
and the earlier version let the copy take as much as it wanted — which pushed
|
|
434
|
+
the compose command and the ask control out of the box on the longest modules
|
|
435
|
+
(digigraph, digivault). The copy shrinks, the stack row and the foot below are
|
|
436
|
+
pinned, and the lead paragraph is clamped, so the controls are always visible. */
|
|
437
|
+
|
|
438
|
+
/* The WHY drawer's typewriter fill. Each owned word carries its index (`--i`)
|
|
439
|
+
and the word count (`--n`), and the drawer writes a single `--seam-fill`
|
|
440
|
+
(0..1) on the grid; the clamp below turns that into a per-word opacity, so
|
|
441
|
+
the sentence types itself out as the panel slides right. `--seam-fill`
|
|
442
|
+
defaults to 1, so SSR, no-JS and prefers-reduced-motion all render the full
|
|
443
|
+
line with no reveal. */
|
|
444
|
+
.dg-seam-word {
|
|
445
|
+
opacity: clamp(0, calc(var(--seam-fill, 1) * var(--n) - var(--i)), 1);
|
|
446
|
+
}
|
|
447
|
+
/* The compose command and the CTA share the last line. The command wraps
|
|
448
|
+
on the focused tile so a zoomed page lengthens the card instead of
|
|
449
|
+
cutting the line off. */
|
|
450
|
+
.dg-mosaic-foot { display: flex; align-items: center; flex-wrap: wrap; gap: var(--dg-cell-gap) 0.9rem; margin-top: 0; min-width: 0; flex: 0 0 auto; }
|
|
451
|
+
.dg-mosaic-foot .dg-docker { margin-top: 0; min-width: 0; }
|
|
452
|
+
.dg-mosaic-ask { margin-left: auto; white-space: nowrap; font-family: var(--font-mono); font-size: 0.9rem; color: var(--ink-mute); }
|
|
453
|
+
button.dg-mosaic-ask { background: none; border: 0; padding: 0; cursor: pointer; }
|
|
454
|
+
button.dg-mosaic-ask:hover { color: var(--ink); }
|
|
455
|
+
|
|
456
|
+
/* The compose command is a control in the focused tile: a click copies it. The
|
|
457
|
+
`.dg-docker` skin is shared with the graph panel, where the command is plain
|
|
458
|
+
text, so the pointer affordance is scoped to the button form. */
|
|
459
|
+
button.dg-docker { cursor: pointer; text-align: left; }
|
|
460
|
+
button.dg-docker:hover { border-color: var(--hair-2); }
|
|
461
|
+
button.dg-docker.is-copied { color: var(--accent); }
|
|
462
|
+
|
|
463
|
+
/* Resting tiles clip detail that does not fit their share of the mosaic.
|
|
464
|
+
The focused tile unclamps its copy and grows inside the fixed grid.
|
|
465
|
+
Text that still exceeds that grid scrolls inside the card. */
|
|
466
|
+
.dg-cell .dg-mosaic-detail { overflow: hidden; flex: 1 1 auto; min-height: 0; }
|
|
467
|
+
.dg-cell.on .dg-mosaic-detail { overflow: visible; flex: 0 1 auto; min-height: auto; }
|
|
468
|
+
.dg-cell.on .dg-docker { margin-top: 0; overflow: visible; white-space: normal; }
|
|
469
|
+
.dg-cell.on .dg-mosaic-serves {
|
|
470
|
+
display: block;
|
|
471
|
+
-webkit-line-clamp: unset;
|
|
472
|
+
line-clamp: unset;
|
|
473
|
+
overflow: visible;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/* The deeper description paragraphs: what the module is for, in its own words.
|
|
477
|
+
Only on the focused tile — a resting tile is a fraction of a row tall, so it
|
|
478
|
+
carries the name, version, stats box and role and nothing else. */
|
|
479
|
+
.dg-mosaic-serves { color: var(--ink-mute); font-family: var(--font-mono); font-size: 0.94rem; line-height: 1.5; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 5; line-clamp: 5; overflow: hidden; }
|
|
480
|
+
|
|
481
|
+
/* Card density tiers (owner: a tile shows whatever fits, never clipped).
|
|
482
|
+
The tile's tier is set from its measured width and height (see
|
|
483
|
+
ModuleGrid): full shows everything; medium keeps the head plus the
|
|
484
|
+
logo-only package row and drops the role prose (the collapsed tile keeps
|
|
485
|
+
the owner's logo packages); mini keeps name + version only. Tiers
|
|
486
|
+
CROSS-FADE (opacity + visibility) instead of flipping display: tiles clip
|
|
487
|
+
(overflow hidden on .dg-cell) and the hidden content keeps its layout, so
|
|
488
|
+
a tier change is paint-only — no pop, no reflow. */
|
|
489
|
+
.dg-cell .dg-mosaic-stack,
|
|
490
|
+
.dg-cell .dg-mosaic-role,
|
|
491
|
+
.dg-cell .dg-mosaic-detail {
|
|
492
|
+
opacity: 1;
|
|
493
|
+
visibility: visible;
|
|
494
|
+
transition: opacity 0.3s var(--ease), visibility 0s;
|
|
495
|
+
}
|
|
496
|
+
.dg-cell[data-tier="medium"] .dg-mosaic-role,
|
|
497
|
+
.dg-cell[data-tier="medium"] .dg-mosaic-detail,
|
|
498
|
+
.dg-cell[data-tier="mini"] .dg-mosaic-role,
|
|
499
|
+
.dg-cell[data-tier="mini"] .dg-mosaic-stack,
|
|
500
|
+
.dg-cell[data-tier="mini"] .dg-mosaic-detail {
|
|
501
|
+
opacity: 0;
|
|
502
|
+
visibility: hidden;
|
|
503
|
+
transition: opacity 0.3s var(--ease), visibility 0s 0.3s;
|
|
504
|
+
}
|
|
505
|
+
/* The name stays put. Focus detail enters as the tile grows and leaves
|
|
506
|
+
ahead of the shrink, so a step never blanks the grid or squishes the copy.
|
|
507
|
+
Resting tiles take the detail out of flow (no gap, no extra height) and
|
|
508
|
+
fade it; the focused tile brings it back in flow once the box has started
|
|
509
|
+
to open. Transform/opacity only, per the kit's motion vocabulary. */
|
|
510
|
+
.dg-cell-body { animation: dg-cell-in 0.3s var(--ease) 0.12s both; }
|
|
511
|
+
.dg-mosaic--rows .dg-cell-body { animation: none; }
|
|
512
|
+
@keyframes dg-cell-in {
|
|
513
|
+
from { opacity: 0; transform: translateY(6px); }
|
|
514
|
+
}
|
|
515
|
+
.dg-mosaic--rows .dg-cell:not(.on) .dg-mosaic-enter {
|
|
516
|
+
position: absolute;
|
|
517
|
+
z-index: 1;
|
|
518
|
+
inset-inline: var(--dg-cell-pad-inline);
|
|
519
|
+
margin-top: 0;
|
|
520
|
+
opacity: 0;
|
|
521
|
+
transform: translateY(6px);
|
|
522
|
+
pointer-events: none;
|
|
523
|
+
visibility: hidden;
|
|
524
|
+
transition:
|
|
525
|
+
opacity 0.18s var(--ease),
|
|
526
|
+
transform 0.18s var(--ease),
|
|
527
|
+
visibility 0s linear 0.18s;
|
|
528
|
+
}
|
|
529
|
+
.dg-mosaic--rows .dg-cell.on .dg-mosaic-enter {
|
|
530
|
+
position: relative;
|
|
531
|
+
opacity: 1;
|
|
532
|
+
transform: none;
|
|
533
|
+
pointer-events: auto;
|
|
534
|
+
visibility: visible;
|
|
535
|
+
transition:
|
|
536
|
+
opacity 0.34s var(--ease),
|
|
537
|
+
transform 0.42s var(--ease) 0.14s,
|
|
538
|
+
visibility 0s linear 0s;
|
|
539
|
+
}
|
|
540
|
+
/* Reduced motion: every mosaic transition above goes instant — dock,
|
|
541
|
+
growth, tier fades, body crossfade. State changes still apply, with no animation. */
|
|
542
|
+
@media (prefers-reduced-motion: reduce) {
|
|
543
|
+
.dg-mosaic--rows,
|
|
544
|
+
.dg-mosaic-row,
|
|
545
|
+
.dg-cell,
|
|
546
|
+
.dg-cell .dg-mosaic-stack,
|
|
547
|
+
.dg-cell .dg-mosaic-role,
|
|
548
|
+
.dg-cell .dg-mosaic-detail,
|
|
549
|
+
.dg-mosaic--rows .dg-cell:not(.on) .dg-mosaic-enter,
|
|
550
|
+
.dg-mosaic--rows .dg-cell.on .dg-mosaic-enter {
|
|
551
|
+
transition: none;
|
|
552
|
+
}
|
|
553
|
+
.dg-cell-body { animation: none; }
|
|
554
|
+
.dg-mosaic--rows .dg-cell:not(.on) .dg-mosaic-enter { transform: none; }
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/* The stated figures. They are printed on the cell rather than implied by its
|
|
558
|
+
size, so the sizing is readable rather than felt — a reader can check that
|
|
559
|
+
digiquant's box is bigger because its figure is bigger. Right-aligned inside
|
|
560
|
+
`.dg-stats`, because that is the column the reader compares down. */
|
|
561
|
+
.dg-loc {
|
|
562
|
+
font-family: var(--font-mono);
|
|
563
|
+
font-size: 0.82rem;
|
|
564
|
+
letter-spacing: 0.06em;
|
|
565
|
+
color: var(--ink-mute);
|
|
566
|
+
font-variant-numeric: tabular-nums;
|
|
567
|
+
white-space: nowrap;
|
|
568
|
+
}
|
|
569
|
+
.dg-cell.on .dg-loc { color: var(--ink-soft); }
|
|
570
|
+
|
|
571
|
+
/* The focus morph is the whole point of the mosaic, so the one place it
|
|
572
|
+
must not run is where motion is unwanted: focus then lands on the final
|
|
573
|
+
layout with no travel. The mosaic-face selector keeps the higher
|
|
574
|
+
specificity of the transition it cancels. */
|
|
575
|
+
@media (prefers-reduced-motion: reduce) {
|
|
576
|
+
.dg-mosaic-row,
|
|
577
|
+
.dg-cell,
|
|
578
|
+
.dg-mosaic--rows .dg-cell,
|
|
579
|
+
.dg-mosaic--rows .dg-cell:not(.on) .dg-mosaic-enter,
|
|
580
|
+
.dg-mosaic--rows .dg-cell.on .dg-mosaic-enter {
|
|
581
|
+
transition: none;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
/* Terminal registers (v15, #4429): the boot playback is a fixed box on the
|
|
588
|
+
landing page, so it must not grow as lines type in. `fill` stretches .term
|
|
589
|
+
to the wrapper's height; `compact` drops the body type a step. Both are
|
|
590
|
+
additive modifiers over the shared .term base in site.css. */
|
|
591
|
+
.term--fill { display: flex; flex-direction: column; height: 100%; }
|
|
592
|
+
.term--fill .term-body { flex: 1 1 auto; min-height: 0; overflow: hidden; }
|
|
593
|
+
.term--compact .term-bar { padding: 0.55rem 0.9rem; }
|
|
594
|
+
.term--compact .term-body { font-size: 0.72rem; line-height: 1.72; padding: 0.9rem 1rem 1rem; min-height: 0; }
|
|
595
|
+
.term--compact { box-shadow: 0 28px 64px -40px rgba(0, 0, 0, 0.5); }
|
|
596
|
+
|
|
597
|
+
/* mobile / reduced-motion stepper */
|
|
598
|
+
.dg-stepper { display: flex; flex-direction: column; gap: var(--space-5); max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }
|
|
599
|
+
.dg-step { display: grid; gap: var(--space-3); }
|
|
600
|
+
.dg-graph-mini { max-width: 22.5rem; margin-inline: auto; }
|
|
601
|
+
@media (min-width: 720px) { .dg-step { grid-template-columns: 1fr 1.2fr; align-items: center; } }
|
|
602
|
+
@media (max-width: 900px) { .dg-stage-grid { grid-template-columns: 1fr; } .dg-rail { display: none; } }
|
|
603
|
+
|
|
604
|
+
/* ── disclosure rows (native <details>/<summary>) ───────────────────────────
|
|
605
|
+
A summary that opens something must read as clickable, and a bare <summary>
|
|
606
|
+
computes `cursor: auto` — so the affordance is owned here rather than
|
|
607
|
+
hand-rolled as an app-local `cursor-pointer` on every FAQ (canon: pointer
|
|
608
|
+
cursors are kit-level; apps/ utilities are refused). `list-style: none` plus
|
|
609
|
+
the webkit marker rule drop the default triangle so the caller can draw its
|
|
610
|
+
own indicator. ─────────────────────────────────────────────────────────── */
|
|
611
|
+
.disclosure-row > summary { cursor: pointer; list-style: none; }
|
|
612
|
+
.disclosure-row > summary::-webkit-details-marker { display: none; }
|
|
613
|
+
|
|
614
|
+
/* ── ScrollyFeatures (useScrollyFeatures reference skin) ────────────────────
|
|
615
|
+
Pinned section + progress rail (Graphite pattern). The hook owns state; this
|
|
616
|
+
is the reference CSS. Track height comes from scrollyTrackHeightVh() inline.
|
|
617
|
+
Small-viewport/reduced-motion consumers render .scrolly-stepper instead (all
|
|
618
|
+
slides in flow — the hook signals this via `stepper`). ────────────────── */
|
|
619
|
+
.scrolly-track { position: relative; }
|
|
620
|
+
.scrolly-pin { position: sticky; top: 0; min-height: 100svh; display: flex; flex-direction: column; justify-content: center; }
|
|
621
|
+
.scrolly-rail { --rail-dot: 0.375rem; --rail-dot-gap: var(--space-2); position: absolute; inset-inline-end: clamp(1rem, 3vw, 2rem); top: 50%; transform: translateY(-50%); display: flex; flex-direction: column; gap: var(--rail-dot-gap); }
|
|
622
|
+
.scrolly-tick { width: var(--rail-dot); height: var(--rail-dot); border-radius: 50%; background: var(--hair-2); transition: background .2s var(--ease), transform .2s var(--ease); }
|
|
623
|
+
.scrolly-tick.on { background: var(--accent); transform: scale(1.5); }
|
|
624
|
+
.scrolly-stepper { display: flex; flex-direction: column; gap: var(--space-5); max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }
|
|
625
|
+
|
|
626
|
+
@media (prefers-reduced-motion: reduce) {
|
|
627
|
+
/* Belt-and-suspenders: even if a consumer keeps the pinned track mounted,
|
|
628
|
+
drop the sticky pin so slides read as a static stack. The hook's `stepper`
|
|
629
|
+
flag is the primary path (renders .scrolly-stepper); this is the fallback. */
|
|
630
|
+
.scrolly-pin { position: static; min-height: 0; }
|
|
631
|
+
.scrolly-tick { transition: none; }
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/* ── DatePager calendar (kit, #4306 batch K2) ──────────────────────────────
|
|
635
|
+
Ported verbatim from styles/controls-overlay.css (`.nb-cal*`) so the kit
|
|
636
|
+
<DatePager/> no longer depends on the controls sheet. The enter/exit travel
|
|
637
|
+
is the kit's own `kit-pop` (same 0.15s fade + 0.5rem side slide as the
|
|
638
|
+
controls `.ctl-pop`), declared here rather than in a family sheet. */
|
|
639
|
+
.kit-pop {
|
|
640
|
+
--kit-pop-dur: 0.15s;
|
|
641
|
+
--kit-slide-x: 0rem;
|
|
642
|
+
--kit-slide-y: 0rem;
|
|
643
|
+
}
|
|
644
|
+
.kit-pop[data-side="bottom"] { --kit-slide-y: -0.5rem; }
|
|
645
|
+
.kit-pop[data-side="top"] { --kit-slide-y: 0.5rem; }
|
|
646
|
+
.kit-pop[data-side="left"],
|
|
647
|
+
.kit-pop[data-side="inline-start"] { --kit-slide-x: 0.5rem; }
|
|
648
|
+
.kit-pop[data-side="right"],
|
|
649
|
+
.kit-pop[data-side="inline-end"] { --kit-slide-x: -0.5rem; }
|
|
650
|
+
.kit-pop[data-open] { animation: kit-pop-in var(--kit-pop-dur) ease; }
|
|
651
|
+
.kit-pop[data-closed] { animation: kit-pop-out var(--kit-pop-dur) ease forwards; }
|
|
652
|
+
|
|
653
|
+
@keyframes kit-pop-in {
|
|
654
|
+
from { opacity: 0; transform: translate(var(--kit-slide-x), var(--kit-slide-y)) scale(0.95); }
|
|
655
|
+
}
|
|
656
|
+
@keyframes kit-pop-out {
|
|
657
|
+
to { opacity: 0; transform: translate(var(--kit-slide-x), var(--kit-slide-y)) scale(0.95); }
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
@layer components {
|
|
661
|
+
.nb-cal {
|
|
662
|
+
width: 17.5rem;
|
|
663
|
+
padding: 0.75rem;
|
|
664
|
+
border: 1px solid var(--hair);
|
|
665
|
+
border-radius: 0;
|
|
666
|
+
background: color-mix(in oklab, var(--term-bg) 92%, var(--surface));
|
|
667
|
+
box-shadow: 0 18px 40px -18px rgba(0, 0, 0, 0.55);
|
|
668
|
+
font-family: var(--font-mono);
|
|
669
|
+
color: var(--ink);
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
.nb-cal-head {
|
|
673
|
+
display: grid;
|
|
674
|
+
grid-template-columns: 1.75rem 1fr 1.75rem;
|
|
675
|
+
align-items: center;
|
|
676
|
+
gap: 0.35rem;
|
|
677
|
+
margin-bottom: 0.65rem;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
.nb-cal-title {
|
|
681
|
+
text-align: center;
|
|
682
|
+
font-size: 0.75rem;
|
|
683
|
+
font-weight: 500;
|
|
684
|
+
color: var(--ink);
|
|
685
|
+
letter-spacing: 0.01em;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
.nb-cal-nav {
|
|
689
|
+
display: inline-flex;
|
|
690
|
+
align-items: center;
|
|
691
|
+
justify-content: center;
|
|
692
|
+
width: 1.75rem;
|
|
693
|
+
height: 1.75rem;
|
|
694
|
+
margin: 0;
|
|
695
|
+
padding: 0;
|
|
696
|
+
border: none;
|
|
697
|
+
border-radius: 0;
|
|
698
|
+
background: transparent;
|
|
699
|
+
color: var(--ink-mute);
|
|
700
|
+
cursor: pointer;
|
|
701
|
+
transition:
|
|
702
|
+
color 0.15s cubic-bezier(0.4, 0, 0.2, 1),
|
|
703
|
+
background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1);
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
.nb-cal-nav:hover:not(:disabled) {
|
|
707
|
+
color: var(--ink);
|
|
708
|
+
background: color-mix(in oklab, var(--ink) 6%, transparent);
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
.nb-cal-nav:disabled {
|
|
712
|
+
opacity: 0.3;
|
|
713
|
+
cursor: not-allowed;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
.nb-cal-weekdays,
|
|
717
|
+
.nb-cal-row {
|
|
718
|
+
display: grid;
|
|
719
|
+
grid-template-columns: repeat(7, 1fr);
|
|
720
|
+
gap: 0.15rem;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
.nb-cal-grid {
|
|
724
|
+
display: flex;
|
|
725
|
+
flex-direction: column;
|
|
726
|
+
gap: 0.15rem;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
.nb-cal-weekday {
|
|
730
|
+
display: flex;
|
|
731
|
+
align-items: center;
|
|
732
|
+
justify-content: center;
|
|
733
|
+
height: 1.35rem;
|
|
734
|
+
font-size: 0.62rem;
|
|
735
|
+
color: var(--ink-mute);
|
|
736
|
+
text-transform: uppercase;
|
|
737
|
+
letter-spacing: 0.04em;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
.nb-cal-day {
|
|
741
|
+
display: inline-flex;
|
|
742
|
+
align-items: center;
|
|
743
|
+
justify-content: center;
|
|
744
|
+
width: 100%;
|
|
745
|
+
aspect-ratio: 1;
|
|
746
|
+
margin: 0;
|
|
747
|
+
padding: 0;
|
|
748
|
+
border: 1px solid transparent;
|
|
749
|
+
border-radius: 0;
|
|
750
|
+
background: transparent;
|
|
751
|
+
color: var(--ink-soft);
|
|
752
|
+
font: inherit;
|
|
753
|
+
font-size: 0.72rem;
|
|
754
|
+
font-variant-numeric: tabular-nums;
|
|
755
|
+
cursor: pointer;
|
|
756
|
+
transition:
|
|
757
|
+
color 0.15s cubic-bezier(0.4, 0, 0.2, 1),
|
|
758
|
+
background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1),
|
|
759
|
+
border-color 0.15s cubic-bezier(0.4, 0, 0.2, 1);
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
.nb-cal-day:hover:not(:disabled):not(.nb-cal-day--selected) {
|
|
763
|
+
color: var(--ink);
|
|
764
|
+
background: color-mix(in oklab, var(--ink) 6%, transparent);
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
.nb-cal-day--selected {
|
|
768
|
+
color: var(--accent);
|
|
769
|
+
background: color-mix(in oklab, var(--accent) 20%, transparent);
|
|
770
|
+
border-color: color-mix(in oklab, var(--accent) 35%, transparent);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
.nb-cal-day--muted,
|
|
774
|
+
.nb-cal-day:disabled {
|
|
775
|
+
color: var(--ink-mute);
|
|
776
|
+
opacity: 0.35;
|
|
777
|
+
cursor: not-allowed;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
.nb-cal-day--empty {
|
|
781
|
+
pointer-events: none;
|
|
782
|
+
visibility: hidden;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
@media (prefers-reduced-motion: reduce) {
|
|
787
|
+
.kit-pop[data-open],
|
|
788
|
+
.kit-pop[data-closed] {
|
|
789
|
+
animation: none;
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
/* ==========================================================================
|
|
794
|
+
PAGE GEOMETRY + ENTRANCE CHOREOGRAPHY (D1, #4429 — ported techniques)
|
|
795
|
+
--------------------------------------------------------------------------
|
|
796
|
+
Two things this kit was missing, both read out of launch-ui's source (MIT)
|
|
797
|
+
rather than invented:
|
|
798
|
+
|
|
799
|
+
1. `line-*` / `fade-*` / `glass-*` — a named utility vocabulary so sections
|
|
800
|
+
COMPOSE instead of hand-rolling a border or a mask each time. That
|
|
801
|
+
hand-rolling is exactly why the first pass of pages read as ad hoc.
|
|
802
|
+
|
|
803
|
+
2. `animate-appear` — the staged entrance. Every hero element carries it
|
|
804
|
+
with a `delay-*` class, starting from `opacity-0`; `forwards` means the
|
|
805
|
+
resting state after the run is the visible one, so nothing flashes.
|
|
806
|
+
|
|
807
|
+
Both are token-backed. NOTE for the canon guard: `line-*` deliberately
|
|
808
|
+
duplicates @digithings-ai/design/site/site.css's legacy `.line-*` names — that
|
|
809
|
+
sheet is imported by apps that do NOT import this bridge, so neither can
|
|
810
|
+
own it exclusively. Declared here as `@utility` so Tailwind generates them
|
|
811
|
+
alongside its own.
|
|
812
|
+
========================================================================== */
|
|
813
|
+
|
|
814
|
+
/* ---- Layout rules: the persistent page geometry -------------------------
|
|
815
|
+
A section that runs the full container height between two vertical hairlines
|
|
816
|
+
reads as one built object rather than boxes in a column. `line-y` draws only
|
|
817
|
+
the inline edges (0 top/bottom), `line-x` only the block edges.
|
|
818
|
+
|
|
819
|
+
These two are the *rails*, and they draw at `--hair-2` rather than `--hair`.
|
|
820
|
+
At `--hair` (9% white) the rail was invisible against the page ground, which
|
|
821
|
+
defeats the technique: a guide nobody can see is not geometry. One step up
|
|
822
|
+
(15%) registers at a glance while staying below any content edge, so the rail
|
|
823
|
+
reads as structure rather than as a border.
|
|
824
|
+
|
|
825
|
+
`line-t` / `line-b` deliberately stay at `--hair`. They are section
|
|
826
|
+
*dividers* — a different role, and there are dozens of them; raising those
|
|
827
|
+
would change the rhythm of every page rather than the frame around it. The
|
|
828
|
+
weight classes are: content edge > rail > divider > ground. */
|
|
829
|
+
/* Plain CSS, not @apply and not a var()-based shorthand: Tailwind's utility
|
|
830
|
+
generator resolves these at build time and a `var(--line-width, 1px)` inside
|
|
831
|
+
a shorthand did not survive (the border rendered 0px). A literal `1px` is
|
|
832
|
+
correct here — the hairline width is a canon constant, not a themed value. */
|
|
833
|
+
@utility line-y {
|
|
834
|
+
border-left-width: 1px;
|
|
835
|
+
border-right-width: 1px;
|
|
836
|
+
border-style: solid;
|
|
837
|
+
border-color: var(--hair-2);
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
@utility line-x {
|
|
841
|
+
border-top-width: 1px;
|
|
842
|
+
border-bottom-width: 1px;
|
|
843
|
+
border-style: solid;
|
|
844
|
+
border-color: var(--hair-2);
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
@utility line-t {
|
|
848
|
+
border-top-width: 1px;
|
|
849
|
+
border-style: solid;
|
|
850
|
+
border-color: var(--hair);
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
@utility line-b {
|
|
854
|
+
border-bottom-width: 1px;
|
|
855
|
+
border-style: solid;
|
|
856
|
+
border-color: var(--hair);
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
/* Must come AFTER the line-* rules in source order for equal specificity to
|
|
860
|
+
win, which is why it is declared here rather than with the others. */
|
|
861
|
+
@utility line-dashed {
|
|
862
|
+
border-style: dashed;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
/* ---- Fade masks: bleed an artefact into the page instead of cutting it ---
|
|
866
|
+
(`fade-bottom` on a hero section is what stops a product shot ending on a
|
|
867
|
+
hard edge.) */
|
|
868
|
+
@utility fade-x {
|
|
869
|
+
mask-image: linear-gradient(to right, transparent 0%, black 25%, black 75%, transparent 100%);
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
@utility fade-y {
|
|
873
|
+
mask-image: linear-gradient(to top, transparent 0%, black 25%, black 75%, transparent 100%);
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
@utility fade-top {
|
|
877
|
+
mask-image: linear-gradient(to bottom, transparent 0%, black 35%);
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
@utility fade-bottom {
|
|
881
|
+
mask-image: linear-gradient(to top, transparent 0%, black 35%);
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
@utility fade-top-lg {
|
|
885
|
+
mask-image: linear-gradient(to bottom, transparent 15%, black 100%);
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
@utility fade-bottom-lg {
|
|
889
|
+
mask-image: linear-gradient(to top, transparent 15%, black 100%);
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
@utility fade-left {
|
|
893
|
+
mask-image: linear-gradient(to right, transparent 0%, black 35%);
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
@utility fade-right {
|
|
897
|
+
mask-image: linear-gradient(to left, transparent 0%, black 35%);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
/* ---- Glass: layered gradient surfaces over the flat ground -------------
|
|
901
|
+
Five depths. `hair` is this system's border token, so the edges stay in the
|
|
902
|
+
canon rather than reaching for a Tailwind palette. */
|
|
903
|
+
@utility glass-1 {
|
|
904
|
+
border: 1px solid var(--hair);
|
|
905
|
+
background-image: linear-gradient(to bottom, color-mix(in srgb, var(--surface) 80%, transparent), color-mix(in srgb, var(--surface) 40%, transparent));
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
@utility glass-2 {
|
|
909
|
+
border: 1px solid var(--hair);
|
|
910
|
+
background-image: linear-gradient(to bottom, var(--surface), color-mix(in srgb, var(--surface) 80%, transparent));
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
@utility glass-3 {
|
|
914
|
+
border: 1px solid var(--hair);
|
|
915
|
+
background-image: linear-gradient(to bottom, color-mix(in srgb, var(--surface) 30%, transparent), color-mix(in srgb, var(--surface) 20%, transparent));
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
@utility glass-4 {
|
|
919
|
+
border: 1px solid var(--hair);
|
|
920
|
+
background-image: linear-gradient(to bottom, color-mix(in srgb, var(--surface) 60%, transparent), color-mix(in srgb, var(--surface) 20%, transparent));
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
@utility glass-5 {
|
|
924
|
+
border: 1px solid var(--hair);
|
|
925
|
+
background-image: linear-gradient(to bottom, var(--surface), color-mix(in srgb, var(--surface) 20%, transparent));
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
/* ---- The entrance choreography: keyframes + tokens live in the one
|
|
929
|
+
@theme inline block above, per web-theme.test.ts. ---- */
|
|
930
|
+
|
|
931
|
+
/* Reduced motion: the choreography parks elements at their END state rather
|
|
932
|
+
than their start state, so a reduced-motion visitor sees the finished page
|
|
933
|
+
immediately instead of a page of invisible elements. */
|
|
934
|
+
@media (prefers-reduced-motion: reduce) {
|
|
935
|
+
.animate-appear,
|
|
936
|
+
.animate-appear-zoom {
|
|
937
|
+
animation: none;
|
|
938
|
+
opacity: 1;
|
|
939
|
+
transform: none;
|
|
940
|
+
filter: none;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
/* ── Squared scrollbars: one bar for the whole product surface ─────────────
|
|
945
|
+
Every box in this system is square, so the scrollbar must be too. macOS
|
|
946
|
+
draws a rounded overlay pill by default, and on a page of hairline edges it
|
|
947
|
+
is the only rounded shape left.
|
|
948
|
+
|
|
949
|
+
Two renderers, two mechanisms, and they must not meet:
|
|
950
|
+
|
|
951
|
+
· Blink/WebKit expose a bar only through ::-webkit-scrollbar-*. A styled
|
|
952
|
+
pseudo is a classic bar — it reserves its own track and never becomes an
|
|
953
|
+
overlay — and `border-radius: 0` on the thumb is what squares it. This is
|
|
954
|
+
the same treatment as digichat's `data-scrollbars="always"` skin
|
|
955
|
+
(chat-digichat.css), so the chat surface and the site read identically.
|
|
956
|
+
· Firefox has no pseudo-elements, so it takes the standard
|
|
957
|
+
`scrollbar-width` / `scrollbar-color` pair — guarded to Gecko. That guard
|
|
958
|
+
is load-bearing, not tidiness: declaring either property in Blink switches
|
|
959
|
+
the element to the native bar renderer and silently disables the
|
|
960
|
+
::-webkit-scrollbar rules above, so an unguarded `*` rule would un-square
|
|
961
|
+
every Chromium surface while still looking right in the source.
|
|
962
|
+
|
|
963
|
+
The fill stays under :where(*) and therefore carries zero specificity. A
|
|
964
|
+
surface that hides its bar — `.dg-cell`, `.cr-track`, `.h-scroll__track`,
|
|
965
|
+
Tailwind's `[&::-webkit-scrollbar]:hidden` — keeps winning with its own
|
|
966
|
+
class-level `display: none` / `scrollbar-width: none`, and a surface that
|
|
967
|
+
paints its own thumb (digichat's skin, digiquant-web's `McpCli`) keeps its
|
|
968
|
+
colour. Do not raise these selectors to "fix" a local case. */
|
|
969
|
+
:where(*)::-webkit-scrollbar {
|
|
970
|
+
width: 0.625rem;
|
|
971
|
+
height: 0.625rem;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
/* Transparent, so the bar lies on whatever surface it crosses — page, panel,
|
|
975
|
+
popover, terminal — instead of painting a stripe across it. */
|
|
976
|
+
:where(*)::-webkit-scrollbar-track,
|
|
977
|
+
:where(*)::-webkit-scrollbar-corner {
|
|
978
|
+
background: transparent;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
/* Shape is the one part that is not negotiable, and it is the one part an
|
|
982
|
+
app-local stylesheet is most likely to have already answered: a bare
|
|
983
|
+
`::-webkit-scrollbar-thumb { border-radius: 3px }` (apps/dashboard) ties
|
|
984
|
+
:where(*) on specificity and wins on order, because every app imports this
|
|
985
|
+
file before its own rules. The element-level `html` prefix lifts this rule
|
|
986
|
+
to (0,0,2) — above a bare pseudo (0,0,1) and still far below any
|
|
987
|
+
class-level `display: none` (0,1,x) — so the square holds everywhere. */
|
|
988
|
+
html::-webkit-scrollbar-thumb,
|
|
989
|
+
html :where(*)::-webkit-scrollbar-thumb {
|
|
990
|
+
border-radius: 0;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
:where(*)::-webkit-scrollbar-thumb {
|
|
994
|
+
background: color-mix(in oklab, var(--ink-mute) 32%, transparent);
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
:where(*)::-webkit-scrollbar-thumb:hover,
|
|
998
|
+
:where(*)::-webkit-scrollbar-thumb:active {
|
|
999
|
+
background: color-mix(in oklab, var(--ink-mute) 55%, transparent);
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
@supports (-moz-appearance: none) {
|
|
1003
|
+
:where(*) {
|
|
1004
|
+
scrollbar-width: thin;
|
|
1005
|
+
scrollbar-color: color-mix(in oklab, var(--ink-mute) 38%, transparent) transparent;
|
|
1006
|
+
}
|
|
1007
|
+
}
|