# largen 0.6.3: the complete authoring contract A property algebra for CSS. Plain CSS, with no build step, no preprocessor and no plugin. TOKENS --canvas --ink --surface --line, --primary/--primary-on … theme sets these SLOTS --bg --fg --pad --gap --radius --font-size … library, fixed AXES tone · variant · size · state library, fixed PAINT one universal rule library, fixed ───────────────────────────────────────────────────────────────────────────────────── UTILITIES stack row cluster center grid switcher sidebar library, fixed ───────────────────────────────────────────────────────────────────────────────────── COMPONENTS whatever this project needs ← YOU WRITE THESE Only the last row grows. A component is about six lines because everything above it is already solved. The tones, the variants, the sizes, the states and both themes are supplied by the rows it never mentions. ## Writing a component @layer largen.components { .notification, notification { --bg: var(--tone-soft); --fg: var(--tone-ink); --border-width: 0 0 0 3px; --border-color: var(--tone); --border-style: solid; --radius: var(--radius-md); --pad: .75em 1em; --gap: .75em; display: grid; grid-template-columns: auto 1fr; align-items: center; } } Two accounts need review.
…same thing…
That is a complete component: seven tones, four variants, five sizes, every state and both themes, none of which it mentions. ## Slots --bg --fg --border-color --border-width --border-style --radius --pad --gap --font-size --weight --line-height --letter-spacing --shadow --transition A slot splits deciding a value from applying it. Plain CSS does both in one rule, so every change after that needs another rule that knows the component. Here a component only fills blanks, `--bg: var(--tone-soft)`, and one shared rule applies them. A rule like `[data-variant="outline"] { --bg: transparent }` knows nothing about any component, so it works on all of them, including ones not written yet. The cost of the system drops from axes times components to axes plus components. Every component is painted from these slots and only these. All are registered `inherits: false` with no `initial-value`, so a component's background cannot cascade onto its children, and an unset slot stays guaranteed-invalid. That is what makes `var(--pad, revert-layer)` hand the property back to the UA stylesheet. @property --bg { syntax: "*"; inherits: false; } @property --fg { syntax: "*"; inherits: false; } @property --border-color { syntax: "*"; inherits: false; } @property --border-width { syntax: "*"; inherits: false; } @property --border-style { syntax: "*"; inherits: false; } @property --radius { syntax: "*"; inherits: false; } @property --pad { syntax: "*"; inherits: false; } @property --gap { syntax: "*"; inherits: false; } @property --font-size { syntax: "*"; inherits: false; } @property --weight { syntax: "*"; inherits: false; } @property --line-height { syntax: "*"; inherits: false; } @property --letter-spacing { syntax: "*"; inherits: false; } @property --shadow { syntax: "*"; inherits: false; } @property --transition { syntax: "*"; inherits: false; } @property --scale { syntax: ""; inherits: true; initial-value: 1; } Inheriting, registered: --scale Inheriting, unregistered: --tone --tone-contrast --tone-ink --tone-line --tone-soft `--scale` is the only *registered* inheriting property: it is declared `@property --scale { syntax: ""; inherits: true; initial-value: 1 }`, so it is type-checked and animatable. `--tone` and its derivations are not registered at all. They inherit because inheritance is the default for a custom property. The distinction matters: only a registered property is checked against a syntax, only a registered property can be transitioned, and only a registered universal property with no initial value becomes guaranteed-invalid when unset. ## The paint rule * { color: var(--fg, revert-layer); background-color: var(--bg, revert-layer); border-width: var(--border-width, revert-layer); border-style: var(--border-style, revert-layer); border-color: var(--border-color, revert-layer); border-radius: var(--radius, revert-layer); padding: var(--pad, revert-layer); gap: var(--gap, revert-layer); font-size: var(--font-size, revert-layer); font-weight: var(--weight, revert-layer); line-height: var(--line-height, revert-layer); letter-spacing: var(--letter-spacing, revert-layer); box-shadow: var(--shadow, revert-layer); transition: var(--transition, revert-layer); } One rule reads the slots and applies them to every element. It is safe universally only because an unset slot is guaranteed-invalid, so `var(…, revert-layer)` fires and hands the property straight back to the UA stylesheet. A `