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.
| Word | Selector | Rule | Note | Worn 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: 1 | semantic hue helpers — lock hue + flag components to commit ink | Compositions Forms Primitives rocket-combo-box rocket-toast-card Stack |
.inf | :where(.inf) | --hue-lock: var(--hue-inf); --_sem-ink: 1 | Compositions Drawers Motion Primitives rocket-toast-card Stack Wash | |
.wrn | :where(.wrn) | --hue-lock: var(--hue-wrn); --_sem-ink: 1 | Compositions Forms Primitives rocket-toast-card Stack | |
.dgr | :where(.dgr) | --hue-lock: var(--hue-dgr); --_sem-ink: 1 | Compositions 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 start | hud 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 center | Compositions | |
.tr | :where(.hud) > :where(.tr) | place-self: start end | Compositions | |
.cl | :where(.hud) > :where(.cl) | place-self: center start | Compositions | |
.cc | :where(.hud) > :where(.cc) | place-self: center center | Compositions | |
.cr | :where(.hud) > :where(.cr) | place-self: center end | Compositions | |
.bl | :where(.hud) > :where(.bl) | place-self: end start | Compositions | |
.bc | :where(.hud) > :where(.bc) | place-self: end center | Compositions | |
.br | :where(.hud) > :where(.br) | place-self: end end | Compositions 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 existed | Compositions 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 share | Compositions 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; |