fractalstyler2 0.1.0 → 0.3.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 +60 -58
- package/dist/cli.js +47 -9
- package/dist/index.d.ts +32 -1
- package/dist/index.js +73 -4
- package/dist/mcp/export.d.ts +13 -0
- package/dist/mcp/export.js +76 -0
- package/dist/mcp/schemas/compile_fractals.json +20 -0
- package/dist/mcp/schemas/css_to_fractals.json +16 -0
- package/dist/mcp/schemas/generate_component.json +45 -0
- package/dist/mcp/schemas/get_design_tokens.json +23 -0
- package/dist/mcp/schemas/instructions.md +18 -0
- package/dist/mcp/schemas/list_fractals.json +20 -0
- package/dist/mcp/schemas/snap_to_tokens.json +25 -0
- package/dist/mcp/schemas/validate_recipe.json +16 -0
- package/dist/mcp/server.js +28 -12
- package/dist/styles/_00_tokens.sass +177 -0
- package/{templates/_config.sass → dist/styles/_01_config.sass} +11 -5
- package/dist/styles/_02_fonts.sass +13 -0
- package/dist/styles/_03_responsive.sass +31 -0
- package/dist/styles/{_atoms.sass → _04_atoms.sass} +4 -4
- package/{templates/_molecules.sass → dist/styles/_05_molecules.sass} +16 -12
- package/dist/styles/_06_recipes.sass +189 -0
- package/dist/styles/{_base.sass → _07_base.sass} +3 -2
- package/dist/styles/_08_blocks.sass +433 -0
- package/dist/styles/{_utilities.sass → _09_utilities.sass} +96 -16
- package/dist/styles/_10_layouts.sass +373 -0
- package/dist/styles/_11_own.sass +21 -0
- package/dist/styles/_fractals.sass +7 -6
- package/dist/styles/index.sass +14 -16
- package/mcp.json +11 -0
- package/package.json +6 -3
- package/plugin.json +22 -0
- package/skills/fractal-styler/SKILL.md +83 -0
- package/skills/fractal-styler/references/fractals.md +28 -0
- package/skills/fractal-styler/references/tokens.md +36 -0
- package/skills/style-migration/SKILL.md +45 -0
- package/templates/_00_tokens.sass +177 -0
- package/{dist/styles/_config.sass → templates/_01_config.sass} +11 -5
- package/templates/_02_fonts.sass +13 -0
- package/templates/_03_responsive.sass +31 -0
- package/templates/{_atoms.sass → _04_atoms.sass} +4 -4
- package/{dist/styles/_molecules.sass → templates/_05_molecules.sass} +16 -12
- package/templates/_06_recipes.sass +189 -0
- package/templates/{_base.sass → _07_base.sass} +3 -2
- package/templates/_08_blocks.sass +433 -0
- package/templates/{_utilities.sass → _09_utilities.sass} +96 -16
- package/templates/_10_layouts.sass +373 -0
- package/templates/_11_own.sass +21 -0
- package/templates/_fractals.sass +7 -6
- package/templates/index.sass +14 -16
- package/dist/styles/_blocks.sass +0 -88
- package/dist/styles/_layouts.sass +0 -108
- package/dist/styles/_responsive.sass +0 -43
- package/dist/styles/_tokens.sass +0 -127
- package/templates/_blocks.sass +0 -88
- package/templates/_layouts.sass +0 -108
- package/templates/_responsive.sass +0 -43
- package/templates/_tokens.sass +0 -127
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fractal-styler
|
|
3
|
+
description: Design, compose, and build UI components and page layouts using the fractalstyler2 SASS mixin system and fluid design tokens in SvelteKit. Use when authoring components, applying design tokens, styling layouts, or compiling fractal recipes.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Fractal Styler (fractalstyler2)
|
|
7
|
+
|
|
8
|
+
`fractalstyler2` is a fractal-composition styling system for SvelteKit and modern web applications. Every styling decision is a reusable SASS mixin ("a fractal"), and components and layouts are clean recipes composed of smaller fractals.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## The Four Tiers of Composition
|
|
13
|
+
|
|
14
|
+
| Tier | Role | Examples |
|
|
15
|
+
| :--- | :--- | :--- |
|
|
16
|
+
| **1. Tokens & Config** | Fluid Utopia scales & resolvers | `space(m)` → `var(--space-m)`, `radius(12)` → `var(--radius-12)` |
|
|
17
|
+
| **2. Atoms** | Single layout/styling decisions | `+box`, `+row`, `+gap(s)`, `+pad(m)`, `+border`, `+radius(12)`, `+bg(surface)`, `+ink(primary)` |
|
|
18
|
+
| **3. Molecules** | Compositions of atoms | `+stack(s)`, `+cluster(xs)`, `+surface(surface, s, 12)`, `+cover(80vh)`, `+frame(16/9)`, `+with-sidebar` |
|
|
19
|
+
| **4. Components & Layouts** | Recipes of molecules | `.card`, `.panel`, `.button`, `.badge` · `.grid-3`, `.card-grid`, `.hero`, `.holy-grail`, `.docs`, `.app-shell` |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Golden Rules for Agents
|
|
24
|
+
|
|
25
|
+
1. **Never hardcode values that tokens cover**: Use `+gap(m)`, `+radius(12)`, `+bg(surface)` instead of arbitrary pixel values.
|
|
26
|
+
2. **Compose fractals; don't write raw CSS**: Raw CSS is strictly for unique lines that no fractal covers.
|
|
27
|
+
3. **State on `data-*` / `aria-*` attributes**: Never use modifier classes like `.is-active` or `.btn--primary`. Use `&[data-elevated]`, `&[data-variant='primary']`.
|
|
28
|
+
4. **Markup stays semantic**: Prefer `<article class="card">` over 20 nested utility classes.
|
|
29
|
+
5. **Mobile-first**: Define base layout first, grow with `+at(md/lg/xl)` and `+cols()`.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## How to Author a Svelte 5 Component
|
|
34
|
+
|
|
35
|
+
```svelte
|
|
36
|
+
<script lang="ts">
|
|
37
|
+
let {
|
|
38
|
+
title = 'Pricing Tier',
|
|
39
|
+
price = '$29',
|
|
40
|
+
highlighted = false,
|
|
41
|
+
children
|
|
42
|
+
} = $props();
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<article class="pricing-card" data-highlighted={highlighted || undefined}>
|
|
46
|
+
<div class="row ycenter xbetween">
|
|
47
|
+
<h3 class="text-xl">{title}</h3>
|
|
48
|
+
{#if highlighted}
|
|
49
|
+
<span class="badge" data-variant="theme">Popular</span>
|
|
50
|
+
{/if}
|
|
51
|
+
</div>
|
|
52
|
+
<div class="row ycenter gap-2xs">
|
|
53
|
+
<span class="text-4xl font-bold">{price}</span>
|
|
54
|
+
<span class="muted">/month</span>
|
|
55
|
+
</div>
|
|
56
|
+
{#if children}
|
|
57
|
+
{@render children()}
|
|
58
|
+
{/if}
|
|
59
|
+
</article>
|
|
60
|
+
|
|
61
|
+
<style lang="sass">
|
|
62
|
+
@use '$lib/styles/fractals' as *
|
|
63
|
+
|
|
64
|
+
.pricing-card
|
|
65
|
+
+surface(surface, m, 16)
|
|
66
|
+
+stack(m)
|
|
67
|
+
transition: transform 150ms ease, box-shadow 150ms ease
|
|
68
|
+
|
|
69
|
+
&[data-highlighted]
|
|
70
|
+
+border(all, var(--theme))
|
|
71
|
+
+shadow(lg)
|
|
72
|
+
</style>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## MCP Tools Integration
|
|
78
|
+
|
|
79
|
+
If the host environment connects to the `fractalstyler2` MCP server, use the available tools:
|
|
80
|
+
* `get_design_tokens`: Query available space, typography, and radius steps.
|
|
81
|
+
* `compile_fractals`: Compile SASS mixin recipes to verify CSS output.
|
|
82
|
+
* `snap_to_tokens`: Snap canvas pixel values to tokens.
|
|
83
|
+
* `validate_recipe`: Lint SASS/Svelte against the golden rules.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Fractals Catalog Reference
|
|
2
|
+
|
|
3
|
+
## Atom Fractals (Single Decisions)
|
|
4
|
+
|
|
5
|
+
* **Layout Flow**: `+box(x, y)` (flex col), `+row(x, y)` (flex row), `+wrap`, `+grid(cols)`, `+auto-grid(min, gap)`, `+center` (grid center).
|
|
6
|
+
* **Spacing**: `+gap(v)`, `+pad(v)`, `+px(v)`, `+py(v)`, `+mx-auto`, `+my-auto`.
|
|
7
|
+
* **Sizing**: `+w(v)`, `+h(v)`, `+full`, `+square(v)`, `+grow(n)`, `+shrink(n)`, `+min0`.
|
|
8
|
+
* **Surfaces**: `+bg(role)`, `+ink(role)`, `+border(side, color)`, `+radius(v)`, `+shadow(v)`.
|
|
9
|
+
* **Position**: `+relative`, `+absolute(inset)`, `+sticky(top)`, `+fill`.
|
|
10
|
+
* **Type**: `+type(v)`, `+weight(w)`, `+leading(lh)`, `+truncate`, `+clamp-lines(n)`.
|
|
11
|
+
* **Motion**: `+transition(props, dur, ease)`, `+ring(color)`.
|
|
12
|
+
|
|
13
|
+
## Molecule Fractals (Compositions of Atoms)
|
|
14
|
+
|
|
15
|
+
* **`+stack($gap: xs, $x: null)`**: Vertical flex column rhythm with uniform gap.
|
|
16
|
+
* **`+cluster($gap: xs, $x: start, $y: center)`**: Wrapping flex row for tag clouds, chips, and button rows.
|
|
17
|
+
* **`+center-column($max: 60ch, $pad: s)`**: Bounded reading column with max-width measure and auto margins.
|
|
18
|
+
* **`+cover($min: 100vh, $pad: s)`**: Full-height container with a vertically centered focal child (`> .center`).
|
|
19
|
+
* **`+frame($ratio: 16 / 9)`**: Fixed aspect-ratio container for media.
|
|
20
|
+
* **`+reel($gap: xs)`**: Horizontal scroll-snap rail.
|
|
21
|
+
* **`+with-sidebar($rail: 240px, $gap: s, $min: 60%)`**: Intrinsic sidebar + fluid main layout.
|
|
22
|
+
* **`+surface($bg: surface, $pad: s, $radius: 12, $elevation: none)`**: The all-in-one material mixin.
|
|
23
|
+
* **`+cols($map, $gap: s)`**: Responsive grid mapped across breakpoints, e.g. `+cols((base: 1, sm: 2, lg: 3), m)`.
|
|
24
|
+
|
|
25
|
+
## Responsive Utilities
|
|
26
|
+
* `+at(sm | md | lg | xl)`: Mobile-first min-width media query.
|
|
27
|
+
* `+until(sm | md | lg | xl)`: Max-width media query.
|
|
28
|
+
* `+cq`, `+cq-at(width)`, `+cq-until(width)`: Container queries.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Design Tokens Reference
|
|
2
|
+
|
|
3
|
+
## Space Scale (Fluid Utopia)
|
|
4
|
+
| Step | Token Variable | Approximate Px | Clamp Formula |
|
|
5
|
+
| :--- | :--- | :--- | :--- |
|
|
6
|
+
| `3xs` | `--space-3xs` | ~5px | `clamp(0.3125rem, 0.3125rem + 0vw, 0.3125rem)` |
|
|
7
|
+
| `2xs` | `--space-2xs` | ~9px | `clamp(0.5625rem, 0.5369rem + 0.1136vw, 0.625rem)` |
|
|
8
|
+
| `xs` | `--space-xs` | ~14px | `clamp(0.875rem, 0.8494rem + 0.1136vw, 0.9375rem)` |
|
|
9
|
+
| `s` | `--space-s` | ~18px | `clamp(1.125rem, 1.0739rem + 0.2273vw, 1.25rem)` |
|
|
10
|
+
| `m` | `--space-m` | ~27px | `clamp(1.6875rem, 1.6108rem + 0.3409vw, 1.875rem)` |
|
|
11
|
+
| `l` | `--space-l` | ~36px | `clamp(2.25rem, 2.1477rem + 0.4545vw, 2.5rem)` |
|
|
12
|
+
| `xl` | `--space-xl` | ~54px | `clamp(3.375rem, 3.2216rem + 0.6818vw, 3.75rem)` |
|
|
13
|
+
| `2xl` | `--space-2xl` | ~72px | `clamp(4.5rem, 4.2955rem + 0.9091vw, 5rem)` |
|
|
14
|
+
| `3xl` | `--space-3xl` | ~108px | `clamp(6.75rem, 6.4432rem + 1.3636vw, 7.5rem)` |
|
|
15
|
+
| `s-l` | `--space-s-l` | ~18→40px | `clamp(1.125rem, 0.5625rem + 2.5vw, 2.5rem)` |
|
|
16
|
+
|
|
17
|
+
## Typography Scale
|
|
18
|
+
| Step | Token Variable | Fluid Clamp |
|
|
19
|
+
| :--- | :--- | :--- |
|
|
20
|
+
| `xs` | `--text-xs` | `0.75rem` (12px) |
|
|
21
|
+
| `sm` | `--text-sm` | `clamp(0.9375rem, 0.9119rem + 0.1136vw, 1rem)` |
|
|
22
|
+
| `md` | `--text-md` | `clamp(1.125rem, 1.0739rem + 0.2273vw, 1.25rem)` |
|
|
23
|
+
| `lg` | `--text-lg` | `clamp(1.35rem, 1.2631rem + 0.3864vw, 1.5625rem)` |
|
|
24
|
+
| `xl` | `--text-xl` | `clamp(1.62rem, 1.4837rem + 0.6057vw, 1.9531rem)` |
|
|
25
|
+
| `2xl` | `--text-2xl` | `clamp(1.944rem, 1.7405rem + 0.9044vw, 2.4414rem)` |
|
|
26
|
+
| `3xl` | `--text-3xl` | `clamp(2.3328rem, 2.0387rem + 1.3072vw, 3.0518rem)` |
|
|
27
|
+
| `4xl` | `--text-4xl` | `clamp(2.7994rem, 2.384rem + 1.8461vw, 3.8147rem)` |
|
|
28
|
+
|
|
29
|
+
## Radius Scale
|
|
30
|
+
`0`, `2`, `4`, `6`, `8`, `12`, `16`, `24`, `full`
|
|
31
|
+
|
|
32
|
+
## Color & Surface Roles
|
|
33
|
+
* **Surfaces**: `--bg`, `--bg-surface`, `--bg-raised`
|
|
34
|
+
* **Ink**: `--text-primary`, `--text-secondary`, `--text-muted`, `--text-inverse`
|
|
35
|
+
* **Borders**: `--border`, `--border-strong`
|
|
36
|
+
* **Brand**: `--theme`, `--theme-hover`, `--theme-active`, `--ring`
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: style-migration
|
|
3
|
+
description: Migrate legacy CSS, Tailwind utilities, or fractals-styler (v1) classes into modern fractalstyler2 SASS mixin recipes and token scales. Use when refactoring stylesheets, updating legacy components, or cleaning up utility class soup.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Style Migration & Refactoring Skill
|
|
7
|
+
|
|
8
|
+
This skill guides the refactoring and migration of existing styles into idiomatic `fractalstyler2`.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. Quick Replacement Matrix
|
|
13
|
+
|
|
14
|
+
| Legacy Pattern | Problem | fractalstyler2 Replacement |
|
|
15
|
+
| :--- | :--- | :--- |
|
|
16
|
+
| `gap8`, `gap16`, `gap24` | Dynamic JIT classes removed in v2 | Markup: `.gap-xs`, `.gap-s`, `.gap-m`<br>SASS: `+gap(8)` or `+gap(s)` |
|
|
17
|
+
| `pad8`, `pad16`, `pad24` | Dynamic JIT classes removed in v2 | Markup: `.pad-xs`, `.pad-s`, `.pad-m`<br>SASS: `+pad(16)` or `+pad(m)` |
|
|
18
|
+
| `<div class="center">` (as reading text column) | In v2, `.center` dead-centers items in a grid | SASS: `.reading-col { +center-column }` |
|
|
19
|
+
| `<div class="stack">` | Markup class `.stack` does not exist | SASS: `.container { +stack(s) }` |
|
|
20
|
+
| `<div class="cluster">` | Markup class `.cluster` does not exist | SASS: `.tag-row { +cluster(xs) }` |
|
|
21
|
+
| `w100`, `h100` | Removed aliases | `.wfull`, `.hfull` |
|
|
22
|
+
| `min-w-0`, `min-h-0` | Removed utilities | `.min0` |
|
|
23
|
+
| `[data-variant='quiet']` | Renamed on button | `[data-variant='ghost']` |
|
|
24
|
+
| `.appshell` | Renamed layout | `.app-shell` |
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 2. Refactoring Procedure
|
|
29
|
+
|
|
30
|
+
1. **Identify the Container**: Is it a card, panel, button, reading column, or grid?
|
|
31
|
+
2. **Select the Molecule**:
|
|
32
|
+
- Vertical list of items → `+stack(s)`
|
|
33
|
+
- Tag list / button row → `+cluster(xs)`
|
|
34
|
+
- Box with border/radius/padding → `+surface(surface, s, 12)`
|
|
35
|
+
- Full height hero → `+cover(80vh, xl)`
|
|
36
|
+
3. **Strip Utility Soup from Markup**: Replace long class strings (`class="box pad16 gap12 w100 min-w-0 radius12 border"`) with a single semantic class (`class="card"` or `class="feed-item"`).
|
|
37
|
+
4. **Move Decisions to `<style lang="sass">`**:
|
|
38
|
+
```sass
|
|
39
|
+
@use '$lib/styles/fractals' as *
|
|
40
|
+
|
|
41
|
+
.feed-item
|
|
42
|
+
+surface(surface, s, 12)
|
|
43
|
+
+stack(s)
|
|
44
|
+
```
|
|
45
|
+
5. **Verify**: Use the MCP tool `validate_recipe` or `npx sass src/lib/styles/index.sass /tmp/check.css`.
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// 00_TOKENS — the single source of truth for runtime CSS custom properties.
|
|
3
|
+
// -----------------------------------------------------------------------------
|
|
4
|
+
// Light is the marker-free default so tokens stay defined during SSR and with
|
|
5
|
+
// JS disabled; dark comes from prefers-color-scheme and explicit [data-mode='dark'].
|
|
6
|
+
// =============================================================================
|
|
7
|
+
|
|
8
|
+
:root
|
|
9
|
+
color-scheme: light
|
|
10
|
+
|
|
11
|
+
// Fonts
|
|
12
|
+
--font-sans: "Google Sans Flex", sans-serif
|
|
13
|
+
--font-mono: "JetBrains Mono", 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 (Concentric 2px, 3px, 4px, 6px hierarchy)
|
|
38
|
+
--radius-0: 0
|
|
39
|
+
--radius-2: 2px
|
|
40
|
+
--radius-3: 3px
|
|
41
|
+
--radius-4: 4px
|
|
42
|
+
--radius-6: 6px
|
|
43
|
+
--radius-8: 6px
|
|
44
|
+
--radius-12: 6px
|
|
45
|
+
--radius-16: 6px
|
|
46
|
+
--radius-24: 6px
|
|
47
|
+
--radius-full: 9999px
|
|
48
|
+
|
|
49
|
+
// Control Heights
|
|
50
|
+
--control-h-sm: 26px
|
|
51
|
+
--control-h-md: 32px
|
|
52
|
+
--control-h-lg: 38px
|
|
53
|
+
|
|
54
|
+
// Shadow
|
|
55
|
+
--shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06)
|
|
56
|
+
--shadow-md: 0 4px 12px rgba(15, 23, 42, 0.08)
|
|
57
|
+
--shadow-lg: 0 12px 32px rgba(15, 23, 42, 0.12)
|
|
58
|
+
|
|
59
|
+
// Layering
|
|
60
|
+
--z-base: 0
|
|
61
|
+
--z-raised: 10
|
|
62
|
+
--z-sticky: 100
|
|
63
|
+
--z-modal: 200
|
|
64
|
+
--z-toast: 300
|
|
65
|
+
|
|
66
|
+
// Layout
|
|
67
|
+
--header-height: 48px
|
|
68
|
+
--footer-height: 56px
|
|
69
|
+
--measure: 65ch
|
|
70
|
+
|
|
71
|
+
// Light palette (marker-free default)
|
|
72
|
+
--bg: #fdfefe
|
|
73
|
+
--bg-surface: #f8f7f7
|
|
74
|
+
--bg-raised: #f1f5f9
|
|
75
|
+
--bg-panel: #F1F3F5
|
|
76
|
+
--bg-footer: #E9ECEF
|
|
77
|
+
--bg-popover: #FFFFFF
|
|
78
|
+
--bg-dialog: #FFFFFF
|
|
79
|
+
--bg-terminal: #0F172A
|
|
80
|
+
--bg-input: #FFFFFF
|
|
81
|
+
--bg-canvas: #F8F9FA
|
|
82
|
+
--text-primary: #0f172a
|
|
83
|
+
--text-secondary: #5b6472
|
|
84
|
+
--text-muted: #929497
|
|
85
|
+
--text-inverse: #ffffff
|
|
86
|
+
--state-hover: #E2E8F0
|
|
87
|
+
--state-hover-subtle: #F1F5F9
|
|
88
|
+
--state-selected: #CBD5E1
|
|
89
|
+
--border: #E2E8F0
|
|
90
|
+
--border-subtle: #EDF2F7
|
|
91
|
+
--theme-color: #04825B
|
|
92
|
+
--theme-color-alt: #047857
|
|
93
|
+
--theme: var(--theme-color)
|
|
94
|
+
--theme-hover: var(--theme-color-alt)
|
|
95
|
+
--ring: rgba(0, 127, 78, 0.35)
|
|
96
|
+
|
|
97
|
+
@media (prefers-color-scheme: dark)
|
|
98
|
+
:root:not([data-mode='light'])
|
|
99
|
+
color-scheme: dark
|
|
100
|
+
--bg: #0E1118
|
|
101
|
+
--bg-surface: #141824
|
|
102
|
+
--bg-raised: #1C2232
|
|
103
|
+
--bg-panel: #101420
|
|
104
|
+
--bg-footer: #0B0D14
|
|
105
|
+
--bg-popover: #20273A
|
|
106
|
+
--bg-dialog: #20273A
|
|
107
|
+
--bg-terminal: #080A0F
|
|
108
|
+
--bg-input: #121622
|
|
109
|
+
--bg-canvas: #0E1118
|
|
110
|
+
--border: #28324A
|
|
111
|
+
--border-subtle: #1E2538
|
|
112
|
+
--text-primary: #EDF2F7
|
|
113
|
+
--text-secondary: #9BB0C7
|
|
114
|
+
--text-muted: #5D7087
|
|
115
|
+
--state-hover: #263047
|
|
116
|
+
--state-hover-subtle: #1B2233
|
|
117
|
+
--state-selected: #32405E
|
|
118
|
+
--theme-color: #38BDF8
|
|
119
|
+
--theme-color-alt: #0EA5E9
|
|
120
|
+
--theme: var(--theme-color)
|
|
121
|
+
--theme-hover: var(--theme-color-alt)
|
|
122
|
+
--text-inverse: #0E1118
|
|
123
|
+
--ring: rgba(16, 185, 129, 0.4)
|
|
124
|
+
|
|
125
|
+
[data-mode='dark']
|
|
126
|
+
color-scheme: dark
|
|
127
|
+
--bg: #0E1118
|
|
128
|
+
--bg-surface: #141824
|
|
129
|
+
--bg-raised: #1C2232
|
|
130
|
+
--bg-panel: #101420
|
|
131
|
+
--bg-footer: #0B0D14
|
|
132
|
+
--bg-popover: #20273A
|
|
133
|
+
--bg-dialog: #20273A
|
|
134
|
+
--bg-terminal: #080A0F
|
|
135
|
+
--bg-input: #121622
|
|
136
|
+
--bg-canvas: #0E1118
|
|
137
|
+
--border: #28324A
|
|
138
|
+
--border-subtle: #1E2538
|
|
139
|
+
--text-primary: #EDF2F7
|
|
140
|
+
--text-secondary: #9BB0C7
|
|
141
|
+
--text-muted: #5D7087
|
|
142
|
+
--state-hover: #263047
|
|
143
|
+
--state-hover-subtle: #1B2233
|
|
144
|
+
--state-selected: #32405E
|
|
145
|
+
--theme-color: #38BDF8
|
|
146
|
+
--theme-color-alt: #0EA5E9
|
|
147
|
+
--theme: var(--theme-color)
|
|
148
|
+
--theme-hover: var(--theme-color-alt)
|
|
149
|
+
--text-inverse: #0E1118
|
|
150
|
+
--ring: rgba(16, 185, 129, 0.4)
|
|
151
|
+
|
|
152
|
+
[data-mode='light']
|
|
153
|
+
color-scheme: light
|
|
154
|
+
--bg: #fdfefe
|
|
155
|
+
--bg-surface: #f8f7f7
|
|
156
|
+
--bg-raised: #f1f5f9
|
|
157
|
+
--bg-panel: #F1F3F5
|
|
158
|
+
--bg-footer: #E9ECEF
|
|
159
|
+
--bg-popover: #FFFFFF
|
|
160
|
+
--bg-dialog: #FFFFFF
|
|
161
|
+
--bg-terminal: #0F172A
|
|
162
|
+
--bg-input: #FFFFFF
|
|
163
|
+
--bg-canvas: #F8F9FA
|
|
164
|
+
--text-primary: #0f172a
|
|
165
|
+
--text-secondary: #5b6472
|
|
166
|
+
--text-muted: #929497
|
|
167
|
+
--text-inverse: #ffffff
|
|
168
|
+
--state-hover: #E2E8F0
|
|
169
|
+
--state-hover-subtle: #F1F5F9
|
|
170
|
+
--state-selected: #CBD5E1
|
|
171
|
+
--border: #E2E8F0
|
|
172
|
+
--border-subtle: #EDF2F7
|
|
173
|
+
--theme-color: #04825B
|
|
174
|
+
--theme-color-alt: #047857
|
|
175
|
+
--theme: var(--theme-color)
|
|
176
|
+
--theme-hover: var(--theme-color-alt)
|
|
177
|
+
--ring: rgba(0, 127, 78, 0.35)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// =============================================================================
|
|
2
|
-
//
|
|
2
|
+
// 01_CONFIG — the finite vocabulary every fractal draws from.
|
|
3
3
|
// -----------------------------------------------------------------------------
|
|
4
4
|
// Scales live here as Sass data; resolvers turn a keyword-or-raw value into the
|
|
5
5
|
// right token var() or unit. Fractals never hardcode a px or a token name —
|
|
@@ -11,15 +11,17 @@
|
|
|
11
11
|
@use 'sass:meta'
|
|
12
12
|
@use 'sass:list'
|
|
13
13
|
|
|
14
|
-
// --- Scales (mirror the custom properties in
|
|
14
|
+
// --- Scales (mirror the custom properties in _00_tokens.sass) ----------------
|
|
15
15
|
$breakpoints: (sm: 640px, md: 768px, lg: 1024px, xl: 1240px)
|
|
16
16
|
|
|
17
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
|
|
18
|
+
$radius-steps: 0 2 3 4 6 8 12 16 24 full
|
|
19
19
|
$text-steps: xs sm md lg xl 2xl 3xl 4xl
|
|
20
20
|
$shadow-steps: sm md lg
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
|
|
22
|
+
// Surfaces mapped to the 21 theme token contract
|
|
23
|
+
$surface-roles: bg surface raised panel footer popover dialog terminal input canvas
|
|
24
|
+
$ink-roles: primary secondary muted inverse theme-color theme-color-alt
|
|
23
25
|
|
|
24
26
|
$align-map: (start: flex-start, end: flex-end, center: center, between: space-between, around: space-around, evenly: space-evenly, stretch: stretch, baseline: baseline)
|
|
25
27
|
|
|
@@ -59,12 +61,16 @@ $align-map: (start: flex-start, end: flex-end, center: center, between: space-be
|
|
|
59
61
|
@function surface($role)
|
|
60
62
|
@if $role == bg
|
|
61
63
|
@return var(--bg)
|
|
64
|
+
@else if list.index($surface-roles, $role)
|
|
65
|
+
@return var(--bg-#{$role})
|
|
62
66
|
@else
|
|
63
67
|
@return var(--bg-#{$role})
|
|
64
68
|
|
|
65
69
|
@function ink($role)
|
|
66
70
|
@if $role == primary
|
|
67
71
|
@return var(--text-primary)
|
|
72
|
+
@else if list.index($ink-roles, $role)
|
|
73
|
+
@return var(--text-#{$role})
|
|
68
74
|
@else
|
|
69
75
|
@return var(--text-#{$role})
|
|
70
76
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// 02_FONTS — local webfont declarations & font-family fallbacks.
|
|
3
|
+
// -----------------------------------------------------------------------------
|
|
4
|
+
// Downstream projects customize their font loading here.
|
|
5
|
+
// =============================================================================
|
|
6
|
+
|
|
7
|
+
// Define custom @font-face rules or load Google / local webfonts as needed:
|
|
8
|
+
// @font-face
|
|
9
|
+
// font-family: 'YourFont'
|
|
10
|
+
// src: url('/fonts/YourFont.woff2') format('woff2')
|
|
11
|
+
// font-weight: 100 900
|
|
12
|
+
// font-style: normal
|
|
13
|
+
// font-display: swap
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// 03_RESPONSIVE — the breakpoint mixins. Viewport-aware conditional styling.
|
|
3
|
+
// -----------------------------------------------------------------------------
|
|
4
|
+
// Mobile-first defaults; use +at($bp) for min-width media queries.
|
|
5
|
+
// =============================================================================
|
|
6
|
+
|
|
7
|
+
@use '01_config' as *
|
|
8
|
+
|
|
9
|
+
=at($bp)
|
|
10
|
+
$width: bp($bp)
|
|
11
|
+
@if $width
|
|
12
|
+
@media (min-width: $width)
|
|
13
|
+
@content
|
|
14
|
+
@else
|
|
15
|
+
@media (min-width: $bp)
|
|
16
|
+
@content
|
|
17
|
+
|
|
18
|
+
=below($bp)
|
|
19
|
+
$width: bp($bp)
|
|
20
|
+
@if $width
|
|
21
|
+
@media (max-width: ($width - 1px))
|
|
22
|
+
@content
|
|
23
|
+
@else
|
|
24
|
+
@media (max-width: $bp)
|
|
25
|
+
@content
|
|
26
|
+
|
|
27
|
+
=between($min-bp, $max-bp)
|
|
28
|
+
$min: bp($min-bp)
|
|
29
|
+
$max: bp($max-bp)
|
|
30
|
+
@media (min-width: $min) and (max-width: ($max - 1px))
|
|
31
|
+
@content
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// =============================================================================
|
|
2
|
-
//
|
|
2
|
+
// 04_ATOMS — the indivisible units. One visual decision each.
|
|
3
3
|
// -----------------------------------------------------------------------------
|
|
4
4
|
// Every atom is a mixin. Call it inside a class to compose, or let
|
|
5
|
-
//
|
|
5
|
+
// _09_utilities.sass project it to a utility class. Same fractal, two consumers.
|
|
6
6
|
// =============================================================================
|
|
7
7
|
|
|
8
|
-
@use '
|
|
8
|
+
@use '01_config' as *
|
|
9
9
|
|
|
10
10
|
// --- Flow: the two axes of layout ------------------------------------------
|
|
11
11
|
// A box is a vertical stack, a row is horizontal. Optional semantic alignment:
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
@else
|
|
103
103
|
border-#{$side}: 1px solid $color
|
|
104
104
|
|
|
105
|
-
=radius($v:
|
|
105
|
+
=radius($v: 4)
|
|
106
106
|
border-radius: radius($v)
|
|
107
107
|
|
|
108
108
|
=shadow($v: md)
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
// =============================================================================
|
|
2
|
-
//
|
|
2
|
+
// 05_MOLECULES — self-similar: each is a small graph of atom fractals.
|
|
3
3
|
// -----------------------------------------------------------------------------
|
|
4
4
|
// This is the payoff of the model. A molecule reads like a recipe of atoms,
|
|
5
5
|
// and a component (next layer up) reads like a recipe of molecules. Same move
|
|
6
6
|
// at every scale — that is the "fractal" in fractalstyler2.
|
|
7
7
|
// =============================================================================
|
|
8
8
|
|
|
9
|
-
@use '
|
|
10
|
-
@use '
|
|
11
|
-
@use '
|
|
9
|
+
@use 'sass:string'
|
|
10
|
+
@use '01_config' as *
|
|
11
|
+
@use '04_atoms' as *
|
|
12
|
+
@use '03_responsive' as *
|
|
12
13
|
|
|
13
14
|
// Stack — vertical rhythm with one shared gap.
|
|
14
15
|
=stack($gap: xs, $x: null)
|
|
@@ -38,11 +39,13 @@
|
|
|
38
39
|
+my-auto
|
|
39
40
|
|
|
40
41
|
// Frame — fixed aspect-ratio media box.
|
|
41
|
-
=frame($ratio: 16 / 9)
|
|
42
|
-
aspect-ratio: $ratio
|
|
42
|
+
=frame($ratio: '16 / 9')
|
|
43
|
+
aspect-ratio: string.unquote('#{$ratio}')
|
|
43
44
|
overflow: hidden
|
|
44
|
-
|
|
45
|
+
position: relative
|
|
46
|
+
> *
|
|
45
47
|
+full
|
|
48
|
+
> :is(img, video, iframe)
|
|
46
49
|
object-fit: cover
|
|
47
50
|
|
|
48
51
|
// Reel — horizontal scroll-snap rail.
|
|
@@ -69,13 +72,14 @@
|
|
|
69
72
|
flex-grow: 999
|
|
70
73
|
min-width: $min
|
|
71
74
|
|
|
72
|
-
// Surface — the "material" fractal: skin +
|
|
75
|
+
// Surface — the "material" fractal: skin + border + optional radius + optional padding + elevation.
|
|
73
76
|
// The building block of every card/panel/popover.
|
|
74
|
-
=surface($bg: surface, $pad:
|
|
77
|
+
=surface($bg: surface, $pad: null, $radius: 6, $elevation: none)
|
|
75
78
|
+bg($bg)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
@if $radius != null
|
|
80
|
+
+radius($radius)
|
|
81
|
+
@if $pad != null
|
|
82
|
+
+pad($pad)
|
|
79
83
|
@if $elevation != none
|
|
80
84
|
+shadow($elevation)
|
|
81
85
|
|