fertig 4.0.3 → 4.0.7

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
@@ -1,473 +1,77 @@
1
1
  # fertig
2
2
 
3
- [![Bundlephobia minified size](https://img.shields.io/bundlephobia/min/fertig?label=minified&cacheSeconds=86400)](https://bundlephobia.com/package/fertig)
4
- [![Bundlephobia minified and compressed size](https://img.shields.io/bundlephobia/minzip/fertig?label=min%2Bgzip&cacheSeconds=86400)](https://bundlephobia.com/package/fertig)
3
+ [![minified size](https://img.shields.io/bundlephobia/min/fertig?label=minified&cacheSeconds=86400)](https://bundlephobia.com/package/fertig)
4
+ [![min+gzip size](https://img.shields.io/bundlephobia/minzip/fertig?label=min%2Bgzip&cacheSeconds=86400)](https://bundlephobia.com/package/fertig)
5
5
 
6
- A classless CSS file that gives you **components**, not just styled elements —
7
- menus, dialogs, drawers, toasts and tooltips from plain semantic HTML,
8
- built from native HTML and the ARIA that makes it accessible, and working with
9
- JavaScript switched off.
6
+ A classless CSS framework for finished interfaces. Link one file and write
7
+ semantic HTML; fertig styles the page, forms, tables, dialogs, popovers,
8
+ navigation, feedback, and common layout patterns.
10
9
 
11
- Link it, write ordinary HTML, and the page is finished.
10
+ **41.1 KB raw · 9.3 KB gzipped · no build step · no dependencies · no JavaScript.**
12
11
 
13
- **36.7 KB raw · 8.6 KB gzipped · no build step · no dependencies · no JavaScript.**
14
-
15
- ### What makes it different
16
-
17
- Surveyed across the eleven most-used classless stylesheets on 2026-08-31
18
- ([working notes](docs/classless-landscape-2026.md)):
19
-
20
- - **Components addressed by ARIA.** Only one other classless sheet ships a
21
- single ARIA-addressed component. None ships tabs, a segmented control, or an
22
- anchored popover menu.
23
- - **Behaviour without JavaScript.** Others style `<dialog>` and leave the open
24
- and close to you. Here `popover`, `command` and anchor positioning do it —
25
- [audited with scripting disabled](#components-that-work-without-javascript).
26
- - **Modern CSS.** Zero of the eleven use `oklch()`, `light-dark()`, `@layer`,
27
- `@property`, container queries or anchor positioning. This sheet uses all of
28
- them.
29
- - **Cascade-layered.** It lives in `@layer fertig`, so your own unlayered CSS
30
- wins at any specificity and overriding never needs `!important`. No other
31
- classless sheet does this.
32
- - **RTL by construction.** Written in logical properties throughout, not
33
- patched with `[dir=rtl]` overrides afterwards.
34
-
35
- `fertig.min.css` is 8.6 KB gzipped. That includes semantic element styling,
36
- the component layer, responsive utilities, light and dark themes, RTL support
37
- and accessibility safeguards. Size is a constraint here, not the pitch.
38
-
39
- ## Components that work without JavaScript
40
-
41
- Audited in a browser with scripting disabled:
42
-
43
- | | |
44
- |---|---|
45
- | Popover menu, dialog, drawer, toast, tooltip, disclosure | **work with no script** |
46
- | Tabs | **styled only** — selection, panels and arrow keys need a short script |
47
-
48
- This gap is deliberate: `aria-selected` must be a real attribute, inactive tabs
49
- need roving focus, and CSS cannot implement the arrow-key contract. The complete
50
- enhancement is in the docs. `<details name>` remains an exclusive accordion,
51
- not a tabs substitute.
52
-
53
- ```html
54
- <link rel="stylesheet" href="fertig.css">
55
- ```
56
-
57
- That is the whole integration. Write semantic HTML; it looks finished.
58
- Open the [live site](https://moji2002.github.io/fertig/) for the full demo.
59
-
60
- ## Upgrading from 2.x
61
-
62
- 3.0 is breaking for one reason: **every public token now carries a `--fertig-`
63
- prefix**, and the old names are gone — no aliases. The classes, the ARIA
64
- attributes the components read, and the layout utilities are all unchanged.
65
- The sheet's behaviour is the same; the migration is a rename.
66
-
67
- If you override tokens, prefix what you set. The common ones:
68
-
69
- | 2.x | 3.0 |
70
- |---|---|
71
- | `--ac` | `--fertig-ac` |
72
- | `--on-ac` | `--fertig-on-ac` |
73
- | `--w` / `--g` | `--fertig-w` / `--fertig-g` |
74
- | `--r` / `--rs` / `--rw` | `--fertig-r` / `--fertig-rs` / `--fertig-rw` |
75
- | `--bg` / `--el` / `--face` / `--fg` / `--mut` / `--bd` / `--tb` | `--fertig-*` (same short name) |
76
- | `--up` / `--up2` / `--dn` / `--sh` / `--sh1` / `--sh2` | `--fertig-up` / `--fertig-up2` / `--fertig-dn` / `--fertig-sh` / `--fertig-sh1` / `--fertig-sh2` |
77
- | fonts `--f` / `--fm`, page width `--w`, gutter `--g`, caps `--caps`, `--nw` | `--fertig-*` |
78
- | color ramps `--stone-*` / `--sage-*` / `--sky-*` / `--clay-*` / `--plum-*` / `--gold-*` | `--fertig-*` (same stop) |
79
-
80
- The rule is simple: **any `--name` you set becomes `--fertig-name`.** Nothing
81
- changed meaning; the prefix exists so the sheet never collides with a custom
82
- property of yours (it is the same reason `--fertig-a1` / `--fertig-a2` were
83
- already prefixed — those are `@property` registrations, which are global).
84
-
85
- The defaults now favor a platform-neutral interface:
86
-
87
- - **Palette.** Accents and neutrals moved to a cooler voice — graphite
88
- neutrals and a violet-blue accent — replacing the older indigo/warm scheme.
89
- - **Geometry.** Buttons share the restrained control radius. Pill geometry is
90
- reserved for badges, switches, meters and joined ends.
91
-
92
- The docs site was also rebuilt and the two demo pages (`app.html` /
93
- `app-invoice.html`) are gone. None of that touches the sheet.
94
-
95
- ## Install
12
+ ## Use
96
13
 
97
14
  ```sh
98
15
  npm install fertig
99
16
  ```
100
17
 
101
- ```html
102
- <!-- or from a CDN, pinned -->
103
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fertig@4/fertig.min.css">
104
- ```
105
-
106
18
  ```css
107
- /* or through a bundler */
108
19
  @import "fertig";
109
20
  ```
110
21
 
111
- ## What it is
112
-
113
- Opinions, so you don't have to have them: system type, one accent, one page
114
- width and a clear content canvas. The structure is classic — a toolbar,
115
- sunken fields and flat buttons — while the finish stays platform-neutral:
116
- opaque surfaces, hairlines, restrained corners and a violet-blue focus ring
117
- over cool graphite neutrals.
118
-
119
- - **System type, set properly** — 16px on a 1.65 line height. Long-form copy
120
- gets a roughly seventy-character measure with `.max-w-prose`. Code keeps a
121
- monospace face, where it earns its place.
122
- - **A centered content canvas.** `<nav>` becomes a full-bleed opaque toolbar;
123
- `header`/`main`/`footer` form the page surface.
124
- - **Depth from hairlines and soft shadows.** Cards sit above the page while
125
- buttons stay flat and inputs and code sit below it. Shadow alphas step up in dark mode,
126
- because a shadow on a dark background does nothing on its own.
127
- - **Quiet text.** Links underline on hover rather than inverting mid-paragraph.
128
- - **Comfortable foregrounds.** Light mode uses graphite rather than absolute
129
- black; dark mode uses a softened near-white rather than full white.
130
- - **Dark mode with no second stylesheet.** One `light-dark()` token block.
131
- Add `data-theme="dark"` (or `"light"`) on `<html>` to override the OS.
132
-
133
- ## Layout
134
-
135
- Direct children of `<body>` are full-width containers with responsive page
136
- gutters:
22
+ Or use the CDN:
137
23
 
138
24
  ```html
139
- <body>
140
- <nav>…</nav> <!-- toolbar: full-bleed, contents on the page column -->
141
- <header>…</header>
142
- <main>…</main>
143
- <footer>…</footer>
144
- </body>
145
- ```
146
-
147
- There is no default maximum width on body-level containers. Add
148
- `.max-w-prose` to long-form content for a readable `38rem` line length, or use
149
- the `max-w-*` utilities when a page needs a specific measure. The
150
- `--fertig-g` gutter scales from `1.15rem` on narrow phones to `1.9rem` on
151
- larger screens.
152
-
153
- One wrapper is fine. React, Vue, Svelte and Next render into a mount node, so
154
- the shell matches `body`'s children *or* the children of a single `#root`,
155
- `#app`, `#__next`, or `[data-fertig]` wrapper:
156
-
157
- ```html
158
- <body>
159
- <div id="root">
160
- <nav>…</nav>
161
- <main>…</main>
162
- </div>
163
- </body>
164
- ```
165
-
166
- Deeper than that, or a differently named mount node, and you re-point the shell
167
- yourself — it is the only place `body >` appears:
168
-
169
- ```css
170
- #shell > *, #shell > header, #shell > main, #shell > footer { /* … */ }
25
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fertig@4/fertig.min.css">
171
26
  ```
172
27
 
173
- ## Components
28
+ That is the complete setup. See the [documentation](https://moji2002.github.io/fertig/docs.html),
29
+ [component catalogue](https://moji2002.github.io/fertig/components.html), and
30
+ [copy-paste blocks](https://moji2002.github.io/fertig/blocks.html).
174
31
 
175
- Addressed by semantic HTML and ARIA attributes, not by component classes — the
176
- markup stays accessible by construction.
32
+ ## What it includes
177
33
 
178
- | Component | Markup |
179
- |---|---|
180
- | Segmented control | `<div role="group">` of buttons, `aria-pressed` |
181
- | ARIA tabs | `<div role="tablist">`, `<button role="tab" aria-selected>`; switching and arrow keys need script |
182
- | Switch | `<input type="checkbox" role="switch">` |
183
- | Menu | any `[popover]` + `popovertarget` (anchored, no JS) |
184
- | Breadcrumb | `<nav aria-label="Breadcrumb"><ol>` |
185
- | Dialog | `<dialog>` — animates in; optional `<header>`/`<footer>` pin while the body scrolls |
186
- | Loading | `aria-busy="true"` (inline spinner) |
187
- | Tooltip | `data-tooltip="…"` — decorative; put the same words in `aria-label` too |
188
- | Button variants | `data-variant="ghost\|link"`, `data-size="sm\|lg"`, `data-icon`, `data-block` — on controls only, so they cannot catch a `<span data-size>` of yours |
189
- | Card anatomy | `<header>` / `<footer>` inside `.card`; `<a class="card">` lifts on hover |
190
- | Tones | `data-tone="ok\|warn\|err"` retints any component |
34
+ - Light and dark themes through `light-dark()`
35
+ - Accessible forms, input groups, one-time codes, listboxes, surfaces, cards,
36
+ items, empty states, tabs, menus, dialogs, tooltips, and more
37
+ - Native no-JavaScript behavior for popovers, dialogs, drawers, disclosures,
38
+ toasts, and tooltips
39
+ - Logical properties for RTL layouts
40
+ - OKLCH color ramps and WCAG AA semantic pairs
41
+ - A cascade layer, so unlayered project CSS overrides fertig cleanly
191
42
 
192
- And a second set, added for parity with the component libraries — same rule,
193
- no classes:
43
+ Seven component classes are optional: `.row`, `.grid`, `.card`, `.badge`,
44
+ `.muted`, `.center`, and `.wide`. Layout utilities are available when semantic
45
+ HTML alone cannot express the layout.
194
46
 
195
- | Component | Markup |
196
- |---|---|
197
- | Avatar | `data-avatar` on an `<img>` or on initials in a `<span>`; `="sm\|lg"` |
198
- | Skeleton | `data-skeleton` on the element that is still loading |
199
- | Sheet / drawer | `<dialog data-side="left\|right\|bottom">` — the same dialog, docked to an edge |
200
- | Toast | `[popover][data-toast]` — non-modal, parked in a corner. Several at once: `<div popover="manual" data-toast-region>` with a `<div data-toast>` per message |
201
- | List group | a plain `<menu>` outside a popover becomes a bordered list |
202
- | Nav menu | a `<menu>` inside a `<nav>` is navigation instead — no rules, no bullets, `aria-current` marks the page |
203
- | Sidebar layout | `data-layout="sidebar"` on a wrapper of two children; the first sticks |
204
- | Carousel | `data-carousel` — scroll snapping, with real scroll buttons where they exist |
47
+ ## Customize
205
48
 
206
- ## The seven optional classes
207
-
208
- `.row` `.grid` `.card` `.badge` `.muted` `.center` `.wide`
209
-
210
- Plus `.primary` on a button — though `type="submit"` already gets it.
211
-
212
- ## Layout utilities
213
-
214
- A compact set of predictable layout helpers covers common flex, grid,
215
- alignment, gap, margin, width and visibility needs.
216
-
217
- ```
218
- .flex .flex-col .flex-wrap .flex-1
219
- .grid-cols-2 .grid-cols-3 .grid-cols-4
220
- .items-start .items-center .items-end
221
- .justify-start .justify-center .justify-end .justify-between
222
- .gap-0 .gap-1 .gap-2 .gap-3 .gap-4 .gap-6 (0 · .25 · .5 · .75 · 1 · 1.5rem)
223
- .mx-auto .ms-auto .me-auto .w-full .hidden
224
- .max-w-xs .max-w-sm .max-w-md .max-w-lg .max-w-xl (20 · 24 · 28 · 32 · 36rem)
225
- .max-w-2xl .max-w-3xl .max-w-4xl .max-w-5xl .max-w-6xl .max-w-7xl (42 · 48 · 56 · 64 · 72 · 80rem)
226
- .max-w-full .max-w-none .max-w-prose
227
- ```
228
-
229
- Layout and width only. No colour or type scale, and no responsive
230
- variants — those need a build step, and this file does not have one. The
231
- margins are flow-relative (`ms`/`me`, not `ml`/`mr`), so a toolbar still lands
232
- correctly in Persian or Arabic. `.grid` is fertig's own auto-fit grid;
233
- adding `.grid-cols-3` pins it to three columns.
234
-
235
- The `max-w-*` scale is complete rather than partial — a half-scale where
236
- `.max-w-2xl` works and `.max-w-3xl` silently does not is worse than no scale
237
- at all. They are `max-inline-size`, so they still mean "along the text"
238
- in a vertical writing mode and can constrain a page container as readily as
239
- anything inside one. `.max-w-prose` is a fixed `38rem` reading measure.
240
-
241
- ## Customising
242
-
243
- Override the tokens you'd actually want to change:
49
+ Override tokens in your own CSS:
244
50
 
245
51
  ```css
246
52
  :root {
247
- --fertig-ac: light-dark(var(--fertig-blue-700), var(--fertig-blue-300)); /* blue accent */
248
- --fertig-w: 48rem; /* toolbar content width */
249
- --fertig-g: 1.25rem; /* page gutter */
250
- --fertig-r: 0px; /* control radius — go sharp */
251
- --fertig-f: "Inter", system-ui, sans-serif; /* text font */
53
+ --fertig-ac: oklch(52% 0.18 270);
54
+ --fertig-r: 10px;
55
+ --fertig-w: 72rem;
252
56
  }
253
57
  ```
254
58
 
255
- The accent is the only colour most people touch. The default is blue sitting
256
- on cool gray neutrals; the
257
- `data-accent` attribute retints a whole region without touching tokens:
258
-
259
- ```html
260
- <section data-accent="green">…</section> <!-- or blue, cyan, amber, red, violet, gray -->
261
- ```
262
-
263
- The palette exposes `gray`, `blue`, `cyan`, `green`, `amber`, `red` and
264
- `violet` ramps at `100`, `300`, `500`, `700` and `900`. For example,
265
- `--fertig-violet-500` is the middle violet stop. The former
266
- `stone/sage/sky/clay/plum/gold` ramps and named accents were removed rather
267
- than retained as aliases.
268
-
269
- Tones work the same way — `data-tone="ok|warn|err"` retints any component
270
- without a round trip through the tokens:
271
-
272
- ```html
273
- <button data-tone="err">Delete</button>
274
- ```
275
-
276
- If you change `--fertig-ac`, check `--fertig-on-ac` too — that is the text
277
- colour sitting on the accent, and a light accent needs dark text to stay
278
- legible. `--fertig-up` / `--fertig-up2` / `--fertig-dn` are the elevation
279
- scale, `--fertig-a1` / `--fertig-a2` the shadow alphas (these two are
280
- `@property` registrations, and a registration is global — hence the prefix),
281
- `--fertig-rw` the large-surface radius, and `--fertig-nw` the column the toolbar's
282
- contents line up with. `--fertig-nw` follows `--fertig-w`, so nothing moves by
283
- default; `<nav class="wide">` re-points it at the wide column, which is what an
284
- app screen built on `.wide` wants so its wordmark doesn't float in the middle
285
- of the viewport.
286
-
287
- ## Also handled
288
-
289
- `:target`, external-link arrows, `user-invalid` fields, a CSS-drawn select
290
- chevron, thin scrollbars, `sup`/`sub` that don't stretch lines, `q`/`dfn`/
291
- `ins`/`del`/`address`/`meter`/`output`/`optgroup`/`hgroup`, print styles, and
292
- `prefers-reduced-motion`.
293
-
294
- ## Right-to-left
295
-
296
- Every inline-direction rule is flow-relative — `padding-inline-start`,
297
- `border-inline-start`, `margin-inline-end`, `text-align: start`,
298
- `border-start-end-radius` — so `dir="rtl"` mirrors the sheet with nothing to
299
- configure:
300
-
301
- ```html
302
- <html lang="fa" dir="rtl">
303
- ```
304
-
305
- List markers, blockquote and `<aside>` accent bars, table gutters, breadcrumb
306
- separators, the segmented control's rounded ends, the `<select>` chevron and
307
- the switch knob all move to the correct side. Two of those cannot be expressed
308
- logically — `translate` and a background position — and carry `:dir(rtl)`
309
- rules instead. The layout utilities follow the same rule: `.ms-auto` and
310
- `.me-auto` exist, `.ml-auto` deliberately does not.
311
-
312
- Tested by rendering a Persian page in both directions, not by inspection.
313
-
314
- ## Accessibility
315
-
316
- Every foreground/background pair meets WCAG 2.1 AA (>= 4.5:1) in **both**
317
- themes, calculated from the computed token values:
318
-
319
- | Pair | Light | Dark |
320
- |---|---:|---:|
321
- | Body text on content surface | 16.83 | 15.32 |
322
- | Muted text on content surface | 6.92 | 7.15 |
323
- | Links on content surface | 6.72 | 9.50 |
324
- | Muted on controls | 6.57 | 6.45 |
325
- | Muted on page ground | 5.89 | 7.88 |
326
- | Text on accent | 6.16 | 11.22 |
327
- | Tones (ok / warn / err) | 5.91–7.17 | 9.12–10.76 |
328
-
329
- The tightest pair in the sheet is text on the amber fill in light mode, at
330
- 5.41:1.
331
-
332
- Motion is gated behind `prefers-reduced-motion`, focus uses a visible ring at
333
- `:focus-visible`, and the component layer is driven by the same ARIA attributes
334
- assistive technology reads.
335
-
336
- ## Size
337
-
338
- | File | Raw | Gzip |
339
- |---|---:|---:|
340
- | **fertig.min.css** | **36.7 KB** | **8.6 KB** |
341
-
342
- Measured with `gzip -9`; KB = 1024 bytes.
343
-
344
- ## Overriding it
345
-
346
- The sheet declares two layers, `@layer fertig, fertig-a11y` — the second holds
347
- the forced-colors block so it can beat a `.card` shadow on layer order instead
348
- of `!important`. Anything you write outside a layer beats both whatever the
349
- specificity, so overriding is never a fight:
350
-
351
- ```css
352
- button { background: hotpink } /* wins, no !important needed */
353
- ```
354
-
355
- ## Modern CSS, used deliberately
356
-
357
- Everything past the floor sits behind `@supports` and is additive:
358
- `contrast-color()` picks the light or dark text colour on your accent and a
359
- small mix keeps it away from absolute black or white; anchor positioning
360
- attaches popover menus to their button;
361
- `::details-content` with `interpolate-size` animates disclosures open;
362
- `field-sizing` grows textareas; `text-box: trim-both` sits headings on their
363
- cap height; and
364
- `appearance: base-select` styles the dropdown picker itself. Without any of it,
365
- nothing breaks. Relative colour (`oklch(from …)`) is on that list too, for one
366
- job only: lightening the filled button on hover in OKLCH. The shadow alphas
367
- that used to need it are taken with `color-mix` against `transparent` instead —
368
- pixel-identical, and three years older, which is what keeps Safari 17.5 inside
369
- the floor. Two things are *not* on the list because they are part of the floor:
370
- `@property`, which types the shadow alphas so elevation can transition, and
371
- `container-type` on `.card`, which makes every card a container you can write
372
- `@container` queries against.
373
-
374
- It also answers to user and device preferences: `prefers-reduced-motion`,
375
- `prefers-contrast`, `forced-colors`,
376
- `pointer: coarse` (44px targets, WCAG 2.5.8), `env(safe-area-inset-*)`,
377
- `update: fast` (e-ink never starts a transition), `inverted-colors` and
378
- `color-gamut: p3`.
379
-
380
- And it survives content it has never seen: a pasted URL wraps instead of
381
- widening the page, tables scroll themselves on a phone, autofilled fields are
382
- repainted so the browser yellow never shows, required and read-only fields
383
- read correctly, numerals are slashed and tabular, and print gets real page
384
- margins with no stranded lines.
385
-
386
- ## Browser support
387
-
388
- The two-year window is on *browsers*, not on CSS. fertig runs in anything
389
- released since August 2024. The CSS it uses is mostly older than that:
390
- `@layer` has been cross-engine since 2022, `oklch()` and `color-mix()` since
391
- 2023, `light-dark()` since May 2024. The newest thing it *requires* is
392
- `@starting-style`, cross-engine since August 2024 — nothing it needs shipped
393
- inside the last two years.
394
-
395
- It carries almost nothing for the browsers before that: no polyfills, no
396
- fallback build, and no vendor prefixes beyond the three no engine has replaced
397
- (`-webkit-text-size-adjust`, the `-webkit-text-fill-color` autofill repaint,
398
- and the `progress` pseudo-elements). The one concession is a `@supports not
399
- (color: light-dark(…))` block restating the palette in flat sRGB — without it
400
- an engine that lacks `light-dark()` gets invalid colour tokens and lands
401
- unreadable rather than plain.
402
-
403
- | Engine | Minimum | Set by |
404
- |---|---|---|
405
- | Chrome / Edge | **123** | `light-dark()` |
406
- | Safari | **17.5** | `light-dark()`, `@starting-style`, `text-wrap: balance` |
407
- | Firefox | **129** | `@starting-style`, `transition-behavior` |
408
-
409
- No component needs more than that floor — anything a component would *like* to
410
- have it asks for through `@supports`. Anchor positioning, for instance, is
411
- gated; without it `[popover]` menus centre on screen instead of sitting under
412
- their button. Below the floor everything degrades to unstyled-but-readable
413
- HTML.
414
-
415
- Per-component and per-enhancement version tables, with the shipping dates
416
- behind them, are in [`docs/browser-support-research.md`](docs/browser-support-research.md)
417
- and on the [docs site](https://moji2002.github.io/fertig/docs.html#support).
418
-
419
59
  ## Development
420
60
 
421
61
  ```sh
422
- npm run hooks:install # enable the committed pre-commit hook in this clone
423
- npm run check # run the same complete gate manually
424
- npm run build # regenerate fertig.min.css and print sizes
425
- npm run site # build the site into dist/ with Eleventy
426
- npm run site:serve # build + live-reload on :8080 (the Eleventy dev server)
427
- npm run sizes # sync the size claims in README + site copy
62
+ npm install
63
+ npm run hooks:install # enable automatic patch versioning for commits
64
+ npm run build # regenerate fertig.min.css
65
+ npm test # library and site tests
66
+ npm run site # Astro production build
67
+ npm run site:serve # Astro development server
68
+ npm run check # complete release check
428
69
  ```
429
70
 
430
- The pre-commit gate is read-only for tracked files. It rejects whitespace
431
- errors, inconsistent release versions, stale minified CSS, stale size claims,
432
- bundle-budget regressions, test failures, invalid site output and unexpected
433
- package contents. If a generated file or size claim is stale, run the command
434
- named by the failure, review the diff, and commit it deliberately.
435
- Tracked changes must be fully staged, preventing an unstaged fix from hiding a
436
- broken staged snapshot during validation.
437
-
438
- ## Builds
439
-
440
- | Build | Raw | Gzip | |
441
- |---|---:|---:|---|
442
- | `fertig.min.css` | 36.7 KB | 8.6 KB | everything |
443
-
444
- ## Files
445
-
446
- The sheet:
447
-
448
- - `fertig.css` — source, commented
449
- - `fertig.min.css` — minified, what you ship
450
- - `build.js` — minifier and size report
451
-
452
- The site (Eleventy, output to `dist/`):
453
-
454
- - `src/_includes/layout.njk` — shared document shell and navigation
455
- - `src/_includes/{page-header,footer}.njk` — shared inner-page header and footer
456
- - `src/_data/site.js` — version pulled from `package.json` (the one source of truth)
457
- - `src/{index,docs,components,blocks}.njk` — the only authored page sources
458
- - `site.css`, `site.js`, `icons.svg`, `favicon.svg` — the site's own chrome,
459
- none of it part of the sheet
460
- - `dist/` — the built site that GitHub Pages deploys
461
-
462
- Everything else:
463
-
464
- - `llms.txt` — machine-readable summary for LLMs, per llmstxt.org
465
- - `CHANGELOG.md` — what changed and why, per release
466
- - `docs/classless-css-research.md` — the research behind the decisions
467
-
468
- The sheet itself ships without the site — the npm package holds the two CSS
469
- files plus the README and licence, nothing else.
71
+ The package publishes only `fertig.css`, `fertig.min.css`, this README, and the
72
+ MIT license. The Astro site lives in `src/pages`, with its shared shell in
73
+ `src/layouts` and `src/components`.
470
74
 
471
75
  ## License
472
76
 
473
- MIT © Mojtaba Beheshti
77
+ MIT