# PARITY.md: DSSL vs CSS, honestly
The point of this table is to stop two bad arguments: "DSSL is missing everything" and
"DSSL replaces all of CSS". Both are false. Here is the ledger. Status: shipped / partial
/ planned / by-design-no.
| CSS feature | In DSSL | Status | Notes |
|---|---|---|---|
| Type / class / id / attribute selectors | native (rides browser matching) | shipped | |
| Combinators (`>`, `+`, `~`, descendant) | native | shipped | |
| Nesting | native, `&` substitution | shipped | predates CSS nesting; no build step needed |
| `:nth-child()`, `:nth-of-type()`, `:not()`, `:is()`, `:where()`, `:has()` | native | shipped | the browser does the matching; v0.7 docs say so loudly |
| Pseudo-classes (`:hover`, `:focus`...) | engine-native states as nested blocks | shipped | real events, enter + leave, descendants re-evaluated; `seen` (first viewport entry) has no CSS equivalent |
| Pseudo-elements | one compiled shadow stylesheet | shipped | the ONE place DSSL emits real CSS; inline styles cannot reach them |
| `@media` queries | `@media (max-width: 860)`, sugar: `dark`, `light`, `reduced-motion`, bare widths, `<=` ranges | shipped | |
| `@container` queries | `@container (min-width: 480)` | shipped | nearest ancestor (or self) with container-type |
| `@layer` cascade layers | `@layer base\|components\|utilities` + `pin {}` | shipped | cascade is (layer, source order); no specificity, no !important |
| `@supports` | `raw { }` passes it through verbatim | partial | no sugar; the engine feature-detects itself, and `dssl import` moves it into `raw { }` |
| `@font-face` | `raw { }` passes it through verbatim (semicolons required inside) | partial | `font.*` tokens can name any loaded family; a missing `;` in `raw` is a warning with a line number |
| `@keyframes` | `motion name { from {} to {} }` via WAAPI | shipped | `animate: name 600 ease-out infinite alternate` |
| View transitions | not implemented | planned | |
| Scroll-driven animations | not implemented | planned | pairs naturally with `seen` + `stagger` |
| Custom properties (`--*`) | pass through unvalidated, plus dotted token re-declaration per subtree | shipped | `--color.accent: color.err` re-themes a subtree via inheritance |
| Design tokens | first-class: `tokens { }`, numeric keys, alpha suffix `/85`, scoped per file and subtree | shipped | no CSS-native equivalent at this ergonomics level |
| Flexbox / Grid | raw properties pass through + `row:` `column:` `grid:` `stack:` sugar | shipped | shorthands write `display`; the compiler warns when that clobbers an explicit `display:` |
| `place-items` / alignment | `center: both` | shipped | the engine promotes a formatting context when missing, so alignment cannot silently no-op |
| Transitions | per-property: `transition: 200 snap transform` | shipped | honors `reduced-motion` |
| Background patterns and noise | `texture:` (40 presets including ten wood species, 11 generators, your own) | shipped | there is no CSS shorthand for "grain on top of my background"; this one keeps the author's background and removes cleanly. Runtime-only |
| Glow, particles, fire | `aura-glow`, `aura-particle`, `glow-particle`, `aura-glow-particle`, `aura:` | shipped | CSS has `box-shadow` and `filter: drop-shadow`, and nothing for particles. No presets by design. Runtime-only |
| Styling `` | `slider:` writes the `::-webkit-slider-*` and `::-moz-range-*` rules together | shipped | Chrome tested; the Firefox rules are generated but not run yet. Histogram sliders via `graph` |
| Accessibility hints in the compiler | contrast, removed focus outline, small targets (warnings) | shipped | CSS says nothing; these never fail a build unless you pass `--strict` |
| Moving existing CSS over | `dssl import styles.css` | shipped | converts the mechanical differences and reports the rest; the output always compiles |
| print styles (`@media print`) | not implemented | planned | |
| `!important` | by design no | by-design-no | `pin { }` is the must-win block; specificity wars are the thing DSSL deletes |
| Cascade | (layer, source order) | shipped | later wins; identical selectors resolve by order, deterministically |
| Static extraction / view-source styling | `dssl build` emits real CSS (v0.8.0); prerender snapshot for live pages planned | partially shipped | freeze() already makes big static pages zero-cost after first paint |
| DevTools story | `DSSL.explain(el)` returns the cascade as data | shipped | matched rules with file/line, winning declaration per property, pseudo rules; browser-extension panel planned |
| Work without JavaScript | `dssl build` emits the static subset as real CSS (v0.8.0); `@signal`/`animate:` stay runtime-only and counted | shipped for the static subset; prerender snapshot still planned for live pages | the honest trade has an exit now |
## The exit story
Abandoning DSSL leaves you: a DOM of valid inline styles, one small `