{"_id":"@embyth/scss-design-system","_rev":"3-d07e0a0741a2c82a44a2ea169c7395f0","name":"@embyth/scss-design-system","dist-tags":{"latest":"1.0.1"},"versions":{"0.1.0":{"name":"@embyth/scss-design-system","version":"0.1.0","author":{"url":"https://github.com/embyth","name":"Rostyslav Miniukov","email":"miniukovrostyslav@gmail.com"},"license":"MIT","_id":"@embyth/scss-design-system@0.1.0","maintainers":[{"name":"embyth","email":"thresh1337@gmail.com"}],"homepage":"https://github.com/embyth/scss-design-system#readme","bugs":{"url":"https://github.com/embyth/scss-design-system/issues"},"dist":{"shasum":"a2801a17a91ce583e4eb6d162227c123abb6ddf5","tarball":"https://registry.npmjs.org/@embyth/scss-design-system/-/scss-design-system-0.1.0.tgz","fileCount":116,"integrity":"sha512-OnlFo3bu83qbRgxEOcv6JJLSj18K8bKrMpeWAjnnPXcPoh41gw5G4Ud6VaM4re9tmq3LtgZSG1H4YTpshe94lg==","signatures":[{"sig":"MEUCIFFAZ3YOVSQ8AhdZOALsjjs+SNucEL2F8NTFjDKOoY9cAiEA6n80PGVyv8F6BrvR7kWya61evLz+CRCcU8o3Kf/hG0A=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":116549},"main":"src/index.scss","_from":"file:embyth-scss-design-system-0.1.0.tgz","style":"src/index.scss","engines":{"node":">=18.15.0","pnpm":">=8.1.0"},"scripts":{"lint":"pnpm exec stylelint \"src/**/*.scss\" --config .stylelintrc","test":"jest","clean":"pnpm run clean:cache && pnpm run clean:deps","lint:fix":"pnpm exec stylelint \"src/**/*.scss\" --config .stylelintrc --fix","react:dev":"pnpm -F react-ts dev","clean:deps":"rimraf node_modules","react:lint":"pnpm -F react-ts lint","clean:cache":"rimraf dist","react:build":"pnpm -F react-ts build"},"_npmUser":{"name":"embyth","email":"thresh1337@gmail.com"},"_resolved":"/tmp/16e0715fc98a978e8633bb5963c7ef8d/embyth-scss-design-system-0.1.0.tgz","_integrity":"sha512-OnlFo3bu83qbRgxEOcv6JJLSj18K8bKrMpeWAjnnPXcPoh41gw5G4Ud6VaM4re9tmq3LtgZSG1H4YTpshe94lg==","repository":{"url":"git+https://github.com/embyth/scss-design-system.git","type":"git"},"_npmVersion":"9.6.7","description":"Simple Design System template built on SCSS","directories":{},"_nodeVersion":"18.17.0","dependencies":{"normalize.css":"8.0.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"29.6.2","sass":"1.66.1","husky":"8.0.3","rimraf":"5.0.1","devmoji":"2.3.0","sass-true":"7.0.0","stylelint":"15.7.0","@commitlint/cli":"17.6.5","@embyth/stylelint-config":"0.1.1","@commitlint/config-conventional":"17.6.5","jest-environment-node-single-context":"29.1.0"},"peerDependencies":{"sass":"1.66.1"},"_npmOperationalInternal":{"tmp":"tmp/scss-design-system_0.1.0_1692530528870_0.7216698326273665","host":"s3://npm-registry-packages"}},"0.2.0":{"name":"@embyth/scss-design-system","version":"0.2.0","author":{"url":"https://github.com/embyth","name":"Rostyslav Miniukov","email":"miniukovrostyslav@gmail.com"},"license":"MIT","_id":"@embyth/scss-design-system@0.2.0","maintainers":[{"name":"embyth","email":"thresh1337@gmail.com"}],"homepage":"https://github.com/embyth/scss-design-system#readme","bugs":{"url":"https://github.com/embyth/scss-design-system/issues"},"dist":{"shasum":"b17853d84261f04e2f688f4e105b777d3701ddcc","tarball":"https://registry.npmjs.org/@embyth/scss-design-system/-/scss-design-system-0.2.0.tgz","fileCount":198,"integrity":"sha512-h+Lkk5u9gFq+mU62mNT+tqkHjNx3fc58hFAKjbz5SEnQqvng4d+5F3WyVkfcso0PRtLT4rF2XC2/4vx5eECAJg==","signatures":[{"sig":"MEUCIDHXDwVFmn6GnGp0Xkq0tGKb+WdTvQ6m0oDtXpx7h6Y1AiEAznUwrlywdX5ppA7tE6zXZEDQogWZsqw0G/kXfcQR2t8=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":2813845},"main":"src/index.scss","_from":"file:embyth-scss-design-system-0.2.0.tgz","style":"src/index.scss","engines":{"node":">=18.15.0","pnpm":">=8.1.0"},"scripts":{"lint":"pnpm exec stylelint \"{test,src}/**/*.scss\" --config .stylelintrc","test":"jest","clean":"pnpm run clean:cache && pnpm run clean:deps","lint:fix":"pnpm exec stylelint \"{test,src}/**/*.scss\" --config .stylelintrc --fix","react:dev":"pnpm -F react-ts dev","clean:deps":"rimraf node_modules","react:lint":"pnpm -F react-ts lint","clean:cache":"rimraf dist","react:build":"pnpm -F react-ts build"},"_npmUser":{"name":"embyth","email":"thresh1337@gmail.com"},"_resolved":"/tmp/2d882475f5fabb1f0891268c3a5b6860/embyth-scss-design-system-0.2.0.tgz","_integrity":"sha512-h+Lkk5u9gFq+mU62mNT+tqkHjNx3fc58hFAKjbz5SEnQqvng4d+5F3WyVkfcso0PRtLT4rF2XC2/4vx5eECAJg==","repository":{"url":"git+https://github.com/embyth/scss-design-system.git","type":"git"},"_npmVersion":"9.6.7","description":"Simple Design System template built on SCSS","directories":{},"_nodeVersion":"18.17.1","dependencies":{"normalize.css":"8.0.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"29.6.4","sass":"1.66.1","husky":"8.0.3","rimraf":"5.0.1","devmoji":"2.3.0","prettier":"3.0.3","sass-true":"7.0.0","stylelint":"15.10.3","@commitlint/cli":"17.7.1","@embyth/prettier-config":"1.0.0","@embyth/stylelint-config":"0.3.0","@commitlint/config-conventional":"17.7.0","jest-environment-node-single-context":"29.1.0"},"peerDependencies":{"sass":"1.66.1"},"_npmOperationalInternal":{"tmp":"tmp/scss-design-system_0.2.0_1694206803257_0.1224082970113396","host":"s3://npm-registry-packages"}},"1.0.1":{"name":"@embyth/scss-design-system","version":"1.0.1","type":"module","publishConfig":{"access":"public"},"description":"Simple Design System template built on SCSS","author":{"name":"Rostyslav Miniukov","email":"miniukovrostyslav@gmail.com","url":"https://github.com/embyth"},"license":"MIT","homepage":"https://github.com/embyth/scss-design-system#readme","repository":{"type":"git","url":"git+https://github.com/embyth/scss-design-system.git"},"bugs":{"url":"https://github.com/embyth/scss-design-system/issues"},"main":"src/index.scss","style":"src/index.scss","sass":"src/index.scss","exports":{".":{"sass":"./src/index.scss","style":"./src/index.scss","default":"./src/index.scss"}},"sideEffects":["*.scss"],"engines":{"node":">=22.0.0","pnpm":">=10.0.0"},"packageManager":"pnpm@10.34.3","scripts":{"react:dev":"pnpm -F react-ts dev","react:build":"pnpm -F react-ts build","react:lint":"pnpm -F react-ts lint","vanilla:dev":"pnpm -F vanilla dev","vanilla:build":"pnpm -F vanilla build","vanilla:lint":"pnpm -F vanilla lint","vue:dev":"pnpm -F vue-ts dev","vue:build":"pnpm -F vue-ts build","clean:cache":"rimraf dist","clean:deps":"rimraf node_modules","clean":"pnpm run clean:cache && pnpm run clean:deps","lint":"pnpm exec stylelint \"{test,src}/**/*.scss\" --config .stylelintrc","lint:fix":"pnpm exec stylelint \"{test,src}/**/*.scss\" --config .stylelintrc --fix","format":"prettier --check .","format:fix":"prettier --write .","test":"vitest run","test:watch":"vitest","prepublishOnly":"publint","prepare":"husky"},"devDependencies":{"@commitlint/cli":"21.0.2","@commitlint/config-conventional":"21.0.2","@embyth/prettier-config":"1.1.1","@embyth/stylelint-config":"0.7.1","devmoji":"2.3.0","husky":"9.1.7","prettier":"3.8.4","publint":"0.3.21","rimraf":"6.1.3","sass":"1.101.0","sass-true":"10.1.0","stylelint":"17.13.0","vitest":"4.1.9"},"peerDependencies":{"sass":">=1.80.0 <3.0.0"},"gitHead":"0e368217ba0da969cf1e2d5e0502e011b1ca60d6","_id":"@embyth/scss-design-system@1.0.1","_nodeVersion":"24.16.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-NJU2pdECj1UXc/CqEYDwgr6DvYfGPHqtIxmQ1GZFsVhiGxj9KlHZlwIu5WVPnxKPk0XHNwsz04j28323ze4QKw==","shasum":"2d94d56bd477f982bf63a5976b5085e1c8b006dc","tarball":"https://registry.npmjs.org/@embyth/scss-design-system/-/scss-design-system-1.0.1.tgz","fileCount":70,"unpackedSize":137633,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@embyth%2fscss-design-system@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHL6jSdqHadEuYJVZpqnRyjBL/p5E1JXPrnuGRqVD5/NAiBdJZH4eoG4JeumtwJtTcGUPiW1MA/aiRfSXWGKDavoXA=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:76ae5148-1b43-417a-a38b-156fb55c870f"}},"directories":{},"maintainers":[{"name":"embyth","email":"thresh1337@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/scss-design-system_1.0.1_1781524004487_0.19395658688481632"},"_hasShrinkwrap":false}},"time":{"created":"2023-08-20T11:22:08.764Z","modified":"2026-06-15T11:46:44.923Z","0.1.0":"2023-08-20T11:22:09.101Z","0.2.0":"2023-09-08T21:00:03.594Z","1.0.1":"2026-06-15T11:46:44.622Z"},"bugs":{"url":"https://github.com/embyth/scss-design-system/issues"},"author":{"name":"Rostyslav Miniukov","email":"miniukovrostyslav@gmail.com","url":"https://github.com/embyth"},"license":"MIT","homepage":"https://github.com/embyth/scss-design-system#readme","repository":{"type":"git","url":"git+https://github.com/embyth/scss-design-system.git"},"description":"Simple Design System template built on SCSS","maintainers":[{"name":"embyth","email":"thresh1337@gmail.com"}],"readme":"# :lipstick: `@embyth/scss-design-system`\n\n> A self-contained Sass design system: two-tier OKLCH color tokens, cascade layers, dark mode, fluid typography,\n> container queries and a rich mixin library — all pure SCSS, zero runtime.\n\n[![npm version](https://img.shields.io/npm/v/@embyth/scss-design-system)](https://www.npmjs.com/package/@embyth/scss-design-system)\n[![CI](https://github.com/embyth/scss-design-system/actions/workflows/ci.yml/badge.svg)](https://github.com/embyth/scss-design-system/actions/workflows/ci.yml)\n[![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](#balance_scale-license)\n\n## :sparkles: Highlights\n\n- **Two-tier color tokens** — a constant palette (tier 1) plus semantic tokens (tier 2) that re-point per theme.\n- **OKLCH-first** — author plain hex, ship perceptual channel triplets with one-argument alpha composition.\n- **Dark mode, four ways** — data attribute, class, `prefers-color-scheme` or CSS `light-dark()`.\n- **Cascade layers** — your app styles always win, no specificity wars.\n- **Modern CSS, wrapped** — fluid `clamp()` values, container queries, `@starting-style`, typed `@property`,\n  reduced-motion guards, standard scrollbar styling.\n- **Everything is a config map** — deep-merged with defaults, you only declare overrides.\n- **Fully tested** — every function and mixin has a [sass-true](https://github.com/oddbird/true) spec plus compiled-CSS\n  snapshot coverage.\n\n## :bookmark_tabs: Table of Contents\n\n- [:rocket: Quick Start](#rocket-quick-start)\n- [:gear: Configuration](#gear-configuration)\n- [:bulb: Core Concepts](#bulb-core-concepts)\n  - [Semantic Tokens (two-tier system)](#semantic-tokens-two-tier-system)\n  - [Themes & Dark Mode](#themes--dark-mode)\n  - [Cascade Layers](#cascade-layers)\n  - [Customizing the Palette](#customizing-the-palette)\n- [:books: API Reference](#books-api-reference)\n  - [Colors](#colors)\n  - [Typography](#typography)\n  - [Spacing & Shape](#spacing--shape)\n  - [Fluid Values](#fluid-values)\n  - [Breakpoints & Media Queries](#breakpoints--media-queries)\n  - [Container Queries](#container-queries)\n  - [Elevation & Borders](#elevation--borders)\n  - [Motion & Animation](#motion--animation)\n  - [Loading Skeletons](#loading-skeletons)\n  - [Scrollbars](#scrollbars)\n  - [Text Utilities](#text-utilities)\n  - [Accessibility](#accessibility)\n  - [Layout Helpers](#layout-helpers)\n  - [Utility Functions](#utility-functions)\n  - [Shorthand Aliases](#shorthand-aliases)\n- [:globe_with_meridians: Browser Support](#globe_with_meridians-browser-support)\n- [:joystick: Examples](#joystick-examples)\n- [:handshake: Contributing](#handshake-contributing)\n- [:balance_scale: License](#balance_scale-license)\n- [:thinking: Supporting Materials](#thinking-supporting-materials)\n\n---\n\n## :rocket: Quick Start\n\nInstall the package along with Dart Sass (>= 1.80):\n\n```bash\n# pnpm:\npnpm add -D @embyth/scss-design-system sass\n\n# npm:\nnpm install -D @embyth/scss-design-system sass\n\n# yarn:\nyarn add -D @embyth/scss-design-system sass\n```\n\nLoad it in your entry stylesheet with the Sass module system and emit the styles:\n\n```scss\n@use '@embyth/scss-design-system' as * with (\n  $settings: (\n    'semantic': true,\n    // tier-2 semantic tokens\n    'color-format': 'oklch',\n    // channel triplets + alpha composition\n    'layers': true,\n    // cascade layers\n  )\n);\n\n@include generate-styles;\n```\n\nThen build components from tokens and helpers:\n\n```scss\n.card {\n  @include shape('xl');\n  @include shadow($elevation: 'md');\n\n  padding: space('2xl');\n  font-size: fluid(16px, 20px);\n  color: token('text-default');\n  background-color: token('background-base');\n  border: 1px solid token('border-default');\n}\n```\n\n> [!NOTE]\n>\n> `@import` is deprecated by Sass and will be removed in Dart Sass 3.0.0 — always use `@use`/`@forward` with the\n> `with (...)` configuration syntax. With Dart Sass >= 1.71 you can also load the package via the Node package importer:\n> `@use 'pkg:@embyth/scss-design-system'`.\n\n---\n\n## :gear: Configuration\n\nEverything lives in the `$settings` map. All configuration maps deep-merge with the defaults — you only declare what you\noverride. Read any setting back with the `config($key, $group)` helper.\n\n| Setting                      | Default            | Description                                                                                                       |\n| ---------------------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------- |\n| `'generators'.'light-reset'` | `true`             | Emit the light reset of sensible defaults.                                                                        |\n| `'generators'.'normalize'`   | `false`            | Emit normalize.css. **Deprecated**, removed in v1.0.0.                                                            |\n| `'generators'.'root'`        | `true`             | Emit the `:root` CSS variables.                                                                                   |\n| `'prefix'`                   | `null`             | Prefix for every emitted CSS variable (e.g. `'ds'` → `--ds-color-primary`).                                       |\n| `'color-format'`             | `'raw'`            | `'raw'` (whole colors) \\| `'hsl'` \\| `'oklch'` (channel triplets, enable alpha composition). `'oklch'` in v1.0.0. |\n| `'semantic'`                 | `false`            | Emit tier-2 semantic tokens. `true` in v1.0.0.                                                                    |\n| `'layers'`                   | `false`            | Wrap generated styles in CSS cascade layers. `true` in v1.0.0.                                                    |\n| `'theme-strategy'`           | `'data-attribute'` | How dark overrides are emitted: `'data-attribute'` \\| `'class'` \\| `'media'` \\| `'light-dark'`.                   |\n| `'theme-selector'`           | `null`             | Custom selector for dark overrides (data-attribute/class strategies).                                             |\n| `'color-fallback'`           | `false`            | Emit inline fallback values inside `var()` references.                                                            |\n| `'poly-themed'`              | `false`            | Legacy whole-palette theming. **Deprecated**, use `'semantic'` + `$config-semantic-dark`.                         |\n| `'paths'`                    | `./images` etc.    | Base paths for `images`, `icons` and `fonts` assets.                                                              |\n\nBesides `$settings`, every scale is its own configurable map: `$colors`, `$config-semantic`, `$config-semantic-dark`,\n`$config-font-stack`, `$config-font-size`, `$config-font-weight`, `$config-line-height`, `$config-letter-spacing`,\n`$config-breakpoint`, `$config-space`, `$config-shape`, `$config-shadow`, `$config-z-index`, `$config-motion-duration`,\n`$config-motion-timing` and `$config-keyframes`.\n\n```scss\n@use '@embyth/scss-design-system' as * with (\n  $settings: (\n    'prefix': 'app',\n    'semantic': true,\n  ),\n  $config-breakpoint: (\n    'md': 840px,\n    // override one key, keep the rest\n  ),\n  $config-space: (\n    '6xl': 128px,\n    // or extend a scale with new keys\n  )\n);\n```\n\n---\n\n## :bulb: Core Concepts\n\n### Semantic Tokens (two-tier system)\n\nThe color system is layered in two tiers:\n\n- **Tier 1 — palette**: the `$colors` map (`default`, `primary`, `secondary`, `success`, `warning`, `danger` × shades\n  50–900). Constant across themes.\n- **Tier 2 — semantic tokens**: the `$config-semantic` map gives palette values _purpose_ (`background-base`,\n  `text-default`, `primary`, `primary-foreground`, …). Themes re-point these.\n\nEnable with `'semantic': true` and consume tokens only through the `token()` function — components stay theme-agnostic:\n\n```scss\n.card {\n  color: token('text-default');\n  background-color: token('background-base');\n  border: 1px solid token('border-default');\n\n  // Alpha composition (requires 'color-format': 'hsl' or 'oklch'):\n  box-shadow: 0 4px 16px token('text-default', 0.1);\n}\n```\n\nThe default token set: `background-base/subtle/elevated`, `text-default/muted/inverted`, `border-default/strong`,\n`primary`, `secondary`, `success`, `warning`, `danger` (each with a `*-foreground` partner) and `focus-ring`.\n\nOverride, re-point or extend the maps when loading the system — custom tokens merge right in:\n\n```scss\n@use '@embyth/scss-design-system' as * with (\n  $settings: (\n    'semantic': true,\n    'color-format': 'oklch',\n  ),\n  $config-semantic: (\n    'primary': (\n      'primary',\n      600,\n    ),\n    // re-point at a palette shade\n    'brand-glow': #7c3aed,\n    // or add your own token with a raw color\n  ),\n  $config-semantic-dark: (\n    'primary': (\n      'primary',\n      300,\n    ),\n  )\n);\n```\n\n### Themes & Dark Mode\n\nWith semantic tokens enabled, dark mode is a tier-2 override — the palette never changes, only what the tokens point at.\nOnly the keys that differ need to be listed in `$config-semantic-dark`. Pick how the override is emitted with\n`'theme-strategy'`:\n\n| Strategy           | Emitted as                              | Use when                                                         |\n| ------------------ | --------------------------------------- | ---------------------------------------------------------------- |\n| `'data-attribute'` | `[data-theme=dark] { ... }` (default)   | JS toggles `document.documentElement.dataset.theme = 'dark'`     |\n| `'class'`          | `.dark { ... }`                         | JS toggles a `dark` class on the root element                    |\n| `'media'`          | `@media (prefers-color-scheme: dark)`   | Pure OS preference, no JS toggle needed                          |\n| `'light-dark'`     | `light-dark(<light>, <dark>)` per token | No JS and no duplicate blocks; alpha falls back to `color-mix()` |\n\nThe system also emits the proper `color-scheme` declarations so form controls and scrollbars follow the active theme\nautomatically.\n\n> [!NOTE]\n>\n> The legacy `'poly-themed'` + `$config-theme` approach (inverting the whole tier-1 palette per theme) still works but\n> is deprecated and will be removed in v1.0.0.\n\n### Cascade Layers\n\nWith `'layers': true` the generated styles are wrapped in CSS cascade layers, declared in this order:\n\n1. `@layer reset` — the light reset (and normalize, if enabled)\n2. `@layer base` — foundation defaults (root font setup, body baseline)\n3. `@layer components` — declared but left empty, reserved for your component styles\n\nToken custom properties stay unlayered on `:root`. Your app styles, when left unlayered, always win over everything the\nsystem emits — no specificity wars:\n\n```scss\n@layer components {\n  .button {\n    /* your design-system-level component styles */\n  }\n}\n\n.button.special {\n  /* app-level override — beats the layer automatically */\n}\n```\n\n### Customizing the Palette\n\nThe tier-1 palette lives in the `$colors` map — six groups with shades 50–900. Override any subset when loading the\nsystem:\n\n```scss\n@use '@embyth/scss-design-system' as * with (\n  $colors: (\n    'primary': (\n      500: #6644ff,\n      600: #5233d4,\n    ),\n  )\n);\n```\n\nWith `'color-format': 'hsl'` or `'oklch'`, palette values are converted to channel triplets at compile time — you keep\nauthoring plain hex.\n\n---\n\n## :books: API Reference\n\nAll examples assume the system is loaded with `@use '@embyth/scss-design-system' as *`.\n\n### Colors\n\n| API                                                  | Kind     | Description                                                                               |\n| ---------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------- |\n| `token($name, $alpha)`                               | function | **Preferred accessor.** Tier-2 semantic token reference; `$alpha` composes transparency.  |\n| `color($category, $type, $only-color, $map, $alpha)` | function | Tier-1 palette CSS variable. `$only-color: true` returns the literal color value instead. |\n| `color-value($category, $type, $map)`                | function | Literal palette color for compile-time math.                                              |\n| `color-contrast($color)`                             | function | White or black — whichever passes the YIQ brightness check against `$color`.              |\n| `channels($color, $format)`                          | function | Compile-time conversion of a color to `'hsl'`/`'oklch'` channel triplets.                 |\n| `semantic-value($reference, $palette)`               | function | Resolves a semantic reference (`('group', shade)` pair or raw color) to its color value.  |\n\nUse `token()` for everything that should follow the theme; reach for `color()` only for decorative values that must stay\nconstant:\n\n```scss\n.selector {\n  color: token('text-default'); // theme-aware\n  background-color: color('primary', 50); // theme-constant\n  border-color: token('border-default', 0.5); // 50% alpha\n}\n\n.badge {\n  // pick a readable label color at compile time:\n  color: color-contrast(color-value('primary', 500));\n}\n```\n\n### Typography\n\nSet up self-hosted fonts with `font-setup()` — it generates the full `@font-face` block, resolving files from\n`config('fonts', 'paths')`:\n\n```scss\n@include font-setup($name: 'Roboto', $filename: 'Roboto-Regular', $exts: woff2 ttf);\n@include font-setup($name: 'Roboto', $filename: 'Roboto-Bold', $weight: 700, $exts: woff2 ttf);\n```\n\n| API                      | Kind     | Description                                                                                 |\n| ------------------------ | -------- | ------------------------------------------------------------------------------------------- |\n| `font-family($family)`   | function | Font stack from `$config-font-stack` (default key: `'default'`).                            |\n| `font-size($range)`      | function | Size from `$config-font-size` (`'default'`, `'h1'`, `'h2'`, `'text'`, `'small'`, `'tiny'`). |\n| `font-weight($weight)`   | function | Weight from `$config-font-weight` (`'thin'` 100 → `'black'` 900, plus aliases).             |\n| `line-height($range)`    | function | Line height from `$config-line-height`.                                                     |\n| `letter-spacing($range)` | function | Letter spacing from `$config-letter-spacing`.                                               |\n| `font-setup(...)`        | mixin    | `@font-face` generator: `$name`, `$filename`, `$weight`, `$style`, `$display`, `$exts`.     |\n\n```scss\n.selector {\n  font-family: font-family('default');\n  font-size: font-size('h1');\n  font-weight: font-weight('semi-bold');\n  line-height: line-height('h1');\n  letter-spacing: letter-spacing('default');\n}\n```\n\nEvery scale is a map you can override or extend — name keys after intent (component names work well):\n\n```scss\n@use '@embyth/scss-design-system' as * with (\n  $config-font-size: (\n    'hero': 3rem,\n    'caption': 0.8125rem,\n  )\n);\n```\n\n### Spacing & Shape\n\n| API                               | Kind     | Description                                                                                               |\n| --------------------------------- | -------- | --------------------------------------------------------------------------------------------------------- |\n| `space($space, $map)`             | function | Value from the spacing scale (`'xs'` 2px → `'5xl'` 80px).                                                 |\n| `shape($size)`                    | function | Border radius from the shape scale (`'sm'`–`'xxl'`, `'circle'`, `'square'`).                              |\n| `shape($size, $important)`        | mixin    | Applies `border-radius` from the shape scale.                                                             |\n| `size($width, $height, $logical)` | mixin    | Width + height in one call (height defaults to width). `$logical: true` emits `inline-size`/`block-size`. |\n\n```scss\n.selector {\n  @include shape('md');\n  @include size(48px); // width + height\n  @include size(100%, 320px, $logical: true); // inline-size / block-size\n\n  padding: space('none') space('md');\n  gap: space('xl');\n}\n```\n\n### Fluid Values\n\n`fluid($min, $max, $min-breakpoint, $max-breakpoint)` builds a `clamp()` expression that interpolates any length between\ntwo viewport widths — fluid typography and fluid spacing with one function. Breakpoints accept `$config-breakpoint` keys\nor raw lengths (defaults: `'xs'` to `'xl'`):\n\n```scss\n.selector {\n  font-size: fluid(16px, 20px);\n  // -> clamp(1rem, 0.9167rem + 0.4167vw, 1.25rem)\n\n  padding-block: fluid(16px, 48px, 'sm', 'xxl');\n}\n```\n\n### Breakpoints & Media Queries\n\nThe breakpoint scale lives in `$config-breakpoint`; `bp($point)` resolves a key (or passes lengths through):\n\n```scss\n$config-breakpoint: (\n  'xs': 320px,\n  'sm': 768px,\n  'md': 900px,\n  'lg': 1024px,\n  'xl': 1280px,\n  'xxl': 1440px,\n);\n```\n\n| API                                              | Description                                           |\n| ------------------------------------------------ | ----------------------------------------------------- |\n| `breakpoint($breakpoint, $logic, $mobile-first)` | The base mixin — mobile-first by default.             |\n| `min-xs` … `min-xxl`                             | Mobile-first: the breakpoint and above.               |\n| `max-xs` … `max-xxl`                             | Desktop-first: below the breakpoint.                  |\n| `only-xs` … `only-xxl`                           | Exactly one breakpoint range.                         |\n| `not-xs` … `not-xxl`                             | Readable aliases of the `min-*` family.               |\n| `hide-at-xs` … `hide-at-xxl`                     | `display: none` within exactly that breakpoint range. |\n\n```scss\n.selector {\n  opacity: 0.5;\n\n  @include min-md {\n    opacity: 0.75; // 900px and up\n  }\n\n  @include only-xl {\n    opacity: 1; // 1280px–1439px only\n  }\n\n  @include max-sm {\n    display: none; // below 768px\n  }\n}\n```\n\n### Container Queries\n\n`container($name, $type)` marks an element as a containment context; `container-up($size, $name)` /\n`container-down($size, $name)` query against it. `$size` accepts `$config-breakpoint` keys or raw lengths:\n\n```scss\n.sidebar {\n  @include container('sidebar');\n}\n\n.widget {\n  display: block;\n\n  @include container-up('sm', 'sidebar') {\n    display: flex;\n  }\n\n  @include container-down(400px) {\n    font-size: font-size('small');\n  }\n}\n```\n\n### Elevation & Borders\n\n| API                                                  | Kind  | Description                                                           |\n| ---------------------------------------------------- | ----- | --------------------------------------------------------------------- |\n| `shadow($x, $y, $blur, $spread, $color, $elevation)` | mixin | Custom shadow, or a predefined elevation (`'xs'`–`'xxl'`, `'inner'`). |\n| `border($direction, $size, $style, $color)`          | mixin | Border on one side or all.                                            |\n\n```scss\n.selector {\n  @include shadow($elevation: 'xl'); // predefined elevation\n  @include shadow(0, 2px, 8px, 0, token('text-default', 0.15)); // custom\n  @include border(top, 1px, solid, token('border-default'));\n}\n```\n\n### Motion & Animation\n\nDurations and easing curves come from `$config-motion-duration` (`'fast'`, `'base'`, `'slow'`, …) and\n`$config-motion-timing` (`'standard'`, `'overshoot'`, …); raw values pass through.\n\n| API                                                                                                    | Kind  | Description                                                                               |\n| ------------------------------------------------------------------------------------------------------ | ----- | ----------------------------------------------------------------------------------------- |\n| `transition($property, $duration, $timing-function, $delay, $will-change, $respect-motion-preference)` | mixin | Transition shorthand; pass lists for per-property control.                                |\n| `animate($name, $duration, $timing, $delay, $iterations, $direction)`                                  | mixin | Plays a keyframe animation from `$config-keyframes` (emits keyframes once, deduplicated). |\n| `motion-safe` / `motion-reduce`                                                                        | mixin | Wraps content in the corresponding `prefers-reduced-motion` media query.                  |\n| `starting-style`                                                                                       | mixin | Emits an `@starting-style` block — the state an element transitions _from_ on entry.      |\n| `transition-discrete`                                                                                  | mixin | `transition-behavior: allow-discrete` for `display`/`overlay` transitions.                |\n| `register-property($name, $syntax, $inherits, $initial-value)`                                         | mixin | Registers a typed custom property via `@property` (deduplicated) — makes it animatable.   |\n\n```scss\n.selector {\n  @include transition(opacity transform, 'fast', $will-change: false, $respect-motion-preference: true);\n\n  @include motion-safe {\n    animation: bounce 1s infinite;\n  }\n}\n```\n\nDialogs and popovers animate in **and out** with pure CSS:\n\n```scss\ndialog[open] {\n  @include transition(opacity translate display overlay, 'slow', $respect-motion-preference: true);\n  @include transition-discrete;\n\n  @include starting-style {\n    opacity: 0;\n    translate: 0 8px;\n  }\n}\n```\n\nTyped custom properties animate for real:\n\n```scss\n.progress {\n  @include register-property('--progress', '<percentage>', $initial-value: 0%);\n  @include transition('--progress', 'slow');\n\n  background: linear-gradient(90deg, token('primary'), token('secondary')) 0 0 / var(--progress) 100% no-repeat;\n}\n```\n\n### Loading Skeletons\n\n`skeleton()` paints a multi-line shimmering placeholder with masked CSS gradients — the shine is clipped to the lines\nand travels the viewport in one page-wide wave (`background-attachment: fixed`), resting for the final third of each\ncycle. Reduced motion is respected automatically.\n\n| Parameter                                      | Default                               | Description                                                                  |\n| ---------------------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------- |\n| `$lines`                                       | `2`                                   | Number of lines (the last renders shorter).                                  |\n| `$line-height`                                 | `24px`                                | Height of each line.                                                         |\n| `$line-gap`                                    | `8px`                                 | Gap between lines.                                                           |\n| `$background`                                  | `#e1e4e8`                             | Line color — accepts `token()` values.                                       |\n| `$shimmer`                                     | `rgba(255, 255, 255, 0.6)`            | Shine color — pick one that **contrasts with `$background`** in every theme. |\n| `$speed`                                       | `3s`                                  | One shimmer cycle.                                                           |\n| `$level`                                       | `'selector'`                          | `'selector'` applies directly; `'empty'` only while the element is `:empty`. |\n| `$radius`                                      | `4px`                                 | Line corner radius; large values yield pills, `null`/`0` for square corners. |\n| `$shine-size` / `$shine-blur` / `$shine-angle` | `clamp(...)` / `clamp(...)` / `96deg` | Geometry of the travelling shine.                                            |\n\n```scss\n.placeholder {\n  @include skeleton(3, 18px, 12px, $background: token('border-default'), $shimmer: token('skeleton-shine', 0.85));\n}\n```\n\n> [!TIP]\n>\n> Define a custom semantic token for the shine (e.g. a mid-gray) so it stays visible over the line color in both light\n> and dark mode — mid-grays are darker than light-mode lines and lighter than dark-mode ones.\n\n### Scrollbars\n\n`scrollbar($thumb-background-color, $track-background-color, $size, $shape, $stable, $transition, $transition-duration, $modern)`\n\nWith `$modern: true` (recommended, default in v1.0.0) it emits the standard `scrollbar-width`/`scrollbar-color`\nproperties; otherwise the legacy `::-webkit-*` styling with an optional fade animation. `$stable` reserves the gutter.\n\n```scss\n.list {\n  @include scrollbar(token('primary'), transparent, sm, $stable: true, $modern: true);\n}\n```\n\n### Text Utilities\n\n| API                                               | Description                                                        |\n| ------------------------------------------------- | ------------------------------------------------------------------ |\n| `text-ellipsis($number-of-lines)`                 | Single-line or multiline (line-clamp) truncation with an ellipsis. |\n| `text-balance` / `text-pretty`                    | `text-wrap: balance` (headings) / `pretty` (body copy).            |\n| `word-wrap`                                       | Break long unbreakable strings (URLs etc.).                        |\n| `text-selection($color, $background, $is-direct)` | Styles `::selection` for the element or its children.              |\n| `placeholder`                                     | Styles input/textarea `::placeholder` content.                     |\n\n```scss\n.teaser {\n  @include text-ellipsis(2);\n}\n\n.heading {\n  @include text-balance;\n}\n\n.input {\n  @include placeholder {\n    color: token('text-muted');\n  }\n}\n```\n\n### Accessibility\n\n| API                                                   | Description                                                                           |\n| ----------------------------------------------------- | ------------------------------------------------------------------------------------- |\n| `focus-ring($size, $offset, $color, $radius, $thick)` | Animated, `:focus-visible`-based focus outline with `prefers-contrast` support.       |\n| `visually-hidden` / `visually-unhidden`               | Hide content visually while keeping it available to assistive technology.             |\n| `forced-colors`                                       | Styles applied only when a forced-colors mode (e.g. Windows High Contrast) is active. |\n\n```scss\n.button {\n  @include focus-ring($color: token('focus-ring'));\n\n  @include forced-colors {\n    border: 1px solid ButtonText;\n  }\n}\n\n.sr-only {\n  @include visually-hidden;\n}\n```\n\n### Layout Helpers\n\n| API                                                                      | Kind     | Description                                                                                                                  |\n| ------------------------------------------------------------------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------- |\n| `position($position, $top, $right, $bottom, $left, $axis, $logical)`     | mixin    | Positioning shorthand; `$axis: both/horizontal/vertical` centers via transform; `$logical: true` emits `inset-*` properties. |\n| `pseudo($loc, $content, $position, $top, $right, $bottom, $left, $axis)` | mixin    | Generates a `::before`/`::after` pseudo element with positioning in one call.                                                |\n| `z($layer)`                                                              | function | Z-index from `$config-z-index` (`'deep'`, `'base'`, `'default'`, `'sticky'`, `'modal'`, `'tooltip'`, …).                     |\n| `z-index($layer, $important)`                                            | mixin    | Applies the z-index property from the same scale.                                                                            |\n| `triangle($size, $color, $direction)`                                    | mixin    | Border-built triangle (`up`/`right`/`down`/`left`) — tooltips, dropdown arrows.                                              |\n| `icon-size($width, $height)`                                             | mixin    | Sizes inline SVG icons.                                                                                                      |\n| `clear-btn` / `clear-list`                                               | mixin    | Strips default button / list styling.                                                                                        |\n| `escape-to-parent($selector)`                                            | mixin    | Re-attaches the block under a given parent selector.                                                                         |\n\n```scss\n.modal {\n  @include position(fixed, $axis: both); // centered both axes\n  @include z-index('modal');\n}\n\n.tooltip_arrow {\n  @include triangle(12px 6px, token('text-default'), down);\n}\n\n.menu {\n  @include clear-list;\n}\n```\n\n### Utility Functions\n\n| API                                        | Description                                                                         |\n| ------------------------------------------ | ----------------------------------------------------------------------------------- |\n| `config($key, $group)`                     | Reads a value from `$settings` (e.g. `config('fonts', 'paths')`).                   |\n| `bp($point)`                               | Resolves a `$config-breakpoint` key; numbers pass through (unitless become px).     |\n| `remify($value)` / `em($value)`            | Converts px (or unitless) values to `rem`/`em` against the root font size.          |\n| `strip-unit($value)`                       | Removes the unit from a number.                                                     |\n| `ternary($condition, $if-true, $if-false)` | Inline conditional — a drop-in replacement for the deprecated Sass `if()` function. |\n| `str-replace($string, $search, $replace)`  | Replaces all occurrences of a substring.                                            |\n\n```scss\n.selector {\n  width: remify(320px); // -> 20rem\n  margin-inline: ternary($centered, auto, 0);\n}\n```\n\n### Shorthand Aliases\n\nThe high-frequency getters ship with compact aliases — same arguments, same behavior, fewer keystrokes:\n\n| Alias  | Full name          |\n| ------ | ------------------ |\n| `ff()` | `font-family()`    |\n| `fs()` | `font-size()`      |\n| `fw()` | `font-weight()`    |\n| `lh()` | `line-height()`    |\n| `ls()` | `letter-spacing()` |\n| `sp()` | `space()`          |\n| `sh()` | `shape()`          |\n\n```scss\n.selector {\n  padding: sp('md') sp('xl');\n  font-size: fs('small');\n  font-weight: fw('semi-bold');\n  line-height: lh('default');\n  border-radius: sh('lg');\n}\n```\n\n---\n\n## :globe_with_meridians: Browser Support\n\nThe system targets evergreen browsers. Everything emitted by the default configuration works in all modern browsers; the\nopt-in features rely on widely supported platform primitives:\n\n- **CSS custom properties, `color-scheme`** — universal.\n- **OKLCH / `color-mix()` / relative color values** — Baseline 2023.\n- **Cascade layers (`@layer`)** — Baseline 2022.\n- **Container queries** — Baseline 2023.\n- **`light-dark()`** — Baseline 2024.\n- **`@starting-style`, `transition-behavior: allow-discrete`** — Baseline 2024.\n- **`text-wrap: balance/pretty`, `scrollbar-width/color`, `dvh`** — Baseline 2024 (with graceful fallbacks where\n  applicable).\n\nIf you must support older browsers, stay on `'color-format': 'raw'` and `'layers': false` (the defaults) and enable\n`'color-fallback': true`.\n\n---\n\n## :joystick: Examples\n\nThree runnable example apps live in [`examples/`](examples/). They all render the same screen — a glassmorphism card\nover an animated noise canvas with a theme switch — and exist to show exactly how to wire the system into an app: the\n`@forward ... with (...)` configuration, semantic tokens, OKLCH and cascade layers.\n\n- [`examples/vanilla`](examples/vanilla) — Vite + vanilla JavaScript.\n- [`examples/react-ts`](examples/react-ts) — Vite + React + TypeScript.\n- [`examples/vue-ts`](examples/vue-ts) — Vite + Vue + TypeScript.\n\n```bash\npnpm install\npnpm vanilla:dev   # or: pnpm react:dev / pnpm vue:dev\n```\n\n---\n\n## :handshake: Contributing\n\nContributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for the project layout, testing workflow (`pnpm test`\nruns sass-true specs + compiled-CSS snapshots) and the rules of thumb — every new function or mixin ships with a spec,\nand the default output never changes silently.\n\n---\n\n## :balance_scale: License\n\n[MIT](https://github.com/embyth/scss-design-system/blob/main/LICENSE) © Rostyslav Miniukov\n\n---\n\n## :thinking: Supporting Materials\n\n- [Color in Design Systems](https://medium.com/eightshapes-llc/color-in-design-systems-a1c80f65fa3)\n- [OKLCH in CSS: why we moved from RGB and HSL](https://evilmartians.com/chronicles/oklch-in-css-why-quit-rgb-hsl)\n- [A Complete Guide to CSS Cascade Layers](https://css-tricks.com/css-cascade-layers/)\n- [Responsive Typography With Sass Maps](https://www.smashingmagazine.com/2015/06/responsive-typography-with-scss-maps/)\n- [The Type System](https://material.io/design/typography/the-type-system.html#type-scale)\n- [Modular Scale](http://www.modularscale.com/)\n- [Sass Docs](https://sass-lang.com/documentation/)\n","readmeFilename":"README.md"}