@toybreaker/fiko 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024–2025 Toybreaker
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,168 @@
1
+ # 404.css
2
+
3
+ **A minimal, layered CSS foundation you override by design, not by accident.**
4
+
5
+ [![npm](https://img.shields.io/npm/v/@toybreaker/fiko)](https://www.npmjs.com/package/@toybreaker/fiko)
6
+ [![MIT License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
7
+
8
+ ---
9
+
10
+ ## The Problem
11
+
12
+ Modern CSS frameworks fall into two traps:
13
+
14
+ 1. **Too much opinion** — ship components that look like every other site, forcing you to fight the framework to express your brand.
15
+ 2. **Too much complexity** — utility-only systems (Tailwind, etc.) put all design decisions in HTML, making templates hard to read and refactor.
16
+
17
+ 404.css takes a third path: a minimal, layered foundation you override by design, not by accident.
18
+
19
+ ---
20
+
21
+ ## Install
22
+
23
+ ```bash
24
+ npm install @toybreaker/fiko
25
+ # or
26
+ pnpm add @toybreaker/fiko
27
+ ```
28
+
29
+ ---
30
+
31
+ ## Usage
32
+
33
+ ### 1. Import the framework
34
+
35
+ ```css
36
+ /* your project's index.css */
37
+ @import "@toybreaker/fiko";
38
+ ```
39
+
40
+ This imports `omg/` — the brand-agnostic framework. It declares six cascade layers and imports all `omg/` sheets in the correct order.
41
+
42
+ ### 2. Add your brand (copy the template)
43
+
44
+ ```bash
45
+ # copy the starter brand files into your project
46
+ cp node_modules/@toybreaker/fiko/template/000/ src/assets/404/000/ -r
47
+ ```
48
+
49
+ Then import your brand tokens **after** the framework, inside the same layers:
50
+
51
+ ```css
52
+ @import "@toybreaker/fiko";
53
+
54
+ /* brand palette — loads in the tokens layer */
55
+ @import url(./000/1client_vars.css) layer(tokens);
56
+
57
+ /* semantic aliases (surface, text, cta) — loads in the theme layer */
58
+ @import url(./000/2client_datatheme.css) layer(theme);
59
+
60
+ /* element defaults, heading scale — loads in the theme layer */
61
+ @import url(./000/3client_theme.css) layer(theme);
62
+ ```
63
+
64
+ ### 3. Customize your brand
65
+
66
+ Edit `000/1client_vars.css` — change the hue angle for your brand color:
67
+
68
+ ```css
69
+ --brand: oklch(0.55 0.19 28); /* orange — change the hue (0–360) */
70
+ ```
71
+
72
+ ---
73
+
74
+ ## Architecture: `omg/` vs `000/`
75
+
76
+ ```
77
+ 404/
78
+ ├── omg/ ← THE FRAMEWORK — brand-agnostic, versioned, never touch
79
+ │ ├── 0reset.css
80
+ │ ├── 1vars.css ← layout, spacing, typography tokens
81
+ │ ├── 3base.css ← element defaults
82
+ │ ├── 4layout.css ← container, grid, nav
83
+ │ ├── 5components.css ← buttons, links, controls
84
+ │ ├── 6states.css ← data-state helpers
85
+ │ └── utils/ ← atomic utility classes
86
+
87
+ └── 000/ ← YOUR BRAND — per-client, fully owned, never extracted
88
+ ├── 1client_vars.css ← raw palette (OKLCH colors)
89
+ ├── 2client_datatheme.css ← semantic aliases (surface, text, cta…)
90
+ └── 3client_theme.css ← element defaults, heading scale, brand specifics
91
+ ```
92
+
93
+ **The rule:** if it could work on any website → `omg/`. If it's specific to one brand → `000/`.
94
+
95
+ ---
96
+
97
+ ## Cascade Layers
98
+
99
+ ```css
100
+ @layer reset, tokens, theme, layout, components, utilities;
101
+ ```
102
+
103
+ | Layer | Purpose |
104
+ |---|---|
105
+ | `reset` | Margin/padding zero, box-sizing, smooth scroll |
106
+ | `tokens` | CSS custom properties: spacing, type, color |
107
+ | `theme` | Semantic aliases + element defaults |
108
+ | `layout` | Body, container, grid, nav |
109
+ | `components` | Buttons, inputs, links |
110
+ | `utilities` | Atomic helpers: `.hide`, `.flex`, `.center`, etc. |
111
+
112
+ `@layer` makes specificity predictable. A utility class in `utilities` always beats a component in `components` — no `!important` wars.
113
+
114
+ ---
115
+
116
+ ## OKLCH Colors
117
+
118
+ All color tokens use OKLCH:
119
+
120
+ ```css
121
+ --brand: oklch(0.55 0.19 28);
122
+ /* L = lightness (0–1), C = chroma (0–0.37), H = hue (0–360) */
123
+ ```
124
+
125
+ - **Perceptually uniform** — same L value = same perceived lightness across hues
126
+ - **Relative calculations** — `oklch(from var(--brand) calc(l + 0.08) c h)` = guaranteed lighter tint
127
+ - **Wide gamut** — P3 and Rec2020 renders richer colors automatically
128
+
129
+ ---
130
+
131
+ ## Utilities
132
+
133
+ | Class | Effect |
134
+ |---|---|
135
+ | `.hide` | `display: none` |
136
+ | `.flex` | `display: flex` |
137
+ | `.center` | flex center both axes |
138
+ | `.pad_block_sm` | block padding small |
139
+ | `.h1` – `.h6` | heading scale classes |
140
+ | `.dim` | secondary text color + smaller size |
141
+ | `.typewriter` | `max-width: 66ch; margin-inline: auto` |
142
+ | `.aspect_square` | `aspect-ratio: 1` |
143
+ | `.aspect_video` | `aspect-ratio: 16/9` |
144
+
145
+ ---
146
+
147
+ ## What 404.css Intentionally Does NOT Do
148
+
149
+ - **No dark mode** — permanent light mode
150
+ - **No JavaScript** — pure CSS
151
+ - **No component library** — no `.card`, `.modal`, `.navbar` in `omg/`
152
+ - **No magic class names** — every utility is obvious
153
+
154
+ ---
155
+
156
+ ## Pairing with Astro
157
+
158
+ 404.css was designed to pair with Astro scoped styles:
159
+
160
+ - 404.css owns the global layer stack (reset → utilities)
161
+ - Astro components own their own layout via `<style>` blocks
162
+ - Zero specificity conflicts
163
+
164
+ ---
165
+
166
+ ## License
167
+
168
+ MIT — Copyright (c) 2024–2025 Toybreaker
package/index.css ADDED
@@ -0,0 +1,51 @@
1
+ /*!
2
+ * 🐉 404.css v0.1.0-alpha.1
3
+ * https://github.com/junglesta/404css
4
+ *
5
+ * Copyright (c) 2024–2025 Toybreaker
6
+ * Released under the MIT License
7
+ *
8
+ * An unknown modern CSS framework.
9
+ * Implementing issues gone 404. SMILING DX!
10
+ *
11
+ * ─────────────────────────────────────────────
12
+ * USAGE
13
+ *
14
+ * This file imports only the framework (omg/) layers.
15
+ * You must also supply your brand's 000/ files:
16
+ *
17
+ * your-project/404.css
18
+ * ├── @import "@junglesta/404css"; ← this file (tokens + layout + components + utils)
19
+ * ├── @import "./000/1client_vars.css" layer(tokens);
20
+ * ├── @import "./000/2client_datatheme.css" layer(theme);
21
+ * └── @import "./000/3client_theme.css" layer(theme);
22
+ *
23
+ * Starter 000/ templates are in node_modules/@junglesta/404css/template/000/
24
+ * ─────────────────────────────────────────────
25
+ */
26
+
27
+ /* CASCADING ORDER — declared first so all @imports know their place */
28
+ @layer reset, tokens, theme, layout, components, utilities;
29
+
30
+ /* RESET */
31
+ @import url(omg/0reset.css) layer(reset);
32
+
33
+ /* TOKENS — framework spacing, typography, motion */
34
+ @import url(omg/1vars.css) layer(tokens);
35
+
36
+ /* LAYOUT — element defaults, grid, container, states */
37
+ @import url(omg/3base.css) layer(layout);
38
+ @import url(omg/4layout.css) layer(layout);
39
+ @import url(omg/6states.css) layer(layout);
40
+
41
+ /* COMPONENTS — buttons, links, controls */
42
+ @import url(omg/5components.css) layer(components);
43
+
44
+ /* UTILITIES — highest priority, no !important needed */
45
+ @import url(omg/utils/text.css) layer(utilities);
46
+ @import url(omg/utils/visibility.css) layer(utilities);
47
+ @import url(omg/utils/layout.css) layer(utilities);
48
+ @import url(omg/utils/spacing.css) layer(utilities);
49
+ @import url(omg/utils/aspect.css) layer(utilities);
50
+ @import url(omg/utils/gradients.css) layer(utilities);
51
+ @import url(omg/utils/misc.css) layer(utilities);
package/omg/0reset.css ADDED
@@ -0,0 +1,55 @@
1
+ /*! 🐉 404.css | MIT License */
2
+ /* 0reset.css */
3
+
4
+ *,
5
+ *::before,
6
+ *::after {
7
+ margin: 0;
8
+ padding: 0;
9
+ box-sizing: border-box;
10
+ background-repeat: no-repeat;
11
+ }
12
+
13
+ html {
14
+ -webkit-text-size-adjust: 100%;
15
+ text-size-adjust: 100%;
16
+ scroll-behavior: smooth;
17
+ overflow-x: clip;
18
+ }
19
+
20
+ @media (prefers-reduced-motion: reduce) {
21
+ html {
22
+ scroll-behavior: auto;
23
+ }
24
+ *,
25
+ *::before,
26
+ *::after {
27
+ animation-duration: 0.01ms !important;
28
+ animation-iteration-count: 1 !important;
29
+ transition-duration: 0.01ms !important;
30
+ }
31
+ }
32
+
33
+ h1, h2, h3, h4, h5, h6 {
34
+ margin: 0;
35
+ padding: 0;
36
+ text-wrap: balance;
37
+ }
38
+
39
+ p {
40
+ text-wrap: pretty;
41
+ }
42
+
43
+ img,
44
+ video {
45
+ display: block;
46
+ max-width: 100%;
47
+ content-visibility: auto;
48
+ }
49
+
50
+ input,
51
+ button,
52
+ textarea,
53
+ select {
54
+ font: inherit;
55
+ }
package/omg/1vars.css ADDED
@@ -0,0 +1,62 @@
1
+ /*! 🐉 404.css | MIT License */
2
+ /* 1vars.css — layout, spacing, typography tokens */
3
+ /* Color tokens live in 000/1client_vars.css */
4
+
5
+ :root {
6
+ /* ── MOTION ─────────────────────────────────── */
7
+ --transition: 200ms ease-out;
8
+ --ease_out: cubic-bezier(0.22, 1, 0.36, 1);
9
+
10
+ /* ── SIZING ─────────────────────────────────── */
11
+ --tap_size: clamp(42px, 5vw, 52px);
12
+ --radius: 6px;
13
+ --borderpx: 3px;
14
+ --sticky_header_height: 88px; /* override in 000/ per client */
15
+ --maximise: -1.5rem; /* negative container bleed */
16
+
17
+ /* ── SPACING ─────────────────────────────────── */
18
+ --spaceH: 1.75svw;
19
+ --spaceV: 1.5svh;
20
+ --space: calc(var(--spaceH) + var(--spaceV) / 2);
21
+ --breath: calc(var(--space) * 1.5);
22
+
23
+ /* ── BREAKPOINTS ─────────────────────────────── */
24
+ --bp_xs: 390px;
25
+ --bp_sm: 576px;
26
+ --bp_md: 768px;
27
+ --bp_lg: 992px;
28
+ --bp_xl: 1200px;
29
+ --max_window_width: 1400px;
30
+
31
+ /* ── CONTAINER WIDTHS ────────────────────────── */
32
+ --container_xs: var(--bp_xs);
33
+ --container_sm: calc(var(--bp_sm) - var(--breath) * 2);
34
+ --container_md: calc(var(--bp_md) - var(--breath) * 2);
35
+ --container_lg: calc(var(--bp_lg) - var(--breath) * 2);
36
+ --container_xl: calc(var(--bp_xl) - var(--breath) * 2);
37
+
38
+ /* ── TYPOGRAPHY ──────────────────────────────── */
39
+ --font_serif: "Courier New", Courier, monospace;
40
+ --font_family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
41
+ Roboto, Ubuntu, "Helvetica Neue", sans-serif;
42
+ --line_height: 1.5;
43
+ --font_size: clamp(1.1rem, 0.34vw + 0.92rem, 1.21rem);
44
+ --text_decoration: none;
45
+
46
+ /* weight scale */
47
+ --weight_100: 100;
48
+ --weight_200: 200;
49
+ --weight_300: 300;
50
+ --weight_400: 400;
51
+ --weight_500: 500;
52
+ --weight_600: 600;
53
+ --weight_700: 700;
54
+ --weight_800: 800;
55
+
56
+ /* semantic aliases */
57
+ --weight_thin: var(--weight_400);
58
+ --weight_light: var(--weight_500);
59
+ --weight_regular: var(--weight_600);
60
+ --weight_medium: var(--weight_700);
61
+ --weight_bold: var(--weight_800);
62
+ }
package/omg/3base.css ADDED
@@ -0,0 +1,29 @@
1
+ /*! 🐉 404.css | MIT License */
2
+ /* 3base.css — element defaults */
3
+
4
+ body {
5
+ font-family: var(--font_family);
6
+ font-size: var(--font_size);
7
+ line-height: var(--line_height);
8
+ background: var(--surface);
9
+ color: var(--text);
10
+ text-rendering: optimizeLegibility;
11
+ -webkit-font-smoothing: antialiased;
12
+ }
13
+
14
+ :focus-visible {
15
+ outline: 2px solid var(--focus_color, var(--primary));
16
+ outline-offset: 2px;
17
+ }
18
+
19
+ /* minimum tap target for accessibility */
20
+ a {
21
+ min-height: var(--tap_size);
22
+ }
23
+
24
+ img,
25
+ video {
26
+ width: 100%;
27
+ height: 100%;
28
+ object-fit: cover;
29
+ }
@@ -0,0 +1,76 @@
1
+ /*! 🐉 404.css | MIT License */
2
+ /* 4layout.css */
3
+
4
+ /* Container implementation using container queries */
5
+ .container {
6
+ /* Container query setup */
7
+ container-type: inline-size;
8
+ container-name: main-container;
9
+
10
+ /* Simplified width calculation using the pre-defined container width variables */
11
+ width: min(100% - (var(--breath) * 2), var(--container_xl));
12
+ margin-inline: auto;
13
+ }
14
+
15
+ /* Modern grid system with CSS Grid */
16
+ .grid {
17
+ display: grid;
18
+ grid-template-columns: repeat(var(--grid_cols, 1), 1fr);
19
+ gap: var(--breath);
20
+ }
21
+
22
+ /* Responsive grid using container queries
23
+ This leverages the breakpoint variables defined in 1vars.css */
24
+ @container main-container (min-width: var(--bp_sm)) {
25
+ .grid {
26
+ --grid_cols: 2;
27
+ }
28
+ }
29
+
30
+ @container main-container (min-width: var(--bp_md)) {
31
+ .grid {
32
+ --grid_cols: 3;
33
+ }
34
+ }
35
+
36
+ @container main-container (min-width: var(--bp_lg)) {
37
+ .grid {
38
+ --grid_cols: 4;
39
+ }
40
+ }
41
+
42
+ /* Modern navigation layout */
43
+ nav {
44
+ display: flex;
45
+ flex-wrap: wrap;
46
+ align-items: center;
47
+ justify-content: space-between;
48
+ gap: 1px;
49
+ }
50
+
51
+ nav ul,
52
+ nav ol {
53
+ display: flex;
54
+ flex-wrap: wrap;
55
+ padding: 0;
56
+ margin: 0;
57
+ list-style: none;
58
+ }
59
+
60
+ nav li {
61
+ display: flex;
62
+ align-items: center;
63
+ }
64
+
65
+ /* Optional: Add responsive navigation behavior */
66
+ @container main-container (max-width: var(--bp_sm)) {
67
+ nav {
68
+ flex-direction: column;
69
+ }
70
+
71
+ nav ul,
72
+ nav ol {
73
+ flex-direction: column;
74
+ width: 100%;
75
+ }
76
+ }
@@ -0,0 +1,101 @@
1
+ /*! 🐉 404.css | MIT License */
2
+ /* 5components.css — interactive elements */
3
+
4
+ /* BUTTON / INPUT — shape & layout */
5
+ button,
6
+ .button input[type="submit"],
7
+ input[type="button"],
8
+ input[type="reset"],
9
+ [role="button"] {
10
+ height: var(--tap_size);
11
+ padding-inline: var(--spaceH);
12
+ border: var(--borderpx) solid var(--border_color, currentColor);
13
+ border-radius: var(--radius);
14
+ outline: none;
15
+ background-color: transparent;
16
+ color: inherit;
17
+ font-size: var(--font_size);
18
+ font-weight: var(--weight_bold);
19
+ text-align: center;
20
+ cursor: pointer;
21
+ transition:
22
+ background-color var(--transition),
23
+ border-color var(--transition),
24
+ color var(--transition),
25
+ box-shadow var(--transition);
26
+ user-select: none;
27
+ }
28
+
29
+ /* BUTTON CLASS — wraps a <button> inside an <a> */
30
+ .button {
31
+ border: none;
32
+ border-radius: var(--radius);
33
+ cursor: pointer;
34
+ color: var(--text);
35
+ display: inline-flex;
36
+ font-weight: var(--weight_bold);
37
+ gap: var(--spaceV) var(--spaceH);
38
+ padding: calc(var(--spaceV) / 3) calc(var(--spaceH) / 3);
39
+ transition: transform 0.2s var(--ease_out);
40
+ user-select: none;
41
+ }
42
+
43
+ .button:hover,
44
+ button:hover {
45
+ transform: translateY(3px);
46
+ }
47
+
48
+ /* LINK defaults */
49
+ a:not(.underline),
50
+ [role="link"] {
51
+ outline: none;
52
+ background-color: transparent;
53
+ color: var(--text);
54
+ text-decoration: var(--text_decoration);
55
+ transition:
56
+ background-color var(--transition),
57
+ color var(--transition),
58
+ text-decoration var(--transition),
59
+ box-shadow var(--transition);
60
+ user-select: none;
61
+ }
62
+
63
+ /* button inside link — reset decoration, inherit color from context */
64
+ a button,
65
+ a [role="button"],
66
+ a input[type="submit"],
67
+ a input[type="button"],
68
+ a input[type="reset"] {
69
+ color: inherit;
70
+ text-decoration: none;
71
+ user-select: none;
72
+ }
73
+
74
+ /* CTA BUTTON — filled, primary action */
75
+ .button_cta button {
76
+ background-color: var(--cta);
77
+ border-color: var(--cta);
78
+ color: var(--cta_text);
79
+ }
80
+ .button_cta:hover button {
81
+ background-color: var(--cta_hover);
82
+ border-color: var(--cta_hover);
83
+ }
84
+
85
+ /* SVG overflow fix */
86
+ svg:not(:root) {
87
+ overflow: hidden;
88
+ }
89
+
90
+ /* STICKY HEADER */
91
+ .controls {
92
+ height: var(--sticky_header_height);
93
+ min-height: var(--sticky_header_height);
94
+ max-height: var(--sticky_header_height);
95
+ user-select: none;
96
+ }
97
+ .controls.sticky {
98
+ position: sticky;
99
+ top: 0;
100
+ z-index: 20;
101
+ }
@@ -0,0 +1,16 @@
1
+ /*! 🐉 404.css | MIT License */
2
+ /* 6states.css */
3
+
4
+ [data-state="loading"] {
5
+ cursor: progress;
6
+ opacity: 0.7;
7
+ }
8
+
9
+ [data-state="disabled"] {
10
+ opacity: 0.5;
11
+ pointer-events: none;
12
+ }
13
+
14
+ [data-state="empty"] {
15
+ display: none;
16
+ }
@@ -0,0 +1,61 @@
1
+ /*! 🐉 404.css | MIT License */
2
+ /* utils/aspect.css — aspect ratios, object-fit, object-position, clip */
3
+
4
+ /* ── ASPECT CONTAINERS ───────────────────────────── */
5
+
6
+ .aspect,
7
+ .aspect_container {
8
+ position: relative;
9
+ width: 100%;
10
+
11
+ &:hover { opacity: 0.95; }
12
+ &:active { transform: scale(0.985); }
13
+
14
+ & > img,
15
+ & > video {
16
+ width: 100%;
17
+ height: 100%;
18
+ object-fit: cover;
19
+ }
20
+
21
+ & > .caption {
22
+ padding: var(--spaceV) var(--spaceH);
23
+ color: var(--text);
24
+ }
25
+ }
26
+
27
+ /* dynamic ratio via inline style */
28
+ .aspect[style*="--ratio"],
29
+ .aspect_container[style*="--ratio"] {
30
+ aspect-ratio: var(--ratio);
31
+ }
32
+
33
+ /* ── RATIOS ──────────────────────────────────────── */
34
+
35
+ .ratio_1x1, .aspect1_1 { aspect-ratio: 1 / 1; }
36
+ .ratio_4x3, .aspect4_3 { aspect-ratio: 4 / 3; }
37
+ .ratio_3x4, .aspect3_4 { aspect-ratio: 3 / 4; }
38
+ .ratio_3x5, .aspect3_5 { aspect-ratio: 3 / 5; }
39
+ .ratio_16x9, .aspect16_9 { aspect-ratio: 16 / 9; }
40
+ .ratio_9x16, .aspect9_16 { aspect-ratio: 9 / 16; }
41
+ .ratio_2x1, .aspect2_1 { aspect-ratio: 2 / 1; }
42
+ .ratio_1x2, .aspect1_2 { aspect-ratio: 1 / 2; }
43
+ .ratio_21x9, .aspect21_9 { aspect-ratio: 21 / 9; }
44
+
45
+ .aspect_cinema,
46
+ .aspect_cinemascope { aspect-ratio: 2.35 / 1; }
47
+
48
+ /* ── OBJECT POSITION ─────────────────────────────── */
49
+
50
+ .focus_center > img { object-position: center; }
51
+ .focus_top > img { object-position: top; }
52
+ .focus_bottom > img { object-position: bottom; }
53
+ .focus_left > img { object-position: left; }
54
+ .focus_right > img { object-position: right; }
55
+
56
+ /* ── CLIP ────────────────────────────────────────── */
57
+
58
+ .clip_none > img { clip-path: none; }
59
+ .clip_letterbox > img { clip-path: inset(15% 0); }
60
+ .clip_pillarbox > img { clip-path: inset(0 15%); }
61
+ .clip_custom > img { clip-path: inset(10% 5% 10% 5%); }
@@ -0,0 +1,5 @@
1
+ /*! 🐉 404.css | MIT License */
2
+ /* utils/gradients.css — gradient utility classes */
3
+
4
+ .gradient_brand { background: var(--gradient_brand); }
5
+ .gradient_warm { background: var(--gradient_warm); }
@@ -0,0 +1,27 @@
1
+ /*! 🐉 404.css | MIT License */
2
+ /* utils/layout.css — flex, positioning, writing mode */
3
+
4
+ .flex {
5
+ display: flex;
6
+ }
7
+
8
+ .flex_col {
9
+ flex-direction: column;
10
+ }
11
+
12
+ .sticky {
13
+ position: sticky;
14
+ top: 0;
15
+ }
16
+
17
+ .vertical {
18
+ display: block;
19
+ writing-mode: vertical-rl;
20
+ transform: rotate(180deg);
21
+ text-transform: uppercase;
22
+ position: relative;
23
+ top: -10px;
24
+ .active & {
25
+ font-size: 200%;
26
+ }
27
+ }
@@ -0,0 +1,9 @@
1
+ /*! 🐉 404.css | MIT License */
2
+ /* utils/misc.css — one-off component state overrides */
3
+
4
+ .adv {
5
+ opacity: 0.5;
6
+ #icn_whatsapp {
7
+ filter: grayscale(88%);
8
+ }
9
+ }
@@ -0,0 +1,40 @@
1
+ /*! 🐉 404.css | MIT License */
2
+ /* utils/spacing.css — gap, padding, spacer blocks */
3
+ /* No !important needed — utilities layer is highest priority in cascade */
4
+
5
+ /* ── GAPS ─────────────────────────────────────────── */
6
+
7
+ .gap_sm { gap: var(--spaceV) var(--spaceH); }
8
+ .gap_md { gap: calc(var(--spaceV) * 2) calc(var(--spaceH) * 2); }
9
+ .gap_lg { gap: calc(var(--spaceV) * 3) calc(var(--spaceH) * 3); }
10
+
11
+ /* ── PADDING BLOCKS ──────────────────────────────── */
12
+
13
+ .pad_block_sm { padding-block: calc(var(--spaceV) * 1.5); }
14
+ .pad_block_md { padding-block: calc(var(--spaceV) * 3); }
15
+ .pad_block_lg { padding-block: calc(var(--spaceV) * 6); }
16
+ .pad_block_xl { padding-block: calc(var(--spaceV) * 9); }
17
+ .pad_block_xxl { padding-block: calc(var(--spaceV) * 12); }
18
+
19
+ .pad_top_sm { padding-top: calc(var(--spaceV) * 1.5); }
20
+ .pad_top_md { padding-top: calc(var(--spaceV) * 3); }
21
+ .pad_top_lg { padding-top: calc(var(--spaceV) * 6); }
22
+ .pad_top_xl { padding-top: calc(var(--spaceV) * 9); }
23
+ .pad_top_xxl { padding-top: calc(var(--spaceV) * 12); }
24
+
25
+ .pad_bottom_sm { padding-bottom: calc(var(--spaceV) * 1.5); }
26
+ .pad_bottom_md { padding-bottom: calc(var(--spaceV) * 3); }
27
+ .pad_bottom_lg { padding-bottom: calc(var(--spaceV) * 6); }
28
+ .pad_bottom_xl { padding-bottom: calc(var(--spaceV) * 9); }
29
+ .pad_bottom_xxl { padding-bottom: calc(var(--spaceV) * 12); }
30
+
31
+ .top_padding { padding-top: var(--spaceV); }
32
+
33
+ /* ── SPACER BLOCKS ───────────────────────────────── */
34
+
35
+ .spacer_block_xs { min-height: 1svh; max-height: 88px; }
36
+ .spacer_block_sm { min-height: 2.5svh; max-height: 100px; }
37
+ .spacer_block_md { min-height: 5svh; max-height: 133px; }
38
+ .spacer_block_lg { min-height: 10svh; max-height: 200px; }
39
+ .spacer_block_xl { min-height: 15svh; max-height: 250px; }
40
+ .spacer_block_xxl { min-height: 20svh; max-height: 400px; }
@@ -0,0 +1,27 @@
1
+ /*! 🐉 404.css | MIT License */
2
+ /* utils/text.css — text alignment, transform, wrap */
3
+
4
+ .center,
5
+ .centre,
6
+ .centered {
7
+ text-align: center;
8
+ }
9
+
10
+ .uppercase,
11
+ .uppercase > * {
12
+ text-transform: uppercase !important;
13
+ }
14
+
15
+ .capitalize,
16
+ .capitalise,
17
+ .titlecase {
18
+ text-transform: capitalize;
19
+ }
20
+
21
+ .strikethrough {
22
+ text-decoration: line-through;
23
+ }
24
+
25
+ .pretty {
26
+ text-wrap: pretty;
27
+ }
@@ -0,0 +1,45 @@
1
+ /*! 🐉 404.css | MIT License */
2
+ /* utils/visibility.css — show/hide, screen reader, print */
3
+
4
+ .hide,
5
+ .hidden {
6
+ display: none !important;
7
+ }
8
+
9
+ .hide.not {
10
+ display: block !important;
11
+ }
12
+
13
+ .maybe_hide {
14
+ display: none !important;
15
+ }
16
+ @media screen and (min-width: 480px) {
17
+ .maybe_hide {
18
+ display: inline !important;
19
+ }
20
+ }
21
+
22
+ .is_empty_hide {
23
+ display: none;
24
+ }
25
+
26
+ /* visually hidden but accessible to screen readers */
27
+ .visually_hidden,
28
+ .sr_only {
29
+ position: absolute;
30
+ width: 1px;
31
+ height: 1px;
32
+ padding: 0;
33
+ margin: -1px;
34
+ overflow: hidden;
35
+ clip-path: inset(100%);
36
+ white-space: nowrap;
37
+ border: 0;
38
+ user-select: none;
39
+ }
40
+
41
+ @media print {
42
+ .print_hidden {
43
+ display: none !important;
44
+ }
45
+ }
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@toybreaker/fiko",
3
+ "version": "0.1.0-alpha.1",
4
+ "description": "An unknown modern CSS framework. Implementing issues gone 404. SMILING DX!",
5
+ "license": "MIT",
6
+ "author": "Toybreaker <hello@junglestar.co>",
7
+ "homepage": "https://github.com/junglesta/fiko",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/junglesta/fiko.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/junglesta/fiko/issues"
14
+ },
15
+ "keywords": [
16
+ "css",
17
+ "framework",
18
+ "cascade-layers",
19
+ "oklch",
20
+ "design-tokens",
21
+ "utility-css",
22
+ "modern-css"
23
+ ],
24
+ "main": "index.css",
25
+ "style": "index.css",
26
+ "exports": {
27
+ ".": "./index.css",
28
+ "./template/*": "./template/*",
29
+ "./omg/*": "./omg/*"
30
+ },
31
+ "files": [
32
+ "index.css",
33
+ "omg/",
34
+ "template/"
35
+ ]
36
+ }
@@ -0,0 +1,40 @@
1
+ /*! 🐉 404.css | MIT License */
2
+ /* 000/1client_vars.css — brand palette tokens
3
+ *
4
+ * Copy this file into your project's 000/ folder.
5
+ * Customize the values below for your brand.
6
+ * This file loads in the `tokens` layer alongside omg/1vars.css.
7
+ */
8
+
9
+ :root {
10
+ /* ── NEUTRALS ──────────────────────────────────── */
11
+ --dark: oklch(0.20 0 0);
12
+ --darkT25: color-mix(in oklch, var(--dark), transparent 75%);
13
+ --darkT50: color-mix(in oklch, var(--dark), transparent 50%);
14
+
15
+ --light: oklch(0.97 0 0);
16
+ --lightT25: color-mix(in oklch, var(--light), transparent 75%);
17
+ --lightT50: color-mix(in oklch, var(--light), transparent 50%);
18
+
19
+ /* ── BRAND COLOR ───────────────────────────────── */
20
+ /* Change the hue (0–360) to match your brand.
21
+ * Lightness (0–1) and chroma (0–0.37) control shade and saturation.
22
+ * Examples:
23
+ * red oklch(0.55 0.22 20)
24
+ * orange oklch(0.55 0.19 40)
25
+ * green oklch(0.45 0.18 145)
26
+ * blue oklch(0.50 0.20 250)
27
+ * purple oklch(0.45 0.22 290)
28
+ */
29
+ --brand: oklch(0.55 0.19 28); /* ← change me */
30
+ --brand_lighter: oklch(from var(--brand) calc(l + 0.08) c h);
31
+ --brand_darker: oklch(from var(--brand) calc(l - 0.18) c h);
32
+ --brandT25: color-mix(in oklch, var(--brand), transparent 75%);
33
+ --brandT50: color-mix(in oklch, var(--brand), transparent 50%);
34
+
35
+ /* ── PAGE SURFACES ─────────────────────────────── */
36
+ /* --surface is defined in 2client_datatheme.css as var(--light).
37
+ * Add custom section surfaces here as needed, e.g.:
38
+ * --surface_hero: oklch(0.92 0.02 var(--brand-hue));
39
+ */
40
+ }
@@ -0,0 +1,34 @@
1
+ /*! 🐉 404.css | MIT License */
2
+ /* 000/2client_datatheme.css — semantic theme aliases
3
+ *
4
+ * Maps raw palette tokens (from 1client_vars.css) to semantic roles.
5
+ * This file loads in the `theme` layer.
6
+ * Permanent light mode — dark mode intentionally excluded.
7
+ */
8
+
9
+ :root {
10
+ /* ── SURFACE & TEXT ───────────────────────────────── */
11
+ --surface: var(--light);
12
+ --surface_inverse: var(--dark);
13
+ --surfaceT25: var(--lightT25);
14
+ --surface_inverseT25: var(--darkT25);
15
+ --text: var(--dark);
16
+ --textT50: var(--darkT50);
17
+
18
+ /* ── LOGO ─────────────────────────────────────────── */
19
+ --logo: var(--dark);
20
+
21
+ /* ── BRAND — identity (logo, icons, decorative) ───── */
22
+ --primary: var(--brand);
23
+ --primary_hover: var(--brand_lighter);
24
+ --contrast: var(--brand_darker);
25
+
26
+ /* ── CTA — interactive (buttons, links, actions) ──── */
27
+ --cta: var(--brand);
28
+ --cta_text: var(--light);
29
+ --cta_hover: var(--brand_lighter);
30
+
31
+ /* ── BORDERS & FOCUS ──────────────────────────────── */
32
+ --border_color: var(--dark);
33
+ --focus_color: var(--brand);
34
+ }
@@ -0,0 +1,37 @@
1
+ /*! 🐉 404.css | MIT License */
2
+ /* 000/3client_theme.css — element & component defaults
3
+ *
4
+ * Brand-specific overrides that sit on top of the framework.
5
+ * Loaded in the `theme` layer — below utilities, above components.
6
+ * Customize freely. All rules here are brand-specific, not framework rules.
7
+ */
8
+
9
+ /* ── TYPOGRAPHY SCALE ─────────────────────────────────────────── */
10
+
11
+ .h1 { font-size: calc(var(--font_size) * 2.5) !important; font-weight: var(--weight_light) !important; }
12
+ .h2 { font-size: calc(var(--font_size) * 2.0) !important; font-weight: var(--weight_light) !important; }
13
+ .h3 { font-size: calc(var(--font_size) * 1.75) !important; font-weight: var(--weight_thin) !important; }
14
+ .h4 { font-size: calc(var(--font_size) * 1.5) !important; font-weight: var(--weight_thin) !important; }
15
+ .h5 { font-size: calc(var(--font_size) * 1.25) !important; font-weight: var(--weight_thin) !important; }
16
+ .h6 { font-size: calc(var(--font_size) * 1.0) !important; font-weight: var(--weight_light) !important; }
17
+
18
+ /* ── DIM — secondary text ──────────────────────────────────────── */
19
+
20
+ .dim {
21
+ color: var(--textT50);
22
+ font-size: calc(var(--font_size) * 0.85);
23
+ }
24
+
25
+ /* ── UNDERLINE LINK ───────────────────────────────────────────── */
26
+
27
+ .underline {
28
+ text-decoration: underline;
29
+ text-underline-offset: 3px;
30
+ }
31
+
32
+ /* ── TYPEWRITER — constrained readable prose column ─────────────── */
33
+
34
+ .typewriter {
35
+ max-width: 66ch;
36
+ margin-inline: auto;
37
+ }