The real src/ layout this proof-of-concept (POC) compiles from: global layers by concern, variables split by type, a small function + mixin toolkit, and a four-file-per-component convention. "Dual" means one SCSS source compiles to two outputs — shadow-DOM web components and plain CSS classes. Every path, function, mixin, and variable group below is read from the POC source — nothing invented.
src/global/ holds the framework layers; src/components/ holds one folder per component. Each concern owns a folder with an _index.scss "barrel" — an index file that re-exports (@forwards) the folder's partials (the underscore-prefixed _*.scss files).
src/
├── config.yaml # build config: namespace, variablePrefix, modes,
│ # tokenSubset, cssCompiled.{…}, presets.{…}
├── global/
│ ├── variables/ # CSS-variable layer (emits --dual-*)
│ │ ├── _index.scss # barrel + $font-size emit loop (per family)
│ │ ├── _reference.scss # reference-tier bridge
│ │ ├── _color.scss # semantic color vars + theme mode blocks
│ │ ├── _spacing.scss # spacing, content-measure + fluid $size scales
│ │ ├── _typography.scss # $font-size map (display/title/body/intro/quote/topline)
│ │ ├── _viewport-regular.scss# per-breakpoint @media var overrides
│ │ ├── _styles.scss # effect/style composites
│ │ └── generated/ # compiled from tokens/ by compile-tokens-scss.mjs
│ │ ├── _reference.generated.scss
│ │ └── _effects.generated.scss
│ ├── functions/ # ref, get, at, cssvar, dual-space, px-to-rem
│ │ ├── _index.scss
│ │ └── _functions.scss
│ ├── mixins/ # type, theme, surface, border, pad, stack, media, color
│ │ ├── _index.scss
│ │ ├── _typography.scss # type() + blockquote()/intro()/topline()
│ │ ├── _media.scss # above()/below() + theme()
│ │ ├── _spacing.scss # pad()/pad-x()/stack()
│ │ └── _color.scss # surface()/border()
│ ├── base/ # opinionated globals (reset + element type)
│ │ ├── _index.scss
│ │ ├── _reset.scss # minimal box-model reset
│ │ └── _typography.scss # h1–h6/p/blockquote/small element styles
│ ├── utilities/ # u-* single-purpose classes
│ │ ├── _index.scss
│ │ ├── _display.scss _flexbox.scss _spacing.scss
│ │ ├── _sizing.scss _text.scss _color.scss
│ └── grid/ # layout system
│ ├── _index.scss # barrel + layout decision-tree guidance
│ ├── _flex-grid.scss # .FlexGrid gap grid
│ ├── _css-grid.scss # .CssGrid 12-col / autoFit / bento
│ └── _primitives.scss # 10 Every-Layout primitives
└── components/ # one folder per component (4 files each)
├── _index.scss
├── button/ card/ checkbox/ dropdown/ radio/ text-field/
The variable layer is partitioned by type (color, spacing, typography, viewport, styles), not by component. Each partial emits its slice of the --dual-* custom-property set; _index.scss forwards them and runs the per-family typography emit loop. The compiled layer carries 322 distinct --dual-* declarations across 5 theme modes + per-breakpoint @media.
| Partial | Emits |
|---|---|
_color.scss | semantic color vars (--dual-base-*, --dual-text-*, --dual-ui-*, --dual-action-*, --dual-border-*) + the .dual-theme-{dark,sand,wireframe,dark-brand} mode blocks |
_spacing.scss | --dual-gap-* / --dual-pad-*, the content-measure --dual-size-content-* + fluid --dual-size-fluid-* scales, and --dual-spacing (the dual-space() base) |
_typography.scss | the $font-size map (groups: display / title / body / intro / quote / topline) consumed by type(); emitted per family (sans + slab) |
_viewport-regular.scss | per-breakpoint @media overrides (vpXS…vpXXL) for the responsive var tier |
_styles.scss + generated/_effects.generated.scss | effect/style composites (--dual-effect-*) |
_reference.scss + generated/_reference.generated.scss | reference-tier bridge — the reference tier is the raw palette layer (see Token Architecture); compiled from tokens/reference/ by compile-tokens-scss.mjs. Reference aliases are resolved at build time, so they never ship in dist. |
Six functions in functions/_functions.scss. The first four resolve tokens/vars; the last two are unit helpers. All fail loud on bad input rather than emitting a wrong value.
| Function | Purpose |
|---|---|
ref($path) | resolve a reference-tier (raw palette) token alias to its value |
get($map, $key) | safe map lookup (errors on a missing key) |
at($map, $path...) | nested map lookup by path |
cssvar($name) | compose a var(--dual-…) reference with the live prefix |
dual-space($n) | spacing multiplier — calc(var(--dual-spacing) * $n) (the layout escape hatch) |
px-to-rem($px) | unit-aware px→rem against a documented base |
Mixins compose vars into declarations so components and base styles never hand-write var(--dual-…) chains. Grouped by concern across the mixins/ partials.
type($family,$group,$size,$weight,$italic) | the parameterized composite type mixin (allow-list @error validated) |
blockquote() · intro() · topline() | block-level type mixins built on type() |
pad($n) · pad-x($n) | padding via the spacing scale |
stack($n) | vertical spacing between stacked siblings (the * + * "owl" selector) |
above($bp) · below($bp) | desktop-first max-width / min-width queries |
theme($mode) | emits BOTH .dual-theme-* and [data-dual-theme] selectors for a mode |
surface($level) | background + text pairing for a surface level |
border($side) | token-bound border shorthand |
Every component is a folder of four files with a fixed naming pattern. Component tokens are color-only; dimensions/typography/spacing bind semantic vars directly.
| File | Role |
|---|---|
<name>.variables.scss | the component's own color tokens, e.g. --dual-button-fill, --dual-button-content, --dual-button-fill-hover, --dual-button-focus, --dual-button-border-color — a consumer override surface |
<name>.styles.scss | the @mixin styles($namespace) — one source that compiles to shadow-DOM ($namespace: '') OR light-DOM (.Dual-Button) |
<name>.template.html | the markup template the web-component build wraps |
<name>.index.scss | the component barrel forwarding variables + styles |
The six POC components: button, card, checkbox, dropdown, radio, text-field.
Each concern's _index.scss barrel forwards its partials; build-css.mjs @uses the barrels per cssCompiled section. You don't run these scripts by hand — this is the build order the POC uses to turn tokens into CSS:
tokens/reference/*.json → compile-tokens-scss.mjs → src/global/variables/generated/*.scss → build-css.mjs @use 'variables/index' → dist/css/variables.css (RESOLVED --dual-*) → regenerate-split-tokens.mjs reads it → tokens/semantic/*.json (spec mirror)
See Token Architecture for the token pipeline, Output Architecture for the dual shadow/light compile, and CSS Overview for the whole POC.