asw-v01: archive deferred content (packs, site, lab, legacy examples)

- 2.1: packs/ -> archive/packs/
- 2.2: site/ -> archive/site/
- 2.3: src/lab/ -> archive/lab/
- 2.4: examples/ -> archive/examples-legacy/ (SSI-based)
This commit is contained in:
exe.dev user 2026-06-07 10:39:21 +02:00
parent 416fe2f180
commit e47a9f4401
173 changed files with 11 additions and 5 deletions

521
archive/lab/css-art.html Normal file
View file

@ -0,0 +1,521 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/asw.css">
<meta name="color-scheme" content="dark">
<title>CSS Art — ASW Lab</title>
<meta name="description" content="Pure CSS art using Open Props tokens. No JS, no images, no classes.">
<style>
/* ── Gallery layout ─────────────────────────────────────────────── */
body { background: var(--surface); }
[data-gallery] {
display: grid;
gap: 3rem;
padding: 2rem 0;
}
[data-piece] {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
align-items: center;
padding: 2rem;
background: var(--surface-1);
border: 1px solid var(--border);
border-radius: 0.75rem;
}
@media (max-width: 700px) {
[data-piece] { grid-template-columns: 1fr; }
}
[data-piece] > [data-stage] {
display: flex;
align-items: center;
justify-content: center;
min-height: 280px;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 0.5rem;
overflow: hidden;
}
[data-piece] > [data-explain] > h3 {
margin-top: 0;
color: var(--text);
font-size: 1.1rem;
}
[data-piece] > [data-explain] > p {
color: var(--text-2);
font-size: 0.9rem;
line-height: 1.6;
margin-bottom: 1rem;
}
[data-piece] > [data-explain] > pre {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 0.375rem;
padding: 0.75rem;
font-size: 0.8rem;
overflow-x: auto;
margin: 0;
}
/* ── Header ─────────────────────────────────────────────────────── */
[data-art-header] {
padding: 3rem 0 1rem;
}
[data-art-header] h1 {
font-size: 2.5rem;
margin-bottom: 0.5rem;
}
[data-art-header] p {
color: var(--text-2);
font-size: 1.1rem;
margin: 0;
}
/* ── Hue grid ────────────────────────────────────────────────────── */
[data-hue-grid] {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1rem;
}
[data-hue-grid] > [data-hue-swatch] {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.75rem;
}
[data-hue-grid] > [data-hue-swatch] > span {
font-family: var(--font-mono);
font-size: 0.75rem;
color: var(--text-3);
}
@media (max-width: 700px) {
[data-hue-grid] { grid-template-columns: repeat(2, 1fr); }
}
/* ── Section divider ─────────────────────────────────────────────── */
[data-section-label] {
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--text-3);
padding: 1rem 0 0.25rem;
border-top: 1px solid var(--border);
margin-top: 1rem;
}
/* ════════════════════════════════════════════════════════════════
ART PIECES — all via data-attributes, zero classes
════════════════════════════════════════════════════════════════ */
/* ── 1. Floating blob ──────────────────────────────────────────── */
[data-art="blob-float"] {
width: 160px;
height: 160px;
border-radius: var(--radius-blob-2);
background: var(--gradient-4);
animation: var(--animation-float);
}
/* ── 2. Spinning prism ─────────────────────────────────────────── */
[data-art="prism"] {
width: 140px;
height: 140px;
border-radius: var(--radius-blob-3);
background: var(--gradient-10);
animation: spin 4s linear infinite;
}
/* ── 3. Layered depth ──────────────────────────────────────────── */
[data-art="depth"] {
position: relative;
width: 200px;
height: 200px;
}
[data-art="depth"] > [data-layer] {
position: absolute;
border-radius: var(--radius-blob-1);
animation: var(--animation-float);
}
[data-art="depth"] > [data-layer="3"] {
width: 160px;
height: 160px;
top: 20px;
left: 20px;
background: var(--gradient-11);
opacity: 0.6;
animation-delay: 0s;
}
[data-art="depth"] > [data-layer="2"] {
width: 120px;
height: 120px;
top: 50px;
left: 40px;
background: var(--gradient-24);
opacity: 0.75;
animation-delay: -1s;
}
[data-art="depth"] > [data-layer="1"] {
width: 80px;
height: 80px;
top: 80px;
left: 60px;
background: var(--gradient-4);
animation-delay: -2s;
}
/* ── 4. Pulse ring ─────────────────────────────────────────────── */
[data-art="pulse-ring"] {
position: relative;
width: 120px;
height: 120px;
display: flex;
align-items: center;
justify-content: center;
}
[data-art="pulse-ring"]::before,
[data-art="pulse-ring"]::after {
content: "";
position: absolute;
inset: 0;
border-radius: var(--radius-blob-5);
background: var(--gradient-13);
}
[data-art="pulse-ring"]::before {
animation: pulse 2s var(--ease-out-3) infinite;
opacity: 0.5;
}
[data-art="pulse-ring"]::after {
animation: pulse 2s var(--ease-out-3) infinite;
animation-delay: -1s;
opacity: 0.4;
}
[data-art="pulse-ring"] > [data-core] {
width: 60px;
height: 60px;
border-radius: var(--radius-blob-5);
background: var(--gradient-13);
position: relative;
z-index: 1;
}
/* ── 5. Gradient text ──────────────────────────────────────────── */
[data-art="gradient-text"] {
font-family: var(--font-mono);
font-size: 3.5rem;
font-weight: 900;
line-height: 1;
background: var(--gradient-1);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
text-align: center;
letter-spacing: -0.03em;
user-select: none;
}
/* ── 6. Hue tinting demo ───────────────────────────────────────── */
[data-art="hue-blob"] {
width: 90px;
height: 90px;
border-radius: var(--radius-blob-4);
background:
radial-gradient(circle at 30% 30%, oklch(65% 0.18 var(--gray-hue, 220)), oklch(25% 0.06 var(--gray-hue, 220)));
animation: var(--animation-float);
}
[data-hue="0"] > [data-art="hue-blob"] { --gray-hue: 0; animation-delay: 0s; }
[data-hue="45"] > [data-art="hue-blob"] { --gray-hue: 45; animation-delay: -0.75s; }
[data-hue="150"] > [data-art="hue-blob"] { --gray-hue: 150; animation-delay: -1.5s; }
[data-hue="220"] > [data-art="hue-blob"] { --gray-hue: 220; animation-delay: -2.25s; }
/* ── 7. Waveform ───────────────────────────────────────────────── */
[data-art="waveform"] {
display: flex;
align-items: flex-end;
gap: 4px;
height: 80px;
padding: 0 8px;
}
[data-art="waveform"] > [data-bar] {
flex: 1;
border-radius: 3px 3px 0 0;
background: var(--gradient-4);
animation: var(--animation-bounce);
}
[data-art="waveform"] > [data-bar="1"] { height: 45%; animation-delay: -0.0s; }
[data-art="waveform"] > [data-bar="2"] { height: 70%; animation-delay: -0.2s; }
[data-art="waveform"] > [data-bar="3"] { height: 90%; animation-delay: -0.4s; }
[data-art="waveform"] > [data-bar="4"] { height: 55%; animation-delay: -0.6s; }
[data-art="waveform"] > [data-bar="5"] { height: 80%; animation-delay: -0.8s; }
[data-art="waveform"] > [data-bar="6"] { height: 65%; animation-delay: -1.0s; }
[data-art="waveform"] > [data-bar="7"] { height: 40%; animation-delay: -1.2s; }
[data-art="waveform"] > [data-bar="8"] { height: 75%; animation-delay: -1.4s; }
[data-art="waveform"] > [data-bar="9"] { height: 50%; animation-delay: -1.6s; }
[data-art="waveform"] > [data-bar="10"] { height: 85%; animation-delay: -1.8s; }
[data-art="waveform"] > [data-bar="11"] { height: 60%; animation-delay: -2.0s; }
[data-art="waveform"] > [data-bar="12"] { height: 35%; animation-delay: -2.2s; }
</style>
</head>
<body>
<nav>
<ul>
<li><a href="../index.html"><strong>ASW</strong></a></li>
<li><a href="../docs/index.html">Docs</a></li>
<li><a href="../lab/kitchen-sink.html">Lab</a></li>
</ul>
<ul>
<li><span data-text="dim">CSS Art</span></li>
</ul>
</nav>
<main data-layout="prose">
<section data-art-header>
<h1>CSS Art</h1>
<p>Pure CSS using Open Props tokens. No JavaScript, no images, no classes. Each piece is a data-attribute.</p>
</section>
<p data-text="dim">
Open Props ships <code>--radius-blob-*</code> (organic shapes), <code>--gradient-1</code><code>--gradient-30</code>,
<code>--animation-float</code>, and <code>--ease-spring-*</code>. Combined with ASW's data-attribute vocabulary,
these compose into genuine visual objects with a single HTML element.
</p>
<div data-gallery>
<!-- 1. Floating blob -->
<article data-piece>
<div data-stage>
<div data-art="blob-float"></div>
</div>
<div data-explain>
<h3>Floating blob</h3>
<p>
A single <code>&lt;div&gt;</code> with an organic border-radius from
<code>--radius-blob-2</code>, a teal-to-green linear gradient from
<code>--gradient-4</code>, and <code>--animation-float</code> — a gentle
2-axis sine wave encoded in 3 lines of CSS.
</p>
<pre><code>[data-art="blob-float"] {
width: 160px;
height: 160px;
border-radius: var(--radius-blob-2);
background: var(--gradient-4);
animation: var(--animation-float);
}</code></pre>
</div>
</article>
<!-- 2. Spinning prism -->
<article data-piece>
<div data-stage>
<div data-art="prism"></div>
</div>
<div data-explain>
<h3>Spinning prism</h3>
<p>
<code>--gradient-10</code> is a conic rainbow sweep — originally designed
for color wheels. Applied to an organic shape and spun at 4 seconds per
revolution, it becomes something else entirely. The color order is preserved,
the edge is alive.
</p>
<pre><code>[data-art="prism"] {
width: 140px;
height: 140px;
border-radius: var(--radius-blob-3);
background: var(--gradient-10);
animation: spin 4s linear infinite;
}</code></pre>
</div>
</article>
<!-- 3. Layered depth -->
<article data-piece>
<div data-stage>
<div data-art="depth">
<div data-layer="3"></div>
<div data-layer="2"></div>
<div data-layer="1"></div>
</div>
</div>
<div data-explain>
<h3>Layered depth</h3>
<p>
Three blobs, each a different gradient and opacity, each floating at
a different phase offset. The same <code>--animation-float</code>
keyframes with staggered <code>animation-delay</code> values create
independent rhythms. Nothing is synchronized; depth emerges from
desynchronization.
</p>
<pre><code>[data-layer="3"] { background: var(--gradient-11); }
[data-layer="2"] { background: var(--gradient-24); }
[data-layer="1"] { background: var(--gradient-4); }
/* stagger: 0s / -1s / -2s */</code></pre>
</div>
</article>
<!-- 4. Pulse ring -->
<article data-piece>
<div data-stage>
<div data-art="pulse-ring">
<div data-core></div>
</div>
</div>
<div data-explain>
<h3>Pulse ring</h3>
<p>
Three concentric blobs from <code>--gradient-13</code> (a deep purple-to-coral
radial), pulsing outward with staggered timing. Two are <code>::before</code>
and <code>::after</code> pseudo-elements — no extra HTML. The core sits above
them on a higher stacking context.
</p>
<pre><code>[data-art="pulse-ring"]::before,
[data-art="pulse-ring"]::after {
border-radius: var(--radius-blob-5);
background: var(--gradient-13);
animation: pulse 2s var(--ease-out-3) infinite;
}
::after { animation-delay: -1s; }</code></pre>
</div>
</article>
<!-- 5. Gradient text -->
<article data-piece>
<div data-stage>
<div data-art="gradient-text">ASW</div>
</div>
<div data-explain>
<h3>Gradient text</h3>
<p>
<code>--gradient-1</code> is a purple-to-amber diagonal — normally
a background gradient. Applied via <code>background-clip: text</code>,
it becomes a fill. The typeset word becomes a window into the gradient
space below it.
</p>
<pre><code>[data-art="gradient-text"] {
background: var(--gradient-1);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}</code></pre>
</div>
</article>
<!-- 6. Hue tinting demo -->
<article data-piece>
<div data-stage>
<div data-hue-grid>
<div data-hue-swatch>
<div data-hue="0">
<div data-art="hue-blob"></div>
</div>
<span>--gray-hue: 0</span>
<span data-text="dim">red</span>
</div>
<div data-hue-swatch>
<div data-hue="45">
<div data-art="hue-blob"></div>
</div>
<span>--gray-hue: 45</span>
<span data-text="dim">amber</span>
</div>
<div data-hue-swatch>
<div data-hue="150">
<div data-art="hue-blob"></div>
</div>
<span>--gray-hue: 150</span>
<span data-text="dim">green</span>
</div>
<div data-hue-swatch>
<div data-hue="220">
<div data-art="hue-blob"></div>
</div>
<span>--gray-hue: 220</span>
<span data-text="dim">blue</span>
</div>
</div>
</div>
<div data-explain>
<h3>Hue tinting</h3>
<p>
ASW's <code>--gray-hue</code> cascades through all surfaces. The same blob,
the same gradient formula — only the hue angle changes. The oklch color space
keeps perceptual lightness constant across hues, so red and blue land at the
same visual weight.
</p>
<pre><code>[data-hue="0"] { --gray-hue: 0; }
[data-hue="45"] { --gray-hue: 45; }
[data-hue="150"] { --gray-hue: 150; }
[data-hue="220"] { --gray-hue: 220; }
background: radial-gradient(
circle at 30% 30%,
oklch(65% 0.18 var(--gray-hue)),
oklch(25% 0.06 var(--gray-hue))
);</code></pre>
</div>
</article>
<!-- 7. Waveform -->
<article data-piece>
<div data-stage>
<div data-art="waveform">
<div data-bar="1"></div>
<div data-bar="2"></div>
<div data-bar="3"></div>
<div data-bar="4"></div>
<div data-bar="5"></div>
<div data-bar="6"></div>
<div data-bar="7"></div>
<div data-bar="8"></div>
<div data-bar="9"></div>
<div data-bar="10"></div>
<div data-bar="11"></div>
<div data-bar="12"></div>
</div>
</div>
<div data-explain>
<h3>Waveform</h3>
<p>
Twelve bars, each a different height and animation phase. The bounce keyframe
is a squish-ease: it overshoots slightly at peak and returns. The stagger
is 200ms between each bar — enough to create a wave motion, not enough to
look sequential. It reads as a signal, not a list.
</p>
<pre><code>[data-art="waveform"] > [data-bar] {
background: var(--gradient-4);
animation: var(--animation-bounce);
}
[data-bar="1"] { height: 45%; animation-delay: -0.0s; }
[data-bar="2"] { height: 70%; animation-delay: -0.2s; }
/* … 12 bars total */</code></pre>
</div>
</article>
</div><!-- /gallery -->
<hr>
<p data-text="dim">
All pieces use only Open Props tokens and ASW data-attributes.
No <code>class</code>, no <code>id</code>, no JavaScript.
Source: <a href="../packs/flask/"><code>packs/</code></a> ·
Tokens: <a href="../docs/design-tokens.html">design-tokens</a>
</p>
</main>
<footer>
<p><a href="../index.html">ASW</a> · <a href="../docs/index.html">Docs</a> · CSS Art Lab</p>
</footer>
</body>
</html>