Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion _layouts/default.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<a href="/">SLASHED</a>
<a href="/docs/architecture">Docs</a>
<a href="/docs/tokens">Tokens</a>
<a href="/docs/demo.html">Demo</a>
<a href="/docs/test-coverage.html">Coverage</a>
<a href="https://github.com/codeslash-dev/SLASHED">GitHub</a>
<a href="/configurator/" class="nav-cta">Configurator →</a>
</nav>
Expand Down
2 changes: 1 addition & 1 deletion demos/full-api-demo-with-overrides.html
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
</nav>
<main id="main">
<h1>SLASHED Full API Demo</h1>
<p style="color:var(--sf-color-text--muted)">v0.7.3 · optimal-components bundle from jsDelivr CDN · 324 classes · 729 tokens (238 configurable)</p>
<p style="color:var(--sf-color-text--muted)">v0.7.5 · optimal-components bundle from jsDelivr CDN · 324 classes · 729 tokens (238 configurable)</p>
<div class="notice"><strong>ultimate-override.css is ACTIVE.</strong> Every value below is recomputed from perturbed knob tokens — toggle it off in the toolbar, or compare against <a href="full-api-demo.html">the un-overridden page</a>.</div>

<section id="tokens">
Expand Down
2 changes: 1 addition & 1 deletion demos/full-api-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
</nav>
<main id="main">
<h1>SLASHED Full API Demo</h1>
<p style="color:var(--sf-color-text--muted)">v0.7.3 · optimal-components bundle from jsDelivr CDN · 324 classes · 729 tokens (238 configurable)</p>
<p style="color:var(--sf-color-text--muted)">v0.7.5 · optimal-components bundle from jsDelivr CDN · 324 classes · 729 tokens (238 configurable)</p>
<div class="notice">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 <a href="full-api-demo-with-overrides.html">full-api-demo-with-overrides.html</a>.</div>

<section id="tokens">
Expand Down
2 changes: 1 addition & 1 deletion demos/ultimate-override.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* ============================================================================
ULTIMATE OVERRIDE — generated by demos/generate.mjs (do not edit by hand)
SLASHED v0.7.3
SLASHED v0.7.5

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.
Expand Down
2 changes: 1 addition & 1 deletion docs/layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 [`demo.html`](demo.html).
All primitives are demoed in the [layout coverage page](test-coverage-3-layout.html).

## The primitives

Expand Down
2 changes: 1 addition & 1 deletion docs/motion.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 [`demo.html`](demo.html).
All animations are demoed in the [macros & states coverage page](test-coverage-4-macros-states.html).

## Design principles

Expand Down
2 changes: 1 addition & 1 deletion docs/states.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 [`demo.html`](demo.html).
All states are exercised in the [macros & states coverage page](test-coverage-4-macros-states.html).

## Reference

Expand Down
93 changes: 51 additions & 42 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@
letter-spacing: var(--sf-tracking-tight);
}
.site-nav .brand b { color: var(--sf-color-primary); }
/* The header is a nav bar, not a content section: .sf-section--xs still
resolves to the section rhythm scale (--sf-space-xl ≈ 3.25rem a side),
which stacks a ~150px-tall band around a 49px nav. Pin it to a compact,
symmetric bar instead — the gutter (inline padding) stays. */
header:has(.site-nav) { padding-block: var(--sf-space-s); }
/* The link cluster is the part that has room to give: on narrow
viewports it's dropped in favor of the primary CTA + theme toggle,
instead of wrapping into three cramped rows. */
Expand Down Expand Up @@ -116,7 +121,7 @@
color: var(--sf-color-heading);
margin: 0;
}
.al { display: inline-flex; align-items: baseline; cursor: default; }
.al { position: relative; display: inline-flex; align-items: baseline; cursor: default; }
.al b {
background-image: var(--sf-gradient-brand);
background-clip: text;
Expand All @@ -130,49 +135,52 @@
font-weight: var(--sf-font-weight-light);
margin-inline: 0.1em;
}
@media (any-hover: hover) {
/* Per-word widths (ch). Each word expands to exactly --w, and the
centered row is counter-shifted by --w/2, so the hovered letter
stays put under the cursor instead of sliding onto a neighbour
and re-firing the hover. */
.al:nth-of-type(1) { --w: 8.2ch; }
.al:nth-of-type(2) { --w: 3.1ch; }
.al:nth-of-type(3) { --w: 6ch; }
.al:nth-of-type(4) { --w: 7.8ch; }
.al:nth-of-type(5) { --w: 4.3ch; }
.al:nth-of-type(6) { --w: 5ch; }
.al:nth-of-type(7) { --w: 9.8ch; }
/* Gate the collapsed/unfold interaction on a PRIMARY input that can
actually hover (a fine pointer), not `any-hover` — which is true on
hybrid devices (touchscreen laptops, a phone with a stylus/mouse)
even while the user is touching, which would strand the acronym in
its collapsed state with no touch way to reveal the words. Touch /
coarse-pointer devices keep the default in-flow state above, where
every word is already shown. */
@media (hover: hover) and (pointer: fine) {
/* Collapsed to the tight letter-row; each word unfolds on hover.
The unfolded text is taken OUT OF FLOW — absolutely positioned and
revealed with clip-path — so unfolding a word changes the size and
position of nothing else. No letter ever moves under the cursor, so
a hovered word can't slide onto a neighbour and re-fire the hover.
(The old approach animated real width and tried to counter-shift the
centered row by a hardcoded per-word amount; the amounts couldn't
match the real glyph widths, so siblings leapt and re-triggered.) */
.acronym-hero {
/* Never wrap mid-interaction, and cap the size relative to the
hero's own container, with a floor so a hover-capable device
at a narrow width (a resized browser, a laptop touchscreen)
never shrinks below a readable size — so the widest unfolded
word still fits the row on one line. */
flex-wrap: nowrap;
row-gap: 0;
font-size: max(2.75rem, min(var(--sf-text-4xl), 4.4cqi));
/* Never wrap mid-interaction; cap the size relative to the hero's
own container, with a readable floor for narrow hover-capable
viewports (resized browser, laptop touchscreen). */
flex-wrap: nowrap;
row-gap: 0;
/* Floor sized so the longest unfolded word (Deterministic) still
fits the hero without clipping on narrow hover-capable widths. */
font-size: max(2.4rem, min(var(--sf-text-4xl), 4.4cqi));
line-height: var(--sf-display-l-line-height);
transition: translate var(--sf-duration-slow) var(--sf-ease-out);
}
.al { white-space: nowrap; }
.al .rest {
display: inline-block;
width: 0;
opacity: 0;
overflow: hidden;
transition: width var(--sf-duration-slow) var(--sf-ease-out),
opacity var(--sf-duration-normal) var(--sf-ease-out);
position: absolute;
inset-block-start: 0;
inset-inline-start: 100%; /* immediately after the bold letter */
width: max-content;
opacity: 0;
clip-path: inset(0 100% 0 0); /* hidden by clip, so it occupies no layout space */
transition: clip-path var(--sf-duration-slow) var(--sf-ease-out),
opacity var(--sf-duration-normal) var(--sf-ease-out);
}
/* The unfolded word overlays its dimmed neighbours cleanly. */
.al:hover { z-index: 1; }
.al:hover .rest {
opacity: 1;
clip-path: inset(0 0 0 0);
transition-delay: 60ms;
}
.al:hover .rest { width: var(--w); opacity: 1; transition-delay: 120ms; }
.acronym-hero:hover .al:not(:hover) b { opacity: 0.35; }
.acronym-hero:has(.al:hover) { transition-delay: 120ms; }
.acronym-hero:has(.al:nth-of-type(1):hover) { translate: calc(8.2ch / 2) 0; }
.acronym-hero:has(.al:nth-of-type(2):hover) { translate: calc(3.1ch / 2) 0; }
.acronym-hero:has(.al:nth-of-type(3):hover) { translate: calc(6ch / 2) 0; }
.acronym-hero:has(.al:nth-of-type(4):hover) { translate: calc(7.8ch / 2) 0; }
.acronym-hero:has(.al:nth-of-type(5):hover) { translate: calc(4.3ch / 2) 0; }
.acronym-hero:has(.al:nth-of-type(6):hover) { translate: calc(5ch / 2) 0; }
.acronym-hero:has(.al:nth-of-type(7):hover) { translate: calc(9.8ch / 2) 0; }
}
@media (prefers-reduced-motion: reduce) {
.acronym-hero, .al b, .al .rest { transition: none; }
Expand Down Expand Up @@ -365,9 +373,11 @@
.doc-list a small { color: var(--sf-color-text--muted); margin-inline-start: var(--sf-space-2xs); }

.footer-meta, .footer-meta a { color: var(--sf-color-text--muted); font-size: var(--sf-text-xs); }
/* The hover hint only makes sense where hovering is a thing. */
/* The hover hint only makes sense where hovering is a thing — and it
must match the interaction gate above, or a hybrid touch device
would see "hover the name" over an already-unfolded acronym. */
.hover-hint { display: none; }
@media (any-hover: hover) { .hover-hint { display: inline; } }
@media (hover: hover) and (pointer: fine) { .hover-hint { display: inline; } }

.eyebrow {
font-size: var(--sf-text-xs);
Expand All @@ -393,7 +403,7 @@
<div class="nav-links sf-cluster sf-cluster--s sf-cluster--no-wrap">
<a href="/docs/architecture">Docs</a>
<a href="/docs/tokens">Tokens</a>
<a href="/docs/demo.html">Demo</a>
<a href="/docs/test-coverage.html">Coverage</a>
<a href="https://github.com/codeslash-dev/SLASHED">GitHub</a>
</div>
<div class="nav-actions sf-cluster sf-cluster--xs sf-cluster--no-wrap">
Expand All @@ -420,8 +430,8 @@ <h1 class="acronym-hero" aria-label="SLASHED — Standalone, Lean, Agnostic, Str
<p class="lede">A cascade-layer CSS framework: 729 design tokens, automatic dark mode, fluid type &amp; spacing — zero JavaScript, zero build step. Override six tokens and the whole site rebrands.</p>
<div class="sf-cluster sf-cluster--center sf-cluster--s">
<a class="btn btn--primary" href="/configurator/">Open Configurator →</a>
<a class="btn btn--quiet" href="/docs/demo.html">View Demo</a>
<a class="btn btn--quiet" href="/demos/full-api-demo.html">Full API Demo</a>
<a class="btn btn--quiet" href="/docs/test-coverage.html">Coverage Suite</a>
<a class="btn btn--quiet" href="https://github.com/codeslash-dev/SLASHED">GitHub</a>
</div>
<p class="footer-meta"><span class="hover-hint">Psst — hover the name. </span>This page is styled by <code>slashed.optimal.css</code> itself: switch your OS to dark mode and watch it follow.</p>
Expand Down Expand Up @@ -627,7 +637,6 @@ <h3 class="eyebrow">Developer</h3>
<a href="/docs/llm-guide">LLM Guide <small>AI-assisted development reference</small></a>
<a href="/docs/api-index">API Index <small>machine-readable catalogue</small></a>
<a href="/docs/source-comment-policy">Comment Policy <small>contributor conventions</small></a>
<a href="/docs/demo.html">Demo <small>live showcase</small></a>
<a href="/demos/full-api-demo.html">Full API Demo <small>every class &amp; token, live · dark mode</small></a>
<a href="/docs/test-coverage.html">Test Coverage <small>visual regression suite</small></a>
</div>
Expand Down