@echodial/deck 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/LICENSE +21 -0
- package/README.md +1327 -0
- package/bin/deck.mjs +219 -0
- package/build.mjs +338 -0
- package/dist/api-buckets.json +10486 -0
- package/dist/api.json +57896 -0
- package/dist/brand/deck-apple-touch-icon.png +0 -0
- package/dist/brand/deck-logo-dark.svg +1 -0
- package/dist/brand/deck-logo-light.svg +1 -0
- package/dist/brand/deck-logo-stacked.svg +1 -0
- package/dist/brand/deck-logo.svg +1 -0
- package/dist/brand/deck-mark.svg +7 -0
- package/dist/brand/deck-og.png +0 -0
- package/dist/collisions.json +223 -0
- package/dist/deck-adapters.js +482 -0
- package/dist/deck-adapters.min.js +23 -0
- package/dist/deck-extras.js +823 -0
- package/dist/deck-extras.min.js +5 -0
- package/dist/deck-icons.svg +184 -0
- package/dist/deck.bundle.js +2638 -0
- package/dist/deck.bundle.min.js +86 -0
- package/dist/deck.css +7904 -0
- package/dist/deck.esm.js +2644 -0
- package/dist/deck.js +1331 -0
- package/dist/deck.min.css +32 -0
- package/dist/deck.min.js +60 -0
- package/dist/layers/anchor.css +192 -0
- package/dist/layers/buttons.css +210 -0
- package/dist/layers/charts.css +337 -0
- package/dist/layers/combobox.css +248 -0
- package/dist/layers/components.css +868 -0
- package/dist/layers/container.css +199 -0
- package/dist/layers/datagrid.css +335 -0
- package/dist/layers/datepicker.css +305 -0
- package/dist/layers/forms.css +401 -0
- package/dist/layers/gradients.css +302 -0
- package/dist/layers/inputs.css +522 -0
- package/dist/layers/layers.css +87 -0
- package/dist/layers/layout.css +235 -0
- package/dist/layers/logical.css +226 -0
- package/dist/layers/media.css +400 -0
- package/dist/layers/mobile.css +245 -0
- package/dist/layers/motion.css +379 -0
- package/dist/layers/nav.css +771 -0
- package/dist/layers/perf.css +234 -0
- package/dist/layers/print.css +198 -0
- package/dist/layers/reset.css +103 -0
- package/dist/layers/space3d.css +280 -0
- package/dist/layers/toasts.css +201 -0
- package/dist/layers/tokens.css +229 -0
- package/dist/layers/type.css +114 -0
- package/dist/layers/utilities.css +241 -0
- package/dist/sizes.json +52 -0
- package/dist/usage.json +6340 -0
- package/package.json +94 -0
- package/src/00-layers.css +87 -0
- package/src/01-tokens.css +229 -0
- package/src/02-reset.css +103 -0
- package/src/03-type.css +114 -0
- package/src/04-layout.css +235 -0
- package/src/05-buttons.css +210 -0
- package/src/06-forms.css +401 -0
- package/src/07-components.css +868 -0
- package/src/08-mobile.css +245 -0
- package/src/09-utilities.css +241 -0
- package/src/10-datepicker.css +305 -0
- package/src/11-combobox.css +248 -0
- package/src/12-datagrid.css +335 -0
- package/src/13-toasts.css +201 -0
- package/src/14-charts.css +337 -0
- package/src/16-motion.css +379 -0
- package/src/18-container.css +199 -0
- package/src/19-logical.css +226 -0
- package/src/20-gradients.css +302 -0
- package/src/21-space3d.css +280 -0
- package/src/22-nav.css +771 -0
- package/src/23-inputs.css +522 -0
- package/src/24-media.css +400 -0
- package/src/25-anchor.css +192 -0
- package/src/26-perf.css +234 -0
- package/src/99-print.css +198 -0
- package/src/brand/deck-apple-touch-icon.png +0 -0
- package/src/brand/deck-logo-dark.svg +1 -0
- package/src/brand/deck-logo-light.svg +1 -0
- package/src/brand/deck-logo-stacked.svg +1 -0
- package/src/brand/deck-logo.svg +1 -0
- package/src/brand/deck-mark.svg +7 -0
- package/src/brand/deck-og.png +0 -0
- package/src/brand/sources.json +7 -0
- package/src/deck-icons.svg +184 -0
- package/src/js/deck-adapters.js +482 -0
- package/src/js/deck-extras.js +823 -0
- package/src/js/deck.js +1331 -0
package/package.json
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@echodial/deck",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A mobile-first CSS framework with no build step, no config file, and no dependencies. Retheme an entire app from one number.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"css",
|
|
7
|
+
"css-framework",
|
|
8
|
+
"mobile-first",
|
|
9
|
+
"no-build",
|
|
10
|
+
"design-tokens",
|
|
11
|
+
"oklch",
|
|
12
|
+
"cascade-layers",
|
|
13
|
+
"container-queries",
|
|
14
|
+
"logical-properties",
|
|
15
|
+
"view-transitions",
|
|
16
|
+
"rtl",
|
|
17
|
+
"php",
|
|
18
|
+
"keel"
|
|
19
|
+
],
|
|
20
|
+
"homepage": "https://get-keel.dev/deck",
|
|
21
|
+
"bugs": "https://github.com/srivera145/deck/issues",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/srivera145/deck.git"
|
|
25
|
+
},
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"author": "Santos Rivera",
|
|
28
|
+
"type": "module",
|
|
29
|
+
"sideEffects": [
|
|
30
|
+
"*.css",
|
|
31
|
+
"./dist/deck.js",
|
|
32
|
+
"./dist/deck-extras.js",
|
|
33
|
+
"./dist/deck-adapters.js",
|
|
34
|
+
"./dist/deck.bundle.js"
|
|
35
|
+
],
|
|
36
|
+
"main": "./dist/deck.bundle.js",
|
|
37
|
+
"module": "./dist/deck.esm.js",
|
|
38
|
+
"style": "./dist/deck.css",
|
|
39
|
+
"unpkg": "./dist/deck.min.css",
|
|
40
|
+
"jsdelivr": "./dist/deck.min.css",
|
|
41
|
+
"bin": {
|
|
42
|
+
"deck": "./bin/deck.mjs"
|
|
43
|
+
},
|
|
44
|
+
"exports": {
|
|
45
|
+
".": {
|
|
46
|
+
"import": "./dist/deck.esm.js",
|
|
47
|
+
"require": "./dist/deck.bundle.js",
|
|
48
|
+
"default": "./dist/deck.bundle.js"
|
|
49
|
+
},
|
|
50
|
+
"./css": "./dist/deck.css",
|
|
51
|
+
"./css/min": "./dist/deck.min.css",
|
|
52
|
+
"./icons": "./dist/deck-icons.svg",
|
|
53
|
+
"./js": "./dist/deck.js",
|
|
54
|
+
"./extras": "./dist/deck-extras.js",
|
|
55
|
+
"./adapters": "./dist/deck-adapters.js",
|
|
56
|
+
"./bundle": "./dist/deck.bundle.js",
|
|
57
|
+
"./layers/*": "./dist/layers/*",
|
|
58
|
+
"./src/*": "./src/*",
|
|
59
|
+
"./package.json": "./package.json"
|
|
60
|
+
},
|
|
61
|
+
"files": [
|
|
62
|
+
"dist",
|
|
63
|
+
"src",
|
|
64
|
+
"bin",
|
|
65
|
+
"build.mjs",
|
|
66
|
+
"README.md",
|
|
67
|
+
"LICENSE"
|
|
68
|
+
],
|
|
69
|
+
"scripts": {
|
|
70
|
+
"build": "node build.mjs",
|
|
71
|
+
"demo": "node build.mjs && node bin/deck.mjs init public_html/assets/deck --force && node -e \"import('node:fs/promises').then(async f=>{await Promise.all(['deck.min.css','deck.bundle.min.js'].map(n=>f.copyFile('dist/'+n,'public_html/assets/deck/'+n)));await f.mkdir('public_html/assets/images',{recursive:true});for(const n of await f.readdir('dist/brand'))await f.copyFile('dist/brand/'+n,'public_html/assets/images/'+n)})\"",
|
|
72
|
+
"start": "php -S localhost:4321 -t public_html",
|
|
73
|
+
"clean": "node -e \"import('node:fs/promises').then(f=>f.rm('dist',{recursive:true,force:true}))\"",
|
|
74
|
+
"prepublishOnly": "node build.mjs",
|
|
75
|
+
"brand": "node tools/make-brand.mjs",
|
|
76
|
+
"icons": "node tools/icons/build-icons.mjs"
|
|
77
|
+
},
|
|
78
|
+
"devDependencies": {
|
|
79
|
+
"esbuild": "^0.28.0",
|
|
80
|
+
"opentype.js": "^2.0.0"
|
|
81
|
+
},
|
|
82
|
+
"engines": {
|
|
83
|
+
"node": ">=18"
|
|
84
|
+
},
|
|
85
|
+
"browserslist": [
|
|
86
|
+
"chrome >= 117",
|
|
87
|
+
"edge >= 117",
|
|
88
|
+
"safari >= 17.4",
|
|
89
|
+
"firefox >= 128"
|
|
90
|
+
],
|
|
91
|
+
"publishConfig": {
|
|
92
|
+
"access": "public"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/* ==========================================================================
|
|
2
|
+
Deck — 00 Layers
|
|
3
|
+
The whole cascade contract in one place, declared before any rule exists.
|
|
4
|
+
Order is decided here, not by file order, not by specificity, and never by
|
|
5
|
+
!important.
|
|
6
|
+
|
|
7
|
+
Later layers win. Anything you write OUTSIDE a layer beats every layer, so
|
|
8
|
+
a plain rule in a page template always wins with no escalation.
|
|
9
|
+
|
|
10
|
+
deck.* the framework
|
|
11
|
+
app.* your slots, in the order you almost certainly want them
|
|
12
|
+
|
|
13
|
+
In a Keel view you can write:
|
|
14
|
+
|
|
15
|
+
@layer app.pages {
|
|
16
|
+
.page-header { padding-block: var(--space-8); }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
and it beats every deck rule without a single !important, while still being
|
|
20
|
+
overridable by app.overrides and by unlayered CSS.
|
|
21
|
+
========================================================================== */
|
|
22
|
+
|
|
23
|
+
@layer
|
|
24
|
+
deck.reset, /* normalize and element defaults */
|
|
25
|
+
deck.tokens, /* custom properties only */
|
|
26
|
+
deck.type, /* headings, prose, links */
|
|
27
|
+
deck.layout, /* containers, stack, grid, containers */
|
|
28
|
+
deck.components, /* buttons, forms, cards, grid, charts */
|
|
29
|
+
deck.mobile, /* sheets, tab bar, icons, emoji */
|
|
30
|
+
deck.motion, /* transitions, entrances, view trans. */
|
|
31
|
+
deck.effects, /* gradients, 3D, surface treatments */
|
|
32
|
+
deck.utilities, /* single-purpose classes */
|
|
33
|
+
deck.rtl, /* direction fixes, must beat utilities */
|
|
34
|
+
deck.print, /* paper */
|
|
35
|
+
|
|
36
|
+
app.base, /* your resets and element styles */
|
|
37
|
+
app.components, /* your components and deck overrides */
|
|
38
|
+
app.pages, /* per-page and per-view tweaks */
|
|
39
|
+
app.overrides; /* the escape hatch, still not !important */
|
|
40
|
+
|
|
41
|
+
/* --------------------------------------------------------------------------
|
|
42
|
+
Registered custom properties.
|
|
43
|
+
@property is not affected by layers. Registering a property gives it a type,
|
|
44
|
+
which is what lets the browser interpolate it — an angle or a color in a
|
|
45
|
+
custom property can now animate, which plain custom properties cannot do.
|
|
46
|
+
-------------------------------------------------------------------------- */
|
|
47
|
+
|
|
48
|
+
@property --g-angle {
|
|
49
|
+
syntax: "<angle>";
|
|
50
|
+
initial-value: 180deg;
|
|
51
|
+
inherits: false;
|
|
52
|
+
}
|
|
53
|
+
@property --g-from {
|
|
54
|
+
syntax: "<color>";
|
|
55
|
+
initial-value: transparent;
|
|
56
|
+
inherits: false;
|
|
57
|
+
}
|
|
58
|
+
@property --g-to {
|
|
59
|
+
syntax: "<color>";
|
|
60
|
+
initial-value: transparent;
|
|
61
|
+
inherits: false;
|
|
62
|
+
}
|
|
63
|
+
@property --g-stop {
|
|
64
|
+
syntax: "<percentage>";
|
|
65
|
+
initial-value: 50%;
|
|
66
|
+
inherits: false;
|
|
67
|
+
}
|
|
68
|
+
@property --sheen {
|
|
69
|
+
syntax: "<percentage>";
|
|
70
|
+
initial-value: -40%;
|
|
71
|
+
inherits: false;
|
|
72
|
+
}
|
|
73
|
+
@property --tilt-x {
|
|
74
|
+
syntax: "<angle>";
|
|
75
|
+
initial-value: 0deg;
|
|
76
|
+
inherits: false;
|
|
77
|
+
}
|
|
78
|
+
@property --tilt-y {
|
|
79
|
+
syntax: "<angle>";
|
|
80
|
+
initial-value: 0deg;
|
|
81
|
+
inherits: false;
|
|
82
|
+
}
|
|
83
|
+
@property --depth {
|
|
84
|
+
syntax: "<length>";
|
|
85
|
+
initial-value: 0px;
|
|
86
|
+
inherits: false;
|
|
87
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/* ==========================================================================
|
|
2
|
+
Deck — 01 Tokens
|
|
3
|
+
Everything is a custom property. Change a hue, retheme the whole app.
|
|
4
|
+
No build step. No purge. No config file.
|
|
5
|
+
========================================================================== */
|
|
6
|
+
|
|
7
|
+
/* Layer order is declared in 00-layers.css. */
|
|
8
|
+
|
|
9
|
+
@layer deck.tokens {
|
|
10
|
+
|
|
11
|
+
:root {
|
|
12
|
+
color-scheme: light dark;
|
|
13
|
+
|
|
14
|
+
/* --- Hue control -------------------------------------------------------
|
|
15
|
+
These six numbers are the whole palette. Set --hue-brand to 12 and the
|
|
16
|
+
framework becomes rust. Set it to 265 and it becomes violet. Buttons,
|
|
17
|
+
focus rings, links, charts, and shadows all follow.
|
|
18
|
+
---------------------------------------------------------------------- */
|
|
19
|
+
--hue-brand: 196; /* harbor teal */
|
|
20
|
+
--hue-accent: 42; /* signal amber */
|
|
21
|
+
--hue-good: 152; /* starboard */
|
|
22
|
+
--hue-warn: 74; /* caution */
|
|
23
|
+
--hue-bad: 24; /* port light */
|
|
24
|
+
--hue-neutral: 232; /* chart ink */
|
|
25
|
+
|
|
26
|
+
--chroma-brand: .118;
|
|
27
|
+
--chroma-accent: .142;
|
|
28
|
+
--chroma-status: .132;
|
|
29
|
+
--chroma-neutral: .012; /* neutrals carry a trace of the ink hue */
|
|
30
|
+
|
|
31
|
+
/* --- Brand ramp -------------------------------------------------------- */
|
|
32
|
+
--brand-50: oklch(97.4% calc(var(--chroma-brand) * .16) var(--hue-brand));
|
|
33
|
+
--brand-100: oklch(94.2% calc(var(--chroma-brand) * .30) var(--hue-brand));
|
|
34
|
+
--brand-200: oklch(88.6% calc(var(--chroma-brand) * .48) var(--hue-brand));
|
|
35
|
+
--brand-300: oklch(80.4% calc(var(--chroma-brand) * .70) var(--hue-brand));
|
|
36
|
+
--brand-400: oklch(70.2% calc(var(--chroma-brand) * .90) var(--hue-brand));
|
|
37
|
+
--brand-500: oklch(60.8% var(--chroma-brand) var(--hue-brand));
|
|
38
|
+
--brand-600: oklch(51.6% var(--chroma-brand) var(--hue-brand));
|
|
39
|
+
--brand-700: oklch(43.4% calc(var(--chroma-brand) * .92) var(--hue-brand));
|
|
40
|
+
--brand-800: oklch(35.6% calc(var(--chroma-brand) * .78) var(--hue-brand));
|
|
41
|
+
--brand-900: oklch(28.2% calc(var(--chroma-brand) * .62) var(--hue-brand));
|
|
42
|
+
--brand-950: oklch(20.4% calc(var(--chroma-brand) * .46) var(--hue-brand));
|
|
43
|
+
|
|
44
|
+
/* --- Neutral ramp ------------------------------------------------------ */
|
|
45
|
+
--ink-0: oklch(100% 0 0);
|
|
46
|
+
--ink-25: oklch(99.1% calc(var(--chroma-neutral) * .5) var(--hue-neutral));
|
|
47
|
+
--ink-50: oklch(97.8% var(--chroma-neutral) var(--hue-neutral));
|
|
48
|
+
--ink-100: oklch(95.4% calc(var(--chroma-neutral) * 1.4) var(--hue-neutral));
|
|
49
|
+
--ink-200: oklch(91.2% calc(var(--chroma-neutral) * 1.8) var(--hue-neutral));
|
|
50
|
+
--ink-300: oklch(84.6% calc(var(--chroma-neutral) * 2.2) var(--hue-neutral));
|
|
51
|
+
--ink-400: oklch(70.8% calc(var(--chroma-neutral) * 2.6) var(--hue-neutral));
|
|
52
|
+
--ink-500: oklch(58.4% calc(var(--chroma-neutral) * 2.8) var(--hue-neutral));
|
|
53
|
+
--ink-600: oklch(47.6% calc(var(--chroma-neutral) * 2.8) var(--hue-neutral));
|
|
54
|
+
--ink-700: oklch(38.2% calc(var(--chroma-neutral) * 2.6) var(--hue-neutral));
|
|
55
|
+
--ink-800: oklch(29.4% calc(var(--chroma-neutral) * 2.4) var(--hue-neutral));
|
|
56
|
+
--ink-900: oklch(22.6% calc(var(--chroma-neutral) * 2.2) var(--hue-neutral));
|
|
57
|
+
--ink-950: oklch(16.2% calc(var(--chroma-neutral) * 2.0) var(--hue-neutral));
|
|
58
|
+
--ink-1000: oklch(11.4% calc(var(--chroma-neutral) * 1.8) var(--hue-neutral));
|
|
59
|
+
|
|
60
|
+
/* --- Status ------------------------------------------------------------ */
|
|
61
|
+
--good-100: oklch(94% calc(var(--chroma-status) * .3) var(--hue-good));
|
|
62
|
+
--good-500: oklch(62% var(--chroma-status) var(--hue-good));
|
|
63
|
+
--good-600: oklch(52% var(--chroma-status) var(--hue-good));
|
|
64
|
+
--good-700: oklch(44% var(--chroma-status) var(--hue-good));
|
|
65
|
+
--warn-100: oklch(95% calc(var(--chroma-status) * .32) var(--hue-warn));
|
|
66
|
+
--warn-500: oklch(76% var(--chroma-status) var(--hue-warn));
|
|
67
|
+
--warn-700: oklch(50% var(--chroma-status) var(--hue-warn));
|
|
68
|
+
--bad-100: oklch(94.5% calc(var(--chroma-status) * .3) var(--hue-bad));
|
|
69
|
+
--bad-500: oklch(58% calc(var(--chroma-status) * 1.25) var(--hue-bad));
|
|
70
|
+
--bad-600: oklch(52% calc(var(--chroma-status) * 1.25) var(--hue-bad));
|
|
71
|
+
--bad-700: oklch(44% calc(var(--chroma-status) * 1.1) var(--hue-bad));
|
|
72
|
+
--accent-100: oklch(95% calc(var(--chroma-accent) * .3) var(--hue-accent));
|
|
73
|
+
--accent-500: oklch(74% var(--chroma-accent) var(--hue-accent));
|
|
74
|
+
--accent-700: oklch(52% calc(var(--chroma-accent) * .9) var(--hue-accent));
|
|
75
|
+
|
|
76
|
+
/* --- Semantic surfaces (auto light/dark) -------------------------------- */
|
|
77
|
+
--bg: light-dark(var(--ink-50), var(--ink-1000));
|
|
78
|
+
--bg-sunken: light-dark(var(--ink-100), oklch(8.6% .012 var(--hue-neutral)));
|
|
79
|
+
--surface: light-dark(var(--ink-0), var(--ink-950));
|
|
80
|
+
--surface-2: light-dark(var(--ink-25), var(--ink-900));
|
|
81
|
+
--surface-hover:light-dark(var(--ink-50), var(--ink-900));
|
|
82
|
+
--line: light-dark(var(--ink-200), oklch(28% .016 var(--hue-neutral)));
|
|
83
|
+
--line-strong: light-dark(var(--ink-300), oklch(36% .018 var(--hue-neutral)));
|
|
84
|
+
|
|
85
|
+
--text: light-dark(var(--ink-900), var(--ink-100));
|
|
86
|
+
--text-muted: light-dark(var(--ink-600), var(--ink-400));
|
|
87
|
+
--text-faint: light-dark(var(--ink-500), var(--ink-500));
|
|
88
|
+
/* --- Ink on a coloured surface ----------------------------------------
|
|
89
|
+
One per saturated surface. These are the static values: they are correct
|
|
90
|
+
for the shipped hues but they are guesses about any hue you set, which
|
|
91
|
+
is what the @supports block below fixes.
|
|
92
|
+
-------------------------------------------------------------------- */
|
|
93
|
+
--text-on-brand: oklch(99% .01 var(--hue-brand));
|
|
94
|
+
--text-on-accent: oklch(24% .06 var(--hue-accent));
|
|
95
|
+
--text-on-good: oklch(99% .01 var(--hue-good));
|
|
96
|
+
--text-on-warn: oklch(24% .06 var(--hue-warn));
|
|
97
|
+
--text-on-bad: oklch(99% .01 var(--hue-bad));
|
|
98
|
+
|
|
99
|
+
--brand: light-dark(var(--brand-600), var(--brand-400));
|
|
100
|
+
--brand-hover: light-dark(var(--brand-700), var(--brand-300));
|
|
101
|
+
--brand-soft: light-dark(var(--brand-50), oklch(26% .05 var(--hue-brand)));
|
|
102
|
+
--brand-soft-text: light-dark(var(--brand-800), var(--brand-200));
|
|
103
|
+
|
|
104
|
+
--focus: light-dark(var(--brand-500), var(--brand-300));
|
|
105
|
+
|
|
106
|
+
/* --- Space: 4px base, plus fluid steps for page rhythm ------------------ */
|
|
107
|
+
--space-0: 0;
|
|
108
|
+
--space-px: 1px;
|
|
109
|
+
--space-1: .25rem;
|
|
110
|
+
--space-2: .5rem;
|
|
111
|
+
--space-3: .75rem;
|
|
112
|
+
--space-4: 1rem;
|
|
113
|
+
--space-5: 1.25rem;
|
|
114
|
+
--space-6: 1.5rem;
|
|
115
|
+
--space-8: 2rem;
|
|
116
|
+
--space-10: 2.5rem;
|
|
117
|
+
--space-12: 3rem;
|
|
118
|
+
--space-16: 4rem;
|
|
119
|
+
--space-20: 5rem;
|
|
120
|
+
--space-24: 6rem;
|
|
121
|
+
--space-section: clamp(2.5rem, 1.4rem + 5.5vw, 6rem);
|
|
122
|
+
--space-gutter: clamp(1rem, .55rem + 2.2vw, 2rem);
|
|
123
|
+
|
|
124
|
+
/* --- Radius: intentionally not one value ------------------------------- */
|
|
125
|
+
--r-xs: 4px; /* chips, tags, kbd */
|
|
126
|
+
--r-sm: 7px; /* inputs, buttons */
|
|
127
|
+
--r-md: 12px; /* cards, menus */
|
|
128
|
+
--r-lg: 18px; /* sheets, modals, hero panels */
|
|
129
|
+
--r-full: 999px;
|
|
130
|
+
|
|
131
|
+
/* --- Elevation: tinted with the ink hue, never flat black -------------- */
|
|
132
|
+
--shadow-color: var(--hue-neutral);
|
|
133
|
+
--shadow-1: 0 1px 2px oklch(20% .03 var(--shadow-color) / .06),
|
|
134
|
+
0 1px 1px oklch(20% .03 var(--shadow-color) / .04);
|
|
135
|
+
--shadow-2: 0 2px 4px oklch(20% .03 var(--shadow-color) / .05),
|
|
136
|
+
0 4px 12px oklch(20% .03 var(--shadow-color) / .07);
|
|
137
|
+
--shadow-3: 0 4px 8px oklch(20% .03 var(--shadow-color) / .06),
|
|
138
|
+
0 12px 28px oklch(20% .03 var(--shadow-color) / .10);
|
|
139
|
+
--shadow-4: 0 8px 16px oklch(20% .03 var(--shadow-color) / .08),
|
|
140
|
+
0 24px 56px oklch(20% .03 var(--shadow-color) / .14);
|
|
141
|
+
--shadow-inset: inset 0 1px 0 oklch(100% 0 0 / .6);
|
|
142
|
+
|
|
143
|
+
/* A legible floor for text over a photo. Eased rather than a flat wash: a
|
|
144
|
+
50% black overlay dulls the whole image, while this only darkens where
|
|
145
|
+
the text actually sits. Shared by .g-scrim and .carousel-caption so the
|
|
146
|
+
two cannot drift apart. */
|
|
147
|
+
--scrim: linear-gradient(to top,
|
|
148
|
+
oklch(12% .02 var(--hue-neutral) / .82) 0%,
|
|
149
|
+
oklch(12% .02 var(--hue-neutral) / .62) 22%,
|
|
150
|
+
oklch(12% .02 var(--hue-neutral) / .28) 48%,
|
|
151
|
+
transparent 78%);
|
|
152
|
+
|
|
153
|
+
/* --- Type -------------------------------------------------------------- */
|
|
154
|
+
--font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI Variable Text",
|
|
155
|
+
"Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
156
|
+
--font-mono: ui-monospace, "SF Mono", "Cascadia Mono", "Roboto Mono",
|
|
157
|
+
Menlo, Consolas, monospace;
|
|
158
|
+
--font-display: var(--font-sans);
|
|
159
|
+
|
|
160
|
+
--text-2xs: .6875rem;
|
|
161
|
+
--text-xs: .75rem;
|
|
162
|
+
--text-sm: .8125rem;
|
|
163
|
+
--text-base: .9375rem;
|
|
164
|
+
--text-md: 1.0625rem;
|
|
165
|
+
--text-lg: clamp(1.125rem, 1.06rem + .32vw, 1.3125rem);
|
|
166
|
+
--text-xl: clamp(1.3125rem, 1.19rem + .62vw, 1.625rem);
|
|
167
|
+
--text-2xl: clamp(1.5625rem, 1.33rem + 1.16vw, 2.125rem);
|
|
168
|
+
--text-3xl: clamp(1.875rem, 1.44rem + 2.16vw, 2.875rem);
|
|
169
|
+
--text-4xl: clamp(2.25rem, 1.5rem + 3.75vw, 3.75rem);
|
|
170
|
+
|
|
171
|
+
--leading-tight: 1.12;
|
|
172
|
+
--leading-snug: 1.3;
|
|
173
|
+
--leading-normal: 1.55;
|
|
174
|
+
--leading-loose: 1.72;
|
|
175
|
+
--measure: 68ch;
|
|
176
|
+
|
|
177
|
+
/* --- Motion ------------------------------------------------------------ */
|
|
178
|
+
--ease-out: cubic-bezier(.22, 1, .36, 1);
|
|
179
|
+
--ease-in-out: cubic-bezier(.65, 0, .35, 1);
|
|
180
|
+
--ease-spring: linear(0, .18 6%, .53 14%, .89 24%, 1.04 32%, 1.06 40%, 1);
|
|
181
|
+
--dur-1: 110ms;
|
|
182
|
+
--dur-2: 190ms;
|
|
183
|
+
--dur-3: 300ms;
|
|
184
|
+
|
|
185
|
+
/* --- Controls ---------------------------------------------------------- */
|
|
186
|
+
--tap: 44px; /* minimum touch target, everywhere */
|
|
187
|
+
--control-h-sm: 34px;
|
|
188
|
+
--control-h: 42px;
|
|
189
|
+
--control-h-lg: 50px;
|
|
190
|
+
--ring: 0 0 0 3px light-dark(oklch(from var(--focus) l c h / .32),
|
|
191
|
+
oklch(from var(--focus) l c h / .42));
|
|
192
|
+
|
|
193
|
+
--z-sticky: 100;
|
|
194
|
+
--z-nav: 200;
|
|
195
|
+
--z-sheet: 300;
|
|
196
|
+
--z-modal: 400;
|
|
197
|
+
--z-toast: 500;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/* contrast-color() resolves against the colour as it actually computes, so
|
|
201
|
+
these follow --hue-brand and friends wherever they are dragged. It returns
|
|
202
|
+
only black or white and it aims at AA (4.5:1), which is why every surface
|
|
203
|
+
that carries text is kept out of the 55-65% lightness band -- see
|
|
204
|
+
--good-600 and --bad-600 above. Baseline Newly Available, so the static
|
|
205
|
+
values in :root stand in where it is missing. */
|
|
206
|
+
@supports (color: contrast-color(red)) {
|
|
207
|
+
:root {
|
|
208
|
+
--text-on-brand: contrast-color(var(--brand-600));
|
|
209
|
+
--text-on-accent: contrast-color(var(--accent-500));
|
|
210
|
+
--text-on-good: contrast-color(var(--good-600));
|
|
211
|
+
--text-on-warn: contrast-color(var(--warn-500));
|
|
212
|
+
--text-on-bad: contrast-color(var(--bad-600));
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/* Explicit theme override beats the OS setting */
|
|
217
|
+
[data-theme="light"] { color-scheme: light; }
|
|
218
|
+
[data-theme="dark"] { color-scheme: dark; }
|
|
219
|
+
|
|
220
|
+
/* Dark mode wants slightly less shadow and slightly more border */
|
|
221
|
+
@media (prefers-color-scheme: dark) {
|
|
222
|
+
:root {
|
|
223
|
+
--shadow-2: 0 2px 4px oklch(0% 0 0 / .3), 0 4px 12px oklch(0% 0 0 / .34);
|
|
224
|
+
--shadow-3: 0 4px 10px oklch(0% 0 0 / .34), 0 14px 30px oklch(0% 0 0 / .4);
|
|
225
|
+
--shadow-4: 0 10px 20px oklch(0% 0 0 / .4), 0 28px 60px oklch(0% 0 0 / .5);
|
|
226
|
+
--shadow-inset: inset 0 1px 0 oklch(100% 0 0 / .06);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
package/src/02-reset.css
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/* ==========================================================================
|
|
2
|
+
Deck — 02 Reset
|
|
3
|
+
========================================================================== */
|
|
4
|
+
|
|
5
|
+
@layer deck.reset {
|
|
6
|
+
|
|
7
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
8
|
+
|
|
9
|
+
* { margin: 0; }
|
|
10
|
+
|
|
11
|
+
html {
|
|
12
|
+
-webkit-text-size-adjust: 100%;
|
|
13
|
+
-moz-text-size-adjust: 100%;
|
|
14
|
+
text-size-adjust: 100%;
|
|
15
|
+
tab-size: 2;
|
|
16
|
+
scroll-behavior: smooth;
|
|
17
|
+
scroll-padding-block-start: calc(var(--control-h-lg) + var(--space-4));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
body {
|
|
21
|
+
min-block-size: 100dvh;
|
|
22
|
+
background: var(--bg);
|
|
23
|
+
color: var(--text);
|
|
24
|
+
font-family: var(--font-sans);
|
|
25
|
+
font-size: var(--text-base);
|
|
26
|
+
line-height: var(--leading-normal);
|
|
27
|
+
font-synthesis-weight: none;
|
|
28
|
+
-webkit-font-smoothing: antialiased;
|
|
29
|
+
text-rendering: optimizeLegibility;
|
|
30
|
+
overflow-wrap: break-word;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
img, svg, video, canvas, audio, iframe, embed, object {
|
|
34
|
+
display: block;
|
|
35
|
+
max-inline-size: 100%;
|
|
36
|
+
}
|
|
37
|
+
img, video { block-size: auto; }
|
|
38
|
+
|
|
39
|
+
input, button, textarea, select { font: inherit; color: inherit; }
|
|
40
|
+
|
|
41
|
+
button { background: none; border: 0; }
|
|
42
|
+
|
|
43
|
+
p, li, figcaption { text-wrap: pretty; }
|
|
44
|
+
h1, h2, h3, h4, h5, h6 { text-wrap: balance; }
|
|
45
|
+
|
|
46
|
+
ul[class], ol[class] { list-style: none; padding: 0; }
|
|
47
|
+
|
|
48
|
+
table { border-collapse: collapse; border-spacing: 0; }
|
|
49
|
+
|
|
50
|
+
hr {
|
|
51
|
+
border: 0;
|
|
52
|
+
block-size: 1px;
|
|
53
|
+
background: var(--line);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
:target { scroll-margin-block-start: var(--space-16); }
|
|
57
|
+
|
|
58
|
+
::selection {
|
|
59
|
+
background: var(--brand-200);
|
|
60
|
+
color: var(--ink-950);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* One focus treatment for the whole framework */
|
|
64
|
+
:focus-visible {
|
|
65
|
+
outline: 2px solid var(--focus);
|
|
66
|
+
outline-offset: 2px;
|
|
67
|
+
border-radius: var(--r-xs);
|
|
68
|
+
}
|
|
69
|
+
:focus:not(:focus-visible) { outline: none; }
|
|
70
|
+
|
|
71
|
+
/* Firefox needs help with the scrollbar; WebKit gets the thin version */
|
|
72
|
+
* { scrollbar-color: var(--ink-300) transparent; scrollbar-width: thin; }
|
|
73
|
+
::-webkit-scrollbar { inline-size: 10px; block-size: 10px; }
|
|
74
|
+
::-webkit-scrollbar-thumb {
|
|
75
|
+
background: var(--ink-300);
|
|
76
|
+
border-radius: var(--r-full);
|
|
77
|
+
border: 3px solid transparent;
|
|
78
|
+
background-clip: content-box;
|
|
79
|
+
}
|
|
80
|
+
::-webkit-scrollbar-thumb:hover { background: var(--ink-400); background-clip: content-box; }
|
|
81
|
+
|
|
82
|
+
@media (prefers-reduced-motion: reduce) {
|
|
83
|
+
html { scroll-behavior: auto; }
|
|
84
|
+
*, *::before, *::after {
|
|
85
|
+
animation-duration: .01ms !important;
|
|
86
|
+
animation-iteration-count: 1 !important;
|
|
87
|
+
transition-duration: .01ms !important;
|
|
88
|
+
scroll-behavior: auto !important;
|
|
89
|
+
}
|
|
90
|
+
/* Loading indicators keep moving, slowly. A frozen spinner reads as broken,
|
|
91
|
+
and progress feedback is information, not decoration. */
|
|
92
|
+
.spinner, .icon-spin, .skeleton, .marquee-track, .btn.is-loading::after,
|
|
93
|
+
.dg-wrap.is-loading::after, .ping::after {
|
|
94
|
+
animation-duration: 2.4s !important;
|
|
95
|
+
animation-iteration-count: infinite !important;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* Opt in per-element where a smooth auto height matters */
|
|
100
|
+
@supports (interpolate-size: allow-keywords) {
|
|
101
|
+
:root { interpolate-size: allow-keywords; }
|
|
102
|
+
}
|
|
103
|
+
}
|
package/src/03-type.css
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/* ==========================================================================
|
|
2
|
+
Deck — 03 Type
|
|
3
|
+
========================================================================== */
|
|
4
|
+
|
|
5
|
+
@layer deck.type {
|
|
6
|
+
|
|
7
|
+
h1, .h1, h2, .h2, h3, .h3, h4, .h4, h5, .h5, h6, .h6 {
|
|
8
|
+
font-family: var(--font-display);
|
|
9
|
+
font-weight: 640;
|
|
10
|
+
line-height: var(--leading-tight);
|
|
11
|
+
letter-spacing: -.021em;
|
|
12
|
+
color: var(--text);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
h1, .h1 { font-size: var(--text-3xl); letter-spacing: -.031em; }
|
|
16
|
+
h2, .h2 { font-size: var(--text-2xl); letter-spacing: -.026em; }
|
|
17
|
+
h3, .h3 { font-size: var(--text-xl); }
|
|
18
|
+
h4, .h4 { font-size: var(--text-lg); letter-spacing: -.014em; }
|
|
19
|
+
h5, .h5 { font-size: var(--text-md); letter-spacing: -.008em; font-weight: 620; }
|
|
20
|
+
h6, .h6 { font-size: var(--text-base); letter-spacing: 0; font-weight: 640; }
|
|
21
|
+
|
|
22
|
+
.display {
|
|
23
|
+
font-size: var(--text-4xl);
|
|
24
|
+
font-weight: 700;
|
|
25
|
+
line-height: 1.04;
|
|
26
|
+
letter-spacing: -.036em;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.lede {
|
|
30
|
+
font-size: var(--text-md);
|
|
31
|
+
line-height: var(--leading-loose);
|
|
32
|
+
color: var(--text-muted);
|
|
33
|
+
max-inline-size: var(--measure);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
small { font-size: var(--text-sm); }
|
|
37
|
+
|
|
38
|
+
strong, b { font-weight: 640; }
|
|
39
|
+
|
|
40
|
+
a {
|
|
41
|
+
color: var(--brand);
|
|
42
|
+
text-decoration-thickness: 1px;
|
|
43
|
+
text-underline-offset: .18em;
|
|
44
|
+
text-decoration-color: color-mix(in oklab, currentColor 40%, transparent);
|
|
45
|
+
transition: color var(--dur-1) var(--ease-out),
|
|
46
|
+
text-decoration-color var(--dur-1) var(--ease-out);
|
|
47
|
+
}
|
|
48
|
+
a:hover { color: var(--brand-hover); text-decoration-color: currentColor; }
|
|
49
|
+
|
|
50
|
+
.link-quiet { color: var(--text); text-decoration: none; }
|
|
51
|
+
.link-quiet:hover { color: var(--brand); text-decoration: underline; }
|
|
52
|
+
|
|
53
|
+
code, kbd, samp, pre { font-family: var(--font-mono); font-size: .92em; }
|
|
54
|
+
|
|
55
|
+
:not(pre) > code {
|
|
56
|
+
background: var(--surface-2);
|
|
57
|
+
border: 1px solid var(--line);
|
|
58
|
+
border-radius: var(--r-xs);
|
|
59
|
+
padding: .12em .38em;
|
|
60
|
+
color: light-dark(var(--brand-800), var(--brand-200));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
pre {
|
|
64
|
+
background: var(--ink-950);
|
|
65
|
+
color: var(--ink-100);
|
|
66
|
+
padding: var(--space-4);
|
|
67
|
+
border-radius: var(--r-md);
|
|
68
|
+
overflow-x: auto;
|
|
69
|
+
line-height: 1.6;
|
|
70
|
+
font-size: var(--text-sm);
|
|
71
|
+
-webkit-overflow-scrolling: touch;
|
|
72
|
+
}
|
|
73
|
+
pre code { background: none; border: 0; padding: 0; color: inherit; }
|
|
74
|
+
|
|
75
|
+
kbd {
|
|
76
|
+
display: inline-block;
|
|
77
|
+
background: var(--surface);
|
|
78
|
+
border: 1px solid var(--line-strong);
|
|
79
|
+
border-block-end-width: 2px;
|
|
80
|
+
border-radius: var(--r-xs);
|
|
81
|
+
padding: .1em .42em;
|
|
82
|
+
font-size: var(--text-xs);
|
|
83
|
+
line-height: 1.5;
|
|
84
|
+
color: var(--text-muted);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
blockquote {
|
|
88
|
+
border-inline-start: 3px solid var(--brand-300);
|
|
89
|
+
padding-inline-start: var(--space-4);
|
|
90
|
+
color: var(--text-muted);
|
|
91
|
+
font-size: var(--text-md);
|
|
92
|
+
line-height: var(--leading-loose);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
mark {
|
|
96
|
+
background: var(--accent-100);
|
|
97
|
+
color: light-dark(var(--ink-900), var(--ink-900));
|
|
98
|
+
padding: .05em .2em;
|
|
99
|
+
border-radius: var(--r-xs);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
abbr[title] { text-decoration: underline dotted; cursor: help; }
|
|
103
|
+
|
|
104
|
+
/* Prose: for anything that came out of a WYSIWYG or markdown */
|
|
105
|
+
.prose { max-inline-size: var(--measure); }
|
|
106
|
+
.prose > * + * { margin-block-start: var(--space-4); }
|
|
107
|
+
.prose > * + :is(h2, h3, h4) { margin-block-start: var(--space-8); }
|
|
108
|
+
.prose :is(ul, ol) { padding-inline-start: var(--space-6); display: grid; gap: var(--space-2); }
|
|
109
|
+
.prose ul { list-style: disc; }
|
|
110
|
+
.prose ol { list-style: decimal; }
|
|
111
|
+
.prose li::marker { color: var(--text-faint); }
|
|
112
|
+
.prose img { border-radius: var(--r-md); }
|
|
113
|
+
.prose hr { margin-block: var(--space-8); }
|
|
114
|
+
}
|