fractalstyler2 0.4.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -95
- package/dist/cli.js +105 -25
- package/dist/components/Accordion.svelte +44 -0
- package/dist/components/Accordion.svelte.d.ts +23 -0
- package/dist/components/AccordionItem.svelte +44 -0
- package/dist/components/AccordionItem.svelte.d.ts +21 -0
- package/dist/components/AppShell.svelte +86 -0
- package/dist/components/AppShell.svelte.d.ts +39 -0
- package/dist/components/ColorPicker.svelte +38 -0
- package/dist/components/ColorPicker.svelte.d.ts +6 -0
- package/dist/components/Hero.svelte +14 -0
- package/dist/components/Hero.svelte.d.ts +9 -0
- package/dist/components/LayoutPicker.svelte +34 -0
- package/dist/components/LayoutPicker.svelte.d.ts +6 -0
- package/dist/components/MotionPicker.svelte +34 -0
- package/dist/components/MotionPicker.svelte.d.ts +6 -0
- package/dist/components/PageShell.svelte +14 -0
- package/dist/components/PageShell.svelte.d.ts +9 -0
- package/dist/components/PageSplit.svelte +26 -0
- package/dist/components/PageSplit.svelte.d.ts +18 -0
- package/dist/components/ShapePicker.svelte +37 -0
- package/dist/components/ShapePicker.svelte.d.ts +6 -0
- package/dist/css/fractalstyler.css +10643 -0
- package/dist/css/fractalstyler.min.css +2 -0
- package/dist/index.d.ts +18 -6
- package/dist/index.js +30 -12
- package/dist/mcp/schemas/compile_fractals.json +3 -3
- package/dist/mcp/schemas/css_to_fractals.json +1 -1
- package/dist/mcp/schemas/generate_component.json +2 -2
- package/dist/mcp/schemas/instructions.md +41 -14
- package/dist/mcp/schemas/list_fractals.json +9 -7
- package/dist/mcp/schemas/validate_recipe.json +2 -2
- package/dist/mcp/server.d.ts +1 -1
- package/dist/mcp/server.js +320 -234
- package/dist/presets.core.d.ts +42 -0
- package/dist/presets.core.js +190 -0
- package/dist/presets.svelte.d.ts +6 -0
- package/dist/presets.svelte.js +21 -0
- package/dist/styles/_00_presets.sass +111 -0
- package/dist/styles/_00_themes.sass +1061 -0
- package/dist/styles/_00_tokens.sass +39 -17
- package/dist/styles/_01_config.sass +77 -70
- package/dist/styles/_02_dimensions.sass +174 -0
- package/dist/styles/_03_containers.sass +105 -0
- package/dist/styles/_04_layouts.sass +100 -0
- package/dist/styles/_05_shells.sass +374 -0
- package/dist/styles/_06_visuals.sass +236 -0
- package/dist/styles/_07_interactions.sass +112 -0
- package/dist/styles/_08_own.sass +4 -0
- package/dist/styles/canonical-markups.md +160 -0
- package/dist/styles/index.sass +11 -18
- package/dist/themes.d.ts +7 -0
- package/dist/themes.js +45 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +2 -0
- package/package.json +26 -15
- package/plugin.json +11 -10
- package/registry.json +2002 -0
- package/skills/fractal-styler/SKILL.md +137 -50
- package/skills/fractal-styler/references/fractals.md +416 -28
- package/skills/fractal-styler/references/tokens.md +110 -36
- package/dist/styles/_02_fonts.sass +0 -13
- package/dist/styles/_03_responsive.sass +0 -31
- package/dist/styles/_04_atoms.sass +0 -155
- package/dist/styles/_05_molecules.sass +0 -97
- package/dist/styles/_06_recipes.sass +0 -189
- package/dist/styles/_07_base.sass +0 -44
- package/dist/styles/_08_blocks.sass +0 -433
- package/dist/styles/_09_utilities.sass +0 -208
- package/dist/styles/_10_layouts.sass +0 -374
- package/dist/styles/_11_own.sass +0 -21
- package/dist/styles/_fractals.sass +0 -14
- package/skills/style-migration/SKILL.md +0 -45
- package/templates/_00_tokens.sass +0 -154
- package/templates/_01_config.sass +0 -66
- package/templates/_02_fonts.sass +0 -13
- package/templates/_03_responsive.sass +0 -31
- package/templates/_04_atoms.sass +0 -155
- package/templates/_05_molecules.sass +0 -97
- package/templates/_06_recipes.sass +0 -189
- package/templates/_07_base.sass +0 -44
- package/templates/_08_blocks.sass +0 -433
- package/templates/_09_utilities.sass +0 -207
- package/templates/_10_layouts.sass +0 -374
- package/templates/_11_own.sass +0 -21
- package/templates/_fractals.sass +0 -14
- package/templates/index.sass +0 -18
|
@@ -28,8 +28,6 @@
|
|
|
28
28
|
--border-subtle: #EDF2F7
|
|
29
29
|
--theme-color: #04825B
|
|
30
30
|
--theme-color-alt: #047857
|
|
31
|
-
--theme: var(--theme-color)
|
|
32
|
-
--theme-hover: var(--theme-color-alt)
|
|
33
31
|
--success: #10B981
|
|
34
32
|
--success-hover: #059669
|
|
35
33
|
--warning: #F59E0B
|
|
@@ -40,6 +38,10 @@
|
|
|
40
38
|
--info-hover: #2563EB
|
|
41
39
|
--feedback-error: #DC2626
|
|
42
40
|
--ring: rgba(0, 127, 78, 0.35)
|
|
41
|
+
// Per-mode shadows (registry v1)
|
|
42
|
+
--shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06)
|
|
43
|
+
--shadow-md: 0 4px 12px rgba(15, 23, 42, 0.08)
|
|
44
|
+
--shadow-lg: 0 12px 32px rgba(15, 23, 42, 0.12)
|
|
43
45
|
|
|
44
46
|
=dark-theme-tokens
|
|
45
47
|
color-scheme: dark
|
|
@@ -63,8 +65,6 @@
|
|
|
63
65
|
--state-selected: #32405E
|
|
64
66
|
--theme-color: #38BDF8
|
|
65
67
|
--theme-color-alt: #0EA5E9
|
|
66
|
-
--theme: var(--theme-color)
|
|
67
|
-
--theme-hover: var(--theme-color-alt)
|
|
68
68
|
--text-inverse: #0E1118
|
|
69
69
|
--success: #34D399
|
|
70
70
|
--success-hover: #6EE7B7
|
|
@@ -76,6 +76,10 @@
|
|
|
76
76
|
--info-hover: #93C5FD
|
|
77
77
|
--feedback-error: #F87171
|
|
78
78
|
--ring: rgba(16, 185, 129, 0.4)
|
|
79
|
+
// Per-mode shadows (registry v1)
|
|
80
|
+
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4)
|
|
81
|
+
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.35)
|
|
82
|
+
--shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.45)
|
|
79
83
|
|
|
80
84
|
:root
|
|
81
85
|
color-scheme: light
|
|
@@ -94,17 +98,17 @@
|
|
|
94
98
|
--text-3xl: clamp(2.3328rem, 2.0387rem + 1.3072vw, 3.0518rem)
|
|
95
99
|
--text-4xl: clamp(2.7994rem, 2.384rem + 1.8461vw, 3.8147rem)
|
|
96
100
|
|
|
97
|
-
// Fluid space scale
|
|
101
|
+
// Fluid space scale — the comfortable values. data-layout scales at USE
|
|
102
|
+
// sites: gaps/margins × var(--gap-scale), paddings × var(--pad-scale).
|
|
98
103
|
--space-3xs: clamp(0.3125rem, 0.3125rem + 0vw, 0.3125rem)
|
|
99
104
|
--space-2xs: clamp(0.5625rem, 0.5369rem + 0.1136vw, 0.625rem)
|
|
100
105
|
--space-xs: clamp(0.875rem, 0.8494rem + 0.1136vw, 0.9375rem)
|
|
101
|
-
--space-
|
|
102
|
-
--space-
|
|
103
|
-
--space-
|
|
106
|
+
--space-sm: clamp(1.125rem, 1.0739rem + 0.2273vw, 1.25rem)
|
|
107
|
+
--space-md: clamp(1.6875rem, 1.6108rem + 0.3409vw, 1.875rem)
|
|
108
|
+
--space-lg: clamp(2.25rem, 2.1477rem + 0.4545vw, 2.5rem)
|
|
104
109
|
--space-xl: clamp(3.375rem, 3.2216rem + 0.6818vw, 3.75rem)
|
|
105
110
|
--space-2xl: clamp(4.5rem, 4.2955rem + 0.9091vw, 5rem)
|
|
106
111
|
--space-3xl: clamp(6.75rem, 6.4432rem + 1.3636vw, 7.5rem)
|
|
107
|
-
--space-s-l: clamp(1.125rem, 0.5625rem + 2.5vw, 2.5rem)
|
|
108
112
|
|
|
109
113
|
// Radius (Concentric hierarchy)
|
|
110
114
|
--radius-0: 0
|
|
@@ -118,15 +122,25 @@
|
|
|
118
122
|
--radius-24: 24px
|
|
119
123
|
--radius-full: 9999px
|
|
120
124
|
|
|
125
|
+
// Radius channels — compositions read these; shape presets remap them.
|
|
126
|
+
// Defaults = curved (registry v1); unset data-shape IS curved.
|
|
127
|
+
--radius-sm: 8px
|
|
128
|
+
--radius-md: 16px
|
|
129
|
+
--radius-lg: 24px
|
|
130
|
+
|
|
131
|
+
// Motion language (registry v1) — durations and easings all compositions read.
|
|
132
|
+
--motion-fast: 120ms
|
|
133
|
+
--motion-base: 160ms
|
|
134
|
+
--motion-slow: 240ms
|
|
135
|
+
--ease-out: cubic-bezier(0.16, 1, 0.3, 1)
|
|
136
|
+
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1)
|
|
137
|
+
|
|
121
138
|
// Control Heights
|
|
122
139
|
--control-h-sm: 26px
|
|
123
140
|
--control-h-md: 32px
|
|
124
141
|
--control-h-lg: 38px
|
|
125
142
|
|
|
126
|
-
// Shadow
|
|
127
|
-
--shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06)
|
|
128
|
-
--shadow-md: 0 4px 12px rgba(15, 23, 42, 0.08)
|
|
129
|
-
--shadow-lg: 0 12px 32px rgba(15, 23, 42, 0.12)
|
|
143
|
+
// Shadow values live in the theme mixins (per-mode since registry v1).
|
|
130
144
|
|
|
131
145
|
// Layering
|
|
132
146
|
--z-base: 0
|
|
@@ -137,14 +151,24 @@
|
|
|
137
151
|
|
|
138
152
|
// Layout
|
|
139
153
|
--header-height: 48px
|
|
140
|
-
--footer-height:
|
|
154
|
+
--footer-height: 32px
|
|
141
155
|
--measure: 65ch
|
|
156
|
+
--page-gutter: clamp(1rem, 4vw, 2rem)
|
|
157
|
+
--sidebar-width: 260px
|
|
158
|
+
--toc-width: 240px
|
|
159
|
+
--card-min: 16rem
|
|
160
|
+
--breakpoint: 768px
|
|
142
161
|
|
|
143
162
|
// Default Light Palette
|
|
144
163
|
+light-theme-tokens
|
|
145
164
|
|
|
165
|
+
// Plain :root, NOT :root:not([data-mode='light']). The :not() was redundant —
|
|
166
|
+
// [data-mode='light'] is emitted below and wins on source order at equal
|
|
167
|
+
// specificity — and it was harmful: :not() pushed this to (0,2,0), which
|
|
168
|
+
// outranks a .theme-* class at (0,1,0). Under OS dark mode every theme's
|
|
169
|
+
// surface tokens were silently overridden by these generic defaults.
|
|
146
170
|
@media (prefers-color-scheme: dark)
|
|
147
|
-
:root
|
|
171
|
+
:root
|
|
148
172
|
+dark-theme-tokens
|
|
149
173
|
|
|
150
174
|
[data-mode='dark']
|
|
@@ -152,5 +176,3 @@
|
|
|
152
176
|
|
|
153
177
|
[data-mode='light']
|
|
154
178
|
+light-theme-tokens
|
|
155
|
-
|
|
156
|
-
|
|
@@ -1,70 +1,77 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
$
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
$
|
|
21
|
-
|
|
22
|
-
//
|
|
23
|
-
$
|
|
24
|
-
$
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// config — the builder knobs the Contract names. All !default: overridable at
|
|
3
|
+
// compile time, never edited in place. The numbered filename is not a valid
|
|
4
|
+
// Sass identifier, so a consumer MUST namespace the configuring load:
|
|
5
|
+
//
|
|
6
|
+
// @use 'styles/01_config' as cfg with ($literal-max: 256)
|
|
7
|
+
// @use 'styles/index' as *
|
|
8
|
+
//
|
|
9
|
+
// Configure before anything else loads 01_config, or Sass rejects it.
|
|
10
|
+
// ============================================================================
|
|
11
|
+
|
|
12
|
+
// The responsive seam. Every loop-generated class takes -mob (below) and
|
|
13
|
+
// -desk (at or above) this width.
|
|
14
|
+
$breakpoint: 768px !default
|
|
15
|
+
$responsive-modes: (mob: 'all and (max-width: #{$breakpoint - 1})', desk: 'all and (min-width: #{$breakpoint})') !default
|
|
16
|
+
|
|
17
|
+
// Literal ladder: the discrete pixel values .gap-{N}, .radius-{N}, .w-{N}… emit.
|
|
18
|
+
//
|
|
19
|
+
// Fine at the bottom, where interfaces genuinely need 1px and 2px precision,
|
|
20
|
+
// then multiples of $literal-step the rest of the way. A continuous 1…256
|
|
21
|
+
// range emitted 7,302 rungs per band to serve maybe forty useful values;
|
|
22
|
+
// nobody types .marg-left--193.
|
|
23
|
+
$literal-fine: (0, 1, 2, 4, 6, 8, 12) !default
|
|
24
|
+
$literal-step: 8 !default
|
|
25
|
+
$literal-max: 512 !default
|
|
26
|
+
|
|
27
|
+
// Space literals stop earlier than sizing ones. Gaps, paddings and margins are
|
|
28
|
+
// 24 of the 28 classes emitted per rung (marg doubles for negatives), so they
|
|
29
|
+
// dominate the output — and a 512px gap is meaningless where a 512px width is
|
|
30
|
+
// not. Large spacing is the preset steps' job: --space-3xl is already ~120px.
|
|
31
|
+
$literal-space-max: 64 !default
|
|
32
|
+
|
|
33
|
+
// Radius stops early for the same reason: .radius-full already handles pills,
|
|
34
|
+
// and the shape presets top out at --radius-lg (~24-32px). A 512px corner is
|
|
35
|
+
// not a corner.
|
|
36
|
+
$literal-radius-max: 64 !default
|
|
37
|
+
|
|
38
|
+
// Named steps for grid stepping and the shell rails (not the responsive seam).
|
|
39
|
+
$breakpoints: (sm: 640px, md: 768px, lg: 1024px, xl: 1280px) !default
|
|
40
|
+
|
|
41
|
+
// ============================================================================
|
|
42
|
+
// base — element baseline. Builder infrastructure, not registry classes: the
|
|
43
|
+
// registry is a list of classes; this only makes documents predictable so the
|
|
44
|
+
// classes behave. Deliberately minimal — no typographic opinions beyond body.
|
|
45
|
+
// ============================================================================
|
|
46
|
+
|
|
47
|
+
*,
|
|
48
|
+
*::before,
|
|
49
|
+
*::after
|
|
50
|
+
box-sizing: border-box
|
|
51
|
+
|
|
52
|
+
*
|
|
53
|
+
margin: 0
|
|
54
|
+
|
|
55
|
+
body, html
|
|
56
|
+
font-family: var(--font-sans)
|
|
57
|
+
font-size: var(--text-sm)
|
|
58
|
+
line-height: 1.5
|
|
59
|
+
color: var(--text-primary)
|
|
60
|
+
background: var(--bg)
|
|
61
|
+
box-sizing: border-box
|
|
62
|
+
|
|
63
|
+
img,
|
|
64
|
+
video,
|
|
65
|
+
svg
|
|
66
|
+
display: block
|
|
67
|
+
max-width: 100%
|
|
68
|
+
|
|
69
|
+
button,
|
|
70
|
+
input,
|
|
71
|
+
select,
|
|
72
|
+
textarea
|
|
73
|
+
font: inherit
|
|
74
|
+
color: inherit
|
|
75
|
+
|
|
76
|
+
a
|
|
77
|
+
color: inherit
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// dimensions — L1. The loop-generated half of the registry: 17 space families,
|
|
3
|
+
// radius, size, viewport heights, shadows — each class in three bands (base,
|
|
4
|
+
// -mob, -desk) per Contract 7. Presets are token-routed; literals are px.
|
|
5
|
+
// ============================================================================
|
|
6
|
+
|
|
7
|
+
@use 'sass:string'
|
|
8
|
+
@use 'sass:list'
|
|
9
|
+
@use 'sass:math'
|
|
10
|
+
@use '01_config' as *
|
|
11
|
+
|
|
12
|
+
// The literal ladder, built once: the fine tail, then every $literal-step up
|
|
13
|
+
// to $literal-max. Radius and sizing iterate all of it.
|
|
14
|
+
$literals: $literal-fine
|
|
15
|
+
@for $i from 2 through math.div($literal-max, $literal-step)
|
|
16
|
+
$literals: list.append($literals, $i * $literal-step)
|
|
17
|
+
|
|
18
|
+
// The space families take the same ladder truncated at $literal-space-max,
|
|
19
|
+
// radius at $literal-radius-max. Only sizing runs the whole thing.
|
|
20
|
+
$space-literals: ()
|
|
21
|
+
@each $n in $literals
|
|
22
|
+
@if $n <= $literal-space-max
|
|
23
|
+
$space-literals: list.append($space-literals, $n)
|
|
24
|
+
|
|
25
|
+
$radius-literals: ()
|
|
26
|
+
@each $n in $literals
|
|
27
|
+
@if $n <= $literal-radius-max
|
|
28
|
+
$radius-literals: list.append($radius-literals, $n)
|
|
29
|
+
$steps: ('3xs' '2xs' 'xs' 'sm' 'md' 'lg' 'xl' '2xl' '3xl')
|
|
30
|
+
|
|
31
|
+
// Space families, role-split for the layout preset: gaps/margins separate
|
|
32
|
+
// content (× --gap-scale); paddings are the container's breathing (× --pad-scale).
|
|
33
|
+
$gap-families: (gap: gap, rgap: row-gap, cgap: column-gap)
|
|
34
|
+
|
|
35
|
+
$pad-families: (pad: padding, pad-x: padding-inline, pad-y: padding-block, pad-top: padding-top, pad-right: padding-right, pad-bottom: padding-bottom, pad-left: padding-left)
|
|
36
|
+
|
|
37
|
+
// Negatives ride margin families only (Contract: `--` infix).
|
|
38
|
+
$marg-families: (marg: margin, marg-x: margin-inline, marg-y: margin-block, marg-top: margin-top, marg-right: margin-right, marg-bottom: margin-bottom, marg-left: margin-left)
|
|
39
|
+
|
|
40
|
+
// --- Base band ---------------------------------------------------------------
|
|
41
|
+
@each $name, $prop in $gap-families
|
|
42
|
+
@each $step in $steps
|
|
43
|
+
.#{$name}-#{$step}
|
|
44
|
+
#{$prop}: calc(var(--space-#{$step}) * var(--gap-scale, 1))
|
|
45
|
+
@each $n in $space-literals
|
|
46
|
+
.#{$name}-#{$n}
|
|
47
|
+
#{$prop}: #{$n}px
|
|
48
|
+
|
|
49
|
+
@each $name, $prop in $pad-families
|
|
50
|
+
@each $step in $steps
|
|
51
|
+
.#{$name}-#{$step}
|
|
52
|
+
#{$prop}: calc(var(--space-#{$step}) * var(--pad-scale, 1))
|
|
53
|
+
@each $n in $space-literals
|
|
54
|
+
.#{$name}-#{$n}
|
|
55
|
+
#{$prop}: #{$n}px
|
|
56
|
+
|
|
57
|
+
@each $name, $prop in $marg-families
|
|
58
|
+
@each $step in $steps
|
|
59
|
+
.#{$name}-#{$step}
|
|
60
|
+
#{$prop}: calc(var(--space-#{$step}) * var(--gap-scale, 1))
|
|
61
|
+
.#{$name}--#{$step}
|
|
62
|
+
#{$prop}: calc(var(--space-#{$step}) * var(--gap-scale, 1) * -1)
|
|
63
|
+
@each $n in $space-literals
|
|
64
|
+
.#{$name}-#{$n}
|
|
65
|
+
#{$prop}: #{$n}px
|
|
66
|
+
.#{$name}--#{$n}
|
|
67
|
+
#{$prop}: -#{$n}px
|
|
68
|
+
|
|
69
|
+
// Radius — literal px (0 = the reset); never rides shape presets.
|
|
70
|
+
@each $n in $radius-literals
|
|
71
|
+
.radius-#{$n}
|
|
72
|
+
border-radius: #{$n}px
|
|
73
|
+
|
|
74
|
+
.radius-full
|
|
75
|
+
border-radius: var(--radius-full)
|
|
76
|
+
|
|
77
|
+
// The radius CHANNELS as classes. Unlike the numeric ladder these follow
|
|
78
|
+
// data-shape, so a card on .radius-md goes round -> curved -> pro -> sharp with
|
|
79
|
+
// the preset. Reach for these first; the literals are for exact requirements.
|
|
80
|
+
@each $step in ('sm' 'md' 'lg')
|
|
81
|
+
.radius-#{$step}
|
|
82
|
+
border-radius: var(--radius-#{$step})
|
|
83
|
+
|
|
84
|
+
// Size
|
|
85
|
+
@each $n in $literals
|
|
86
|
+
.w-#{$n}
|
|
87
|
+
width: #{$n}px
|
|
88
|
+
.h-#{$n}
|
|
89
|
+
height: #{$n}px
|
|
90
|
+
.square-#{$n}
|
|
91
|
+
width: #{$n}px
|
|
92
|
+
height: #{$n}px
|
|
93
|
+
|
|
94
|
+
.wfull
|
|
95
|
+
width: 100%
|
|
96
|
+
.hfull
|
|
97
|
+
height: 100%
|
|
98
|
+
.full
|
|
99
|
+
width: 100%
|
|
100
|
+
height: 100%
|
|
101
|
+
.min0
|
|
102
|
+
min-width: 0
|
|
103
|
+
min-height: 0
|
|
104
|
+
|
|
105
|
+
// Viewport heights
|
|
106
|
+
.hfull-vh
|
|
107
|
+
min-height: 100vh
|
|
108
|
+
.hfull-vh-fitted
|
|
109
|
+
min-height: calc(100vh - var(--header-height, 48px) - var(--footer-height))
|
|
110
|
+
|
|
111
|
+
// --- Responsive bands: -mob / -desk, generated wholesale (Contract 7) --------
|
|
112
|
+
@each $mode, $query in $responsive-modes
|
|
113
|
+
@media #{string.unquote($query)}
|
|
114
|
+
@each $name, $prop in $gap-families
|
|
115
|
+
@each $step in $steps
|
|
116
|
+
.#{$name}-#{$step}-#{$mode}
|
|
117
|
+
#{$prop}: calc(var(--space-#{$step}) * var(--gap-scale, 1))
|
|
118
|
+
@each $n in $space-literals
|
|
119
|
+
.#{$name}-#{$n}-#{$mode}
|
|
120
|
+
#{$prop}: #{$n}px
|
|
121
|
+
@each $name, $prop in $pad-families
|
|
122
|
+
@each $step in $steps
|
|
123
|
+
.#{$name}-#{$step}-#{$mode}
|
|
124
|
+
#{$prop}: calc(var(--space-#{$step}) * var(--pad-scale, 1))
|
|
125
|
+
@each $n in $space-literals
|
|
126
|
+
.#{$name}-#{$n}-#{$mode}
|
|
127
|
+
#{$prop}: #{$n}px
|
|
128
|
+
@each $name, $prop in $marg-families
|
|
129
|
+
@each $step in $steps
|
|
130
|
+
.#{$name}-#{$step}-#{$mode}
|
|
131
|
+
#{$prop}: calc(var(--space-#{$step}) * var(--gap-scale, 1))
|
|
132
|
+
.#{$name}--#{$step}-#{$mode}
|
|
133
|
+
#{$prop}: calc(var(--space-#{$step}) * var(--gap-scale, 1) * -1)
|
|
134
|
+
@each $n in $space-literals
|
|
135
|
+
.#{$name}-#{$n}-#{$mode}
|
|
136
|
+
#{$prop}: #{$n}px
|
|
137
|
+
.#{$name}--#{$n}-#{$mode}
|
|
138
|
+
#{$prop}: -#{$n}px
|
|
139
|
+
@each $n in $radius-literals
|
|
140
|
+
.radius-#{$n}-#{$mode}
|
|
141
|
+
border-radius: #{$n}px
|
|
142
|
+
.radius-full-#{$mode}
|
|
143
|
+
border-radius: var(--radius-full)
|
|
144
|
+
@each $step in ('sm' 'md' 'lg')
|
|
145
|
+
.radius-#{$step}-#{$mode}
|
|
146
|
+
border-radius: var(--radius-#{$step})
|
|
147
|
+
@each $n in $literals
|
|
148
|
+
.w-#{$n}-#{$mode}
|
|
149
|
+
width: #{$n}px
|
|
150
|
+
.h-#{$n}-#{$mode}
|
|
151
|
+
height: #{$n}px
|
|
152
|
+
.square-#{$n}-#{$mode}
|
|
153
|
+
width: #{$n}px
|
|
154
|
+
height: #{$n}px
|
|
155
|
+
.wfull-#{$mode}
|
|
156
|
+
width: 100%
|
|
157
|
+
.hfull-#{$mode}
|
|
158
|
+
height: 100%
|
|
159
|
+
.full-#{$mode}
|
|
160
|
+
width: 100%
|
|
161
|
+
height: 100%
|
|
162
|
+
.min0-#{$mode}
|
|
163
|
+
min-width: 0
|
|
164
|
+
min-height: 0
|
|
165
|
+
.hfull-vh-#{$mode}
|
|
166
|
+
min-height: 100vh
|
|
167
|
+
.hfull-vh-fitted-#{$mode}
|
|
168
|
+
min-height: calc(100vh - var(--header-height, 48px) - var(--footer-height))
|
|
169
|
+
.shadow-sm-#{$mode}
|
|
170
|
+
box-shadow: var(--shadow-sm)
|
|
171
|
+
.shadow-md-#{$mode}
|
|
172
|
+
box-shadow: var(--shadow-md)
|
|
173
|
+
.shadow-lg-#{$mode}
|
|
174
|
+
box-shadow: var(--shadow-lg)
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// flow — L2. Containers and the alignment universe, verbatim from the
|
|
3
|
+
// registry. Alignment classes are nested under their base — never standalone.
|
|
4
|
+
// x/y are physical axes, always (Contract 4).
|
|
5
|
+
// ============================================================================
|
|
6
|
+
.box
|
|
7
|
+
display: flex
|
|
8
|
+
flex-direction: column
|
|
9
|
+
&.xcenter
|
|
10
|
+
align-items: center
|
|
11
|
+
text-align: center
|
|
12
|
+
&.xleft
|
|
13
|
+
align-items: flex-start
|
|
14
|
+
text-align: left
|
|
15
|
+
&.xright
|
|
16
|
+
align-items: flex-end
|
|
17
|
+
text-align: right
|
|
18
|
+
&.ycenter
|
|
19
|
+
justify-content: center
|
|
20
|
+
&.ytop
|
|
21
|
+
justify-content: flex-start
|
|
22
|
+
&.ybot
|
|
23
|
+
justify-content: flex-end
|
|
24
|
+
&.ybetween
|
|
25
|
+
justify-content: space-between
|
|
26
|
+
&.yevenly
|
|
27
|
+
justify-content: space-evenly
|
|
28
|
+
&.yaround
|
|
29
|
+
justify-content: space-around
|
|
30
|
+
|
|
31
|
+
.row
|
|
32
|
+
display: flex
|
|
33
|
+
flex-direction: row
|
|
34
|
+
&.xleft
|
|
35
|
+
justify-content: flex-start
|
|
36
|
+
&.xcenter
|
|
37
|
+
justify-content: center
|
|
38
|
+
&.xright
|
|
39
|
+
justify-content: flex-end
|
|
40
|
+
&.xbetween
|
|
41
|
+
justify-content: space-between
|
|
42
|
+
&.xevenly
|
|
43
|
+
justify-content: space-evenly
|
|
44
|
+
&.xaround
|
|
45
|
+
justify-content: space-around
|
|
46
|
+
&.ycenter
|
|
47
|
+
align-items: center
|
|
48
|
+
&.ytop
|
|
49
|
+
align-items: flex-start
|
|
50
|
+
&.ybot
|
|
51
|
+
align-items: flex-end
|
|
52
|
+
|
|
53
|
+
.grid
|
|
54
|
+
display: grid
|
|
55
|
+
&.center
|
|
56
|
+
place-items: center
|
|
57
|
+
&.xcenter
|
|
58
|
+
justify-items: center
|
|
59
|
+
text-align: center
|
|
60
|
+
&.xleft
|
|
61
|
+
justify-items: start
|
|
62
|
+
text-align: left
|
|
63
|
+
&.xright
|
|
64
|
+
justify-items: end
|
|
65
|
+
text-align: right
|
|
66
|
+
&.xstretch
|
|
67
|
+
justify-items: stretch
|
|
68
|
+
&.ycenter
|
|
69
|
+
align-items: center
|
|
70
|
+
&.ytop
|
|
71
|
+
align-items: start
|
|
72
|
+
&.ybot
|
|
73
|
+
align-items: end
|
|
74
|
+
&.ystretch
|
|
75
|
+
align-items: stretch
|
|
76
|
+
&.xbetween
|
|
77
|
+
justify-content: space-between
|
|
78
|
+
&.xevenly
|
|
79
|
+
justify-content: space-evenly
|
|
80
|
+
&.xaround
|
|
81
|
+
justify-content: space-around
|
|
82
|
+
&.ybetween
|
|
83
|
+
align-content: space-between
|
|
84
|
+
&.yevenly
|
|
85
|
+
align-content: space-evenly
|
|
86
|
+
&.yaround
|
|
87
|
+
align-content: space-around
|
|
88
|
+
|
|
89
|
+
.wrap
|
|
90
|
+
flex-wrap: wrap
|
|
91
|
+
|
|
92
|
+
.grow
|
|
93
|
+
flex: 1 1 0%
|
|
94
|
+
|
|
95
|
+
.shrink-0
|
|
96
|
+
flex-shrink: 0
|
|
97
|
+
|
|
98
|
+
.relative
|
|
99
|
+
position: relative
|
|
100
|
+
.absolute
|
|
101
|
+
position: absolute
|
|
102
|
+
.fixed
|
|
103
|
+
position: fixed
|
|
104
|
+
.sticky
|
|
105
|
+
position: sticky
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// layouts — L3. Grids (gridding golden rules), card-grid, prose, frame
|
|
3
|
+
// presets, reel. Grids are pure stepping: no default gap — compose .gap-*
|
|
4
|
+
// (self-sufficiency; a default gap is an opinion the system doesn't hold).
|
|
5
|
+
// ============================================================================
|
|
6
|
+
|
|
7
|
+
@use 'sass:string'
|
|
8
|
+
@use 'sass:list'
|
|
9
|
+
@use 'sass:map'
|
|
10
|
+
@use '01_config' as *
|
|
11
|
+
|
|
12
|
+
$sm: map.get($breakpoints, sm)
|
|
13
|
+
$md: map.get($breakpoints, md)
|
|
14
|
+
$lg: map.get($breakpoints, lg)
|
|
15
|
+
|
|
16
|
+
// Gridding golden rules: exactly 3 items → 3→1, never 2+1; count 4 or a
|
|
17
|
+
// multiple of 4 → 4→2→1, never 3+1; 6 → 6→3→2→1 (both rules hold throughout).
|
|
18
|
+
.grid-1
|
|
19
|
+
display: grid
|
|
20
|
+
grid-template-columns: repeat(1, minmax(0, 1fr))
|
|
21
|
+
|
|
22
|
+
.grid-2
|
|
23
|
+
display: grid
|
|
24
|
+
grid-template-columns: repeat(1, minmax(0, 1fr))
|
|
25
|
+
@media #{string.unquote('(min-width: #{$md})')}
|
|
26
|
+
grid-template-columns: repeat(2, minmax(0, 1fr))
|
|
27
|
+
|
|
28
|
+
.grid-3
|
|
29
|
+
display: grid
|
|
30
|
+
grid-template-columns: repeat(1, minmax(0, 1fr))
|
|
31
|
+
@media #{string.unquote('(min-width: #{$lg})')}
|
|
32
|
+
grid-template-columns: repeat(3, minmax(0, 1fr))
|
|
33
|
+
|
|
34
|
+
.grid-4
|
|
35
|
+
display: grid
|
|
36
|
+
grid-template-columns: repeat(1, minmax(0, 1fr))
|
|
37
|
+
@media #{string.unquote('(min-width: #{$sm})')}
|
|
38
|
+
grid-template-columns: repeat(2, minmax(0, 1fr))
|
|
39
|
+
@media #{string.unquote('(min-width: #{$lg})')}
|
|
40
|
+
grid-template-columns: repeat(4, minmax(0, 1fr))
|
|
41
|
+
|
|
42
|
+
.grid-6
|
|
43
|
+
display: grid
|
|
44
|
+
grid-template-columns: repeat(1, minmax(0, 1fr))
|
|
45
|
+
@media #{string.unquote('(min-width: #{$sm})')}
|
|
46
|
+
grid-template-columns: repeat(2, minmax(0, 1fr))
|
|
47
|
+
@media #{string.unquote('(min-width: #{$md})')}
|
|
48
|
+
grid-template-columns: repeat(3, minmax(0, 1fr))
|
|
49
|
+
@media #{string.unquote('(min-width: #{$lg})')}
|
|
50
|
+
grid-template-columns: repeat(6, minmax(0, 1fr))
|
|
51
|
+
|
|
52
|
+
// Auto-fit repeatable cards — column count negotiable, min track from config.
|
|
53
|
+
.card-grid
|
|
54
|
+
display: grid
|
|
55
|
+
grid-template-columns: repeat(auto-fit, minmax(min(var(--card-min), 100%), 1fr))
|
|
56
|
+
|
|
57
|
+
// Prose — the reading measure (≤ 760px) + typographic rhythm (rhythm authored).
|
|
58
|
+
.prose
|
|
59
|
+
max-width: min(100%, 760px)
|
|
60
|
+
margin-inline: auto
|
|
61
|
+
line-height: 1.65
|
|
62
|
+
// Rhythm comes from gap, not from adjacent-sibling margins: one rule
|
|
63
|
+
// instead of a combinator, and it cannot leak into nested content.
|
|
64
|
+
display: flex
|
|
65
|
+
flex-direction: column
|
|
66
|
+
gap: calc(var(--space-sm) * var(--gap-scale, 1))
|
|
67
|
+
h1, h2, h3, h4
|
|
68
|
+
line-height: 1.25
|
|
69
|
+
font-weight: 600
|
|
70
|
+
// Extra breathing above a heading, on top of the gap.
|
|
71
|
+
margin-top: calc(var(--space-2xs) * var(--gap-scale, 1))
|
|
72
|
+
&:first-child
|
|
73
|
+
margin-top: 0
|
|
74
|
+
|
|
75
|
+
// Frame presets — aspect-ratio media boxes (replaces any frame abstraction).
|
|
76
|
+
$frame-ratios: ('16-9': '16 / 9', '9-16': '9 / 16', '4-3': '4 / 3', '3-4': '3 / 4', '3-2': '3 / 2', '2-3': '2 / 3', '1-1': '1 / 1')
|
|
77
|
+
@each $name, $ratio in $frame-ratios
|
|
78
|
+
.frame-#{$name}
|
|
79
|
+
aspect-ratio: #{$ratio}
|
|
80
|
+
overflow: hidden
|
|
81
|
+
position: relative
|
|
82
|
+
img, video, iframe
|
|
83
|
+
width: 100%
|
|
84
|
+
height: 100%
|
|
85
|
+
object-fit: cover
|
|
86
|
+
|
|
87
|
+
// Reel — the human-driven scroll-snap rail (filmstrip). Open for carousel duty.
|
|
88
|
+
.reel
|
|
89
|
+
display: flex
|
|
90
|
+
flex-direction: row
|
|
91
|
+
overflow-x: auto
|
|
92
|
+
overscroll-behavior-inline: contain
|
|
93
|
+
scroll-snap-type: inline mandatory
|
|
94
|
+
// The system's one permitted `>`. Snap targets must be the rail's own
|
|
95
|
+
// children: a descendant selector would make nested elements snap too and
|
|
96
|
+
// the rail would catch in the wrong places. Kept deliberately — see the
|
|
97
|
+
// combinator guard in scripts/validate-deck.js.
|
|
98
|
+
> *
|
|
99
|
+
flex: 0 0 auto
|
|
100
|
+
scroll-snap-align: start
|