fractalstyler2 0.0.1 → 0.0.2

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 CHANGED
@@ -3,62 +3,35 @@
3
3
  A fractal-composition styling system for SvelteKit. **Every style unit is a SASS
4
4
  mixin ("a fractal"), and components and layouts are recipes of smaller fractals.**
5
5
 
6
- This is a standalone package with no relationship to any earlier styler. The
7
- product is framework-agnostic SASS surfaced through a SvelteKit library; the JS
8
- runtime is just a tiny mode helper.
6
+ Use it either as a **shadcn-style scaffolder** (copying editable SASS into your project's `src/lib/styles`) or as a **direct package dependency**.
9
7
 
10
- ## The idea
8
+ ---
11
9
 
12
- A fractal is a mixin: a tiny reusable styling decision that composes other
13
- fractals. They form four self-similar tiers — each tier is "a recipe of the one
14
- below":
10
+ ## Quickstart (shadcn-style Scaffolding)
15
11
 
16
- | Tier | What | Examples |
17
- | --- | --- | --- |
18
- | **Config** | scales-as-data + resolvers | `space()`, `radius()`, `align()`, `$breakpoints` |
19
- | **Atoms** | one decision each | `+box` `+row` `+gap` `+pad` `+border` `+radius` `+bg` `+ink` `+type` `+sticky` |
20
- | **Molecules** | graphs of atoms | `+stack` `+cluster` `+cover` `+frame` `+surface` `+cols` `+auto-grid` |
21
- | **Components / Layouts** | graphs of molecules | `.card` `.button` · `.grid-3` `.hero` `.holy-grail` `.docs` `.app-shell` |
22
-
23
- The one idea that makes it click:
24
-
25
- > **A utility class and a semantic component are the same fractal, consumed two ways.**
26
- > `.gap-m { +gap(m) }` binds the fractal to markup; `.hero { +cover; +stack(m) }`
27
- > composes it into a component. One vocabulary, you pick where each is used.
28
-
29
- ## Install
12
+ Scaffold the complete, customizable SASS design system directly into your project's `src/lib/styles`:
30
13
 
31
14
  ```bash
32
- pnpm add fractalstyler2
33
- ```
15
+ # Scaffold into src/lib/styles
16
+ npx fractalstyler2 init
34
17
 
35
- ## Use
18
+ # Or using pnpm
19
+ pnpm dlx fractalstyler2 init
20
+ ```
36
21
 
37
- **1 Emit the ready-made stylesheet** (tokens, base reset, utility classes,
38
- blocks, layouts). Import once, globally (e.g. in your root `+layout.svelte`):
22
+ ### Next Steps in Your Project
39
23
 
24
+ **1. Import the stylesheet in your root `+layout.svelte`:**
40
25
  ```svelte
41
26
  <script>
42
- import 'fractalstyler2/styles';
27
+ import '$lib/styles/index.sass';
43
28
  </script>
44
29
  ```
45
30
 
46
- Then write thin, semantic markup:
47
-
48
- ```svelte
49
- <div class="grid-3">
50
- <article class="card"><h3 class="text-lg">Composable</h3></article>
51
- <article class="card" data-elevated><h3 class="text-lg">Elevated</h3></article>
52
- <article class="card"><h3 class="text-lg">Semantic</h3></article>
53
- </div>
54
- ```
55
-
56
- **2 — Compose your own components from the fractals.** Import the pure API
57
- (emits nothing until called) inside any component's SASS:
58
-
31
+ **2. Compose your components using the fractals:**
59
32
  ```svelte
60
33
  <style lang="sass">
61
- @use 'fractalstyler2/fractals' as *
34
+ @use '$lib/styles/fractals' as *
62
35
 
63
36
  .pricing-card
64
37
  +surface(surface, l, 16, md) // bg + border + radius + pad + shadow
@@ -67,48 +40,91 @@ Then write thin, semantic markup:
67
40
  </style>
68
41
  ```
69
42
 
70
- Values prefer the finite token scale and fall back to raw units in the same
71
- call: `+gap(m)` → `var(--space-m)`, `+gap(16)` → `16px`. No JIT class explosion.
43
+ ---
44
+
45
+ ## Alternative: Direct Package Dependency
72
46
 
73
- ## What ships
47
+ If you prefer importing from `node_modules` instead of scaffolding local files:
48
+
49
+ ```bash
50
+ npm install fractalstyler2
51
+ # or
52
+ pnpm add fractalstyler2
53
+ ```
74
54
 
55
+ Your app also needs `sass`:
56
+ ```bash
57
+ npm install -D sass
58
+ # or
59
+ pnpm add -D sass
75
60
  ```
76
- fractalstyler2/
77
- ├─ styles → the full emitted stylesheet (import 'fractalstyler2/styles')
78
- ├─ fractals → the mixin/function API (@use 'fractalstyler2/fractals' as *)
79
- ├─ tokens → just the custom properties (@use 'fractalstyler2/tokens')
80
- └─ (default) → { version, setMode, toggleMode }
61
+
62
+ ### Use from `node_modules`:
63
+
64
+ ```svelte
65
+ <script>
66
+ import 'fractalstyler2/styles';
67
+ </script>
68
+
69
+ <style lang="sass">
70
+ @use 'fractalstyler2/fractals' as *
71
+
72
+ .card
73
+ +surface(surface, s, 12)
74
+ +stack(s)
75
+ </style>
81
76
  ```
82
77
 
83
- Source layout: `src/lib/fractals/` (config, tokens, base, responsive, atoms,
84
- molecules, utilities), `src/lib/components/` (blocks, layouts),
85
- `src/lib/styles/` (the emit entry).
78
+ ---
86
79
 
87
- ## Color mode
80
+ ## The Model
88
81
 
89
- Light is the marker-free default (SSR-safe). Dark comes from
90
- `prefers-color-scheme` and from an explicit `data-mode="dark"` on `<html>`:
82
+ A fractal is a mixin: a tiny reusable styling decision that composes other
83
+ fractals. They form four self-similar tiers each tier is "a recipe of the one
84
+ below":
85
+
86
+ | Tier | What | Examples |
87
+ | --- | --- | --- |
88
+ | **Config** | scales-as-data + resolvers | `space()`, `radius()`, `align()`, `$breakpoints` |
89
+ | **Atoms** | one decision each | `+box` `+row` `+gap` `+pad` `+border` `+radius` `+bg` `+ink` `+type` `+sticky` |
90
+ | **Molecules** | graphs of atoms | `+stack` `+cluster` `+cover` `+frame` `+surface` `+cols` `+auto-grid` |
91
+ | **Components / Layouts** | graphs of molecules | `.card` `.button` · `.grid-3` `.hero` `.holy-grail` `.docs` `.app-shell` |
92
+
93
+ The one idea that makes it click:
94
+
95
+ > **A utility class and a semantic component are the same fractal, consumed two ways.**
96
+ > `.gap-m { +gap(m) }` binds the fractal to markup; `.hero { +cover; +stack(m) }`
97
+ > composes it into a component. One vocabulary, you pick where each is used.
98
+
99
+ ---
100
+
101
+ ## Color Mode
102
+
103
+ Light is the marker-free default (SSR-safe). Dark comes from `prefers-color-scheme` and from an explicit `data-mode="dark"` on `<html>`:
91
104
 
92
105
  ```js
93
106
  import { toggleMode, setMode } from 'fractalstyler2';
94
107
  toggleMode(); // flip light/dark
95
- setMode('dark'); // force
108
+ setMode('dark'); // force mode
96
109
  ```
97
110
 
98
- ## Included layouts
111
+ ---
99
112
 
100
- `.grid-3` (responsive 1→2→3), `.card-grid` (intrinsic auto-fit), `.hero`,
101
- `.holy-grail`, `.docs`, `.app-shell` — each a few fractal calls in
102
- `src/lib/components/_layouts.sass`.
103
-
104
- ## Develop
113
+ ## CLI Options
105
114
 
106
115
  ```bash
107
- pnpm install
108
- pnpm dev # demo showcase at /
109
- pnpm run prepack # build the distributable package into dist/
116
+ fractalstyler2 init [dest] [options]
117
+
118
+ Arguments:
119
+ dest Target directory for SASS partials (default: src/lib/styles)
120
+
121
+ Options:
122
+ -f, --force Overwrite files if they already exist
123
+ -h, --help Show help message
110
124
  ```
111
125
 
126
+ ---
127
+
112
128
  ## License
113
129
 
114
130
  MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync, mkdirSync, readdirSync, copyFileSync } from 'node:fs';
3
+ import { dirname, join, resolve, relative } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import process from 'node:process';
6
+ function getTemplatesDir() {
7
+ const HERE = dirname(fileURLToPath(import.meta.url));
8
+ const candidates = [
9
+ join(HERE, '..', 'templates'),
10
+ join(HERE, '..', '..', 'templates'),
11
+ join(HERE, 'templates')
12
+ ];
13
+ for (const candidate of candidates) {
14
+ if (existsSync(candidate))
15
+ return candidate;
16
+ }
17
+ throw new Error(`Templates directory not found. Searched in: ${candidates.join(', ')}`);
18
+ }
19
+ function printUsage() {
20
+ console.log(`
21
+ fractalstyler2 — SASS fractal design system scaffolder
22
+
23
+ Usage:
24
+ npx fractalstyler2 init [dest] [options]
25
+
26
+ Arguments:
27
+ dest Target directory for SASS partials (default: src/lib/styles)
28
+
29
+ Options:
30
+ -f, --force Overwrite files if they already exist
31
+ -h, --help Show this help message
32
+
33
+ Examples:
34
+ npx fractalstyler2 init
35
+ npx fractalstyler2 init src/lib/styles --force
36
+ npx fractalstyler2 init src/styles
37
+ `);
38
+ }
39
+ function init(destArg, force) {
40
+ const dest = destArg ?? 'src/lib/styles';
41
+ const cwd = process.cwd();
42
+ const targetDir = resolve(cwd, dest);
43
+ console.log(`\n▲ fractalstyler2 init\n`);
44
+ console.log(`Scaffolding SASS design system into: ${dest}\n`);
45
+ mkdirSync(targetDir, { recursive: true });
46
+ const templatesDir = getTemplatesDir();
47
+ const files = readdirSync(templatesDir).filter((f) => f.endsWith('.sass'));
48
+ let created = 0;
49
+ let overwritten = 0;
50
+ let skipped = 0;
51
+ for (const file of files) {
52
+ const targetFile = join(targetDir, file);
53
+ const relPath = relative(cwd, targetFile);
54
+ if (existsSync(targetFile)) {
55
+ if (force) {
56
+ copyFileSync(join(templatesDir, file), targetFile);
57
+ console.log(` \x1b[33moverwrite\x1b[0m ${relPath}`);
58
+ overwritten++;
59
+ }
60
+ else {
61
+ console.log(` \x1b[90mskip\x1b[0m ${relPath} (already exists, use --force to overwrite)`);
62
+ skipped++;
63
+ }
64
+ }
65
+ else {
66
+ copyFileSync(join(templatesDir, file), targetFile);
67
+ console.log(` \x1b[32mcreate\x1b[0m ${relPath}`);
68
+ created++;
69
+ }
70
+ }
71
+ console.log(`\nDone: ${created} created, ${overwritten} overwritten, ${skipped} skipped.\n`);
72
+ const importPath = dest === 'src/lib/styles' ? '$lib/styles/index.sass' : `${dest}/index.sass`;
73
+ const fractalsPath = dest === 'src/lib/styles' ? '$lib/styles/fractals' : `${dest}/fractals`;
74
+ console.log(`Next steps:
75
+ 1. Import the stylesheet once globally (e.g. in src/routes/+layout.svelte):
76
+ <script>
77
+ import '${importPath}';
78
+ </script>
79
+
80
+ 2. Compose your components with fractal mixins:
81
+ <style lang="sass">
82
+ @use '${fractalsPath}' as *
83
+
84
+ .card
85
+ +surface(surface, s, 12)
86
+ +stack(s)
87
+ </style>
88
+ `);
89
+ }
90
+ const args = process.argv.slice(2);
91
+ const showHelp = args.includes('-h') || args.includes('--help');
92
+ const force = args.includes('-f') || args.includes('--force');
93
+ const positional = args.filter((a) => !a.startsWith('-'));
94
+ const command = positional[0];
95
+ if (showHelp || (command && command !== 'init')) {
96
+ if (command && command !== 'init') {
97
+ console.error(`Unknown command: ${command}`);
98
+ }
99
+ printUsage();
100
+ process.exit(command && command !== 'init' ? 1 : 0);
101
+ }
102
+ else if (command === 'init') {
103
+ init(positional[1], force);
104
+ }
105
+ else {
106
+ // Default to init if no subcommand given (e.g., `npx fractalstyler2`)
107
+ init(positional[0], force);
108
+ }
@@ -4,7 +4,7 @@
4
4
  // State is expressed with data-*/aria-*, never modifier classes.
5
5
  // =============================================================================
6
6
 
7
- @use '../fractals' as *
7
+ @use 'fractals' as *
8
8
 
9
9
  .card
10
10
  +surface(surface, s, 12)
@@ -1,7 +1,9 @@
1
1
  // =============================================================================
2
2
  // FRACTALS — the pure API barrel. Emits NO css on its own.
3
3
  // -----------------------------------------------------------------------------
4
- // In any component partial: @use '../fractals' as *
4
+ // In any component partial or Svelte component:
5
+ // @use '$lib/styles/fractals' as *
6
+ // (or @use './fractals' as *)
5
7
  // then call fractals freely: +surface(...) +stack(...) space(m) ...
6
8
  // =============================================================================
7
9
 
@@ -4,7 +4,7 @@
4
4
  // hero, a holy-grail, a docs template. Each is a short composition of fractals.
5
5
  // =============================================================================
6
6
 
7
- @use '../fractals' as *
7
+ @use 'fractals' as *
8
8
 
9
9
  // 1. Responsive grid of 3 columns — 1 → 2 → 3 across breakpoints.
10
10
  .grid-3
@@ -2,18 +2,19 @@
2
2
  // STYLES ENTRY — the full emitted stylesheet in cascade order.
3
3
  // -----------------------------------------------------------------------------
4
4
  // 1. tokens the CSS custom properties (only literal values)
5
- // 2. utilities atom fractals projected to markup classes (optional layer)
6
- // 3. blocks components composed from fractals
7
- // 4. layouts page templates composed from fractals
5
+ // 2. base fluid reset
6
+ // 3. utilities atom fractals projected to markup classes (optional layer)
7
+ // 4. blocks components composed from fractals
8
+ // 5. layouts page templates composed from fractals
8
9
  //
9
- // Consume from a SvelteKit app: import 'fractalstyler2/styles'
10
- // or, from SASS: @use 'fractalstyler2/styles'
10
+ // Consume from a SvelteKit app: import '$lib/styles/index.sass'
11
+ // or from package: import 'fractalstyler2/styles'
11
12
  // The fractal mixins/functions themselves emit nothing until called, so output
12
13
  // contains only what you use.
13
14
  // =============================================================================
14
15
 
15
- @use '../fractals/tokens'
16
- @use '../fractals/base'
17
- @use '../fractals/utilities'
18
- @use '../components/blocks'
19
- @use '../components/layouts'
16
+ @use './tokens'
17
+ @use './base'
18
+ @use './utilities'
19
+ @use './blocks'
20
+ @use './layouts'
package/package.json CHANGED
@@ -1,20 +1,25 @@
1
1
  {
2
2
  "name": "fractalstyler2",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "A fractal-composition styling system for SvelteKit — every style unit is a SASS mixin, and components and layouts are recipes of smaller fractals.",
5
+ "bin": {
6
+ "fractalstyler2": "./dist/cli.js",
7
+ "fractalstyler": "./dist/cli.js"
8
+ },
5
9
  "scripts": {
6
10
  "dev": "vite dev",
7
11
  "build": "vite build && npm run prepack",
8
12
  "preview": "vite preview",
9
13
  "prepare": "svelte-kit sync || echo ''",
10
- "prepack": "svelte-kit sync && svelte-package && publint",
14
+ "prepack": "svelte-kit sync && svelte-package && chmod +x dist/cli.js && publint",
11
15
  "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
12
16
  "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
13
17
  },
14
18
  "files": [
15
19
  "dist",
16
20
  "!dist/**/*.test.*",
17
- "!dist/**/*.spec.*"
21
+ "!dist/**/*.spec.*",
22
+ "templates"
18
23
  ],
19
24
  "sideEffects": [
20
25
  "**/*.css"
@@ -28,8 +33,9 @@
28
33
  "svelte": "./dist/index.js"
29
34
  },
30
35
  "./styles": "./dist/styles/index.sass",
31
- "./fractals": "./dist/fractals/index.sass",
32
- "./tokens": "./dist/fractals/_tokens.sass",
36
+ "./styles/*": "./dist/styles/*",
37
+ "./fractals": "./dist/styles/_fractals.sass",
38
+ "./tokens": "./dist/styles/_tokens.sass",
33
39
  "./package.json": "./package.json"
34
40
  },
35
41
  "peerDependencies": {
@@ -40,6 +46,7 @@
40
46
  "@sveltejs/kit": "^2.63.0",
41
47
  "@sveltejs/package": "^2.5.8",
42
48
  "@sveltejs/vite-plugin-svelte": "^7.1.2",
49
+ "@types/node": "^26.2.0",
43
50
  "publint": "^0.3.21",
44
51
  "sass": "^1.102.0",
45
52
  "svelte": "^5.56.1",
@@ -0,0 +1,155 @@
1
+ // =============================================================================
2
+ // ATOM FRACTALS — the indivisible units. One visual decision each.
3
+ // -----------------------------------------------------------------------------
4
+ // Every atom is a mixin. Call it inside a class to compose, or let
5
+ // _utilities.sass project it to a utility class. Same fractal, two consumers.
6
+ // =============================================================================
7
+
8
+ @use 'config' as *
9
+
10
+ // --- Flow: the two axes of layout ------------------------------------------
11
+ // A box is a vertical stack, a row is horizontal. Optional semantic alignment:
12
+ // +box(center) → items centered on the cross axis
13
+ // +row(between, center) → spread on main axis, centered on cross axis
14
+ =box($x: null, $y: null)
15
+ display: flex
16
+ flex-direction: column
17
+ @if $x
18
+ align-items: align($x)
19
+ @if $y
20
+ justify-content: align($y)
21
+
22
+ =row($x: null, $y: null)
23
+ display: flex
24
+ flex-direction: row
25
+ @if $x
26
+ justify-content: align($x)
27
+ @if $y
28
+ align-items: align($y)
29
+
30
+ =wrap
31
+ flex-wrap: wrap
32
+
33
+ =grid($cols: 1)
34
+ display: grid
35
+ grid-template-columns: repeat($cols, minmax(0, 1fr))
36
+
37
+ // A grid that reflows on its own — no breakpoints, no counting columns.
38
+ =auto-grid($min: 15rem, $gap: s)
39
+ display: grid
40
+ grid-template-columns: repeat(auto-fit, minmax(min(#{$min}, 100%), 1fr))
41
+ gap: space($gap)
42
+
43
+ // Dead-center anything (grid is the one-liner that works for a single child).
44
+ =center
45
+ display: grid
46
+ place-items: center
47
+
48
+ // --- Spacing ---------------------------------------------------------------
49
+ =gap($v: s)
50
+ gap: space($v)
51
+
52
+ =pad($v: s)
53
+ padding: space($v)
54
+
55
+ =px($v: s)
56
+ padding-inline: space($v)
57
+
58
+ =py($v: s)
59
+ padding-block: space($v)
60
+
61
+ =mx-auto
62
+ margin-inline: auto
63
+
64
+ =my-auto
65
+ margin-block: auto
66
+
67
+ // --- Size ------------------------------------------------------------------
68
+ =w($v: 100%)
69
+ width: $v
70
+
71
+ =h($v: 100%)
72
+ height: $v
73
+
74
+ =full
75
+ width: 100%
76
+ height: 100%
77
+
78
+ =square($v)
79
+ width: $v
80
+ height: $v
81
+
82
+ =grow($n: 1)
83
+ flex-grow: $n
84
+
85
+ =shrink($n: 0)
86
+ flex-shrink: $n
87
+
88
+ =min0
89
+ min-width: 0
90
+ min-height: 0
91
+
92
+ // --- Surface & skin --------------------------------------------------------
93
+ =bg($role: surface)
94
+ background-color: surface($role)
95
+
96
+ =ink($role: primary)
97
+ color: ink($role)
98
+
99
+ =border($side: all, $color: var(--border))
100
+ @if $side == all
101
+ border: 1px solid $color
102
+ @else
103
+ border-#{$side}: 1px solid $color
104
+
105
+ =radius($v: 12)
106
+ border-radius: radius($v)
107
+
108
+ =shadow($v: md)
109
+ box-shadow: shadow($v)
110
+
111
+ // --- Position --------------------------------------------------------------
112
+ =relative
113
+ position: relative
114
+
115
+ =absolute($inset: null)
116
+ position: absolute
117
+ @if $inset
118
+ inset: $inset
119
+
120
+ =sticky($top: 0)
121
+ position: sticky
122
+ top: $top
123
+
124
+ =fill
125
+ position: absolute
126
+ inset: 0
127
+
128
+ // --- Type ------------------------------------------------------------------
129
+ =type($v)
130
+ font-size: text-size($v)
131
+
132
+ =weight($w: 500)
133
+ font-weight: $w
134
+
135
+ =leading($lh: 1.5)
136
+ line-height: $lh
137
+
138
+ =truncate
139
+ overflow: hidden
140
+ white-space: nowrap
141
+ text-overflow: ellipsis
142
+
143
+ =clamp-lines($n: 2)
144
+ display: -webkit-box
145
+ -webkit-line-clamp: $n
146
+ -webkit-box-orient: vertical
147
+ overflow: hidden
148
+
149
+ // --- Motion ----------------------------------------------------------------
150
+ =transition($props: all, $dur: 150ms, $ease: ease)
151
+ transition: $props $dur $ease
152
+
153
+ =ring($color: var(--ring))
154
+ outline: 2px solid $color
155
+ outline-offset: 1px
@@ -0,0 +1,43 @@
1
+ // =============================================================================
2
+ // BASE — a minimal, opinionated reset so the tokens actually reach the page.
3
+ // Kept tiny: box model, sane media defaults, and wiring body to the palette.
4
+ // =============================================================================
5
+
6
+ *, *::before, *::after
7
+ box-sizing: border-box
8
+
9
+ html
10
+ -webkit-text-size-adjust: 100%
11
+
12
+ body
13
+ margin: 0
14
+ min-height: 100vh
15
+ font-family: var(--font-sans)
16
+ font-size: var(--text-md)
17
+ line-height: 1.5
18
+ color: var(--text-primary)
19
+ background-color: var(--bg)
20
+ -webkit-font-smoothing: antialiased
21
+
22
+ :where(h1, h2, h3, h4, h5, h6, p, figure, blockquote)
23
+ margin: 0
24
+
25
+ :where(h1, h2, h3, h4)
26
+ line-height: 1.15
27
+ text-wrap: balance
28
+
29
+ :where(img, picture, video, canvas, svg)
30
+ display: block
31
+ max-width: 100%
32
+
33
+ :where(a)
34
+ color: inherit
35
+ text-decoration-color: var(--border-strong)
36
+
37
+ :where(button, input, select, textarea)
38
+ font: inherit
39
+ color: inherit
40
+
41
+ :where(:focus-visible)
42
+ outline: 2px solid var(--ring)
43
+ outline-offset: 2px
@@ -0,0 +1,88 @@
1
+ // =============================================================================
2
+ // BLOCKS — components as recipes of fractals. Note how little CSS is here:
3
+ // each block is a handful of fractal calls plus its own genuinely-unique lines.
4
+ // State is expressed with data-*/aria-*, never modifier classes.
5
+ // =============================================================================
6
+
7
+ @use 'fractals' as *
8
+
9
+ .card
10
+ +surface(surface, s, 12)
11
+ +stack(s)
12
+ &[data-elevated]
13
+ +shadow(md)
14
+
15
+ .panel
16
+ +surface(raised, m, 16)
17
+ +stack(m)
18
+
19
+ .badge
20
+ +row(center, center)
21
+ display: inline-flex
22
+ +px(2xs)
23
+ +type(xs)
24
+ +weight(500)
25
+ +radius(full)
26
+ +bg(raised)
27
+ +ink(secondary)
28
+ padding-block: 2px
29
+
30
+ .avatar
31
+ +center
32
+ +square(var(--avatar-size, 40px))
33
+ +radius(full)
34
+ +bg(raised)
35
+ +ink(secondary)
36
+ overflow: hidden
37
+
38
+ .input
39
+ display: block
40
+ +w(100%)
41
+ +px(2xs)
42
+ +type(md)
43
+ +leading(1.5)
44
+ +border
45
+ +radius(6)
46
+ +bg(bg)
47
+ +ink(primary)
48
+ padding-block: 8px
49
+ &:focus-visible
50
+ +ring
51
+
52
+ .button
53
+ +row(center, center)
54
+ +gap(2xs)
55
+ +px(s)
56
+ +radius(6)
57
+ +weight(500)
58
+ +transition(background-color)
59
+ cursor: pointer
60
+ padding-block: 8px
61
+ user-select: none
62
+ // Exceptions: variants live on data-variant, not in the class name.
63
+ &[data-variant='primary']
64
+ background: var(--theme)
65
+ color: var(--text-inverse)
66
+ &:hover
67
+ background: var(--theme-hover)
68
+ &[data-variant='ghost']
69
+ background: transparent
70
+ +ink(secondary)
71
+ &:hover
72
+ +bg(raised)
73
+
74
+ .divider
75
+ border: none
76
+ +border(top)
77
+ margin-block: space(s)
78
+
79
+ .kbd
80
+ display: inline-block
81
+ +px(3xs)
82
+ +type(xs)
83
+ +leading(1)
84
+ +radius(4)
85
+ +bg(raised)
86
+ border: 1px solid var(--border-strong)
87
+ font-family: var(--font-mono)
88
+ padding-block: 2px
@@ -0,0 +1,78 @@
1
+ // =============================================================================
2
+ // CONFIG — the finite vocabulary every fractal draws from.
3
+ // -----------------------------------------------------------------------------
4
+ // Scales live here as Sass data; resolvers turn a keyword-or-raw value into the
5
+ // right token var() or unit. Fractals never hardcode a px or a token name —
6
+ // they route through space(), radius(), etc. so the system speaks one language.
7
+ // =============================================================================
8
+
9
+ @use 'sass:map'
10
+ @use 'sass:math'
11
+ @use 'sass:meta'
12
+ @use 'sass:list'
13
+
14
+ // --- Scales (mirror the custom properties in _tokens.sass) --------------------
15
+ $breakpoints: (sm: 640px, md: 768px, lg: 1024px, xl: 1240px)
16
+
17
+ $space-steps: 3xs 2xs xs s m l xl 2xl 3xl s-l
18
+ $radius-steps: 0 2 4 6 8 12 16 24 full
19
+ $text-steps: xs sm md lg xl 2xl 3xl 4xl
20
+ $shadow-steps: sm md lg
21
+ $surface-roles: bg surface raised
22
+ $ink-roles: primary secondary muted inverse
23
+
24
+ $align-map: (start: flex-start, end: flex-end, center: center, between: space-between, around: space-around, evenly: space-evenly, stretch: stretch, baseline: baseline)
25
+
26
+ // --- Resolvers ----------------------------------------------------------------
27
+
28
+ // space(m) → var(--space-m) | space(18) → 18px | space(2rem) → 2rem
29
+ @function space($v)
30
+ @if $v == null
31
+ @return null
32
+ @else if list.index($space-steps, $v)
33
+ @return var(--space-#{$v})
34
+ @else if meta.type-of($v) == number and math.is-unitless($v)
35
+ @return #{$v}px
36
+ @else
37
+ @return $v
38
+
39
+ @function radius($v)
40
+ @if list.index($radius-steps, $v)
41
+ @return var(--radius-#{$v})
42
+ @else if meta.type-of($v) == number and math.is-unitless($v)
43
+ @return #{$v}px
44
+ @else
45
+ @return $v
46
+
47
+ @function text-size($v)
48
+ @if list.index($text-steps, $v)
49
+ @return var(--text-#{$v})
50
+ @else
51
+ @return $v
52
+
53
+ @function shadow($v)
54
+ @if list.index($shadow-steps, $v)
55
+ @return var(--shadow-#{$v})
56
+ @else
57
+ @return $v
58
+
59
+ @function surface($role)
60
+ @if $role == bg
61
+ @return var(--bg)
62
+ @else
63
+ @return var(--bg-#{$role})
64
+
65
+ @function ink($role)
66
+ @if $role == primary
67
+ @return var(--text-primary)
68
+ @else
69
+ @return var(--text-#{$role})
70
+
71
+ @function align($v)
72
+ $m: map.get($align-map, $v)
73
+ @if $m
74
+ @return $m
75
+ @return $v
76
+
77
+ @function bp($name)
78
+ @return map.get($breakpoints, $name)
@@ -0,0 +1,13 @@
1
+ // =============================================================================
2
+ // FRACTALS — the pure API barrel. Emits NO css on its own.
3
+ // -----------------------------------------------------------------------------
4
+ // In any component partial or Svelte component:
5
+ // @use '$lib/styles/fractals' as *
6
+ // (or @use './fractals' as *)
7
+ // then call fractals freely: +surface(...) +stack(...) space(m) ...
8
+ // =============================================================================
9
+
10
+ @forward 'config'
11
+ @forward 'responsive'
12
+ @forward 'atoms'
13
+ @forward 'molecules'
@@ -0,0 +1,108 @@
1
+ // =============================================================================
2
+ // LAYOUTS — the largest fractals. Same recipe move, page scale.
3
+ // These are the concrete deliverables you named: a responsive 3-col grid, a
4
+ // hero, a holy-grail, a docs template. Each is a short composition of fractals.
5
+ // =============================================================================
6
+
7
+ @use 'fractals' as *
8
+
9
+ // 1. Responsive grid of 3 columns — 1 → 2 → 3 across breakpoints.
10
+ .grid-3
11
+ +cols((base: 1, sm: 2, lg: 3), m)
12
+
13
+ // A grid that never needs breakpoints: it fits as many columns as will hold
14
+ // the min track. Reach for this before .grid-3 when column count is negotiable.
15
+ .card-grid
16
+ +auto-grid(16rem, m)
17
+
18
+ // 2. Hero — full-viewport cover with a centered, measured message.
19
+ .hero
20
+ +cover(80vh, xl)
21
+ > .center
22
+ +stack(m, center)
23
+ text-align: center
24
+ max-width: 45ch
25
+
26
+ // 3. Holy grail — header / (nav · main · aside) / footer.
27
+ .holy-grail
28
+ display: grid
29
+ min-height: 100vh
30
+ grid-template-rows: auto 1fr auto
31
+ grid-template-areas: 'header' 'main' 'footer'
32
+ > .hg-header
33
+ grid-area: header
34
+ > .hg-footer
35
+ grid-area: footer
36
+ > .hg-body
37
+ grid-area: main
38
+ display: grid
39
+ grid-template-columns: 1fr
40
+ +gap(m)
41
+ +pad(m)
42
+ +at(lg)
43
+ > .hg-body
44
+ grid-template-columns: var(--nav-w, 220px) minmax(0, 1fr) var(--aside-w, 260px)
45
+ > .hg-nav
46
+ +sticky(var(--space-m))
47
+ align-self: start
48
+ > .hg-aside
49
+ +sticky(var(--space-m))
50
+ align-self: start
51
+
52
+ // 4. Docs template — sidebar nav + reading column + on-page TOC.
53
+ .docs
54
+ display: grid
55
+ min-height: 100vh
56
+ grid-template-columns: 1fr
57
+ > .docs-nav
58
+ display: none
59
+ > .docs-toc
60
+ display: none
61
+ > .docs-main
62
+ +min0
63
+ +stack(m)
64
+ +center-column(72ch, s-l)
65
+ +py(l)
66
+ +at(md)
67
+ grid-template-columns: var(--docs-nav-w, 240px) minmax(0, 1fr)
68
+ > .docs-nav
69
+ +box
70
+ +sticky(0)
71
+ +py(l)
72
+ +px(s)
73
+ height: 100vh
74
+ overflow-y: auto
75
+ +border(right)
76
+ +at(xl)
77
+ grid-template-columns: var(--docs-nav-w, 240px) minmax(0, 1fr) var(--docs-toc-w, 220px)
78
+ > .docs-toc
79
+ +box
80
+ +sticky(0)
81
+ +py(l)
82
+ +px(s)
83
+ height: 100vh
84
+ overflow-y: auto
85
+ +ink(secondary)
86
+
87
+ // 5. App shell — sticky header, fluid body, footer. The frame most apps live in.
88
+ .app-shell
89
+ +box
90
+ +relative
91
+ isolation: isolate
92
+ min-height: 100vh
93
+ > .app-header
94
+ +row(null, center)
95
+ +sticky(0)
96
+ +px(m)
97
+ z-index: var(--z-sticky)
98
+ height: var(--header-height)
99
+ +bg(surface)
100
+ +border(bottom)
101
+ > .app-main
102
+ +grow
103
+ +min0
104
+ > .app-footer
105
+ +row(null, center)
106
+ +px(m)
107
+ min-height: var(--footer-height)
108
+ +border(top)
@@ -0,0 +1,93 @@
1
+ // =============================================================================
2
+ // MOLECULE FRACTALS — self-similar: each is a small graph of atom fractals.
3
+ // -----------------------------------------------------------------------------
4
+ // This is the payoff of the model. A molecule reads like a recipe of atoms,
5
+ // and a component (next layer up) reads like a recipe of molecules. Same move
6
+ // at every scale — that is the "fractal" in fractalstyler2.
7
+ // =============================================================================
8
+
9
+ @use 'config' as *
10
+ @use 'atoms' as *
11
+ @use 'responsive' as *
12
+
13
+ // Stack — vertical rhythm with one shared gap.
14
+ =stack($gap: xs, $x: null)
15
+ +box($x)
16
+ +gap($gap)
17
+
18
+ // Cluster — wrapping row of chips/tags/buttons.
19
+ =cluster($gap: xs, $x: start, $y: center)
20
+ +row($x, $y)
21
+ +wrap
22
+ +gap($gap)
23
+
24
+ // Center — a centered reading column bounded by a measure.
25
+ =center-column($max: var(--measure, 60ch), $pad: s)
26
+ max-width: $max
27
+ +mx-auto
28
+ +px($pad)
29
+
30
+ // Cover — fills a min-height with a centered focal child.
31
+ =cover($min: 100vh, $pad: s)
32
+ +box
33
+ min-height: $min
34
+ +pad($pad)
35
+ > *
36
+ margin-block: 0
37
+ > .center
38
+ +my-auto
39
+
40
+ // Frame — fixed aspect-ratio media box.
41
+ =frame($ratio: 16 / 9)
42
+ aspect-ratio: $ratio
43
+ overflow: hidden
44
+ > :is(img, video, iframe)
45
+ +full
46
+ object-fit: cover
47
+
48
+ // Reel — horizontal scroll-snap rail.
49
+ =reel($gap: xs)
50
+ +row
51
+ +gap($gap)
52
+ overflow-x: auto
53
+ overscroll-behavior-inline: contain
54
+ scroll-snap-type: inline mandatory
55
+ > *
56
+ scroll-snap-align: start
57
+ flex: 0 0 auto
58
+
59
+ // Sidebar — an intrinsic rail beside a fluid main; wraps when tight.
60
+ =with-sidebar($rail: 240px, $gap: s, $min: 60%)
61
+ +row
62
+ +wrap
63
+ +gap($gap)
64
+ > .rail
65
+ flex-basis: $rail
66
+ flex-grow: 1
67
+ > .flow
68
+ flex-basis: 0
69
+ flex-grow: 999
70
+ min-width: $min
71
+
72
+ // Surface — the "material" fractal: skin + elevation in one call.
73
+ // The building block of every card/panel/popover.
74
+ =surface($bg: surface, $pad: s, $radius: 12, $elevation: none)
75
+ +bg($bg)
76
+ +border
77
+ +radius($radius)
78
+ +pad($pad)
79
+ @if $elevation != none
80
+ +shadow($elevation)
81
+
82
+ // Responsive column grid from a per-breakpoint map:
83
+ // +cols((base: 1, sm: 2, lg: 3))
84
+ =cols($map, $gap: s)
85
+ display: grid
86
+ grid-auto-flow: row
87
+ +gap($gap)
88
+ @each $bp, $n in $map
89
+ @if $bp == base
90
+ grid-template-columns: repeat($n, minmax(0, 1fr))
91
+ @else
92
+ +at($bp)
93
+ grid-template-columns: repeat($n, minmax(0, 1fr))
@@ -0,0 +1,43 @@
1
+ // =============================================================================
2
+ // RESPONSIVE FRACTALS — the units that let any other fractal grow with the page.
3
+ // -----------------------------------------------------------------------------
4
+ // These are self-similar too: +at(md) wraps any block of fractal calls in a
5
+ // breakpoint, so a "responsive component" is just a component whose fractals
6
+ // are re-stated inside +at(...).
7
+ // =============================================================================
8
+
9
+ @use 'sass:map'
10
+ @use 'config' as *
11
+
12
+ // +at(md) — mobile-first min-width query by name (sm/md/lg/xl) or raw length.
13
+ =at($name)
14
+ $edge: $name
15
+ @if map.has-key($breakpoints, $name)
16
+ $edge: bp($name)
17
+ @media (min-width: #{$edge})
18
+ @content
19
+
20
+ // +until(md) — max-width query (one below the named edge).
21
+ =until($name)
22
+ $edge: $name
23
+ @if map.has-key($breakpoints, $name)
24
+ $edge: bp($name)
25
+ @media (max-width: #{$edge})
26
+ @content
27
+
28
+ // Container-query fractals — component-scoped responsiveness.
29
+ =cq
30
+ container-type: inline-size
31
+
32
+ =cq-at($width)
33
+ @container (min-width: #{$width})
34
+ @content
35
+
36
+ =cq-until($width)
37
+ @container (max-width: #{$width})
38
+ @content
39
+
40
+ // Motion / preference-aware fractal.
41
+ =reduce-motion
42
+ @media (prefers-reduced-motion: reduce)
43
+ @content
@@ -0,0 +1,127 @@
1
+ // =============================================================================
2
+ // TOKENS — the only place literal values live. Everything else is a fractal
3
+ // that consumes these custom properties. Light is the marker-free default so
4
+ // tokens stay defined during SSR and with JS disabled; dark comes from
5
+ // prefers-color-scheme and from an explicit [data-mode='dark'].
6
+ // =============================================================================
7
+
8
+ :root
9
+ color-scheme: light
10
+
11
+ // Fonts
12
+ --font-sans: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif
13
+ --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace
14
+
15
+ // Fluid type scale (Utopia 360→1240)
16
+ --text-xs: 0.75rem
17
+ --text-sm: clamp(0.9375rem, 0.9119rem + 0.1136vw, 1rem)
18
+ --text-md: clamp(1.125rem, 1.0739rem + 0.2273vw, 1.25rem)
19
+ --text-lg: clamp(1.35rem, 1.2631rem + 0.3864vw, 1.5625rem)
20
+ --text-xl: clamp(1.62rem, 1.4837rem + 0.6057vw, 1.9531rem)
21
+ --text-2xl: clamp(1.944rem, 1.7405rem + 0.9044vw, 2.4414rem)
22
+ --text-3xl: clamp(2.3328rem, 2.0387rem + 1.3072vw, 3.0518rem)
23
+ --text-4xl: clamp(2.7994rem, 2.384rem + 1.8461vw, 3.8147rem)
24
+
25
+ // Fluid space scale
26
+ --space-3xs: clamp(0.3125rem, 0.3125rem + 0vw, 0.3125rem)
27
+ --space-2xs: clamp(0.5625rem, 0.5369rem + 0.1136vw, 0.625rem)
28
+ --space-xs: clamp(0.875rem, 0.8494rem + 0.1136vw, 0.9375rem)
29
+ --space-s: clamp(1.125rem, 1.0739rem + 0.2273vw, 1.25rem)
30
+ --space-m: clamp(1.6875rem, 1.6108rem + 0.3409vw, 1.875rem)
31
+ --space-l: clamp(2.25rem, 2.1477rem + 0.4545vw, 2.5rem)
32
+ --space-xl: clamp(3.375rem, 3.2216rem + 0.6818vw, 3.75rem)
33
+ --space-2xl: clamp(4.5rem, 4.2955rem + 0.9091vw, 5rem)
34
+ --space-3xl: clamp(6.75rem, 6.4432rem + 1.3636vw, 7.5rem)
35
+ --space-s-l: clamp(1.125rem, 0.5625rem + 2.5vw, 2.5rem)
36
+
37
+ // Radius
38
+ --radius-0: 0
39
+ --radius-2: 2px
40
+ --radius-4: 4px
41
+ --radius-6: 6px
42
+ --radius-8: 8px
43
+ --radius-12: 12px
44
+ --radius-16: 16px
45
+ --radius-24: 24px
46
+ --radius-full: 9999px
47
+
48
+ // Shadow
49
+ --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06)
50
+ --shadow-md: 0 4px 12px rgba(15, 23, 42, 0.08)
51
+ --shadow-lg: 0 12px 32px rgba(15, 23, 42, 0.12)
52
+
53
+ // Layering
54
+ --z-base: 0
55
+ --z-raised: 10
56
+ --z-sticky: 100
57
+ --z-modal: 200
58
+ --z-toast: 300
59
+
60
+ // Layout
61
+ --header-height: 64px
62
+ --footer-height: 56px
63
+ --measure: 65ch
64
+
65
+ // Light palette (marker-free default)
66
+ --bg: #fdfefe
67
+ --bg-surface: #f8f7f7
68
+ --bg-raised: #f1f5f9
69
+ --text-primary: #0f172a
70
+ --text-secondary: #5b6472
71
+ --text-muted: #929497
72
+ --text-inverse: #ffffff
73
+ --border: #e2e8f0
74
+ --border-strong: #cbd5e1
75
+ --theme: #007f4e
76
+ --theme-hover: #00663f
77
+ --theme-active: #005031
78
+ --ring: rgba(0, 127, 78, 0.35)
79
+
80
+ @media (prefers-color-scheme: dark)
81
+ :root:not([data-mode='light'])
82
+ color-scheme: dark
83
+ --bg: #131313
84
+ --bg-surface: #1e1e1e
85
+ --bg-raised: #2b2b2b
86
+ --text-primary: #f9fafb
87
+ --text-secondary: #a7adb7
88
+ --text-muted: #6b7280
89
+ --text-inverse: #0b0f17
90
+ --border: #2f3030
91
+ --border-strong: #4a4b4b
92
+ --theme: #10b981
93
+ --theme-hover: #34d399
94
+ --theme-active: #059669
95
+ --ring: rgba(16, 185, 129, 0.4)
96
+
97
+ [data-mode='dark']
98
+ color-scheme: dark
99
+ --bg: #131313
100
+ --bg-surface: #1e1e1e
101
+ --bg-raised: #2b2b2b
102
+ --text-primary: #f9fafb
103
+ --text-secondary: #a7adb7
104
+ --text-muted: #6b7280
105
+ --text-inverse: #0b0f17
106
+ --border: #2f3030
107
+ --border-strong: #4a4b4b
108
+ --theme: #10b981
109
+ --theme-hover: #34d399
110
+ --theme-active: #059669
111
+ --ring: rgba(16, 185, 129, 0.4)
112
+
113
+ [data-mode='light']
114
+ color-scheme: light
115
+ --bg: #fdfefe
116
+ --bg-surface: #f8f7f7
117
+ --bg-raised: #f1f5f9
118
+ --text-primary: #0f172a
119
+ --text-secondary: #5b6472
120
+ --text-muted: #929497
121
+ --text-inverse: #ffffff
122
+ --border: #e2e8f0
123
+ --border-strong: #cbd5e1
124
+ --theme: #007f4e
125
+ --theme-hover: #00663f
126
+ --theme-active: #005031
127
+ --ring: rgba(0, 127, 78, 0.35)
@@ -0,0 +1,125 @@
1
+ // =============================================================================
2
+ // UTILITY PROJECTION — the *other* way to consume a fractal.
3
+ // -----------------------------------------------------------------------------
4
+ // A fractal is a mixin. Here we bind a subset of them to class names so they
5
+ // stay usable straight from markup (`class="box gap-m pad-l"`). This is the
6
+ // key idea: utility classes are not a separate system — they are a generated
7
+ // projection of the exact same fractals your components compose. Emit only the
8
+ // atoms you want in markup; delete this whole file if you go SASS-only.
9
+ // =============================================================================
10
+
11
+ @use 'config' as *
12
+ @use 'atoms' as *
13
+ @use 'molecules' as *
14
+ @use 'responsive' as *
15
+
16
+ // --- Flow ------------------------------------------------------------------
17
+ .box
18
+ +box
19
+ .row
20
+ +row
21
+ &.wrap
22
+ +wrap
23
+
24
+ // Alignment modifiers, semantic and axis-aware.
25
+ .box
26
+ &.xcenter
27
+ align-items: center
28
+ &.xleft
29
+ align-items: flex-start
30
+ &.xright
31
+ align-items: flex-end
32
+ &.ycenter
33
+ justify-content: center
34
+ &.ytop
35
+ justify-content: flex-start
36
+ &.ybot
37
+ justify-content: flex-end
38
+
39
+ .row
40
+ &.ycenter
41
+ align-items: center
42
+ &.ytop
43
+ align-items: flex-start
44
+ &.ybot
45
+ align-items: flex-end
46
+ &.xbetween
47
+ justify-content: space-between
48
+ &.xevenly
49
+ justify-content: space-evenly
50
+ &.xleft
51
+ justify-content: flex-start
52
+ &.xright
53
+ justify-content: flex-end
54
+
55
+ // Fixed column grids.
56
+ @for $n from 1 through 6
57
+ .grid-cols-#{$n}
58
+ +grid($n)
59
+
60
+ .center
61
+ +center
62
+
63
+ // --- Spacing scale → gap-* / pad-* -----------------------------------------
64
+ @each $s in $space-steps
65
+ .gap-#{$s}
66
+ +gap($s)
67
+ .pad-#{$s}
68
+ +pad($s)
69
+ .px-#{$s}
70
+ +px($s)
71
+ .py-#{$s}
72
+ +py($s)
73
+
74
+ // --- Radius / shadow / surface ---------------------------------------------
75
+ @each $r in $radius-steps
76
+ .radius-#{$r}
77
+ +radius($r)
78
+
79
+ @each $s in $shadow-steps
80
+ .shadow-#{$s}
81
+ +shadow($s)
82
+
83
+ @each $role in $surface-roles
84
+ .bg-#{$role}
85
+ +bg($role)
86
+
87
+ .border
88
+ +border
89
+ @each $side in top right bottom left
90
+ .border-#{$side}
91
+ +border($side)
92
+
93
+ // --- Type ------------------------------------------------------------------
94
+ @each $t in $text-steps
95
+ .text-#{$t}
96
+ +type($t)
97
+
98
+ .truncate
99
+ +truncate
100
+
101
+ // Semantic type primitives — so you stop retyping `.text-sm .lh15 .muted`.
102
+ .body
103
+ +type(md)
104
+ +leading(1.6)
105
+ +ink(primary)
106
+ .muted
107
+ +ink(secondary)
108
+ .eyebrow
109
+ +type(sm)
110
+ +ink(muted)
111
+ text-transform: uppercase
112
+ letter-spacing: 0.06em
113
+ font-weight: 500
114
+
115
+ // --- Sizing shortcuts ------------------------------------------------------
116
+ .wfull
117
+ +w(100%)
118
+ .hfull
119
+ +h(100%)
120
+ .full
121
+ +full
122
+ .grow
123
+ +grow
124
+ .min0
125
+ +min0
@@ -0,0 +1,20 @@
1
+ // =============================================================================
2
+ // STYLES ENTRY — the full emitted stylesheet in cascade order.
3
+ // -----------------------------------------------------------------------------
4
+ // 1. tokens the CSS custom properties (only literal values)
5
+ // 2. base fluid reset
6
+ // 3. utilities atom fractals projected to markup classes (optional layer)
7
+ // 4. blocks components composed from fractals
8
+ // 5. layouts page templates composed from fractals
9
+ //
10
+ // Consume from a SvelteKit app: import '$lib/styles/index.sass'
11
+ // or from package: import 'fractalstyler2/styles'
12
+ // The fractal mixins/functions themselves emit nothing until called, so output
13
+ // contains only what you use.
14
+ // =============================================================================
15
+
16
+ @use './tokens'
17
+ @use './base'
18
+ @use './utilities'
19
+ @use './blocks'
20
+ @use './layouts'
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes