system.cssthe engine GitHub

Utilities

The utility layer of system.css, read from the file at build time: 56 rules. A utility is a single-purpose word a usage site composes with the primitives; it cascades after the components so it wins where it is worn. The note is the comment above the rule; the wearers are the lab pages whose markup carries the word.

WordSelectorRuleNoteWorn in the lab
.active:where(.active)--bg: 0.3; background-color: var(--_bg); --fg: var(--_sem-ink, -1); font-weight: 600;.active — THE transient-highlight utility (gf-191, per Mike): the standard active-row paint for CLIENT-owned, momentary emphasis (a combobox's keyboard row, a rocket's "this one"). Global on purpose — utilities are the layer for exactly this. Not for real current-ness: aria-current keeps pages/steps, aria-pressed keeps toggles.State
.suc:where(.suc)--hue-lock: var(--hue-suc); --_sem-ink: 1semantic hue helpers — lock hue + flag components to commit inkCompositions Forms Primitives rocket-combo-box rocket-toast-card Stack
.inf:where(.inf)--hue-lock: var(--hue-inf); --_sem-ink: 1Compositions Drawers Motion Primitives rocket-toast-card Stack Wash
.wrn:where(.wrn)--hue-lock: var(--hue-wrn); --_sem-ink: 1Compositions Forms Primitives rocket-toast-card Stack
.dgr:where(.dgr)--hue-lock: var(--hue-dgr); --_sem-ink: 1Compositions Drawers Primitives rocket-combo-box rocket-hold-confirm Stack
.is-event.is-event--hue-shift: -30;Kind identity: events and activations are the same base hue, offset ±30 so they read as related-but-distinct everywhere. The engine does the rest; semantic --hue-lock pills (status) still override.Compositions
.is-activation.is-activation--hue-shift: 30;Compositions
.bw:where(.bw)--chroma: 0;black & white — the one mono mechanism
.glass:where(.glass)background-color: color-mix(in oklch, var(--_bg) calc(var(--glass-alpha, 0.65) * 100%), transparent); -webkit-backdrop-filter: blur(var(--glass-blur, 0.5lh)); backdrop-filter: blur(var(--glass-blur, 0.5lh)); --surf: var(--_bg); --surf-bg: var(--bg);frosted surface — the engine's own resolved surface, translucent, over a backdrop blur. Publishes like .bg. Knobs: --glass-alpha (0.65 — a dialog over its dimmed backdrop) · --glass-blur (0.5lh). Needs content BEHIND it to read as glass. TWO RULES (EventOS 2026-10-05, toasts over a map unreadable): an overlay that must read over ANYTHING — a hud card — raises --glass-alpha (0.88; a toast wears 0.75 and shows a little of what is behind it); and quiet is INK (--fg), never opacity on the card — opacity multiplies into the glass and the words go with it.Compositions Drawers Primitives rocket-toast-card
.oneline:where(.oneline)flex-wrap: nowrap;.oneline — a row that must not wrap (header clusters, icon pairs). Composition class: replaces inline flex-wrap styles.Color Compositions Icons Primitives Stack Vocabulary
.start:where(.start)align-items: start;.start — a composition whose items align to the block start (an icon beside multi-line text). Replaces inline align-items.Compositions
.tl:where(.hud) > :where(.tl)place-self: start starthud slots — promoted past components so .cr etc. override a component's own place-self (the fab default is end/end).Compositions
.tc:where(.hud) > :where(.tc)place-self: start centerCompositions
.tr:where(.hud) > :where(.tr)place-self: start endCompositions
.cl:where(.hud) > :where(.cl)place-self: center startCompositions
.cc:where(.hud) > :where(.cc)place-self: center centerCompositions
.cr:where(.hud) > :where(.cr)place-self: center endCompositions
.bl:where(.hud) > :where(.bl)place-self: end startCompositions
.bc:where(.hud) > :where(.bc)place-self: end centerCompositions
.br:where(.hud) > :where(.br)place-self: end endCompositions rocket-toast-card
.tl .tr .bl .br:where(.hud) > :where(.tl, .tr, .bl, .br)padding: 1lh; gap: var(--gap, 0.5lh);a corner slot used as a STACK of hud triggers: breathing room from the viewport edge, tight rhythm between members, members hug the corner.Compositions rocket-toast-card
.br .toasts:where(.page:has(> .hud.mobile)) ~ :where(.hud) > :where(.br.toasts)padding-block-end: 4lh;THE TOAST PILE'S CLEARANCE (gf-409, 2026-09-24): above the fab cluster where a phone hud is on, above the dock where a main footer is — HERE, in the slot's own layer: the components-layer copy had lost to this padding for as long as it existedCompositions rocket-toast-card
.br .toasts:where(.page:has(> .pg-main-footer)) ~ :where(.hud) > :where(.br.toasts)padding-block-end: 9lh;Compositions rocket-toast-card
.tr .br .column:where(.hud) > :where(.tr, .br):where(.column)align-items: flex-end;Compositions rocket-toast-card ARIA Charts Code Color Drawers Forms Icons Motion Primitives rocket-activation-tracker rocket-bug-report rocket-combo-box rocket-command-palette rocket-date-picker rocket-day-picker rocket-element-pick rocket-exif rocket-google-maps rocket-group-pick rocket-hold-confirm rocket-image-input rocket-mini-calc Stack State Type Vocabulary Wash
.tl .bl .column:where(.hud) > :where(.tl, .bl):where(.column)align-items: flex-start;Compositions ARIA Charts Code Color Drawers Forms Icons Motion Primitives rocket-activation-tracker rocket-bug-report rocket-combo-box rocket-command-palette rocket-date-picker rocket-day-picker rocket-element-pick rocket-exif rocket-google-maps rocket-group-pick rocket-hold-confirm rocket-image-input rocket-mini-calc rocket-toast-card Stack State Type Vocabulary Wash
.fill:where(.fill)inline-size: 100%;
.grow:where(.grow)flex: 1 1 auto; min-block-size: 0;.grow — the block-axis complement to .fill: take the leftover space in a flex chain AND stay shrinkable (min-block-size: 0 defeats the auto-min). Chain it from a region's child down to a .scroll-y and the INNER surface becomes the scroller instead of the region.Compositions Vocabulary
.grow:where(mini-map.grow)aspect-ratio: auto; flex-basis: 0; min-block-size: 3lh;a growing box with an aspect (mini-map) takes the share its column has left, not its aspect: beside a sibling card that sets the row, it absorbs the difference (EventOS local feedback #28); 3lh keeps it legible when there is no shareCompositions Vocabulary
.container:where(.container)container-type: inline-size;.container — the generic self-measuring wrapper: content inside it gates on ITS width (cards in a grid, widgets in a flank).Compositions Vocabulary
.scroll-x:where(.scroll-x)overflow-x: auto; overscroll-behavior: contain; min-inline-size: 0;scroll viewports — the axis scrolls; pair with a constrained size (a flex/grid track, a max-block-size, etc.) since something must bound the box for it to scroll. min-*-size:0 defeats the flex/grid auto-min so it can shrink-and-scroll inside a parent; overscroll-behavior:contain stops scroll-chaining to the page.Color rocket-bug-report
.scroll-y:where(.scroll-y)overflow-y: auto; overscroll-behavior: contain; min-block-size: 0; scrollbar-gutter: stable;Vocabulary
:where(.row, .column, .spread, .spread-column, .lcr) > :where(hr)margin-block: 0;an hr inside a composition is a LINE, not a spacer — the gap owns the rhythm. Kills the app-wide `style="margin: 0"` hr pattern.
.nowrap:where(.nowrap)white-space: nowrap;Vocabulary
.stress:where(.stress)resize: both; overflow: auto; min-inline-size: 14rem;.stress — the lab's resize handle (gf-175, per Mike: "give each form a resize so we can stress test"). Drag the corner; the specimen reflows at any width — and any height since the blocks (gf-608: a block answers its height too). A LAB utility — product surfaces size by composition, not by handles.Compositions Forms rocket-combo-box
.truncate:where(.truncate)white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-inline-size: 0;Icons
.content-1:where(.content-1)--content: var(--content-1);.content-1 · .content-2 · .content-3 — a surface centred at a rung of THE CONTENT LADDER (the tokens in theme; 2026-10-01, replacing .measure + --measure, which said the word twice): the class names the rung, the rule is one for all three. It fills anything narrower. The dialog wears the same words — .modal reads --content with rung 2 as its default, so a confirm is a .modal.content-1 and a workbench a .modal.content-3; one ladder, two kinds of surface. Rosters take no rung: they fill the canvas.Motion Primitives Vocabulary
.content-2:where(.content-2)--content: var(--content-2);Vocabulary
.content-3:where(.content-3)--content: var(--content-3);Compositions Primitives Vocabulary
.content-1 .content-2 .content-3:where(.content-1, .content-2, .content-3)inline-size: 100%; max-inline-size: var(--content); margin-inline: auto;Motion Primitives Vocabulary Compositions
.center:where(.center)text-align: center;(.type-flow is RETIRED, gf-68 — --type inherits natively now; the class was the opt-in workaround and its utility-layer rule squashed component-set steps, which the native cascade respects.)Color
:where(.center) > :where(svg)margin-inline: auto;
.vh:where(.vh)position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;a declared-box glyph centres like the text beside it (EventOS gf-580)
.np@media print :where(.np)display: none !important;Compositions
:where([data-ui-state="on"])border-color: var(--focus); box-shadow: inset 0 0 0 1px var(--focus);
.tag:where([data-ui-state="off"]:not(.tag))filter: grayscale(1) opacity(0.5);ARIA Charts Compositions Drawers Primitives rocket-combo-box rocket-group-pick Stack State Vocabulary
:where(.card) :where(table)border: 0; border-radius: 0; background: none;FRAME-IN-FRAME, table edition (moved from components, gf-24 — it lived there as a DEAD rule: the table recipe sits later in that layer and out-ordered it at zero specificity, which is exactly the "weird borders" a card-hosted table showed): the card owns the frame; a table inside one keeps only its two vibrant rules.
:where(span[data-ui-state="on"]:has(> svg:only-child))border: 0; box-shadow: none; --fg: 1;── data-ui-state, generalized past tags (gf-25, per Mike) ────────── The on-ring recipe (border + inset focus ring) needs a BOX; a bare icon holder — a span whose whole content is one svg — can't wear it. "on" commits full-chroma ink instead (the engine's own emphasis grammar); "off" keeps the standard grayscale quiet from above.
.menu:where(.menu):not(:popover-open)pointer-events: none;.menu plumbing — must out-rank the button paint in components. ⚠ display/align/padding are set HERE, not assumed: a bare <a> row has no button recipe behind it, and without flex its icon and label stack.ARIA Primitives rocket-combo-box rocket-group-pick
:where(.menu) > :where(button, a)display: flex; align-items: center; flex-direction: row; inline-size: auto; block-size: auto; justify-content: flex-start; gap: 0.5em; min-block-size: 1.7lh; padding: 0 0.8em; border: 0; --lift: initial; --bg: initial; background: transparent; box-shadow: none; text-decoration: none; --fg: var(--_sem-ink, -0.85); font-weight: 500; border-radius: max(0px, calc(var(--cfg-radius) - 3px));
:where(.menu) > :where(button, a) > :where(svg)inline-size: 1.15em; block-size: 1.15em; flex: 0 0 auto;
:where(.menu) > :where(button, a):hover--bg: 0.16; background-color: var(--_bg);
:where(.menu) > :where(button, a):where([aria-current="page"], [aria-pressed="true"], [aria-selected="true"])--bg: 0.3; background-color: var(--_bg); --fg: var(--_sem-ink, -1); font-weight: 600;current/selected row — same grammar as .nav-item: state rides ARIA, and aria-selected joins it (gf-191, per Mike: the correct key for a listbox's chosen row — generalized here like .tabs already does). Transient client highlights wear the global .active utility instead.
:where(.menu) :where(mark)background: transparent; --fg: 1;NO color property here: the core pipeline computes ink from --fg — an explicit color would override it (the palette's mark knows).
:where(.menu) > :where(div[role="option"])display: flex; align-items: center; gap: 0.25em; min-block-size: 1.7lh; padding-inline: 0.8em 0.3em; border-radius: max(0px, calc(var(--cfg-radius) - 3px)); & > :where(button) { border: 0; --lift: initial; --bg: initial; background: transparent; box-shadow: none; min-block-size: 0; padding: 0; } & > :where([data-gp-pick]) { flex: 1 1 auto; display: flex; align-items: center; justify-content: flex-start; gap: 0.5em; text-align: start; --fg: var(--_sem-ink, -0.85); font-weight: 500; } & > :where([data-gp-pick]) > :where(svg) { inline-size: 1.15em; block-size: 1.15em; flex: 0 0 auto; } & > :where([data-gp-edit], [data-gp-del], [data-gp-save]) { --fg: -0.5; } & > :where([data-gp-del]):disabled { --fg: -0.25; } & > :where([data-gp-rename]) { flex: 1 1 auto; min-inline-size: 0; inline-size: auto; min-block-size: 0; padding-block: 0.1em; margin-block: 0.15lh; } &[data-ui-state="editing"] > :where([data-gp-pick], [data-gp-edit], [data-gp-del]) { display: none; } & > :where([hidden]) { display: none; } &:hover, &:where(.active, [aria-selected="true"]) { --bg: 0.16; background-color: var(--_bg); } &:where(.active, [aria-selected="true"]) > :where([data-gp-pick]) { --fg: var(--_sem-ink, -1); font-weight: 600; } &[hidden] { display: none; }── group-pick rows (gf-385): a menu row that is a DIV holding two buttons — the pick (grows, reads as the row) and the delete glyph at the end. Same height, hover and selected paint as a button row; the row's own buttons drop the button recipe. A disabled delete (the group is in use) stays visible, dimmed. ──
:where(.menu) > :where([data-gp-empty])display: block; padding: 0.3lh 0.8em;
:where(.menu) > :where([data-gp-empty])[hidden]display: none;