@felloinnovations/brand-kit 0.4.0 → 0.5.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/AGENTS.md +198 -24
- package/CHANGELOG.md +197 -0
- package/README.md +34 -7
- package/design-system/01-how-claude-decides.md +26 -17
- package/design-system/02-principles.md +11 -6
- package/design-system/03-colour.md +134 -47
- package/design-system/04-type.md +45 -23
- package/design-system/05-space-and-layout.md +175 -52
- package/design-system/06-sizing-profiles.md +4 -4
- package/design-system/07-scrolling.md +66 -20
- package/design-system/08-choosing-components.md +50 -22
- package/design-system/09-charts.md +71 -28
- package/design-system/10-patterns.md +33 -10
- package/design-system/11-page-recipes.md +110 -23
- package/design-system/12-content.md +2 -1
- package/design-system/13-motion.md +330 -47
- package/design-system/14-accessibility.md +47 -24
- package/design-system/15-ai-experiences.md +11 -6
- package/design-system/16-creativity.md +1 -1
- package/design-system/17-decisions.md +357 -1
- package/design-system/18-checklist.md +79 -16
- package/design-system/19-public-pages.md +6 -4
- package/design-system/20-palettes.md +275 -0
- package/design-system/README.md +30 -17
- package/design-system/components/ActionList/README.md +96 -10
- package/design-system/components/ActionList/preview.html +52 -7
- package/design-system/components/ActionList/style.css +64 -0
- package/design-system/components/ActivityGrid/README.md +38 -2
- package/design-system/components/ActivityGrid/preview.html +1 -1
- package/design-system/components/ActivityGrid/style.css +35 -0
- package/design-system/components/AppShell/README.md +205 -75
- package/design-system/components/AppShell/preview.html +339 -58
- package/design-system/components/AppShell/style.css +154 -0
- package/design-system/components/Avatar/README.md +37 -10
- package/design-system/components/Avatar/preview.html +13 -4
- package/design-system/components/Avatar/style.css +14 -0
- package/design-system/components/Badge/README.md +41 -19
- package/design-system/components/Badge/preview.html +13 -10
- package/design-system/components/Badge/style.css +23 -0
- package/design-system/components/Banner/README.md +30 -9
- package/design-system/components/Banner/preview.html +1 -1
- package/design-system/components/Banner/style.css +19 -0
- package/design-system/components/Breadcrumb/README.md +58 -46
- package/design-system/components/Breadcrumb/preview.html +16 -16
- package/design-system/components/Breadcrumb/style.css +17 -0
- package/design-system/components/Button/README.md +113 -55
- package/design-system/components/Button/preview.html +98 -25
- package/design-system/components/Button/style.css +86 -0
- package/design-system/components/Card/README.md +158 -49
- package/design-system/components/Card/preview.html +141 -19
- package/design-system/components/Card/style.css +115 -0
- package/design-system/components/CardBoard/README.md +58 -37
- package/design-system/components/CardBoard/preview.html +26 -29
- package/design-system/components/ChatCard/README.md +115 -29
- package/design-system/components/ChatCard/preview.html +149 -32
- package/design-system/components/ChatCard/style.css +49 -0
- package/design-system/components/ChatShell/README.md +116 -0
- package/design-system/components/ChatShell/preview.html +201 -0
- package/design-system/components/ChatShell/style.css +86 -0
- package/design-system/components/ChatTurn/README.md +78 -35
- package/design-system/components/ChatTurn/preview.html +60 -28
- package/design-system/components/ChatTurn/style.css +50 -0
- package/design-system/components/CheckRow/README.md +141 -0
- package/design-system/components/CheckRow/preview.html +140 -0
- package/design-system/components/CheckRow/style.css +88 -0
- package/design-system/components/Checkbox/README.md +58 -22
- package/design-system/components/Checkbox/preview.html +112 -50
- package/design-system/components/Checkbox/style.css +45 -0
- package/design-system/components/Chip/README.md +78 -47
- package/design-system/components/Chip/preview.html +29 -4
- package/design-system/components/Chip/style.css +17 -0
- package/design-system/components/Combobox/README.md +44 -11
- package/design-system/components/Combobox/preview.html +35 -12
- package/design-system/components/Combobox/style.css +54 -0
- package/design-system/components/Composer/README.md +137 -35
- package/design-system/components/Composer/preview.html +115 -40
- package/design-system/components/Composer/style.css +81 -0
- package/design-system/components/ConfirmDialog/README.md +73 -52
- package/design-system/components/ConfirmDialog/preview.html +70 -26
- package/design-system/components/ConfirmDialog/style.css +5 -0
- package/design-system/components/Cover/preview.html +3 -3
- package/design-system/components/Cover/style.css +19 -0
- package/design-system/components/DateInput/README.md +77 -12
- package/design-system/components/DateInput/preview.html +27 -12
- package/design-system/components/DateInput/style.css +38 -0
- package/design-system/components/Dialog/README.md +112 -44
- package/design-system/components/Dialog/preview.html +141 -18
- package/design-system/components/Dialog/style.css +74 -0
- package/design-system/components/EmptyState/README.md +42 -12
- package/design-system/components/EmptyState/preview.html +11 -11
- package/design-system/components/EmptyState/style.css +9 -0
- package/design-system/components/EntryShell/README.md +73 -48
- package/design-system/components/EntryShell/preview.html +60 -27
- package/design-system/components/EntryShell/style.css +19 -0
- package/design-system/components/FeatureGrid/README.md +61 -39
- package/design-system/components/FeatureGrid/preview.html +2 -2
- package/design-system/components/FeatureGrid/style.css +20 -0
- package/design-system/components/FileUpload/README.md +33 -3
- package/design-system/components/FileUpload/preview.html +18 -4
- package/design-system/components/FileUpload/style.css +23 -0
- package/design-system/components/FilterBar/README.md +114 -0
- package/design-system/components/FilterBar/preview.html +82 -0
- package/design-system/components/FilterBar/style.css +22 -0
- package/design-system/components/Fold/README.md +84 -26
- package/design-system/components/Fold/preview.html +77 -34
- package/design-system/components/Fold/style.css +48 -0
- package/design-system/components/Footer/README.md +62 -39
- package/design-system/components/Footer/preview.html +5 -5
- package/design-system/components/Footer/style.css +30 -0
- package/design-system/components/FunnelBars/README.md +24 -3
- package/design-system/components/FunnelBars/preview.html +5 -5
- package/design-system/components/FunnelBars/style.css +13 -0
- package/design-system/components/GoalBars/README.md +54 -10
- package/design-system/components/GoalBars/preview.html +69 -28
- package/design-system/components/GoalBars/style.css +51 -0
- package/design-system/components/GoalTicks/README.md +74 -58
- package/design-system/components/GoalTicks/preview.html +41 -118
- package/design-system/components/GoalTicks/style.css +37 -0
- package/design-system/components/GoalTubes/README.md +29 -3
- package/design-system/components/GoalTubes/preview.html +6 -6
- package/design-system/components/GoalTubes/style.css +23 -0
- package/design-system/components/Heatmap/README.md +133 -0
- package/design-system/components/Heatmap/preview.html +168 -0
- package/design-system/components/Heatmap/style.css +119 -0
- package/design-system/components/Hero/README.md +58 -40
- package/design-system/components/Hero/preview.html +1 -1
- package/design-system/components/Hero/style.css +19 -0
- package/design-system/components/HoverCard/README.md +114 -0
- package/design-system/components/HoverCard/preview.html +107 -0
- package/design-system/components/HoverCard/style.css +59 -0
- package/design-system/components/IconButton/README.md +69 -38
- package/design-system/components/IconButton/preview.html +77 -43
- package/design-system/components/IconButton/style.css +45 -0
- package/design-system/components/Input/README.md +36 -11
- package/design-system/components/Input/preview.html +1 -1
- package/design-system/components/Input/style.css +23 -0
- package/design-system/components/KanbanBoard/README.md +93 -45
- package/design-system/components/KanbanBoard/preview.html +159 -43
- package/design-system/components/KanbanBoard/style.css +53 -0
- package/design-system/components/Kbd/README.md +25 -9
- package/design-system/components/Kbd/preview.html +6 -2
- package/design-system/components/Kbd/style.css +9 -0
- package/design-system/components/KitButton/README.md +81 -47
- package/design-system/components/KitButton/preview.html +35 -13
- package/design-system/components/KitButton/style.css +46 -0
- package/design-system/components/KitCard/README.md +75 -44
- package/design-system/components/KitCard/preview.html +18 -10
- package/design-system/components/KitCard/style.css +15 -0
- package/design-system/components/KitInput/README.md +54 -39
- package/design-system/components/KitInput/preview.html +7 -7
- package/design-system/components/KitInput/style.css +23 -0
- package/design-system/components/Leaderboard/README.md +76 -49
- package/design-system/components/Leaderboard/preview.html +61 -26
- package/design-system/components/Leaderboard/style.css +44 -0
- package/design-system/components/ListDetail/README.md +222 -0
- package/design-system/components/ListDetail/preview.html +213 -0
- package/design-system/components/ListDetail/style.css +148 -0
- package/design-system/components/LoadBar/README.md +79 -0
- package/design-system/components/LoadBar/preview.html +40 -0
- package/design-system/components/LoadBar/style.css +17 -0
- package/design-system/components/MarketingNav/README.md +76 -42
- package/design-system/components/MarketingNav/preview.html +37 -8
- package/design-system/components/MarketingNav/style.css +45 -0
- package/design-system/components/Matrix/README.md +129 -0
- package/design-system/components/Matrix/preview.html +99 -0
- package/design-system/components/Matrix/style.css +84 -0
- package/design-system/components/Menu/README.md +117 -41
- package/design-system/components/Menu/preview.html +85 -23
- package/design-system/components/Menu/style.css +61 -0
- package/design-system/components/Meter/README.md +39 -4
- package/design-system/components/Meter/preview.html +18 -1
- package/design-system/components/Meter/style.css +23 -0
- package/design-system/components/MetricTile/README.md +237 -0
- package/design-system/components/MetricTile/preview.html +241 -0
- package/design-system/components/MetricTile/style.css +129 -0
- package/design-system/components/Morph/README.md +106 -0
- package/design-system/components/Morph/preview.html +103 -0
- package/design-system/components/Morph/style.css +31 -0
- package/design-system/components/Motion/README.md +164 -0
- package/design-system/components/Motion/preview.html +2537 -0
- package/design-system/components/NumberInput/README.md +27 -8
- package/design-system/components/NumberInput/preview.html +21 -5
- package/design-system/components/NumberInput/style.css +34 -0
- package/design-system/components/PaceBar/README.md +75 -0
- package/design-system/components/PaceBar/preview.html +67 -0
- package/design-system/components/PaceBar/style.css +25 -0
- package/design-system/components/Page/README.md +57 -18
- package/design-system/components/Page/preview.html +15 -17
- package/design-system/components/Page/style.css +7 -0
- package/design-system/components/PageBar/README.md +90 -34
- package/design-system/components/PageBar/preview.html +60 -19
- package/design-system/components/PageBar/style.css +35 -0
- package/design-system/components/PageHero/README.md +87 -51
- package/design-system/components/PageHero/preview.html +35 -6
- package/design-system/components/PageHero/style.css +31 -0
- package/design-system/components/Pagination/README.md +70 -49
- package/design-system/components/Pagination/preview.html +24 -15
- package/design-system/components/Pagination/style.css +12 -0
- package/design-system/components/Panel/README.md +109 -51
- package/design-system/components/Panel/preview.html +118 -20
- package/design-system/components/Panel/style.css +51 -0
- package/design-system/components/PasswordInput/README.md +50 -18
- package/design-system/components/PasswordInput/preview.html +71 -21
- package/design-system/components/PasswordInput/style.css +31 -0
- package/design-system/components/Plate/README.md +75 -17
- package/design-system/components/Plate/preview.html +40 -7
- package/design-system/components/Plate/style.css +37 -0
- package/design-system/components/Popover/README.md +70 -49
- package/design-system/components/Popover/preview.html +44 -22
- package/design-system/components/Popover/style.css +41 -0
- package/design-system/components/PricingTable/README.md +69 -49
- package/design-system/components/PricingTable/preview.html +21 -21
- package/design-system/components/PricingTable/style.css +21 -0
- package/design-system/components/ProgressPetals/README.md +31 -3
- package/design-system/components/ProgressPetals/preview.html +14 -15
- package/design-system/components/ProgressPetals/style.css +27 -0
- package/design-system/components/README.md +151 -0
- package/design-system/components/Radio/README.md +40 -17
- package/design-system/components/Radio/preview.html +16 -1
- package/design-system/components/Radio/style.css +21 -0
- package/design-system/components/RankBar/README.md +29 -2
- package/design-system/components/RankBar/preview.html +14 -12
- package/design-system/components/RankBar/style.css +18 -0
- package/design-system/components/Ring/README.md +61 -11
- package/design-system/components/Ring/preview.html +55 -10
- package/design-system/components/Ring/style.css +49 -0
- package/design-system/components/ScoreHero/README.md +91 -0
- package/design-system/components/ScoreHero/preview.html +104 -0
- package/design-system/components/ScoreHero/style.css +32 -0
- package/design-system/components/Section/README.md +72 -33
- package/design-system/components/Section/preview.html +46 -16
- package/design-system/components/Section/style.css +18 -0
- package/design-system/components/Segmented/README.md +100 -55
- package/design-system/components/Segmented/preview.html +107 -26
- package/design-system/components/Segmented/style.css +94 -0
- package/design-system/components/SegmentedProgress/README.md +64 -0
- package/design-system/components/SegmentedProgress/preview.html +69 -0
- package/design-system/components/SegmentedProgress/style.css +11 -0
- package/design-system/components/Select/README.md +47 -12
- package/design-system/components/Select/preview.html +28 -2
- package/design-system/components/Select/style.css +22 -0
- package/design-system/components/ShareBar/README.md +69 -0
- package/design-system/components/ShareBar/preview.html +72 -0
- package/design-system/components/ShareBar/style.css +25 -0
- package/design-system/components/SideList/README.md +147 -0
- package/design-system/components/SideList/preview.html +139 -0
- package/design-system/components/SideList/style.css +94 -0
- package/design-system/components/Skeleton/README.md +52 -16
- package/design-system/components/Skeleton/preview.html +35 -23
- package/design-system/components/Skeleton/style.css +22 -0
- package/design-system/components/Slider/README.md +95 -0
- package/design-system/components/Slider/preview.html +49 -0
- package/design-system/components/Slider/style.css +13 -0
- package/design-system/components/Split/README.md +112 -0
- package/design-system/components/Split/preview.html +105 -0
- package/design-system/components/Split/style.css +30 -0
- package/design-system/components/Starter/README.md +21 -9
- package/design-system/components/Starter/preview.html +5 -5
- package/design-system/components/Stat/README.md +64 -43
- package/design-system/components/Stat/preview.html +3 -3
- package/design-system/components/Stat/style.css +15 -0
- package/design-system/components/StatTiles/README.md +88 -44
- package/design-system/components/StatTiles/preview.html +142 -71
- package/design-system/components/StatTiles/style.css +64 -0
- package/design-system/components/StatusLine/README.md +85 -0
- package/design-system/components/StatusLine/preview.html +49 -0
- package/design-system/components/StatusLine/style.css +14 -0
- package/design-system/components/StatusScreen/README.md +49 -35
- package/design-system/components/StatusScreen/preview.html +20 -5
- package/design-system/components/StatusScreen/style.css +9 -0
- package/design-system/components/StepLine/README.md +97 -0
- package/design-system/components/StepLine/preview.html +108 -0
- package/design-system/components/StepLine/style.css +62 -0
- package/design-system/components/Stepper/README.md +35 -13
- package/design-system/components/Stepper/style.css +13 -0
- package/design-system/components/StreakCalendar/README.md +22 -1
- package/design-system/components/StreakCalendar/preview.html +10 -10
- package/design-system/components/StreakCalendar/style.css +12 -0
- package/design-system/components/SuggestionChip/README.md +87 -0
- package/design-system/components/SuggestionChip/preview.html +42 -0
- package/design-system/components/SuggestionChip/style.css +20 -0
- package/design-system/components/Switch/README.md +44 -24
- package/design-system/components/Switch/preview.html +23 -8
- package/design-system/components/Switch/style.css +31 -0
- package/design-system/components/Table/README.md +129 -58
- package/design-system/components/Table/preview.html +106 -72
- package/design-system/components/Table/style.css +104 -0
- package/design-system/components/Tabs/README.md +71 -46
- package/design-system/components/Tabs/preview.html +56 -24
- package/design-system/components/Tabs/style.css +44 -0
- package/design-system/components/Testimonial/README.md +48 -32
- package/design-system/components/Testimonial/preview.html +14 -14
- package/design-system/components/Testimonial/style.css +12 -0
- package/design-system/components/TextArea/README.md +27 -11
- package/design-system/components/TextArea/preview.html +8 -2
- package/design-system/components/TextArea/style.css +12 -0
- package/design-system/components/ThemeSwitch/README.md +116 -0
- package/design-system/components/ThemeSwitch/preview.html +57 -0
- package/design-system/components/ThemeSwitch/style.css +6 -0
- package/design-system/components/TickRow/README.md +52 -36
- package/design-system/components/TickRow/preview.html +64 -41
- package/design-system/components/TickRow/style.css +23 -0
- package/design-system/components/TickStrip/README.md +95 -0
- package/design-system/components/TickStrip/preview.html +88 -0
- package/design-system/components/TickStrip/style.css +42 -0
- package/design-system/components/Tile/README.md +79 -18
- package/design-system/components/Tile/preview.html +91 -40
- package/design-system/components/Tile/style.css +36 -0
- package/design-system/components/Timeline/README.md +68 -48
- package/design-system/components/Timeline/preview.html +27 -15
- package/design-system/components/Timeline/style.css +25 -0
- package/design-system/components/Toast/README.md +70 -38
- package/design-system/components/Toast/preview.html +43 -8
- package/design-system/components/Toast/style.css +25 -0
- package/design-system/components/Tooltip/README.md +93 -35
- package/design-system/components/Tooltip/preview.html +69 -15
- package/design-system/components/Tooltip/style.css +78 -0
- package/design-system/components/TopBar/README.md +67 -53
- package/design-system/components/TopBar/preview.html +14 -27
- package/design-system/components/TopBar/style.css +35 -0
- package/design-system/components/TopicRail/README.md +108 -0
- package/design-system/components/TopicRail/preview.html +58 -0
- package/design-system/components/TopicRail/style.css +48 -0
- package/design-system/components/TrendBars/README.md +52 -14
- package/design-system/components/TrendBars/preview.html +65 -32
- package/design-system/components/TrendBars/style.css +25 -0
- package/design-system/components/TrendLine/README.md +164 -0
- package/design-system/components/TrendLine/preview.html +373 -0
- package/design-system/components/TrendLine/style.css +155 -0
- package/design-system/components/Well/README.md +64 -22
- package/design-system/components/Well/preview.html +14 -14
- package/design-system/components/Well/style.css +22 -0
- package/design-system/components/_house.css +324 -0
- package/design-system/components/bundle.css +4091 -744
- package/design-system/tokens.json +1314 -124
- package/dist/fello-core.css +2 -2
- package/dist/fello.css +6 -1369
- package/dist/fello.scoped.css +7 -0
- package/dist/index.d.ts +110 -11
- package/dist/index.js +781 -96
- package/dist/palettes.d.ts +464 -0
- package/dist/palettes.js +497 -0
- package/dist/scoped.d.ts +3 -0
- package/dist/scoped.js +16 -0
- package/dist/toast.d.ts +14 -0
- package/dist/toast.js +33 -29
- package/dist/tokens.d.ts +1686 -62
- package/dist/tokens.js +1668 -61
- package/package.json +20 -4
- package/scripts/check-palette.mjs +295 -0
- package/scripts/token-model.mjs +552 -0
- package/tokens/_dark.css +174 -0
- package/tokens/_palettes.css +46 -0
- package/tokens/_product.css +266 -53
- package/tokens/_source.hubl.css +39 -19
- package/tokens/design-tokens.json +319 -0
- package/tokens/palettes.ts +504 -0
- package/tokens/shadcn-compat.css +19 -19
- package/tokens/shadcn-compat.hsl.css +76 -0
- package/tokens/tokens.css +1292 -62
- package/tokens/tokens.md +588 -61
- package/tokens/tokens.root.css +1298 -62
- package/tokens/tokens.ts +1677 -64
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/* Fello Brand Kit: the house styles every preview and consumer shares. Loaded after tokens.css, which declares
|
|
2
|
+
every --color-*, --ws-*, --space-*, --radius-*, --shadow-* and --font-body custom property from tokens.json.
|
|
3
|
+
The class names are the product layer's (ws-*), so code and system speak one language.
|
|
4
|
+
|
|
5
|
+
Two parts: the house (base, stage, layout, surfaces, words, fields, rows, motion, touch), then every catalog component
|
|
6
|
+
(scripts/build-bundle.mjs: the primitives, then A to Z) under its own block, `.ws-<component>` (the component's name in kebab case), its parts
|
|
7
|
+
`.ws-<component>__part` and its variants `.ws-<component>--variant`. A preview is markup only: everything it shows
|
|
8
|
+
is styled here. Every value is a token or a calc on tokens.
|
|
9
|
+
|
|
10
|
+
The kit touches only its own elements (0.5.0, D11). An element reset applies to an element that wears a ws-* class
|
|
11
|
+
or sits inside one, through :where(), so it costs no specificity and a host's own markup and utilities are left
|
|
12
|
+
alone; only the page itself (html, body) is styled bare. In dist/fello.css everything above the base mark below sits
|
|
13
|
+
in the base.fello cascade layer and the rest in components.fello (scripts/fello-css.mjs says why). */
|
|
14
|
+
@import url("https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400;500;600&display=swap");
|
|
15
|
+
|
|
16
|
+
/* ---- Base: the page, then resets on kit elements ([class^="ws-"], [class*=" ws-"] and what sits inside them) ---- */
|
|
17
|
+
html { font-family: var(--font-body); -webkit-font-smoothing: antialiased; }
|
|
18
|
+
body { margin: 0; background: var(--color-bg-page); color: var(--color-text-body); font-family: var(--font-body); font-size: var(--ws-text-body); line-height: calc(var(--space-md) + var(--space-xxs)); }
|
|
19
|
+
/* An element that sets a palette or a theme sets its words too (D15): `color` inherits as the colour it resolved to, so
|
|
20
|
+
without this a dark container in a light page would keep the page's grey for every word it does not colour itself.
|
|
21
|
+
No specificity, so any colour a component or the host gives wins. */
|
|
22
|
+
:where([data-palette], [data-theme], .fello) { color: var(--color-text-body); }
|
|
23
|
+
/* The page type on the kit's roots too. A host or an artifact skeleton that styles body unlayered beats this layer on
|
|
24
|
+
body, and the kit would inherit its face; a rule on the root itself wins over what the root inherits. */
|
|
25
|
+
:where(.ws-app-shell, .ws-page, .ws-entry-shell, .ws-status-screen, dialog.ws-dialog, .ws-menu, .ws-popover) { font-family: var(--font-body); font-size: var(--ws-text-body); line-height: calc(var(--space-md) + var(--space-xxs)); color: var(--color-text-body); }
|
|
26
|
+
:where([class^="ws-"], [class*=" ws-"], [class^="ws-"] *, [class*=" ws-"] *), :where([class^="ws-"], [class*=" ws-"], [class^="ws-"] *, [class*=" ws-"] *)::before, :where([class^="ws-"], [class*=" ws-"], [class^="ws-"] *, [class*=" ws-"] *)::after { box-sizing: border-box; }
|
|
27
|
+
:where(h1, h2, h3, h4, p, ul, ol, figure):where([class^="ws-"], [class*=" ws-"], [class^="ws-"] *, [class*=" ws-"] *) { margin: 0; }
|
|
28
|
+
:where(ul, ol):where([class^="ws-"], [class*=" ws-"], [class^="ws-"] *, [class*=" ws-"] *) { padding: 0; list-style: none; }
|
|
29
|
+
/* K14: text-align inherits too, so a button.ws-act starts on its column's edge instead of centring its words. */
|
|
30
|
+
:where(button, input, select, textarea):where([class^="ws-"], [class*=" ws-"], [class^="ws-"] *, [class*=" ws-"] *) { font: inherit; color: inherit; text-align: inherit; }
|
|
31
|
+
:where(svg):where([class^="ws-"], [class*=" ws-"], [class^="ws-"] *, [class*=" ws-"] *) { display: block; }
|
|
32
|
+
.ws-tnum { font-variant-numeric: tabular-nums; }
|
|
33
|
+
/* K2: clipped to nothing and taken out of the flow without stretching a scroller (every kit scroller is positioned). */
|
|
34
|
+
.ws-sr { position: absolute; width: var(--ws-line); height: var(--ws-line); margin: calc(var(--ws-line) * -1); padding: 0; border: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
|
|
35
|
+
|
|
36
|
+
/* K15: an icon never takes the browser's 300 px default. .ws-icon is an inline icon in running text (16, sm 12, lg 20);
|
|
37
|
+
an svg with no width of its own inside a kit control gets the control icon size, inside words the small one. Both
|
|
38
|
+
cost nothing, so a component's own size wins. */
|
|
39
|
+
.ws-icon { display: inline-block; flex-shrink: 0; width: var(--ws-icon); height: var(--ws-icon); vertical-align: -0.125em; }
|
|
40
|
+
.ws-icon--sm { width: var(--ws-icon-sm); height: var(--ws-icon-sm); }
|
|
41
|
+
.ws-icon--lg { width: var(--ws-icon-lg); height: var(--ws-icon-lg); }
|
|
42
|
+
:where(.ws-btn, .ws-icon-btn, .ws-chip, .ws-change, .ws-menu-item, .ws-segmented__item, .ws-tabs__tab, .ws-row, .ws-well-row, .ws-link, .ws-act, .ws-field-msg) > svg:where(:not([width])) { flex-shrink: 0; width: var(--ws-icon); height: var(--ws-icon); }
|
|
43
|
+
:where(.ws-meta, .ws-muted, .ws-body, .ws-eyebrow, .ws-cluster, .ws-kanban-board__meta) > svg:where(:not([width])) { display: inline-block; flex-shrink: 0; width: var(--ws-icon-sm); height: var(--ws-icon-sm); vertical-align: -0.125em; }
|
|
44
|
+
|
|
45
|
+
/* Focus (D8): Seth's 2 px navy outline, 2 px out, on every kit element that takes keyboard focus. Inside a dense row
|
|
46
|
+
(a menu, a well, a list) the same ring is drawn inside the row. Never outline: none without a visible replacement. */
|
|
47
|
+
:where([class^="ws-"], [class*=" ws-"], [class^="ws-"] *, [class*=" ws-"] *):focus-visible { outline: var(--ws-focus-width) solid var(--ws-focus-color); outline-offset: var(--ws-focus-offset); }
|
|
48
|
+
:where(.ws-menu-item, .ws-well-row, .ws-row, .ws-segmented__item):focus-visible { outline-offset: calc(var(--ws-focus-width) * -1); }
|
|
49
|
+
|
|
50
|
+
/* Reduced motion (D7): everything is still. State changes are instant, nothing travels, loops stop on a still frame
|
|
51
|
+
(a shimmer becomes its ghost). Components still write their motion inside (prefers-reduced-motion: no-preference);
|
|
52
|
+
this is the net under all of them. ws-theme-switching (set by the theme switch for two frames) is the same for a
|
|
53
|
+
theme change, so every surface turns at once. */
|
|
54
|
+
@media (prefers-reduced-motion: reduce) {
|
|
55
|
+
:where([class^="ws-"], [class*=" ws-"], [class^="ws-"] *, [class*=" ws-"] *), :where([class^="ws-"], [class*=" ws-"], [class^="ws-"] *, [class*=" ws-"] *)::before, :where([class^="ws-"], [class*=" ws-"], [class^="ws-"] *, [class*=" ws-"] *)::after { animation-duration: 0.01ms !important; animation-delay: 0s !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; transition-delay: 0s !important; scroll-behavior: auto !important; }
|
|
56
|
+
}
|
|
57
|
+
:root.ws-theme-switching :where([class^="ws-"], [class*=" ws-"], [class^="ws-"] *, [class*=" ws-"] *) { transition: none !important; }
|
|
58
|
+
/* ==== The base layer ends here ==== */
|
|
59
|
+
|
|
60
|
+
/* The preview's own stage: the grey around the surface, so a card shows its edge. Previews only. Its children are capped
|
|
61
|
+
to it, the way a page column holds them, so a preview shows how a component behaves in a 358 px column. */
|
|
62
|
+
.ws-stage { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--ws-gap-component); padding: var(--ws-gap-component); background: var(--color-bg-page); }
|
|
63
|
+
.ws-stage > * { max-width: 100%; min-width: 0; }
|
|
64
|
+
.ws-stage--grey { background: var(--ws-page); }
|
|
65
|
+
.ws-stage--sunk { background: var(--ws-surface-sunk); }
|
|
66
|
+
.ws-stage--column { flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: var(--ws-gap-group); }
|
|
67
|
+
.ws-stage--bleed { padding: 0; }
|
|
68
|
+
|
|
69
|
+
/* ---- Layout: the page, an area, the board, a stack and a cluster ---- */
|
|
70
|
+
/* A page: its content as wide as two board columns (2 x 556 and the gap: no page width token exists, so it is derived
|
|
71
|
+
from the board's), centred, with the canvas's 24 gutter, 16 on a phone; its children one gap apart. It is a size
|
|
72
|
+
container, so tiles and small cards inside it size from the page, not the window. --column: the one 656 column. */
|
|
73
|
+
.ws-page { container-type: inline-size; display: flex; flex-direction: column; gap: var(--ws-gap-component); width: 100%; max-width: calc(var(--ws-chart-card-w) * 2 + var(--ws-gap-component) + var(--ws-gutter) * 2); margin-inline: auto; padding: var(--ws-gutter); }
|
|
74
|
+
.ws-page--column { max-width: calc(var(--ws-column-width) + var(--ws-gutter) * 2); }
|
|
75
|
+
@media (max-width: 40rem) { .ws-page { padding: var(--space-md); } }
|
|
76
|
+
/* An area: any other region tiles or small cards should size from (a card, a pane). The page is one already. */
|
|
77
|
+
.ws-area { container-type: inline-size; }
|
|
78
|
+
/* The board (CardBoard): two columns side by side once both fit at 480 (976 and up), each up to 556 (the board is at most
|
|
79
|
+
two columns and the gap wide, on the content's start edge, K12); below that one column filling the width, in DOM order. Its children are cards
|
|
80
|
+
or columns of cards (__column), each its own height. No breakpoint: it wraps by width, so it works in any region.
|
|
81
|
+
--4 (small cards, one, two or four across, measured on the board itself) is the Page block's. */
|
|
82
|
+
.ws-board { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--ws-chart-card-min)), 1fr)); align-items: start; gap: var(--ws-gap-component); width: 100%; max-width: calc(var(--ws-chart-card-w) * 2 + var(--ws-gap-component)); }
|
|
83
|
+
.ws-board > * { min-width: 0; }
|
|
84
|
+
.ws-board__column { display: flex; flex-direction: column; gap: var(--ws-gap-component); }
|
|
85
|
+
/* A stack (top to bottom) and a cluster (side by side, wrapping), 8 apart; the modifiers take the other named gaps:
|
|
86
|
+
block 32 (Seth's report blocks; a 28 in his Fixes frame snaps to it, D4), section 56 (between page sections). The base
|
|
87
|
+
gap is the step itself, not --ws-gap, so a parent that sets --ws-gap for its own layout never leaks into a stack. */
|
|
88
|
+
.ws-stack { display: flex; flex-direction: column; gap: var(--space-xs); }
|
|
89
|
+
.ws-cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-xs); }
|
|
90
|
+
.ws-cluster--start { align-items: flex-start; }
|
|
91
|
+
.ws-stack--tight, .ws-cluster--tight { gap: var(--ws-gap-tight); }
|
|
92
|
+
.ws-stack--loose, .ws-cluster--loose { gap: var(--ws-gap-loose); }
|
|
93
|
+
.ws-stack--component, .ws-cluster--component { gap: var(--ws-gap-component); }
|
|
94
|
+
.ws-stack--group, .ws-cluster--group { gap: var(--ws-gap-group); }
|
|
95
|
+
.ws-stack--block { gap: var(--ws-gap-block); }
|
|
96
|
+
.ws-stack--section { gap: var(--ws-gap-section); }
|
|
97
|
+
/* K1: a column that can be height-bound (a scroll region, a dialog, a stack made to scroll) never squashes its children
|
|
98
|
+
to fit: they keep their height and the column scrolls. A child that should scroll inside says so
|
|
99
|
+
(flex: 1; min-height: 0; overflow: auto). No specificity, so that wins. */
|
|
100
|
+
:where(.ws-app-shell__body, .ws-app-shell__nav, .ws-dialog, .ws-dialog__content, .ws-panel__body, .ws-stack, .ws-card--compound, .ws-page, .ws-board__column) > * { flex-shrink: 0; }
|
|
101
|
+
/* K2: every kit scroller is positioned, so what sits absolutely inside it (screen-reader words, a sticky cell's shade)
|
|
102
|
+
is held by it and never stretches the window. */
|
|
103
|
+
:where(.ws-app-shell__body, .ws-dialog__content, .ws-panel__body, .ws-table__scroll, .ws-kanban-board, .ws-tabs) { position: relative; }
|
|
104
|
+
|
|
105
|
+
/* ---- Surfaces ---- */
|
|
106
|
+
/* A card: the cream, 8 px corners. Its edge (Seth's tray rim, D5), the selected look and the padding steps are the Card
|
|
107
|
+
block's. Inside a card the band shares the head's 20 px rail (Seth's foot words sit on the surface's edge); a drawer
|
|
108
|
+
keeps the band's 28. */
|
|
109
|
+
.ws-card { --ws-band-inset: var(--ws-card-inset); border-radius: var(--ws-radius-card); background: var(--color-bg-page); }
|
|
110
|
+
/* A card with nothing but its content: the 20 px inset all round (a chart drawn bare, without its head or band). */
|
|
111
|
+
.ws-card--inset { padding: var(--ws-card-inset); }
|
|
112
|
+
/* A plate inside a card: the cream a shade darker, 8 px corners (its 14 / 16 inside is the Plate block's). */
|
|
113
|
+
.ws-plate { border-radius: var(--ws-radius-card); background: var(--ws-surface-sunk); }
|
|
114
|
+
/* The well, from the first product built on the system: a grey plate of 48 px cream rows with 6 px corners, white under
|
|
115
|
+
the pointer (its insets are the Well block's). */
|
|
116
|
+
.ws-well { border-radius: var(--ws-radius-card); background: var(--ws-well); display: flex; flex-direction: column; }
|
|
117
|
+
.ws-well-row { display: flex; align-items: center; min-height: var(--ws-row-h); border-radius: var(--ws-radius-row); background: var(--color-bg-page); color: var(--color-text-heading); font-weight: 500; text-align: left; width: 100%; border: 0; cursor: pointer; transition: background-color var(--ws-duration-hover) var(--ws-ease-soft); }
|
|
118
|
+
@media (hover: hover) { .ws-well-row:hover { background: var(--color-surface); } }
|
|
119
|
+
.ws-well-row:active { background: var(--ws-surface-press); }
|
|
120
|
+
/* Something sunk inside a raised surface (an active option, a range band, a disabled field in a menu, a picker, a dialog,
|
|
121
|
+
a panel) takes the raised surface's own sunk step: the house sunk exactly in light, still seen in dark, where the
|
|
122
|
+
page's sunk is 1/255 off raised. */
|
|
123
|
+
:where(.ws-menu, .ws-popover, .ws-dialog, .ws-panel) { --ws-surface-sunk: var(--ws-raised-sunk); }
|
|
124
|
+
/* The dotted field a drawing sits on. */
|
|
125
|
+
.ws-dots { background-image: radial-gradient(circle, var(--ws-chart-dot) calc(var(--ws-hairline) * 1.5), transparent calc(var(--ws-hairline) * 2.2)); background-size: var(--ws-chart-dot-gap) var(--ws-chart-dot-gap); }
|
|
126
|
+
/* The foot band (D5): the card's foot on its tray rim, flat (no shade), the head's rail at the sides, at least 80 tall. */
|
|
127
|
+
.ws-band { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-sm) var(--space-md); min-height: var(--ws-band-h); padding: var(--space-md) var(--ws-band-inset); background: var(--ws-tray); }
|
|
128
|
+
.ws-band__words { display: flex; flex: 1; min-width: min(100%, var(--space-9xl)); flex-direction: column; gap: var(--space-xxs); }
|
|
129
|
+
.ws-band__title { font-size: var(--ws-text-value); line-height: calc(var(--space-md) + var(--space-xxs)); font-weight: 500; color: var(--color-text-heading); text-wrap: balance; }
|
|
130
|
+
.ws-band__how { font-size: var(--ws-text-meta); line-height: var(--space-md); color: var(--color-text-muted); }
|
|
131
|
+
/* A card's head: 20 px inside, the 22 px title and one 14 px line. Its first div is the words column; a div after it
|
|
132
|
+
(an aside, a cluster) lays itself out. */
|
|
133
|
+
.ws-head { display: flex; align-items: flex-start; gap: var(--space-md); padding: var(--ws-card-inset); }
|
|
134
|
+
.ws-head > div:first-of-type { flex: 1; min-width: 0; display: flex; flex-direction: column; }
|
|
135
|
+
/* A menu: a card lifted off the page. */
|
|
136
|
+
.ws-menu { display: flex; flex-direction: column; border-radius: var(--ws-radius-card); background: var(--ws-raised); padding: var(--space-xxs); box-shadow: var(--ws-shadow-lift); z-index: var(--z-dropdown); min-width: var(--space-9xl); }
|
|
137
|
+
.ws-menu-item { display: flex; width: 100%; min-height: var(--ws-control-h); padding: var(--space-xxs) var(--space-sm); align-items: center; gap: var(--space-xs); border-radius: var(--ws-radius-control); text-align: left; font-size: var(--ws-text-body); font-weight: 500; color: var(--color-text-heading); background: none; border: 0; cursor: pointer; }
|
|
138
|
+
@media (hover: hover) { .ws-menu-item:hover { background: var(--ws-hover); } }
|
|
139
|
+
.ws-menu-item:active { background: var(--ws-surface-press); }
|
|
140
|
+
.ws-menu-line { height: var(--ws-line); margin: var(--space-xxs) 0; background: var(--ws-menu-line); }
|
|
141
|
+
.ws-disc { display: inline-flex; flex-shrink: 0; align-items: center; justify-content: center; border-radius: var(--radius-full); background: var(--ws-surface-sunk); color: var(--color-text-heading); }
|
|
142
|
+
|
|
143
|
+
/* ---- Words ---- */
|
|
144
|
+
/* Titles: Seth draws no tracking on the 22 / 28 titles or the 15 / 22 sections (D1); a long one balances its lines, so
|
|
145
|
+
no word is left alone on the last. */
|
|
146
|
+
.ws-title { font-size: var(--ws-text-title); line-height: var(--ws-leading-title); font-weight: 600; color: var(--color-text-heading); text-wrap: balance; }
|
|
147
|
+
.ws-section { font-size: var(--ws-text-section); line-height: var(--ws-leading-section); font-weight: 600; color: var(--color-text-heading); text-wrap: balance; }
|
|
148
|
+
.ws-body { font-size: var(--ws-text-body); line-height: calc(var(--space-md) + var(--space-xxs)); color: var(--color-text-body); }
|
|
149
|
+
.ws-muted { font-size: var(--ws-text-dense); line-height: var(--space-md); color: var(--color-text-muted); }
|
|
150
|
+
.ws-meta { font-size: var(--ws-text-meta); line-height: var(--space-md); color: var(--color-text-muted); }
|
|
151
|
+
.ws-eyebrow { font-size: var(--ws-text-dense); line-height: var(--space-md); font-weight: 600; text-transform: uppercase; letter-spacing: var(--letter-spacing-overline); color: var(--color-text-muted); }
|
|
152
|
+
.ws-link { color: var(--color-text-interactive); text-decoration: none; font-weight: 500; }
|
|
153
|
+
.ws-act { font-weight: 500; color: var(--color-text-heading); text-decoration: none; background: none; border: 0; padding: 0; cursor: pointer; }
|
|
154
|
+
/* Hover only where a pointer hovers: on touch a tap would leave it stuck on. */
|
|
155
|
+
@media (hover: hover) { .ws-link:hover, .ws-act:hover { text-decoration: underline; } }
|
|
156
|
+
.ws-display { font-size: var(--ws-text-display); line-height: var(--space-5xl); font-weight: 400; letter-spacing: var(--ws-tracking-display); color: var(--color-text-heading); font-variant-numeric: tabular-nums; }
|
|
157
|
+
.ws-figure { font-size: var(--font-size-3xl); line-height: var(--font-size-3xl); font-weight: 400; letter-spacing: var(--ws-tracking-display); color: var(--color-text-heading); font-variant-numeric: tabular-nums; }
|
|
158
|
+
/* Seth's figure steps (D6): a row's figure 28 / 32, a tile's 32 / 38, a pane's 44 / 48 (untracked, as Seth draws it),
|
|
159
|
+
the report's hero 96 / 96. */
|
|
160
|
+
.ws-figure--row { font-size: var(--ws-text-figure-row); line-height: var(--ws-leading-figure-row); }
|
|
161
|
+
.ws-figure--tile { font-size: var(--ws-text-figure); line-height: var(--ws-leading-figure); }
|
|
162
|
+
.ws-figure--pane { font-size: var(--ws-text-figure-lg); line-height: var(--ws-leading-figure-lg); letter-spacing: normal; }
|
|
163
|
+
.ws-figure--score { font-size: var(--ws-text-score); line-height: var(--ws-leading-score); font-variant-numeric: proportional-nums; } /* a lone hero figure, never a column: proportional digits as Seth draws them */
|
|
164
|
+
/* A row's name (15 / 20 medium) and control words (13 / 18 medium), Seth's (D6). */
|
|
165
|
+
.ws-row-name { font-size: var(--ws-text-section); line-height: var(--ws-leading-row); font-weight: 500; color: var(--color-text-heading); }
|
|
166
|
+
.ws-control-words { font-size: var(--ws-text-control); line-height: var(--ws-leading-control); font-weight: 500; }
|
|
167
|
+
.ws-positive { color: var(--ws-word-positive); }
|
|
168
|
+
.ws-needs { color: var(--ws-word-needs); }
|
|
169
|
+
|
|
170
|
+
/* ---- Buttons, icon buttons, fields, chips, keys and the segmented switch are their components' blocks (Button,
|
|
171
|
+
IconButton, Input, Select, TextArea, Chip, Kbd, Segmented), each restating the whole control, so their hovers sit
|
|
172
|
+
inside (hover: hover) and nothing sticks after a tap. What they share stays here. ---- */
|
|
173
|
+
/* The working dot before a pressed button's words: the one beat. */
|
|
174
|
+
.ws-dot { width: calc(var(--space-xxs) * 1.5); height: calc(var(--space-xxs) * 1.5); border-radius: var(--radius-full); background: currentColor; }
|
|
175
|
+
|
|
176
|
+
/* ---- Fields: the label, the field's column and its message. ---- */
|
|
177
|
+
.ws-field { display: flex; flex-direction: column; gap: var(--space-xxs); }
|
|
178
|
+
.ws-label { font-size: var(--ws-text-dense); line-height: var(--space-md); font-weight: 500; color: var(--color-text-body); }
|
|
179
|
+
/* ponytail: Input/style.css has no placeholder rule of its own yet; this one line stays until it does. */
|
|
180
|
+
.ws-input::placeholder { color: var(--color-text-placeholder); }
|
|
181
|
+
.ws-field-msg { font-size: var(--ws-text-dense); line-height: var(--space-md); color: var(--color-text-muted); }
|
|
182
|
+
.ws-field-msg--error { display: flex; align-items: flex-start; gap: var(--space-xxs); color: var(--ws-word-needs); }
|
|
183
|
+
.ws-field-msg--error svg { width: var(--ws-icon-sm); height: var(--ws-icon-sm); flex-shrink: 0; margin-top: calc(var(--space-xxs) / 2); }
|
|
184
|
+
|
|
185
|
+
/* A change beside its number (from the first product built on the system): arrow and words, never colour alone; up
|
|
186
|
+
teal, down mid blue, the same grey. Seth's tag beside Chip (D1): 24 tall, 4 px corners, 13 / 18 medium. */
|
|
187
|
+
.ws-change { display: inline-flex; align-items: center; gap: var(--space-xxs); height: var(--space-lg); padding: 0 var(--space-xs); border-radius: var(--ws-radius-control); background: var(--color-bg-page); font-size: var(--ws-text-control); line-height: var(--ws-leading-control); font-weight: 500; white-space: nowrap; color: var(--color-text-muted); box-shadow: inset 0 0 0 var(--ws-hairline) var(--ws-edge-chip); }
|
|
188
|
+
.ws-change--up { color: var(--ws-word-positive); }
|
|
189
|
+
.ws-change--down { color: var(--color-text-interactive); }
|
|
190
|
+
.ws-change svg { width: var(--ws-icon-sm); height: var(--ws-icon-sm); }
|
|
191
|
+
|
|
192
|
+
/* ---- Rows and lists ---- */
|
|
193
|
+
.ws-row { display: flex; align-items: center; gap: var(--space-xs); min-height: var(--ws-row-h-dense); padding: 0 var(--space-sm); border-radius: var(--ws-radius-row); color: var(--color-text-heading); transition: background-color var(--ws-duration-hover) var(--ws-ease-soft); }
|
|
194
|
+
@media (hover: hover) { .ws-row:hover { background: var(--ws-surface-sunk); } }
|
|
195
|
+
.ws-row:active { background: var(--ws-surface-press); }
|
|
196
|
+
.ws-row__title { font-size: var(--ws-text-body); line-height: calc(var(--space-md) + var(--space-xxs)); font-weight: 500; color: var(--color-text-heading); }
|
|
197
|
+
.ws-rule { height: var(--ws-line); background: var(--ws-chart-cell-edge, var(--ws-edge-slot)); }
|
|
198
|
+
/* An avatar: a disc of navy initials on the sunk cream, the hairline ring by default (it mostly sits on a cream card);
|
|
199
|
+
--plain drops the ring. Sizes as the first product writes them: sm 28 (12 px initials), the default 32 (14), deck 48
|
|
200
|
+
(14), panel 56 (16), xl 64 (24). */
|
|
201
|
+
.ws-avatar { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: var(--ws-avatar); height: var(--ws-avatar); overflow: hidden; border-radius: var(--radius-full); background: var(--ws-surface-sunk); color: var(--color-text-heading); font-size: var(--ws-text-body); font-weight: 600; box-shadow: var(--ws-shadow-hairline); }
|
|
202
|
+
.ws-avatar--plain { box-shadow: none; }
|
|
203
|
+
.ws-avatar--dim { opacity: 0.6; }
|
|
204
|
+
.ws-avatar--sm { width: var(--ws-control-h-sm); height: var(--ws-control-h-sm); font-size: var(--ws-text-dense); }
|
|
205
|
+
.ws-avatar--deck { width: var(--space-3xl); height: var(--space-3xl); font-size: var(--ws-text-body); }
|
|
206
|
+
.ws-avatar--panel { width: calc(var(--space-3xl) + var(--space-xs)); height: calc(var(--space-3xl) + var(--space-xs)); font-size: var(--ws-text-value); }
|
|
207
|
+
.ws-avatar--xl { width: var(--space-4xl); height: var(--space-4xl); font-size: var(--font-size-xl); }
|
|
208
|
+
/* A stack of faces overlapping by 4 on cream rings, the rest as "+N" in the same disc. */
|
|
209
|
+
.ws-avatar-stack { display: flex; align-items: center; }
|
|
210
|
+
.ws-avatar-stack > * + * { margin-left: calc(var(--space-xxs) * -1); }
|
|
211
|
+
.ws-avatar-stack > .ws-avatar { box-shadow: 0 0 0 var(--ws-ring) var(--color-bg-page); }
|
|
212
|
+
.ws-avatar-stack__more { color: var(--color-text-body); }
|
|
213
|
+
|
|
214
|
+
/* ---- Motion: soft by default, named by role (D7, Seth's North); everything is still with reduced motion. ---- */
|
|
215
|
+
@keyframes ws-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
|
|
216
|
+
@keyframes ws-rise { from { opacity: 0; transform: translateY(var(--ws-rise)); } to { opacity: 1; transform: none; } }
|
|
217
|
+
@keyframes ws-grow { from { transform: scaleX(0); } to { transform: none; } }
|
|
218
|
+
@keyframes ws-grow-up { from { transform: scaleY(0); } to { transform: none; } }
|
|
219
|
+
@keyframes ws-wipe { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0); } }
|
|
220
|
+
@keyframes ws-bloom { from { opacity: 0; transform: scale(0.6); } to { opacity: 1; transform: none; } }
|
|
221
|
+
@keyframes ws-pop { from { transform: scale(0.85); } to { transform: none; } }
|
|
222
|
+
@keyframes ws-draw { from { stroke-dasharray: 0 1; } }
|
|
223
|
+
/* North's two: a detail settling in (it rises 6 px out of a 3 px blur), and the loading sweep over the ghost. */
|
|
224
|
+
@keyframes ws-settle { from { opacity: 0; transform: translateY(var(--ws-rise)); filter: blur(var(--ws-blur-arrive)); } to { opacity: 1; transform: none; filter: none; } }
|
|
225
|
+
@keyframes ws-shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }
|
|
226
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
227
|
+
.ws-working { animation: ws-pulse var(--ws-loop) var(--ws-ease-loop) infinite; }
|
|
228
|
+
.ws-working-slow { animation: ws-pulse var(--ws-loop-slow) var(--ws-ease-loop) infinite; }
|
|
229
|
+
.ws-arrive { animation: ws-rise var(--ws-duration-gentle) var(--ws-ease-soft) backwards; }
|
|
230
|
+
.ws-rise { animation: ws-rise var(--ws-duration-settle) var(--ws-ease-soft) backwards; }
|
|
231
|
+
.ws-grow { animation: ws-grow var(--ws-duration-calm) var(--ws-ease-soft) backwards; transform-origin: left; }
|
|
232
|
+
.ws-grow-up { animation: ws-grow-up var(--ws-duration-calm) var(--ws-ease-soft) backwards; transform-origin: bottom; }
|
|
233
|
+
.ws-wipe { animation: ws-wipe var(--ws-duration-calm) var(--ws-ease-soft) backwards; }
|
|
234
|
+
.ws-bloom { animation: ws-bloom var(--ws-duration-settle) var(--ws-ease-soft) backwards; }
|
|
235
|
+
.ws-pop { animation: ws-pop var(--ws-duration-settle) var(--ws-ease-soft) backwards; }
|
|
236
|
+
/* Settle-in: details arrive after their frame, top to bottom; set --ws-i (0, 1, 2 ...) on each for the stagger. */
|
|
237
|
+
.ws-settle { animation: ws-settle var(--ws-duration-settle) var(--ws-ease-soft) backwards; animation-delay: calc(var(--ws-i, 0) * var(--ws-stagger-detail)); }
|
|
238
|
+
.ws-shimmer { animation: ws-shimmer var(--ws-loop-shimmer) var(--ws-ease-shimmer) infinite; }
|
|
239
|
+
}
|
|
240
|
+
/* Loading (North): a ghost block in the chart colours' sweep. Give it the size of what it stands for; its words, if
|
|
241
|
+
any, are transparent. Under reduced motion it is a still ghost. */
|
|
242
|
+
.ws-shimmer { border-radius: var(--ws-radius-bar); background: var(--ws-shimmer); background-size: 300% 100%; color: transparent; }
|
|
243
|
+
/* Hover tint (North): Seth's navy wash over whatever ground, a colour change, never a lift. --faint for a list row,
|
|
244
|
+
the default for a nav or menu row, --strong for an icon button or an act. */
|
|
245
|
+
.ws-hover-tint { transition: background-color var(--ws-duration-hover) var(--ws-ease-soft); }
|
|
246
|
+
@media (hover: hover) {
|
|
247
|
+
.ws-hover-tint:hover { background-color: var(--ws-hover); }
|
|
248
|
+
.ws-hover-tint--faint:hover { background-color: var(--ws-hover-faint); }
|
|
249
|
+
.ws-hover-tint--strong:hover { background-color: var(--ws-hover-strong); }
|
|
250
|
+
}
|
|
251
|
+
/* Springs (D7): Seth's North springs are tokens, --ws-spring-<name> (a linear() curve sampled from the motion library's
|
|
252
|
+
own solver, overshoot kept) over --ws-spring-<name>-duration; a transition names both. A browser without linear()
|
|
253
|
+
drops that transition and the change is instant. Reduced motion: the net above makes every one instant. */
|
|
254
|
+
/* Press (North "Button press (mic, add)": the press spring, .2 / .3): a button, an icon button, a suggestion chip, a chip
|
|
255
|
+
that acts and anything that wears .ws-press gives to .97 under a press and springs back on the same spring. The round
|
|
256
|
+
voice act (an --round icon button, the composer's round act, .ws-press--round) gives to .94, the send act
|
|
257
|
+
(.ws-press--send) to .92. It rides on `scale`, so a control's own transform is left alone; words that act (--link,
|
|
258
|
+
--text), a disabled control and a busy one do not move. Hover stays a tint, never a lift. The rule restates each
|
|
259
|
+
control's colour beats (the hover beat, at once under the press) beside the spring, and outranks the controls' own
|
|
260
|
+
transition lists by a class. */
|
|
261
|
+
:where(.ws-icon-btn--round, .ws-composer__trail > .ws-icon-btn--primary, .ws-press--round) { --ws-press: var(--ws-press-scale-round); }
|
|
262
|
+
.ws-press--send { --ws-press: var(--ws-press-scale-send); }
|
|
263
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
264
|
+
:is(.ws-btn, .ws-icon-btn, .ws-suggestion-chip, :is(button, a).ws-chip, .ws-press):not(.ws-btn--link, .ws-btn--text, :disabled, [aria-disabled="true"], [aria-busy="true"]) { transition: background-color var(--ws-duration-hover) var(--ws-ease-soft), color var(--ws-duration-hover) var(--ws-ease-soft), border-color var(--ws-duration-hover) var(--ws-ease-soft), box-shadow var(--ws-duration-hover) var(--ws-ease-soft), opacity var(--ws-duration-hover) var(--ws-ease-soft), scale var(--ws-spring-press-duration) var(--ws-spring-press); }
|
|
265
|
+
:is(.ws-btn, .ws-icon-btn, .ws-suggestion-chip, :is(button, a).ws-chip, .ws-press):not(.ws-btn--link, .ws-btn--text, :disabled, [aria-disabled="true"], [aria-busy="true"]):active { scale: var(--ws-press, var(--ws-press-scale)); transition-duration: var(--ws-duration-instant), var(--ws-duration-instant), var(--ws-duration-instant), var(--ws-duration-instant), var(--ws-duration-instant), var(--ws-spring-press-duration); }
|
|
266
|
+
/* the press is the house's now: a control's own press transform stands down (its still is-pressed picture keeps it) */
|
|
267
|
+
:is(.ws-btn, .ws-icon-btn):not(.ws-btn--link, .ws-btn--text):active { transform: none; }
|
|
268
|
+
}
|
|
269
|
+
/* Folds (North "Sidebar sections open / close": the fold spring, .32 / 0): what opens in place grows from nothing to
|
|
270
|
+
its height and fades in, and closes back the same way on the same spring; a chevron turns on it too. Every kit
|
|
271
|
+
<details> does it on its own (its ::details-content); a body shown and hidden by the hidden attribute wears .ws-unfold
|
|
272
|
+
(its block padding and margins grow with it, so it never jumps). Without ::details-content, @starting-style or
|
|
273
|
+
interpolate-size the body opens and closes at once. Reduced motion: at once. */
|
|
274
|
+
@media (prefers-reduced-motion: no-preference) { @supports (interpolate-size: allow-keywords) {
|
|
275
|
+
:where(details):where([class^="ws-"], [class*=" ws-"], [class^="ws-"] *, [class*=" ws-"] *) { interpolate-size: allow-keywords; }
|
|
276
|
+
:where(details):where([class^="ws-"], [class*=" ws-"], [class^="ws-"] *, [class*=" ws-"] *)::details-content { block-size: 0; opacity: 0; overflow: clip; overflow-clip-margin: calc(var(--ws-focus-width) + var(--ws-focus-offset)); transition: block-size var(--ws-spring-fold-duration) var(--ws-spring-fold), opacity var(--ws-spring-fold-duration) var(--ws-spring-fold), content-visibility var(--ws-spring-fold-duration) allow-discrete; }
|
|
277
|
+
:where(details[open]):where([class^="ws-"], [class*=" ws-"], [class^="ws-"] *, [class*=" ws-"] *)::details-content { block-size: auto; opacity: 1; }
|
|
278
|
+
.ws-unfold { interpolate-size: allow-keywords; overflow: clip; overflow-clip-margin: calc(var(--ws-focus-width) + var(--ws-focus-offset)); transition: height var(--ws-spring-fold-duration) var(--ws-spring-fold), padding-block var(--ws-spring-fold-duration) var(--ws-spring-fold), margin-block var(--ws-spring-fold-duration) var(--ws-spring-fold), opacity var(--ws-spring-fold-duration) var(--ws-spring-fold), display var(--ws-spring-fold-duration) allow-discrete; }
|
|
279
|
+
.ws-unfold[hidden] { display: none; height: 0; padding-block: 0; margin-block: 0; opacity: 0; }
|
|
280
|
+
@starting-style { .ws-unfold:not([hidden]) { height: 0; padding-block: 0; margin-block: 0; opacity: 0; } }
|
|
281
|
+
} }
|
|
282
|
+
/* The build-in (Amit, 5 Nov 2026: a kit default for a dashboard, from North's Home intro). .ws-build on a page or a
|
|
283
|
+
section; each card in it wears .ws-build__card with --ws-i (0, 1, 2 ... in reading order). A card rises in 70 ms
|
|
284
|
+
after the one before it (--ws-stagger-part) and the charts in it that carry their --draw draw after it lands, once,
|
|
285
|
+
when the card scrolls into view: --ws-build-at, the card's start, is what each chart adds to its own delays. Where
|
|
286
|
+
scroll-triggered animation is supported (timeline-trigger on a view() timeline, animation-trigger play-once) a card
|
|
287
|
+
below the fold waits and plays as it comes into view; elsewhere everything plays on first paint, so a card below
|
|
288
|
+
the fold has finished, its final state, by the time it is reached. Reduced motion: no build, the final state. */
|
|
289
|
+
.ws-build__card { --ws-build-at: calc(var(--ws-i, 0) * var(--ws-stagger-part)); }
|
|
290
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
291
|
+
.ws-build .ws-build__card { animation: ws-rise var(--ws-duration-settle) var(--ws-ease-settle) backwards; animation-delay: var(--ws-build-at); }
|
|
292
|
+
@supports (timeline-trigger: --a view() cover 10% cover 100%) and (animation-trigger: --a play-once) and (trigger-scope: --a) {
|
|
293
|
+
.ws-build .ws-build__card { trigger-scope: --ws-build; timeline-trigger: --ws-build view() cover 10% cover 100%; }
|
|
294
|
+
.ws-build .ws-build__card, .ws-build .ws-build__card * { animation-trigger: --ws-build play-once; }
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/* The scroll edge cue (Tabs, Segmented, a wide table, a board): a track wider than its box fades at the edge that hides
|
|
298
|
+
something, and only there, driven by its own scroll (nothing when it fits, nothing moves under reduced motion: the
|
|
299
|
+
timeline is the scroll, not time). .ws-scroll-edges on any horizontal scroller; a component can run ws-scroll-edges
|
|
300
|
+
on its own selector the same way. */
|
|
301
|
+
@property --ws-fade-start { syntax: "<length>"; inherits: false; initial-value: 0px; }
|
|
302
|
+
@property --ws-fade-end { syntax: "<length>"; inherits: false; initial-value: 0px; }
|
|
303
|
+
@keyframes ws-scroll-edges {
|
|
304
|
+
0% { --ws-fade-start: 0px; --ws-fade-end: var(--space-xl); }
|
|
305
|
+
8% { --ws-fade-start: var(--space-xl); }
|
|
306
|
+
92% { --ws-fade-end: var(--space-xl); }
|
|
307
|
+
100% { --ws-fade-start: var(--space-xl); --ws-fade-end: 0px; }
|
|
308
|
+
}
|
|
309
|
+
@supports (animation-timeline: scroll()) {
|
|
310
|
+
.ws-scroll-edges { mask-image: linear-gradient(90deg, transparent, currentColor var(--ws-fade-start), currentColor calc(100% - var(--ws-fade-end)), transparent); animation: ws-scroll-edges linear; animation-timeline: scroll(self inline); }
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/* ---- Touch (K10): one coarse-pointer block. A control that is a box is at least 40 px (an icon button that must look
|
|
314
|
+
small keeps its look and gets a 40 px hit area); words that act are at least 24 px tall. ---- */
|
|
315
|
+
@media (pointer: coarse) {
|
|
316
|
+
.ws-btn:not(.ws-btn--link, .ws-btn--text), .ws-input, .ws-select, .ws-segmented__item, .ws-tabs__tab, .ws-date-input__cell, .ws-fold__summary:not(.ws-fold__summary--quiet), .ws-app-shell__row, .ws-menu-item, .ws-toast__action, .ws-pagination__rows select, .ws-combobox__panel .ws-combobox__option { min-height: var(--ws-touch); }
|
|
317
|
+
.ws-input, .ws-select { height: var(--ws-touch); }
|
|
318
|
+
.ws-icon-btn { min-width: var(--ws-touch); min-height: var(--ws-touch); }
|
|
319
|
+
.ws-icon-btn--xs, .ws-icon-btn--sm { position: relative; min-width: 0; min-height: 0; }
|
|
320
|
+
.ws-icon-btn--xs::after, .ws-icon-btn--sm::after { content: ""; position: absolute; inset: calc((100% - var(--ws-touch)) / 2); }
|
|
321
|
+
.ws-btn--link, .ws-btn--text, .ws-act, .ws-table__sort, .ws-chat-card__door, .ws-fold__summary--quiet { min-height: var(--space-lg); }
|
|
322
|
+
/* inline words that act: 4 px above and below grows the hit area to 24 without moving a line */
|
|
323
|
+
.ws-breadcrumb a, .ws-breadcrumb__ellipsis, .ws-link { padding-block: var(--space-xxs); }
|
|
324
|
+
}
|