diff --git a/CHANGELOG_FULL.md b/CHANGELOG_FULL.md deleted file mode 100644 index 46cc15215..000000000 --- a/CHANGELOG_FULL.md +++ /dev/null @@ -1,499 +0,0 @@ -# SLASHED Changelog - -Complete development history from v0.1.0 through v0.5.24, organized by category and version. - -## Contents -- [Framework](#framework) -- [Plugins](#plugins) - ---- - -## Framework - - -### v0.1.0 - -- **#42** — add v0.1.0 entries for last 7 merged PRs (Phases 1–6) - > Covers PRs #34–41: truthfulness foundation, WCAG AA token fix, print colour -- **#43** — use oklab for palette color-mix to prevent hue drift - > Two fixes addressing palette correctness and demo page performance: -- **#44** — comprehensive visual tests + missing layout demos - > - Replace text-only layout references in docs/demo.html with proper visual demonstrations -- **#45** — tighten assertions flagged in PR #44 review - > - Replace permissive regex on .is-loading color with an explicit -- **#46** — tighten visual test assertions and clarify customizer labels - > - Tighten .is-loading color assertion — replace the loose /rgba?\(.*0\)|transparent/ regex (which could falsely pass on opaque rgb() values containing -- **#47** — completion checklist — framework coverage benchmark - > Comprehensive completion checklist for bringing the existing SLASHED layers to 100% — benchmarked against a comparable utility-class feature set (closest match, ~85% overla -- **#48** — API freeze prep — contrast docs, optional forms, npm exports - > Zamyka ostatnie potencjalne źródła breaking changes przed rozpoczęciem pracy nad komponentami i utilities. -- **#49** — update TOKENS CONSUMED comment to match actual usage - > Align the documented token list in optional/forms.css header comment with the actual CSS custom properties used after the token-name correction in PR -- **#50** — Premium furniture store homepage (FORMA) - > Premium furniture store homepage FORMA built entirely using the SLASHED CSS framework. -- **#51** — Production-readiness checklist v2 - > Complete production-readiness audit for SLASHED CSS framework v1.0, benchmarked against 7 industry references: -- **#52** — repair broken interactive demos in docs/demo.html - > Addresses the issues you reported in /docs/demo.html. Each fix is surgical and targets the specific demo that misbehaved — no library API changes, jus -- **#53** — Add production readiness checklist v3 with implementation decisions - > This PR introduces audits/completion-checklist-v3.md, a comprehensive production readiness audit that supersedes v2. Unlike v2 (which was an inventory -- **#54** — Add D11 — token alias-chain hygiene & API-surface freeze to checklist v3 - > Follow-up to the merged checklist v3 (#53). Adds a token API-freeze checkup based on a full var()-graph audit of all 562 token definitions. -- **#55** — foundation polish for v0.2.0 (checklist v3 §F batch) - > Wire up declared-but-unused base/print tokens, fix two form bugs, ship -- **#56** — move container-type to parent for sf-grid-6 and ratio grids - > @container queries look for an ancestor container, not the element -- **#57** — comprehensive optimal bundle index & inventory - > Full indexing and inventory of the slashed.optimal.css bundle — every token, class, alias, keyframe, and cascade relationship mapped and analysed for -- **#58** — refined comparative gap audit prompt v2 - > Adds a comprehensive, source-verified audit prompt (audits/comparative-audit-prompt.md) designed to produce a definitive gap analysis of SLASHED again -- **#59** — add flat (unlayered) bundle option for page builders - > Adds a flat: true per-bundle option to bundle.config.json that strips the SLASHED @layer scaffolding before emit. First consumer is dist/slashed.brick -- **#62** — comprehensive comparative gap audit - > Adds a full comparative gap audit of SLASHED v0.2.10 (commit 4d0103e) against four benchmark frameworks: -- **#63** — clean up repo structure and gitignore - > Brings the repo in line with best practices for a published CSS framework: -- **#64** — restore jsDelivr CDN link so demo works without local build - > - Reverts the demo's CSS ` tags from local relative paths back to the jsDelivr @main CDN URLs that were in use prior to commit 26658d5`. -- **#65** — re-commit dist/ to unbreak jsDelivr @main CDN URLs - > Reverts the dist/ removal from #63 so the jsDelivr CDN URLs that #64 restored (and any external user pinning to @main) keep working. -- **#66** — build dist on merge to main, publish to dedicated `dist` branch - > Replaces the per-commit dist regeneration (via the .githooks/pre-commit hook) with a once-per-merge GitHub Action that publishes built CSS bundles to -- **#68** — fix 4 factual inaccuracies in comparative-gap-audit.md - > The comparative gap audit (audits/comparative-gap-audit.md) contained 4 major factual errors where it claimed features were missing that actually exis -- **#70** — fix documentation vs CSS discrepancies - > Fixes 11 documentation vs CSS discrepancies identified during a full audit of the codebase. -- **#72** — attach all dist bundles to releases + backfill CHANGELOG - > Fixes two issues with the release workflow: -- **#73** — use clamp() for dark-mode link lightness (WebKit) - > Fixes the CI regression test failure: [webkit] › a11y.spec.js › axe: no WCAG A/AA violations (dark). -- **#75** — trigger CI to verify regression tests after PR #73 webkit fix - > This is a small dummy-style PR primarily intended to trigger CI one more time and verify whether the Regression tests job now passes after the WebKit -- **#76** — use a:link selector to win over WebKit UA stylesheet (dark-mode link contrast) - > Replaces the WebKit dark-mode link contrast fix from PR #73 (which didn't actually work) with one that does. Fixes the WCAG AA failure flagged by axe- -- **#77** — add admin GUI for editing SLASHED design tokens - > Adds a full WordPress admin settings page to the Bricks Builder integration plugin for visually editing all user-customizable SLASHED design tokens. -- **#78** — connect orphaned tokens and close page-property control gaps - > Four tokens were defined but never consumed by the framework, making - -### v0.2.0 - -- **#30** — v0.2.0: bugfixes from quality audit + token enrichment + a11y/docs/tooling - > Doprowadza framework do stanu opisanego w zatwierdzonym 7-fazowym planie: 3 bugfixy z audits/quality-audit-2024-full.md, 5 warningów rozstrzygniętych -- **#32** — show auto-derived dark colors in the configurator - > Follow-up to #29. The theme configurator's dark color pickers were seeded from a hardcoded TOKEN_DEFAULTS table, which: -- **#33** — Add comprehensive comparative audit against reference CSS frameworks - > This PR adds a detailed comparative audit of SLASHED against a curated set of reference CSS frameworks -- **#34** — Phase 1: truthfulness foundation — themes layer extraction, bundle scope, browser floor accuracy - > Phase 1 of the perfection roadmap from audits/comparative-audit-2026.md Resolution Log. Foundation pass — no behavioural changes, no breaking changes. -- **#35** — clear WCAG AA Normal by default for every brand & status on-color (Phase 2) - > Phase 2 of the perfection roadmap. Tightens the default brand & status palette so every on-color foreground clears WCAG AA Normal (4.5:1) by default — -- **#36** — WCAG AA Normal by default for every brand & status on-color (Phase 2 redo) - > Phase 2 (#35) was approved and clicked-merge, but its base.ref was chore/phase-1-truthfulness (the now-deleted Phase 1 branch) instead of main. After -- **#37** — preserve authored colour by default; opt-in .print-color-exact / .print-no-color (Phase 3) - > Phase 3 of the perfection roadmap. Reverses the print-stylesheet colour contract: authored colour is preserved by default, ink-on-paper is now an opt- -- **#38** — comparative audit of framework coverage (2026-05-20) - > Adds a single new file: audits/comparative-audit-2026-05-20.md (1501 linii, narracja po polsku, nagłówki sekcji po angielsku zgodnie ze specyfikacją a -- **#39** — name container queries — sf-layout and sf-alternate (Phase 4) - > Phase 4 of the perfection roadmap. Names two of the framework's container-query containers and binds one framework-internal query to a name. The remai -- **#40** — Phase 5 — Motion API polish - > Phase 5 of the framework perfection plan. Polishes the motion/transition API, modernizes accessibility patterns, and proves @property color interpolat -- **#41** — Phase 6 — regression tests & full demo coverage - > Phase 6 — Coverage & regression tests. Completes the full audit remediation plan. - -### v0.3.0 - -- **#79** — class taxonomy + macros layer + components blueprint - > Class taxonomy refactor for v0.3.0. Introduces the new slashed.macros cascade layer, ships 12 macro recipes, adds 3 recipe-coverage essentials (icon-boxed -- **#80** — add workflow_dispatch trigger to release workflow - > Allows publishing a release manually (e.g. v0.3.0) without needing to -- **#82** — replace 'blueprint' with plain language - > Replaces the word "blueprint" across docs, README, CHANGELOG, and CSS file headers with plain language ("not yet complete", "commented out", "8 compon -- **#85** — POC: Svelte 5 admin page (alongside legacy jQuery one) - > Hypothetical, non-merging PR. Goal: see what adopting Svelte 5 for the admin settings page actually looks like in this codebase. Discardable. -- **#86** — Replace light-dark() with FieldText system color for select chevron - > Replaces the light-dark() function with the CSS system color FieldText for the select element chevron SVG stroke. This simplifies the implementation w -- **#87** — bump softprops/action-gh-release from 2 to 3 - > Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2 to 3. -- **#88** — bump actions/upload-artifact from 4.6.2 to 7.0.1 - > Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.2 to 7.0.1. -- **#89** — bump actions/checkout from 4 to 6 - > Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6. -- **#90** — bump actions/setup-node from 4 to 6 - > Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 6. -- **#91** — surface macros, entrance effects, unified lightness, section collapse - > Implements the full Tier 1 feature set discussed in the framework audit session: -- **#93** — surface macros, entrance effects, unified lightness, section collapse (replaces #91) - > Replaces #91, which got tangled in non-fast-forward state after PR #92 landed and could not be cleanly updated in place. -- **#94** — Add comprehensive public API audit for SLASHED v0.3.0 - > This PR adds a detailed public API audit document (audits/audit-c.md) for SLASHED v0.3.0, conducted on 2026-05-25. The audit comprehensively reviews t -- **#95** — pre-freeze API audit (audit-b) for v0.3.0 - > Full public API audit of the SLASHED framework v0.3.0, performed before the API freeze. -- **#96** — pre-freeze API audit for v0.3.0 - > Full public API audit of SLASHED v0.3.0 before the token-API freeze. The audit reads every source file (core/*.css, active optional/*.css, all docs/*. -- **#99** — admin panel full API coverage + cheatsheet (v2) - > This PR supersedes #98 with review feedback fixes applied. -- **#100** — address PR #98 review feedback (a11y, timer, tab separation) - > Addresses all CodeRabbit review comments from PR #98.\n\n## Changes\n\n- BundleTab.svelte: Prevent overlapping success timers on rapid saves (track/cl -- **#101** — add canonical token/class counter as single source of truth - > Introduce scripts/audit.js + docs/registry.json to eliminate count -- **#102** — Depersonalize framework references in docs and comments - > Replace named third-party framework references in documentation and source comments with neutral wording. -- **#104** — API freeze - new tokens, hardcode fixes, cleanup - > Prepares the token layer for API freeze by: -- **#107** — PUBLIC/ADVANCED/INTERNAL contract + docs sync - > Completes the PUBLIC/ADVANCED/INTERNAL token classification and syncs documentation with code for the v0.3.0 API freeze. -- **#110** — dual-mode link selection, built-in focus ring, broader lifting - > Explicit mode: add [data-overlay-link] to the primary link and every -- **#111** — rebuild minified bundles to purge stale vendor wording from sourcemaps - > Rebuilds all 10 minified CSS bundles and their sourcemaps to remove a stale vendor-specific comment that survived PR #102's framework-name cleanup. -- **#112** — Remove all third-party CSS framework references - > Strip mentions of specific framework names and comparative advantage claims -- **#113** — Pre-freeze cleanup: drop deprecated, consolidate hover, canonical xs..2xl scale - > Pre-freeze cleanup. Single PR, no version bump (no users yet). Five logical commits: -- **#115** — Standardize hover color variable naming convention - > This PR standardizes the naming convention for hover state color variables across the design system by replacing double-dash separators (--) with sing -- **#117** — Add .sf-gap and .sf-equal layout utility classes - > Adds layout-agnostic gap utilities and a fixed equal-column grid system to provide more flexible spacing and grid options for developers. -- **#118** — resolve pre-freeze audit items (9 remaining 🟠) - > Addresses all remaining 🟠 items from the v0.3.0 API audit. After this PR, the only open items are 🟡 (cosmetic/historical, safe to defer). -- **#121** — pre-freeze audit fixes (rebased onto main) - > Rebased PR #118 (audit-fixes-pre-freeze) onto current main (which now includes PRs #116, #117, #120). All merge conflicts resolved. -- **#126** — resolve pre-freeze API audit findings - > Resolves all findings from the pre-freeze API audit (9 issues across documentation drift, naming inconsistencies, and tooling gaps). -- **#127** — auto-bundle WordPress plugin zip in dist folder - > Adds automatic packaging of the "SLASHED for Bricks" WordPress plugin into a distributable zip (dist/slashed-bricks.zip) as part of the standard build -- **#128** — prevent node_modules from being staged on dist branch - > git rm -rf . (in the orphan checkout step) deletes .gitignore from -- **#130** — implement element-aware suggestions, auto-numbering, migrate mode, unused-class endpoint - > Stacked on #129 — branch is feat/rebemer-v1-implementations ⇐ fix/natural-sort-color-palette ⇐ main. Merge #129 first, then this. -- **#131** — Fix/natural sort color palette - > * Added "Migrate ID Styles" mode to reBEMer panel with class migration preview and summary -- **#133** — remove redundant .visually-hidden alias from .sr-only rule - > .sr-only is the canonical class name used throughout the codebase. -- **#135** — Generalize Auto-BEM references and remove vendor-specific wording - > Updated documentation to use neutral language for Auto-BEM tooling and remove vendor-specific references. -- **#136** — Add CodeSlash homepage design and layout - > Added a complete, production-ready homepage for CodeSlash — a senior WordPress developer portfolio/service site. This is a standalone HTML file with e -- **#138** — Redesign default token palette and fix selection color - > - Redesigned default color palette — all 6 brand source tokens updated for a more vibrant, internally cohesive out-of-the-box appearance; neutral bump -- **#141** — add comprehensive Playwright test suite (172 tests) - > Six spec files covering every major framework area: -- **#146** — automatic version sync on release - > Adds scripts/version-sync.js which reads the canonical version from -- **#147** — Add typography preview and improve color swatches in admin UI - > This PR enhances the Bricks admin app with a live typography scale preview component and improves the color preview to show dark mode variants and sta -- **#148** — version display, generated CSS fix, spacing step controls, type scale generator - > - Version pills in admin header: Framework version (SLASHED_BRICKS_CSS_REF) and plugin version (SLASHED_BRICKS_VERSION) now appear as small monospace -- **#149** — Sync version constants during release and update bundle size - > This PR improves the release workflow by automatically syncing version constants to match the release tag, and updates documentation to reflect curren -- **#150** — Fix OKLch color conversion matrices for accurate round-trip conversion - > This PR corrects the color conversion matrices used in the OKLch to hex and hex to OKLch conversion functions to use the standard OKLab matrices, ensu -- **#151** — richer live preview — motion, focus ring, card, dark mode toggle, CSS export - > - Replace static dark section with ☀/☾ Light/Dark toggle; all swatches, -- **#152** — dark swatches respect the dark-overrides-enabled toggle - > - Bug: When the "Custom dark mode colors" toggle was OFF, the live preview still injected explicit --sf-color-*-dark custom properties — from previous -- **#153** — remove dead code, stale artifacts, and empty placeholder - > - Delete legacy admin-page.js/.css (17KB) — PHP now enqueues admin-app/app.js/.css -- **#154** — comprehensive CSS quality review — 49 issues corrected - > - print.css: remove var() from @page (not valid there); hardcode A4/2cm -- **#155** — 16 CSS correctness issues found in systematic audit - > - layout.css: replace physical left with logical-safe approach for -- **#156** — add roadmap with pre-1.0 priorities and post-1.0 enhancements - > Captures planned work (reBEMer v1, prose tokens, contrast table, class -- **#158** — mid-apply snapshot/rollback - > - applyToSubtree() now snapshots each element's class IDs, structure-panel label, and (for migrate mode) the exact setting keys that will be deleted, -- **#159** — WCAG contrast checker + reBEMer undo batching - > - New WCAG tab in the admin settings page with two features: -- **#160** — add Jekyll _config.yml to stop Pages build failing on Liquid syntax - > - Adds a minimal _config.yml at the repo root with render_with_liquid: false -- **#161** — require class-admin-page-svelte before reBEMer enqueue (frontend fatal) - > - Adds require_once for class-admin-page-svelte.php inside slashed_bricks_rebemer_init() before instantiating Slashed_Bricks_ReBEMer_Enqueue -- **#162** — modifier ensures base class present; rename carries modifiers - > Two reBEMer apply-mode bugs related to modifier classes. -- **#165** — serve CSS from dist-branch SHA + add Layouts admin tab - > - CDN URL now uses immutable dist-branch SHA instead of the release tag, so the jsDelivr URL is stable and doesn't require CSS files to be tracked on -- **#168** — add standalone Gutenberg integration plugin (v1) - > Three files, zero Bricks dependencies — designed to be severable into an -- **#169** — move token infrastructure to global includes/ - > - Token overrides, REST API, and admin page are now global — moved from integrations/bricks/includes/ to includes/ and renamed from Slashed_Bricks_* t -- **#175** — move WP plugin into plugins/SLASHED-for-WP/ - > Separates the WordPress plugin from the SLASHED CSS framework at the repository level. The framework stays at root; all WordPress-specific code moves - -### v0.5.0 - -- **#179** — Identity Refresh and Documentation Overhaul for v0.5.0 - > This comprehensive update refreshes the SLASHED framework's identity and documentation for the v0.5.0 release. -- **#181** — don't abort commits staging gitignored dist bundles - > The .githooks/pre-commit hook rebuilds dist bundles and git adds every output. But dist/*.css is gitignored on main (built via npm run build, shipped -- **#188** — complete color system — shade scale, section theming, swatch coverage - > A comprehensive pass over the SLASHED color system touching the core framework CSS, the Bricks builder integration, and the documentation. All changes -- **#192** — refresh all docs, add WordPress plugin section, fix version sync - > - E: Edgeless → Explicit — describes @layer declaration order, BEM naming, and the token API contract more precisely than the opaque "Edgeless" -- **#194** — Rename --sf-color-base to --sf-color-surface - > This PR renames the --sf-color-base token family to --sf-color-surface throughout the codebase, along with renaming --sf-color-well to --sf-color-inse -- **#196** — Harden CSS value validation and fix color export regression - > This PR addresses critical security and correctness issues in the CSS generator and color handling: -- **#197** — move numeric scale ownership to tokens.palette.css - > Removes 121 numeric-scale lines (50–950) from core/tokens.css across -- **#198** — Redesign SF colors panel: Quick Use + Palette layout, two distinct modes - > Badge (bottom-right): reference-only. Click copies var() to clipboard. -- **#199** — Redesign SF Colors panel: Quick Use + Palette layout, two behaviour modes - > - Two distinct modes replace the old single-mode panel: -- **#200** — handle border/box-shadow colour inputs without explicit type attribute - > - SF Colors picker was throwing "Couldn't apply var… input not found" when used inside border and box-shadow controls, while working correctly for bac -- **#201** — SF Colors picker panel — Quick Use + Palette, active swatch, border support, base rename - > Full overhaul of the SF Colors panel and the --sf-color-base brand family rename. -- **#203** — Add contextual color cascade and fluid layout dimension controls - > This PR enhances the design system with two major features: a contextual color cascade for surfaces that automatically adapts semantic color tokens to -- **#209** — Replace modifier mode with multi-modifier support in all modes - > This PR removes the dedicated "modifier" mode and instead adds support for multiple modifiers across all non-migrate modes (add, rename, replace). Mod -- **#210** — Build reBEMer editor app (multi-block + multi-modifier) - > - Compiles the Svelte source changes from #209 into the deployed plugin assets -- **#211** — auto-rebuild all generated artifacts on commit + CI - > - Adds scripts/artifacts.json — a single manifest mapping source globs → build command → outputs for every generated/compiled file in the repo -- **#213** — escape Liquid delimiters in rebemer.md code block - > - Fixes the red cross on main — GitHub Pages build was failing with a Liquid syntax error -- **#224** — Add optional sizes-extended tokens and color/border shorthands - > Introduces a new optional token module (optional/tokens.sizes-extended.css) that extends the core spacing and typography scales with bridge variables -- **#226** — add All-in-one (mixed) mode with per-row op toggle and family picker - > New 'mixed' mode in the reBEMer panel lets users assign BEM classes to a -- **#228** — Document all framework tokens/classes in cheatsheet with coverage enforcement - > This PR significantly expands and reorganizes the Cheatsheet documentation to cover every token and class shipped in the framework, and adds automated -- **#229** — Sync viewport previews, revamp live preview, icon-trigger class hints - > - Live Scale Preview sliders in the Spacing and Typography tabs now scrub -- **#232** — Fix SF color button state sync and touch event handling - > This PR improves the reliability of the SLASHED color button in the Bricks editor by ensuring its visual state stays synchronized with the color input -- **#233** — restore -webkit-background-clip for .sf-text-gradient (Safari 17.5) - > A full audit pass over the CSS source (core/ + optional/, 22 files) found the framework in excellent shape — stylelint is clean, tradeoffs are documen -- **#234** — native validation, autofill, auto-grow textarea & numeric/overlay tokens - > Resolves the batch of well-scoped, low-risk open issues. Each change is additive, progressively enhanced, and built on existing tokens. -- **#235** — add .sf-content-auto and .sf-tabular-nums macros (#222, #214) - > Follow-up to #234. Resolves the two remaining issues that I'd previously mis-shelved as "blocked utilities" — they're actually macros (token-driven re -- **#236** — class-family picker for rename/replace + remove-all toggle - > In the reBEMer panel, Rename mode previously always renamed *the first* class on an element ("This element has 2 classes. Only the first will be renam -- **#237** — scrim, focus-shadow, divider & link recipes + auto-colour tests - > Implements the recipe-tier enhancements and tests recommended after the SLASHED recipe coverage audit. Everything here is a token-driven macro/rec -- **#239** — prepare for WordPress.org submission - > - Add readme.txt (required for wp.org review) -- **#240** — WordPress.org submission prep, docs cleanup, ESM scripts - > - WordPress.org submission prep — local-first CSS delivery (dist/ bundled in plugin), in-admin updater to download latest bundles from jsDelivr, optio -- **#241** — add feature-completeness & graceful-degradation issue backlog - > Adds docs/issue-backlog.md — a grouped backlog of suggested GitHub issues covering feature completeness on the modern CSS baseline and graceful degrad -- **#251** — add path to maximum engine-design score - > - Adds docs/path-to-max-score.md, a per-criterion roadmap for raising SLASHED toward the ceiling of the 14-category engine-design scoring model (max 1 -- **#252** — Add comprehensive index documentation for optimal bundle - > This PR adds a complete reference index document (docs/optimal-bundle-index.md) that exhaustively catalogs everything shipped in the SLASHED optimal b -- **#253** — add 100% framework coverage test pages - > Adds a six-page manual cross-browser test suite under docs/, designed to exercise 100% of the framework in action. Loads only the full variant via the -- **#254** — add Tier-1 sRGB color fallbacks for pre-Chrome-123 / pre-Safari-17.5 engines - > Implements the "gate at declaration site" pattern to fix IACVT failures on -- **#255** — add optimal bundle master index - > Adds docs/optimal-bundle-index.md — a complete master reference for the dist/slashed.optimal.css bundle variant, built directly from all 18 source fil -- **#256** — keep WordPress plugin's bundled CSS in sync with core builds - > The plugin ships local copies of the essential/optimal/full CSS bundles -- **#257** — version sync to 0.5.21 + pre-release audit fixes (0.6.0 prep) - > Pre-release audit and cleanup ahead of the 0.6.0 freeze. This does not release 0.6.0 — it restores the version invariant to the current released versi -- **#259** — Remove unused semantic color variant tokens - > Removed 45 unused semantic color variant tokens across success, warning, error, info, and danger color families. These tokens were defined but not uti -- **#260** — full token palette, gradients, font-size/spacing presets + in-editor token panel - > Brings the Gutenberg integration up to parity with the Bricks one. The block editor was shipping a stale, hand-maintained 20-entry color palette with -- **#261** — : wire scales, semantic z-index aliases, complete Tier-1 fallbacks - > Token-layer audit follow-ups: fixes dead/non-functional tokens, completes the Tier-1 sRGB fallback coverage, adds a semantic z-index layer, and makes -- **#262** — Split WordPress plugin into its own repo; decouple framework + docs cleanup - > Prepares the framework repo for the upcoming API freeze by splitting the bundled WordPress plugin out into its own repository (codeslash-dev/slashed-f -- **#263** — Make framework plugin-agnostic and fix release version drift - > Follow-up to the plugin split (#262). Removes leftover integration references from the framework and fixes the version pipeline that left bundle heade - -### v0.5.24 - -- **#264** — consolidate post-0.3.0 work under v0.5.24 - > Fixes the framework changelog version history. The changelog was stuck at 0.3.0 with everything piled under a perpetual [Unreleased] section, even tho - -### Unreleased - -- **#1** — scaffold CSS architecture - > - Replaces the two empty placeholder files (css/slashed-core.css, css/slashed-tokens.css) with a fully structured cascade-layer CSS scaffold -- **#2** — add layout primitives and token files from new-essential framework - > - core/layout.tokens.css — semantic tokens for layout primitives -- **#3** — Add uploaded files - > * Full accessibility layer with robust focus visibility, preference-aware motion/contrast/transparency handling, larger touch targets, hardened screen -- **#4** — Add CSS bundling system with file concatenation and watch mode - > This PR introduces a build system for concatenating CSS files into a single distributable bundle. It includes a Node.js-based bundler script with file -- **#5** — Add CSS bundler for slashed-essential.css - > - Dodaje scripts/bundle.js — bundler konkatenujący pliki z core/ w prawidłowej kolejności cascade layers do dist/slashed-essential.css -- **#6** — Add light theme support and theme application layer - > This PR adds comprehensive light theme support to the design system and introduces a new theme application layer that properly applies color-scheme an -- **#7** — light/dark mode with auto-derived color system - > Completely reworks the color system to be fully derived from 22 base colors (6+6 brand, 5+5 status). -- **#10** — CSS audit improvements — tokens, base, print, docs - > Comprehensive CSS audit fixes across core and optional files. Each change was validated with a plus/minus/devil's-advocate analysis. -- **#11** — implement states.css and move motion.css to core - > Two changes that promote essential bundle completeness: -- **#12** — restore --sf-shadow-color and --sf-prose-paragraph to tokens.css - > Token names in tokens.css are part of the public API — they must not be -- **#13** — correct raised surface level, on-inverse text, shadow glow, space-scale integration; clarify cq breakpoint tokens - > - --sf-color-raised: l+0.02 → l+0.04 so hierarchy well < surface < bg < raised is correct -- **#14** — design token bugs + demo nav UX - > - --sf-color-raised: poprawka formuły l + 0.02 → l + 0.04 — hierarchia powierzchni well < surface < bg < raised była zepsuta (bg i raised były identyc -- **#15** — Fix layout utilities and dark mode color tokens - > This PR fixes missing layout utility classes, improves dark mode color token definitions, and corrects animation implementation in the demo page. -- **#16** — dynamic brand/status color customizer + distinct token defaults - > - demo: add Theme Customizer section at top of main with 22 color pickers -- **#17** — demo: theme customizer + distinct defaults for primary/action and error/danger - > - core/tokens.css — fix overlapping defaults so role names actually correspond to distinct colors: -- **#18** — Theme-aware palette via light-dark() as single source of truth - > In dark mode, large parts of the demo were unreadable: white islands inside the dark page, near-white text on near-white surfaces. Root cause was in o -- **#19** — migrate dark mode to light-dark() hybrid architecture - > Eliminates the 80-line duplicate dark mode block in base.css by moving -- **#20** — Refactor design tokens and simplify color/spacing aliases - > This PR refactors the design token system to improve consistency, reduce complexity, and establish clearer semantic relationships between tokens. Chan -- **#21** — demo color pickers showing black for light mode - > Fixes the theme customizer color pickers in docs/demo.html that were incorrectly showing #000000 (black) for all light-mode tokens. -- **#22** — color palette aliases design decisions - > Adds a design decisions document for the upcoming semantic color alias layer in tokens.palette.css. -- **#23** — rename status color tokens to --sf-color-{status}-subtle/muted/strong - > Replaces --sf-status-{status}-{bg|border|text} with the new -- **#25** — color system DX - dark fallback + theme-aware palette - > Improves the color system developer experience and fixes issue #24. -- **#26** — improve color system DX with dark-mode fallback and theme-aware palette - > - Add dark-mode fallback to all 11 resolved color tokens so dark mode -- **#27** — add comprehensive quality audit (2024) - > Adds audits/quality-audit-2024-full.md -- a comprehensive quality audit of the entire SLASHED framework covering all core and optional files. -- **#28** — Add API coverage audit vs 5 reference frameworks - > Adds audits/api-coverage-vs-reference-frameworks.md - a comprehensive comparison of SLASHED's current API surface against Tailwind CSS v4, Open Props -- **#29** — fix token bugs, modernize tokens, expand palette, add regression suite - > Correctness (verified against audits/): - - ---- - -## Plugins - -### Bricks Builder Integration - -- **#60** — : add generic flat bundles, drop bricks-branded bundle - > Replaces the single bricks-branded flat bundle with a generic *.flat.css sibling for every tier, and produces them in dist/. -- **#61** — add generic flat bundles, replace bricks-branded bundle - > Adds generic *.flat.css bundles for every tier, replacing the single bricks-branded flat bundle. -- **#71** — add Bricks Builder integration plugin - > Adds a WordPress plugin at integrations/bricks/ that natively integrates SLASHED with Bricks Builder, providing the same type of in-builder experience -- **#74** — use jsDelivr CDN as default CSS source for Bricks - > Changes the default CSS source for the Bricks Builder integration plugin to load from jsDelivr CDN instead of requiring local files. -- **#81** — inject all framework classes and variables into Bricks UI - > The Bricks integration was supposed to populate the Bricks Builder UI with every SLASHED token and class so users get a complete picker / autocomplete -- **#83** — separate color palette + HEX picker + Contrast tab in admin - > Three GUI/integration improvements to the SLASHED ↔ Bricks integration, addressing user feedback (PL): -- **#84** — register variables/classes via canonical options and stop CSS bleed into builder UI - > Fixes two bugs in the Bricks integration that were surfacing together: -- **#92** — use official bricks/builder/color_palette filter for color injection - > The previous option_bricks_color_palette filter only fires when WordPress -- **#97** — resolve color swatches + add HTML font-size option - > Fixes two issues with the SLASHED for Bricks plugin: -- **#98** — expand admin panel to full API + add cheatsheet tab - > Expands the Svelte 5 admin SPA (integrations/bricks/admin-app/) to cover the entire SLASHED Bricks plugin public API and adds a comprehensive Cheatshe -- **#103** — sync Bricks color palette with admin-saved overrides - > Fixes the disconnect between admin-saved color customizations and the Bricks Builder color palette swatches. -- **#105** — port remaining 7 token tabs to Svelte admin SPA - > Bring the Svelte v2 admin SPA (SLASHED → Tokens (v2)) to functional parity with the legacy jQuery admin page (SLASHED → SLASHED), so the next PR can p -- **#106** — extract Token_Store / Token_Sanitizer / Tab_Registry helpers - > Extracts the data-layer pieces of class-admin-page.php into three small, stateless helper classes so the Svelte SPA, the REST controller, and the lega -- **#108** — promote Svelte SPA to the primary admin slug - > Promotes the Svelte SPA to the primary admin page (top-level "SLASHED" menu, slug slashed-bricks). Moves the legacy jQuery form behind an opt-in filte -- **#109** — remove the legacy jQuery admin page - > Final PR of the migration: deletes the legacy jQuery admin page, the transitional opt-in filter, and the Slashed_Bricks_Admin_Page class entirely. The -- **#114** — bridge data-brx-theme to SLASHED theme system - > Adds a CSS-only bridge in the Bricks integration plugin that maps Bricks' data-brx-theme attribute to SLASHED's theme system. -- **#116** — resolve REST 404 and add dark mode colors - > Fixes three issues in the Svelte admin app: -- **#119** — add Export CSS button to admin panel - > Adds a client-side CSS export feature to the Bricks admin panel so users can download a slashed-custom.css file containing only their non-default toke -- **#120** — remove dead constructor hook + document sanitizer contract - > Follow-up to #116 (merged). Addresses two non-blocking review findings: -- **#122** — add CSS export functionality (rebased) - > Rebased PR #119 (feat/export-css) onto current main (which now includes PRs #116, #117, #120). All merge conflicts resolved. -- **#124** — add reBEMer — subtree BEM class manager for the Bricks structure panel - > - Five operation modes: Add, Rename, Replace, Add Modifier, Migrate ID styles. -- **#125** — reBEMer MVP — subtree BEM class manager - > Stripped-down MVP of reBEMer: add/rename/replace BEM classes for an element and its children via the Bricks Builder structure panel. -- **#129** — natural-sort palette so -50 lands before -500 + reBEMer design refinements - > Two related changes from this design-review pass: -- **#132** — hover-only badge that matches Bricks action-icon size - > Three small fixes to the reBEMer badge in the Bricks structure panel: -- **#134** — CSS bundle selector in admin panel, remove legacy admin page - > - Add css_bundle plugin setting (essential / optimal / full) so admins -- **#142** — Add token export/import and Bricks template workflow - > - REST: GET /tokens/export returns all token overrides + plugin settings -- **#157** — REST validation, stale detection, and class hints - > - REST validation endpoint — POST /slashed-bricks/v1/tokens/validate runs Token_Sanitizer on submitted values without saving; returns { section, sanit -- **#163** — include Google Fonts from Bricks font manager in Bricks tab - > - The bricks-fonts REST endpoint was only probing bricks_custom_fonts (uploaded fonts) and bricks_adobe_fonts. Fonts added via Bricks > Settings > Goo -- **#164** — use title as family name fallback for Bricks custom fonts - > Fonts added via Bricks > Settings > Custom Fonts (including Google Fonts downloaded for local serving) store the CSS family name only in title — no se -- **#170** — builder-agnostic CSS delivery and de-Bricks admin UI - > SLASHED is a CSS framework, not a Bricks tool. This PR makes the core CSS delivery work on any WordPress site — custom theme, classic theme, or no pag -- **#171** — builder-agnostic architecture, global token infrastructure, Bricks CPT font fix - > - Move token infrastructure to global includes/ — Slashed_Token_Store, Slashed_CSS_Generator, Slashed_CSS_Loader, Slashed_Token_Page, and REST control -- **#172** — builder-aware admin UI and fix Bricks Font Manager fonts in dropdown - > - Fix Bricks Font Manager fonts missing in dropdown — fonts created via the new Font Manager start as post_status = 'draft' and were excluded by the p -- **#173** — Fix Bricks font tab always visible + WCAG oklch color resolution - > - Bricks font tab always shows when the Bricks integration is enabled — the tab is no longer hidden if no fonts are registered yet; instead it shows a -- **#174** — Fix fatal error when opening Bricks editor (Slashed_Token_Page not found) - > - Slashed_Token_Page::get_class_hints() is called from Slashed_Bricks_ReBEMer_Enqueue::enqueue() on the wp_enqueue_scripts hook — a frontend hook that -- **#176** — Gutenberg CSS bleed into Bricks editor + dark mode toggle + misc - > - Bricks editor CSS bleed: Slashed_Gutenberg_Enqueue::enqueue_frontend_styles() lacked a bricks_is_builder_main() guard. In the unified plugin both in -- **#177** — Show class hints in Bricks editor - > This PR implements "Show class hints" in the Bricks editor. When enabled in the SLASHED plugin settings, hovering over a SLASHED class (sf-* or is-*) -- **#178** — restore sf-container max-width overridden by Bricks generic selector - > Bricks emits [class*=brxe-] { max-width: 100% } as unlayered author CSS. SLASHED's container classes live inside @layer slashed.layout, and unlayered -- **#180** — class documentation tooltips in builder - > Completes the class documentation tooltips feature for the Bricks integration. All the data/admin/PHP plumbing already existed on main (generator → da -- **#182** — skip color-palette injection on Bricks 2.2+ Color Manager - > Dark/light mode silently breaks for SLASHED colors in Bricks 2.2+. Bricks 2.2's new Color Manager materializes every color-palette entry into :root as -- **#184** — add color swatches to variable-picker dropdown - > Restores colour swatches in the Bricks builder without re-introducing the dark-mode bug that #182 fixed. Closes the follow-up tracked in #183. -- **#189** — add missing *-strong status swatches to variable-picker hex map - > The five status *-strong tokens appeared as plain text in the Bricks variable-picker dropdown while every other variant for the same family (-subtle, -- **#190** — complete color swatch coverage in variable picker - > - Add hex entries for all 11 --sf-color-{family}-light source tokens (previously the resolver read them as inputs but never wrote them to the hex map, -- **#191** — Bricks swatch coverage + lightweight CSS normalize - > - Add hex entries for all 11 --sf-color-{family}-light source tokens — the resolver read them as inputs but never wrote them to the hex map, leaving c -- **#193** — add in-builder Color System panel with light/dark preview - > A floating Color System panel for the Bricks builder, launched from a -- **#195** — Add SF Colors button to Bricks colour fields for quick variable access - > This PR adds a contextual "SF Colors" button to Bricks colour input fields, allowing users to quickly insert SLASHED color variables directly into any -- **#202** — SF Colors panel — pick flow, icon, and remove Color Manager palette injection - > - Remove class-colors.php — the class injected SLASHED tokens into Bricks' Color Manager as static hex values, overriding the framework's adaptive lig -- **#206** — prevent focus-steal that closed border/box-shadow colour picker - > For border and box-shadow controls, Bricks renders the colour input inside -- **#208** — SF colour panel broken for border/box-shadow + missing admin inputs - > - SF colour panel — border/box-shadow fix: clicking a swatch closed the Bricks settings panel and showed "input not found" for border and box-shadow c -- **#212** — remove SF colour border/box-shadow fixes - > - Reverts the three SF colour border/box-shadow fix commits (93da924, cafa170, 18303c0) that were introduced to handle event-ordering issues with Bric -- **#227** — lock framework classes by default in Class Manager - > Adds a lock_framework_classes plugin setting (default: true) so all -- **#230** — emit brand `base` token in CSS export + color overrides; de-dupe font collector - > Focused re-audit of plugins/SLASHED-for-WP. Most prior High/Medium audit items were already resolved (CSS-generator allowlist validation, slashed.php -- **#231** — Refresh Bricks fonts dropdown on mount via REST endpoint - > Previously bricksFonts was a const read once from the PHP bootstrap -- **#238** — translate Bricks workflow to English, fix stale facts, trim redundancy - > A documentation/comment cleanup pass across the repo: ensure everything is in English, fix factual claims that had drifted from the source, and trim g -- **#258** — Refactor bundle settings and improve Bricks font CPT handling - > This PR refactors the CSS bundle selection UI, improves Bricks Font Manager CPT compatibility, and adds support for legacy color fallback tokens. The - - ---- - -## Development Summary - -- **Framework**: 168 PRs -- **Plugins**: 54 PRs -- **Total**: 222 PRs -- **Versions**: 6 releases - -**Version History**: v0.1.0 → v0.2.0 → v0.3.0 → v0.5.0 → v0.5.24 - ---- - -*Generated from 222 merged PRs* -*Last Updated: 2026-06-08* diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b7b268cb5..7c7b18665 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -45,7 +45,7 @@ and `dist/` must be rebuilt and committed. ## Tests & demo coverage -- Any new `.sf-*` or `.is-*` class in `core/*.css` must appear in `docs/demo.html` +- Any new `.sf-*` or `.is-*` class in `core/*.css` must appear in `demo/index.html` (`tests/coverage.test.js`). - Any new token must resolve in both themes (`tests/tokens.spec.js`); tokens whose value is `inherit` go in that file's `EXPECTED_EMPTY` allowlist. diff --git a/_config.yml b/_config.yml index 0fc307630..8e56b52b3 100644 --- a/_config.yml +++ b/_config.yml @@ -14,10 +14,6 @@ exclude: - scripts - tests - dist - - analysis - - demos/generate.mjs - - demos/validate.mjs - - demos/.validate - bundle.config.json - commitlint.config.js - playwright.config.js diff --git a/_layouts/default.html b/_layouts/default.html index 11729cb89..b62ab0f4e 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -28,7 +28,7 @@ SLASHED Docs Tokens - Coverage + Demo GitHub Configurator → diff --git a/analysis/gap-analysis.md b/analysis/gap-analysis.md deleted file mode 100644 index 5e18c5da2..000000000 --- a/analysis/gap-analysis.md +++ /dev/null @@ -1,235 +0,0 @@ - - -# SLASHED — Competitive Gap Analysis (v0.5.28) - -> **Question:** what is still missing from SLASHED that holds it back versus -> its closest competitor — a leading variable-first CSS framework? -> -> **Scope guard (per request):** pre-built components, plain utility classes, -> and ecosystem/community factors are **excluded** on both sides. We compare -> *engines*: the token/variable API, the generative colour/type/space machinery, -> theming, contexts, and architecture. -> -> **Lens:** every gap is judged against SLASHED's stated philosophy — -> **no build, no Node, no JS, pure CSS, BEM-first, token-first, modern-only.** -> A "gap" only counts if closing it is *consistent with that philosophy*. Where a -> difference is a deliberate philosophical choice, it is flagged as **Not a gap**. -> -> This supersedes the earlier revision of this document, which audited a -> pre-generative-engine build. Two of its Tier-1 gaps have since been closed in -> source; the verdicts below reflect **v0.5.28** as shipped. -> -> The competitor is referred to generically throughout ("the reference -> framework"); findings were verified against its public documentation. - ---- - -## Headline - -The reference framework has repositioned to **"variable-first, BEM-first"** -with cascade layers, OKLCH, `light-dark()`/`color-scheme`, and a -breakpoint-free stance — the exact category SLASHED occupies. The two are now -directly comparable engines, and the feature-for-feature distance has -**narrowed dramatically since the previous audit**: - -- **The generative fluid engine has landed.** Type, display, and space scales - are now computed at runtime from 12 override-able inputs - (`--sf-fluid-{min,max}-vw`, `--sf-{text,space}-ratio-{min,max}`, - `--sf-{text,space}-base-{min,max}`, `--sf-text-display-base-{min,max}`, - `core/tokens.css`). This was the previous audit's #1 gap. SLASHED now matches - the "few inputs regenerate the system" value proposition **without a - dashboard or build step** — and exceeds it in one respect: the **dual-ratio** - design (a different modular ratio at the min and max viewport) has no - equivalent in the reference framework. -- **The contextual colour cascade has landed.** `.sf-surface--*` (11 variants, - `core/macros.css`) now re-declares ~11 semantic tokens (`--sf-color-text`, - `--sf-color-heading`, `--sf-color-link`+states, secondary/placeholder/disabled - text, three border weights, shadow colour) so descendants adapt with no extra - classes. This is functional parity with the reference framework's contextual - backgrounds. -- The 72 `-to-` bridge tokens are now **generated from the same engine** - (`optional/tokens.sizes-extended.css`) and recalibrate with it, and have been - re-tiered PUBLIC-ADVANCED — the "hand-computed matrix" critique no longer - applies. - -What remains is a shorter list: one genuine platform-bound limitation -(an ad-hoc fluid primitive), one coverage gap (contexts beyond the 11 -surfaces), and a cluster of **documentation/packaging gaps** — the new engine -is barely surfaced in the human-readable docs. - ---- - -## Closed since the previous audit (verified in source) - -| Former gap | Status in v0.5.28 | -|---|---| -| #1 Fluid scales pre-computed, not generative | **Closed.** Runtime `pow()`/`calc()` engine over 12 `@property`-typed inputs; every `clamp()` recalibrates from `:root` overrides. | -| #4 Colour contexts class-gated, shallow | **Largely closed.** `.sf-surface--*` rebinds the full semantic token set for descendants (text, heading, links, borders, shadow colour). | -| Bridge matrix as "brute-force stand-in" | **Reframed.** Bridges are now engine-derived outputs, consistent by construction. | - ---- - -## Tier 1 — Remaining real gaps - -### 1. No ad-hoc `fluid(min, max)` primitive ⭐ (the one competitor feature with no SLASHED answer) - -The reference framework ships a `fluid()` helper so *any* property value can -interpolate between two endpoints. SLASHED offers the fixed scale steps plus -the bridge matrix; an arbitrary "go from 0.875rem to 1.375rem here" still needs -a hand-written `clamp()`, and nothing guarantees the author reuses the engine's -viewport range. - -CSS has no cross-browser user-defined functions, so a literal `fluid()` remains -**a platform limitation, not an oversight**. But it can be closed in stages, -all philosophy-safe: - -1. **Now — documented recipe.** One canonical `clamp()` pattern driven by the - existing engine tokens, published in `docs/theming.md`/`docs/macros.md`: - - ```css - /* fluid from MIN rem to MAX rem across the engine's viewport range */ - --my-value: clamp( - MINrem, - calc((MAX - MIN) / (var(--sf-fluid-max-vw) - var(--sf-fluid-min-vw)) - * (100vw - var(--sf-fluid-min-vw) * 1rem) + MINrem), - MAXrem - ); - ``` - - Because it reads `--sf-fluid-*`, ad-hoc values stay in sync when the engine - is recalibrated — the property `fluid()` users actually rely on. -2. **Now — open slots.** A few pre-wired tokens - (`--sf-fluid-custom-{1..3}` with `--sf-fluid-custom-N-{min,max}` endpoint - inputs) so common cases need only two numbers, no formula. -3. **Later — native `@function`.** CSS custom functions (`@function --fluid(...)`) - shipped in Chromium in 2025 and are progressing elsewhere. An optional - `optional/functions.css` module can deliver a true `--fluid()` as progressive - enhancement once a second engine ships, without violating no-build. Track it - in the roadmap now. - -### 2. The generative engine is invisible in the docs and the theming story - -This is the inverse of the old gap: the engine exists, but a consumer reading -`README.md`, `docs/theming.md`, or `optional/theme-example.css` will not learn -it exists. Verified: `docs/theming.md` and `docs/architecture.md` contain **no -mention** of `--sf-text-ratio-*` / `--sf-fluid-*-vw`; `theme-example.css` -demonstrates every *colour* mechanism but none of the 12 scale dials. The -reference framework's adoption advantage is precisely that its inputs are -impossible to miss (dashboard); SLASHED's equivalent must be impossible to miss -*in the docs*. - -**Fix (docs/packaging, no engine work):** -- a "Fluid engine" section in `docs/theming.md` (what each of the 12 inputs - does, worked examples: change ratio, widen viewport range, scale base); -- extend `optional/theme-example.css` (or add `optional/config-example.css`) - into the **single annotated control panel** the previous audit asked for: - 6 brand colours + 12 engine inputs + 5 scale multipliers + font families + - radius in one copy-paste block; -- a README paragraph: "change one ratio, the whole system regenerates — no - build" is now true and is the headline parity claim. Say it. - -### 3. Colour contexts stop at the 11 surface classes - -In the reference framework, contexts apply to any palette background, including -tints/shades. SLASHED's contextual cascade fires only on -`.sf-surface--{brand|status|inverse}`. Set -`background: var(--sf-color-primary-100)` (or any arbitrary background) and -nothing re-derives; there is also no documented way to *author your own* surface -that participates in the contract. - -**Fix, in order of leverage:** -1. **Document the surface contract as a recipe** — the 11-token rebinding block - is a copy-paste pattern; publishing it lets any BEM component become a - conforming surface today. -2. **Ship a generic surface primitive**: a `.sf-surface` (or `[data-surface]`) - that reads one input — `--sf-surface-color: ` — and derives - background, auto-contrast foreground (the `oklch(from …)` lightness-flip - technique already used for `--sf-color-text--on-*`), and the contextual - token set from it. This generalises contexts to *every* colour, including - palette shades, with one class + one custom property — arguably beyond what - the reference framework offers. -3. Optional sugar: tint variants (`.sf-surface--primary-subtle` etc.) mapping to - the existing `-100`/`-900` ramp with dark-mode-aware flips. - ---- - -## Tier 2 — Smaller gaps / polish - -### 4. Smart, metric-aware line-height -The reference framework computes line-height from a leading value relative to -font size. SLASHED has static `--sf-leading-*` plus per-size overrides in -`sizes-extended` whose *defaults* encode the convention (big = tight) — close -in outcome, manual in mechanism. **Closeable** with a `calc()` leading formula -keyed to the size step (the engine exposes everything needed); low priority. - -### 5. Section rhythm: indirect dial only -`--sf-section-pad--*` now derives from the generative space scale, so -recalibrating the engine or `--sf-space-scale` *does* re-rhythm sections — but -there is no **independent** section multiplier (competitor: one section-space -input × fluid multiplier). **Fix:** multiply the six `--sf-section-pad--*` -definitions by a new `--sf-section-scale` (default `1`). One token, ~6 lines. -*(Addressed in v0.5.30 / PR #299 — `--sf-section-scale` now multiplies all -`--sf-section-pad--*` definitions.)* - -### 6. Root font-size / zoom accessibility story -The reference framework documents root-size and rem strategy explicitly. -SLASHED is rem-based and zoom-safe in practice but says nothing about it. -**Docs-only gap:** a short "root size, rem and user zoom" section in -`docs/theming.md` (don't set a px root size; how `--sf-*-base-*` interacts -with user font-size preferences). - ---- - -## Not a gap — deliberate philosophical choices (do NOT "fix") - -| Competitor feature | Why SLASHED should not copy it | -|---|---| -| **Dashboard / live preview / selective CSS output** | Requires a host-platform plugin runtime. SLASHED's equivalent is the engine tokens + (gap #2) a config partial. | -| **Build-time expandable utility "recipes"** | Expansion happens inside a page-builder runtime; needs tooling. SLASHED's macros (`.sf-prose`, `.sf-flow`, …) are runtime recipes — different, philosophy-consistent answer. | -| **Breakpoint configuration** | Both frameworks are now breakpoint-free; SLASHED is container-query-first on top. Parity-or-better, nothing to add. | -| **Utility classes** | Excluded from scope; BEM-first stance through v1.0. | -| **Page-builder integrations** | Ecosystem — out of scope per request; handled by the separate `slashed-for-wp` repo anyway. | - ---- - -## Where SLASHED already leads (context for balance) - -- **Dual-ratio fluid engine** — different modular ratio at min vs max viewport; - the reference framework exposes single ratios. -- **Typed tokens** — `@property` registration (animatable colours, typed engine - scalars, sane `initial` behaviour). The competitor's variables are untyped. -- **Fully ordered explicit layer stack** (`tokens → … → overrides`) with an - always-last consumer layer; the competitor adopted layers recently but with a - coarser contract. -- **Container-query-native layout primitives**, a real **print layer**, the - **motion token system**, the 40-strong **`.is-*` ARIA-mapped state - vocabulary**, and **LumLocker** — no competitor equivalents. -- **Zero-dependency portability** — one ``, any stack; the competitor - requires a CMS plugin (noting ecosystem is out of scope, the *architectural* - consequence — no runtime requirement — is in scope and favours SLASHED). -- **One-token→full-ramp palette** (22 steps/family in `tokens.palette.css`) - derived in pure CSS — the competitor needs its dashboard to do the same job. - ---- - -## Recommended priority order - -1. **Surface the engine** — docs section + single config-example "control - panel" partial + README claim. Highest value-per-effort; pure docs. *(Gap #2)* -2. **Ship the fluid recipe + open slots**, and put native `@function --fluid()` - on the roadmap. *(Gap #1)* -3. **Generalise the surface contract** — document the rebinding recipe, then a - `--sf-surface-color`-driven generic surface. *(Gap #3)* -4. Polish: `--sf-section-scale`, calc-based smart leading, root-size/zoom docs. - *(Gaps #4–6)* - -> Net verdict: with the generative engine and contextual cascade shipped, -> SLASHED has reached **engine parity with its closest competitor and leads it -> on modern-CSS depth** (typed tokens, dual ratios, container queries, layer -> rigour). The remaining deficit is one platform-bound primitive (an ad-hoc -> fluid helper, mitigable today, solvable natively soon) and -> **discoverability**: the engine's configurability currently lives only in -> source comments and generated references. diff --git a/demo-audit.html b/demo-audit.html deleted file mode 100644 index 48e9d5bdc..000000000 --- a/demo-audit.html +++ /dev/null @@ -1,816 +0,0 @@ - - - - - -SLASHED .sf-* Class Coverage Audit - - - - - -
-
-

This page is a hand-authored coverage audit for the SLASHED framework. Every - .sf-* class documented in docs/classes.md is applied to - real, visible markup below, organised by source file. It loads only - dist/slashed.full.css — no custom CSS, no scripts, no third-party - resources. .sf-box's border is opt-in via its - --sf-box-border-width custom property (0 by default); it's set to - 1px once here on <body> — a documented public token, - inherited like any CSS custom property — purely so every box demo below is - visible at a glance.

-
-
- - -
-
-

Layout primitives (core/layout.css)

-

Breakpoint-free, container-query-driven layout building blocks. Each demo below -exercises one primitive (and its size/variant modifiers) with realistic children.

- -

Section rhythm & section-group

-
-
section--xs
-
section--s
-
section--m (default)
-
section--l
-
section--xl
-
section--2xl + section--collapse (shares padding with neighbour)
-
-
-

section--guttered adds inline gutters without a container

-
- -

Header padding rhythm

-
header--xs
-
header--s
-
header--m
-
header--l
-
header--xl
- -

Containers & container-query scopes

-

default .sf-container

-

container--narrow

-

container--prose

-

container--wide

-

container--full

-
sf-cq scope, col 1
col 2 — resizes by container width, not viewport
-

sf-fluid-cq — children interpolate type/space against this box's own inline size rather than the viewport.

- -

Box & centering

-
sf-box — isolated padded unit with an outline
-
sf-center — intrinsic centering with gutters
-
sf-center--intrinsic
- -

Stack — vertical flow

-
-

xs

gap

-

s

gap

-

m

gap (default)

-

l

gap

-

xl

gap

-

2xl

gap

-
-
-
-
-
-
- -

Cluster — wrapping inline group

-
-
xsgap
-
sgap
-
mgap (default)
-
lgap
-
xlgap
-
2xlgap
-
no-wrapstayson one line
-
cluster--between: leftright
-
cluster--center
-
cluster--end
-
- -

Gap — inject gap into an existing container

-
gap xs
a
b
-
gap s
a
b
-
gap m
a
b
-
gap l
a
b
-
gap xl
a
b
-
gap 2xl
a
b
- -

Sidebar

-
Main content wraps below when narrow
-
Main
-
sidebar--right panel
-
Main
- -

Switcher

-
A
B
C
-
A
B
C
-
A
B
C
- -

Grid — auto-fill responsive

-
xs
min col
width
-
s
min col
width
-
m
min col
width
-
l
min col
width
-
xl
min col
width
-
2xl
min col
width
-
fit
stretches to fill row
-
dense
packing
fills gaps
- -

Grid — fixed columns & ratios

-
grid-cols-1
-
grid-cols-2 a
b
-
grid-cols-3 a
b
c
-
1
2
3
4
-
1
2
3
4
5
6
-
1fr
2fr
-
2fr
1fr
-
1fr
3fr
-
3fr
1fr
- -

Grid-flex

-
xs
item
item
-
s
item
item
-
m
item
item
-
l
item
item
-
xl
item
item
-
2xl
item
item
-
center
last row
stays fixed
- -

Bento — dense free-form grid

-
- -
bento-wide (span 2)
-
bento-tall (row span 2)
-
normal cell
-
bento-full (full width)
-
-
bento--2
bento--row-compact rows
-
bento--6
bento--row-tall rows
c
d
e
f
- -

Alternate — zigzag two-column

-
-
-

Feature one

Text column reverses order on alternate rows.

-
placeholder
-
-
-

Feature two

Second row — image/text order swaps automatically.

-
placeholder
-
-
- -

Pancake — sticky-footer grid

-
-
-
-
Pancake header
-
Pancake main (1fr)
-
Pancake footer
-
-
- -

Content-grid — breakout & full-bleed

-
-

Regular content-width paragraph inside .sf-content-grid.

-
sf-breakout — wider than content, narrower than viewport
-
sf-full-bleed — spans the whole viewport width
-
- -

Cover — full-height centered region

-

cover--min + cover__center

-

cover--max + cover--padding-s

-

cover--padding-l

- -

Frame — aspect-ratio media box

-
-
default 16:9
-
square
-
video
-
cinema
-
portrait
-
4:3
-
3:2
-
golden
-
- -

Background layer

-
- -

sf-bg-layer fills behind this text; the parent auto-positions itself.

-
- -

Reel — horizontal scroll strip

-
-
1
2
3
-
4
5
6
-
- -

Imposter — absolutely-centered overlay

-
-

Host box (positioning context)

- imposter (centered) -
-
-

Host box (transform creates a containing block so the fixed-positioned imposter stays inside it)

- imposter--fixed -
-
-
imposter--contain: constrained + scrollable long content that overflows the imposter box on purpose to show the scrollbar in action.
-
- -

Overlay helper

-
-

Base content

-
-
- -

Subgrid

-
-
-
subgrid a
subgrid b
subgrid c
-
-
-
-
-
subgrid-rows row 1
subgrid-rows row 2
-
-
- -

Divider & divide

-
-
-
-
-
-
-
Left
Right
-

One

Two (divide adds a border between siblings)

Three

-
XYZ
- -

Equal — CSS multi-column flow

-

Newspaper-style flowing columns, 2 target columns. Text flows down one column, then continues at the top of the next, unlike grid cells.

-

Three target columns of flowing text content for a denser magazine layout.

-

Four target columns for a very dense flowing layout of short list items.

-

Six target columns, useful for long tag/keyword lists that should flow.

- -

Icon sizing

-
- - - - - - - -
- -
-
- - -
-
-

Macro classes (core/macros.css)

-

Recipes that answer "what does this element do/look like?" — composable on top of layout primitives.

- -

Prose & not-prose

-
-

Article heading

-

Paragraph one of long-form text with automatic vertical rhythm between children.

-

Paragraph two — automatically spaced from the previous one.

-
  • Bullet one
  • Bullet two
-
This region opts out of prose spacing/list rules (sf-not-prose).
-

More article body after the opted-out region.

-
- -

Flow

-
-

One

-

Two — gets margin-block-start from the flow rhythm.

-

Three — same.

-
- -

Truncate & line-clamp

-

This very long sentence about the SLASHED framework will be cut off with an ellipsis after exactly one line because the box has a finite inline size.

-

Two-line clamp: SLASHED ships breakpoint-free, container-query-driven layout primitives that respond to their own container's width instead of the viewport, which keeps components portable across sidebars, cards, and full-width sections alike.

-

Three-line clamp: token-driven design system with a fluid type and space engine computed at runtime from a handful of input scalars, so retuning one number recalibrates the whole scale without a rebuild step or any SCSS preprocessing.

-

Five-line clamp via the N variant and the --sf-line-clamp custom property: this paragraph is intentionally long so the clamp is visible — it keeps going and going, describing layout primitives, macros, state classes, motion utilities and components until it is cut off after five lines with an ellipsis, no matter how much more text follows this point in the source.

- -

Equal-height flex children

-
-
Short
-
Two
lines
-
Three
lines
here
-
- -

Aspect ratio

-
sf-aspect at 4/3 via the --sf-aspect custom property
- -

Scroll shadow & scroll snap

-
-

Long scrolling content fades near the top/bottom edges of this box.

-

Line two.

Line three.

Line four.

Line five.

Line six.

-
-
-
Snap A
-
Snap B
-
Snap C
-
- -

Overflow fade

-
- tagtagtagtag -
-
- rightfadedemotags -
-
- leftfadedemotags -
-

Top-fade content. Line 2.

Line 3.

Line 4.

-

Bottom-fade content. Line 2.

Line 3.

Line 4.

-

Both block edges fade. Line 2.

Line 3.

Line 4.

-
- inlinefadebothedges -
- -

No tap highlight

-Link with suppressed mobile tap-highlight overlay - -

Content-visibility auto

-
Offscreen rendering is skipped until this section nears the viewport (content-visibility: auto).
- -

Tabular numbers

- - - -
Invoice #1024$1,204.50
Invoice #999$88.00
- -

Drop shadows

-
- xs shadow - s shadow - m shadow - l shadow - xl shadow -
- -

Surfaces

-
-
sf-surface (generic, tinted)
-
surface--primary
-
surface--secondary
-
surface--tertiary
-
surface--action
-
surface--neutral
-
surface--inverse
-
surface--success
-
surface--warning
-
surface--info
-
surface--danger
-
-
sf-surface-bg — named background preset (colour fallback layer shown here)
- -

Text gradient & text protect

-

Gradient headline

-
- -

Legible text over a busy photo

-
- -

Link helpers

-

- External link · - Subtle link (underline on hover) · - Reverse link (underline at rest) -

- -

Scrim over media

-
- -
-

scrim--bottom + scrim__content

-
-
-
- -
-

scrim--top

-
-
-
- -
-

scrim--full

-
-
- -

Entrance & exit scroll animations

-
-
entrance--fade
-
entrance--fade-up
-
entrance--fade-down
-
entrance--fade-left
-
entrance--fade-right
-
entrance--scale-up
-
exit--fade
-
exit--fade-up
-
exit--fade-down
-
exit--fade-left
-
exit--fade-right
-
exit--scale-down
-
- -

Stagger

-
    -
  • First
  • -
  • Second
  • -
  • Third
  • -
- -

Overlap & overlap-host

-
-
- badge -
overlap (pulls up) + overlap-host reserves space
-
-
-
Host for overlap--down
- badge -
-
-
Host
- badge -
-
- badge -
Host
-
-
- -
-
- - -
-
-

State classes (core/states.css)

-

Runtime-condition classes, applied statically here on realistic hosts so each visual treatment is visible.

- -
-
is-hidden (removed from layout — you should not see this box)
-
is-invisible (keeps its box, invisible)
-
is-visible
- -
-
is-loading (spinner replaces content)
-
is-pending (content stays usable)
- -
- -
  • is-selected list item
- is-current nav item - -
is-highlighted
-
is-open panel
-
is-collapsed panel
- -
- -

Form validation states

-
-
-
Please enter a valid email
-
- -

Feedback states

-
-

is-success: saved successfully

- -

is-warning: quota nearly reached

-

is-info: new version available

- -
- -

Drag & drop

-
-
is-draggable item
-
is-dragging item
-
is-drop-target zone
-
- -

Empty state

-
    - -
    -
    - - -
    -
    -

    Accessibility (core/accessibility.css)

    -

    Focus and clickable-area helpers.

    - -
    -

    sf-focus-parent — this whole box rings when a descendant has keyboard focus.

    - -
    - -
    - -
    -
    -

    sf-clickable-parent

    -

    The whole card is a single click target via the overlay link below.

    - Read more -
    -
    - -
    -
    - - -
    -
    -

    Motion / entrances (core/motion.css)

    -

    Looping and one-shot animation classes applied to visible elements (final/initial state may render statically depending on browser support).

    - -
    -
    fade-in
    -
    fade-out
    -
    scale-up
    -
    scale-down
    -
    slide-in-up
    -
    slide-in-down
    -
    slide-in-left
    -
    slide-in-right
    -
    - -

    Colour pulse

    -
    sf-color-pulse — animates the primary hue lightness
    - -
    -
    - - -
    -
    -

    Print utilities (core/print.css)

    -

    Print rules key off classes already used elsewhere on the page for other purposes — .sf-link-external also -gains print-specific treatment (its href is expanded next to the link text when the page is printed).

    -

    This external link also exercises the print stylesheet — see the "Link helpers" demo above for the on-screen version of the same class.

    -
    -
    - - -
    -
    -

    Theme utilities (core/themes.css)

    -

    Forcing light/dark on a region, plus the smooth-transition helper.

    - -
    -
    sf-theme-dark — forces dark palette on this region
    -
    sf-theme-light — forces light palette on this region
    -
    -
    sf-theme-transition — cross-fades registered colour tokens when a theme toggle script flips data-theme on this element (normally applied to <html>; shown here on a scoped region since this page has no toggle script).
    -
    -
    - - -
    -
    -

    Forms (optional/forms.css)

    -

    Classless form controls, styled without any .sf-* class needed on the inputs themselves — the one opt-in -utility here is .sf-live-validate, which enables native :user-invalid/:user-valid border feedback -after a submit attempt.

    - -
    -
    - Contact details - - - - - - - -
    - -
    - -
    -
    - - -
    -
    -

    Components — Buttons (optional/components.css)

    -

    All colour families, style treatments, gradient axis, sizes, width, and state modifiers for .sf-btn.

    - -

    Colour families

    -
    - - - - - - - - - - - -
    - -

    Style treatments

    -
    - - - - -
    - -

    Gradient axis

    -
    - - - -
    - -

    Sizes

    -
    - - - - - -
    - -

    Width

    - -
    - -
    - -

    States

    -
    - - -
    - -
    -
    - - -
    -
    -

    Components — Cards (optional/components.css)

    - -
    -
    - -
    - -

    Default card

    -
    -
    -

    Body content with header, media, avatar and title slots.

    -
    -
    - -
    -
    - -
    -

    card--bordered: flat, outlined, no shadow.

    -
    - -
    -

    card--elevated: floating shadow, no border.

    -
    - - -

    card--interactive: lifts on hover/focus.

    -
    - -
    -

    Card in an is-loading state.

    -
    - -
    -

    Card in an is-disabled state.

    -
    - -
    -

    Standalone card__body composed with sf-flow for spacing.

    -

    Second paragraph.

    -
    - -
    - New - Popular -
    -
    - -
    -
    - - -
    -
    -

    Utilities (optional/utilities.css)

    - -

    Heading helper classes

    -
    -
    Visually H1 (div)
    -
    Visually H2 (div)
    -
    Visually H3 (div)
    -
    Visually H4 (div)
    -
    Visually H5 (div)
    -
    Visually H6 (div)
    -
    - -

    Text-size utilities

    -
    -

    2xs — legal / metadata copy

    -

    xs — fine print

    -

    s — secondary copy

    -

    m — body copy

    -

    l — larger body copy

    -

    xl — lede paragraph

    -

    2xl — subheading

    -

    3xl — heading

    -

    4xl — display heading

    -
    - -

    Hover transforms

    -
    -
    hover-grow
    -
    hover-shrink
    - hover-float - hover-sink -
    hover-slide-start
    -
    hover-slide-end
    -
    - -

    List reset & marker colours

    -
      -
    • sf-list-none: no bullets, no inline-start padding
    • -
    -
      -
    • marker--primary bullet
    • -
    -
      -
    • marker--secondary bullet
    • -
    -
      -
    • marker--tertiary bullet
    • -
    -
      -
    • marker--action bullet
    • -
    - -

    Selection colour

    -

    Select this text — sf-selection--alt swaps the ::selection colours for a surface with poor default contrast.

    - -

    Sticky positioning

    -

    --sf-sticky-offset normally reads the page's fixed header height (0 here, -since this page has none) — set to 0 per demo box below so the base case -sticks flush to each isolated scroll container's own top edge; scroll each box to see -it hold in place.

    -
    -
    sf-sticky (base offset)
    -

    Scroll content…

    More…

    More…

    More…

    More…

    -
    -
    -
    sf-sticky--s (extra gap)
    -

    Scroll content…

    More…

    More…

    More…

    More…

    -
    -
    -
    sf-sticky--m
    -

    Scroll content…

    More…

    More…

    More…

    More…

    -
    -
    -
    sf-sticky--l
    -

    Scroll content…

    More…

    More…

    More…

    More…

    -
    - -
    -
    - - - diff --git a/demo/index.html b/demo/index.html new file mode 100644 index 000000000..f82a828ab --- /dev/null +++ b/demo/index.html @@ -0,0 +1,5415 @@ + + + + + + SLASHED — Demo + + + + + + + + +
    +
    + + SLASHED / demo +
    + +
    + + + +
    + + + +
    + + +
    +

    Theme Customizer

    +

    + Override just 6 tokens in the Light mode column for quick branding — dark mode automatically derives an appropriate value via relative color syntax, no extra work needed. Optionally override any token in the Dark mode column for full per-mode control. Changes apply live to :root; toggle dark mode in the header to preview. +

    + +
    + +
    +

    Light mode

    + +
    + Brand +
    + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    + Status +
    + + + + + + + + + + + + + + + +
    +
    +
    + + +
    +

    Dark mode

    + +
    + Brand +
    + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    + Status +
    + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    + + +
    + +
    +

    Accessibility report (live, both modes)

    +

    + WCAG 2 contrast for your chosen colours, recomputed live. The framework auto-picks readable on-colours (black/white by lightness) and clamps link lightness — but contrast also depends on chroma, so this panel shows the actual result, including any pairs that fall short. AA = 4.5:1 (normal text); AA Large = 3:1 (large/UI). Fix a ✗ by adjusting that colour's lightness, or override the on-/text token directly. +

    +
    +
    +
    + + +
    +

    Colors

    + +

    Brand — light mode (base values)

    +
    +
    primary
    +
    secondary
    +
    tertiary
    +
    action
    +
    neutral
    +
    surface
    +
    + +

    Semantic Surfaces

    +
    +
    bg
    +
    surface
    +
    inset
    +
    raised
    +
    overlay
    +
    inverse
    +
    + +

    Status Colors

    +
    +
    success
    +
    warning
    +
    info
    +
    danger
    +
    + +

    Status Triplets

    +
    +
    Success
    +
    Warning
    +
    Danger
    +
    Info
    +
    + +

    Text Hierarchy

    +
    +

    --sf-color-text (primary)

    +

    --sf-color-text--secondary

    +

    --sf-color-text--muted

    +

    --sf-color-text--placeholder

    +

    --sf-color-text--disabled

    +

    --sf-color-heading

    +
    + +

    Borders

    +
    +
    --sf-color-border
    +
    --sf-color-border--subtle
    +
    --sf-color-border--strong
    +
    --sf-color-border--focus (action color)
    +
    + +

    Gradients

    +
    +
    gradient-primary
    +
    gradient-secondary
    +
    gradient-tertiary
    +
    gradient-brand
    +
    gradient-surface
    +
    + +

    Palette Numeric Scale 50–950 (core/tokens.css)

    +
    +
    50
    +
    100
    +
    200
    +
    300
    +
    400
    +
    500
    +
    600
    +
    700
    +
    800
    +
    900
    +
    950
    +
    + +

    Alpha Scale a5–a80

    +
    +
    a5
    +
    a10
    +
    a30
    +
    a50
    +
    a80
    +
    + +

    Semantic & Functional Aliases

    +
    +
    superlight
    +
    xlight
    +
    lighter
    +
    darker
    +
    xdark
    +
    superdark
    +
    hover
    +
    active
    +
    subtle
    +
    muted
    +
    tint
    +
    +
    + + +
    +

    Scoped Themes

    +

    + Use data-theme="dark" or data-theme="light" on any element to scope a theme. When attributes are inconvenient, .sf-theme-dark and .sf-theme-light are equivalent class aliases. Tokens resolve correctly per-section, enabling nested light-inside-dark (or vice-versa) without extra overrides. +

    + + +
    +

    Dark section data-theme="dark"

    + +
    +
    primary
    +
    secondary
    +
    tertiary
    +
    action
    +
    neutral
    +
    surface
    +
    + +
    +

    --sf-color-text (primary)

    +

    --sf-color-text--secondary

    +

    --sf-color-text--muted

    +
    + +
    +
    Success
    +
    Warning
    +
    Danger
    +
    + + +
    +

    Light section (nested) data-theme="light"

    + +
    +
    primary
    +
    secondary
    +
    tertiary
    +
    action
    +
    neutral
    +
    surface
    +
    + +
    +

    --sf-color-text (primary)

    +

    --sf-color-text--secondary

    +

    --sf-color-text--muted

    +
    + +
    +
    Success
    +
    Warning
    +
    Danger
    +
    +
    +
    + +

    Opt-in theme cross-fade .sf-theme-transition

    +

    + Add class="sf-theme-transition" to <html> (or any subtree) so colours + fade instead of switching instantly when the theme flips. Tune the speed with + --sf-theme-transition-duration. Toggle dark mode in the header to see this block cross-fade. +

    +
    + Smooth theme transition +

    This card fades its background, text and border colours when the mode changes.

    +
    + +

    Section theme aliases .sf-theme-light / .sf-theme-dark

    +

    + Class aliases for data-theme: one class scopes the theme, setting the background and flipping the + whole foreground (text, links, borders) to match — always light or always dark, + regardless of the ambient scheme. +

    +
    +
    + .sf-theme-dark +

    Auto-light text, and a themed link.

    +
    +
    + .sf-theme-light +

    Auto-dark text, and a themed link.

    +
    +
    + +

    Named background surface .sf-surface-bg

    +

    + A reusable, named background bundling a base colour + image/gradient + an optional + overlay layered above it. Define the --sf-surface-bg-* tokens on a scope, + then apply the class. Here the overlay is a scrim over a gradient "image". +

    +
    + Composed background preset +
    +
    + + +
    +

    Typography

    + +

    Heading Scale (base.css)

    +
    +

    h1 — The quick brown fox

    +

    h2 — The quick brown fox

    +

    h3 — The quick brown fox

    +

    h4 — The quick brown fox

    +
    h5 — The quick brown fox
    +
    h6 — The quick brown fox
    +
    + +

    Fluid Text Scale (--sf-text-*)

    +

    All sizes use clamp() — resize the window to see fluid scaling.

    +
    +
    2xs — The quick brown fox jumps over the lazy dog
    +
    xs — The quick brown fox jumps over the lazy dog
    +
    s — The quick brown fox jumps
    +
    m (base) — The quick brown fox
    +
    l — The quick brown fox
    +
    xl — The quick brown
    +
    2xl — The quick
    +
    3xl — Quick
    +
    4xl
    +
    display-s
    +
    display-m
    +
    display-l
    +
    + +

    Font Weights — base weights + semantic roles

    +
    + 300 light — The quick brown fox + 400 normal — The quick brown fox + 500 medium — The quick brown fox + 600 semibold — The quick brown fox + 700 bold — The quick brown fox +
    +

    Semantic roles (override to reweight the whole site):

    +
    + body — The quick brown fox + interactive — buttons, badges, nav + heading — section titles + strong — inline emphasis + display — hero headlines +
    + +

    Semantic Weight Aliases & Font Stacks

    +
    + body + heading + display +
    +
    + humanist — The quick brown fox jumps + geometric — The quick brown fox jumps + slab — The quick brown fox jumps + mono — The quick brown fox jumps +
    + +

    Line Heights (--sf-leading-*)

    +
    +
    + --sf-leading-tight (1.1) +

    Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod.

    +
    +
    + --sf-leading-snug (1.3) +

    Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod.

    +
    +
    + --sf-leading-normal (1.5) +

    Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod.

    +
    +
    + --sf-leading-relaxed (1.625) +

    Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod.

    +
    +
    + +

    Letter Spacing (--sf-tracking-*)

    +
    +
    tracking-tight — THE QUICK BROWN FOX JUMPS OVER
    +
    tracking-normal — THE QUICK BROWN FOX JUMPS OVER
    +
    tracking-wide — THE QUICK BROWN FOX
    +
    tracking-wider — THE QUICK BROWN
    +
    tracking-widest — THE QUICK
    +
    + +

    Semantic Elements (base.css)

    +

    + strong, + em, + mark highlight, + inline code, + Ctrl + C, + CSS, + H2O, + E=mc2, + small text, + link, + deleted, + inserted +

    +
    /* pre + code block */
    +:root {
    +  --sf-color-primary-source-light: oklch(0.47 0.27 264);
    +  --sf-color-neutral-source-light: oklch(0.52 0.025 260);
    +}
    +
    + A blockquote. Try selecting this text to see --sf-color-selection-bg. +
    + +

    Link States

    + +
    + + +
    +

    Spacing

    +

    All fluid tokens use clamp() — resize the window to see bars animate.

    + +
    +
    + --sf-space-none +
    + 0 +
    +
    + --sf-space-px +
    +
    +
    + --sf-space-2xs +
    +
    +
    + --sf-space-xs +
    +
    +
    + --sf-space-s +
    +
    +
    + --sf-space-m +
    +
    +
    + --sf-space-l +
    +
    +
    + --sf-space-xl +
    +
    +
    + --sf-space-2xl +
    +
    +
    + --sf-space-3xl +
    +
    +
    + --sf-space-4xl +
    +
    +
    + +

    Spacing Aliases

    +
    + --sf-gap → --sf-space-m + --sf-content-gap → --sf-space-s + --sf-component-pad → --sf-space-m + --sf-field-block → --sf-space-l + --sf-prose-paragraph → --sf-content-gap → --sf-space-s +
    +
    + + +
    +

    Shadows

    +

    Shadow color is a neutral near-black auto-derived from --sf-color-neutral (--sf-shadow-color) — override it to var(--sf-color-primary) for tinted shadows. In dark mode strength scales up but every layer's alpha is capped at 0.7. Adjust via --sf-shadow-strength.

    + +
    +
    shadow-none
    +
    shadow-xs
    +
    shadow-s
    +
    shadow-m
    +
    shadow-l
    +
    shadow-xl
    +
    shadow-2xl
    +
    shadow-inner
    +
    shadow-glow
    +
    + +

    Text Shadows

    +
    + text-shadow-xs + text-shadow-s + text-shadow-m + text-shadow-l + text-shadow-xl +
    + +

    Drop Shadows (filter — follows alpha edges)

    +
    + + + + + +
    + +

    3D Perspective

    +
    +
    +
    +
    +
    +
    + + +
    +

    Border Radius

    +

    All values multiplied by --sf-radius-scale (1 by default).

    + +
    +
    none
    0
    +
    xs
    2px
    +
    s
    4px
    +
    m
    8px
    +
    l
    12px
    +
    xl
    16px
    +
    2xl
    24px
    +
    3xl
    32px
    +
    4xl
    48px
    +
    full
    9999px
    +
    +
    + + +
    +

    Motion & States

    + +
    + Reduced motion active — Your OS has reduced motion enabled. Animations are paused (duration: 0.01ms via accessibility.css). +
    + +

    Transitions (motion.css — hover these)

    +

    + motion.css applies a default transition to all interactive elements (a, button, input, etc.) using --sf-duration-fast and --sf-ease-out. Hover to see the transition between the base and hover states. +

    +
    + + + Link transition +
    + +

    Easing Curves

    +
    +
    + ease-linear +
    +
    +
    + ease-out +
    +
    +
    + ease-in +
    +
    +
    + ease-in-out +
    +
    +
    + ease-spring +
    +
    +
    + ease-elastic +
    +
    +
    + ease-bounce +
    +
    +
    + ease-overshoot +
    +
    +
    + +

    Animation Presets (motion.css — click to replay)

    +
    + + + + + + +
    + +

    .sf-stagger (motion.css — parent choreographs children's animation-delay; click to replay)

    +
      +
    • 1
    • +
    • 2
    • +
    • 3
    • +
    • 4
    • +
    + +

    @property Color Interpolation (motion.css — sf-color-pulse)

    +

    + Demonstrates smooth oklch color animation via @property-registered tokens. + The box below pulses its --sf-color-primary-source-light lightness. Only works in browsers supporting @property inherits. +

    +
    + .sf-color-pulse — animating --sf-color-primary-source-light +
    + +

    Duration Tokens

    +

    Hover any row — the dot slides across using that duration token. Easing is the same (--sf-ease-out) so the only variable is speed.

    +
    +
    + --sf-duration-instant +
    +
    +
    +
    +
    + --sf-duration-fast (default) +
    +
    +
    +
    +
    + --sf-duration-normal +
    +
    +
    +
    +
    + --sf-duration-slow +
    +
    +
    +
    +
    + --sf-duration-slower +
    +
    +
    +
    +
    + +

    States (states.css)

    +
    +
    +

    .sf-is-loading

    + +
    +
    +

    .sf-is-skeleton

    +
    +
    +
    +
    +
    +
    +
    +

    .sf-is-hidden / .sf-is-invisible

    +
    + visible + hidden (display:none) + invisible (visibility:hidden) + .sf-is-visible (force visibility:visible) +
    +
    +
    +
    + + +
    +

    States — Full Coverage

    +

    Every .sf-is-* class from states.css. Grouped by category.

    + +

    Navigation & Toggling

    +
    + .sf-is-active (--sf-is-active: 1) + .sf-is-current (bold) + .sf-is-selected + .sf-is-highlighted +
    + +

    Disclosure

    +
    + .sf-is-open + .sf-is-expanded + .sf-is-collapsed +
    + +

    Validation / Feedback

    +
    + .sf-is-valid + .sf-is-invalid + .sf-is-warning + .sf-is-success + .sf-is-error + .sf-is-info + .sf-is-danger +
    + +

    Drag & Drop

    +
    + .sf-is-dragging + .sf-is-drop-target + .sf-is-draggable +
    + +

    Overlay

    +
    +
    .sf-overlay
    +
    + +

    Interactivity

    +
    + .sf-is-busy + .sf-is-readonly + .sf-is-disabled + .sf-is-pending + .sf-is-pressed +
    +
    + .sf-focus-parent (focus the input → parent rings) + +
    + +

    Empty State

    +
    +
    + .sf-is-empty:empty → display:none (the empty div above is gone) +
    +
    + + +
    +

    Layout — Additional Primitives

    + +

    .sf-imposter

    +

    Absolutely positioned overlay. Modifiers: --fixed, --contain.

    +
    +
    .sf-imposter (centered)
    +
    +
    +
    .sf-imposter--contain (clamps to 100% − 2 × --sf-imposter-margin in both axes; overflow: auto kicks in only when the content is larger than that box)
    +
    + +

    .sf-imposter--fixed

    +

    Uses position: fixed — not demoed visually to avoid viewport takeover. Class reference: sf-imposter--fixed.

    + +

    .sf-subgrid / .sf-subgrid-rows

    +

    Inherit parent grid tracks. Requires parent with explicit grid.

    +
    +
    +
    Subgrid col 1
    +
    Subgrid col 2
    +
    +
    Regular col
    +
    +

    .sf-subgrid-rows works the same for row tracks.

    + +

    .sf-section-group

    +

    Groups adjacent .sf-section elements with zero gap between them.

    +
    +
    Section A (--s padding)
    +
    Section B (--s padding)
    +
    + +

    .sf-divider

    +

    Token-driven separator (--sf-divider-width/-style/-color). Horizontal by default; .sf-divider--vertical for inline use.

    +

    Content above the divider.

    +
    +

    Content below the divider.

    +
    + Left + + Right +
    +

    Style modifiers — colour via .sf-divider--soft / .sf-divider--strong, line via .sf-divider--dashed / .sf-divider--dotted, and a fading .sf-divider--gradient.

    +
    +
    +
    +
    +
    + +

    .sf-divide

    +

    Places a rule between direct children in one class — no extra markup per gap. .sf-divide--vertical switches to an inline-start border.

    +
    +

    First

    +

    Second

    +

    Third

    +
    +
    + Left + Middle + Right +
    + +

    .sf-icon

    +

    Em-based inline icon sizing. Scales with surrounding text; size modifiers .sf-icon--xs.sf-icon--2xl.

    +
    + + + + + + +
    + +

    .sf-icon--boxed

    +

    Padded, bordered icon frame. Override --sf-icon-box-bg / -border / -radius per instance. Combine with size modifiers; the visible glyph stays at --sf-icon-size and the frame grows around it.

    +
    + + + +
    + +

    .sf-grid--dense

    +

    Dense auto-flow lets later items backfill earlier gaps. Add .sf-grid--dense to any grid.

    +
    +
    span 2
    +
    a
    +
    b
    +
    span 2
    +
    c
    +
    + +

    .sf-cover modifiers

    +
    +
    + .sf-cover--min +
    +
    min
    +
    +
    +
    + .sf-cover--max +
    +
    max
    +
    +
    +
    + .sf-cover--padding-s / --padding-l +
    +
    pad-s
    +
    +
    +
    + +

    .sf-cluster--no-wrap / .sf-switcher--no-wrap / .sf-switcher--vertical

    +
    +
    + .sf-cluster--no-wrap +
    +
    A
    B
    C
    D
    E
    F
    +
    +
    +
    + .sf-switcher--no-wrap +
    +
    1
    2
    3
    +
    +
    +
    + .sf-switcher--vertical +
    +
    1
    2
    3
    +
    +
    +
    + +

    .sf-grid-cols-1 / Ratio grids

    +

    + .sf-grid-cols-1 is intentionally a single-column grid. Ratio grids (.sf-grid-cols-1-2 etc.) collapse to a single column on narrow widths and switch to two columns at 48em via container queries — the parent must declare container-type: inline-size. +

    +
    +
    + .sf-grid-cols-1 (single column by design) +
    +
    Full width row
    +
    Full width row
    +
    +
    +
    + .sf-grid-cols-1-2 (1fr 2fr) +
    +
    1fr
    +
    2fr
    +
    +
    +
    + .sf-grid-cols-2-1 (2fr 1fr) +
    +
    2fr
    +
    1fr
    +
    +
    +
    + .sf-grid-cols-1-3 (1fr 3fr) +
    +
    1fr
    +
    3fr
    +
    +
    +
    + .sf-grid-cols-3-1 (3fr 1fr) +
    +
    3fr
    +
    1fr
    +
    +
    +
    + +

    .sf-cq — container query scope

    +

    + Establishes an inline-size container context so children can use container queries. +

    +
    + container-type: inline-size +
    + +

    .sf-fluid-cq — container-relative fluid scale

    +

    + Makes the fluid type + space scales interpolate against this box's width + (100cqi) instead of the viewport — so text in a narrow column + scales with the column, not the page. Resize the box to see it. +

    +
    +

    Fluid text tied to this container's width.

    +
    + +

    .sf-equal — fixed N-column grid

    +

    + Column count never collapses — unlike .sf-grid-* which uses container queries. +

    +
    +
    + .sf-equal--2 +
    +
    1
    2
    +
    +
    +
    + .sf-equal--3 +
    +
    1
    2
    3
    +
    +
    +
    + .sf-equal--4 +
    +
    1
    2
    3
    4
    +
    +
    +
    + .sf-equal--6 +
    +
    1
    2
    3
    4
    5
    6
    +
    +
    +
    + +

    .sf-scale-down (motion.css)

    +
    + +
    + +

    .sf-center / .sf-center--intrinsic

    +
    +
    + .sf-center (max 20rem, auto margins) +
    +
    +
    +
    +
    .sf-center--intrinsic (flex column, items centered)
    +
    +
    + +

    .sf-box

    +
    +
    + .sf-box — padding + outline border (no box-model disturbance) +
    +
    + +

    .sf-grid-cols-6 / .sf-grid--xs … .sf-grid--2xl

    +

    + Fixed-column grids (.sf-grid-cols-6) use container queries — wrap in container-type: inline-size. Auto-fill grids (.sf-grid--xs/s/m/l/xl/2xl) use repeat(auto-fill, minmax(min(--sf-grid-min, 100%), 1fr)) — they collapse to fewer columns as the container narrows. On very narrow viewports both will stack to a single column; resize the window to see them respond. +

    +
    +
    + .sf-grid-cols-6 +
    +
    1
    2
    3
    4
    5
    6
    +
    +
    +
    + .sf-grid--xs (min ~10rem) +
    +
    A
    B
    C
    D
    E
    +
    +
    +
    + .sf-grid--s (min ~13rem) +
    +
    A
    B
    C
    D
    +
    +
    +
    + .sf-grid--m (min ~16rem) +
    +
    A
    B
    C
    +
    +
    +
    + .sf-grid--l (min ~20rem) +
    +
    A
    B
    C
    +
    +
    +
    + .sf-grid--xl (min ~24rem) +
    +
    A
    B
    +
    +
    +
    + .sf-grid--2xl (min ~28rem) +
    +
    A
    B
    +
    +
    +
    + +

    .sf-grid-flex — flex alternative for uneven item counts

    +

    + Flexbox-based alternative to .sf-grid for item counts that don't divide evenly. By default the last row's leftover items stretch to fill the row; .sf-grid-flex--center keeps them fixed-width and centered instead. Reuses --sf-grid-min/--sf-grid-gap — same --xs … --2xl scale as .sf-grid. +

    +
    +
    + .sf-grid-flex (default — last row stretches) +
    +
    1
    2
    3
    4
    5
    +
    +
    +
    + .sf-grid-flex--center (leftover fixed-width, centered) +
    +
    1
    2
    3
    4
    5
    +
    +
    +
    + .sf-grid-flex--xs / --s / --m / --l / --xl / --2xl (re-point --sf-grid-min) +
    +
    xs
    xs
    xs
    +
    +
    +
    s
    s
    s
    +
    +
    +
    m
    m
    m
    +
    +
    +
    l
    l
    l
    +
    +
    +
    xl
    xl
    +
    +
    +
    2xl
    2xl
    +
    +
    +
    + +

    .sf-sidebar--narrow / .sf-sidebar--wide

    +
    +
    + .sf-sidebar--narrow (12rem sidebar) +
    +
    Narrow sidebar
    +
    Main content
    +
    +
    +
    + .sf-sidebar--wide (26rem sidebar) +
    +
    Wide sidebar
    +
    Main content
    +
    +
    +
    + +

    .sf-container--full / .sf-container--wide

    +
    +
    + .sf-container--wide (90rem) +
    wide content (90rem)
    +
    +
    + .sf-container--full (100%) +
    full-width content (100%)
    +
    +
    + +

    .sf-section--xs / .sf-section--l / .sf-section--xl / .sf-section--2xl

    +
    +
    + .sf-section--xs (small vertical padding) +
    +
    + .sf-section--l (large vertical padding) +
    +
    + .sf-section--xl (extra-large vertical padding) +
    +
    + .sf-section--2xl (hero vertical padding) +
    +
    + +

    .sf-header--xs / .sf-header--s / .sf-header--m / .sf-header--l / .sf-header--xl

    +

    Block padding on the standard spacing scale — lighter than .sf-section. Inline gutter is left untouched.

    +
    +
    .sf-header--xs
    +
    .sf-header--s
    +
    .sf-header--m
    +
    .sf-header--l
    +
    .sf-header--xl
    +
    + +

    .sf-frame--3-2 / .sf-frame--4-3 / .sf-frame--golden

    +
    +
    + .sf-frame--3-2 +
    + 3 / 2 +
    +
    +
    + .sf-frame--4-3 +
    + 4 / 3 +
    +
    +
    + .sf-frame--golden +
    + golden +
    +
    +
    + +

    .sf-stack alignment: --center / --end / --stretch

    +
    +
    + .sf-stack--s --center +
    +
    A
    +
    B
    +
    C
    +
    +
    +
    + .sf-stack--l --end +
    +
    A
    +
    B
    +
    C
    +
    +
    +
    + .sf-stack--2xl --stretch +
    +
    A
    +
    B
    +
    +
    +
    + override beyond scale: style="--sf-stack-gap: var(--sf-space-3xl)" +
    +
    A
    +
    B
    +
    +
    +
    + +

    .sf-gap — gap size modifiers

    +

    + Injects gap into any existing flex or grid container without imposing a display type. +

    +
    +
    + .sf-gap--xs +
    +
    A
    B
    C
    +
    +
    +
    + .sf-gap--s +
    +
    A
    B
    C
    +
    +
    +
    + .sf-gap--m +
    +
    A
    B
    C
    +
    +
    +
    + .sf-gap--l +
    +
    A
    B
    C
    +
    +
    +
    + .sf-gap--xl +
    +
    A
    B
    C
    +
    +
    +
    + .sf-gap--2xl +
    +
    A
    B
    C
    +
    +
    +
    + +

    .sf-cluster gap modifiers: --xs / --s / --m / --l / --xl / --2xl

    +

    + The size suffix sets the gap between items (not alignment). Compare side by side: +

    +
    +
    + override below scale: style="--sf-cluster-gap: var(--sf-space-2xs)" +
    +
    A
    B
    C
    D
    E
    +
    +
    +
    + .sf-cluster--xs (smallest of the canonical scale) +
    +
    A
    B
    C
    D
    E
    +
    +
    +
    + .sf-cluster--l +
    +
    A
    B
    C
    D
    E
    +
    +
    +
    + .sf-cluster--2xl (largest of the canonical scale) +
    +
    A
    B
    C
    D
    E
    +
    +
    +
    + +

    .sf-cluster alignment: --center / --end / --between

    +

    + These set justify-content. Default is flex-start. +

    +
    +
    + default (flex-start) +
    +
    A
    B
    C
    +
    +
    +
    + .sf-cluster--center +
    +
    A
    B
    C
    +
    +
    +
    + .sf-cluster--end +
    +
    A
    B
    C
    +
    +
    +
    + .sf-cluster--between +
    +
    A
    B
    C
    +
    +
    +
    + +

    .sf-cover--padding-l

    +
    +
    padding-l (4xl)
    +
    + +

    .sf-fade-out

    +

    + The animation ends at opacity: 0 with animation-fill-mode: both, so the target stays hidden after playing. Click the button to (re)apply the animation to the box on its right. +

    +
    + +
    Target — watch me fade
    +
    +
    + + +
    +

    Accessibility

    + +

    Skip Link

    +

    A .skip-link is at the very top of this page. Press Tab from the browser address bar to reveal it — it appears above the header.

    + +

    Focus Ring (accessibility.css)

    +

    Tab through these elements to verify :focus-visible ring (2px solid, 2px offset, action color). The ring uses !important so it's never overridden.

    +
    + + Link + + +
    + Details summary +

    Details content.

    +
    +
    + +

    .sr-only

    +

    Hidden from sighted users but available to screen readers: [THIS TEXT IS SCREEN-READER ONLY — not visible] (check with DevTools or a screen reader)

    + +

    Disabled States

    +
    + + + + +
    + +

    Touch Targets (pointer: coarse)

    +

    On touch devices, a, button, input, select, summary automatically get min-height: var(--sf-touch-target) = var(--sf-size-l) = 2.75rem (≈44px). No extra classes needed.

    + +

    High Contrast & Reduced Transparency

    +

    + prefers-contrast: more → thicker focus ring (3px), thicker <hr>.
    + prefers-reduced-transparency: reduce → backdrop becomes solid.
    + These are handled automatically by accessibility.css. +

    + +

    Color Scheme Token

    +

    + --sf-color-scheme: light dark controls the browser's native UI color adaptation (scrollbars, form controls). Override to only light or only dark to lock the mode at the browser level. + Used by both reset.css and base.css. +

    +
    + + +
    +

    Layout — Stack

    +

    .sf-stack — flex column with uniform gap. Modifier suffix sets gap size.

    + +
    +
    + .sf-stack--xs +
    +
    Item 1
    +
    Item 2
    +
    Item 3
    +
    +
    +
    + .sf-stack--m +
    +
    Item 1
    +
    Item 2
    +
    Item 3
    +
    +
    +
    + .sf-stack--xl +
    +
    Item 1
    +
    Item 2
    +
    Item 3
    +
    +
    +
    +

    Override gap: style="--sf-stack-gap: 2rem"

    +
    + + +
    +

    Layout — Cluster

    +

    .sf-cluster — flex wrapping group with uniform gap. Ideal for tags, buttons, inline groups.

    + +
    +
    Design tokens
    +
    CSS layers
    +
    Layout primitives
    +
    Fluid typography
    +
    Motion
    +
    Accessibility
    +
    Reset
    +
    Base
    +
    +

    Alignment modifiers: --center, --end, --between, --no-wrap

    +
    + + +
    +

    Layout — Sidebar

    +

    .sf-sidebar — first child is sidebar (fixed width), second child grows. Collapses to stack when content width < --sf-sidebar-min-width (50%).

    + +
    +
    Sidebar
    (18rem default)
    +
    Main content — grows to fill available space
    +
    +

    Override: --sf-sidebar-width, --sf-sidebar-min-width. Modifier: .sf-sidebar--right

    +
    + + +
    +

    Layout — Switcher

    +

    .sf-switcher — switches between row and column layout at a container threshold. No media queries.

    + +
    +
    Column A
    +
    Column B
    +
    Column C
    +
    +

    Threshold: --sf-switcher-threshold (default from tokens). Below threshold → stacks vertically.

    +
    + + +
    +

    Layout — Grid

    +

    .sf-grid — auto-fill CSS grid. Responsive without any media queries.

    + +
    +
    1
    +
    2
    +
    3
    +
    4
    +
    5
    +
    6
    +
    7
    +
    +

    Override: --sf-grid-min (min column width), --sf-grid-gap. Modifier: .sf-grid--fit (auto-fit). Fixed columns: .sf-grid-cols-2, .sf-grid-cols-3, .sf-grid-cols-4

    +
    + + +
    +

    Layout — Cover

    +

    .sf-cover — full-height flex column. .sf-cover__center child is vertically centered via margin-block: auto.

    + +
    +

    Top content

    +
    + Vertically centered (.sf-cover__center) +
    +

    Bottom content

    +
    +

    Default --sf-cover-min-height: 100dvh — overridden to 16rem here for demo.

    +
    + + +
    +

    Layout — Frame

    +

    .sf-frame — aspect-ratio container. Media children use object-fit: cover.

    + +
    +
    + sf-frame--video (16:9) +
    + 16 / 9 +
    +
    +
    + sf-frame--square (1:1) +
    + 1 / 1 +
    +
    +
    + sf-frame--portrait (3:4) +
    + 3 / 4 +
    +
    +
    + sf-frame--cinema (21:9) +
    + 21 / 9 +
    +
    +
    +
    + + +
    +

    Layout — Reel

    +

    .sf-reel — horizontal scroll container with scroll-snap-type: x mandatory. Scroll to snap cards.

    + +
    +
    Card 1
    +
    Card 2
    +
    Card 3
    +
    Card 4
    +
    Card 5
    +
    Card 6
    +
    +

    Override: --sf-reel-item-width, --sf-reel-gap, --sf-reel-height

    +
    + + +
    +

    Layout — Prose

    +

    .sf-prose — long-form text rhythm. Adds margin-block-start: var(--sf-prose-paragraph) between children. Restores list styles.

    + +
    +

    Prose Heading

    +

    The .sf-prose class provides automatic vertical rhythm for long-form content. All direct children receive spacing automatically — no extra margin classes needed.

    +

    Lists Are Restored

    +
      +
    • List items get list-style: disc back (reset removes it)
    • +
    • Nested list indentation is preserved
    • +
    • Marker color follows --sf-prose-marker-color (defaults to --sf-color-primary)
    • +
    +
      +
    1. Ordered lists work too
    2. +
    3. Each step is clearly numbered
    4. +
    +
    + A blockquote inside prose gets consistent margin-block spacing from the surrounding paragraphs. +
    +

    Use .sf-not-prose on a child to opt out of prose spacing for that element.

    +
    +
    + + +
    +

    Layout — Container & Section

    +

    .sf-container — centered max-width with horizontal gutters. Declares a named inline-size container sf-layout, so consumers can target it precisely with @container sf-layout (...) in their own CSS. .sf-section adds vertical padding.

    + +
    +
    + sf-container--narrow (38rem) +
    narrow content
    +
    +
    + sf-container--prose (65ch) +
    prose content
    +
    +
    + sf-container (75rem default) +
    default content
    +
    +
    +

    .sf-section modifiers: --xs, --s, --m, --l, --xl, --2xl. Combine: <section class="sf-section--m"><div class="sf-container">

    +
    + + +
    +

    Layout — Bento

    +

    .sf-bento — free-form dense grid. Parent needs container-type: inline-size for responsive column collapse.

    + +
    +
    Wide + tall
    (span 2 col, 2 row)
    +
    1
    +
    2
    +
    Wide (span 2)
    +
    3
    +
    4
    +
    +

    Override: --sf-bento-cols (default 4), --sf-bento-row (row height). Column modifiers: .sf-bento--2, .sf-bento--3, .sf-bento--6. Row modifiers: .sf-bento--row-compact, .sf-bento--row-tall. Child span modifiers: .sf-bento-wide (col span 2), .sf-bento-tall (row span 2), .sf-bento-featured (2×2), .sf-bento-full (full width).

    +
    + +
    wide
    .sf-bento-wide
    +
    normal
    +
    normal
    +
    tall
    .sf-bento-tall
    +
    full width — .sf-bento-full
    +
    +

    Column modifiers below use .sf-bento--2, .sf-bento--3, .sf-bento--6

    +
    + + +
    +

    Layout — Alternate (zigzag)

    +

    .sf-alternate — alternating two-column rows. Below 48em (own container width) it stacks; above, every other row reverses its children. Declares the named container sf-alternate and binds the flip query to that name — so a nested .sf-alternate reacts to its OWN width, not its outer container's.

    + +
    +
    +
    Image / leading column
    +
    + Row 1 +

    Standard order: leading column on the left, text on the right (above 48em).

    +
    +
    +
    +
    Image / leading column
    +
    + Row 2 +

    Even row — children swap order via order: 2 / 1.

    +
    +
    +
    +
    Image / leading column
    +
    + Row 3 +

    Back to standard order.

    +
    +
    +
    + +

    Smoke test — .sf-alternate nested inside .sf-bento

    +

    Phase 4 contract: the inner .sf-alternate's flip query is bound to the sf-alternate name, so it reacts to the bento cell's intrinsic width — not the outer page container. The cell below is wide enough (a span-2 bento cell) to flip into the two-column layout independently of viewport width.

    + +
    +
    +

    Wide cell (span 2) — contains a .sf-alternate

    +
    +
    +
    A1
    +
    Left → right
    +
    +
    +
    B1
    +
    Right → left (flipped)
    +
    +
    +
    +
    Narrow bento cell
    +
    +
    + + +
    +

    Layout — Content Grid

    +

    .sf-content-grid — named column grid. Children default to content column. .sf-breakout spans wider. .sf-full-bleed spans edge-to-edge.

    + +
    +

    Normal content column — max-width: --sf-content-width

    +
    + .sf-breakout — spans --sf-breakout-width +
    +
    + .sf-full-bleed — edge to edge +
    +

    Back to content column.

    +
    +
    + + +
    +

    Layout — Pancake

    +

    .sf-pancake — 3-row grid (auto 1fr auto) for sticky-footer layouts. Default min-height: 100dvh.

    + +
    +
    + Header (auto height) +
    +
    + Main (1fr — grows to fill remaining space) +
    +
    + Footer (auto height — sticks to bottom) +
    +
    +

    This demo is capped at 18rem. In production: min-height: 100dvh on <body>.

    +
    + + +
    +

    Reset & Base

    + +

    Form Elements (reset.css + base.css)

    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + + + + +
    +
    + + + + + +
    +
    + +

    Table (reset: border-collapse)

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    TokenValueType
    --sf-color-primaryoklch(0.45 0.2 264)Brand
    --sf-text-mclamp(1rem, …, 1.125rem)Typography
    --sf-space-mclamp(1rem, …, 1.5rem)Spacing
    +
    + +

    Selection Color

    +

    Try selecting this text to see --sf-color-selection-bg in action. The highlight color adapts in dark mode.

    + +

    List Reset

    +

    reset.css sets list-style: none on menu, ul, ol. Outside .sf-prose, styles must be applied manually:

    +
      +
    • This list has manually re-applied list-style: disc
    • +
    • Inside .sf-prose, styles are restored automatically
    • +
    + +

    HR & Separator

    +
    +

    Above: standard <hr> with border token. High-contrast mode thickens it automatically.

    + +

    Box Model (reset.css)

    +

    All elements: box-sizing: border-box. Media (img, video, svg): display: block; max-width: 100%. Margins/padding removed globally. scrollbar-gutter: stable prevents layout shift.

    +
    + + +
    +

    Print

    +

    + SLASHED's print stylesheet preserves authored colour by default — open print preview (Cmd/Ctrl + P) to compare. Two opt-in classes adjust the contract: .print-color-exact forces colours when the browser would flatten them, .print-no-color opts back into ink-on-paper. +

    + +

    Default — authored colour survives

    +

    + Highlighted text in <mark> stays yellow in print. + Success-coloured text stays green. + Danger-coloured text stays red. + External links carry their href in parentheses: visit the SLASHED repo. +

    + +

    .no-print — vanishes from print

    +

    + The badge below disappears from printed output: + SCREEN-ONLY +

    + +

    .print-color-exact — force colour preservation

    + + +

    .print-no-color — opt back into ink-on-paper

    + + +

    Manual verification checklist

    +

    Open print preview and confirm each of the following.

    +
      +
    1. <mark> retains its yellow background (the test for F-04).
    2. +
    3. Success, danger and warning text retain their colour.
    4. +
    5. The SCREEN-ONLY badge is absent.
    6. +
    7. The .print-color-exact callout retains its tinted background.
    8. +
    9. The .print-no-color callout has lost its background.
    10. +
    11. The repo link shows its href in parentheses.
    12. +
    13. The Open print preview button below is absent (it carries .no-print).
    14. +
    + +

    + +

    +
    + + +
    +

    Macros

    +

    + Recipes / patterns from core/macros.css. + Macros answer "what does this element do?" — distinct + from layout primitives, which answer "where do my children go?". +

    + +

    .sf-content-auto — skip offscreen rendering

    +

    + Sets content-visibility: auto so the browser skips layout and paint for this + section while it is offscreen on a long page. contain-intrinsic-size (token + --sf-content-intrinsic-size) reserves a placeholder box so the scrollbar + doesn't jump. Unsupported engines render it normally. +

    +
    +

    This block is render-deferred until it nears the viewport. On long product or article + pages, applying it to repeated sections measurably cuts initial render cost.

    +
    + +

    .sf-tabular-nums — column-aligned figures

    +

    + Fixed-width digits (font-variant-numeric: var(--sf-font-numeric)) so numbers + line up in columns — prices, totals, invoices. +

    +
    +
    1,110.00
    +
    98.40
    +
    7,001.99
    +
    + +

    .sf-flow — equal vertical rhythm

    +
    +

    First child has no top margin (only siblings get the rhythm).

    +

    Second child gets margin-block-start: var(--sf-flow-space).

    +

    So does every subsequent child. Override with the token.

    +
    + +

    .sf-truncate — single-line ellipsis

    +
    + This sentence is intentionally too long for the container so the ellipsis + will appear — text-overflow ellipsis on a single line. +
    + +

    .sf-line-clamp-2 / -3 / -N

    +
    +

    + 2 lines: Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam, quis nostrud exercitation. +

    +

    + 3 lines: Lorem ipsum dolor sit amet, consectetur adipiscing + elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam, quis nostrud exercitation. +

    +

    + 4 lines (via --sf-line-clamp): Lorem ipsum dolor sit amet, + consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation + ullamco laboris nisi ut aliquip ex ea commodo consequat. +

    +
    + +

    .sf-aspect — generic ratio container

    +
    +
    +
    +
    +
    + +

    .sf-equal-height — children stretch to tallest

    +
    +
    Short.
    +
    Two
    lines.
    +
    Three
    lines
    here.
    +
    + +

    .sf-scroll-shadow — top + bottom mask gradient

    +
    +

    Scroll inside this box.

    +

    The mask gradient fades the top and bottom of the content.

    +

    It's pure CSS — no scroll listener.

    +

    Override --sf-scroll-shadow-size to tune the fade depth.

    +

    Pairs nicely with overflow-y: auto on tables, lists, code blocks.

    +

    Also useful inside cards with overflowing comment threads.

    +

    Keep scrolling — the bottom edge fades the same way.

    +

    Final paragraph for proof.

    +
    + +

    .sf-scroll-snap — vertical scroll-snap container

    +
    +
    Slide A
    +
    Slide B
    +
    Slide C
    +
    + +

    .sf-overflow-fade — end-edge mask

    +
    +
    + tag-one + tag-two + tag-three + tag-four + tag-five +
    +
    + +

    .sf-overflow-fade--* — directional variants

    +
    +
    right: tag-one tag-two tag-three tag-four tag-five
    +
    left: tag-one tag-two tag-three tag-four tag-five
    +
    inline: tag-one tag-two tag-three tag-four tag-five
    +
    top: line one
    line two
    line three
    line four
    line five
    +
    bottom: line one
    line two
    line three
    line four
    line five
    +
    block: line one
    line two
    line three
    line four
    line five
    +
    + +

    .sf-no-tap-highlight — suppress mobile tap overlay

    + + +

    .sf-clickable-parent — full-card click target

    +

    + Automatic mode — one link, no extra attributes. Click anywhere on the card to navigate; + the button remains independently clickable. Tab to the card to see the built-in card-level focus ring + (no separate sf-focus-parent recipe needed). +

    +
    +

    Click anywhere on this card to navigate

    +

    The entire card surface is the click target — heading, body text, list, and padding.

    +
      +
    • Click here too — the whole card is the link
    • +
    + +
    + +

    + Explicit mode — multiple links. Add data-overlay-link to the primary link; + all other links and buttons are lifted above the overlay automatically — no manual z-index work required. +

    + + +

    + Class mode (.sf-clickable-parent__overlay) — alternative to data-overlay-link; resolves nesting fragility when secondary links live at different depths. +

    + + +

    .sf-surface--* — auto-flipped foreground

    +
    +
    primary
    +
    secondary
    +
    tertiary
    +
    action
    +
    neutral
    +
    inverse
    +
    success
    +
    warning
    +
    info
    +
    danger
    +
    + +

    .sf-text-gradient — gradient-clipped text

    +

    Headline gradient

    + +

    .sf-link-external — external-link indicator

    +

    + See the external project + for more — the marker is configurable via --sf-link-external-marker. +

    + +

    .sf-link--subtle / .sf-link--reverse — underline affordance

    +

    The variant classes toggle only the underline line; its geometry comes from base a:link via --sf-link-underline-offset / --sf-link-underline-thickness.

    +

    + A subtle link hides its underline until hover/focus, while a + reverse link is underlined at rest and clears on hover. +

    + +

    .sf-scrim — text-over-image legibility

    +

    Gradient overlay between an image and its text. Direction modifiers .sf-scrim--top / .sf-scrim--bottom, or an even wash with .sf-scrim--full. Retune via --sf-scrim-color / --sf-scrim-direction / --sf-scrim-gradient.

    +
    +
    +
    + Bottom scrim +
    +
    +
    +
    + Top scrim +
    +
    +
    +
    + Full wash + .sf-text-protect +
    +
    +
    + +
    + <img> child +
    +
    +
    +
    + +
    +
    + .sf-scrim__content — wrapped img +
    +
    +
    + +

    .sf-bg-layer — background-layer primitive

    +

    Absolutely-positioned cover layer that sits behind a parent's content. The parent auto-promotes to a positioned stacking context via :has(). Compose under .sf-scrim for background → gradient → content layering.

    +
    +
    +
    + bare .sf-bg-layer div +
    +
    +
    +
    + .sf-bg-layer + .sf-scrim +
    +
    +
    + +

    .sf-overlap / .sf-overlap-host — intentional overlap recipe

    +

    One element pulled up over the next, which reserves clearance for it automatically.

    +
    +
    +
    + .sf-overlap-host — content clears the badge above +
    +
    +

    Directional variants: .sf-overlap--down (pulls into the next element), .sf-overlap--start / .sf-overlap--end (pulls into the inline edge).

    + +

    Macros in action — a composed profile card

    +

    A realistic card built from the overlap recipe: a banner with an avatar overlapping into the body below (.sf-overlap / .sf-overlap-host).

    +
    +
    +
    +
    + Jamie Chen +

    Design Systems Lead

    +
    +
    + +

    .sf-focus-shadow — box-shadow focus ring (opt-in)

    +

    Tab to this link: the focus indicator follows the rounded corner via box-shadow: var(--sf-focus-ring-shadow) instead of the default outline.

    +

    + Focusable pill +

    + +

    .sf-section--collapse — adjacent sections share padding

    +
    +
    +

    Section A — primary surface

    +
    +
    +

    Section B — secondary surface (different bg, but content has half-padding from boundary)

    +
    +
    + +

    .sf-section--guttered — section carries the gutter

    +

    Adds padding-inline: var(--sf-gutter) to the section itself while zeroing it on any nested .sf-container, preventing double-guttering.

    +
    +
    +

    .sf-section--guttered — horizontal padding lives on the section, not the container

    +
    +
    + +

    .sf-entrance--* — scroll-driven entrance

    +

    Animations require animation-timeline: view() support (Chrome 115+, Firefox flag-gated). Refresh and scroll to see effects in supported engines.

    +
    +
    .sf-entrance--fade
    +
    .sf-entrance--fade-up
    +
    .sf-entrance--fade-down
    +
    .sf-entrance--fade-left
    +
    .sf-entrance--fade-right
    +
    .sf-entrance--scale-up
    +
    + +

    .sf-exit--* — scroll-driven exit

    +

    Symmetric counterpart of .sf-entrance--*: fires as the element scrolls out of view. Requires animation-timeline: view() support — engines without it render these statically (no unconditional fade-to-hidden fallback).

    +
    +
    .sf-exit--fade
    +
    .sf-exit--fade-up
    +
    .sf-exit--fade-down
    +
    .sf-exit--fade-left
    +
    .sf-exit--fade-right
    +
    .sf-exit--scale-down
    +
    +
    + + + +
    +

    Full API coverage

    +

    + Every public class () rendered live for + manual inspection, and every design token () + with its value resolved from the loaded bundle. Empty token values or broken + previews flag a renamed or dropped API member. +

    + +

    Components 30

    + + +

    Layout primitives 145

    + + +

    Macros & effects 53

    + + +

    Motion & animation 22

    + + +

    State classes (.sf-is-*) 28

    + + +

    Utilities 31

    + + +

    Theme 3

    + + +

    Accessibility 8

    + + +

    Print 4

    + + +

    Forms 1

    + + +

    Design tokens 754

    +

    Values resolve from the loaded bundle. Component-scoped tokens + (--sf-btn-*, --sf-card-*, --sf-field-*) resolve against a + hidden probe of that component; a means the token has no value outside its + own context (e.g. ::selection tokens).

    + + +
    +
    --sf-alternate-gap
    +
    --sf-alternate-inner-gap
    +
    --sf-animation-blink
    +
    --sf-animation-color-pulse
    +
    --sf-animation-fade-in
    +
    --sf-animation-fade-out
    +
    --sf-animation-float
    +
    --sf-animation-ping
    +
    --sf-animation-scale-down
    +
    --sf-animation-scale-up
    +
    --sf-animation-shimmer
    +
    --sf-animation-slide-in-down
    +
    --sf-animation-slide-in-left
    +
    --sf-animation-slide-in-right
    +
    --sf-animation-slide-in-up
    +
    --sf-animation-slide-out-down
    +
    --sf-animation-slide-out-left
    +
    --sf-animation-slide-out-right
    +
    --sf-animation-slide-out-up
    +
    --sf-animation-spin
    +
    --sf-aspect
    +
    --sf-bento-cols-default
    +
    --sf-bento-gap
    +
    --sf-bento-row-compact
    +
    --sf-bento-row-default
    +
    --sf-bento-row-tall
    +
    --sf-bg-layer-fit
    +
    --sf-bg-layer-inset
    +
    --sf-bg-layer-position
    +
    --sf-bg-layer-radius
    +
    --sf-bg-layer-z
    +
    --sf-blur
    +
    --sf-body-color
    +
    --sf-body-em-style
    +
    --sf-body-font-family
    +
    --sf-body-font-size
    +
    --sf-body-font-weight
    +
    --sf-body-line-height
    +
    --sf-body-strong-weight
    +
    --sf-body-text-wrap
    +
    --sf-border
    +
    --sf-border-scale
    +
    --sf-border-strong
    +
    --sf-border-style
    +
    --sf-border-subtle
    +
    --sf-border-width-1
    +
    --sf-border-width-2
    +
    --sf-border-width-3
    +
    --sf-border-width-4
    +
    --sf-border-width-hairline
    +
    --sf-box-border-color
    +
    --sf-box-border-width
    +
    --sf-box-padding
    +
    --sf-breakout-width
    +
    --sf-btn-border-width
    +
    --sf-btn-font-scale
    +
    --sf-btn-font-size
    +
    --sf-btn-font-weight
    +
    --sf-btn-gap
    +
    --sf-btn-l-font-size
    +
    --sf-btn-l-min-height
    +
    --sf-btn-l-padding-block
    +
    --sf-btn-l-padding-inline
    +
    --sf-btn-m-font-size
    +
    --sf-btn-m-min-height
    +
    --sf-btn-m-padding-block
    +
    --sf-btn-m-padding-inline
    +
    --sf-btn-min-height
    +
    --sf-btn-padding-block
    +
    --sf-btn-padding-inline
    +
    --sf-btn-radius
    +
    --sf-btn-s-font-size
    +
    --sf-btn-s-min-height
    +
    --sf-btn-s-padding-block
    +
    --sf-btn-s-padding-inline
    +
    --sf-btn-xl-font-size
    +
    --sf-btn-xl-min-height
    +
    --sf-btn-xl-padding-block
    +
    --sf-btn-xl-padding-inline
    +
    --sf-btn-xs-font-size
    +
    --sf-btn-xs-min-height
    +
    --sf-btn-xs-padding-block
    +
    --sf-btn-xs-padding-inline
    +
    --sf-card-avatar-size
    +
    --sf-card-bg
    +
    --sf-card-border-color
    +
    --sf-card-border-width
    +
    --sf-card-gap
    +
    --sf-card-heading-size
    +
    --sf-card-media-radius
    +
    --sf-card-media-ratio
    +
    --sf-card-padding
    +
    --sf-card-radius
    +
    --sf-card-radius-outer
    +
    --sf-card-shadow
    +
    --sf-card-shadow--elevated
    +
    --sf-card-shadow--hover
    +
    --sf-caret-color
    +
    --sf-center-gutter
    +
    --sf-center-max
    +
    --sf-cluster-align
    +
    --sf-cluster-gap
    +
    --sf-cluster-justify
    +
    --sf-code-font-size
    +
    --sf-color-action
    +
    --sf-color-action--active
    +
    --sf-color-action--hover
    +
    --sf-color-action-100
    +
    --sf-color-action-200
    +
    --sf-color-action-300
    +
    --sf-color-action-400
    +
    --sf-color-action-50
    +
    --sf-color-action-500
    +
    --sf-color-action-600
    +
    --sf-color-action-700
    +
    --sf-color-action-800
    +
    --sf-color-action-900
    +
    --sf-color-action-950
    +
    --sf-color-action-a10
    +
    --sf-color-action-a30
    +
    --sf-color-action-a5
    +
    --sf-color-action-a50
    +
    --sf-color-action-a80
    +
    --sf-color-action-darker
    +
    --sf-color-action-lighter
    +
    --sf-color-action-muted
    +
    --sf-color-action-source-dark
    +
    --sf-color-action-source-light
    +
    --sf-color-action-subtle
    +
    --sf-color-action-superdark
    +
    --sf-color-action-superlight
    +
    --sf-color-action-tint
    +
    --sf-color-action-xdark
    +
    --sf-color-action-xlight
    +
    --sf-color-base
    +
    --sf-color-base--active
    +
    --sf-color-base--hover
    +
    --sf-color-base-100
    +
    --sf-color-base-200
    +
    --sf-color-base-300
    +
    --sf-color-base-400
    +
    --sf-color-base-50
    +
    --sf-color-base-500
    +
    --sf-color-base-600
    +
    --sf-color-base-700
    +
    --sf-color-base-800
    +
    --sf-color-base-900
    +
    --sf-color-base-950
    +
    --sf-color-base-a10
    +
    --sf-color-base-a30
    +
    --sf-color-base-a5
    +
    --sf-color-base-a50
    +
    --sf-color-base-a80
    +
    --sf-color-base-muted
    +
    --sf-color-base-source-dark
    +
    --sf-color-base-source-light
    +
    --sf-color-base-subtle
    +
    --sf-color-base-tint
    +
    --sf-color-bg
    +
    --sf-color-bg--active
    +
    --sf-color-bg--disabled
    +
    --sf-color-bg--focus
    +
    --sf-color-bg--hover
    +
    --sf-color-bg--selected
    +
    --sf-color-black
    +
    --sf-color-border
    +
    --sf-color-border--disabled
    +
    --sf-color-border--focus
    +
    --sf-color-border--strong
    +
    --sf-color-border--subtle
    +
    --sf-color-border--translucent
    +
    --sf-color-code-bg
    +
    --sf-color-code-text
    +
    --sf-color-danger
    +
    --sf-color-danger-muted
    +
    --sf-color-danger-source-dark
    +
    --sf-color-danger-source-light
    +
    --sf-color-danger-strong
    +
    --sf-color-danger-subtle
    +
    --sf-color-danger-tint
    +
    --sf-color-dim
    +
    --sf-color-heading
    +
    --sf-color-info
    +
    --sf-color-info-muted
    +
    --sf-color-info-source-dark
    +
    --sf-color-info-source-light
    +
    --sf-color-info-strong
    +
    --sf-color-info-subtle
    +
    --sf-color-info-tint
    +
    --sf-color-inset
    +
    --sf-color-inverse
    +
    --sf-color-link
    +
    --sf-color-link--active
    +
    --sf-color-link--disabled
    +
    --sf-color-link--hover
    +
    --sf-color-link--underline
    +
    --sf-color-link--visited
    +
    --sf-color-mark-bg
    +
    --sf-color-mark-text
    +
    --sf-color-neutral
    +
    --sf-color-neutral--active
    +
    --sf-color-neutral--hover
    +
    --sf-color-neutral-100
    +
    --sf-color-neutral-200
    +
    --sf-color-neutral-300
    +
    --sf-color-neutral-400
    +
    --sf-color-neutral-50
    +
    --sf-color-neutral-500
    +
    --sf-color-neutral-600
    +
    --sf-color-neutral-700
    +
    --sf-color-neutral-800
    +
    --sf-color-neutral-900
    +
    --sf-color-neutral-950
    +
    --sf-color-neutral-a10
    +
    --sf-color-neutral-a30
    +
    --sf-color-neutral-a5
    +
    --sf-color-neutral-a50
    +
    --sf-color-neutral-a80
    +
    --sf-color-neutral-darker
    +
    --sf-color-neutral-lighter
    +
    --sf-color-neutral-muted
    +
    --sf-color-neutral-source-dark
    +
    --sf-color-neutral-source-light
    +
    --sf-color-neutral-subtle
    +
    --sf-color-neutral-superdark
    +
    --sf-color-neutral-superlight
    +
    --sf-color-neutral-tint
    +
    --sf-color-neutral-xdark
    +
    --sf-color-neutral-xlight
    +
    --sf-color-overlay
    +
    --sf-color-primary
    +
    --sf-color-primary--active
    +
    --sf-color-primary--hover
    +
    --sf-color-primary-100
    +
    --sf-color-primary-200
    +
    --sf-color-primary-300
    +
    --sf-color-primary-400
    +
    --sf-color-primary-50
    +
    --sf-color-primary-500
    +
    --sf-color-primary-600
    +
    --sf-color-primary-700
    +
    --sf-color-primary-800
    +
    --sf-color-primary-900
    +
    --sf-color-primary-950
    +
    --sf-color-primary-a10
    +
    --sf-color-primary-a30
    +
    --sf-color-primary-a5
    +
    --sf-color-primary-a50
    +
    --sf-color-primary-a80
    +
    --sf-color-primary-darker
    +
    --sf-color-primary-lighter
    +
    --sf-color-primary-muted
    +
    --sf-color-primary-source-dark
    +
    --sf-color-primary-source-light
    +
    --sf-color-primary-subtle
    +
    --sf-color-primary-superdark
    +
    --sf-color-primary-superlight
    +
    --sf-color-primary-tint
    +
    --sf-color-primary-xdark
    +
    --sf-color-primary-xlight
    +
    --sf-color-raised
    +
    --sf-color-scheme
    +
    --sf-color-secondary
    +
    --sf-color-secondary--active
    +
    --sf-color-secondary--hover
    +
    --sf-color-secondary-100
    +
    --sf-color-secondary-200
    +
    --sf-color-secondary-300
    +
    --sf-color-secondary-400
    +
    --sf-color-secondary-50
    +
    --sf-color-secondary-500
    +
    --sf-color-secondary-600
    +
    --sf-color-secondary-700
    +
    --sf-color-secondary-800
    +
    --sf-color-secondary-900
    +
    --sf-color-secondary-950
    +
    --sf-color-secondary-a10
    +
    --sf-color-secondary-a30
    +
    --sf-color-secondary-a5
    +
    --sf-color-secondary-a50
    +
    --sf-color-secondary-a80
    +
    --sf-color-secondary-darker
    +
    --sf-color-secondary-lighter
    +
    --sf-color-secondary-muted
    +
    --sf-color-secondary-source-dark
    +
    --sf-color-secondary-source-light
    +
    --sf-color-secondary-subtle
    +
    --sf-color-secondary-superdark
    +
    --sf-color-secondary-superlight
    +
    --sf-color-secondary-tint
    +
    --sf-color-secondary-xdark
    +
    --sf-color-secondary-xlight
    +
    --sf-color-selection-bg
    +
    --sf-color-selection-bg--alt
    +
    --sf-color-selection-text
    +
    --sf-color-selection-text--alt
    +
    --sf-color-success
    +
    --sf-color-success-muted
    +
    --sf-color-success-source-dark
    +
    --sf-color-success-source-light
    +
    --sf-color-success-strong
    +
    --sf-color-success-subtle
    +
    --sf-color-success-tint
    +
    --sf-color-surface
    +
    --sf-color-tertiary
    +
    --sf-color-tertiary--active
    +
    --sf-color-tertiary--hover
    +
    --sf-color-tertiary-100
    +
    --sf-color-tertiary-200
    +
    --sf-color-tertiary-300
    +
    --sf-color-tertiary-400
    +
    --sf-color-tertiary-50
    +
    --sf-color-tertiary-500
    +
    --sf-color-tertiary-600
    +
    --sf-color-tertiary-700
    +
    --sf-color-tertiary-800
    +
    --sf-color-tertiary-900
    +
    --sf-color-tertiary-950
    +
    --sf-color-tertiary-a10
    +
    --sf-color-tertiary-a30
    +
    --sf-color-tertiary-a5
    +
    --sf-color-tertiary-a50
    +
    --sf-color-tertiary-a80
    +
    --sf-color-tertiary-darker
    +
    --sf-color-tertiary-lighter
    +
    --sf-color-tertiary-muted
    +
    --sf-color-tertiary-source-dark
    +
    --sf-color-tertiary-source-light
    +
    --sf-color-tertiary-subtle
    +
    --sf-color-tertiary-superdark
    +
    --sf-color-tertiary-superlight
    +
    --sf-color-tertiary-tint
    +
    --sf-color-tertiary-xdark
    +
    --sf-color-tertiary-xlight
    +
    --sf-color-text
    +
    --sf-color-text--disabled
    +
    --sf-color-text--inverse
    +
    --sf-color-text--muted
    +
    --sf-color-text--on-action
    +
    --sf-color-text--on-base
    +
    --sf-color-text--on-danger
    +
    --sf-color-text--on-info
    +
    --sf-color-text--on-inverse
    +
    --sf-color-text--on-neutral
    +
    --sf-color-text--on-primary
    +
    --sf-color-text--on-secondary
    +
    --sf-color-text--on-success
    +
    --sf-color-text--on-tertiary
    +
    --sf-color-text--on-warning
    +
    --sf-color-text--placeholder
    +
    --sf-color-text--secondary
    +
    --sf-color-warning
    +
    --sf-color-warning-muted
    +
    --sf-color-warning-source-dark
    +
    --sf-color-warning-source-light
    +
    --sf-color-warning-strong
    +
    --sf-color-warning-subtle
    +
    --sf-color-warning-tint
    +
    --sf-color-white
    +
    --sf-component-pad
    +
    --sf-container-default
    +
    --sf-container-full
    +
    --sf-container-narrow
    +
    --sf-container-prose
    +
    --sf-container-wide
    +
    --sf-content-gap
    +
    --sf-content-intrinsic-size
    +
    --sf-content-width
    +
    --sf-contrast-bias
    +
    --sf-contrast-threshold
    +
    --sf-cover-min-height
    +
    --sf-cover-padding
    +
    --sf-current-font-weight
    +
    --sf-density
    +
    --sf-display-l-line-height
    +
    --sf-display-m-line-height
    +
    --sf-display-s-line-height
    +
    --sf-divider-color
    +
    --sf-divider-gap
    +
    --sf-divider-style
    +
    --sf-divider-width
    +
    --sf-drop-shadow-l
    +
    --sf-drop-shadow-m
    +
    --sf-drop-shadow-s
    +
    --sf-drop-shadow-xl
    +
    --sf-drop-shadow-xs
    +
    --sf-duration-fast
    +
    --sf-duration-instant
    +
    --sf-duration-none
    +
    --sf-duration-normal
    +
    --sf-duration-slow
    +
    --sf-duration-slower
    +
    --sf-ease-bounce
    +
    --sf-ease-elastic
    +
    --sf-ease-in
    +
    --sf-ease-in-out
    +
    --sf-ease-linear
    +
    --sf-ease-out
    +
    --sf-ease-overshoot
    +
    --sf-ease-spring
    +
    --sf-equal-gap
    +
    --sf-equal-min-col
    +
    --sf-equal-rule-color
    +
    --sf-equal-rule-style
    +
    --sf-equal-rule-width
    +
    --sf-field-block
    +
    --sf-field-padding-block
    +
    --sf-field-padding-inline
    +
    --sf-field-radius
    +
    --sf-field-required-marker
    +
    --sf-flow-space
    +
    --sf-fluid-max-vw
    +
    --sf-fluid-min-vw
    +
    --sf-fluid-width
    +
    --sf-focus-ring-color
    +
    --sf-focus-ring-offset
    +
    --sf-focus-ring-shadow
    +
    --sf-focus-ring-style
    +
    --sf-focus-ring-width
    +
    --sf-font-body
    +
    --sf-font-display
    +
    --sf-font-features
    +
    --sf-font-geometric
    +
    --sf-font-heading
    +
    --sf-font-humanist
    +
    --sf-font-mono
    +
    --sf-font-numeric
    +
    --sf-font-slab
    +
    --sf-font-variation
    +
    --sf-font-weight-body
    +
    --sf-font-weight-bold
    +
    --sf-font-weight-display
    +
    --sf-font-weight-heading
    +
    --sf-font-weight-interactive
    +
    --sf-font-weight-light
    +
    --sf-font-weight-medium
    +
    --sf-font-weight-normal
    +
    --sf-font-weight-semibold
    +
    --sf-font-weight-strong
    +
    --sf-frame-ratio
    +
    --sf-gap
    +
    --sf-gradient-action
    +
    --sf-gradient-brand
    +
    --sf-gradient-fade--b
    +
    --sf-gradient-fade--l
    +
    --sf-gradient-fade--r
    +
    --sf-gradient-fade--t
    +
    --sf-gradient-primary
    +
    --sf-gradient-secondary
    +
    --sf-gradient-surface
    +
    --sf-gradient-tertiary
    +
    --sf-grid-gap
    +
    --sf-grid-min
    +
    --sf-grid-min-2xl
    +
    --sf-grid-min-l
    +
    --sf-grid-min-m
    +
    --sf-grid-min-s
    +
    --sf-grid-min-xl
    +
    --sf-grid-min-xs
    +
    --sf-gutter
    +
    --sf-h1-font-weight
    +
    --sf-h1-letter-spacing
    +
    --sf-h1-line-height
    +
    --sf-h1-max-width
    +
    --sf-h1-size
    +
    --sf-h2-font-weight
    +
    --sf-h2-letter-spacing
    +
    --sf-h2-line-height
    +
    --sf-h2-max-width
    +
    --sf-h2-size
    +
    --sf-h3-font-weight
    +
    --sf-h3-letter-spacing
    +
    --sf-h3-line-height
    +
    --sf-h3-max-width
    +
    --sf-h3-size
    +
    --sf-h4-font-weight
    +
    --sf-h4-letter-spacing
    +
    --sf-h4-line-height
    +
    --sf-h4-max-width
    +
    --sf-h4-size
    +
    --sf-h5-font-weight
    +
    --sf-h5-letter-spacing
    +
    --sf-h5-line-height
    +
    --sf-h5-max-width
    +
    --sf-h5-size
    +
    --sf-h6-font-weight
    +
    --sf-h6-letter-spacing
    +
    --sf-h6-line-height
    +
    --sf-h6-max-width
    +
    --sf-h6-size
    +
    --sf-header-height
    +
    --sf-header-height-desktop
    +
    --sf-header-height-mobile
    +
    --sf-heading-color
    +
    --sf-heading-font-family
    +
    --sf-heading-text-wrap
    +
    --sf-hover-grow-scale
    +
    --sf-hover-lift
    +
    --sf-hover-shrink-scale
    +
    --sf-hover-slide
    +
    --sf-icon-2xl
    +
    --sf-icon-box-bg
    +
    --sf-icon-box-border
    +
    --sf-icon-box-pad
    +
    --sf-icon-box-radius
    +
    --sf-icon-l
    +
    --sf-icon-m
    +
    --sf-icon-s
    +
    --sf-icon-xl
    +
    --sf-icon-xs
    +
    --sf-imposter-margin
    +
    --sf-is-active
    +
    --sf-is-current
    +
    --sf-is-dark
    +
    --sf-is-open
    +
    --sf-is-pressed
    +
    --sf-leading-normal
    +
    --sf-leading-relaxed
    +
    --sf-leading-snug
    +
    --sf-leading-taper
    +
    --sf-leading-tight
    +
    --sf-line-clamp
    +
    --sf-link-external-label
    +
    --sf-link-external-marker
    +
    --sf-link-underline-offset
    +
    --sf-link-underline-thickness
    +
    --sf-lumlocker
    +
    --sf-mask-scrim-end
    +
    --sf-mask-scrim-start
    +
    --sf-media-radius
    +
    --sf-motion-scale
    +
    --sf-object-fit
    +
    --sf-object-position
    +
    --sf-opacity-disabled
    +
    --sf-opacity-muted
    +
    --sf-optical-sizing
    +
    --sf-overlap-pull
    +
    --sf-palette-mix-100
    +
    --sf-palette-mix-200
    +
    --sf-palette-mix-300
    +
    --sf-palette-mix-400
    +
    --sf-palette-mix-50
    +
    --sf-palette-mix-600
    +
    --sf-palette-mix-700
    +
    --sf-palette-mix-800
    +
    --sf-palette-mix-900
    +
    --sf-palette-mix-950
    +
    --sf-print-base-size
    +
    --sf-print-page-margin
    +
    --sf-print-page-size
    +
    --sf-prose-block-margin
    +
    --sf-prose-blockquote-border
    +
    --sf-prose-blockquote-padding
    +
    --sf-prose-figcaption-size
    +
    --sf-prose-figure-margin
    +
    --sf-prose-heading-gap
    +
    --sf-prose-hr-margin
    +
    --sf-prose-list-gap
    +
    --sf-prose-marker-color
    +
    --sf-prose-media-margin
    +
    --sf-prose-media-radius
    +
    --sf-prose-nested-list-gap
    +
    --sf-prose-paragraph
    +
    --sf-prose-table-pad
    +
    --sf-radius-2xl
    +
    --sf-radius-2xs
    +
    --sf-radius-3xl
    +
    --sf-radius-4xl
    +
    --sf-radius-full
    +
    --sf-radius-l
    +
    --sf-radius-m
    +
    --sf-radius-none
    +
    --sf-radius-outer
    +
    --sf-radius-pill
    +
    --sf-radius-s
    +
    --sf-radius-scale
    +
    --sf-radius-xl
    +
    --sf-radius-xs
    +
    --sf-ratio-3-2
    +
    --sf-ratio-4-3
    +
    --sf-ratio-cinema
    +
    --sf-ratio-golden
    +
    --sf-ratio-portrait
    +
    --sf-ratio-square
    +
    --sf-ratio-video
    +
    --sf-reel-gap
    +
    --sf-reel-height
    +
    --sf-reel-item-width
    +
    --sf-safe-bottom
    +
    --sf-safe-left
    +
    --sf-safe-right
    +
    --sf-safe-top
    +
    --sf-scrim-color
    +
    --sf-scrim-direction
    +
    --sf-scrim-gradient
    +
    --sf-scrim-text-shadow
    +
    --sf-scroll-shadow-size
    +
    --sf-scroll-timeline-range-end
    +
    --sf-scroll-timeline-range-exit-end
    +
    --sf-scroll-timeline-range-exit-start
    +
    --sf-scroll-timeline-range-start
    +
    --sf-scrollbar-thumb
    +
    --sf-scrollbar-track
    +
    --sf-section-pad
    +
    --sf-section-pad--2xl
    +
    --sf-section-pad--l
    +
    --sf-section-pad--m
    +
    --sf-section-pad--s
    +
    --sf-section-pad--xl
    +
    --sf-section-pad--xs
    +
    --sf-section-scale
    +
    --sf-shadow-2xl
    +
    --sf-shadow-color
    +
    --sf-shadow-glow
    +
    --sf-shadow-glow-color
    +
    --sf-shadow-inner
    +
    --sf-shadow-l
    +
    --sf-shadow-lightness
    +
    --sf-shadow-m
    +
    --sf-shadow-none
    +
    --sf-shadow-s
    +
    --sf-shadow-strength
    +
    --sf-shadow-xl
    +
    --sf-shadow-xs
    +
    --sf-sidebar-gap
    +
    --sf-sidebar-min-width
    +
    --sf-sidebar-width
    +
    --sf-size-l
    +
    --sf-size-m
    +
    --sf-size-s
    +
    --sf-size-xl
    +
    --sf-size-xs
    +
    --sf-space-2xl
    +
    --sf-space-2xs
    +
    --sf-space-3xl
    +
    --sf-space-4xl
    +
    --sf-space-base-max
    +
    --sf-space-base-min
    +
    --sf-space-l
    +
    --sf-space-m
    +
    --sf-space-none
    +
    --sf-space-px
    +
    --sf-space-ratio-max
    +
    --sf-space-ratio-min
    +
    --sf-space-s
    +
    --sf-space-scale
    +
    --sf-space-xl
    +
    --sf-space-xs
    +
    --sf-stack-gap
    +
    --sf-stagger-step
    +
    --sf-state-pending-opacity
    +
    --sf-sticky-offset
    +
    --sf-sticky-offset-desktop
    +
    --sf-sticky-offset-mobile
    +
    --sf-surface-bg-animation
    +
    --sf-surface-bg-attachment
    +
    --sf-surface-bg-color
    +
    --sf-surface-bg-image
    +
    --sf-surface-bg-overlay
    +
    --sf-surface-bg-position
    +
    --sf-surface-bg-repeat
    +
    --sf-surface-bg-size
    +
    --sf-surface-color
    +
    --sf-switcher-gap
    +
    --sf-switcher-threshold
    +
    --sf-text-2xl
    +
    --sf-text-2xl-font-weight
    +
    --sf-text-2xl-letter-spacing
    +
    --sf-text-2xl-line-height
    +
    --sf-text-2xl-max-width
    +
    --sf-text-2xs
    +
    --sf-text-2xs-font-weight
    +
    --sf-text-2xs-letter-spacing
    +
    --sf-text-2xs-line-height
    +
    --sf-text-2xs-max-width
    +
    --sf-text-3xl
    +
    --sf-text-3xl-font-weight
    +
    --sf-text-3xl-letter-spacing
    +
    --sf-text-3xl-line-height
    +
    --sf-text-3xl-max-width
    +
    --sf-text-4xl
    +
    --sf-text-4xl-font-weight
    +
    --sf-text-4xl-letter-spacing
    +
    --sf-text-4xl-line-height
    +
    --sf-text-4xl-max-width
    +
    --sf-text-base-max
    +
    --sf-text-base-min
    +
    --sf-text-display-base-max
    +
    --sf-text-display-base-min
    +
    --sf-text-display-l
    +
    --sf-text-display-m
    +
    --sf-text-display-s
    +
    --sf-text-display-scale
    +
    --sf-text-l
    +
    --sf-text-l-font-weight
    +
    --sf-text-l-letter-spacing
    +
    --sf-text-l-line-height
    +
    --sf-text-l-max-width
    +
    --sf-text-m
    +
    --sf-text-m-font-weight
    +
    --sf-text-m-letter-spacing
    +
    --sf-text-m-line-height
    +
    --sf-text-m-max-width
    +
    --sf-text-ratio-max
    +
    --sf-text-ratio-min
    +
    --sf-text-s
    +
    --sf-text-s-font-weight
    +
    --sf-text-s-letter-spacing
    +
    --sf-text-s-line-height
    +
    --sf-text-s-max-width
    +
    --sf-text-scale
    +
    --sf-text-shadow-l
    +
    --sf-text-shadow-m
    +
    --sf-text-shadow-none
    +
    --sf-text-shadow-s
    +
    --sf-text-shadow-xl
    +
    --sf-text-shadow-xs
    +
    --sf-text-xl
    +
    --sf-text-xl-font-weight
    +
    --sf-text-xl-letter-spacing
    +
    --sf-text-xl-line-height
    +
    --sf-text-xl-max-width
    +
    --sf-text-xs
    +
    --sf-text-xs-font-weight
    +
    --sf-text-xs-letter-spacing
    +
    --sf-text-xs-line-height
    +
    --sf-text-xs-max-width
    +
    --sf-theme-transition-duration
    +
    --sf-touch-target
    +
    --sf-tracking-normal
    +
    --sf-tracking-tight
    +
    --sf-tracking-wide
    +
    --sf-tracking-wider
    +
    --sf-tracking-widest
    +
    --sf-transition-colors
    +
    --sf-transition-enter
    +
    --sf-transition-exit
    +
    --sf-transition-fast
    +
    --sf-transition-form-field
    +
    --sf-transition-opacity
    +
    --sf-transition-overlay
    +
    --sf-transition-shadow
    +
    --sf-transition-slow
    +
    --sf-transition-transform
    +
    --sf-z-base
    +
    --sf-z-below
    +
    --sf-z-dropdown
    +
    --sf-z-fixed
    +
    --sf-z-modal
    +
    --sf-z-overlay
    +
    --sf-z-raised
    +
    --sf-z-sticky
    +
    --sf-z-toast
    +
    --sf-z-tooltip
    +
    + + +
    +
    +
    + + + + + diff --git a/demos/full-api-demo-with-overrides.html b/demos/full-api-demo-with-overrides.html deleted file mode 100644 index 91f44be27..000000000 --- a/demos/full-api-demo-with-overrides.html +++ /dev/null @@ -1,1490 +0,0 @@ - - - - - - SLASHED — Full API Demo (overridden) - - - - - - -
    -

    SLASHED Full API Demo

    -

    v0.7.16 · full bundle from jsDelivr CDN · 325 classes · 754 tokens (265 configurable)

    -
    ultimate-override.css is ACTIVE. Every value below is recomputed from perturbed knob tokens — toggle it off in the toolbar, or compare against the un-overridden page.
    - -
    -

    Token galleries highlights

    -

    Color ramps

    -
    primary
    50
    100
    200
    300
    400
    500
    600
    700
    800
    900
    950
    -
    secondary
    50
    100
    200
    300
    400
    500
    600
    700
    800
    900
    950
    -
    tertiary
    50
    100
    200
    300
    400
    500
    600
    700
    800
    900
    950
    -
    action
    50
    100
    200
    300
    400
    500
    600
    700
    800
    900
    950
    -
    neutral
    50
    100
    200
    300
    400
    500
    600
    700
    800
    900
    950
    -
    base
    50
    100
    200
    300
    400
    500
    600
    700
    800
    900
    950
    -

    Semantic / role colors

    -
    primary
    secondary
    tertiary
    action
    neutral
    danger
    warning
    success
    info
    surface
    bg
    inset
    text
    heading
    link
    border
    -

    Spacing scale

    -
    space-2xs
    space-xs
    space-s
    space-m
    space-l
    space-xl
    space-2xl
    space-3xl
    -

    Type scale

    -
    text-2xsQuick brown fox
    text-xsQuick brown fox
    text-sQuick brown fox
    text-mQuick brown fox
    text-lQuick brown fox
    text-xlQuick brown fox
    text-2xlQuick brown fox
    text-3xlQuick brown fox
    text-4xlQuick brown fox
    -

    Radius

    - -

    Shadow

    - -
    - -
    -

    Interactive functions motion · transitions · gradients

    - -

    Animations

    -
    animation-blink
    animation-color-pulse
    animation-fade-in
    animation-fade-out
    animation-float
    animation-ping
    animation-scale-down
    animation-scale-up
    animation-shimmer
    animation-slide-in-down
    animation-slide-in-left
    animation-slide-in-right
    animation-slide-in-up
    animation-slide-out-down
    animation-slide-out-left
    animation-slide-out-right
    animation-slide-out-up
    animation-spin
    - -

    Easing curves

    -
    ease-bounce
    ease-elastic
    ease-in
    ease-in-out
    ease-linear
    ease-out
    ease-overshoot
    ease-spring
    - -

    Durations

    -
    duration-fast
    duration-instant
    duration-none
    duration-normal
    duration-slow
    duration-slower
    - -

    Transitions

    -
    box
    transition-colors
    box
    transition-enter
    box
    transition-exit
    box
    transition-fast
    box
    transition-form-field
    box
    transition-opacity
    box
    transition-overlay
    box
    transition-shadow
    box
    transition-slow
    box
    transition-transform
    - -

    Gradients

    -
    gradient-action
    gradient-brand
    gradient-fade--b
    gradient-fade--l
    gradient-fade--r
    gradient-fade--t
    gradient-primary
    gradient-secondary
    gradient-surface
    gradient-tertiary
    - -

    Drop shadows (filter)

    -
    drop-shadow-l
    drop-shadow-m
    drop-shadow-s
    drop-shadow-xl
    drop-shadow-xs
    -
    - -
    -

    Layout primitives 145

    -
    -
    -
    .sf-alternate
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-bento
    -
    1
    2
    3
    4
    5
    6
    -
    -
    -
    .sf-bento--2
    -
    1
    2
    3
    4
    5
    6
    -
    -
    -
    .sf-bento--3
    -
    1
    2
    3
    4
    5
    6
    -
    -
    -
    .sf-bento--6
    -
    1
    2
    3
    4
    5
    6
    -
    -
    -
    .sf-bento--row-compact
    -
    1
    2
    3
    4
    5
    6
    -
    -
    -
    .sf-bento--row-tall
    -
    1
    2
    3
    4
    5
    6
    -
    -
    -
    .sf-bento-featured
    -
    1
    2
    3
    4
    5
    -
    -
    -
    .sf-bento-full
    -
    full
    1
    2
    3
    4
    5
    -
    -
    -
    .sf-bento-tall
    -
    tall
    1
    2
    3
    4
    5
    -
    -
    -
    .sf-bento-wide
    -
    wide
    1
    2
    3
    4
    5
    -
    -
    -
    .sf-bg-layer
    -
    content over bg
    -
    -
    -
    .sf-box
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-breakout
    -

    content

    breakout
    -
    -
    -
    .sf-center
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-center--intrinsic
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--2xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--between
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--center
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--end
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--l
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--m
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--no-wrap
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--s
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--xs
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-container
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-container--full
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-container--narrow
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-container--prose
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-container--wide
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-content-grid
    -

    content

    breakout
    full-bleed
    -
    -
    -
    .sf-cover
    -
    cover
    -
    -
    -
    .sf-cover__center
    -
    center
    -
    -
    -
    .sf-cover--max
    -
    cover
    -
    -
    -
    .sf-cover--min
    -
    cover
    -
    -
    -
    .sf-cover--padding-l
    -
    cover
    -
    -
    -
    .sf-cover--padding-s
    -
    cover
    -
    -
    -
    .sf-cq
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-divide
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-divide--vertical
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-divider
    -

    above

    below

    -
    -
    -
    .sf-divider--dashed
    -

    above

    below

    -
    -
    -
    .sf-divider--dotted
    -

    above

    below

    -
    -
    -
    .sf-divider--gradient
    -

    above

    below

    -
    -
    -
    .sf-divider--soft
    -

    above

    below

    -
    -
    -
    .sf-divider--strong
    -

    above

    below

    -
    -
    -
    .sf-divider--vertical
    -

    above

    below

    -
    -
    -
    .sf-equal
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-equal--2
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-equal--3
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-equal--4
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-equal--6
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-fluid-cq
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-frame
    -
    media
    -
    -
    -
    .sf-frame--3-2
    -
    media
    -
    -
    -
    .sf-frame--4-3
    -
    media
    -
    -
    -
    .sf-frame--cinema
    -
    media
    -
    -
    -
    .sf-frame--golden
    -
    media
    -
    -
    -
    .sf-frame--portrait
    -
    media
    -
    -
    -
    .sf-frame--square
    -
    media
    -
    -
    -
    .sf-frame--video
    -
    media
    -
    -
    -
    .sf-full-bleed
    -

    content

    full-bleed
    -
    -
    -
    .sf-gap
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-gap--2xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-gap--l
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-gap--m
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-gap--s
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-gap--xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-gap--xs
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid--2xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid--dense
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid--fit
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid--l
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid--m
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid--s
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid--xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid--xs
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-cols-1
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-cols-1-2
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-cols-1-3
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-cols-2
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-cols-2-1
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-cols-3
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-cols-3-1
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-cols-4
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-cols-6
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-flex
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-flex--2xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-flex--center
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-flex--l
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-flex--m
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-flex--s
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-flex--xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-flex--xs
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-header--l
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-header--m
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-header--s
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-header--xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-header--xs
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-icon
    -
    inline icon
    -
    -
    -
    .sf-icon--2xl
    -
    inline icon
    -
    -
    -
    .sf-icon--boxed
    -
    inline icon
    -
    -
    -
    .sf-icon--l
    -
    inline icon
    -
    -
    -
    .sf-icon--m
    -
    inline icon
    -
    -
    -
    .sf-icon--s
    -
    inline icon
    -
    -
    -
    .sf-icon--xl
    -
    inline icon
    -
    -
    -
    .sf-icon--xs
    -
    inline icon
    -
    -
    -
    .sf-imposter
    -
    base
    imposter
    -
    -
    -
    .sf-imposter--contain
    -
    base
    imposter
    -
    -
    -
    .sf-imposter--fixed
    -
    base
    imposter
    -
    -
    -
    .sf-overlay
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-pancake
    -
    header
    main
    footer
    -
    -
    -
    .sf-reel
    -
    1
    2
    3
    4
    5
    6
    -
    -
    -
    .sf-section
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-section--2xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-section--collapse
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-section--guttered
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-section--l
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-section--m
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-section--s
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-section--xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-section--xs
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-section-group
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-sidebar
    -
    main
    aside
    -
    -
    -
    .sf-sidebar--narrow
    -
    main
    aside
    -
    -
    -
    .sf-sidebar--right
    -
    main
    aside
    -
    -
    -
    .sf-sidebar--wide
    -
    main
    aside
    -
    -
    -
    .sf-stack
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-stack--2xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-stack--center
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-stack--end
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-stack--l
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-stack--m
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-stack--s
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-stack--stretch
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-stack--xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-stack--xs
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-subgrid
    -
    1
    2
    3
    -
    -
    -
    .sf-subgrid-rows
    -
    1
    2
    3
    -
    -
    -
    .sf-switcher
    -
    1
    2
    3
    -
    -
    -
    .sf-switcher--no-wrap
    -
    1
    2
    3
    -
    -
    -
    .sf-switcher--vertical
    -
    1
    2
    3
    -
    -
    -
    -
    -

    Macro classes 53

    -
    -
    -
    .sf-aspect
    -
    16 / 9
    -
    -
    -
    .sf-content-auto
    -
    content-auto
    -
    -
    -
    .sf-drop-shadow-l
    -
    drop-shadow-l
    -
    -
    -
    .sf-drop-shadow-m
    -
    drop-shadow-m
    -
    -
    -
    .sf-drop-shadow-s
    -
    drop-shadow-s
    -
    -
    -
    .sf-drop-shadow-xl
    -
    drop-shadow-xl
    -
    -
    -
    .sf-drop-shadow-xs
    -
    drop-shadow-xs
    -
    -
    -
    .sf-equal-height
    -
    short
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.
    -
    -
    -
    .sf-flow
    -

    one

    two

    three

    -
    -
    -
    .sf-line-clamp-2
    -
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.
    -
    -
    -
    .sf-line-clamp-3
    -
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.
    -
    -
    -
    .sf-line-clamp-N
    -
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.
    -
    -
    -
    .sf-link--reverse
    - -
    -
    -
    .sf-link--subtle
    - -
    -
    -
    .sf-link-external
    - -
    -
    -
    .sf-no-tap-highlight
    -
    no-tap-highlight
    -
    -
    -
    .sf-not-prose
    -

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    opted out of prose

    more.

    -
    -
    -
    .sf-overflow-fade
    -

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    -
    -
    -
    .sf-overflow-fade--block
    -

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    -
    -
    -
    .sf-overflow-fade--bottom
    -

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    -
    -
    -
    .sf-overflow-fade--inline
    -

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    -
    -
    -
    .sf-overflow-fade--left
    -

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    -
    -
    -
    .sf-overflow-fade--right
    -

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    -
    -
    -
    .sf-overflow-fade--top
    -

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    -
    -
    -
    .sf-overlap
    -
    overlap
    -
    -
    -
    .sf-overlap--down
    -
    overlap--down
    -
    -
    -
    .sf-overlap--end
    -
    overlap--end
    -
    -
    -
    .sf-overlap--start
    -
    overlap--start
    -
    -
    -
    .sf-overlap-host
    -
    overlap-host
    -
    -
    -
    .sf-prose
    -

    Heading

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    • one
    • two

    Another paragraph.

    -
    -
    -
    .sf-scrim
    -
    over scrim
    -
    -
    -
    .sf-scrim__content
    -
    scrim content
    -
    -
    -
    .sf-scrim--bottom
    -
    over scrim
    -
    -
    -
    .sf-scrim--full
    -
    over scrim
    -
    -
    -
    .sf-scrim--top
    -
    over scrim
    -
    -
    -
    .sf-scroll-shadow
    -

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    -
    -
    -
    .sf-scroll-snap
    -
    1
    2
    3
    4
    5
    -
    -
    -
    .sf-surface
    -
    surface
    -
    -
    -
    .sf-surface--action
    -
    surface--action
    -
    -
    -
    .sf-surface--danger
    -
    surface--danger
    -
    -
    -
    .sf-surface--info
    -
    surface--info
    -
    -
    -
    .sf-surface--inverse
    -
    surface--inverse
    -
    -
    -
    .sf-surface--neutral
    -
    surface--neutral
    -
    -
    -
    .sf-surface--primary
    -
    surface--primary
    -
    -
    -
    .sf-surface--secondary
    -
    surface--secondary
    -
    -
    -
    .sf-surface--success
    -
    surface--success
    -
    -
    -
    .sf-surface--tertiary
    -
    surface--tertiary
    -
    -
    -
    .sf-surface--warning
    -
    surface--warning
    -
    -
    -
    .sf-surface-bg
    -
    surface-bg
    -
    -
    -
    .sf-tabular-nums
    -
    1234567890
    0987654321
    -
    -
    -
    .sf-text-gradient
    -
    Gradient text
    -
    -
    -
    .sf-text-protect
    -
    text-protect
    -
    -
    -
    .sf-truncate
    -
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.
    -
    -
    -
    -
    -

    State classes 28

    -
    -
    -
    .sf-is-active
    -
    sf-is-active
    -
    -
    -
    .sf-is-busy
    -
    sf-is-busy
    -
    -
    -
    .sf-is-collapsed
    -
    sf-is-collapsed
    -
    -
    -
    .sf-is-current
    -
    sf-is-current
    -
    -
    -
    .sf-is-danger
    -
    sf-is-danger
    -
    -
    -
    .sf-is-disabled
    -
    sf-is-disabled
    -
    -
    -
    .sf-is-draggable
    -
    sf-is-draggable
    -
    -
    -
    .sf-is-dragging
    -
    sf-is-dragging
    -
    -
    -
    .sf-is-drop-target
    -
    sf-is-drop-target
    -
    -
    -
    .sf-is-empty
    -
    sf-is-empty
    -
    -
    -
    .sf-is-error
    -
    sf-is-error
    -
    -
    -
    .sf-is-expanded
    -
    sf-is-expanded
    -
    -
    -
    .sf-is-hidden
    -
    -
    -
    -
    .sf-is-highlighted
    -
    sf-is-highlighted
    -
    -
    -
    .sf-is-info
    -
    sf-is-info
    -
    -
    -
    .sf-is-invalid
    -
    sf-is-invalid
    -
    -
    -
    .sf-is-invisible
    -
    sf-is-invisible
    -
    -
    -
    .sf-is-loading
    -
    sf-is-loading
    -
    -
    -
    .sf-is-open
    -
    sf-is-open
    -
    -
    -
    .sf-is-pending
    -
    sf-is-pending
    -
    -
    -
    .sf-is-pressed
    -
    sf-is-pressed
    -
    -
    -
    .sf-is-readonly
    -
    sf-is-readonly
    -
    -
    -
    .sf-is-selected
    -
    sf-is-selected
    -
    -
    -
    .sf-is-skeleton
    -
    sf-is-skeleton
    -
    -
    -
    .sf-is-success
    -
    sf-is-success
    -
    -
    -
    .sf-is-valid
    -
    sf-is-valid
    -
    -
    -
    .sf-is-visible
    -
    sf-is-visible
    -
    -
    -
    .sf-is-warning
    -
    sf-is-warning
    -
    -
    -
    -
    -

    Motion / animation 22

    -
    -
    -
    .sf-color-pulse
    -
    color-pulse
    -
    -
    -
    .sf-entrance--fade
    -
    entrance--fade
    -
    -
    -
    .sf-entrance--fade-down
    -
    entrance--fade-down
    -
    -
    -
    .sf-entrance--fade-left
    -
    entrance--fade-left
    -
    -
    -
    .sf-entrance--fade-right
    -
    entrance--fade-right
    -
    -
    -
    .sf-entrance--fade-up
    -
    entrance--fade-up
    -
    -
    -
    .sf-entrance--scale-up
    -
    entrance--scale-up
    -
    -
    -
    .sf-exit--fade
    -
    exit--fade
    -
    -
    -
    .sf-exit--fade-down
    -
    exit--fade-down
    -
    -
    -
    .sf-exit--fade-left
    -
    exit--fade-left
    -
    -
    -
    .sf-exit--fade-right
    -
    exit--fade-right
    -
    -
    -
    .sf-exit--fade-up
    -
    exit--fade-up
    -
    -
    -
    .sf-exit--scale-down
    -
    exit--scale-down
    -
    -
    -
    .sf-fade-in
    -
    fade-in
    -
    -
    -
    .sf-fade-out
    -
    fade-out
    -
    -
    -
    .sf-scale-down
    -
    scale-down
    -
    -
    -
    .sf-scale-up
    -
    scale-up
    -
    -
    -
    .sf-slide-in-down
    -
    slide-in-down
    -
    -
    -
    .sf-slide-in-left
    -
    slide-in-left
    -
    -
    -
    .sf-slide-in-right
    -
    slide-in-right
    -
    -
    -
    .sf-slide-in-up
    -
    slide-in-up
    -
    -
    -
    .sf-stagger
    -
    1
    2
    3
    -
    -
    -
    -
    -

    Accessibility 8

    -
    -
    -
    .no-motion
    -
    animation suppressed
    -
    -
    -
    .sf-clickable-parent
    -
    card
    -
    -
    -
    .sf-clickable-parent__overlay
    -
    card (overlay link)
    -
    -
    -
    .sf-focus-parent
    -
    -
    -
    -
    .sf-focus-shadow
    -
    -
    -
    -
    .skip-link
    - -
    -
    -
    .sr-only
    - -
    -
    -
    .sr-only-focusable
    - -
    -
    -
    -
    -

    Print 4

    -
    -
    -
    .no-print
    -
    no-print — affects print preview (Ctrl/Cmd-P)
    -
    -
    -
    .print-color-exact
    -
    -
    -
    -
    .print-no-color
    -
    -
    -
    -
    .print-only
    -
    -
    -
    -
    -
    -

    Theme 3

    -
    -
    -
    .sf-theme-dark
    -
    sf-theme-dark
    -
    -
    -
    .sf-theme-light
    -
    sf-theme-light
    -
    -
    -
    .sf-theme-transition
    -
    sf-theme-transition
    -
    -
    -
    - -
    -

    Part 2 — Complete token reference 754 tokens · live values

    -
    Every --sf-* token — knob and consumption, all tiers — with its live computed value (filled by JS). Toggle the theme or the override in the toolbar and watch every value recompute. Tokens that resolve to a colour, length, shadow, gradient, type or motion value also show a visual.
    -

    color 255

    -
    --sf-color-action
    --sf-color-action--active
    --sf-color-action--hover
    --sf-color-action-100
    --sf-color-action-200
    --sf-color-action-300
    --sf-color-action-400
    --sf-color-action-50
    --sf-color-action-500
    --sf-color-action-600
    --sf-color-action-700
    --sf-color-action-800
    --sf-color-action-900
    --sf-color-action-950
    --sf-color-action-a10
    --sf-color-action-a30
    --sf-color-action-a5
    --sf-color-action-a50
    --sf-color-action-a80
    --sf-color-action-darker
    --sf-color-action-lighter
    --sf-color-action-muted
    --sf-color-action-source-dark
    --sf-color-action-source-light
    --sf-color-action-subtle
    --sf-color-action-superdark
    --sf-color-action-superlight
    --sf-color-action-tint
    --sf-color-action-xdark
    --sf-color-action-xlight
    --sf-color-base
    --sf-color-base--active
    --sf-color-base--hover
    --sf-color-base-100
    --sf-color-base-200
    --sf-color-base-300
    --sf-color-base-400
    --sf-color-base-50
    --sf-color-base-500
    --sf-color-base-600
    --sf-color-base-700
    --sf-color-base-800
    --sf-color-base-900
    --sf-color-base-950
    --sf-color-base-a10
    --sf-color-base-a30
    --sf-color-base-a5
    --sf-color-base-a50
    --sf-color-base-a80
    --sf-color-base-muted
    --sf-color-base-source-dark
    --sf-color-base-source-light
    --sf-color-base-subtle
    --sf-color-base-tint
    --sf-color-bg
    --sf-color-bg--active
    --sf-color-bg--disabled
    --sf-color-bg--focus
    --sf-color-bg--hover
    --sf-color-bg--selected
    --sf-color-black
    --sf-color-border
    --sf-color-border--disabled
    --sf-color-border--focus
    --sf-color-border--strong
    --sf-color-border--subtle
    --sf-color-border--translucent
    --sf-color-code-bg
    --sf-color-code-text
    --sf-color-danger
    --sf-color-danger-muted
    --sf-color-danger-source-dark
    --sf-color-danger-source-light
    --sf-color-danger-strong
    --sf-color-danger-subtle
    --sf-color-danger-tint
    --sf-color-dim
    --sf-color-heading
    --sf-color-info
    --sf-color-info-muted
    --sf-color-info-source-dark
    --sf-color-info-source-light
    --sf-color-info-strong
    --sf-color-info-subtle
    --sf-color-info-tint
    --sf-color-inset
    --sf-color-inverse
    --sf-color-link
    --sf-color-link--active
    --sf-color-link--disabled
    --sf-color-link--hover
    --sf-color-link--underline
    --sf-color-link--visited
    --sf-color-mark-bg
    --sf-color-mark-text
    --sf-color-neutral
    --sf-color-neutral--active
    --sf-color-neutral--hover
    --sf-color-neutral-100
    --sf-color-neutral-200
    --sf-color-neutral-300
    --sf-color-neutral-400
    --sf-color-neutral-50
    --sf-color-neutral-500
    --sf-color-neutral-600
    --sf-color-neutral-700
    --sf-color-neutral-800
    --sf-color-neutral-900
    --sf-color-neutral-950
    --sf-color-neutral-a10
    --sf-color-neutral-a30
    --sf-color-neutral-a5
    --sf-color-neutral-a50
    --sf-color-neutral-a80
    --sf-color-neutral-darker
    --sf-color-neutral-lighter
    --sf-color-neutral-muted
    --sf-color-neutral-source-dark
    --sf-color-neutral-source-light
    --sf-color-neutral-subtle
    --sf-color-neutral-superdark
    --sf-color-neutral-superlight
    --sf-color-neutral-tint
    --sf-color-neutral-xdark
    --sf-color-neutral-xlight
    --sf-color-overlay
    --sf-color-primary
    --sf-color-primary--active
    --sf-color-primary--hover
    --sf-color-primary-100
    --sf-color-primary-200
    --sf-color-primary-300
    --sf-color-primary-400
    --sf-color-primary-50
    --sf-color-primary-500
    --sf-color-primary-600
    --sf-color-primary-700
    --sf-color-primary-800
    --sf-color-primary-900
    --sf-color-primary-950
    --sf-color-primary-a10
    --sf-color-primary-a30
    --sf-color-primary-a5
    --sf-color-primary-a50
    --sf-color-primary-a80
    --sf-color-primary-darker
    --sf-color-primary-lighter
    --sf-color-primary-muted
    --sf-color-primary-source-dark
    --sf-color-primary-source-light
    --sf-color-primary-subtle
    --sf-color-primary-superdark
    --sf-color-primary-superlight
    --sf-color-primary-tint
    --sf-color-primary-xdark
    --sf-color-primary-xlight
    --sf-color-raised
    --sf-color-scheme
    --sf-color-secondary
    --sf-color-secondary--active
    --sf-color-secondary--hover
    --sf-color-secondary-100
    --sf-color-secondary-200
    --sf-color-secondary-300
    --sf-color-secondary-400
    --sf-color-secondary-50
    --sf-color-secondary-500
    --sf-color-secondary-600
    --sf-color-secondary-700
    --sf-color-secondary-800
    --sf-color-secondary-900
    --sf-color-secondary-950
    --sf-color-secondary-a10
    --sf-color-secondary-a30
    --sf-color-secondary-a5
    --sf-color-secondary-a50
    --sf-color-secondary-a80
    --sf-color-secondary-darker
    --sf-color-secondary-lighter
    --sf-color-secondary-muted
    --sf-color-secondary-source-dark
    --sf-color-secondary-source-light
    --sf-color-secondary-subtle
    --sf-color-secondary-superdark
    --sf-color-secondary-superlight
    --sf-color-secondary-tint
    --sf-color-secondary-xdark
    --sf-color-secondary-xlight
    --sf-color-selection-bg
    --sf-color-selection-bg--alt
    --sf-color-selection-text
    --sf-color-selection-text--alt
    --sf-color-success
    --sf-color-success-muted
    --sf-color-success-source-dark
    --sf-color-success-source-light
    --sf-color-success-strong
    --sf-color-success-subtle
    --sf-color-success-tint
    --sf-color-surface
    --sf-color-tertiary
    --sf-color-tertiary--active
    --sf-color-tertiary--hover
    --sf-color-tertiary-100
    --sf-color-tertiary-200
    --sf-color-tertiary-300
    --sf-color-tertiary-400
    --sf-color-tertiary-50
    --sf-color-tertiary-500
    --sf-color-tertiary-600
    --sf-color-tertiary-700
    --sf-color-tertiary-800
    --sf-color-tertiary-900
    --sf-color-tertiary-950
    --sf-color-tertiary-a10
    --sf-color-tertiary-a30
    --sf-color-tertiary-a5
    --sf-color-tertiary-a50
    --sf-color-tertiary-a80
    --sf-color-tertiary-darker
    --sf-color-tertiary-lighter
    --sf-color-tertiary-muted
    --sf-color-tertiary-source-dark
    --sf-color-tertiary-source-light
    --sf-color-tertiary-subtle
    --sf-color-tertiary-superdark
    --sf-color-tertiary-superlight
    --sf-color-tertiary-tint
    --sf-color-tertiary-xdark
    --sf-color-tertiary-xlight
    --sf-color-text
    --sf-color-text--disabled
    --sf-color-text--inverse
    --sf-color-text--muted
    --sf-color-text--on-action
    --sf-color-text--on-base
    --sf-color-text--on-danger
    --sf-color-text--on-info
    --sf-color-text--on-inverse
    --sf-color-text--on-neutral
    --sf-color-text--on-primary
    --sf-color-text--on-secondary
    --sf-color-text--on-success
    --sf-color-text--on-tertiary
    --sf-color-text--on-warning
    --sf-color-text--placeholder
    --sf-color-text--secondary
    --sf-color-warning
    --sf-color-warning-muted
    --sf-color-warning-source-dark
    --sf-color-warning-source-light
    --sf-color-warning-strong
    --sf-color-warning-subtle
    --sf-color-warning-tint
    --sf-color-white
    -

    gradient 10

    -
    --sf-gradient-action
    --sf-gradient-brand
    --sf-gradient-fade--b
    --sf-gradient-fade--l
    --sf-gradient-fade--r
    --sf-gradient-fade--t
    --sf-gradient-primary
    --sf-gradient-secondary
    --sf-gradient-surface
    --sf-gradient-tertiary
    -

    shadow 13

    -
    --sf-shadow-2xl
    --sf-shadow-color adv
    --sf-shadow-glow
    --sf-shadow-glow-color adv
    --sf-shadow-inner
    --sf-shadow-l
    --sf-shadow-lightness
    --sf-shadow-m
    --sf-shadow-none
    --sf-shadow-s
    --sf-shadow-strength adv
    --sf-shadow-xl
    --sf-shadow-xs
    -

    drop 5

    -
    --sf-drop-shadow-l
    --sf-drop-shadow-m
    --sf-drop-shadow-s
    --sf-drop-shadow-xl
    --sf-drop-shadow-xs
    -

    radius 14

    -
    --sf-radius-2xl
    --sf-radius-2xs
    --sf-radius-3xl
    --sf-radius-4xl
    --sf-radius-full
    --sf-radius-l
    --sf-radius-m
    --sf-radius-none
    --sf-radius-outer adv
    --sf-radius-pill
    --sf-radius-s
    --sf-radius-scale adv
    --sf-radius-xl
    --sf-radius-xs
    -

    space 16

    -
    --sf-space-2xl
    --sf-space-2xs
    --sf-space-3xl
    --sf-space-4xl
    --sf-space-base-max adv
    --sf-space-base-min adv
    --sf-space-l
    --sf-space-m
    --sf-space-none
    --sf-space-px
    --sf-space-ratio-max adv
    --sf-space-ratio-min adv
    --sf-space-s
    --sf-space-scale adv
    --sf-space-xl
    --sf-space-xs
    -

    size 5

    -
    --sf-size-l
    --sf-size-m
    --sf-size-s
    --sf-size-xl
    --sf-size-xs
    -

    text 62

    -
    --sf-text-2xl
    Aa
    --sf-text-2xl-font-weight
    Aa
    --sf-text-2xl-letter-spacing
    Aa
    --sf-text-2xl-line-height
    Aa
    --sf-text-2xl-max-width
    --sf-text-2xs
    Aa
    --sf-text-2xs-font-weight
    Aa
    --sf-text-2xs-letter-spacing
    Aa
    --sf-text-2xs-line-height
    Aa
    --sf-text-2xs-max-width
    --sf-text-3xl
    Aa
    --sf-text-3xl-font-weight
    Aa
    --sf-text-3xl-letter-spacing
    Aa
    --sf-text-3xl-line-height
    Aa
    --sf-text-3xl-max-width
    --sf-text-4xl
    Aa
    --sf-text-4xl-font-weight
    Aa
    --sf-text-4xl-letter-spacing
    Aa
    --sf-text-4xl-line-height
    Aa
    --sf-text-4xl-max-width
    --sf-text-base-max adv
    --sf-text-base-min adv
    --sf-text-display-base-max adv
    --sf-text-display-base-min adv
    --sf-text-display-l
    Aa
    --sf-text-display-m
    Aa
    --sf-text-display-s
    Aa
    --sf-text-display-scale adv
    --sf-text-l
    Aa
    --sf-text-l-font-weight
    Aa
    --sf-text-l-letter-spacing
    Aa
    --sf-text-l-line-height
    Aa
    --sf-text-l-max-width
    --sf-text-m
    Aa
    --sf-text-m-font-weight
    Aa
    --sf-text-m-letter-spacing
    Aa
    --sf-text-m-line-height
    Aa
    --sf-text-m-max-width
    --sf-text-ratio-max adv
    --sf-text-ratio-min adv
    --sf-text-s
    Aa
    --sf-text-s-font-weight
    Aa
    --sf-text-s-letter-spacing
    Aa
    --sf-text-s-line-height
    Aa
    --sf-text-s-max-width
    --sf-text-scale adv
    --sf-text-shadow-l
    Aa
    --sf-text-shadow-m
    Aa
    --sf-text-shadow-none
    Aa
    --sf-text-shadow-s
    Aa
    --sf-text-shadow-xl
    Aa
    --sf-text-shadow-xs
    Aa
    --sf-text-xl
    Aa
    --sf-text-xl-font-weight
    Aa
    --sf-text-xl-letter-spacing
    Aa
    --sf-text-xl-line-height
    Aa
    --sf-text-xl-max-width
    --sf-text-xs
    Aa
    --sf-text-xs-font-weight
    Aa
    --sf-text-xs-letter-spacing
    Aa
    --sf-text-xs-line-height
    Aa
    --sf-text-xs-max-width
    -

    font 20

    -
    --sf-font-body
    Ag f
    --sf-font-display
    --sf-font-features adv
    --sf-font-geometric
    Ag f
    --sf-font-heading
    --sf-font-humanist
    Ag f
    --sf-font-mono
    Ag f
    --sf-font-numeric
    --sf-font-slab
    Ag f
    --sf-font-variation adv
    --sf-font-weight-body
    Ag
    --sf-font-weight-bold
    Ag
    --sf-font-weight-display
    Ag
    --sf-font-weight-heading
    Ag
    --sf-font-weight-interactive
    Ag
    --sf-font-weight-light
    Ag
    --sf-font-weight-medium
    Ag
    --sf-font-weight-normal
    Ag
    --sf-font-weight-semibold
    Ag
    --sf-font-weight-strong
    Ag
    -

    leading 5

    -
    --sf-leading-normal

    Aa Bb
    Cc Dd

    --sf-leading-relaxed

    Aa Bb
    Cc Dd

    --sf-leading-snug

    Aa Bb
    Cc Dd

    --sf-leading-taper adv

    Aa Bb
    Cc Dd

    --sf-leading-tight

    Aa Bb
    Cc Dd

    -

    tracking 5

    -
    --sf-tracking-normal
    AVTAW
    --sf-tracking-tight
    AVTAW
    --sf-tracking-wide
    AVTAW
    --sf-tracking-wider
    AVTAW
    --sf-tracking-widest
    AVTAW
    -

    duration 6

    -
    --sf-duration-fast
    --sf-duration-instant
    --sf-duration-none
    --sf-duration-normal
    --sf-duration-slow
    --sf-duration-slower
    -

    ease 8

    -
    --sf-ease-bounce
    --sf-ease-elastic
    --sf-ease-in
    --sf-ease-in-out
    --sf-ease-linear
    --sf-ease-out
    --sf-ease-overshoot
    --sf-ease-spring
    -

    transition 10

    -
    --sf-transition-colors
    --sf-transition-enter
    --sf-transition-exit
    --sf-transition-fast
    --sf-transition-form-field
    --sf-transition-opacity
    --sf-transition-overlay
    --sf-transition-shadow
    --sf-transition-slow
    --sf-transition-transform
    -

    animation 18

    -
    --sf-animation-blink
    --sf-animation-color-pulse
    --sf-animation-fade-in
    --sf-animation-fade-out
    --sf-animation-float
    --sf-animation-ping
    --sf-animation-scale-down
    --sf-animation-scale-up
    --sf-animation-shimmer
    --sf-animation-slide-in-down
    --sf-animation-slide-in-left
    --sf-animation-slide-in-right
    --sf-animation-slide-in-up
    --sf-animation-slide-out-down
    --sf-animation-slide-out-left
    --sf-animation-slide-out-right
    --sf-animation-slide-out-up
    --sf-animation-spin
    -

    border 10

    -
    --sf-border
    --sf-border-scale
    --sf-border-strong
    --sf-border-style
    --sf-border-subtle
    --sf-border-width-1
    --sf-border-width-2
    --sf-border-width-3
    --sf-border-width-4
    --sf-border-width-hairline
    -

    focus 5

    -
    --sf-focus-ring-color
    --sf-focus-ring-offset
    --sf-focus-ring-shadow adv
    --sf-focus-ring-style
    --sf-focus-ring-width
    -

    opacity 2

    -
    --sf-opacity-disabled
    --sf-opacity-muted
    -

    blur 1

    -
    --sf-blur
    -

    z 10

    -
    --sf-z-base
    --sf-z-below
    --sf-z-dropdown
    --sf-z-fixed
    --sf-z-modal
    --sf-z-overlay
    --sf-z-raised
    --sf-z-sticky
    --sf-z-toast
    --sf-z-tooltip
    -

    alternate 2

    -
    --sf-alternate-gap
    --sf-alternate-inner-gap
    -

    aspect 1

    -
    --sf-aspect
    -

    bento 5

    -
    --sf-bento-cols-default
    --sf-bento-gap
    --sf-bento-row-compact
    --sf-bento-row-default
    --sf-bento-row-tall
    -

    bg 5

    -
    --sf-bg-layer-fit
    --sf-bg-layer-inset
    --sf-bg-layer-position
    --sf-bg-layer-radius
    --sf-bg-layer-z
    -

    body 8

    -
    --sf-body-color
    --sf-body-em-style
    --sf-body-font-family
    --sf-body-font-size
    --sf-body-font-weight
    --sf-body-line-height
    --sf-body-strong-weight
    --sf-body-text-wrap
    -

    box 3

    -
    --sf-box-border-color
    --sf-box-border-width
    --sf-box-padding
    -

    breakout 1

    -
    --sf-breakout-width
    -

    btn 29

    -
    --sf-btn-border-width
    --sf-btn-font-scale
    --sf-btn-font-size adv
    --sf-btn-font-weight
    --sf-btn-gap
    --sf-btn-l-font-size
    --sf-btn-l-min-height
    --sf-btn-l-padding-block
    --sf-btn-l-padding-inline
    --sf-btn-m-font-size
    --sf-btn-m-min-height
    --sf-btn-m-padding-block
    --sf-btn-m-padding-inline
    --sf-btn-min-height adv
    --sf-btn-padding-block adv
    --sf-btn-padding-inline adv
    --sf-btn-radius
    --sf-btn-s-font-size
    --sf-btn-s-min-height
    --sf-btn-s-padding-block
    --sf-btn-s-padding-inline
    --sf-btn-xl-font-size
    --sf-btn-xl-min-height
    --sf-btn-xl-padding-block
    --sf-btn-xl-padding-inline
    --sf-btn-xs-font-size
    --sf-btn-xs-min-height
    --sf-btn-xs-padding-block
    --sf-btn-xs-padding-inline
    -

    card 14

    -
    --sf-card-avatar-size
    --sf-card-bg
    --sf-card-border-color
    --sf-card-border-width
    --sf-card-gap
    --sf-card-heading-size
    --sf-card-media-radius
    --sf-card-media-ratio
    --sf-card-padding
    --sf-card-radius
    --sf-card-radius-outer
    --sf-card-shadow
    --sf-card-shadow--elevated
    --sf-card-shadow--hover
    -

    caret 1

    -
    --sf-caret-color
    -

    center 2

    -
    --sf-center-gutter
    --sf-center-max
    -

    cluster 3

    -
    --sf-cluster-align
    --sf-cluster-gap
    --sf-cluster-justify
    -

    code 1

    -
    --sf-code-font-size
    -

    component 1

    -
    --sf-component-pad
    -

    container 5

    -
    --sf-container-default
    --sf-container-full
    --sf-container-narrow
    --sf-container-prose
    --sf-container-wide
    -

    content 3

    -
    --sf-content-gap
    --sf-content-intrinsic-size
    --sf-content-width
    -

    contrast 2

    -
    --sf-contrast-bias adv
    --sf-contrast-threshold adv
    -

    cover 2

    -
    --sf-cover-min-height
    --sf-cover-padding
    -

    current 1

    -
    --sf-current-font-weight
    -

    density 1

    -
    --sf-density adv
    -

    display 3

    -
    --sf-display-l-line-height
    --sf-display-m-line-height
    --sf-display-s-line-height
    -

    divider 4

    -
    --sf-divider-color
    --sf-divider-gap
    --sf-divider-style
    --sf-divider-width
    -

    equal 5

    -
    --sf-equal-gap
    --sf-equal-min-col
    --sf-equal-rule-color
    --sf-equal-rule-style
    --sf-equal-rule-width
    -

    field 5

    -
    --sf-field-block
    --sf-field-padding-block
    --sf-field-padding-inline
    --sf-field-radius
    --sf-field-required-marker
    -

    flow 1

    -
    --sf-flow-space
    -

    fluid 3

    -
    --sf-fluid-max-vw adv
    --sf-fluid-min-vw adv
    --sf-fluid-width
    -

    frame 1

    -
    --sf-frame-ratio
    -

    gap 1

    -
    --sf-gap
    -

    grid 8

    -
    --sf-grid-gap
    --sf-grid-min
    --sf-grid-min-2xl
    --sf-grid-min-l
    --sf-grid-min-m
    --sf-grid-min-s
    --sf-grid-min-xl
    --sf-grid-min-xs
    -

    gutter 1

    -
    --sf-gutter
    -

    h1 5

    -
    --sf-h1-font-weight
    --sf-h1-letter-spacing
    --sf-h1-line-height
    --sf-h1-max-width
    --sf-h1-size
    -

    h2 5

    -
    --sf-h2-font-weight
    --sf-h2-letter-spacing
    --sf-h2-line-height
    --sf-h2-max-width
    --sf-h2-size
    -

    h3 5

    -
    --sf-h3-font-weight
    --sf-h3-letter-spacing
    --sf-h3-line-height
    --sf-h3-max-width
    --sf-h3-size
    -

    h4 5

    -
    --sf-h4-font-weight
    --sf-h4-letter-spacing
    --sf-h4-line-height
    --sf-h4-max-width
    --sf-h4-size
    -

    h5 5

    -
    --sf-h5-font-weight
    --sf-h5-letter-spacing
    --sf-h5-line-height
    --sf-h5-max-width
    --sf-h5-size
    -

    h6 5

    -
    --sf-h6-font-weight
    --sf-h6-letter-spacing
    --sf-h6-line-height
    --sf-h6-max-width
    --sf-h6-size
    -

    header 3

    -
    --sf-header-height
    --sf-header-height-desktop
    --sf-header-height-mobile
    -

    heading 3

    -
    --sf-heading-color
    --sf-heading-font-family
    --sf-heading-text-wrap
    -

    hover 4

    -
    --sf-hover-grow-scale
    --sf-hover-lift
    --sf-hover-shrink-scale
    --sf-hover-slide
    -

    icon 10

    -
    --sf-icon-2xl
    --sf-icon-box-bg
    --sf-icon-box-border
    --sf-icon-box-pad
    --sf-icon-box-radius
    --sf-icon-l
    --sf-icon-m
    --sf-icon-s
    --sf-icon-xl
    --sf-icon-xs
    -

    imposter 1

    -
    --sf-imposter-margin
    -

    is 5

    -
    --sf-is-active adv
    --sf-is-current adv
    --sf-is-dark internal
    --sf-is-open adv
    --sf-is-pressed adv
    -

    line 1

    -
    --sf-line-clamp
    -

    link 4

    -
    --sf-link-external-label
    --sf-link-external-marker
    --sf-link-underline-offset
    --sf-link-underline-thickness
    -

    lumlocker 1

    -
    --sf-lumlocker adv
    -

    mask 2

    -
    --sf-mask-scrim-end adv
    --sf-mask-scrim-start adv
    -

    media 1

    -
    --sf-media-radius
    -

    motion 1

    -
    --sf-motion-scale adv
    -

    object 2

    -
    --sf-object-fit
    --sf-object-position
    -

    optical 1

    -
    --sf-optical-sizing adv
    -

    overlap 1

    -
    --sf-overlap-pull
    -

    palette 10

    -
    --sf-palette-mix-100 adv
    --sf-palette-mix-200 adv
    --sf-palette-mix-300 adv
    --sf-palette-mix-400 adv
    --sf-palette-mix-50 adv
    --sf-palette-mix-600 adv
    --sf-palette-mix-700 adv
    --sf-palette-mix-800 adv
    --sf-palette-mix-900 adv
    --sf-palette-mix-950 adv
    -

    print 3

    -
    --sf-print-base-size adv
    --sf-print-page-margin adv
    --sf-print-page-size adv
    -

    prose 14

    -
    --sf-prose-block-margin
    --sf-prose-blockquote-border
    --sf-prose-blockquote-padding
    --sf-prose-figcaption-size
    --sf-prose-figure-margin
    --sf-prose-heading-gap
    --sf-prose-hr-margin
    --sf-prose-list-gap
    --sf-prose-marker-color
    --sf-prose-media-margin
    --sf-prose-media-radius
    --sf-prose-nested-list-gap
    --sf-prose-paragraph
    --sf-prose-table-pad
    -

    ratio 7

    -
    --sf-ratio-3-2
    --sf-ratio-4-3
    --sf-ratio-cinema
    --sf-ratio-golden
    --sf-ratio-portrait
    --sf-ratio-square
    --sf-ratio-video
    -

    reel 3

    -
    --sf-reel-gap
    --sf-reel-height
    --sf-reel-item-width
    -

    safe 4

    -
    --sf-safe-bottom adv
    --sf-safe-left adv
    --sf-safe-right adv
    --sf-safe-top adv
    -

    scrim 4

    -
    --sf-scrim-color
    --sf-scrim-direction
    --sf-scrim-gradient
    --sf-scrim-text-shadow
    -

    scroll 5

    -
    --sf-scroll-shadow-size
    --sf-scroll-timeline-range-end adv
    --sf-scroll-timeline-range-exit-end
    --sf-scroll-timeline-range-exit-start
    --sf-scroll-timeline-range-start adv
    -

    scrollbar 2

    -
    --sf-scrollbar-thumb
    --sf-scrollbar-track
    -

    section 8

    -
    --sf-section-pad
    --sf-section-pad--2xl
    --sf-section-pad--l
    --sf-section-pad--m
    --sf-section-pad--s
    --sf-section-pad--xl
    --sf-section-pad--xs
    --sf-section-scale adv
    -

    sidebar 3

    -
    --sf-sidebar-gap
    --sf-sidebar-min-width
    --sf-sidebar-width
    -

    stack 1

    -
    --sf-stack-gap
    -

    stagger 1

    -
    --sf-stagger-step
    -

    state 1

    -
    --sf-state-pending-opacity
    -

    sticky 3

    -
    --sf-sticky-offset
    --sf-sticky-offset-desktop
    --sf-sticky-offset-mobile
    -

    surface 9

    -
    --sf-surface-bg-animation
    --sf-surface-bg-attachment
    --sf-surface-bg-color
    --sf-surface-bg-image
    --sf-surface-bg-overlay
    --sf-surface-bg-position
    --sf-surface-bg-repeat
    --sf-surface-bg-size
    --sf-surface-color
    -

    switcher 2

    -
    --sf-switcher-gap
    --sf-switcher-threshold
    -

    theme 1

    -
    --sf-theme-transition-duration
    -

    touch 1

    -
    --sf-touch-target
    -
    -
    - - - diff --git a/demos/full-api-demo.html b/demos/full-api-demo.html deleted file mode 100644 index 485949598..000000000 --- a/demos/full-api-demo.html +++ /dev/null @@ -1,1489 +0,0 @@ - - - - - - SLASHED — Full API Demo - - - - - -
    -

    SLASHED Full API Demo

    -

    v0.7.16 · full bundle from jsDelivr CDN · 325 classes · 754 tokens (265 configurable)

    -
    Baseline render with default tokens. Use the toolbar to switch theme, toggle the ultimate override live, or replay motion. The always-on override variant is full-api-demo-with-overrides.html.
    - -
    -

    Token galleries highlights

    -

    Color ramps

    -
    primary
    50
    100
    200
    300
    400
    500
    600
    700
    800
    900
    950
    -
    secondary
    50
    100
    200
    300
    400
    500
    600
    700
    800
    900
    950
    -
    tertiary
    50
    100
    200
    300
    400
    500
    600
    700
    800
    900
    950
    -
    action
    50
    100
    200
    300
    400
    500
    600
    700
    800
    900
    950
    -
    neutral
    50
    100
    200
    300
    400
    500
    600
    700
    800
    900
    950
    -
    base
    50
    100
    200
    300
    400
    500
    600
    700
    800
    900
    950
    -

    Semantic / role colors

    -
    primary
    secondary
    tertiary
    action
    neutral
    danger
    warning
    success
    info
    surface
    bg
    inset
    text
    heading
    link
    border
    -

    Spacing scale

    -
    space-2xs
    space-xs
    space-s
    space-m
    space-l
    space-xl
    space-2xl
    space-3xl
    -

    Type scale

    -
    text-2xsQuick brown fox
    text-xsQuick brown fox
    text-sQuick brown fox
    text-mQuick brown fox
    text-lQuick brown fox
    text-xlQuick brown fox
    text-2xlQuick brown fox
    text-3xlQuick brown fox
    text-4xlQuick brown fox
    -

    Radius

    - -

    Shadow

    - -
    - -
    -

    Interactive functions motion · transitions · gradients

    - -

    Animations

    -
    animation-blink
    animation-color-pulse
    animation-fade-in
    animation-fade-out
    animation-float
    animation-ping
    animation-scale-down
    animation-scale-up
    animation-shimmer
    animation-slide-in-down
    animation-slide-in-left
    animation-slide-in-right
    animation-slide-in-up
    animation-slide-out-down
    animation-slide-out-left
    animation-slide-out-right
    animation-slide-out-up
    animation-spin
    - -

    Easing curves

    -
    ease-bounce
    ease-elastic
    ease-in
    ease-in-out
    ease-linear
    ease-out
    ease-overshoot
    ease-spring
    - -

    Durations

    -
    duration-fast
    duration-instant
    duration-none
    duration-normal
    duration-slow
    duration-slower
    - -

    Transitions

    -
    box
    transition-colors
    box
    transition-enter
    box
    transition-exit
    box
    transition-fast
    box
    transition-form-field
    box
    transition-opacity
    box
    transition-overlay
    box
    transition-shadow
    box
    transition-slow
    box
    transition-transform
    - -

    Gradients

    -
    gradient-action
    gradient-brand
    gradient-fade--b
    gradient-fade--l
    gradient-fade--r
    gradient-fade--t
    gradient-primary
    gradient-secondary
    gradient-surface
    gradient-tertiary
    - -

    Drop shadows (filter)

    -
    drop-shadow-l
    drop-shadow-m
    drop-shadow-s
    drop-shadow-xl
    drop-shadow-xs
    -
    - -
    -

    Layout primitives 145

    -
    -
    -
    .sf-alternate
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-bento
    -
    1
    2
    3
    4
    5
    6
    -
    -
    -
    .sf-bento--2
    -
    1
    2
    3
    4
    5
    6
    -
    -
    -
    .sf-bento--3
    -
    1
    2
    3
    4
    5
    6
    -
    -
    -
    .sf-bento--6
    -
    1
    2
    3
    4
    5
    6
    -
    -
    -
    .sf-bento--row-compact
    -
    1
    2
    3
    4
    5
    6
    -
    -
    -
    .sf-bento--row-tall
    -
    1
    2
    3
    4
    5
    6
    -
    -
    -
    .sf-bento-featured
    -
    1
    2
    3
    4
    5
    -
    -
    -
    .sf-bento-full
    -
    full
    1
    2
    3
    4
    5
    -
    -
    -
    .sf-bento-tall
    -
    tall
    1
    2
    3
    4
    5
    -
    -
    -
    .sf-bento-wide
    -
    wide
    1
    2
    3
    4
    5
    -
    -
    -
    .sf-bg-layer
    -
    content over bg
    -
    -
    -
    .sf-box
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-breakout
    -

    content

    breakout
    -
    -
    -
    .sf-center
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-center--intrinsic
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--2xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--between
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--center
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--end
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--l
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--m
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--no-wrap
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--s
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-cluster--xs
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-container
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-container--full
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-container--narrow
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-container--prose
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-container--wide
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-content-grid
    -

    content

    breakout
    full-bleed
    -
    -
    -
    .sf-cover
    -
    cover
    -
    -
    -
    .sf-cover__center
    -
    center
    -
    -
    -
    .sf-cover--max
    -
    cover
    -
    -
    -
    .sf-cover--min
    -
    cover
    -
    -
    -
    .sf-cover--padding-l
    -
    cover
    -
    -
    -
    .sf-cover--padding-s
    -
    cover
    -
    -
    -
    .sf-cq
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-divide
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-divide--vertical
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-divider
    -

    above

    below

    -
    -
    -
    .sf-divider--dashed
    -

    above

    below

    -
    -
    -
    .sf-divider--dotted
    -

    above

    below

    -
    -
    -
    .sf-divider--gradient
    -

    above

    below

    -
    -
    -
    .sf-divider--soft
    -

    above

    below

    -
    -
    -
    .sf-divider--strong
    -

    above

    below

    -
    -
    -
    .sf-divider--vertical
    -

    above

    below

    -
    -
    -
    .sf-equal
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-equal--2
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-equal--3
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-equal--4
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-equal--6
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-fluid-cq
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-frame
    -
    media
    -
    -
    -
    .sf-frame--3-2
    -
    media
    -
    -
    -
    .sf-frame--4-3
    -
    media
    -
    -
    -
    .sf-frame--cinema
    -
    media
    -
    -
    -
    .sf-frame--golden
    -
    media
    -
    -
    -
    .sf-frame--portrait
    -
    media
    -
    -
    -
    .sf-frame--square
    -
    media
    -
    -
    -
    .sf-frame--video
    -
    media
    -
    -
    -
    .sf-full-bleed
    -

    content

    full-bleed
    -
    -
    -
    .sf-gap
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-gap--2xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-gap--l
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-gap--m
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-gap--s
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-gap--xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-gap--xs
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid--2xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid--dense
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid--fit
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid--l
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid--m
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid--s
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid--xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid--xs
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-cols-1
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-cols-1-2
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-cols-1-3
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-cols-2
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-cols-2-1
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-cols-3
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-cols-3-1
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-cols-4
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-cols-6
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-flex
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-flex--2xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-flex--center
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-flex--l
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-flex--m
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-flex--s
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-flex--xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-grid-flex--xs
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-header--l
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-header--m
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-header--s
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-header--xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-header--xs
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-icon
    -
    inline icon
    -
    -
    -
    .sf-icon--2xl
    -
    inline icon
    -
    -
    -
    .sf-icon--boxed
    -
    inline icon
    -
    -
    -
    .sf-icon--l
    -
    inline icon
    -
    -
    -
    .sf-icon--m
    -
    inline icon
    -
    -
    -
    .sf-icon--s
    -
    inline icon
    -
    -
    -
    .sf-icon--xl
    -
    inline icon
    -
    -
    -
    .sf-icon--xs
    -
    inline icon
    -
    -
    -
    .sf-imposter
    -
    base
    imposter
    -
    -
    -
    .sf-imposter--contain
    -
    base
    imposter
    -
    -
    -
    .sf-imposter--fixed
    -
    base
    imposter
    -
    -
    -
    .sf-overlay
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-pancake
    -
    header
    main
    footer
    -
    -
    -
    .sf-reel
    -
    1
    2
    3
    4
    5
    6
    -
    -
    -
    .sf-section
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-section--2xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-section--collapse
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-section--guttered
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-section--l
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-section--m
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-section--s
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-section--xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-section--xs
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-section-group
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-sidebar
    -
    main
    aside
    -
    -
    -
    .sf-sidebar--narrow
    -
    main
    aside
    -
    -
    -
    .sf-sidebar--right
    -
    main
    aside
    -
    -
    -
    .sf-sidebar--wide
    -
    main
    aside
    -
    -
    -
    .sf-stack
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-stack--2xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-stack--center
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-stack--end
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-stack--l
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-stack--m
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-stack--s
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-stack--stretch
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-stack--xl
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-stack--xs
    -
    1
    2
    3
    4
    -
    -
    -
    .sf-subgrid
    -
    1
    2
    3
    -
    -
    -
    .sf-subgrid-rows
    -
    1
    2
    3
    -
    -
    -
    .sf-switcher
    -
    1
    2
    3
    -
    -
    -
    .sf-switcher--no-wrap
    -
    1
    2
    3
    -
    -
    -
    .sf-switcher--vertical
    -
    1
    2
    3
    -
    -
    -
    -
    -

    Macro classes 53

    -
    -
    -
    .sf-aspect
    -
    16 / 9
    -
    -
    -
    .sf-content-auto
    -
    content-auto
    -
    -
    -
    .sf-drop-shadow-l
    -
    drop-shadow-l
    -
    -
    -
    .sf-drop-shadow-m
    -
    drop-shadow-m
    -
    -
    -
    .sf-drop-shadow-s
    -
    drop-shadow-s
    -
    -
    -
    .sf-drop-shadow-xl
    -
    drop-shadow-xl
    -
    -
    -
    .sf-drop-shadow-xs
    -
    drop-shadow-xs
    -
    -
    -
    .sf-equal-height
    -
    short
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.
    -
    -
    -
    .sf-flow
    -

    one

    two

    three

    -
    -
    -
    .sf-line-clamp-2
    -
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.
    -
    -
    -
    .sf-line-clamp-3
    -
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.
    -
    -
    -
    .sf-line-clamp-N
    -
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.
    -
    -
    -
    .sf-link--reverse
    - -
    -
    -
    .sf-link--subtle
    - -
    -
    -
    .sf-link-external
    - -
    -
    -
    .sf-no-tap-highlight
    -
    no-tap-highlight
    -
    -
    -
    .sf-not-prose
    -

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    opted out of prose

    more.

    -
    -
    -
    .sf-overflow-fade
    -

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    -
    -
    -
    .sf-overflow-fade--block
    -

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    -
    -
    -
    .sf-overflow-fade--bottom
    -

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    -
    -
    -
    .sf-overflow-fade--inline
    -

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    -
    -
    -
    .sf-overflow-fade--left
    -

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    -
    -
    -
    .sf-overflow-fade--right
    -

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    -
    -
    -
    .sf-overflow-fade--top
    -

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    -
    -
    -
    .sf-overlap
    -
    overlap
    -
    -
    -
    .sf-overlap--down
    -
    overlap--down
    -
    -
    -
    .sf-overlap--end
    -
    overlap--end
    -
    -
    -
    .sf-overlap--start
    -
    overlap--start
    -
    -
    -
    .sf-overlap-host
    -
    overlap-host
    -
    -
    -
    .sf-prose
    -

    Heading

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    • one
    • two

    Another paragraph.

    -
    -
    -
    .sf-scrim
    -
    over scrim
    -
    -
    -
    .sf-scrim__content
    -
    scrim content
    -
    -
    -
    .sf-scrim--bottom
    -
    over scrim
    -
    -
    -
    .sf-scrim--full
    -
    over scrim
    -
    -
    -
    .sf-scrim--top
    -
    over scrim
    -
    -
    -
    .sf-scroll-shadow
    -

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.

    -
    -
    -
    .sf-scroll-snap
    -
    1
    2
    3
    4
    5
    -
    -
    -
    .sf-surface
    -
    surface
    -
    -
    -
    .sf-surface--action
    -
    surface--action
    -
    -
    -
    .sf-surface--danger
    -
    surface--danger
    -
    -
    -
    .sf-surface--info
    -
    surface--info
    -
    -
    -
    .sf-surface--inverse
    -
    surface--inverse
    -
    -
    -
    .sf-surface--neutral
    -
    surface--neutral
    -
    -
    -
    .sf-surface--primary
    -
    surface--primary
    -
    -
    -
    .sf-surface--secondary
    -
    surface--secondary
    -
    -
    -
    .sf-surface--success
    -
    surface--success
    -
    -
    -
    .sf-surface--tertiary
    -
    surface--tertiary
    -
    -
    -
    .sf-surface--warning
    -
    surface--warning
    -
    -
    -
    .sf-surface-bg
    -
    surface-bg
    -
    -
    -
    .sf-tabular-nums
    -
    1234567890
    0987654321
    -
    -
    -
    .sf-text-gradient
    -
    Gradient text
    -
    -
    -
    .sf-text-protect
    -
    text-protect
    -
    -
    -
    .sf-truncate
    -
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.
    -
    -
    -
    -
    -

    State classes 28

    -
    -
    -
    .sf-is-active
    -
    sf-is-active
    -
    -
    -
    .sf-is-busy
    -
    sf-is-busy
    -
    -
    -
    .sf-is-collapsed
    -
    sf-is-collapsed
    -
    -
    -
    .sf-is-current
    -
    sf-is-current
    -
    -
    -
    .sf-is-danger
    -
    sf-is-danger
    -
    -
    -
    .sf-is-disabled
    -
    sf-is-disabled
    -
    -
    -
    .sf-is-draggable
    -
    sf-is-draggable
    -
    -
    -
    .sf-is-dragging
    -
    sf-is-dragging
    -
    -
    -
    .sf-is-drop-target
    -
    sf-is-drop-target
    -
    -
    -
    .sf-is-empty
    -
    sf-is-empty
    -
    -
    -
    .sf-is-error
    -
    sf-is-error
    -
    -
    -
    .sf-is-expanded
    -
    sf-is-expanded
    -
    -
    -
    .sf-is-hidden
    -
    -
    -
    -
    .sf-is-highlighted
    -
    sf-is-highlighted
    -
    -
    -
    .sf-is-info
    -
    sf-is-info
    -
    -
    -
    .sf-is-invalid
    -
    sf-is-invalid
    -
    -
    -
    .sf-is-invisible
    -
    sf-is-invisible
    -
    -
    -
    .sf-is-loading
    -
    sf-is-loading
    -
    -
    -
    .sf-is-open
    -
    sf-is-open
    -
    -
    -
    .sf-is-pending
    -
    sf-is-pending
    -
    -
    -
    .sf-is-pressed
    -
    sf-is-pressed
    -
    -
    -
    .sf-is-readonly
    -
    sf-is-readonly
    -
    -
    -
    .sf-is-selected
    -
    sf-is-selected
    -
    -
    -
    .sf-is-skeleton
    -
    sf-is-skeleton
    -
    -
    -
    .sf-is-success
    -
    sf-is-success
    -
    -
    -
    .sf-is-valid
    -
    sf-is-valid
    -
    -
    -
    .sf-is-visible
    -
    sf-is-visible
    -
    -
    -
    .sf-is-warning
    -
    sf-is-warning
    -
    -
    -
    -
    -

    Motion / animation 22

    -
    -
    -
    .sf-color-pulse
    -
    color-pulse
    -
    -
    -
    .sf-entrance--fade
    -
    entrance--fade
    -
    -
    -
    .sf-entrance--fade-down
    -
    entrance--fade-down
    -
    -
    -
    .sf-entrance--fade-left
    -
    entrance--fade-left
    -
    -
    -
    .sf-entrance--fade-right
    -
    entrance--fade-right
    -
    -
    -
    .sf-entrance--fade-up
    -
    entrance--fade-up
    -
    -
    -
    .sf-entrance--scale-up
    -
    entrance--scale-up
    -
    -
    -
    .sf-exit--fade
    -
    exit--fade
    -
    -
    -
    .sf-exit--fade-down
    -
    exit--fade-down
    -
    -
    -
    .sf-exit--fade-left
    -
    exit--fade-left
    -
    -
    -
    .sf-exit--fade-right
    -
    exit--fade-right
    -
    -
    -
    .sf-exit--fade-up
    -
    exit--fade-up
    -
    -
    -
    .sf-exit--scale-down
    -
    exit--scale-down
    -
    -
    -
    .sf-fade-in
    -
    fade-in
    -
    -
    -
    .sf-fade-out
    -
    fade-out
    -
    -
    -
    .sf-scale-down
    -
    scale-down
    -
    -
    -
    .sf-scale-up
    -
    scale-up
    -
    -
    -
    .sf-slide-in-down
    -
    slide-in-down
    -
    -
    -
    .sf-slide-in-left
    -
    slide-in-left
    -
    -
    -
    .sf-slide-in-right
    -
    slide-in-right
    -
    -
    -
    .sf-slide-in-up
    -
    slide-in-up
    -
    -
    -
    .sf-stagger
    -
    1
    2
    3
    -
    -
    -
    -
    -

    Accessibility 8

    -
    -
    -
    .no-motion
    -
    animation suppressed
    -
    -
    -
    .sf-clickable-parent
    -
    card
    -
    -
    -
    .sf-clickable-parent__overlay
    -
    card (overlay link)
    -
    -
    -
    .sf-focus-parent
    -
    -
    -
    -
    .sf-focus-shadow
    -
    -
    -
    -
    .skip-link
    - -
    -
    -
    .sr-only
    - -
    -
    -
    .sr-only-focusable
    - -
    -
    -
    -
    -

    Print 4

    -
    -
    -
    .no-print
    -
    no-print — affects print preview (Ctrl/Cmd-P)
    -
    -
    -
    .print-color-exact
    -
    -
    -
    -
    .print-no-color
    -
    -
    -
    -
    .print-only
    -
    -
    -
    -
    -
    -

    Theme 3

    -
    -
    -
    .sf-theme-dark
    -
    sf-theme-dark
    -
    -
    -
    .sf-theme-light
    -
    sf-theme-light
    -
    -
    -
    .sf-theme-transition
    -
    sf-theme-transition
    -
    -
    -
    - -
    -

    Part 2 — Complete token reference 754 tokens · live values

    -
    Every --sf-* token — knob and consumption, all tiers — with its live computed value (filled by JS). Toggle the theme or the override in the toolbar and watch every value recompute. Tokens that resolve to a colour, length, shadow, gradient, type or motion value also show a visual.
    -

    color 255

    -
    --sf-color-action
    --sf-color-action--active
    --sf-color-action--hover
    --sf-color-action-100
    --sf-color-action-200
    --sf-color-action-300
    --sf-color-action-400
    --sf-color-action-50
    --sf-color-action-500
    --sf-color-action-600
    --sf-color-action-700
    --sf-color-action-800
    --sf-color-action-900
    --sf-color-action-950
    --sf-color-action-a10
    --sf-color-action-a30
    --sf-color-action-a5
    --sf-color-action-a50
    --sf-color-action-a80
    --sf-color-action-darker
    --sf-color-action-lighter
    --sf-color-action-muted
    --sf-color-action-source-dark
    --sf-color-action-source-light
    --sf-color-action-subtle
    --sf-color-action-superdark
    --sf-color-action-superlight
    --sf-color-action-tint
    --sf-color-action-xdark
    --sf-color-action-xlight
    --sf-color-base
    --sf-color-base--active
    --sf-color-base--hover
    --sf-color-base-100
    --sf-color-base-200
    --sf-color-base-300
    --sf-color-base-400
    --sf-color-base-50
    --sf-color-base-500
    --sf-color-base-600
    --sf-color-base-700
    --sf-color-base-800
    --sf-color-base-900
    --sf-color-base-950
    --sf-color-base-a10
    --sf-color-base-a30
    --sf-color-base-a5
    --sf-color-base-a50
    --sf-color-base-a80
    --sf-color-base-muted
    --sf-color-base-source-dark
    --sf-color-base-source-light
    --sf-color-base-subtle
    --sf-color-base-tint
    --sf-color-bg
    --sf-color-bg--active
    --sf-color-bg--disabled
    --sf-color-bg--focus
    --sf-color-bg--hover
    --sf-color-bg--selected
    --sf-color-black
    --sf-color-border
    --sf-color-border--disabled
    --sf-color-border--focus
    --sf-color-border--strong
    --sf-color-border--subtle
    --sf-color-border--translucent
    --sf-color-code-bg
    --sf-color-code-text
    --sf-color-danger
    --sf-color-danger-muted
    --sf-color-danger-source-dark
    --sf-color-danger-source-light
    --sf-color-danger-strong
    --sf-color-danger-subtle
    --sf-color-danger-tint
    --sf-color-dim
    --sf-color-heading
    --sf-color-info
    --sf-color-info-muted
    --sf-color-info-source-dark
    --sf-color-info-source-light
    --sf-color-info-strong
    --sf-color-info-subtle
    --sf-color-info-tint
    --sf-color-inset
    --sf-color-inverse
    --sf-color-link
    --sf-color-link--active
    --sf-color-link--disabled
    --sf-color-link--hover
    --sf-color-link--underline
    --sf-color-link--visited
    --sf-color-mark-bg
    --sf-color-mark-text
    --sf-color-neutral
    --sf-color-neutral--active
    --sf-color-neutral--hover
    --sf-color-neutral-100
    --sf-color-neutral-200
    --sf-color-neutral-300
    --sf-color-neutral-400
    --sf-color-neutral-50
    --sf-color-neutral-500
    --sf-color-neutral-600
    --sf-color-neutral-700
    --sf-color-neutral-800
    --sf-color-neutral-900
    --sf-color-neutral-950
    --sf-color-neutral-a10
    --sf-color-neutral-a30
    --sf-color-neutral-a5
    --sf-color-neutral-a50
    --sf-color-neutral-a80
    --sf-color-neutral-darker
    --sf-color-neutral-lighter
    --sf-color-neutral-muted
    --sf-color-neutral-source-dark
    --sf-color-neutral-source-light
    --sf-color-neutral-subtle
    --sf-color-neutral-superdark
    --sf-color-neutral-superlight
    --sf-color-neutral-tint
    --sf-color-neutral-xdark
    --sf-color-neutral-xlight
    --sf-color-overlay
    --sf-color-primary
    --sf-color-primary--active
    --sf-color-primary--hover
    --sf-color-primary-100
    --sf-color-primary-200
    --sf-color-primary-300
    --sf-color-primary-400
    --sf-color-primary-50
    --sf-color-primary-500
    --sf-color-primary-600
    --sf-color-primary-700
    --sf-color-primary-800
    --sf-color-primary-900
    --sf-color-primary-950
    --sf-color-primary-a10
    --sf-color-primary-a30
    --sf-color-primary-a5
    --sf-color-primary-a50
    --sf-color-primary-a80
    --sf-color-primary-darker
    --sf-color-primary-lighter
    --sf-color-primary-muted
    --sf-color-primary-source-dark
    --sf-color-primary-source-light
    --sf-color-primary-subtle
    --sf-color-primary-superdark
    --sf-color-primary-superlight
    --sf-color-primary-tint
    --sf-color-primary-xdark
    --sf-color-primary-xlight
    --sf-color-raised
    --sf-color-scheme
    --sf-color-secondary
    --sf-color-secondary--active
    --sf-color-secondary--hover
    --sf-color-secondary-100
    --sf-color-secondary-200
    --sf-color-secondary-300
    --sf-color-secondary-400
    --sf-color-secondary-50
    --sf-color-secondary-500
    --sf-color-secondary-600
    --sf-color-secondary-700
    --sf-color-secondary-800
    --sf-color-secondary-900
    --sf-color-secondary-950
    --sf-color-secondary-a10
    --sf-color-secondary-a30
    --sf-color-secondary-a5
    --sf-color-secondary-a50
    --sf-color-secondary-a80
    --sf-color-secondary-darker
    --sf-color-secondary-lighter
    --sf-color-secondary-muted
    --sf-color-secondary-source-dark
    --sf-color-secondary-source-light
    --sf-color-secondary-subtle
    --sf-color-secondary-superdark
    --sf-color-secondary-superlight
    --sf-color-secondary-tint
    --sf-color-secondary-xdark
    --sf-color-secondary-xlight
    --sf-color-selection-bg
    --sf-color-selection-bg--alt
    --sf-color-selection-text
    --sf-color-selection-text--alt
    --sf-color-success
    --sf-color-success-muted
    --sf-color-success-source-dark
    --sf-color-success-source-light
    --sf-color-success-strong
    --sf-color-success-subtle
    --sf-color-success-tint
    --sf-color-surface
    --sf-color-tertiary
    --sf-color-tertiary--active
    --sf-color-tertiary--hover
    --sf-color-tertiary-100
    --sf-color-tertiary-200
    --sf-color-tertiary-300
    --sf-color-tertiary-400
    --sf-color-tertiary-50
    --sf-color-tertiary-500
    --sf-color-tertiary-600
    --sf-color-tertiary-700
    --sf-color-tertiary-800
    --sf-color-tertiary-900
    --sf-color-tertiary-950
    --sf-color-tertiary-a10
    --sf-color-tertiary-a30
    --sf-color-tertiary-a5
    --sf-color-tertiary-a50
    --sf-color-tertiary-a80
    --sf-color-tertiary-darker
    --sf-color-tertiary-lighter
    --sf-color-tertiary-muted
    --sf-color-tertiary-source-dark
    --sf-color-tertiary-source-light
    --sf-color-tertiary-subtle
    --sf-color-tertiary-superdark
    --sf-color-tertiary-superlight
    --sf-color-tertiary-tint
    --sf-color-tertiary-xdark
    --sf-color-tertiary-xlight
    --sf-color-text
    --sf-color-text--disabled
    --sf-color-text--inverse
    --sf-color-text--muted
    --sf-color-text--on-action
    --sf-color-text--on-base
    --sf-color-text--on-danger
    --sf-color-text--on-info
    --sf-color-text--on-inverse
    --sf-color-text--on-neutral
    --sf-color-text--on-primary
    --sf-color-text--on-secondary
    --sf-color-text--on-success
    --sf-color-text--on-tertiary
    --sf-color-text--on-warning
    --sf-color-text--placeholder
    --sf-color-text--secondary
    --sf-color-warning
    --sf-color-warning-muted
    --sf-color-warning-source-dark
    --sf-color-warning-source-light
    --sf-color-warning-strong
    --sf-color-warning-subtle
    --sf-color-warning-tint
    --sf-color-white
    -

    gradient 10

    -
    --sf-gradient-action
    --sf-gradient-brand
    --sf-gradient-fade--b
    --sf-gradient-fade--l
    --sf-gradient-fade--r
    --sf-gradient-fade--t
    --sf-gradient-primary
    --sf-gradient-secondary
    --sf-gradient-surface
    --sf-gradient-tertiary
    -

    shadow 13

    -
    --sf-shadow-2xl
    --sf-shadow-color adv
    --sf-shadow-glow
    --sf-shadow-glow-color adv
    --sf-shadow-inner
    --sf-shadow-l
    --sf-shadow-lightness
    --sf-shadow-m
    --sf-shadow-none
    --sf-shadow-s
    --sf-shadow-strength adv
    --sf-shadow-xl
    --sf-shadow-xs
    -

    drop 5

    -
    --sf-drop-shadow-l
    --sf-drop-shadow-m
    --sf-drop-shadow-s
    --sf-drop-shadow-xl
    --sf-drop-shadow-xs
    -

    radius 14

    -
    --sf-radius-2xl
    --sf-radius-2xs
    --sf-radius-3xl
    --sf-radius-4xl
    --sf-radius-full
    --sf-radius-l
    --sf-radius-m
    --sf-radius-none
    --sf-radius-outer adv
    --sf-radius-pill
    --sf-radius-s
    --sf-radius-scale adv
    --sf-radius-xl
    --sf-radius-xs
    -

    space 16

    -
    --sf-space-2xl
    --sf-space-2xs
    --sf-space-3xl
    --sf-space-4xl
    --sf-space-base-max adv
    --sf-space-base-min adv
    --sf-space-l
    --sf-space-m
    --sf-space-none
    --sf-space-px
    --sf-space-ratio-max adv
    --sf-space-ratio-min adv
    --sf-space-s
    --sf-space-scale adv
    --sf-space-xl
    --sf-space-xs
    -

    size 5

    -
    --sf-size-l
    --sf-size-m
    --sf-size-s
    --sf-size-xl
    --sf-size-xs
    -

    text 62

    -
    --sf-text-2xl
    Aa
    --sf-text-2xl-font-weight
    Aa
    --sf-text-2xl-letter-spacing
    Aa
    --sf-text-2xl-line-height
    Aa
    --sf-text-2xl-max-width
    --sf-text-2xs
    Aa
    --sf-text-2xs-font-weight
    Aa
    --sf-text-2xs-letter-spacing
    Aa
    --sf-text-2xs-line-height
    Aa
    --sf-text-2xs-max-width
    --sf-text-3xl
    Aa
    --sf-text-3xl-font-weight
    Aa
    --sf-text-3xl-letter-spacing
    Aa
    --sf-text-3xl-line-height
    Aa
    --sf-text-3xl-max-width
    --sf-text-4xl
    Aa
    --sf-text-4xl-font-weight
    Aa
    --sf-text-4xl-letter-spacing
    Aa
    --sf-text-4xl-line-height
    Aa
    --sf-text-4xl-max-width
    --sf-text-base-max adv
    --sf-text-base-min adv
    --sf-text-display-base-max adv
    --sf-text-display-base-min adv
    --sf-text-display-l
    Aa
    --sf-text-display-m
    Aa
    --sf-text-display-s
    Aa
    --sf-text-display-scale adv
    --sf-text-l
    Aa
    --sf-text-l-font-weight
    Aa
    --sf-text-l-letter-spacing
    Aa
    --sf-text-l-line-height
    Aa
    --sf-text-l-max-width
    --sf-text-m
    Aa
    --sf-text-m-font-weight
    Aa
    --sf-text-m-letter-spacing
    Aa
    --sf-text-m-line-height
    Aa
    --sf-text-m-max-width
    --sf-text-ratio-max adv
    --sf-text-ratio-min adv
    --sf-text-s
    Aa
    --sf-text-s-font-weight
    Aa
    --sf-text-s-letter-spacing
    Aa
    --sf-text-s-line-height
    Aa
    --sf-text-s-max-width
    --sf-text-scale adv
    --sf-text-shadow-l
    Aa
    --sf-text-shadow-m
    Aa
    --sf-text-shadow-none
    Aa
    --sf-text-shadow-s
    Aa
    --sf-text-shadow-xl
    Aa
    --sf-text-shadow-xs
    Aa
    --sf-text-xl
    Aa
    --sf-text-xl-font-weight
    Aa
    --sf-text-xl-letter-spacing
    Aa
    --sf-text-xl-line-height
    Aa
    --sf-text-xl-max-width
    --sf-text-xs
    Aa
    --sf-text-xs-font-weight
    Aa
    --sf-text-xs-letter-spacing
    Aa
    --sf-text-xs-line-height
    Aa
    --sf-text-xs-max-width
    -

    font 20

    -
    --sf-font-body
    Ag f
    --sf-font-display
    --sf-font-features adv
    --sf-font-geometric
    Ag f
    --sf-font-heading
    --sf-font-humanist
    Ag f
    --sf-font-mono
    Ag f
    --sf-font-numeric
    --sf-font-slab
    Ag f
    --sf-font-variation adv
    --sf-font-weight-body
    Ag
    --sf-font-weight-bold
    Ag
    --sf-font-weight-display
    Ag
    --sf-font-weight-heading
    Ag
    --sf-font-weight-interactive
    Ag
    --sf-font-weight-light
    Ag
    --sf-font-weight-medium
    Ag
    --sf-font-weight-normal
    Ag
    --sf-font-weight-semibold
    Ag
    --sf-font-weight-strong
    Ag
    -

    leading 5

    -
    --sf-leading-normal

    Aa Bb
    Cc Dd

    --sf-leading-relaxed

    Aa Bb
    Cc Dd

    --sf-leading-snug

    Aa Bb
    Cc Dd

    --sf-leading-taper adv

    Aa Bb
    Cc Dd

    --sf-leading-tight

    Aa Bb
    Cc Dd

    -

    tracking 5

    -
    --sf-tracking-normal
    AVTAW
    --sf-tracking-tight
    AVTAW
    --sf-tracking-wide
    AVTAW
    --sf-tracking-wider
    AVTAW
    --sf-tracking-widest
    AVTAW
    -

    duration 6

    -
    --sf-duration-fast
    --sf-duration-instant
    --sf-duration-none
    --sf-duration-normal
    --sf-duration-slow
    --sf-duration-slower
    -

    ease 8

    -
    --sf-ease-bounce
    --sf-ease-elastic
    --sf-ease-in
    --sf-ease-in-out
    --sf-ease-linear
    --sf-ease-out
    --sf-ease-overshoot
    --sf-ease-spring
    -

    transition 10

    -
    --sf-transition-colors
    --sf-transition-enter
    --sf-transition-exit
    --sf-transition-fast
    --sf-transition-form-field
    --sf-transition-opacity
    --sf-transition-overlay
    --sf-transition-shadow
    --sf-transition-slow
    --sf-transition-transform
    -

    animation 18

    -
    --sf-animation-blink
    --sf-animation-color-pulse
    --sf-animation-fade-in
    --sf-animation-fade-out
    --sf-animation-float
    --sf-animation-ping
    --sf-animation-scale-down
    --sf-animation-scale-up
    --sf-animation-shimmer
    --sf-animation-slide-in-down
    --sf-animation-slide-in-left
    --sf-animation-slide-in-right
    --sf-animation-slide-in-up
    --sf-animation-slide-out-down
    --sf-animation-slide-out-left
    --sf-animation-slide-out-right
    --sf-animation-slide-out-up
    --sf-animation-spin
    -

    border 10

    -
    --sf-border
    --sf-border-scale
    --sf-border-strong
    --sf-border-style
    --sf-border-subtle
    --sf-border-width-1
    --sf-border-width-2
    --sf-border-width-3
    --sf-border-width-4
    --sf-border-width-hairline
    -

    focus 5

    -
    --sf-focus-ring-color
    --sf-focus-ring-offset
    --sf-focus-ring-shadow adv
    --sf-focus-ring-style
    --sf-focus-ring-width
    -

    opacity 2

    -
    --sf-opacity-disabled
    --sf-opacity-muted
    -

    blur 1

    -
    --sf-blur
    -

    z 10

    -
    --sf-z-base
    --sf-z-below
    --sf-z-dropdown
    --sf-z-fixed
    --sf-z-modal
    --sf-z-overlay
    --sf-z-raised
    --sf-z-sticky
    --sf-z-toast
    --sf-z-tooltip
    -

    alternate 2

    -
    --sf-alternate-gap
    --sf-alternate-inner-gap
    -

    aspect 1

    -
    --sf-aspect
    -

    bento 5

    -
    --sf-bento-cols-default
    --sf-bento-gap
    --sf-bento-row-compact
    --sf-bento-row-default
    --sf-bento-row-tall
    -

    bg 5

    -
    --sf-bg-layer-fit
    --sf-bg-layer-inset
    --sf-bg-layer-position
    --sf-bg-layer-radius
    --sf-bg-layer-z
    -

    body 8

    -
    --sf-body-color
    --sf-body-em-style
    --sf-body-font-family
    --sf-body-font-size
    --sf-body-font-weight
    --sf-body-line-height
    --sf-body-strong-weight
    --sf-body-text-wrap
    -

    box 3

    -
    --sf-box-border-color
    --sf-box-border-width
    --sf-box-padding
    -

    breakout 1

    -
    --sf-breakout-width
    -

    btn 29

    -
    --sf-btn-border-width
    --sf-btn-font-scale
    --sf-btn-font-size adv
    --sf-btn-font-weight
    --sf-btn-gap
    --sf-btn-l-font-size
    --sf-btn-l-min-height
    --sf-btn-l-padding-block
    --sf-btn-l-padding-inline
    --sf-btn-m-font-size
    --sf-btn-m-min-height
    --sf-btn-m-padding-block
    --sf-btn-m-padding-inline
    --sf-btn-min-height adv
    --sf-btn-padding-block adv
    --sf-btn-padding-inline adv
    --sf-btn-radius
    --sf-btn-s-font-size
    --sf-btn-s-min-height
    --sf-btn-s-padding-block
    --sf-btn-s-padding-inline
    --sf-btn-xl-font-size
    --sf-btn-xl-min-height
    --sf-btn-xl-padding-block
    --sf-btn-xl-padding-inline
    --sf-btn-xs-font-size
    --sf-btn-xs-min-height
    --sf-btn-xs-padding-block
    --sf-btn-xs-padding-inline
    -

    card 14

    -
    --sf-card-avatar-size
    --sf-card-bg
    --sf-card-border-color
    --sf-card-border-width
    --sf-card-gap
    --sf-card-heading-size
    --sf-card-media-radius
    --sf-card-media-ratio
    --sf-card-padding
    --sf-card-radius
    --sf-card-radius-outer
    --sf-card-shadow
    --sf-card-shadow--elevated
    --sf-card-shadow--hover
    -

    caret 1

    -
    --sf-caret-color
    -

    center 2

    -
    --sf-center-gutter
    --sf-center-max
    -

    cluster 3

    -
    --sf-cluster-align
    --sf-cluster-gap
    --sf-cluster-justify
    -

    code 1

    -
    --sf-code-font-size
    -

    component 1

    -
    --sf-component-pad
    -

    container 5

    -
    --sf-container-default
    --sf-container-full
    --sf-container-narrow
    --sf-container-prose
    --sf-container-wide
    -

    content 3

    -
    --sf-content-gap
    --sf-content-intrinsic-size
    --sf-content-width
    -

    contrast 2

    -
    --sf-contrast-bias adv
    --sf-contrast-threshold adv
    -

    cover 2

    -
    --sf-cover-min-height
    --sf-cover-padding
    -

    current 1

    -
    --sf-current-font-weight
    -

    density 1

    -
    --sf-density adv
    -

    display 3

    -
    --sf-display-l-line-height
    --sf-display-m-line-height
    --sf-display-s-line-height
    -

    divider 4

    -
    --sf-divider-color
    --sf-divider-gap
    --sf-divider-style
    --sf-divider-width
    -

    equal 5

    -
    --sf-equal-gap
    --sf-equal-min-col
    --sf-equal-rule-color
    --sf-equal-rule-style
    --sf-equal-rule-width
    -

    field 5

    -
    --sf-field-block
    --sf-field-padding-block
    --sf-field-padding-inline
    --sf-field-radius
    --sf-field-required-marker
    -

    flow 1

    -
    --sf-flow-space
    -

    fluid 3

    -
    --sf-fluid-max-vw adv
    --sf-fluid-min-vw adv
    --sf-fluid-width
    -

    frame 1

    -
    --sf-frame-ratio
    -

    gap 1

    -
    --sf-gap
    -

    grid 8

    -
    --sf-grid-gap
    --sf-grid-min
    --sf-grid-min-2xl
    --sf-grid-min-l
    --sf-grid-min-m
    --sf-grid-min-s
    --sf-grid-min-xl
    --sf-grid-min-xs
    -

    gutter 1

    -
    --sf-gutter
    -

    h1 5

    -
    --sf-h1-font-weight
    --sf-h1-letter-spacing
    --sf-h1-line-height
    --sf-h1-max-width
    --sf-h1-size
    -

    h2 5

    -
    --sf-h2-font-weight
    --sf-h2-letter-spacing
    --sf-h2-line-height
    --sf-h2-max-width
    --sf-h2-size
    -

    h3 5

    -
    --sf-h3-font-weight
    --sf-h3-letter-spacing
    --sf-h3-line-height
    --sf-h3-max-width
    --sf-h3-size
    -

    h4 5

    -
    --sf-h4-font-weight
    --sf-h4-letter-spacing
    --sf-h4-line-height
    --sf-h4-max-width
    --sf-h4-size
    -

    h5 5

    -
    --sf-h5-font-weight
    --sf-h5-letter-spacing
    --sf-h5-line-height
    --sf-h5-max-width
    --sf-h5-size
    -

    h6 5

    -
    --sf-h6-font-weight
    --sf-h6-letter-spacing
    --sf-h6-line-height
    --sf-h6-max-width
    --sf-h6-size
    -

    header 3

    -
    --sf-header-height
    --sf-header-height-desktop
    --sf-header-height-mobile
    -

    heading 3

    -
    --sf-heading-color
    --sf-heading-font-family
    --sf-heading-text-wrap
    -

    hover 4

    -
    --sf-hover-grow-scale
    --sf-hover-lift
    --sf-hover-shrink-scale
    --sf-hover-slide
    -

    icon 10

    -
    --sf-icon-2xl
    --sf-icon-box-bg
    --sf-icon-box-border
    --sf-icon-box-pad
    --sf-icon-box-radius
    --sf-icon-l
    --sf-icon-m
    --sf-icon-s
    --sf-icon-xl
    --sf-icon-xs
    -

    imposter 1

    -
    --sf-imposter-margin
    -

    is 5

    -
    --sf-is-active adv
    --sf-is-current adv
    --sf-is-dark internal
    --sf-is-open adv
    --sf-is-pressed adv
    -

    line 1

    -
    --sf-line-clamp
    -

    link 4

    -
    --sf-link-external-label
    --sf-link-external-marker
    --sf-link-underline-offset
    --sf-link-underline-thickness
    -

    lumlocker 1

    -
    --sf-lumlocker adv
    -

    mask 2

    -
    --sf-mask-scrim-end adv
    --sf-mask-scrim-start adv
    -

    media 1

    -
    --sf-media-radius
    -

    motion 1

    -
    --sf-motion-scale adv
    -

    object 2

    -
    --sf-object-fit
    --sf-object-position
    -

    optical 1

    -
    --sf-optical-sizing adv
    -

    overlap 1

    -
    --sf-overlap-pull
    -

    palette 10

    -
    --sf-palette-mix-100 adv
    --sf-palette-mix-200 adv
    --sf-palette-mix-300 adv
    --sf-palette-mix-400 adv
    --sf-palette-mix-50 adv
    --sf-palette-mix-600 adv
    --sf-palette-mix-700 adv
    --sf-palette-mix-800 adv
    --sf-palette-mix-900 adv
    --sf-palette-mix-950 adv
    -

    print 3

    -
    --sf-print-base-size adv
    --sf-print-page-margin adv
    --sf-print-page-size adv
    -

    prose 14

    -
    --sf-prose-block-margin
    --sf-prose-blockquote-border
    --sf-prose-blockquote-padding
    --sf-prose-figcaption-size
    --sf-prose-figure-margin
    --sf-prose-heading-gap
    --sf-prose-hr-margin
    --sf-prose-list-gap
    --sf-prose-marker-color
    --sf-prose-media-margin
    --sf-prose-media-radius
    --sf-prose-nested-list-gap
    --sf-prose-paragraph
    --sf-prose-table-pad
    -

    ratio 7

    -
    --sf-ratio-3-2
    --sf-ratio-4-3
    --sf-ratio-cinema
    --sf-ratio-golden
    --sf-ratio-portrait
    --sf-ratio-square
    --sf-ratio-video
    -

    reel 3

    -
    --sf-reel-gap
    --sf-reel-height
    --sf-reel-item-width
    -

    safe 4

    -
    --sf-safe-bottom adv
    --sf-safe-left adv
    --sf-safe-right adv
    --sf-safe-top adv
    -

    scrim 4

    -
    --sf-scrim-color
    --sf-scrim-direction
    --sf-scrim-gradient
    --sf-scrim-text-shadow
    -

    scroll 5

    -
    --sf-scroll-shadow-size
    --sf-scroll-timeline-range-end adv
    --sf-scroll-timeline-range-exit-end
    --sf-scroll-timeline-range-exit-start
    --sf-scroll-timeline-range-start adv
    -

    scrollbar 2

    -
    --sf-scrollbar-thumb
    --sf-scrollbar-track
    -

    section 8

    -
    --sf-section-pad
    --sf-section-pad--2xl
    --sf-section-pad--l
    --sf-section-pad--m
    --sf-section-pad--s
    --sf-section-pad--xl
    --sf-section-pad--xs
    --sf-section-scale adv
    -

    sidebar 3

    -
    --sf-sidebar-gap
    --sf-sidebar-min-width
    --sf-sidebar-width
    -

    stack 1

    -
    --sf-stack-gap
    -

    stagger 1

    -
    --sf-stagger-step
    -

    state 1

    -
    --sf-state-pending-opacity
    -

    sticky 3

    -
    --sf-sticky-offset
    --sf-sticky-offset-desktop
    --sf-sticky-offset-mobile
    -

    surface 9

    -
    --sf-surface-bg-animation
    --sf-surface-bg-attachment
    --sf-surface-bg-color
    --sf-surface-bg-image
    --sf-surface-bg-overlay
    --sf-surface-bg-position
    --sf-surface-bg-repeat
    --sf-surface-bg-size
    --sf-surface-color
    -

    switcher 2

    -
    --sf-switcher-gap
    --sf-switcher-threshold
    -

    theme 1

    -
    --sf-theme-transition-duration
    -

    touch 1

    -
    --sf-touch-target
    -
    -
    - - - diff --git a/demos/generate.mjs b/demos/generate.mjs deleted file mode 100644 index f88500639..000000000 --- a/demos/generate.mjs +++ /dev/null @@ -1,774 +0,0 @@ -// Generates the full-API demo + ultimate override from docs/api-index.json. -// Run: node demos/generate.mjs -// Outputs (repo root): full-api-demo.html, full-api-demo-with-overrides.html, -// ultimate-override.css. Regenerate whenever the token/class set changes so -// coverage stays exact. - -import fs from 'node:fs'; -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; - -const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); -const OUT = path.join(ROOT, 'demos'); // generated artifacts live alongside this script -const api = JSON.parse(fs.readFileSync(path.join(ROOT, 'docs/api-index.json'), 'utf8')); -const CDN = 'https://cdn.jsdelivr.net/gh/codeslash-dev/SLASHED@dist/slashed.full.css'; -const VERSION = JSON.parse(fs.readFileSync(path.join(ROOT, 'package.json'), 'utf8')).version; - -const tokens = api.entries.filter((e) => e.type === 'token'); -const classes = api.entries.filter((e) => e.type === 'class'); -const knobs = tokens.filter((t) => t.role === 'knob'); - -const esc = (s) => String(s).replace(/&/g, '&').replace(//g, '>'); -const round = (n) => Math.round(n * 1000) / 1000; - -// ───────────────────────────────────────────────────────────────────────── -// OVERRIDE GENERATION -// Every knob is either: perturbed by a generic rule, perturbed by a curated -// value, or in SKIP with a documented reason. The build asserts this — a new -// knob that matches nothing fails the generator instead of silently dropping. -// ───────────────────────────────────────────────────────────────────────── - -// Structural / meta / sentinel knobs we deliberately do NOT perturb globally. -const SKIP = { - '--sf-color-scheme': 'meta control — forcing a scheme would override the page light/dark behaviour rather than test a visual token', - '--sf-bg-layer-z': 'stacking order — lowering it would push the background layer over content', - '--sf-z-below': 'stacking order — no single-element visual surface; global change risks hiding content', - '--sf-z-base': 'stacking order — no single-element visual surface', - '--sf-z-raised': 'stacking order — no single-element visual surface', - '--sf-z-sticky': 'stacking order — no single-element visual surface', - '--sf-z-dropdown': 'stacking order — no single-element visual surface', - '--sf-z-overlay': 'stacking order — no single-element visual surface', - '--sf-z-fixed': 'stacking order — no single-element visual surface', - '--sf-z-modal': 'stacking order — no single-element visual surface', - '--sf-z-toast': 'stacking order — no single-element visual surface', - '--sf-z-tooltip': 'stacking order — no single-element visual surface', - '--sf-safe-top': 'env() device inset — zero on desktop, no visual surface', - '--sf-safe-right': 'env() device inset — zero on desktop, no visual surface', - '--sf-safe-bottom': 'env() device inset — zero on desktop, no visual surface', - '--sf-safe-left': 'env() device inset — zero on desktop, no visual surface', - '--sf-is-active': 'runtime state flag — exercised via the .sf-is-active class; a global :root flip would force every element active', - '--sf-is-current': 'runtime state flag — exercised via the .sf-is-current class', - '--sf-is-open': 'runtime state flag — exercised via the .sf-is-open class', - '--sf-is-pressed': 'runtime state flag — exercised via the .sf-is-pressed class', - '--sf-is-dark': 'runtime theme flag — driven by color-scheme; a global flip would desync from the actual scheme', - '--sf-shadow-none': 'sentinel "none" — the API guarantees no shadow; overriding would add one where none is promised', - '--sf-text-shadow-none': 'sentinel "none" — the API guarantees no text-shadow', - '--sf-surface-bg-animation': 'background animation shorthand on .sf-surface — a global value would force motion on every surface and fight reduced-motion; no safe single-element visual perturbation', - '--sf-btn-font-size': 'flatten-all label size — reads FIRST in the font-size cascade, so setting it would shadow the per-size --sf-btn-{size}-font-size knobs (and mask the --sf-btn-font-scale multiplier) this demo exercises; the per-size ladder is the recommended surface', - '--sf-btn-padding-block': 'flatten-all block padding — reads FIRST in the cascade, shadowing the per-size --sf-btn-{size}-padding-block knobs this demo exercises', - '--sf-btn-padding-inline': 'flatten-all inline padding — reads FIRST in the cascade, shadowing the per-size --sf-btn-{size}-padding-inline knobs this demo exercises', - '--sf-btn-min-height': 'flatten-all min-height — reads FIRST in the cascade, shadowing the per-size --sf-btn-{size}-min-height knobs this demo exercises', -}; - -// Curated overrides for keyword / numeric / zero-valued knobs that no generic -// numeric rule can safely transform. Each is a valid, visibly-distinct value. -const CURATED = { - // Button per-size knobs declared `initial` (opt-in hooks with no baked value — - // their default lives on the rule-local --sf-btn-*--size tier). Give explicit - // per-rung lengths so the demo exercises each rung; `initial` carries no type - // to infer. The flatten-all --sf-btn-{font-size,padding-block,padding-inline, - // min-height} are intentionally in SKIP above so they don't shadow these. - // The unitless --sf-btn-font-scale multiplier then scales the whole ladder. - '--sf-btn-font-scale': '1.6', - '--sf-btn-xs-font-size': '0.9rem', - '--sf-btn-s-font-size': '1.1rem', - '--sf-btn-m-font-size': '1.4rem', - '--sf-btn-l-font-size': '1.8rem', - '--sf-btn-xl-font-size': '2.2rem', - '--sf-btn-xs-padding-block': '0.2rem', - '--sf-btn-s-padding-block': '0.35rem', - '--sf-btn-m-padding-block': '0.5rem', - '--sf-btn-l-padding-block': '0.7rem', - '--sf-btn-xl-padding-block': '0.9rem', - '--sf-btn-xs-padding-inline': '0.6rem', - '--sf-btn-s-padding-inline': '0.9rem', - '--sf-btn-m-padding-inline': '1.2rem', - '--sf-btn-l-padding-inline': '1.6rem', - '--sf-btn-xl-padding-inline': '2rem', - '--sf-btn-xs-min-height': '1.8rem', - '--sf-btn-s-min-height': '2.1rem', - '--sf-btn-m-min-height': '2.5rem', - '--sf-btn-l-min-height': '3rem', - '--sf-btn-xl-min-height': '3.5rem', - // zero-valued lengths → small but visible - '--sf-bg-layer-inset': '0.75rem', - '--sf-bg-layer-radius': '0.75rem', - '--sf-media-radius': '0.75rem', - '--sf-box-border-width': '3px', - '--sf-equal-rule-width': '2px', - '--sf-radius-none': '0.4rem', - '--sf-space-none': '0.25rem', - '--sf-space-px': '2px', - '--sf-duration-none': '160ms', - // keyword swaps - '--sf-bg-layer-fit': 'contain', - '--sf-object-fit': 'contain', - '--sf-bg-layer-position': '25% 75%', - '--sf-object-position': '25% 75%', - // .sf-surface background knobs → real background-* properties on .sf-surface - '--sf-surface-bg-color': 'oklch(0.85 0.05 300)', - '--sf-surface-bg-image': 'linear-gradient(135deg, oklch(0.9 0.08 300 / 0.6), oklch(0.8 0.12 200 / 0.6))', - '--sf-surface-bg-overlay': 'linear-gradient(oklch(0 0 0 / 0.15), oklch(0 0 0 / 0.15))', - '--sf-surface-bg-size': 'contain', - '--sf-surface-bg-position': '25% 75%', - '--sf-surface-bg-repeat': 'repeat', - '--sf-surface-bg-attachment': 'fixed', - '--sf-border-style': 'dashed', - '--sf-divider-style': 'dashed', - '--sf-equal-rule-style': 'dashed', - '--sf-focus-ring-style': 'dashed', - '--sf-body-em-style': 'oblique', - '--sf-body-text-wrap': 'balance', - '--sf-heading-text-wrap': 'pretty', - '--sf-cluster-align': 'stretch', - '--sf-cluster-justify': 'center', - '--sf-scrim-direction': 'to right', - '--sf-scrim-text-shadow': '0 2px 6px oklch(0 0 0 / 0.85)', - '--sf-reel-height': '14rem', - '--sf-reel-item-width': 'min-content', - '--sf-scrollbar-track': 'oklch(0.85 0.05 300)', - '--sf-optical-sizing': 'none', - '--sf-font-features': '"liga" 1, "calt" 1', - '--sf-font-variation': '"wght" 650', - '--sf-font-numeric': 'oldstyle-nums', - '--sf-link-underline-thickness': '3px', - '--sf-link-external-marker': '" \\2192"', - '--sf-link-external-label': '"leaves this site"', - '--sf-field-required-marker': '" \\2737"', - '--sf-color-mark-text': 'oklch(0.45 0.27 320)', - '--sf-color-selection-text': 'oklch(0.98 0 0)', - '--sf-color-selection-text--alt': 'oklch(0.9 0.06 300)', - '--sf-print-page-size': 'letter', - '--sf-shadow-strength': '0.45', - '--sf-scroll-timeline-range-start': 'entry 20%', - '--sf-scroll-timeline-range-end': 'cover 60%', - '--sf-scroll-timeline-range-exit-start': 'exit 20%', - '--sf-scroll-timeline-range-exit-end': 'exit 80%', - // 'none' max-widths → a concrete cap so the constraint is visible - '--sf-h1-max-width': '40ch', - '--sf-h2-max-width': '40ch', - '--sf-h3-max-width': '40ch', - '--sf-h4-max-width': '40ch', - '--sf-h5-max-width': '40ch', - '--sf-h6-max-width': '40ch', - '--sf-text-l-max-width': '50ch', - '--sf-text-xl-max-width': '50ch', - '--sf-text-2xl-max-width': '50ch', - '--sf-text-3xl-max-width': '50ch', - '--sf-text-4xl-max-width': '50ch', - // unitless numbers - '--sf-bento-cols-default': '3', - '--sf-line-clamp': '2', - '--sf-leading-tight': '1.25', - '--sf-leading-snug': '1.5', - '--sf-leading-normal': '1.8', - '--sf-leading-relaxed': '2', - '--sf-leading-taper': '0.4', - '--sf-display-l-line-height': '1.2', - '--sf-display-m-line-height': '1.25', - '--sf-fluid-min-vw': '30', - '--sf-fluid-max-vw': '70', - '--sf-space-base-min': '1.4', - '--sf-space-base-max': '3', - '--sf-space-ratio-min': '1.4', - '--sf-space-ratio-max': '1.6', - '--sf-text-base-min': '1.15', - '--sf-text-base-max': '1.5', - '--sf-text-ratio-min': '1.35', - '--sf-text-ratio-max': '1.5', - '--sf-text-display-base-min': '2.8', - '--sf-text-display-base-max': '3.8', - '--sf-tracking-normal': '0.03em', - '--sf-font-weight-light': '200', - '--sf-font-weight-normal': '600', - '--sf-font-weight-medium': '700', - '--sf-font-weight-semibold': '800', - '--sf-font-weight-bold': '900', - '--sf-contrast-threshold': '0.45', - '--sf-contrast-bias': '0.12', - '--sf-opacity-disabled': '0.7', - '--sf-opacity-muted': '0.75', - '--sf-lumlocker': '0.5', - '--sf-shadow-lightness': '0.4', - '--sf-state-pending-opacity': '0.4', - // hover-transform magnitudes (unitless scale factors) + stagger step (time) - '--sf-hover-grow-scale': '1.4', - '--sf-hover-shrink-scale': '0.6', - '--sf-stagger-step': '200ms', - // scale knobs → amplify everything downstream - '--sf-border-scale': '1.6', - '--sf-radius-scale': '1.6', - '--sf-section-scale': '1.6', - '--sf-space-scale': '1.6', - '--sf-text-scale': '1.6', - '--sf-text-display-scale': '1.6', - '--sf-motion-scale': '1.6', - '--sf-density': '1.6', -}; - -const LEN_UNIT = /^(-?[\d.]+)(px|rem|em|ch|vw|vh|dvh|svh|lvh|vmin|vmax|pt|cm|mm|ex|cap|lh|q)$/i; - -function overrideValue(t) { - const v = t.value.trim(); - // colors (registered or a literal color function) — relative-color - // hue-shift keeps the value valid for any input and preserves alpha. - if (t.syntax === '' || /^(oklch|oklab|rgb|rgba|hsl|hwb|lab|lch|color)\(/i.test(v) || /^#[0-9a-f]{3,8}$/i.test(v)) { - return `oklch(from ${v} calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha)`; - } - if (CURATED[t.name] !== undefined) return CURATED[t.name]; - if (t.namespace === 'ease') return 'cubic-bezier(0.68, -0.55, 0.27, 1.55)'; - if (t.namespace === 'font' && /["a-z]/i.test(v) && /,/.test(v) && !/^[\d.]/.test(v)) { - return t.name.includes('mono') ? '"Courier New", ui-monospace, monospace' : '"Georgia", "Times New Roman", serif'; - } - if (/^\s*[\d.]+\s*\/\s*[\d.]+\s*$/.test(v) || (t.namespace === 'ratio' && v === '1')) return '3 / 1'; - if (/^[\d.]+%$/.test(v)) return `${round(Math.min(parseFloat(v) * 0.7, 100))}%`; - const m = v.match(LEN_UNIT); - if (m && parseFloat(m[1]) !== 0) return `${round(parseFloat(m[1]) * 1.6)}${m[2]}`; - return null; // unhandled → completeness assertion fails -} - -function buildOverride() { - const handled = []; - const unhandled = []; - for (const t of knobs) { - if (SKIP[t.name]) continue; - const nv = overrideValue(t); - if (nv === null) unhandled.push(t.name); - else handled.push([t, nv]); - } - if (unhandled.length) { - throw new Error(`Override generator: ${unhandled.length} knob(s) unhandled:\n ${unhandled.join('\n ')}`); - } - - // group by namespace for readability - const byNs = {}; - for (const [t, nv] of handled) (byNs[t.namespace] ||= []).push([t, nv]); - - let css = `/* ============================================================================ - ULTIMATE OVERRIDE — generated by demos/generate.mjs (do not edit by hand) - SLASHED v${VERSION} - - Perturbs every CONFIGURABLE (role: "knob") token to a valid, visibly-distinct - value so full-api-demo.html can prove each one is wired end to end. - - Coverage: ${handled.length} of ${knobs.length} knob tokens overridden. - ${Object.keys(SKIP).length} knobs are intentionally NOT perturbed (structural / - meta / sentinel) — listed with reasons at the bottom of this file. - ============================================================================ */ - -:root { -`; - for (const ns of Object.keys(byNs).sort()) { - css += `\n /* ${ns} */\n`; - for (const [t, nv] of byNs[ns].sort((a, b) => a[0].name.localeCompare(b[0].name))) { - css += ` ${t.name}: ${nv}; /* was: ${t.value} */\n`; - } - } - css += `}\n\n/* ---------------------------------------------------------------------------- - Intentionally NOT overridden (${Object.keys(SKIP).length}): -`; - for (const name of Object.keys(SKIP).sort()) css += ` ${name} — ${SKIP[name]}\n`; - css += ` ---------------------------------------------------------------------------- */\n`; - return { css, handledCount: handled.length }; -} - -// ───────────────────────────────────────────────────────────────────────── -// DEMO GENERATION — one rendered example per class (all of them). -// ───────────────────────────────────────────────────────────────────────── - -const boxes = (k, label = '') => Array.from({ length: k }, (_, i) => `
    ${label || i + 1}
    `).join(''); -const ipsum = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.'; - -const PARENT_OF = { - 'sf-cover__center': 'sf-cover', - 'sf-scrim__content': 'sf-scrim', - 'sf-clickable-parent__overlay': 'sf-clickable-parent', -}; - -function layoutExample(n, applied) { - if (n === 'sf-cover__center') return `
    center
    `; - if (n === 'sf-cover' || PARENT_OF[n] === undefined && /^sf-cover--/.test(n)) return `
    cover
    `; - if (n === 'sf-frame' || /^sf-frame--/.test(n)) return `
    media
    `; - if (n === 'sf-bento' || /^sf-bento--/.test(n)) return `
    ${boxes(6)}
    `; - if (/^sf-bento-(featured|full|tall|wide)/.test(n)) return `
    ${n.replace('sf-bento-', '')}
    ${boxes(5)}
    `; - if (n === 'sf-reel' || /^sf-reel--/.test(n)) return `
    ${Array.from({ length: 6 }, (_, i) => `
    ${i + 1}
    `).join('')}
    `; - if (n === 'sf-content-grid') return `

    content

    breakout
    full-bleed
    `; - if (n === 'sf-breakout' || n === 'sf-full-bleed') return `

    content

    ${n.replace('sf-', '')}
    `; - if (n === 'sf-subgrid' || n === 'sf-subgrid-rows') return `
    ${boxes(3)}
    `; - if (n === 'sf-sidebar' || /^sf-sidebar--/.test(n)) return `
    main
    aside
    `; - if (n === 'sf-switcher' || /^sf-switcher--/.test(n)) return `
    ${boxes(3)}
    `; - if (n === 'sf-imposter' || /^sf-imposter--/.test(n)) return `
    base
    imposter
    `; - if (n === 'sf-icon' || /^sf-icon--/.test(n)) return ` inline icon`; - if (n === 'sf-divider' || /^sf-divider--/.test(n)) return `

    above

    below

    `; - if (n === 'sf-bg-layer') return `
    content over bg
    `; - if (n === 'sf-pancake') return `
    header
    main
    footer
    `; - return `
    ${boxes(4)}
    `; -} - -function macroExample(n, applied) { - if (n === 'sf-prose') return `

    Heading

    ${ipsum}

    • one
    • two

    Another paragraph.

    `; - if (n === 'sf-not-prose') return `

    ${ipsum}

    opted out of prose

    more.

    `; - if (n === 'sf-truncate') return `
    ${ipsum}
    `; - if (/^sf-line-clamp/.test(n)) return `
    ${ipsum} ${ipsum}
    `; - if (n === 'sf-flow') return `

    one

    two

    three

    `; - if (/^sf-surface/.test(n)) return `
    ${n.replace('sf-surface', 'surface') || 'surface'}
    `; - if (n === 'sf-text-gradient') return `
    Gradient text
    `; - if (/^sf-link/.test(n)) return `A ${n.replace('sf-', '')} link`; - if (/^sf-overflow-fade/.test(n)) return `

    ${ipsum}

    ${ipsum}

    `; - if (n === 'sf-scroll-shadow') return `

    ${ipsum}

    ${ipsum}

    `; - if (n === 'sf-scroll-snap') return `
    ${Array.from({ length: 5 }, (_, i) => `
    ${i + 1}
    `).join('')}
    `; - if (n === 'sf-aspect') return `
    16 / 9
    `; - if (/^sf-scrim/.test(n)) { - if (n === 'sf-scrim__content') return `
    scrim content
    `; - return `
    over scrim
    `; - } - if (n === 'sf-tabular-nums') return `
    1234567890
    0987654321
    `; - if (n === 'sf-equal-height') return `
    short
    ${ipsum}
    `; - return `
    ${n.replace('sf-', '')}
    `; -} - -const STATE_ARIA = { - 'sf-is-disabled': ' aria-disabled="true"', 'sf-is-busy': ' aria-busy="true"', 'sf-is-loading': ' aria-busy="true"', - 'sf-is-pending': ' aria-busy="true"', 'sf-is-selected': ' aria-selected="true"', 'sf-is-current': ' aria-current="page"', - 'sf-is-pressed': ' aria-pressed="true"', 'sf-is-expanded': ' aria-expanded="true"', 'sf-is-invalid': ' aria-invalid="true"', - 'sf-is-hidden': ' hidden', 'sf-is-readonly': ' aria-readonly="true"', -}; - -function stateExample(n) { - const aria = STATE_ARIA[n] || ''; - return `
    ${n}
    `; -} - -function a11yExample(n, applied) { - if (n === 'sr-only' || n === 'sr-only-focusable' || n === 'skip-link') return `${n} link (Tab to reveal) ← focusable`; - if (n === 'no-motion') return `
    animation suppressed
    `; - if (n === 'sf-focus-parent' || n === 'sf-focus-shadow') return `
    `; - if (n === 'sf-clickable-parent') return `
    card
    `; - if (n === 'sf-clickable-parent__overlay') return `
    card (overlay link)
    `; - return `
    ${n}
    `; -} - -function printExample(n) { - return `
    ${n} — affects print preview (Ctrl/Cmd-P)
    `; -} - -function example(c) { - const n = c.name; - const applied = c.isVariant && c.baseClass ? `${c.baseClass} ${n}` : n; - switch (c.kind) { - case 'layout': return layoutExample(n, applied); - case 'macro': return macroExample(n, applied); - case 'state': return stateExample(n); - case 'motion': - // .sf-stagger is a parent-level choreography helper — it needs multiple - // animated children to show anything, unlike the single-element motion - // classes handled by the generic tile below. - if (n === 'sf-stagger') { - return `
    ${ - [1, 2, 3].map((i) => `
    ${i}
    `).join('') - }
    `; - } - return `
    ${n.replace('sf-', '')}
    `; - case 'accessibility': return a11yExample(n, applied); - case 'print': return printExample(n); - case 'theme': return `
    ${n}
    `; - default: return `
    ${n}
    `; - } -} - -function tile(c) { - const inBundle = c.bundles.includes('optimal'); - const note = inBundle ? '' : ` not in optimal bundle`; - return `
    -
    .${esc(c.name)}${note}
    -
    ${example(c)}
    -
    `; -} - -// token galleries — make the override's effect on DERIVED tokens visible -function tokenByName(name) { return tokens.find((t) => t.name === name); } -function colorRamp(stem) { - const steps = ['50', '100', '200', '300', '400', '500', '600', '700', '800', '900', '950']; - const cells = steps.filter((s) => tokenByName(`--sf-color-${stem}-${s}`)).map((s) => - `
    ${s}
    `).join(''); - return `
    ${stem}
    ${cells}
    `; -} -function semanticSwatches() { - const names = ['primary', 'secondary', 'tertiary', 'action', 'neutral', 'danger', 'warning', 'success', 'info', - 'surface', 'bg', 'inset', 'text', 'heading', 'link', 'border']; - return names.filter((nm) => tokenByName(`--sf-color-${nm}`)).map((nm) => - `
    ${nm}
    `).join(''); -} -function spacingBars() { - return ['2xs', 'xs', 's', 'm', 'l', 'xl', '2xl', '3xl'].filter((s) => tokenByName(`--sf-space-${s}`)).map((s) => - `
    space-${s}
    `).join(''); -} -function textScale() { - return ['2xs', 'xs', 's', 'm', 'l', 'xl', '2xl', '3xl', '4xl'].filter((s) => tokenByName(`--sf-text-${s}`)).map((s) => - `
    text-${s}Quick brown fox
    `).join(''); -} -function radiusSwatches() { - return ['2xs', 'xs', 's', 'm', 'l', 'xl', '2xl'].filter((s) => tokenByName(`--sf-radius-${s}`)).map((s) => - `
    ${s}
    `).join(''); -} -function shadowSwatches() { - return ['xs', 's', 'm', 'l', 'xl', '2xl'].filter((s) => tokenByName(`--sf-shadow-${s}`)).map((s) => - `
    ${s}
    `).join(''); -} - -function classSection(kind, title) { - const items = classes.filter((c) => c.kind === kind && c.bundles.length > 0).sort((a, b) => a.name.localeCompare(b.name)); - return `
    -

    ${title} ${items.length}

    -
    -${items.map(tile).join('\n')} -
    -
    `; -} - -// ───────────────────────────────────────────────────────────────────────── -// PART 2 — complete token reference (every token, live computed value). -// ───────────────────────────────────────────────────────────────────────── -function tokenVisual(t) { - const n = t.name, ns = t.namespace, v = t.value; - if (/gradient\(/.test(v)) return `
    `; - if (ns === 'color') return `
    `; - if (ns === 'drop' || /drop-shadow\(/.test(v)) return `
    `; - if (ns === 'shadow') { - if (n === '--sf-shadow-color') return `
    `; - if (/none|strength|lightness/.test(n)) return ''; - return `
    `; - } - if (ns === 'radius') return /scale/.test(n) ? '' : `
    `; - if (ns === 'animation') return /delay/.test(n) ? '' : `
    `; - if (ns === 'opacity') return `
    `; - if (ns === 'leading') return `

    Aa Bb
    Cc Dd

    `; - if (ns === 'tracking') return `AVTAW`; - if (ns === 'font') { - if (/weight/.test(n)) return `Ag`; - if (/body|mono|humanist|geometric|slab|family/.test(n)) return `Ag f`; - return ''; - } - if (ns === 'text') { - if (/max-width/.test(n)) return `
    `; - if (/base|ratio|scale/.test(n)) return ''; - return `Aa`; - } - const lenNs = new Set(['space', 'size', 'icon', 'blur', 'gap', 'gutter', 'container', 'sidebar', 'grid', 'equal', - 'bento', 'cover', 'header', 'touch', 'mask', 'scroll', 'focus', 'box', 'content', 'section', 'divider', 'reel', - 'prose', 'stack', 'cluster', 'switcher', 'imposter', 'breakout', 'alternate', 'center', 'btn', 'field', 'scrim', - 'sticky', 'heading']); - if (lenNs.has(ns) && /(\d|\bvar\()/.test(v) && !/\//.test(v) && !/,/.test(v) - && !/^[\d.]+$/.test(v.trim()) // unitless numbers (e.g. --sf-btn-font-scale) can't max() with 3px - && !/^(none|auto|inherit|normal|max-content|min-content|transparent)/.test(v)) { - return `
    `; - } - return ''; -} - -const INHERIT_TOKENS = new Set(['--sf-color-mark-text', '--sf-color-selection-text']); - -function tokenTile(t) { - const vis = tokenVisual(t); - const tier = t.tier === 'PUBLIC' ? '' : ` ${t.tier === 'PUBLIC-ADVANCED' ? 'adv' : t.tier.toLowerCase()}`; - const inheritAttr = INHERIT_TOKENS.has(t.name) ? ' data-inherit="true"' : ''; - return `
    ${esc(t.name)}${tier}${vis ? `
    ${vis}
    ` : ''}
    `; -} - -function tokenReferenceSection() { - const byNs = {}; - tokens.forEach((t) => (byNs[t.namespace] ||= []).push(t)); - const pref = ['color', 'gradient', 'shadow', 'drop', 'radius', 'space', 'size', 'text', 'font', 'leading', 'tracking', - 'duration', 'ease', 'transition', 'animation', 'border', 'focus', 'opacity', 'blur', 'z']; - const order = [...pref.filter((n) => byNs[n]), ...Object.keys(byNs).filter((n) => !pref.includes(n)).sort()]; - const blocks = order.map((ns) => { - const items = byNs[ns].sort((a, b) => a.name.localeCompare(b.name)); - return `

    ${ns} ${items.length}

    \n
    ${items.map(tokenTile).join('')}
    `; - }).join('\n'); - return `
    -

    Part 2 — Complete token reference ${tokens.length} tokens · live values

    -
    Every --sf-* token — knob and consumption, all tiers — with its live computed value (filled by JS). Toggle the theme or the override in the toolbar and watch every value recompute. Tokens that resolve to a colour, length, shadow, gradient, type or motion value also show a visual.
    -${blocks} -
    `; -} - -// ───────────────────────────────────────────────────────────────────────── -// Interactive functions — animations, easings, durations, transitions, -// gradients, drop-shadows. Driven by section-level class toggles + JS replay. -// ───────────────────────────────────────────────────────────────────────── -function fxList(items, render) { return `
    ${items.map(render).join('')}
    `; } -function functionsSection() { - const anims = tokens.filter((t) => t.namespace === 'animation' && !/delay/.test(t.name)); - const eases = tokens.filter((t) => t.namespace === 'ease'); - const durs = tokens.filter((t) => t.namespace === 'duration'); - const trans = tokens.filter((t) => t.namespace === 'transition'); - const grads = tokens.filter((t) => t.namespace === 'gradient'); - const drops = tokens.filter((t) => t.namespace === 'drop'); - const cap = (t) => `${t.name.replace('--sf-', '')}`; - return `
    -

    Interactive functions motion · transitions · gradients

    - -

    Animations

    - ${fxList(anims, (t) => `
    ${cap(t)}
    `)} - -

    Easing curves

    -
    ${fxList(eases, (t) => `
    ${cap(t)}
    `)}
    - -

    Durations

    -
    ${fxList(durs, (t) => `
    ${cap(t)}
    `)}
    - -

    Transitions

    -
    ${fxList(trans, (t) => `
    box
    ${cap(t)}
    `)}
    - -

    Gradients

    - ${fxList(grads, (t) => `
    ${cap(t)}
    `)} - -

    Drop shadows (filter)

    - ${fxList(drops, (t) => `
    ${cap(t)}
    `)} -
    `; -} - -function toolbar() { - return ` `; -} - -const PAGE_SCRIPT = [ - '(function () {', - ' var root = document.documentElement;', - ' function refresh() {', - ' var cs = getComputedStyle(root);', - ' document.querySelectorAll("[data-token]").forEach(function (el) {', - ' var v = cs.getPropertyValue(el.getAttribute("data-token")).trim();', - ' var o = el.querySelector(".ttile__val"); if (o) o.textContent = v || (el.dataset.inherit ? "inherit (contextual)" : "(empty)");', - ' });', - ' }', - ' function playAnims() {', - ' document.querySelectorAll("[data-anim]").forEach(function (el) {', - ' var n = el.getAttribute("data-anim");', - ' el.style.animation = "none"; void el.offsetWidth; el.style.animation = "var(" + n + ")";', - ' });', - ' }', - ' function retrigger(id) { var s = document.getElementById(id); if (!s) return; s.classList.remove("go"); void s.offsetWidth; s.classList.add("go"); }', - ' function setTheme(t) {', - ' if (t === "auto") root.removeAttribute("data-theme"); else root.setAttribute("data-theme", t);', - ' document.querySelectorAll("[data-theme-btn]").forEach(function (b) { b.classList.toggle("active", b.getAttribute("data-theme-btn") === t); });', - ' setTimeout(refresh, 60);', - ' }', - ' var ov = document.getElementById("ov");', - ' function setOverride(on) {', - ' if (on) { if (!ov) { ov = document.createElement("link"); ov.rel = "stylesheet"; ov.href = "ultimate-override.css"; ov.id = "ov"; document.head.appendChild(ov); } }', - ' else if (ov) { ov.remove(); ov = null; }', - ' var b = document.getElementById("ovBtn"); if (b) b.classList.toggle("active", !!ov);', - ' setTimeout(refresh, 90);', - ' }', - ' document.addEventListener("click", function (e) {', - ' var t = e.target.closest("[data-act]"); if (!t) return;', - ' var a = t.getAttribute("data-act");', - ' if (a.indexOf("theme:") === 0) setTheme(a.slice(6));', - ' else if (a === "lumlocker") { root.toggleAttribute("data-lumlocker"); t.classList.toggle("active", root.hasAttribute("data-lumlocker")); setTimeout(refresh, 60); }', - ' else if (a === "crossfade") { root.classList.toggle("sf-theme-transition"); t.classList.toggle("active", root.classList.contains("sf-theme-transition")); }', - ' else if (a === "override") setOverride(!ov);', - ' else if (a === "replay") { playAnims(); retrigger("fx-ease"); retrigger("fx-dur"); var tr = document.getElementById("fx-trans"); if (tr) tr.classList.toggle("on"); }', - ' else if (a === "replay-anim") playAnims();', - ' else if (a === "run-ease") retrigger("fx-ease");', - ' else if (a === "run-dur") retrigger("fx-dur");', - ' else if (a === "toggle-trans") { var s = document.getElementById("fx-trans"); if (s) s.classList.toggle("on"); }', - ' });', - ' setOverride(!!ov);', - ' refresh();', - ' requestAnimationFrame(playAnims);', - '})();', -].join('\n'); - -const bundledClassCount = classes.filter((c) => c.bundles.length > 0).length; - -function buildDemo({ withOverride }) { - const overrideLink = withOverride ? `\n ` : ''; - const banner = withOverride - ? `
    ultimate-override.css is ACTIVE. Every value below is recomputed from perturbed knob tokens — toggle it off in the toolbar, or compare against the un-overridden page.
    ` - : `
    Baseline render with default tokens. Use the toolbar to switch theme, toggle the ultimate override live, or replay motion. The always-on override variant is full-api-demo-with-overrides.html.
    `; - const kinds = [ - ['layout', 'Layout primitives'], - ['macro', 'Macro classes'], - ['state', 'State classes'], - ['motion', 'Motion / animation'], - ['accessibility', 'Accessibility'], - ['print', 'Print'], - ['theme', 'Theme'], - ]; - return ` - - - - - SLASHED — Full API Demo${withOverride ? ' (overridden)' : ''} - ${overrideLink} - - - -${toolbar()} -
    -

    SLASHED Full API Demo

    -

    v${VERSION} · full bundle from jsDelivr CDN · ${bundledClassCount} classes · ${tokens.length} tokens (${knobs.length} configurable)

    - ${banner} - -
    -

    Token galleries highlights

    -

    Color ramps

    - ${['primary', 'secondary', 'tertiary', 'action', 'neutral', 'base'].map(colorRamp).join('\n ')} -

    Semantic / role colors

    -
    ${semanticSwatches()}
    -

    Spacing scale

    - ${spacingBars()} -

    Type scale

    - ${textScale()} -

    Radius

    - -

    Shadow

    - -
    - -${functionsSection()} - -${kinds.map(([k, t]) => classSection(k, t)).join('\n')} - -${tokenReferenceSection()} -
    - - - -`; -} - -// ───────────────────────────────────────────────────────────────────────── -const { css, handledCount } = buildOverride(); -fs.writeFileSync(path.join(OUT, 'ultimate-override.css'), css); - -// completeness assertion for classes -const emitted = new Set(); -for (const c of classes) emitted.add(c.name); -if (emitted.size !== classes.length) throw new Error('class de-dup mismatch'); - -const baseHtml = buildDemo({ withOverride: false }); -fs.writeFileSync(path.join(OUT, 'full-api-demo.html'), baseHtml); -fs.writeFileSync(path.join(OUT, 'full-api-demo-with-overrides.html'), buildDemo({ withOverride: true })); - -// completeness assertion for tokens: every token must appear once in Part 2 -const tokenTiles = (baseHtml.match(/data-token="/g) || []).length; -if (tokenTiles !== tokens.length) { - throw new Error(`Part 2 token reference: ${tokenTiles} tiles != ${tokens.length} tokens`); -} - -console.log(`demos/ultimate-override.css → ${handledCount}/${knobs.length} knobs overridden, ${Object.keys(SKIP).length} skipped (documented)`); -console.log(`demos/full-api-demo.html → ${bundledClassCount} bundled classes (${classes.length - bundledClassCount} example-only excluded) + ${tokens.length} tokens (Part 2), all rendered`); -console.log(`demos/full-api-demo-with-overrides.html → same body + override link`); diff --git a/demos/ultimate-override.css b/demos/ultimate-override.css deleted file mode 100644 index 9aa906552..000000000 --- a/demos/ultimate-override.css +++ /dev/null @@ -1,415 +0,0 @@ -/* ============================================================================ - ULTIMATE OVERRIDE — generated by demos/generate.mjs (do not edit by hand) - SLASHED v0.7.16 - - Perturbs every CONFIGURABLE (role: "knob") token to a valid, visibly-distinct - value so full-api-demo.html can prove each one is wired end to end. - - Coverage: 237 of 265 knob tokens overridden. - 28 knobs are intentionally NOT perturbed (structural / - meta / sentinel) — listed with reasons at the bottom of this file. - ============================================================================ */ - -:root { - - /* aspect */ - --sf-aspect: 3 / 1; /* was: 16 / 9 */ - - /* bento */ - --sf-bento-cols-default: 3; /* was: 4 */ - --sf-bento-row-compact: 9.6rem; /* was: 6rem */ - --sf-bento-row-default: 16rem; /* was: 10rem */ - --sf-bento-row-tall: 25.6rem; /* was: 16rem */ - - /* bg */ - --sf-bg-layer-fit: contain; /* was: cover */ - --sf-bg-layer-inset: 0.75rem; /* was: 0px */ - --sf-bg-layer-position: 25% 75%; /* was: 50% 50% */ - --sf-bg-layer-radius: 0.75rem; /* was: 0 */ - - /* blur */ - --sf-blur: 19.2px; /* was: 12px */ - - /* body */ - --sf-body-em-style: oblique; /* was: italic */ - --sf-body-text-wrap: balance; /* was: pretty */ - - /* border */ - --sf-border-scale: 1.6; /* was: 1 */ - --sf-border-style: dashed; /* was: solid */ - --sf-border-width-hairline: 0.8px; /* was: 0.5px */ - - /* box */ - --sf-box-border-width: 3px; /* was: 0 */ - - /* btn */ - --sf-btn-font-scale: 1.6; /* was: 1 */ - --sf-btn-l-font-size: 1.8rem; /* was: initial */ - --sf-btn-l-min-height: 3rem; /* was: initial */ - --sf-btn-l-padding-block: 0.7rem; /* was: initial */ - --sf-btn-l-padding-inline: 1.6rem; /* was: initial */ - --sf-btn-m-font-size: 1.4rem; /* was: initial */ - --sf-btn-m-min-height: 2.5rem; /* was: initial */ - --sf-btn-m-padding-block: 0.5rem; /* was: initial */ - --sf-btn-m-padding-inline: 1.2rem; /* was: initial */ - --sf-btn-s-font-size: 1.1rem; /* was: initial */ - --sf-btn-s-min-height: 2.1rem; /* was: initial */ - --sf-btn-s-padding-block: 0.35rem; /* was: initial */ - --sf-btn-s-padding-inline: 0.9rem; /* was: initial */ - --sf-btn-xl-font-size: 2.2rem; /* was: initial */ - --sf-btn-xl-min-height: 3.5rem; /* was: initial */ - --sf-btn-xl-padding-block: 0.9rem; /* was: initial */ - --sf-btn-xl-padding-inline: 2rem; /* was: initial */ - --sf-btn-xs-font-size: 0.9rem; /* was: initial */ - --sf-btn-xs-min-height: 1.8rem; /* was: initial */ - --sf-btn-xs-padding-block: 0.2rem; /* was: initial */ - --sf-btn-xs-padding-inline: 0.6rem; /* was: initial */ - - /* card */ - --sf-card-avatar-size: 4rem; /* was: 2.5rem */ - - /* cluster */ - --sf-cluster-align: stretch; /* was: center */ - --sf-cluster-justify: center; /* was: flex-start */ - - /* code */ - --sf-code-font-size: 1.4em; /* was: 0.875em */ - - /* color */ - --sf-color-action-source-dark: oklch(from oklch(0.70 0.198 235) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.70 0.198 235) */ - --sf-color-action-source-light: oklch(from oklch(0.50 0.22 235) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.50 0.22 235) */ - --sf-color-base-source-dark: oklch(from oklch(0.22 0.003 250) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.22 0.003 250) */ - --sf-color-base-source-light: oklch(from oklch(0.96 0.006 250) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.96 0.006 250) */ - --sf-color-black: oklch(from oklch(0% 0 0) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0% 0 0) */ - --sf-color-danger-source-dark: oklch(from oklch(0.71 0.198 12) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.71 0.198 12) */ - --sf-color-danger-source-light: oklch(from oklch(0.48 0.22 12) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.48 0.22 12) */ - --sf-color-dim: oklch(from oklch(0 0 0 / 0.5) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0 0 0 / 0.5) */ - --sf-color-info-source-dark: oklch(from oklch(0.71 0.162 235) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.71 0.162 235) */ - --sf-color-info-source-light: oklch(from oklch(0.48 0.18 235) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.48 0.18 235) */ - --sf-color-mark-text: oklch(0.45 0.27 320); /* was: inherit */ - --sf-color-neutral-source-dark: oklch(from oklch(0.69 0.0225 260) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.69 0.0225 260) */ - --sf-color-neutral-source-light: oklch(from oklch(0.52 0.025 260) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.52 0.025 260) */ - --sf-color-primary-source-dark: oklch(from oklch(0.715 0.243 264) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.715 0.243 264) */ - --sf-color-primary-source-light: oklch(from oklch(0.47 0.27 264) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.47 0.27 264) */ - --sf-color-secondary-source-dark: oklch(from oklch(0.84 0.036 264) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.84 0.036 264) */ - --sf-color-secondary-source-light: oklch(from oklch(0.22 0.04 264) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.22 0.04 264) */ - --sf-color-selection-text: oklch(0.98 0 0); /* was: inherit */ - --sf-color-selection-text--alt: oklch(0.9 0.06 300); /* was: inherit */ - --sf-color-success-source-dark: oklch(from oklch(0.70 0.144 145) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.70 0.144 145) */ - --sf-color-success-source-light: oklch(from oklch(0.50 0.16 145) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.50 0.16 145) */ - --sf-color-tertiary-source-dark: oklch(from oklch(0.74 0.198 295) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.74 0.198 295) */ - --sf-color-tertiary-source-light: oklch(from oklch(0.42 0.22 295) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.42 0.22 295) */ - --sf-color-warning-source-dark: oklch(from oklch(0.65 0.153 80) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.65 0.153 80) */ - --sf-color-warning-source-light: oklch(from oklch(0.75 0.17 80) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0.75 0.17 80) */ - --sf-color-white: oklch(from oklch(100% 0 0) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(100% 0 0) */ - - /* container */ - --sf-container-default: 120rem; /* was: 75rem */ - --sf-container-full: 70%; /* was: 100% */ - --sf-container-narrow: 60.8rem; /* was: 38rem */ - --sf-container-prose: 104ch; /* was: 65ch */ - --sf-container-wide: 144rem; /* was: 90rem */ - - /* content */ - --sf-content-intrinsic-size: 800px; /* was: 500px */ - - /* contrast */ - --sf-contrast-bias: 0.12; /* was: 0 */ - --sf-contrast-threshold: 0.45; /* was: 0.6 */ - - /* cover */ - --sf-cover-min-height: 160dvh; /* was: 100dvh */ - - /* density */ - --sf-density: 1.6; /* was: 1 */ - - /* display */ - --sf-display-l-line-height: 1.2; /* was: 1 */ - --sf-display-m-line-height: 1.25; /* was: 1.05 */ - - /* divider */ - --sf-divider-style: dashed; /* was: solid */ - - /* duration */ - --sf-duration-none: 160ms; /* was: 0ms */ - - /* ease */ - --sf-ease-bounce: cubic-bezier(0.68, -0.55, 0.27, 1.55); /* was: linear(0, 0.35 18%, 1 32%, 0.86 42%, 1.02 56%, 0.98 72%, 1) */ - --sf-ease-elastic: cubic-bezier(0.68, -0.55, 0.27, 1.55); /* was: linear(0, 0.3, 1.2, 0.9, 1.05, 1) */ - --sf-ease-in: cubic-bezier(0.68, -0.55, 0.27, 1.55); /* was: cubic-bezier(0.5, 0, 0.75, 0.25) */ - --sf-ease-in-out: cubic-bezier(0.68, -0.55, 0.27, 1.55); /* was: cubic-bezier(0.4, 0, 0.2, 1) */ - --sf-ease-linear: cubic-bezier(0.68, -0.55, 0.27, 1.55); /* was: linear */ - --sf-ease-out: cubic-bezier(0.68, -0.55, 0.27, 1.55); /* was: cubic-bezier(0.25, 0, 0.15, 1) */ - --sf-ease-overshoot: cubic-bezier(0.68, -0.55, 0.27, 1.55); /* was: linear(0, 0.6 30%, 1.08 55%, 0.98 75%, 1) */ - --sf-ease-spring: cubic-bezier(0.68, -0.55, 0.27, 1.55); /* was: linear(0, 0.5, 1.1, 0.95, 1.02, 1) */ - - /* equal */ - --sf-equal-min-col: 25.6rem; /* was: 16rem */ - --sf-equal-rule-style: dashed; /* was: solid */ - --sf-equal-rule-width: 2px; /* was: 0 */ - - /* field */ - --sf-field-required-marker: " \2737"; /* was: " *" */ - - /* fluid */ - --sf-fluid-max-vw: 70; /* was: 90 */ - --sf-fluid-min-vw: 30; /* was: 22.5 */ - --sf-fluid-width: 160vw; /* was: 100vw */ - - /* focus */ - --sf-focus-ring-offset: 3.2px; /* was: 2px */ - --sf-focus-ring-style: dashed; /* was: solid */ - --sf-focus-ring-width: 3.2px; /* was: 2px */ - - /* font */ - --sf-font-body: "Georgia", "Times New Roman", serif; /* was: system-ui, -apple-system, sans-serif */ - --sf-font-features: "liga" 1, "calt" 1; /* was: normal */ - --sf-font-geometric: "Georgia", "Times New Roman", serif; /* was: "Avenir", "Montserrat", "Corbel", "URW Gothic", source-sans-pro, sans-serif */ - --sf-font-humanist: "Georgia", "Times New Roman", serif; /* was: "Seravek", "Gill Sans Nova", "Ubuntu", "Calibri", "DejaVu Sans", source-sans-pro, sans-serif */ - --sf-font-mono: "Courier New", ui-monospace, monospace; /* was: ui-monospace, monospace */ - --sf-font-numeric: oldstyle-nums; /* was: tabular-nums */ - --sf-font-slab: "Georgia", "Times New Roman", serif; /* was: "Rockwell", "Rockwell Nova", "Roboto Slab", "DejaVu Serif", "Sitka Small", serif */ - --sf-font-variation: "wght" 650; /* was: normal */ - --sf-font-weight-bold: 900; /* was: 700 */ - --sf-font-weight-light: 200; /* was: 300 */ - --sf-font-weight-medium: 700; /* was: 500 */ - --sf-font-weight-normal: 600; /* was: 400 */ - --sf-font-weight-semibold: 800; /* was: 600 */ - - /* frame */ - --sf-frame-ratio: 3 / 1; /* was: 16 / 9 */ - - /* grid */ - --sf-grid-min: 25.6rem; /* was: 16rem */ - --sf-grid-min-2xl: 44.8rem; /* was: 28rem */ - --sf-grid-min-l: 32rem; /* was: 20rem */ - --sf-grid-min-m: 25.6rem; /* was: 16rem */ - --sf-grid-min-s: 20.8rem; /* was: 13rem */ - --sf-grid-min-xl: 38.4rem; /* was: 24rem */ - --sf-grid-min-xs: 16rem; /* was: 10rem */ - - /* h1 */ - --sf-h1-max-width: 40ch; /* was: none */ - - /* h2 */ - --sf-h2-max-width: 40ch; /* was: none */ - - /* h3 */ - --sf-h3-max-width: 40ch; /* was: none */ - - /* h4 */ - --sf-h4-max-width: 40ch; /* was: none */ - - /* h5 */ - --sf-h5-max-width: 40ch; /* was: none */ - - /* h6 */ - --sf-h6-max-width: 40ch; /* was: none */ - - /* header */ - --sf-header-height-desktop: 8rem; /* was: 5rem */ - --sf-header-height-mobile: 5.6rem; /* was: 3.5rem */ - - /* heading */ - --sf-heading-text-wrap: pretty; /* was: balance */ - - /* hover */ - --sf-hover-grow-scale: 1.4; /* was: 1.05 */ - --sf-hover-lift: 0.4em; /* was: 0.25em */ - --sf-hover-shrink-scale: 0.6; /* was: 0.95 */ - --sf-hover-slide: 0.8em; /* was: 0.5em */ - - /* icon */ - --sf-icon-2xl: 6.4em; /* was: 4em */ - --sf-icon-box-pad: 0.8em; /* was: 0.5em */ - --sf-icon-l: 3.2em; /* was: 2em */ - --sf-icon-m: 2.4em; /* was: 1.5em */ - --sf-icon-s: 1.6em; /* was: 1em */ - --sf-icon-xl: 4.8em; /* was: 3em */ - --sf-icon-xs: 1.4em; /* was: 0.875em */ - - /* leading */ - --sf-leading-normal: 1.8; /* was: 1.5 */ - --sf-leading-relaxed: 2; /* was: 1.625 */ - --sf-leading-snug: 1.5; /* was: 1.3 */ - --sf-leading-taper: 0.4; /* was: 0 */ - --sf-leading-tight: 1.25; /* was: 1.1 */ - - /* line */ - --sf-line-clamp: 2; /* was: 3 */ - - /* link */ - --sf-link-external-label: "leaves this site"; /* was: "opens in a new window or external site" */ - --sf-link-external-marker: " \2192"; /* was: " \2197" */ - --sf-link-underline-offset: 0.24em; /* was: 0.15em */ - --sf-link-underline-thickness: 3px; /* was: auto */ - - /* lumlocker */ - --sf-lumlocker: 0.5; /* was: 0.65 */ - - /* media */ - --sf-media-radius: 0.75rem; /* was: 0 */ - - /* motion */ - --sf-motion-scale: 1.6; /* was: 1 */ - - /* object */ - --sf-object-fit: contain; /* was: cover */ - --sf-object-position: 25% 75%; /* was: 50% 50% */ - - /* opacity */ - --sf-opacity-disabled: 0.7; /* was: 0.45 */ - --sf-opacity-muted: 0.75; /* was: 0.5 */ - - /* optical */ - --sf-optical-sizing: none; /* was: auto */ - - /* palette */ - --sf-palette-mix-100: 5.6%; /* was: 8% */ - --sf-palette-mix-200: 14%; /* was: 20% */ - --sf-palette-mix-300: 28%; /* was: 40% */ - --sf-palette-mix-400: 45.5%; /* was: 65% */ - --sf-palette-mix-50: 2.8%; /* was: 4% */ - --sf-palette-mix-600: 57.4%; /* was: 82% */ - --sf-palette-mix-700: 43.4%; /* was: 62% */ - --sf-palette-mix-800: 26.6%; /* was: 38% */ - --sf-palette-mix-900: 12.6%; /* was: 18% */ - --sf-palette-mix-950: 5.6%; /* was: 8% */ - - /* print */ - --sf-print-base-size: 17.6pt; /* was: 11pt */ - --sf-print-page-margin: 3.2cm; /* was: 2cm */ - --sf-print-page-size: letter; /* was: a4 */ - - /* radius */ - --sf-radius-full: 15998.4px; /* was: 9999px */ - --sf-radius-none: 0.4rem; /* was: 0 */ - --sf-radius-scale: 1.6; /* was: 1 */ - - /* ratio */ - --sf-ratio-3-2: 3 / 1; /* was: 3 / 2 */ - --sf-ratio-4-3: 3 / 1; /* was: 4 / 3 */ - --sf-ratio-cinema: 3 / 1; /* was: 21 / 9 */ - --sf-ratio-golden: 3 / 1; /* was: 1.618 / 1 */ - --sf-ratio-portrait: 3 / 1; /* was: 3 / 4 */ - --sf-ratio-square: 3 / 1; /* was: 1 */ - --sf-ratio-video: 3 / 1; /* was: 16 / 9 */ - - /* reel */ - --sf-reel-height: 14rem; /* was: auto */ - --sf-reel-item-width: min-content; /* was: max-content */ - - /* scrim */ - --sf-scrim-color: oklch(from oklch(0 0 0 / 0.55) calc(l + 0.12) calc(c + 0.12) calc(h + 150) / alpha); /* was: oklch(0 0 0 / 0.55) */ - --sf-scrim-direction: to right; /* was: to top */ - --sf-scrim-text-shadow: 0 2px 6px oklch(0 0 0 / 0.85); /* was: 0 1px 3px oklch(0 0 0 / 0.6) */ - - /* scroll */ - --sf-scroll-shadow-size: 3.2rem; /* was: 2rem */ - --sf-scroll-timeline-range-end: cover 60%; /* was: cover 30% */ - --sf-scroll-timeline-range-exit-end: exit 80%; /* was: exit 100% */ - --sf-scroll-timeline-range-exit-start: exit 20%; /* was: cover 70% */ - --sf-scroll-timeline-range-start: entry 20%; /* was: entry 0% */ - - /* scrollbar */ - --sf-scrollbar-track: oklch(0.85 0.05 300); /* was: transparent */ - - /* section */ - --sf-section-scale: 1.6; /* was: 1 */ - - /* shadow */ - --sf-shadow-lightness: 0.4; /* was: 0.15 */ - --sf-shadow-strength: 0.45; /* was: calc(0.08 + var(--sf-is-dark) * 0.17) */ - - /* sidebar */ - --sf-sidebar-min-width: 35%; /* was: 50% */ - --sf-sidebar-width: 28.8rem; /* was: 18rem */ - - /* space */ - --sf-space-base-max: 3; /* was: 2 */ - --sf-space-base-min: 1.4; /* was: 1 */ - --sf-space-none: 0.25rem; /* was: 0 */ - --sf-space-px: 2px; /* was: 1px */ - --sf-space-ratio-max: 1.6; /* was: 1.333 */ - --sf-space-ratio-min: 1.4; /* was: 1.25 */ - --sf-space-scale: 1.6; /* was: 1 */ - - /* stagger */ - --sf-stagger-step: 200ms; /* was: 75ms */ - - /* state */ - --sf-state-pending-opacity: 0.4; /* was: 0.7 */ - - /* surface */ - --sf-surface-bg-attachment: fixed; /* was: scroll */ - --sf-surface-bg-color: oklch(0.85 0.05 300); /* was: transparent */ - --sf-surface-bg-image: linear-gradient(135deg, oklch(0.9 0.08 300 / 0.6), oklch(0.8 0.12 200 / 0.6)); /* was: none */ - --sf-surface-bg-overlay: linear-gradient(oklch(0 0 0 / 0.15), oklch(0 0 0 / 0.15)); /* was: none */ - --sf-surface-bg-position: 25% 75%; /* was: center */ - --sf-surface-bg-repeat: repeat; /* was: no-repeat */ - --sf-surface-bg-size: contain; /* was: cover */ - - /* switcher */ - --sf-switcher-threshold: 48rem; /* was: 30rem */ - - /* text */ - --sf-text-2xl-max-width: 50ch; /* was: none */ - --sf-text-2xs-max-width: 88ch; /* was: 55ch */ - --sf-text-3xl-max-width: 50ch; /* was: none */ - --sf-text-4xl-max-width: 50ch; /* was: none */ - --sf-text-base-max: 1.5; /* was: 1.25 */ - --sf-text-base-min: 1.15; /* was: 1 */ - --sf-text-display-base-max: 3.8; /* was: 3 */ - --sf-text-display-base-min: 2.8; /* was: 2.4 */ - --sf-text-display-scale: 1.6; /* was: 1 */ - --sf-text-l-max-width: 50ch; /* was: none */ - --sf-text-m-max-width: 104ch; /* was: 65ch */ - --sf-text-ratio-max: 1.5; /* was: 1.333 */ - --sf-text-ratio-min: 1.35; /* was: 1.25 */ - --sf-text-s-max-width: 104ch; /* was: 65ch */ - --sf-text-scale: 1.6; /* was: 1 */ - --sf-text-xl-max-width: 50ch; /* was: none */ - --sf-text-xs-max-width: 96ch; /* was: 60ch */ - - /* touch */ - --sf-touch-target: 4.4rem; /* was: 2.75rem */ - - /* tracking */ - --sf-tracking-normal: 0.03em; /* was: 0 */ - --sf-tracking-tight: -0.04em; /* was: -0.025em */ - --sf-tracking-wide: 0.04em; /* was: 0.025em */ - --sf-tracking-wider: 0.08em; /* was: 0.05em */ - --sf-tracking-widest: 0.16em; /* was: 0.1em */ -} - -/* ---------------------------------------------------------------------------- - Intentionally NOT overridden (28): - --sf-bg-layer-z — stacking order — lowering it would push the background layer over content - --sf-btn-font-size — flatten-all label size — reads FIRST in the font-size cascade, so setting it would shadow the per-size --sf-btn-{size}-font-size knobs (and mask the --sf-btn-font-scale multiplier) this demo exercises; the per-size ladder is the recommended surface - --sf-btn-min-height — flatten-all min-height — reads FIRST in the cascade, shadowing the per-size --sf-btn-{size}-min-height knobs this demo exercises - --sf-btn-padding-block — flatten-all block padding — reads FIRST in the cascade, shadowing the per-size --sf-btn-{size}-padding-block knobs this demo exercises - --sf-btn-padding-inline — flatten-all inline padding — reads FIRST in the cascade, shadowing the per-size --sf-btn-{size}-padding-inline knobs this demo exercises - --sf-color-scheme — meta control — forcing a scheme would override the page light/dark behaviour rather than test a visual token - --sf-is-active — runtime state flag — exercised via the .sf-is-active class; a global :root flip would force every element active - --sf-is-current — runtime state flag — exercised via the .sf-is-current class - --sf-is-dark — runtime theme flag — driven by color-scheme; a global flip would desync from the actual scheme - --sf-is-open — runtime state flag — exercised via the .sf-is-open class - --sf-is-pressed — runtime state flag — exercised via the .sf-is-pressed class - --sf-safe-bottom — env() device inset — zero on desktop, no visual surface - --sf-safe-left — env() device inset — zero on desktop, no visual surface - --sf-safe-right — env() device inset — zero on desktop, no visual surface - --sf-safe-top — env() device inset — zero on desktop, no visual surface - --sf-shadow-none — sentinel "none" — the API guarantees no shadow; overriding would add one where none is promised - --sf-surface-bg-animation — background animation shorthand on .sf-surface — a global value would force motion on every surface and fight reduced-motion; no safe single-element visual perturbation - --sf-text-shadow-none — sentinel "none" — the API guarantees no text-shadow - --sf-z-base — stacking order — no single-element visual surface - --sf-z-below — stacking order — no single-element visual surface; global change risks hiding content - --sf-z-dropdown — stacking order — no single-element visual surface - --sf-z-fixed — stacking order — no single-element visual surface - --sf-z-modal — stacking order — no single-element visual surface - --sf-z-overlay — stacking order — no single-element visual surface - --sf-z-raised — stacking order — no single-element visual surface - --sf-z-sticky — stacking order — no single-element visual surface - --sf-z-toast — stacking order — no single-element visual surface - --sf-z-tooltip — stacking order — no single-element visual surface - ---------------------------------------------------------------------------- */ diff --git a/demos/validate.mjs b/demos/validate.mjs deleted file mode 100644 index 167d3ba6c..000000000 --- a/demos/validate.mjs +++ /dev/null @@ -1,102 +0,0 @@ -// Validates the generated demo in a real browser against the locally built -// optimal bundle. Asserts: no console errors, all class + token tiles present, -// JS populates live token values, the dark-mode toggle restyles the page, and -// the runtime override toggle perturbs computed styles. -import { chromium } from '@playwright/test'; -import fs from 'node:fs'; -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; - -const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); -const CDN = 'https://cdn.jsdelivr.net/gh/codeslash-dev/SLASHED@dist/slashed.optimal.css'; -const LOCAL = path.join(ROOT, 'dist/slashed.optimal.css'); -const TMP = path.join(ROOT, 'demos/.validate'); -fs.mkdirSync(TMP, { recursive: true }); -const DEMOS = path.join(ROOT, 'demos'); -// make the runtime-injected override reachable from the temp copy -fs.copyFileSync(path.join(DEMOS, 'ultimate-override.css'), path.join(TMP, 'ultimate-override.css')); - -function localCopy(srcName, outName) { - let html = fs.readFileSync(path.join(DEMOS, srcName), 'utf8'); - html = html.replaceAll(CDN, 'file://' + LOCAL); - const out = path.join(TMP, outName); - fs.writeFileSync(out, html); - return 'file://' + out; -} -const baseUrl = localCopy('full-api-demo.html', 'base.html'); -const expectClasses = (fs.readFileSync(path.join(DEMOS, 'full-api-demo.html'), 'utf8').match(/class="tile"/g) || []).length; -const expectTokens = (fs.readFileSync(path.join(DEMOS, 'full-api-demo.html'), 'utf8').match(/data-token="/g) || []).length; - -const browser = await chromium.launch({ executablePath: '/opt/pw-browsers/chromium' }); -const page = await browser.newPage({ viewport: { width: 1280, height: 1600 } }); -const errors = []; -page.on('console', (m) => { if (m.type() === 'error') errors.push(m.text()); }); -page.on('pageerror', (e) => errors.push(String(e))); -await page.goto(baseUrl, { waitUntil: 'domcontentloaded', timeout: 60000 }); -await page.waitForTimeout(800); - -const fails = []; -const snap = () => page.evaluate(() => { - const cs = getComputedStyle(document.documentElement); - const body = getComputedStyle(document.body); - const vals = [...document.querySelectorAll('.ttile__val')].map((o) => o.textContent.trim()); - return { - classTiles: document.querySelectorAll('.tile').length, - tokenTiles: document.querySelectorAll('[data-token]').length, - filledVals: vals.filter((v) => v && v !== '…' && v !== '(empty)').length, - theme: document.documentElement.getAttribute('data-theme'), - bg: body.backgroundColor, - text: body.color, - primary: cs.getPropertyValue('--sf-color-primary').trim(), - spaceM: cs.getPropertyValue('--sf-space-m').trim(), - fxSections: ['functions', 'reference'].filter((id) => document.getElementById(id)).length, - }; -}); - -const click = (sel) => page.evaluate((s) => document.querySelector(s).click(), sel); - -const light = await snap(); -await page.screenshot({ path: path.join(TMP, 'light.png') }); - -// dark mode -await click('[data-act="theme:dark"]'); -await page.waitForTimeout(300); -const dark = await snap(); -await page.screenshot({ path: path.join(TMP, 'dark.png') }); - -// runtime override toggle (back in light) -await click('[data-act="theme:light"]'); -await click('#ovBtn'); -await page.waitForTimeout(300); -const overridden = await snap(); -await page.screenshot({ path: path.join(TMP, 'override.png') }); - -// section screenshots for the report -await click('#ovBtn'); // override off -await click('[data-act="theme:light"]'); -await page.waitForTimeout(200); -for (const id of ['functions', 'reference']) { - const el = await page.$('#' + id); - if (el) await el.screenshot({ path: path.join(TMP, `sec-${id}.png`) }).catch(() => {}); -} -await browser.close(); - -console.log('expected class tiles:', expectClasses, '| token tiles:', expectTokens); -console.log('LIGHT :', JSON.stringify(light)); -console.log('DARK :', JSON.stringify(dark)); -console.log('OVERRIDE:', JSON.stringify(overridden)); -console.log('console errors:', errors.length); -errors.slice(0, 10).forEach((e) => console.log(' ⚠', e)); - -if (light.classTiles !== expectClasses) fails.push(`class tiles ${light.classTiles} != ${expectClasses}`); -if (light.tokenTiles !== expectTokens) fails.push(`token tiles ${light.tokenTiles} != ${expectTokens}`); -if (light.filledVals < expectTokens * 0.6) fails.push(`only ${light.filledVals}/${expectTokens} token values populated by JS`); -if (light.fxSections !== 2) fails.push('functions/reference sections missing'); -if (dark.theme !== 'dark') fails.push('dark toggle did not set data-theme=dark'); -if (dark.bg === light.bg) fails.push(`dark mode did not change body background (still ${light.bg})`); -if (overridden.primary === light.primary) fails.push('override toggle did not change --sf-color-primary'); -if (overridden.spaceM === light.spaceM) fails.push('override toggle did not change --sf-space-m'); -if (errors.length) fails.push(`${errors.length} console error(s)`); - -if (fails.length) { console.log('\n❌ FAIL:'); fails.forEach((f) => console.log(' ', f)); process.exit(1); } -console.log(`\n✅ PASS — ${expectClasses} classes + ${expectTokens} tokens rendered; JS fills live values; dark mode restyles; override toggles live; 0 console errors.`); diff --git a/docs/architecture.md b/docs/architecture.md index d9f826346..c73ed35db 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -253,7 +253,7 @@ Many tokens — `--sf-shadow-*`, `--sf-blur`, `--sf-gap`, `--sf-gradient-*`, `--sf-scrollbar-*`, `--sf-optical-sizing` — are **not consumed by the framework itself**. They exist for your own BEM classes (`.card { box-shadow: var(--sf-shadow-m) }`) and are exercised in -`docs/demo.html` and validated by `tests/`. +`demo/index.html` and validated by `tests/`. ### Print class naming diff --git a/docs/demo.html b/docs/demo.html deleted file mode 100644 index c268b0dfc..000000000 --- a/docs/demo.html +++ /dev/null @@ -1,3193 +0,0 @@ - - - - - - SLASHED — Demo - - - - - - - - -
    -
    - - SLASHED / demo -
    - -
    - - - -
    - - - -
    - - -
    -

    Theme Customizer

    -

    - Override just 6 tokens in the Light mode column for quick branding — dark mode automatically derives an appropriate value via relative color syntax, no extra work needed. Optionally override any token in the Dark mode column for full per-mode control. Changes apply live to :root; toggle dark mode in the header to preview. -

    - -
    - -
    -

    Light mode

    - -
    - Brand -
    - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - -
    - Status -
    - - - - - - - - - - - - - - - -
    -
    -
    - - -
    -

    Dark mode

    - -
    - Brand -
    - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - -
    - Status -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - -
    - - -
    - -
    -

    Accessibility report (live, both modes)

    -

    - WCAG 2 contrast for your chosen colours, recomputed live. The framework auto-picks readable on-colours (black/white by lightness) and clamps link lightness — but contrast also depends on chroma, so this panel shows the actual result, including any pairs that fall short. AA = 4.5:1 (normal text); AA Large = 3:1 (large/UI). Fix a ✗ by adjusting that colour's lightness, or override the on-/text token directly. -

    -
    -
    -
    - - -
    -

    Colors

    - -

    Brand — light mode (base values)

    -
    -
    primary
    -
    secondary
    -
    tertiary
    -
    action
    -
    neutral
    -
    surface
    -
    - -

    Semantic Surfaces

    -
    -
    bg
    -
    surface
    -
    inset
    -
    raised
    -
    overlay
    -
    inverse
    -
    - -

    Status Colors

    -
    -
    success
    -
    warning
    -
    info
    -
    danger
    -
    - -

    Status Triplets

    -
    -
    Success
    -
    Warning
    -
    Danger
    -
    Info
    -
    - -

    Text Hierarchy

    -
    -

    --sf-color-text (primary)

    -

    --sf-color-text--secondary

    -

    --sf-color-text--muted

    -

    --sf-color-text--placeholder

    -

    --sf-color-text--disabled

    -

    --sf-color-heading

    -
    - -

    Borders

    -
    -
    --sf-color-border
    -
    --sf-color-border--subtle
    -
    --sf-color-border--strong
    -
    --sf-color-border--focus (action color)
    -
    - -

    Gradients

    -
    -
    gradient-primary
    -
    gradient-secondary
    -
    gradient-tertiary
    -
    gradient-brand
    -
    gradient-surface
    -
    - -

    Palette Numeric Scale 50–950 (core/tokens.css)

    -
    -
    50
    -
    100
    -
    200
    -
    300
    -
    400
    -
    500
    -
    600
    -
    700
    -
    800
    -
    900
    -
    950
    -
    - -

    Alpha Scale a5–a80

    -
    -
    a5
    -
    a10
    -
    a30
    -
    a50
    -
    a80
    -
    - -

    Semantic & Functional Aliases

    -
    -
    superlight
    -
    xlight
    -
    lighter
    -
    darker
    -
    xdark
    -
    superdark
    -
    hover
    -
    active
    -
    subtle
    -
    muted
    -
    tint
    -
    -
    - - -
    -

    Scoped Themes

    -

    - Use data-theme="dark" or data-theme="light" on any element to scope a theme. When attributes are inconvenient, .sf-theme-dark and .sf-theme-light are equivalent class aliases. Tokens resolve correctly per-section, enabling nested light-inside-dark (or vice-versa) without extra overrides. -

    - - -
    -

    Dark section data-theme="dark"

    - -
    -
    primary
    -
    secondary
    -
    tertiary
    -
    action
    -
    neutral
    -
    surface
    -
    - -
    -

    --sf-color-text (primary)

    -

    --sf-color-text--secondary

    -

    --sf-color-text--muted

    -
    - -
    -
    Success
    -
    Warning
    -
    Danger
    -
    - - -
    -

    Light section (nested) data-theme="light"

    - -
    -
    primary
    -
    secondary
    -
    tertiary
    -
    action
    -
    neutral
    -
    surface
    -
    - -
    -

    --sf-color-text (primary)

    -

    --sf-color-text--secondary

    -

    --sf-color-text--muted

    -
    - -
    -
    Success
    -
    Warning
    -
    Danger
    -
    -
    -
    - -

    Opt-in theme cross-fade .sf-theme-transition

    -

    - Add class="sf-theme-transition" to <html> (or any subtree) so colours - fade instead of switching instantly when the theme flips. Tune the speed with - --sf-theme-transition-duration. Toggle dark mode in the header to see this block cross-fade. -

    -
    - Smooth theme transition -

    This card fades its background, text and border colours when the mode changes.

    -
    - -

    Section theme aliases .sf-theme-light / .sf-theme-dark

    -

    - Class aliases for data-theme: one class scopes the theme, setting the background and flipping the - whole foreground (text, links, borders) to match — always light or always dark, - regardless of the ambient scheme. -

    -
    -
    - .sf-theme-dark -

    Auto-light text, and a themed link.

    -
    -
    - .sf-theme-light -

    Auto-dark text, and a themed link.

    -
    -
    - -

    Named background surface .sf-surface-bg

    -

    - A reusable, named background bundling a base colour + image/gradient + an optional - overlay layered above it. Define the --sf-surface-bg-* tokens on a scope, - then apply the class. Here the overlay is a scrim over a gradient "image". -

    -
    - Composed background preset -
    -
    - - -
    -

    Typography

    - -

    Heading Scale (base.css)

    -
    -

    h1 — The quick brown fox

    -

    h2 — The quick brown fox

    -

    h3 — The quick brown fox

    -

    h4 — The quick brown fox

    -
    h5 — The quick brown fox
    -
    h6 — The quick brown fox
    -
    - -

    Fluid Text Scale (--sf-text-*)

    -

    All sizes use clamp() — resize the window to see fluid scaling.

    -
    -
    2xs — The quick brown fox jumps over the lazy dog
    -
    xs — The quick brown fox jumps over the lazy dog
    -
    s — The quick brown fox jumps
    -
    m (base) — The quick brown fox
    -
    l — The quick brown fox
    -
    xl — The quick brown
    -
    2xl — The quick
    -
    3xl — Quick
    -
    4xl
    -
    display-s
    -
    display-m
    -
    display-l
    -
    - -

    Font Weights — base weights + semantic roles

    -
    - 300 light — The quick brown fox - 400 normal — The quick brown fox - 500 medium — The quick brown fox - 600 semibold — The quick brown fox - 700 bold — The quick brown fox -
    -

    Semantic roles (override to reweight the whole site):

    -
    - body — The quick brown fox - interactive — buttons, badges, nav - heading — section titles - strong — inline emphasis - display — hero headlines -
    - -

    Semantic Weight Aliases & Font Stacks

    -
    - body - heading - display -
    -
    - humanist — The quick brown fox jumps - geometric — The quick brown fox jumps - slab — The quick brown fox jumps - mono — The quick brown fox jumps -
    - -

    Line Heights (--sf-leading-*)

    -
    -
    - --sf-leading-tight (1.1) -

    Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod.

    -
    -
    - --sf-leading-snug (1.3) -

    Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod.

    -
    -
    - --sf-leading-normal (1.5) -

    Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod.

    -
    -
    - --sf-leading-relaxed (1.625) -

    Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod.

    -
    -
    - -

    Letter Spacing (--sf-tracking-*)

    -
    -
    tracking-tight — THE QUICK BROWN FOX JUMPS OVER
    -
    tracking-normal — THE QUICK BROWN FOX JUMPS OVER
    -
    tracking-wide — THE QUICK BROWN FOX
    -
    tracking-wider — THE QUICK BROWN
    -
    tracking-widest — THE QUICK
    -
    - -

    Semantic Elements (base.css)

    -

    - strong, - em, - mark highlight, - inline code, - Ctrl + C, - CSS, - H2O, - E=mc2, - small text, - link, - deleted, - inserted -

    -
    /* pre + code block */
    -:root {
    -  --sf-color-primary-source-light: oklch(0.47 0.27 264);
    -  --sf-color-neutral-source-light: oklch(0.52 0.025 260);
    -}
    -
    - A blockquote. Try selecting this text to see --sf-color-selection-bg. -
    - -

    Link States

    - -
    - - -
    -

    Spacing

    -

    All fluid tokens use clamp() — resize the window to see bars animate.

    - -
    -
    - --sf-space-none -
    - 0 -
    -
    - --sf-space-px -
    -
    -
    - --sf-space-2xs -
    -
    -
    - --sf-space-xs -
    -
    -
    - --sf-space-s -
    -
    -
    - --sf-space-m -
    -
    -
    - --sf-space-l -
    -
    -
    - --sf-space-xl -
    -
    -
    - --sf-space-2xl -
    -
    -
    - --sf-space-3xl -
    -
    -
    - --sf-space-4xl -
    -
    -
    - -

    Spacing Aliases

    -
    - --sf-gap → --sf-space-m - --sf-content-gap → --sf-space-s - --sf-component-pad → --sf-space-m - --sf-field-block → --sf-space-l - --sf-prose-paragraph → --sf-content-gap → --sf-space-s -
    -
    - - -
    -

    Shadows

    -

    Shadow color is a neutral near-black auto-derived from --sf-color-neutral (--sf-shadow-color) — override it to var(--sf-color-primary) for tinted shadows. In dark mode strength scales up but every layer's alpha is capped at 0.7. Adjust via --sf-shadow-strength.

    - -
    -
    shadow-none
    -
    shadow-xs
    -
    shadow-s
    -
    shadow-m
    -
    shadow-l
    -
    shadow-xl
    -
    shadow-2xl
    -
    shadow-inner
    -
    shadow-glow
    -
    - -

    Text Shadows

    -
    - text-shadow-xs - text-shadow-s - text-shadow-m - text-shadow-l - text-shadow-xl -
    - -

    Drop Shadows (filter — follows alpha edges)

    -
    - - - - - -
    - -

    3D Perspective

    -
    -
    -
    -
    -
    -
    - - -
    -

    Border Radius

    -

    All values multiplied by --sf-radius-scale (1 by default).

    - -
    -
    none
    0
    -
    xs
    2px
    -
    s
    4px
    -
    m
    8px
    -
    l
    12px
    -
    xl
    16px
    -
    2xl
    24px
    -
    3xl
    32px
    -
    4xl
    48px
    -
    full
    9999px
    -
    -
    - - -
    -

    Motion & States

    - -
    - Reduced motion active — Your OS has reduced motion enabled. Animations are paused (duration: 0.01ms via accessibility.css). -
    - -

    Transitions (motion.css — hover these)

    -

    - motion.css applies a default transition to all interactive elements (a, button, input, etc.) using --sf-duration-fast and --sf-ease-out. Hover to see the transition between the base and hover states. -

    -
    - - - Link transition -
    - -

    Easing Curves

    -
    -
    - ease-linear -
    -
    -
    - ease-out -
    -
    -
    - ease-in -
    -
    -
    - ease-in-out -
    -
    -
    - ease-spring -
    -
    -
    - ease-elastic -
    -
    -
    - ease-bounce -
    -
    -
    - ease-overshoot -
    -
    -
    - -

    Animation Presets (motion.css — click to replay)

    -
    - - - - - - -
    - -

    .sf-stagger (motion.css — parent choreographs children's animation-delay; click to replay)

    -
      -
    • 1
    • -
    • 2
    • -
    • 3
    • -
    • 4
    • -
    - -

    @property Color Interpolation (motion.css — sf-color-pulse)

    -

    - Demonstrates smooth oklch color animation via @property-registered tokens. - The box below pulses its --sf-color-primary-source-light lightness. Only works in browsers supporting @property inherits. -

    -
    - .sf-color-pulse — animating --sf-color-primary-source-light -
    - -

    Duration Tokens

    -

    Hover any row — the dot slides across using that duration token. Easing is the same (--sf-ease-out) so the only variable is speed.

    -
    -
    - --sf-duration-instant -
    -
    -
    -
    -
    - --sf-duration-fast (default) -
    -
    -
    -
    -
    - --sf-duration-normal -
    -
    -
    -
    -
    - --sf-duration-slow -
    -
    -
    -
    -
    - --sf-duration-slower -
    -
    -
    -
    -
    - -

    States (states.css)

    -
    -
    -

    .sf-is-loading

    - -
    -
    -

    .sf-is-skeleton

    -
    -
    -
    -
    -
    -
    -
    -

    .sf-is-hidden / .sf-is-invisible

    -
    - visible - hidden (display:none) - invisible (visibility:hidden) - .sf-is-visible (force visibility:visible) -
    -
    -
    -
    - - -
    -

    States — Full Coverage

    -

    Every .sf-is-* class from states.css. Grouped by category.

    - -

    Navigation & Toggling

    -
    - .sf-is-active (--sf-is-active: 1) - .sf-is-current (bold) - .sf-is-selected - .sf-is-highlighted -
    - -

    Disclosure

    -
    - .sf-is-open - .sf-is-expanded - .sf-is-collapsed -
    - -

    Validation / Feedback

    -
    - .sf-is-valid - .sf-is-invalid - .sf-is-warning - .sf-is-success - .sf-is-error - .sf-is-info - .sf-is-danger -
    - -

    Drag & Drop

    -
    - .sf-is-dragging - .sf-is-drop-target - .sf-is-draggable -
    - -

    Overlay

    -
    -
    .sf-overlay
    -
    - -

    Interactivity

    -
    - .sf-is-busy - .sf-is-readonly - .sf-is-disabled - .sf-is-pending - .sf-is-pressed -
    -
    - .sf-focus-parent (focus the input → parent rings) - -
    - -

    Empty State

    -
    -
    - .sf-is-empty:empty → display:none (the empty div above is gone) -
    -
    - - -
    -

    Layout — Additional Primitives

    - -

    .sf-imposter

    -

    Absolutely positioned overlay. Modifiers: --fixed, --contain.

    -
    -
    .sf-imposter (centered)
    -
    -
    -
    .sf-imposter--contain (clamps to 100% − 2 × --sf-imposter-margin in both axes; overflow: auto kicks in only when the content is larger than that box)
    -
    - -

    .sf-imposter--fixed

    -

    Uses position: fixed — not demoed visually to avoid viewport takeover. Class reference: sf-imposter--fixed.

    - -

    .sf-subgrid / .sf-subgrid-rows

    -

    Inherit parent grid tracks. Requires parent with explicit grid.

    -
    -
    -
    Subgrid col 1
    -
    Subgrid col 2
    -
    -
    Regular col
    -
    -

    .sf-subgrid-rows works the same for row tracks.

    - -

    .sf-section-group

    -

    Groups adjacent .sf-section elements with zero gap between them.

    -
    -
    Section A (--s padding)
    -
    Section B (--s padding)
    -
    - -

    .sf-divider

    -

    Token-driven separator (--sf-divider-width/-style/-color). Horizontal by default; .sf-divider--vertical for inline use.

    -

    Content above the divider.

    -
    -

    Content below the divider.

    -
    - Left - - Right -
    -

    Style modifiers — colour via .sf-divider--soft / .sf-divider--strong, line via .sf-divider--dashed / .sf-divider--dotted, and a fading .sf-divider--gradient.

    -
    -
    -
    -
    -
    - -

    .sf-divide

    -

    Places a rule between direct children in one class — no extra markup per gap. .sf-divide--vertical switches to an inline-start border.

    -
    -

    First

    -

    Second

    -

    Third

    -
    -
    - Left - Middle - Right -
    - -

    .sf-icon

    -

    Em-based inline icon sizing. Scales with surrounding text; size modifiers .sf-icon--xs.sf-icon--2xl.

    -
    - - - - - - -
    - -

    .sf-icon--boxed

    -

    Padded, bordered icon frame. Override --sf-icon-box-bg / -border / -radius per instance. Combine with size modifiers; the visible glyph stays at --sf-icon-size and the frame grows around it.

    -
    - - - -
    - -

    .sf-grid--dense

    -

    Dense auto-flow lets later items backfill earlier gaps. Add .sf-grid--dense to any grid.

    -
    -
    span 2
    -
    a
    -
    b
    -
    span 2
    -
    c
    -
    - -

    .sf-cover modifiers

    -
    -
    - .sf-cover--min -
    -
    min
    -
    -
    -
    - .sf-cover--max -
    -
    max
    -
    -
    -
    - .sf-cover--padding-s / --padding-l -
    -
    pad-s
    -
    -
    -
    - -

    .sf-cluster--no-wrap / .sf-switcher--no-wrap / .sf-switcher--vertical

    -
    -
    - .sf-cluster--no-wrap -
    -
    A
    B
    C
    D
    E
    F
    -
    -
    -
    - .sf-switcher--no-wrap -
    -
    1
    2
    3
    -
    -
    -
    - .sf-switcher--vertical -
    -
    1
    2
    3
    -
    -
    -
    - -

    .sf-grid-cols-1 / Ratio grids

    -

    - .sf-grid-cols-1 is intentionally a single-column grid. Ratio grids (.sf-grid-cols-1-2 etc.) collapse to a single column on narrow widths and switch to two columns at 48em via container queries — the parent must declare container-type: inline-size. -

    -
    -
    - .sf-grid-cols-1 (single column by design) -
    -
    Full width row
    -
    Full width row
    -
    -
    -
    - .sf-grid-cols-1-2 (1fr 2fr) -
    -
    1fr
    -
    2fr
    -
    -
    -
    - .sf-grid-cols-2-1 (2fr 1fr) -
    -
    2fr
    -
    1fr
    -
    -
    -
    - .sf-grid-cols-1-3 (1fr 3fr) -
    -
    1fr
    -
    3fr
    -
    -
    -
    - .sf-grid-cols-3-1 (3fr 1fr) -
    -
    3fr
    -
    1fr
    -
    -
    -
    - -

    .sf-cq — container query scope

    -

    - Establishes an inline-size container context so children can use container queries. -

    -
    - container-type: inline-size -
    - -

    .sf-fluid-cq — container-relative fluid scale

    -

    - Makes the fluid type + space scales interpolate against this box's width - (100cqi) instead of the viewport — so text in a narrow column - scales with the column, not the page. Resize the box to see it. -

    -
    -

    Fluid text tied to this container's width.

    -
    - -

    .sf-equal — fixed N-column grid

    -

    - Column count never collapses — unlike .sf-grid-* which uses container queries. -

    -
    -
    - .sf-equal--2 -
    -
    1
    2
    -
    -
    -
    - .sf-equal--3 -
    -
    1
    2
    3
    -
    -
    -
    - .sf-equal--4 -
    -
    1
    2
    3
    4
    -
    -
    -
    - .sf-equal--6 -
    -
    1
    2
    3
    4
    5
    6
    -
    -
    -
    - -

    .sf-scale-down (motion.css)

    -
    - -
    - -

    .sf-center / .sf-center--intrinsic

    -
    -
    - .sf-center (max 20rem, auto margins) -
    -
    -
    -
    -
    .sf-center--intrinsic (flex column, items centered)
    -
    -
    - -

    .sf-box

    -
    -
    - .sf-box — padding + outline border (no box-model disturbance) -
    -
    - -

    .sf-grid-cols-6 / .sf-grid--xs … .sf-grid--2xl

    -

    - Fixed-column grids (.sf-grid-cols-6) use container queries — wrap in container-type: inline-size. Auto-fill grids (.sf-grid--xs/s/m/l/xl/2xl) use repeat(auto-fill, minmax(min(--sf-grid-min, 100%), 1fr)) — they collapse to fewer columns as the container narrows. On very narrow viewports both will stack to a single column; resize the window to see them respond. -

    -
    -
    - .sf-grid-cols-6 -
    -
    1
    2
    3
    4
    5
    6
    -
    -
    -
    - .sf-grid--xs (min ~10rem) -
    -
    A
    B
    C
    D
    E
    -
    -
    -
    - .sf-grid--s (min ~13rem) -
    -
    A
    B
    C
    D
    -
    -
    -
    - .sf-grid--m (min ~16rem) -
    -
    A
    B
    C
    -
    -
    -
    - .sf-grid--l (min ~20rem) -
    -
    A
    B
    C
    -
    -
    -
    - .sf-grid--xl (min ~24rem) -
    -
    A
    B
    -
    -
    -
    - .sf-grid--2xl (min ~28rem) -
    -
    A
    B
    -
    -
    -
    - -

    .sf-grid-flex — flex alternative for uneven item counts

    -

    - Flexbox-based alternative to .sf-grid for item counts that don't divide evenly. By default the last row's leftover items stretch to fill the row; .sf-grid-flex--center keeps them fixed-width and centered instead. Reuses --sf-grid-min/--sf-grid-gap — same --xs … --2xl scale as .sf-grid. -

    -
    -
    - .sf-grid-flex (default — last row stretches) -
    -
    1
    2
    3
    4
    5
    -
    -
    -
    - .sf-grid-flex--center (leftover fixed-width, centered) -
    -
    1
    2
    3
    4
    5
    -
    -
    -
    - .sf-grid-flex--xs / --s / --m / --l / --xl / --2xl (re-point --sf-grid-min) -
    -
    xs
    xs
    xs
    -
    -
    -
    s
    s
    s
    -
    -
    -
    m
    m
    m
    -
    -
    -
    l
    l
    l
    -
    -
    -
    xl
    xl
    -
    -
    -
    2xl
    2xl
    -
    -
    -
    - -

    .sf-sidebar--narrow / .sf-sidebar--wide

    -
    -
    - .sf-sidebar--narrow (12rem sidebar) -
    -
    Narrow sidebar
    -
    Main content
    -
    -
    -
    - .sf-sidebar--wide (26rem sidebar) -
    -
    Wide sidebar
    -
    Main content
    -
    -
    -
    - -

    .sf-container--full / .sf-container--wide

    -
    -
    - .sf-container--wide (90rem) -
    wide content (90rem)
    -
    -
    - .sf-container--full (100%) -
    full-width content (100%)
    -
    -
    - -

    .sf-section--xs / .sf-section--l / .sf-section--xl / .sf-section--2xl

    -
    -
    - .sf-section--xs (small vertical padding) -
    -
    - .sf-section--l (large vertical padding) -
    -
    - .sf-section--xl (extra-large vertical padding) -
    -
    - .sf-section--2xl (hero vertical padding) -
    -
    - -

    .sf-header--xs / .sf-header--s / .sf-header--m / .sf-header--l / .sf-header--xl

    -

    Block padding on the standard spacing scale — lighter than .sf-section. Inline gutter is left untouched.

    -
    -
    .sf-header--xs
    -
    .sf-header--s
    -
    .sf-header--m
    -
    .sf-header--l
    -
    .sf-header--xl
    -
    - -

    .sf-frame--3-2 / .sf-frame--4-3 / .sf-frame--golden

    -
    -
    - .sf-frame--3-2 -
    - 3 / 2 -
    -
    -
    - .sf-frame--4-3 -
    - 4 / 3 -
    -
    -
    - .sf-frame--golden -
    - golden -
    -
    -
    - -

    .sf-stack alignment: --center / --end / --stretch

    -
    -
    - .sf-stack--s --center -
    -
    A
    -
    B
    -
    C
    -
    -
    -
    - .sf-stack--l --end -
    -
    A
    -
    B
    -
    C
    -
    -
    -
    - .sf-stack--2xl --stretch -
    -
    A
    -
    B
    -
    -
    -
    - override beyond scale: style="--sf-stack-gap: var(--sf-space-3xl)" -
    -
    A
    -
    B
    -
    -
    -
    - -

    .sf-gap — gap size modifiers

    -

    - Injects gap into any existing flex or grid container without imposing a display type. -

    -
    -
    - .sf-gap--xs -
    -
    A
    B
    C
    -
    -
    -
    - .sf-gap--s -
    -
    A
    B
    C
    -
    -
    -
    - .sf-gap--m -
    -
    A
    B
    C
    -
    -
    -
    - .sf-gap--l -
    -
    A
    B
    C
    -
    -
    -
    - .sf-gap--xl -
    -
    A
    B
    C
    -
    -
    -
    - .sf-gap--2xl -
    -
    A
    B
    C
    -
    -
    -
    - -

    .sf-cluster gap modifiers: --xs / --s / --m / --l / --xl / --2xl

    -

    - The size suffix sets the gap between items (not alignment). Compare side by side: -

    -
    -
    - override below scale: style="--sf-cluster-gap: var(--sf-space-2xs)" -
    -
    A
    B
    C
    D
    E
    -
    -
    -
    - .sf-cluster--xs (smallest of the canonical scale) -
    -
    A
    B
    C
    D
    E
    -
    -
    -
    - .sf-cluster--l -
    -
    A
    B
    C
    D
    E
    -
    -
    -
    - .sf-cluster--2xl (largest of the canonical scale) -
    -
    A
    B
    C
    D
    E
    -
    -
    -
    - -

    .sf-cluster alignment: --center / --end / --between

    -

    - These set justify-content. Default is flex-start. -

    -
    -
    - default (flex-start) -
    -
    A
    B
    C
    -
    -
    -
    - .sf-cluster--center -
    -
    A
    B
    C
    -
    -
    -
    - .sf-cluster--end -
    -
    A
    B
    C
    -
    -
    -
    - .sf-cluster--between -
    -
    A
    B
    C
    -
    -
    -
    - -

    .sf-cover--padding-l

    -
    -
    padding-l (4xl)
    -
    - -

    .sf-fade-out

    -

    - The animation ends at opacity: 0 with animation-fill-mode: both, so the target stays hidden after playing. Click the button to (re)apply the animation to the box on its right. -

    -
    - -
    Target — watch me fade
    -
    -
    - - -
    -

    Accessibility

    - -

    Skip Link

    -

    A .skip-link is at the very top of this page. Press Tab from the browser address bar to reveal it — it appears above the header.

    - -

    Focus Ring (accessibility.css)

    -

    Tab through these elements to verify :focus-visible ring (2px solid, 2px offset, action color). The ring uses !important so it's never overridden.

    -
    - - Link - - -
    - Details summary -

    Details content.

    -
    -
    - -

    .sr-only

    -

    Hidden from sighted users but available to screen readers: [THIS TEXT IS SCREEN-READER ONLY — not visible] (check with DevTools or a screen reader)

    - -

    Disabled States

    -
    - - - - -
    - -

    Touch Targets (pointer: coarse)

    -

    On touch devices, a, button, input, select, summary automatically get min-height: var(--sf-touch-target) = var(--sf-size-l) = 2.75rem (≈44px). No extra classes needed.

    - -

    High Contrast & Reduced Transparency

    -

    - prefers-contrast: more → thicker focus ring (3px), thicker <hr>.
    - prefers-reduced-transparency: reduce → backdrop becomes solid.
    - These are handled automatically by accessibility.css. -

    - -

    Color Scheme Token

    -

    - --sf-color-scheme: light dark controls the browser's native UI color adaptation (scrollbars, form controls). Override to only light or only dark to lock the mode at the browser level. - Used by both reset.css and base.css. -

    -
    - - -
    -

    Layout — Stack

    -

    .sf-stack — flex column with uniform gap. Modifier suffix sets gap size.

    - -
    -
    - .sf-stack--xs -
    -
    Item 1
    -
    Item 2
    -
    Item 3
    -
    -
    -
    - .sf-stack--m -
    -
    Item 1
    -
    Item 2
    -
    Item 3
    -
    -
    -
    - .sf-stack--xl -
    -
    Item 1
    -
    Item 2
    -
    Item 3
    -
    -
    -
    -

    Override gap: style="--sf-stack-gap: 2rem"

    -
    - - -
    -

    Layout — Cluster

    -

    .sf-cluster — flex wrapping group with uniform gap. Ideal for tags, buttons, inline groups.

    - -
    -
    Design tokens
    -
    CSS layers
    -
    Layout primitives
    -
    Fluid typography
    -
    Motion
    -
    Accessibility
    -
    Reset
    -
    Base
    -
    -

    Alignment modifiers: --center, --end, --between, --no-wrap

    -
    - - -
    -

    Layout — Sidebar

    -

    .sf-sidebar — first child is sidebar (fixed width), second child grows. Collapses to stack when content width < --sf-sidebar-min-width (50%).

    - -
    -
    Sidebar
    (18rem default)
    -
    Main content — grows to fill available space
    -
    -

    Override: --sf-sidebar-width, --sf-sidebar-min-width. Modifier: .sf-sidebar--right

    -
    - - -
    -

    Layout — Switcher

    -

    .sf-switcher — switches between row and column layout at a container threshold. No media queries.

    - -
    -
    Column A
    -
    Column B
    -
    Column C
    -
    -

    Threshold: --sf-switcher-threshold (default from tokens). Below threshold → stacks vertically.

    -
    - - -
    -

    Layout — Grid

    -

    .sf-grid — auto-fill CSS grid. Responsive without any media queries.

    - -
    -
    1
    -
    2
    -
    3
    -
    4
    -
    5
    -
    6
    -
    7
    -
    -

    Override: --sf-grid-min (min column width), --sf-grid-gap. Modifier: .sf-grid--fit (auto-fit). Fixed columns: .sf-grid-cols-2, .sf-grid-cols-3, .sf-grid-cols-4

    -
    - - -
    -

    Layout — Cover

    -

    .sf-cover — full-height flex column. .sf-cover__center child is vertically centered via margin-block: auto.

    - -
    -

    Top content

    -
    - Vertically centered (.sf-cover__center) -
    -

    Bottom content

    -
    -

    Default --sf-cover-min-height: 100dvh — overridden to 16rem here for demo.

    -
    - - -
    -

    Layout — Frame

    -

    .sf-frame — aspect-ratio container. Media children use object-fit: cover.

    - -
    -
    - sf-frame--video (16:9) -
    - 16 / 9 -
    -
    -
    - sf-frame--square (1:1) -
    - 1 / 1 -
    -
    -
    - sf-frame--portrait (3:4) -
    - 3 / 4 -
    -
    -
    - sf-frame--cinema (21:9) -
    - 21 / 9 -
    -
    -
    -
    - - -
    -

    Layout — Reel

    -

    .sf-reel — horizontal scroll container with scroll-snap-type: x mandatory. Scroll to snap cards.

    - -
    -
    Card 1
    -
    Card 2
    -
    Card 3
    -
    Card 4
    -
    Card 5
    -
    Card 6
    -
    -

    Override: --sf-reel-item-width, --sf-reel-gap, --sf-reel-height

    -
    - - -
    -

    Layout — Prose

    -

    .sf-prose — long-form text rhythm. Adds margin-block-start: var(--sf-prose-paragraph) between children. Restores list styles.

    - -
    -

    Prose Heading

    -

    The .sf-prose class provides automatic vertical rhythm for long-form content. All direct children receive spacing automatically — no extra margin classes needed.

    -

    Lists Are Restored

    -
      -
    • List items get list-style: disc back (reset removes it)
    • -
    • Nested list indentation is preserved
    • -
    • Marker color follows --sf-prose-marker-color (defaults to --sf-color-primary)
    • -
    -
      -
    1. Ordered lists work too
    2. -
    3. Each step is clearly numbered
    4. -
    -
    - A blockquote inside prose gets consistent margin-block spacing from the surrounding paragraphs. -
    -

    Use .sf-not-prose on a child to opt out of prose spacing for that element.

    -
    -
    - - -
    -

    Layout — Container & Section

    -

    .sf-container — centered max-width with horizontal gutters. Declares a named inline-size container sf-layout, so consumers can target it precisely with @container sf-layout (...) in their own CSS. .sf-section adds vertical padding.

    - -
    -
    - sf-container--narrow (38rem) -
    narrow content
    -
    -
    - sf-container--prose (65ch) -
    prose content
    -
    -
    - sf-container (75rem default) -
    default content
    -
    -
    -

    .sf-section modifiers: --xs, --s, --m, --l, --xl, --2xl. Combine: <section class="sf-section--m"><div class="sf-container">

    -
    - - -
    -

    Layout — Bento

    -

    .sf-bento — free-form dense grid. Parent needs container-type: inline-size for responsive column collapse.

    - -
    -
    Wide + tall
    (span 2 col, 2 row)
    -
    1
    -
    2
    -
    Wide (span 2)
    -
    3
    -
    4
    -
    -

    Override: --sf-bento-cols (default 4), --sf-bento-row (row height). Column modifiers: .sf-bento--2, .sf-bento--3, .sf-bento--6. Row modifiers: .sf-bento--row-compact, .sf-bento--row-tall. Child span modifiers: .sf-bento-wide (col span 2), .sf-bento-tall (row span 2), .sf-bento-featured (2×2), .sf-bento-full (full width).

    -
    - -
    wide
    .sf-bento-wide
    -
    normal
    -
    normal
    -
    tall
    .sf-bento-tall
    -
    full width — .sf-bento-full
    -
    -

    Column modifiers below use .sf-bento--2, .sf-bento--3, .sf-bento--6

    -
    - - -
    -

    Layout — Alternate (zigzag)

    -

    .sf-alternate — alternating two-column rows. Below 48em (own container width) it stacks; above, every other row reverses its children. Declares the named container sf-alternate and binds the flip query to that name — so a nested .sf-alternate reacts to its OWN width, not its outer container's.

    - -
    -
    -
    Image / leading column
    -
    - Row 1 -

    Standard order: leading column on the left, text on the right (above 48em).

    -
    -
    -
    -
    Image / leading column
    -
    - Row 2 -

    Even row — children swap order via order: 2 / 1.

    -
    -
    -
    -
    Image / leading column
    -
    - Row 3 -

    Back to standard order.

    -
    -
    -
    - -

    Smoke test — .sf-alternate nested inside .sf-bento

    -

    Phase 4 contract: the inner .sf-alternate's flip query is bound to the sf-alternate name, so it reacts to the bento cell's intrinsic width — not the outer page container. The cell below is wide enough (a span-2 bento cell) to flip into the two-column layout independently of viewport width.

    - -
    -
    -

    Wide cell (span 2) — contains a .sf-alternate

    -
    -
    -
    A1
    -
    Left → right
    -
    -
    -
    B1
    -
    Right → left (flipped)
    -
    -
    -
    -
    Narrow bento cell
    -
    -
    - - -
    -

    Layout — Content Grid

    -

    .sf-content-grid — named column grid. Children default to content column. .sf-breakout spans wider. .sf-full-bleed spans edge-to-edge.

    - -
    -

    Normal content column — max-width: --sf-content-width

    -
    - .sf-breakout — spans --sf-breakout-width -
    -
    - .sf-full-bleed — edge to edge -
    -

    Back to content column.

    -
    -
    - - -
    -

    Layout — Pancake

    -

    .sf-pancake — 3-row grid (auto 1fr auto) for sticky-footer layouts. Default min-height: 100dvh.

    - -
    -
    - Header (auto height) -
    -
    - Main (1fr — grows to fill remaining space) -
    -
    - Footer (auto height — sticks to bottom) -
    -
    -

    This demo is capped at 18rem. In production: min-height: 100dvh on <body>.

    -
    - - -
    -

    Reset & Base

    - -

    Form Elements (reset.css + base.css)

    -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - - - - -
    -
    - - - - - -
    -
    - -

    Table (reset: border-collapse)

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    TokenValueType
    --sf-color-primaryoklch(0.45 0.2 264)Brand
    --sf-text-mclamp(1rem, …, 1.125rem)Typography
    --sf-space-mclamp(1rem, …, 1.5rem)Spacing
    -
    - -

    Selection Color

    -

    Try selecting this text to see --sf-color-selection-bg in action. The highlight color adapts in dark mode.

    - -

    List Reset

    -

    reset.css sets list-style: none on menu, ul, ol. Outside .sf-prose, styles must be applied manually:

    -
      -
    • This list has manually re-applied list-style: disc
    • -
    • Inside .sf-prose, styles are restored automatically
    • -
    - -

    HR & Separator

    -
    -

    Above: standard <hr> with border token. High-contrast mode thickens it automatically.

    - -

    Box Model (reset.css)

    -

    All elements: box-sizing: border-box. Media (img, video, svg): display: block; max-width: 100%. Margins/padding removed globally. scrollbar-gutter: stable prevents layout shift.

    -
    - - -
    -

    Print

    -

    - SLASHED's print stylesheet preserves authored colour by default — open print preview (Cmd/Ctrl + P) to compare. Two opt-in classes adjust the contract: .print-color-exact forces colours when the browser would flatten them, .print-no-color opts back into ink-on-paper. -

    - -

    Default — authored colour survives

    -

    - Highlighted text in <mark> stays yellow in print. - Success-coloured text stays green. - Danger-coloured text stays red. - External links carry their href in parentheses: visit the SLASHED repo. -

    - -

    .no-print — vanishes from print

    -

    - The badge below disappears from printed output: - SCREEN-ONLY -

    - -

    .print-color-exact — force colour preservation

    - - -

    .print-no-color — opt back into ink-on-paper

    - - -

    Manual verification checklist

    -

    Open print preview and confirm each of the following.

    -
      -
    1. <mark> retains its yellow background (the test for F-04).
    2. -
    3. Success, danger and warning text retain their colour.
    4. -
    5. The SCREEN-ONLY badge is absent.
    6. -
    7. The .print-color-exact callout retains its tinted background.
    8. -
    9. The .print-no-color callout has lost its background.
    10. -
    11. The repo link shows its href in parentheses.
    12. -
    13. The Open print preview button below is absent (it carries .no-print).
    14. -
    - -

    - -

    -
    - - -
    -

    Macros

    -

    - Recipes / patterns from core/macros.css. - Macros answer "what does this element do?" — distinct - from layout primitives, which answer "where do my children go?". -

    - -

    .sf-content-auto — skip offscreen rendering

    -

    - Sets content-visibility: auto so the browser skips layout and paint for this - section while it is offscreen on a long page. contain-intrinsic-size (token - --sf-content-intrinsic-size) reserves a placeholder box so the scrollbar - doesn't jump. Unsupported engines render it normally. -

    -
    -

    This block is render-deferred until it nears the viewport. On long product or article - pages, applying it to repeated sections measurably cuts initial render cost.

    -
    - -

    .sf-tabular-nums — column-aligned figures

    -

    - Fixed-width digits (font-variant-numeric: var(--sf-font-numeric)) so numbers - line up in columns — prices, totals, invoices. -

    -
    -
    1,110.00
    -
    98.40
    -
    7,001.99
    -
    - -

    .sf-flow — equal vertical rhythm

    -
    -

    First child has no top margin (only siblings get the rhythm).

    -

    Second child gets margin-block-start: var(--sf-flow-space).

    -

    So does every subsequent child. Override with the token.

    -
    - -

    .sf-truncate — single-line ellipsis

    -
    - This sentence is intentionally too long for the container so the ellipsis - will appear — text-overflow ellipsis on a single line. -
    - -

    .sf-line-clamp-2 / -3 / -N

    -
    -

    - 2 lines: Lorem ipsum dolor sit amet, consectetur adipiscing - elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. - Ut enim ad minim veniam, quis nostrud exercitation. -

    -

    - 3 lines: Lorem ipsum dolor sit amet, consectetur adipiscing - elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. - Ut enim ad minim veniam, quis nostrud exercitation. -

    -

    - 4 lines (via --sf-line-clamp): Lorem ipsum dolor sit amet, - consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et - dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation - ullamco laboris nisi ut aliquip ex ea commodo consequat. -

    -
    - -

    .sf-aspect — generic ratio container

    -
    -
    -
    -
    -
    - -

    .sf-equal-height — children stretch to tallest

    -
    -
    Short.
    -
    Two
    lines.
    -
    Three
    lines
    here.
    -
    - -

    .sf-scroll-shadow — top + bottom mask gradient

    -
    -

    Scroll inside this box.

    -

    The mask gradient fades the top and bottom of the content.

    -

    It's pure CSS — no scroll listener.

    -

    Override --sf-scroll-shadow-size to tune the fade depth.

    -

    Pairs nicely with overflow-y: auto on tables, lists, code blocks.

    -

    Also useful inside cards with overflowing comment threads.

    -

    Keep scrolling — the bottom edge fades the same way.

    -

    Final paragraph for proof.

    -
    - -

    .sf-scroll-snap — vertical scroll-snap container

    -
    -
    Slide A
    -
    Slide B
    -
    Slide C
    -
    - -

    .sf-overflow-fade — end-edge mask

    -
    -
    - tag-one - tag-two - tag-three - tag-four - tag-five -
    -
    - -

    .sf-overflow-fade--* — directional variants

    -
    -
    right: tag-one tag-two tag-three tag-four tag-five
    -
    left: tag-one tag-two tag-three tag-four tag-five
    -
    inline: tag-one tag-two tag-three tag-four tag-five
    -
    top: line one
    line two
    line three
    line four
    line five
    -
    bottom: line one
    line two
    line three
    line four
    line five
    -
    block: line one
    line two
    line three
    line four
    line five
    -
    - -

    .sf-no-tap-highlight — suppress mobile tap overlay

    - - -

    .sf-clickable-parent — full-card click target

    -

    - Automatic mode — one link, no extra attributes. Click anywhere on the card to navigate; - the button remains independently clickable. Tab to the card to see the built-in card-level focus ring - (no separate sf-focus-parent recipe needed). -

    -
    -

    Click anywhere on this card to navigate

    -

    The entire card surface is the click target — heading, body text, list, and padding.

    -
      -
    • Click here too — the whole card is the link
    • -
    - -
    - -

    - Explicit mode — multiple links. Add data-overlay-link to the primary link; - all other links and buttons are lifted above the overlay automatically — no manual z-index work required. -

    - - -

    - Class mode (.sf-clickable-parent__overlay) — alternative to data-overlay-link; resolves nesting fragility when secondary links live at different depths. -

    - - -

    .sf-surface--* — auto-flipped foreground

    -
    -
    primary
    -
    secondary
    -
    tertiary
    -
    action
    -
    neutral
    -
    inverse
    -
    success
    -
    warning
    -
    info
    -
    danger
    -
    - -

    .sf-text-gradient — gradient-clipped text

    -

    Headline gradient

    - -

    .sf-link-external — external-link indicator

    -

    - See the external project - for more — the marker is configurable via --sf-link-external-marker. -

    - -

    .sf-link--subtle / .sf-link--reverse — underline affordance

    -

    The variant classes toggle only the underline line; its geometry comes from base a:link via --sf-link-underline-offset / --sf-link-underline-thickness.

    -

    - A subtle link hides its underline until hover/focus, while a - reverse link is underlined at rest and clears on hover. -

    - -

    .sf-scrim — text-over-image legibility

    -

    Gradient overlay between an image and its text. Direction modifiers .sf-scrim--top / .sf-scrim--bottom, or an even wash with .sf-scrim--full. Retune via --sf-scrim-color / --sf-scrim-direction / --sf-scrim-gradient.

    -
    -
    -
    - Bottom scrim -
    -
    -
    -
    - Top scrim -
    -
    -
    -
    - Full wash + .sf-text-protect -
    -
    -
    - -
    - <img> child -
    -
    -
    -
    - -
    -
    - .sf-scrim__content — wrapped img -
    -
    -
    - -

    .sf-bg-layer — background-layer primitive

    -

    Absolutely-positioned cover layer that sits behind a parent's content. The parent auto-promotes to a positioned stacking context via :has(). Compose under .sf-scrim for background → gradient → content layering.

    -
    -
    -
    - bare .sf-bg-layer div -
    -
    -
    -
    - .sf-bg-layer + .sf-scrim -
    -
    -
    - -

    .sf-overlap / .sf-overlap-host — intentional overlap recipe

    -

    One element pulled up over the next, which reserves clearance for it automatically.

    -
    -
    -
    - .sf-overlap-host — content clears the badge above -
    -
    -

    Directional variants: .sf-overlap--down (pulls into the next element), .sf-overlap--start / .sf-overlap--end (pulls into the inline edge).

    - -

    Macros in action — a composed profile card

    -

    A realistic card built from the overlap recipe: a banner with an avatar overlapping into the body below (.sf-overlap / .sf-overlap-host).

    -
    -
    -
    -
    - Jamie Chen -

    Design Systems Lead

    -
    -
    - -

    .sf-focus-shadow — box-shadow focus ring (opt-in)

    -

    Tab to this link: the focus indicator follows the rounded corner via box-shadow: var(--sf-focus-ring-shadow) instead of the default outline.

    -

    - Focusable pill -

    - -

    .sf-section--collapse — adjacent sections share padding

    -
    -
    -

    Section A — primary surface

    -
    -
    -

    Section B — secondary surface (different bg, but content has half-padding from boundary)

    -
    -
    - -

    .sf-section--guttered — section carries the gutter

    -

    Adds padding-inline: var(--sf-gutter) to the section itself while zeroing it on any nested .sf-container, preventing double-guttering.

    -
    -
    -

    .sf-section--guttered — horizontal padding lives on the section, not the container

    -
    -
    - -

    .sf-entrance--* — scroll-driven entrance

    -

    Animations require animation-timeline: view() support (Chrome 115+, Firefox flag-gated). Refresh and scroll to see effects in supported engines.

    -
    -
    .sf-entrance--fade
    -
    .sf-entrance--fade-up
    -
    .sf-entrance--fade-down
    -
    .sf-entrance--fade-left
    -
    .sf-entrance--fade-right
    -
    .sf-entrance--scale-up
    -
    - -

    .sf-exit--* — scroll-driven exit

    -

    Symmetric counterpart of .sf-entrance--*: fires as the element scrolls out of view. Requires animation-timeline: view() support — engines without it render these statically (no unconditional fade-to-hidden fallback).

    -
    -
    .sf-exit--fade
    -
    .sf-exit--fade-up
    -
    .sf-exit--fade-down
    -
    .sf-exit--fade-left
    -
    .sf-exit--fade-right
    -
    .sf-exit--scale-down
    -
    -
    - -
    -
    - - - - - diff --git a/docs/layout.md b/docs/layout.md index 8c93da0df..75126ec88 100644 --- a/docs/layout.md +++ b/docs/layout.md @@ -5,7 +5,7 @@ SLASHED ships breakpoint-free, container-query-driven layout primitives in the per-instance tokens you can override inline (`style="--sf-stack-gap: …"`). Tokens are declared in `core/tokens.layout.css`. -All primitives are demoed in the [layout coverage page](test-coverage-3-layout.html). +All primitives are exercised live in the [demo](/demo/). ## The primitives diff --git a/docs/llm-guide.md b/docs/llm-guide.md index eaf5b3c0d..a6d42057f 100644 --- a/docs/llm-guide.md +++ b/docs/llm-guide.md @@ -1,6 +1,6 @@ # Slashed Framework — LLM Reference Guide -> Version: **0.7.16** · Tokens: **686** · Prefix: `--sf-` +> Version: **0.7.17** · Tokens: **686** · Prefix: `--sf-` --- diff --git a/docs/motion.md b/docs/motion.md index db85f6464..b8f2b2451 100644 --- a/docs/motion.md +++ b/docs/motion.md @@ -5,7 +5,7 @@ SLASHED ships animation primitives in the `slashed.motion` layer `@media (prefers-reduced-motion: no-preference)` -- users who prefer reduced motion see no animation from the framework. -All animations are demoed in the [macros & states coverage page](test-coverage-4-macros-states.html). +All animations are exercised live in the [demo](/demo/). ## Design principles diff --git a/docs/states.md b/docs/states.md index f23e2cbf1..3ab4ede17 100644 --- a/docs/states.md +++ b/docs/states.md @@ -6,7 +6,7 @@ They live in the `slashed.states` layer, are single-class / low-specificity, and set the **minimum** needed to communicate the state; components layer visuals on top. -All states are exercised in the [macros & states coverage page](test-coverage-4-macros-states.html). +All states are exercised live in the [demo](/demo/). ## Reference diff --git a/docs/test-coverage-1-colors.html b/docs/test-coverage-1-colors.html deleted file mode 100644 index fabc814c9..000000000 --- a/docs/test-coverage-1-colors.html +++ /dev/null @@ -1,448 +0,0 @@ - - - - - - SLASHED Coverage 1 — Colors & Theming - - - - - - - - - Skip to main content - -
    - SLASHED / coverage - - -
    - -
    - - -
    -

    Page 1 — Colors & Theming

    -

    - All colours below are auto-derived from 11 overridden source tokens - (6 brand + 5 status) declared inline. Toggle dark mode to verify the relative-colour - dark derivations. Resize the window to verify fluid behaviour. -

    - -

    Brand resolved colours

    -
    -
    primary
    -
    secondary
    -
    tertiary
    -
    action
    -
    neutral
    -
    base
    -
    -
    - - -
    -

    Per-colour variant ladders

    -

    Each brand/status colour exposes the same functional variant set: superlight · xlight · lighter · (base) · darker · xdark · superdark · hover · active · subtle · muted · tint plus strong for status colours.

    - -

    primary

    -
    -
    superlight
    -
    xlight
    -
    lighter
    -
    base
    -
    darker
    -
    xdark
    -
    superdark
    -
    hover
    -
    active
    -
    subtle
    -
    muted
    -
    tint
    -
    - -

    secondary

    -
    -
    superlight
    -
    xlight
    -
    lighter
    -
    base
    -
    darker
    -
    xdark
    -
    superdark
    -
    hover
    -
    active
    -
    subtle
    -
    muted
    -
    tint
    -
    - -

    tertiary

    -
    -
    superlight
    -
    xlight
    -
    lighter
    -
    base
    -
    darker
    -
    xdark
    -
    superdark
    -
    hover
    -
    active
    -
    subtle
    -
    muted
    -
    tint
    -
    - -

    action

    -
    -
    superlight
    -
    xlight
    -
    lighter
    -
    base
    -
    darker
    -
    xdark
    -
    superdark
    -
    hover
    -
    active
    -
    subtle
    -
    muted
    -
    tint
    -
    - -

    neutral

    -
    -
    superlight
    -
    xlight
    -
    lighter
    -
    base
    -
    darker
    -
    xdark
    -
    superdark
    -
    hover
    -
    active
    -
    subtle
    -
    muted
    -
    tint
    -
    - -

    base

    -
    -
    50
    -
    200
    -
    400
    -
    base
    -
    600
    -
    800
    -
    950
    -
    hover
    -
    active
    -
    subtle
    -
    muted
    -
    tint
    -
    -
    - - -
    -

    Status colours

    -

    Resolved + strong + on-colour

    -
    -
    success
    -
    warning
    -
    danger
    -
    info
    -
    danger
    -
    - -

    Status triplets — subtle bg / strong text / muted border

    -
    -
    Success
    -
    Warning
    -
    Danger
    -
    Info
    -
    Danger
    -
    - -
    - - -
    -

    Semantic surfaces & text

    -

    Surfaces

    -
    -
    bg
    -
    surface
    -
    inset
    -
    raised
    -
    overlay
    -
    inverse
    -
    dim
    -
    - -

    Interaction backgrounds

    -
    -
    bg--hover
    -
    bg--active
    -
    bg--focus
    -
    bg--selected
    -
    bg--disabled
    -
    - -

    Text hierarchy

    -
    -

    --sf-color-text (primary)

    -

    --sf-color-text--secondary

    -

    --sf-color-text--muted

    -

    --sf-color-text--placeholder

    -

    --sf-color-text--disabled

    -

    --sf-color-heading

    -
    - -

    On-colour text (auto black/white for WCAG)

    -
    -
    on-primary
    -
    on-secondary
    -
    on-tertiary
    -
    on-action
    -
    on-neutral
    -
    on-success
    -
    on-warning
    -
    on-danger
    -
    on-info
    -
    on-inverse
    -
    - -

    Borders

    -
    -
    --sf-color-border
    -
    --sf-color-border--subtle
    -
    --sf-color-border--strong
    -
    --sf-color-border--focus
    -
    --sf-color-border--disabled
    -
    --sf-color-border--translucent
    -
    - -

    Link / code / mark / selection

    -
    - --sf-color-link - link--hover - link--visited - link--active - link--disabled - inline code (--sf-color-code-bg / -text) - mark (--sf-color-mark-bg) - selection sample -
    -
    - - -
    -

    Palette numeric & alpha scales (core/tokens.css)

    - -

    primary 50–950

    -
    -
    50
    -
    100
    -
    200
    -
    300
    -
    400
    -
    500
    -
    600
    -
    700
    -
    800
    -
    900
    -
    950
    -
    - -

    primary alpha a5–a80 (over a checker)

    -
    -
    a5
    -
    a10
    -
    a30
    -
    a50
    -
    a80
    -
    - -

    secondary / tertiary / action / neutral / base — 500 & key steps

    -
    -
    sec 500
    -
    sec 200
    -
    ter 500
    -
    ter 200
    -
    act 500
    -
    act a50
    -
    neu 700
    -
    neu 100
    -
    base 100
    -
    base 900
    -
    -
    - - -
    -

    Gradients

    -
    -
    primary
    -
    secondary
    -
    tertiary
    -
    brand
    -
    surface
    -
    -

    Fade gradients (t / b / l / r)

    -
    -
    fade--t
    -
    fade--b
    -
    fade--l
    -
    fade--r
    -
    -
    - - -
    -

    Scoped themes — nested data-theme

    -

    Each region re-declares mode-sensitive tokens, so colours/text/borders switch per section.

    - -
    -

    data-theme="dark"

    -
    -
    primary
    -
    action
    -
    surface
    -
    -
    -
    Success
    -
    Danger
    -
    - -
    -

    data-theme="light" nested in dark

    -
    -
    primary
    -
    action
    -
    surface
    -
    -
    -
    - -

    Contrast bias knob

    -
    -
    bias 0
    -
    bias 0.05
    -
    -
    - -
    - - - - diff --git a/docs/test-coverage-2-typography.html b/docs/test-coverage-2-typography.html deleted file mode 100644 index 1ac99d6ca..000000000 --- a/docs/test-coverage-2-typography.html +++ /dev/null @@ -1,438 +0,0 @@ - - - - - - SLASHED Coverage 2 — Typography & Tokens - - - - - - - - Skip to main content - -
    - SLASHED / coverage - - -
    - -
    - - -
    -

    Page 2 — Typography & design tokens

    - -

    Heading elements (base.css h1–h6)

    -
    -

    h1 — The quick brown fox

    -

    h2 — The quick brown fox

    -

    h3 — The quick brown fox

    -

    h4 — The quick brown fox

    -
    h5 — The quick brown fox
    -
    h6 — The quick brown fox
    -
    - -

    Fluid text scale (--sf-text-*) — resize to see clamp()

    -
    -
    2xs — The quick brown fox jumps over the lazy dog
    -
    xs — The quick brown fox jumps over the lazy dog
    -
    s — The quick brown fox jumps
    -
    m (base) — The quick brown fox
    -
    l — The quick brown fox
    -
    xl — The quick brown
    -
    2xl — The quick
    -
    3xl — Quick
    -
    4xl
    -
    display-s
    -
    display-m
    -
    display-l
    -
    - -

    Font weights 300–700

    -
    - 300 light - 400 normal - 500 medium - 600 semibold - 700 bold -
    - -

    Semantic weight aliases

    -
    - body - heading - display -
    - -

    Font stacks

    -
    - body — The quick brown fox jumps - heading — The quick brown fox jumps - display — The quick brown fox jumps - humanist — The quick brown fox jumps - geometric — The quick brown fox jumps - slab — The quick brown fox jumps - mono — The quick brown fox jumps -
    - -

    Line heights (--sf-leading-*)

    -
    -
    - tight (1.1) -

    Lorem ipsum dolor sit amet consectetur adipiscing elit sed do.

    -
    -
    - snug (1.3) -

    Lorem ipsum dolor sit amet consectetur adipiscing elit sed do.

    -
    -
    - normal (1.5) -

    Lorem ipsum dolor sit amet consectetur adipiscing elit sed do.

    -
    -
    - relaxed (1.625) -

    Lorem ipsum dolor sit amet consectetur adipiscing elit sed do.

    -
    -
    - -

    Letter spacing (--sf-tracking-*)

    -
    -
    tracking-tight — THE QUICK BROWN FOX
    -
    tracking-normal — THE QUICK BROWN FOX
    -
    tracking-wide — THE QUICK BROWN
    -
    tracking-wider — THE QUICK
    -
    tracking-widest — QUICK
    -
    - -

    Semantic inline elements + pre

    -

    - strong, em, mark, code, - Ctrl + C, CSS, - H2O, E=mc2, small, - link, deleted, inserted -

    -
    :root {
    -  --sf-color-primary-light: oklch(0.55 0.22 160);
    -}
    -
    - A blockquote — select this text to verify selection colour. -
    -
    - - -
    -

    Spacing scale

    -

    Fluid tokens use clamp() — resize to animate.

    -
    -
    --sf-space-none
    -
    --sf-space-px
    -
    --sf-space-2xs
    -
    --sf-space-xs
    -
    --sf-space-s
    -
    --sf-space-m
    -
    --sf-space-l
    -
    --sf-space-xl
    -
    --sf-space-2xl
    -
    --sf-space-3xl
    -
    --sf-space-4xl
    -
    --sf-gutter
    -
    --sf-gap
    -
    --sf-content-gap
    -
    --sf-gap
    -
    --sf-content-gap
    -
    --sf-component-pad
    -
    --sf-field-block
    -
    - -

    Sizes (--sf-size-*) & touch target

    -
    -
    -
    -
    -
    -
    -
    -
    -
    - - -
    -

    Shadows

    -
    -
    none
    -
    xs
    -
    s
    -
    m
    -
    l
    -
    xl
    -
    2xl
    -
    inner
    -
    glow
    -
    - -

    Text shadows

    -
    - none - s - m - l -
    - -

    Drop shadows (filter)

    -
    - - - -
    -
    - - -
    -

    Border radius

    -
    -
    none
    0
    -
    xs
    2px
    -
    s
    4px
    -
    m
    8px
    -
    l
    12px
    -
    xl
    16px
    -
    2xl
    24px
    -
    3xl
    32px
    -
    4xl
    48px
    -
    full
    -
    pill
    -
    outer
    -
    -
    - - -
    -

    Border widths & styles, strokes

    -
    -
    width-hairline (0.5px)
    -
    width-1 (1px)
    -
    width-2 (2px)
    -
    width-3 (3px)
    -
    width-4 (4px)
    -
    -

    Border styles & composed border tokens

    -
    -
    --sf-border-style (solid)
    -
    dotted (keyword)
    -
    dashed (keyword)
    -
    --sf-border
    -
    --sf-border-strong
    -
    --sf-border-subtle
    -
    -

    SVG stroke widths (inline — set stroke-width directly)

    -
    - - - - -
    -
    - - -
    -

    Blur & opacity

    -

    Backdrop / filter blur

    -
    -
    --sf-blur
    -
    blur(24px)
    -
    -

    Opacity tokens

    -
    -
    -
    -
    -
    - - -
    -

    Motion tokens (durations, easings, transitions)

    -

    Hover a row to trigger the transition; the easing/duration token is named on the left.

    - -

    Durations (hover to move)

    -
    -
    duration-instant
    -
    duration-fast
    -
    duration-normal
    -
    duration-slow
    -
    duration-slower
    -
    - -

    Easings (hover to move)

    -
    -
    ease-linear
    -
    ease-in
    -
    ease-out
    -
    ease-in-out
    -
    ease-spring
    -
    ease-elastic
    -
    ease-bounce
    -
    ease-overshoot
    -
    - -

    Transition tokens (hover the card)

    -
    -
    form-field
    -
    colors
    -
    transform
    -
    opacity
    -
    shadow
    -
    fast
    -
    slow
    -
    enter
    -
    exit
    -
    -
    - - -
    -

    Z-index, perspective & ratios

    - -

    Z-index ladder

    -
    - below - base - raised - low - mid - high - top - max -
    - -

    Perspective (near / normal / far)

    -
    -
    -
    -
    -
    - -

    Aspect ratios

    -
    -
    square
    -
    3:2
    -
    4:3
    -
    16:9
    -
    21:9
    -
    golden
    -
    3:4
    -
    -
    - -
    - - - - - - diff --git a/docs/test-coverage-3-layout.html b/docs/test-coverage-3-layout.html deleted file mode 100644 index 14e8abe07..000000000 --- a/docs/test-coverage-3-layout.html +++ /dev/null @@ -1,418 +0,0 @@ - - - - - - SLASHED Coverage 3 — Layout primitives - - - - - - - - Skip to main content - -
    - SLASHED / coverage - - -
    - -
    - - -
    -

    Page 3 — Layout primitives

    -

    Stack — gap sizes & alignment

    -
    -
    xs
    xs
    -
    s
    s
    -
    m
    m
    -
    l
    l
    -
    xl
    xl
    -
    2xl
    2xl
    -
    -
    -
    center
    center
    -
    end
    end
    -
    stretch
    stretch
    -
    -
    - - -
    -

    Cluster

    -

    Gap sizes

    -
    -
    xs
    xs
    xs
    -
    s
    s
    s
    -
    m
    m
    m
    -
    l
    l
    l
    -
    xl
    xl
    xl
    -
    2xl
    2xl
    2xl
    -
    -

    Justify modifiers

    -
    -
    center
    center
    -
    end
    end
    -
    between
    between
    -
    no-wrap
    no-wrap
    no-wrap
    -
    -
    - - -
    -

    Sidebar

    -
    -
    sidebar (default 18rem)
    main
    -
    --narrow
    main
    -
    --wide
    main
    -
    main
    --right sidebar
    -
    -
    - - -
    -

    Switcher

    -
    -
    A
    B
    C
    -
    no-wrap A
    B
    C
    -
    vertical A
    B
    -
    -
    - - -
    -

    Grid — auto-fill min-width tiers

    -
    -
    .sf-grid--xs
    1
    2
    3
    4
    5
    -
    .sf-grid--s
    1
    2
    3
    4
    -
    .sf-grid--m (default)
    1
    2
    3
    -
    .sf-grid--l
    1
    2
    3
    -
    .sf-grid--xl
    1
    2
    -
    .sf-grid--2xl
    1
    2
    -
    .sf-grid--fit
    1
    2
    3
    -
    .sf-grid--dense
    wide
    2
    3
    4
    -
    - -

    Fixed-column grids

    -
    -
    .sf-grid-cols-1
    1
    -
    .sf-grid-cols-2
    1
    2
    -
    .sf-grid-cols-3
    1
    2
    3
    -
    .sf-grid-cols-4
    1
    2
    3
    4
    -
    .sf-grid-cols-6
    1
    2
    3
    4
    5
    6
    -
    - -

    Ratio grids

    -
    -
    .sf-grid-cols-1-2
    1
    2
    -
    .sf-grid-cols-2-1
    2
    1
    -
    .sf-grid-cols-1-3
    1
    3
    -
    .sf-grid-cols-3-1
    3
    1
    -
    - -

    Subgrid

    -
    -
    -
    subgrid child
    -
    -
    subgrid-rows
    -
    plain
    -
    -
    - - -
    -

    Equal — never-collapsing fixed columns

    -
    -
    .sf-equal--2
    1
    2
    -
    .sf-equal--3
    1
    2
    3
    -
    .sf-equal--4
    1
    2
    3
    4
    -
    .sf-equal--6
    1
    2
    3
    4
    5
    6
    -
    -
    - - -
    -

    Gap — display-agnostic gap injection

    -
    -
    xs
    xs
    xs
    -
    s
    s
    s
    -
    m
    m
    m
    -
    l
    l
    l
    -
    xl
    xl
    xl
    -
    2xl
    2xl
    2xl
    -
    -
    - - -
    -

    Container, center & box

    -
    -
    .sf-container--narrow (38rem)
    narrow
    -
    .sf-container--prose (65ch)
    prose
    -
    .sf-container (75rem)
    default
    -
    .sf-container--wide (90rem)
    wide
    -
    .sf-container--full (100%)
    full
    -
    -

    Center

    -
    .sf-center
    -
    .sf-center--intrinsic
    -

    Box

    -
    .sf-box — padded, outlined unit
    -
    - - -
    -

    Section padding scale & groups

    -
    -
    .sf-section--xs
    -
    .sf-section--s
    -
    .sf-section--m
    -
    .sf-section--l
    -
    .sf-section--xl
    -
    .sf-section--2xl
    -
    -

    Section group (collapsed gaps) + collapse modifier

    -
    -
    group section A
    -
    group section B (--collapse)
    -
    -
    - - -
    -

    Cover

    -
    -
    -

    top

    -
    --padding-s · center
    -

    bottom

    -
    -
    -

    top

    -
    --padding-l · center
    -

    bottom

    -
    -
    -
    -
    --min
    -
    --max
    -
    -
    - - -
    -

    Frame — aspect-ratio media boxes

    -
    -
    video 16:9
    -
    square
    -
    portrait
    -
    3:2
    -
    4:3
    -
    cinema 21:9
    -
    golden
    -
    -
    - - -
    -

    Reel — horizontal scroll-snap strip

    -
    -
    Card 1
    -
    Card 2
    -
    Card 3
    -
    Card 4
    -
    Card 5
    -
    -
    - - -
    -

    Bento

    -
    -
    wide+tall
    -
    1
    -
    2
    -
    wide
    -
    3
    -
    -

    Modifiers

    -
    -
    .sf-bento--2
    1
    2
    3
    4
    -
    .sf-bento--3
    1
    2
    3
    4
    -
    .sf-bento--6
    1
    2
    3
    4
    5
    6
    -
    .sf-bento--row-compact
    1
    2
    3
    -
    .sf-bento--row-tall
    1
    2
    3
    -
    .sf-bento-wide
    wide
    2
    3
    -
    .sf-bento-tall
    tall
    2
    3
    4
    -
    .sf-bento-featured
    2
    3
    4
    5
    -
    .sf-bento-full
    full
    2
    3
    -
    -
    - - -
    -

    Alternate — zigzag rows

    -
    -
    Row 1 lead
    Row 1

    standard order

    -
    Row 2 lead
    Row 2

    flipped

    -
    Row 3 lead
    Row 3

    standard

    -
    -
    - - -
    -

    Content grid — breakout / full-bleed

    -
    -

    Normal content column.

    -
    .sf-breakout — wider span
    -
    .sf-full-bleed — edge to edge
    -

    Back to content column.

    -
    -
    - - -
    -

    Pancake — sticky-footer grid

    -
    -
    Header
    -
    Main (1fr)
    -
    Footer
    -
    -
    - - -
    -

    Imposter — absolute centred overlay

    -
    -
    -
    .sf-imposter
    -
    -
    -
    --contain
    -
    -
    -

    A .sf-imposter--fixed element is positioned relative to the viewport:

    -
    fixed imposter
    -
    - - -
    -

    Divider

    -
    -
    default
    -
    soft
    -
    strong
    -
    dashed
    -
    dotted
    -
    gradient
    -
    verticalafter
    -
    -
    - - -
    -

    Icon sizing

    -
    - - - - - - - -
    -

    Inline icon scales with font-size: Text inline

    -
    - -
    - - - - diff --git a/docs/test-coverage-4-macros-states.html b/docs/test-coverage-4-macros-states.html deleted file mode 100644 index 85e08823d..000000000 --- a/docs/test-coverage-4-macros-states.html +++ /dev/null @@ -1,397 +0,0 @@ - - - - - - SLASHED Coverage 4 — Macros, States, A11y, Motion - - - - - - - - Skip to main content - -
    - SLASHED / coverage - - -
    - -
    - - -
    -

    Page 4 — Macros: surfaces

    -
    -
    surface--primary
    -
    surface--secondary
    -
    surface--tertiary
    -
    surface--action
    -
    surface--neutral
    -
    surface--inverse
    -
    surface--success
    -
    surface--warning
    -
    surface--danger
    -
    surface--info
    -
    -
    - - -
    -

    Text & link macros

    - -

    sf-text-gradient

    -

    Gradient headline

    - -

    sf-text-protect (over photo)

    -
    -

    Protected text

    -
    - -

    sf-truncate / line-clamp

    -

    This is a very long single line that will be truncated with an ellipsis once it overflows its inline size box.

    -

    Two-line clamp. Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua ut enim.

    -

    Three-line clamp. Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua ut enim ad minim veniam quis nostrud exercitation.

    -

    Four-line clamp (--sf-line-clamp: 4). Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua ut enim ad minim veniam quis nostrud exercitation ullamco laboris.

    - -

    Links

    - - -

    sf-tabular-nums

    - - - - - - -
    Item A1,234.50
    Item B9,876.10
    Item C42.00
    - -

    sf-no-tap-highlight

    - Tap me on mobile (no grey highlight) -
    - - -
    -

    Prose, flow & not-prose

    -
    -

    Prose heading

    -

    Automatic vertical rhythm for long-form content. Direct children get spacing automatically.

    -
    • Restored bullets
    • Nested indentation preserved
    -
    1. Ordered too
    2. Numbered steps
    -
    A blockquote inside prose gets consistent spacing.
    -
    - .sf-not-prose — opts this widget out of prose rules. -
    -

    Back to prose body.

    -
    - -

    sf-flow (lobotomized owl)

    -
    -

    First (no top margin)

    -

    Second (gets flow-space)

    -

    Third (gets flow-space)

    -
    -
    - - -
    -

    Scroll, overflow & aspect macros

    - -

    sf-scroll-shadow (vertical)

    -
    -

    Scroll this box. Fade masks appear at top and bottom edges.

    -

    Line 2

    Line 3

    Line 4

    Line 5

    Line 6

    Line 7 (bottom)

    -
    - -

    sf-scroll-snap (vertical)

    -
    -
    Snap A
    -
    Snap B
    -
    Snap C
    -
    - -

    sf-overflow-fade (horizontal)

    -
    - tag one - tag two - tag three - tag four - tag five - tag six (overflows) -
    - -

    sf-aspect & sf-equal-height

    -
    -
    4 / 3 aspect
    -
    -
    Short
    -
    Two
    lines
    -
    Three
    lines
    here
    -
    -
    - -

    sf-content-auto

    -
    -

    This section uses content-visibility: auto to skip offscreen rendering.

    -
    -
    - - -
    -

    Scrim variants

    -
    -
    -

    --bottom

    -
    -
    -

    --top

    -
    -
    -

    --full

    -
    -
    -
    - - -
    -

    State classes (.sf-is-*)

    -
    -
    sf-is-active
    -
    sf-is-selected
    -
    sf-is-current
    - -
    sf-is-highlighted
    -
    sf-is-disabled
    -
    sf-is-readonly
    -
    sf-is-loading
    -
    sf-is-pending
    -
    sf-is-busy
    -
    sf-is-skeleton
    -
    sf-is-valid
    -
    sf-is-invalid
    -
    sf-is-success
    - -
    sf-is-warning
    -
    sf-is-info
    -
    sf-is-danger
    -
    sf-is-expanded
    -
    sf-is-open
    -
    sf-is-collapsed
    -
    sf-is-clickable
    -
    sf-is-unselectable
    -
    sf-is-draggable
    -
    sf-is-dragging
    -
    sf-is-drop-target
    -
    sf-is-resizable
    -
    sf-is-truncated with overflowing long content here
    -
    sf-is-focused
    -
    - -

    Visibility / layout states

    -
    -
    before sf-is-hidden after
    -
    before sf-is-invisible after
    -
    before sf-is-visible after
    -
    sf-is-clipped overflow content that is hidden beyond the box edges here
    -
    sf-is-scrollable
    line
    line
    line
    line
    -
    -
    -

    Positioning helpers: .sf-sticky and .sf-overlay are demonstrated below.

    -
    -
    sf-sticky (scroll me)
    -
    scroll content…
    -
    -
    - sf-overlay -
    -
    - - -
    -

    Accessibility helpers

    - -

    sf-focus-parent (rings when a child is focused)

    -
    - Container · · -
    - -

    sf-clickable-parent (whole card clickable via child link)

    -
    - Card title — entire card is the click target -
    - -

    sf-focus-shadow (box-shadow focus ring on rounded element)

    - - -

    sr-only-focusable

    -

    The skip link at the very top of the page uses .sr-only-focusable — Tab from the address bar to reveal it.

    - -

    .no-motion subtree

    -
    -
    animation suppressed by .no-motion ancestor
    -
    -
    - - -
    -

    Motion — entrance, loop & special

    -

    All motion is gated behind prefers-reduced-motion: no-preference.

    - -

    Entrance animations

    -
    -
    entrance--fade
    -
    entrance--fade-up
    -
    entrance--fade-down
    -
    entrance--fade-left
    -
    entrance--fade-right
    -
    entrance--scale-up
    -
    - -

    Staggered with delay tokens

    -
    -
    delay-1
    -
    delay-2
    -
    delay-3
    -
    delay-4
    -
    delay-5
    -
    - -

    Loop / one-shot animations

    -
    -
    fade-in
    -
    fade-out
    -
    scale-up
    -
    scale-down
    -
    slide-in-up
    -
    slide-in-down
    -
    slide-in-left
    -
    slide-in-right
    -
    - -

    sf-color-pulse (animates primary lightness via @property)

    -
    color-pulse
    - -

    Named animation tokens applied directly

    -
    -
    animation-spin
    -
    animation-ping
    -
    animation-float
    -
    animation-shimmer
    -
    animation-blink
    -
    -
    - -
    - - - - diff --git a/docs/test-coverage-5-forms-features.html b/docs/test-coverage-5-forms-features.html deleted file mode 100644 index 665d10a60..000000000 --- a/docs/test-coverage-5-forms-features.html +++ /dev/null @@ -1,281 +0,0 @@ - - - - - - SLASHED Coverage 5 — Forms & Features - - - - - - - - Skip to main content - -
    - SLASHED / coverage - - -
    - -
    - - -
    -

    Page 5 — Classless forms (optional/forms.css)

    -
    -
    - - - - - - - - - - - - - - -
    - - - - - -
    - Checkbox & radio (accent-color) - - - - -
    - - - - - -

    Validation states (border + --sf-field-text-color hook)

    -
    Field accepted
    -
    Please correct this
    -
    Something went wrong
    -
    Double-check this
    -
    Saved
    -
    For your information
    - -
    - - - - -
    - - - -
    -
    - - -
    -

    Feature — container queries

    -

    Drag the resize handle (bottom-right) to change the container width and watch the box react — no media queries.

    -
    Container-responsive box
    -
    - - -
    -

    Feature — scroll-driven entrances

    -

    In engines that support animation-timeline: view() these animate as they scroll into view; elsewhere they fall back to a one-shot time animation.

    -
    -
    Scroll-revealed block A
    -
    Scroll-revealed block B
    -
    Scroll-revealed block C
    -
    -
    - - -
    -

    Feature — modern colour functions

    -

    light-dark()

    -
    Background flips with mode via light-dark()
    -

    Relative colour syntax (oklch from)

    -
    -
    base
    -
    l +0.15
    -
    h +60
    -
    -

    color-mix()

    -
    -
    75/25 primary↔tertiary
    -
    50/50
    -
    25/75
    -
    -
    - - -
    -

    Feature — selection & scrollbar styling

    -

    Select this paragraph to see ::selection using --sf-color-selection-bg. The framework also sets --sf-scrollbar-thumb / --sf-scrollbar-track.

    -
    -

    Scrollable region — note the themed scrollbar.

    -

    tall content…

    -
    -
    - - -
    -

    Feature — focus ring tokens

    -

    Tab through these to see --sf-focus-ring-* (color/width/offset/style) and the box-shadow ring variant.

    -
    - - Link focus ring - -
    -
    - - -
    -

    Feature — cascade layers & @property

    -

    Framework declares layer order: slashed.reset, slashed.tokens, slashed.base, slashed.themes, slashed.layout, slashed.components, slashed.macros, slashed.states, slashed.motion, slashed.accessibility, slashed.forms, slashed.utilities, slashed.overrides. Registered @property custom properties (e.g. --sf-is-dark, --sf-is-active) drive interpolation and conditional logic.

    -
    Registered boolean flags: --sf-is-dark, --sf-is-open, --sf-is-active, --sf-is-pressed, --sf-is-current
    -
    - - -
    -

    Remaining token groups

    - -

    Per-heading tokens (h1–h6 size/weight/tracking/leading)

    -
    - h1 tokens - h2 tokens - h3 tokens - h4 tokens - h5 tokens - h6 tokens -
    - -

    Layout tokens overridden inline

    -
    cluster-gap override2xl
    -
    stack-gap → space-3xlbig gap
    - -

    Macro tokens overridden inline

    -
    -

    --sf-scroll-shadow-size: 3rem

    -

    tall…

    -
    - -

    Header height & sticky offset tokens

    -
    --sf-header-height, --sf-header-height-mobile/-desktop, --sf-sticky-offset drive the sticky header on every page.
    -
    - - -
    -

    Feature — print

    -

    Use the browser Print Preview (Ctrl/Cmd+P) to verify the slashed.print layer: optimized page margins (--sf-print-page-margin), base size (--sf-print-base-size), and external-link URL expansion.

    -

    This is an external link — in print, its URL is appended after the text.

    -
    - - -
    -

    Feature — high contrast & reduced motion

    -

    Enable OS "increase contrast" to see --sf-contrast-bias auto-raise and borders thicken. Enable "reduce motion" to see all animations on page 4 go inert.

    -
    Bordered element — thickens under prefers-contrast: more.
    -
    - -
    - - - - diff --git a/docs/test-coverage-6-token-reference.html b/docs/test-coverage-6-token-reference.html deleted file mode 100644 index 515f2b8b4..000000000 --- a/docs/test-coverage-6-token-reference.html +++ /dev/null @@ -1,157 +0,0 @@ - - - - - - SLASHED Coverage 6 — Full token reference - - - - - - - - Skip to main content - -
    - SLASHED / coverage - - -
    - -
    -
    -

    Full token reference — tokens

    -

    Every --sf-* token resolved live via getComputedStyle. Colour-valued tokens show a swatch; toggle dark mode to verify auto-derivation across modes. Filter by name below.

    - -
    -
    -
    - - - - diff --git a/docs/test-coverage.html b/docs/test-coverage.html deleted file mode 100644 index 03e70fd4a..000000000 --- a/docs/test-coverage.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - SLASHED — Coverage suite - - - - - - - -
    -
    - SLASHED / coverage suite -

    - Manual visual-coverage pages exercising every framework feature against - the published slashed.full.css bundle. Each page is a - standalone document with its own page-scoped token overrides, so they - are kept as separate files and linked from here. -

    -

    - The automated coverage guarantee lives in tests/ (Playwright) - against docs/demo.html; these pages are for manual review. -

    -
    - - -
    - - diff --git a/docs/test-cq-dark-light.html b/docs/test-cq-dark-light.html deleted file mode 100644 index 8e200e19d..000000000 --- a/docs/test-cq-dark-light.html +++ /dev/null @@ -1,659 +0,0 @@ - - - - - - SLASHED — CQ Layout + Dark/Light Test - - - - - -
    - -
    -

    SLASHED — CQ Layout + Dark/Light Tests

    - -
    -

    - Each CQ layout is shown at three explicit widths (384 px / 608 px / 800 px) inside - container-type: inline-size wrappers. Font-size is pinned to 16 px so - 30 em = 480 px and 48 em = 768 px are stable. The alternate layout is self-sizing - (named container). Toggle theme to verify dark/light token switching. -

    - - -
    -

    Bento — container-query responsive

    -

    - .sf-bento uses unnamed @container queries - so it reads its ancestor container's width.
    - • ≤29.99em → 1 col  •  30–47.99em → 2 cols  •  ≥48em → default 4 cols -

    - -

    Default 4-col bento at 3 widths

    -

    - JS ✓/✗ badges use gridTemplateColumns to count explicit columns. - Plain children only (no sf-bento-wide) to avoid implicit track noise. -

    -
    -
    -

    384 px (24 rem) → expect 1 col

    -
    -
    A
    -
    B
    -
    C
    -
    D
    -
    -
    -
    -

    608 px (38 rem) → expect 2 cols

    -
    -
    A
    -
    B
    -
    C
    -
    D
    -
    -
    -
    -

    800 px (50 rem) → expect 4 cols

    -
    -
    A
    -
    B
    -
    C
    -
    D
    -
    -
    -
    - -

    Bento column modifiers (.sf-bento--2 / --3 / --6)

    -
    -
    -

    24 rem → all collapse to 1 col (CQ override)

    -
    -
    -

    --2

    -
    -
    A
    B
    -
    C
    D
    -
    -
    -
    -

    --3

    -
    -
    A
    B
    -
    C
    -
    -
    -
    -

    --6

    -
    -
    A
    B
    -
    C
    D
    -
    E
    F
    -
    -
    -
    -
    -
    -

    38 rem → all forced to 2 col by CQ

    -
    -
    -

    --2

    -
    -
    A
    B
    -
    C
    D
    -
    -
    -
    -

    --3

    -
    -
    A
    B
    -
    C
    -
    -
    -
    -

    --6

    -
    -
    A
    B
    -
    C
    D
    -
    E
    F
    -
    -
    -
    -
    -
    -

    full width → each uses its own col count

    -
    -
    -

    --2

    -
    -
    A
    B
    -
    C
    D
    -
    -
    -
    -

    --3

    -
    -
    A
    B
    -
    C
    -
    -
    -
    -

    --6

    -
    -
    A
    B
    -
    C
    D
    -
    E
    F
    -
    -
    -
    -
    -
    - -

    Bento child span modifiers (.sf-bento-wide / tall / featured / full)

    -
    -
    - -
    wide (2 col)
    -
    C
    -
    tall
    (2 row)
    -
    E
    -
    full width
    -
    G
    -
    H
    -
    -
    -
    - - -
    -

    Fixed-column grids — container-query responsive

    -

    - .sf-grid-cols-2/3/4/6 use unnamed @container - queries — same ancestor-width rule as bento.
    - • ≥30em: 4-col→2col, 6-col→3col  •  ≥48em: full target columns -

    - -
    -
    -

    24 rem → all single-column (below 30em)

    -
    -

    sf-grid-cols-2

    -
    -
    1
    2
    -
    -
    -

    sf-grid-cols-3

    -
    -
    1
    2
    3
    -
    -
    -

    sf-grid-cols-4

    -
    -
    1
    2
    -
    3
    4
    -
    -
    -

    sf-grid-cols-6

    -
    -
    1
    2
    -
    3
    4
    -
    5
    6
    -
    -
    -
    -
    -
    -

    38 rem → 4-col→2 cols, 6-col→3 cols (30–48em range)

    -
    -

    sf-grid-cols-2 (still 1 col — breaks at 48em)

    -
    -
    1
    2
    -
    -
    -

    sf-grid-cols-3 (still 1 col — breaks at 48em)

    -
    -
    1
    2
    3
    -
    -
    -

    sf-grid-cols-4 → 2 cols

    -
    -
    1
    2
    -
    3
    4
    -
    -
    -

    sf-grid-cols-6 → 3 cols

    -
    -
    1
    2
    -
    3
    4
    -
    5
    6
    -
    -
    -
    -
    -
    -

    full width → all at target column count

    -
    -

    sf-grid-cols-2 → 2 cols

    -
    -
    1
    2
    -
    -
    -

    sf-grid-cols-3 → 3 cols

    -
    -
    1
    2
    3
    -
    -
    -

    sf-grid-cols-4 → 4 cols

    -
    -
    1
    2
    -
    3
    4
    -
    -
    -

    sf-grid-cols-6 → 6 cols

    -
    -
    1
    2
    -
    3
    4
    -
    5
    6
    -
    -
    -
    -
    -
    - -

    Ratio grids (1-2, 2-1, 1-3, 3-1) — also use unnamed @container

    -
    -
    -

    24 rem → all single-column (below 48em)

    -
    -
    1
    2
    -
    2
    1
    -
    1
    3
    -
    3
    1
    -
    -
    -
    -

    38 rem → still single-column (below 48em)

    -
    -
    1
    2
    -
    2
    1
    -
    1
    3
    -
    3
    1
    -
    -
    -
    -

    full width → two-column with correct ratios

    -
    -
    1 (narrow)
    2 (wide)
    -
    2 (wide)
    1 (narrow)
    -
    1 (narrow)
    3 (wide)
    -
    3 (wide)
    1 (narrow)
    -
    -
    -
    -
    - - -
    -

    Alternate (zigzag) — self-sizing via named container

    -

    - .sf-alternate uses @container sf-alternate (min-width: 48em) - — a named query so it responds to its OWN inline-size, no ancestor needed.
    - • Below 48em → stacked (single column per row)  •  ≥48em → 2 cols, even rows reversed -

    - -
    -
    -

    24 rem → single-column (stacked)

    -
    -
    -
    Row 1 — image
    -
    Row 1
    normal order
    -
    -
    -
    Row 2 — image
    -
    Row 2
    would flip ≥48em
    -
    -
    -
    Row 3 — image
    -
    Row 3
    normal order
    -
    -
    -
    -
    -

    38 rem → still stacked (below 48em)

    -
    -
    -
    Row 1 — image
    -
    Row 1
    normal order
    -
    -
    -
    Row 2 — image
    -
    Row 2
    would flip ≥48em
    -
    -
    -
    Row 3 — image
    -
    Row 3
    normal order
    -
    -
    -
    -
    -

    full width → 2-col zigzag; even rows (2nd) flip image right

    -
    -
    -
    Row 1 — image (LEFT)
    -
    Row 1 — text
    image leads (order:0)
    -
    -
    -
    Row 2 — image (RIGHT)
    -
    Row 2 — text
    text leads, image flipped right
    -
    -
    -
    Row 3 — image (LEFT)
    -
    Row 3 — text
    image leads again
    -
    -
    -
    -
    - -

    Alternate nested inside narrow bento cell — CQ isolation check

    -

    - Outer container is narrow (24rem). Bento creates its named sf-bento - context. The alternate inside should still query its OWN width (also 24rem here), - so it should stay stacked — not get confused by the bento's container context. -

    -
    -
    -
    Bento A
    -
    Bento B
    -
    -
    -
    -
    Alternate image
    -
    Row 1 — should be stacked in 24rem
    -
    -
    -
    Alternate image 2
    -
    Row 2 — should not flip
    -
    -
    -
    -
    -
    -
    - - -
    -

    Dark / Light nesting — multi-level

    -

    - Each [data-theme] block auto-resets its own background and text color. - Swatches show resolved token values — they must visually differ between light and dark zones. -

    - - -
    -

    data-theme="light" (level 1)

    -
    - --sf-color-bg - --sf-color-surface - --sf-color-primary - text-secondary - border -
    -

    - Text is var(--sf-color-text). Should be dark on a light background. -

    - - -
    -

    data-theme="dark" (level 2)

    -
    - --sf-color-bg - --sf-color-surface - --sf-color-primary - text-secondary - border -
    -

    - Should be dark background, light text. Primary should be lighter/brighter. -

    - - -
    -

    data-theme="light" (level 3 — inside dark)

    -
    - --sf-color-bg - --sf-color-surface - --sf-color-primary - text-secondary - border -
    -

    - Should revert to light theme. Same visual as level 1. -

    - - -
    -

    no data-theme (level 4 — inherits level 3 light)

    -
    - --sf-color-bg - --sf-color-surface - --sf-color-primary - text-secondary -
    -

    - No theme set — should inherit light from parent. - Background is transparent so the parent's bg shows through. -

    -
    - - -
    -

    data-theme="dark" (level 4 — nested dark inside light)

    -
    - --sf-color-bg - --sf-color-surface - --sf-color-primary - text-secondary -
    -

    - Should be dark again. 4 levels deep — dark/light/light/dark. -

    -
    -
    - - -
    -

    no data-theme (level 3 — inherits level 2 dark)

    -
    - --sf-color-bg - --sf-color-surface - --sf-color-primary - text-secondary -
    -

    - No theme set — should look dark (inherits L2). -

    -
    -
    - - -
    -

    data-theme="dark" (level 2, sibling — isolated from sibling above)

    -
    - --sf-color-bg - --sf-color-surface - --sf-color-primary -
    -

    - Sibling dark block — should also be dark, independent of the previous block. -

    -
    -
    - -

    sf-is-active / sf-is-current state flags inside dark and light

    -
    -
    -

    light

    - -
    -
    -

    dark

    - -
    -
    -
    - -
    - - - - diff --git a/index.html b/index.html index f671f9372..3f2bccbde 100644 --- a/index.html +++ b/index.html @@ -455,7 +455,7 @@ diff --git a/reports/full-api-audit/REPORT.md b/reports/full-api-audit/REPORT.md deleted file mode 100644 index 9875f8cd5..000000000 --- a/reports/full-api-audit/REPORT.md +++ /dev/null @@ -1,194 +0,0 @@ - - -# SLASHED Full-API Testing Operation — Report - -**Framework:** SLASHED v0.6.25 · **Date:** 2026-06-30 -**Surface tested:** 685 tokens + 239 classes (924 API elements) -**Method:** local build (`npm run build`) + configurator dev server, driven with -Playwright/Chromium; computed values diffed against the source-of-truth oracle -`docs/api-index.json`. Harness scripts live alongside this report in -`reports/full-api-audit/` and are re-runnable. - ---- - -## 1. Executive summary - -| Ground | Scope | Result | -|--------|-------|--------| -| **1 — Correctness** (demos + framework) | 685 tokens, 239 classes, 225 knobs, dark mode, visuals | **PASS** — no framework functional defects. 3 demo-packaging polish findings (F1, F2, F4), all low/medium. | -| **2 — Configurator fidelity** | control coverage + live override + preview reflection | **PASS** — every editable knob reachable and overridable; previews reflect changes; 59/59 configurator unit+component tests green. | - -**Headline numbers** - -- Tokens: **685/685** rendered, **0** console errors, **677/685** resolve at `:root` (the 8 "empty" are fully explained below — none is a framework bug). Demo's displayed value matched the independently-read computed value for **685/685** tokens (0 misreports). Aliases: **0** mismatches. Dark mode re-resolves **266** tokens. -- Classes: **239/239** rendered, **238/239** ship in the loaded bundle, **69/69** behavioural contracts pass, **0** console errors. -- Override wiring (overrides demo): **202/202** perturbed knobs move; the **23** non-perturbed knobs exactly equal the **23** documented skips (0 undocumented); **460/460** consumption tokens recompute downstream. -- Configurator: **224/224** editable PUBLIC knobs reachable as controls; **8/8** power knobs (`knobs-report.json`) and **5/5** sampled generic rows (`configurator-report.json`) inject overrides *and* update the live preview; preset + reset work (`preset-reset-report.json`); **59/59** configurator unit+component tests pass (`results/configurator-unit-tests.txt`). - -**Verdict:** The two demo pages are accurate, faithful reflections of the -framework, and the framework itself behaves correctly. The configurator -correctly implements the full token surface and every control overrides the -live preview as intended. Findings are limited to demo-packaging polish (F1, F2, F4). - ---- - -## 2. Ground 1 — correctness - -### 2.1 Tokens (`check-tokens.mjs`) - -All 685 tokens render with a live value tile; the demo's `getComputedStyle` -readout matches an independent read for every token (no misreporting). 266 -tokens change under `data-theme="dark"`, confirming the dark-mode engine. - -**The 8 tokens that read empty at `:root`:** - -| Tokens | Why | Classification | -|--------|-----|----------------| -| `--sf-btn-radius`, `--sf-btn-padding-block`, `--sf-btn-padding-inline`, `--sf-field-radius`, `--sf-field-padding-block`, `--sf-field-padding-inline` | Defined in `optional/tokens.components.css`, which the **`optimal`** bundle (loaded by both demos) excludes. They resolve correctly under `full`/`optimal-components` (`var(--sf-radius-m)`, `var(--sf-space-xs)`). | **F1 — demo** (bundle choice). Framework correct. | -| `--sf-color-mark-text`, `--sf-color-selection-text` | Declared `inherit` (fallback-only hooks consumed as `var(--token, MarkText)`); `inherit` resolves empty at `:root` per CSS rules but works contextually. They *do* take a value in the overrides demo, proving wiring. | **F2 — demo** cosmetic. Framework correct. | - -The 2 reported "literal default mismatches" (`--sf-radius-none`, `--sf-space-none`: -declared `0`, computed `0px`) are `@property ` normalization — **not defects**. - -### 2.2 Classes (`check-classes.mjs`) - -239/239 class tiles render. 238/239 selectors are present in the loaded bundle; -the one exception, `theme-transition`, is an example-only class -(`bundles: []`, from `optional/theme-example.css`) — see **F4**. 69 classes -have a strong behavioural contract (state classes, layout displays, a11y); all -**69/69 pass** (e.g. `.is-hidden`→`display:none`, `.sf-grid`→`display:grid`, -`.is-disabled`→`pointer-events:none`+opacity, `.is-truncated`→ellipsis, -`.sr-only`→clipped 1px). Bento *item* span modifiers (`sf-bento-wide` etc.) -correctly compute `display:block` (their effect is grid-span inside a parent). - -### 2.3 Override-wiring proof (`diff-overrides.mjs`) - -Diffing the baseline vs the always-on overrides demo: - -| Check | Result | -|-------|--------| -| Perturbed knobs that moved | **202 / 202** | -| Knobs not perturbed vs documented skips | **23 = 23** (0 undocumented, 0 mismatched) | -| Consumption tokens that recomputed | **460 / 460** | -| Tokens unchanged | 29 = 23 skips + 6 component tokens (F1) | -| Console errors (both demos) | 0 | - -Every configurable token is wired end-to-end; the 23 skips (z-index ladder, -runtime state flags, `env()` insets, sentinel `none`s) are deliberate and -documented in `ultimate-override.css`. - -### 2.4 Visual - -Baseline and overrides demos render as intended (screenshots: -`baseline-desktop.png`, `overrides-desktop.png`; the harness also captures -tablet/mobile widths, omitted here for size). Color ramps, -semantic colors, spacing and type scales are correct; the overrides demo shows -the dramatic, coherent re-skin (serif type, red palette, enlarged scales, -dashed borders) that proves the cascade. - ---- - -## 3. Ground 2 — configurator fidelity - -### 3.1 Coverage (`probe-panels.mjs` + configurator test suite) - -- `catalogue-projection`, `smoke`, `curation` tests pass → the configurator's - `api-index.generated.json` matches the framework (no drift), all 685 tokens - present, every PUBLIC knob has a domain pattern (no orphans). -- **224/224 editable PUBLIC knobs** are reachable as controls. The only knob - not exposed is the **INTERNAL** `--sf-is-dark` (correctly hidden — "do not - override"). 49 derived/alias consumption tokens are intentionally not - individually editable (they recompute from knobs). -- 641 tokens are additionally browsable/editable as generic rows. - -### 3.2 Override application (`check-knobs.mjs`, `check-configurator.mjs`, `check-preset-reset.mjs`) - -Mechanism: a control's `onChange` → `overrides` state → an `$effect` writes the -override CSS into `