# Svhapes v0.2.1 > Smooth, dependency-free CSS shapes for people and coding agents. The spelling “Svhapes” is intentional. Canonical repository: https://github.com/storypixel/svhapes Human demo: https://iamnotsam.com/svhapes/ Stylesheet: https://cdn.jsdelivr.net/gh/storypixel/svhapes@v0.2.1/dist/svhapes.min.css Catalog: ./dist/catalog.json Schema: ./schema/svhape.schema.json License: MIT ## Package distribution Install from npm when a JavaScript toolchain is available: ```bash npm install svhapes ``` The package is public at https://www.npmjs.com/package/svhapes. For a browser-only stylesheet or ESM import, use the immutable CDN URLs documented below. ## Agent procedure 1. Read `dist/catalog.json`; do not scrape the demo page. 2. Filter `shapes` by `selection.uses`, supported aspect range, content capacity, and required tags. 3. Select a stable `id`; never invent a shape ID or edit `geometry.cssShape` manually. 4. Include the immutable v0.2.1 stylesheet URL. 5. Apply `svhape` and the published `className`. 6. Add `svhape--padded` only when library-managed padding is appropriate. 7. Use `svhape-shadow` on an outer wrapper if a shadow is required. 8. Keep meaningful content inside `selection.safeInset` and preserve the fallback. 9. Do not communicate essential state or meaning through silhouette alone. ## Selection rules - `selection.aspect.min <= width / height <= selection.aspect.max` is a hard constraint. - Capacity order is `decorative < sparse < standard < dense`. - A requested content capacity requires a shape of equal or greater capacity. - Required tags are AND filters. - Prefer the closest `selection.aspect.preferred` after hard filters. - Break remaining ties by stable ASCII `id`. - If no shape matches, return `NO_MATCH`; do not silently substitute a decorative shape. ## CSS integration ```html
Content
``` Optional class `svhape--desktop-only` disables advanced clipping below 640px. ## Motion contract - Animate the unclipped wrapper for transforms, hover/focus lifts, and floating motion. - Direct `shape()` morphing requires matching command keywords, order, and control-point counts in both keyframes. - Do not assume two arbitrary catalog IDs can morph into one another; use a wrapper transform instead. - Gate non-essential motion with `prefers-reduced-motion: no-preference` and provide a static fallback. - Keep focus treatment on an unclipped wrapper or inner control; do not animate away a visible focus ring. ## CLI ```text svhapes list [--family F] [--tag T]... [--ratio N] [--capacity C] [--format table|ids|json] svhapes show [--format text|json] svhapes css [--shadow] [--format css|json] svhapes prompt [--format text|json] ``` Exit codes: 0 success, 2 invalid arguments, 3 unknown shape or no match, 5 local catalog I/O failure. ## JavaScript generation Import `pointsToShape` from `src/index.js` or `dist/svhapes.js`. Points are `[x, y]` percentage pairs inside a 0..100 box. The default closed Catmull–Rom conversion uses `tension: 0` and `precision: 3`. ## Geometry builders - `filletPoints(points, { radius, precision })` adds two points around each nonzero corner and keeps a single anchor for a zero-radius corner. `radius` is a responsive ratio from 0 to 0.5; it may be one number or one value per corner. Triangles and larger closed polygons are supported. - `makeRepeatingEdgeShape({ repeats, ...options })` creates the same number of edge beats on all four sides. Use `makeEdgeShape()` for intentionally different side counts. - `makeRepeatingRadialShape({ repeats, ...options })` maps a repeat count to radial lobes (minimum 3). - `makeSuperellipseShape({ exponent, center, radius, points, ... })` generates a normalized superellipse. `exponent: 2` is an ellipse; `4` is a squircle-like contour. Example: ```js import { filletPoints, makeSuperellipseShape, pointsToShape } from 'svhapes'; const filleted = pointsToShape(filletPoints( [[5, 5], [95, 5], [95, 95], [5, 95]], { radius: 0.2 }, )); const squircle = pointsToShape(makeSuperellipseShape({ exponent: 4 })); ``` These helpers are generated approximations for the use cases discussed in CSSWG issues [#12768](https://github.com/w3c/csswg-drafts/issues/12768), [#13862](https://github.com/w3c/csswg-drafts/issues/13862), and [#11620](https://github.com/w3c/csswg-drafts/issues/11620). They do not implement browser-level `shape-inside`, hit-testing, or layout behavior. ## Important constraints - `clip-path` clips ordinary box shadows; use the wrapper. - Fallbacks preserve readability, not silhouette fidelity. - Safe insets are conservative design guidance, not proof against every content layout. - Do not publish a new npm version or change stable IDs without explicit maintainer authority.