Files
cybersteel/preview/index.html
T

966 lines
30 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Browse the Cybersteel design-system reference gallery.">
<title>Preview Index — Cybersteel</title>
<link rel="stylesheet" href="../styles.css">
<style>
:root {
--gallery-width: 1240px;
--gallery-gutter: clamp(20px, 5vw, 72px);
}
html {
scroll-behavior: smooth;
}
body {
min-width: 320px;
min-height: 100vh;
margin: 0;
background:
var(--gradient-scanline),
radial-gradient(circle at 82% 0%, rgba(250, 189, 47, 0.08), transparent 31rem),
var(--bg-page);
}
a {
color: inherit;
}
.skip-link {
position: fixed;
top: 12px;
left: 12px;
z-index: 100;
padding: 8px 12px;
background: var(--gold-bright);
color: var(--bg-shell);
font-family: var(--font-mono);
font-size: var(--text-xs);
font-weight: var(--weight-semibold);
transform: translateY(-160%);
transition: transform var(--transition-ui);
}
.skip-link:focus {
transform: translateY(0);
}
.shell {
width: min(100%, calc(var(--gallery-width) + (var(--gallery-gutter) * 2)));
margin: 0 auto;
padding-inline: var(--gallery-gutter);
}
.masthead {
background: rgba(29, 32, 33, 0.94);
border-bottom: 1px solid var(--border);
}
.masthead-bar {
display: flex;
align-items: center;
justify-content: space-between;
min-height: 68px;
gap: var(--space-panel);
}
.brand {
display: inline-flex;
align-items: baseline;
gap: var(--space-component);
color: var(--fg-heading);
}
.brand-name {
font-family: var(--font-display);
font-size: var(--text-lg);
font-weight: var(--weight-bold);
letter-spacing: var(--tracking-wider);
text-transform: uppercase;
}
.brand-context {
padding-left: var(--space-component);
border-left: 1px solid var(--gold-dim);
color: var(--fg-muted);
font-family: var(--font-mono);
font-size: 9px;
letter-spacing: var(--tracking-widest);
text-transform: uppercase;
}
.system-state {
display: flex;
align-items: center;
gap: var(--space-element);
font-family: var(--font-mono);
font-size: var(--text-xs);
letter-spacing: var(--tracking-wider);
text-transform: uppercase;
color: var(--fg-caption);
}
.state-light {
width: 7px;
height: 7px;
border-radius: var(--radius-pill);
background: var(--green-bright);
box-shadow: 0 0 0 3px rgba(184, 187, 38, 0.12);
}
.hero {
display: grid;
grid-template-columns: minmax(0, 1.55fr) minmax(280px, 0.65fr);
gap: clamp(40px, 8vw, 108px);
align-items: end;
padding-block: clamp(64px, 9vw, 112px) clamp(52px, 7vw, 88px);
}
.eyebrow,
.section-index,
.card-index,
.search-label,
.meta-label {
font-family: var(--font-mono);
text-transform: uppercase;
}
.eyebrow {
display: flex;
align-items: center;
gap: var(--space-component);
margin-bottom: var(--space-cluster);
color: var(--gold-bright);
font-size: var(--text-xs);
letter-spacing: var(--tracking-widest);
}
.eyebrow::before {
content: "";
width: 34px;
height: 1px;
background: var(--gold-dim);
}
.hero h1 {
max-width: 760px;
margin-bottom: var(--space-panel);
font-size: clamp(44px, 7vw, 84px);
line-height: 0.94;
letter-spacing: -0.025em;
}
.hero-copy {
max-width: 680px;
margin: 0;
color: var(--fg-secondary);
font-size: clamp(16px, 2vw, 19px);
line-height: var(--leading-loose);
}
.hero-copy strong {
color: var(--fg-heading);
font-weight: var(--weight-medium);
}
.stats {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
border: 1px solid var(--border);
border-top-color: var(--gold-dim);
background: rgba(60, 56, 54, 0.58);
}
.stat {
min-height: 112px;
padding: var(--space-cluster);
border-right: 1px solid var(--border-subtle);
border-bottom: 1px solid var(--border-subtle);
}
.stat:nth-child(2n) {
border-right: 0;
}
.stat:nth-last-child(-n + 2) {
border-bottom: 0;
}
.stat-value {
display: block;
margin-bottom: var(--space-element);
color: var(--fg-heading);
font-family: var(--font-mono);
font-size: var(--text-2xl);
font-weight: var(--weight-semibold);
line-height: 1;
}
.stat-label {
color: var(--fg-muted);
font-family: var(--font-mono);
font-size: 9px;
letter-spacing: var(--tracking-wider);
line-height: var(--leading-normal);
text-transform: uppercase;
}
.explorer-bar {
position: sticky;
top: 0;
z-index: 20;
background: rgba(29, 32, 33, 0.97);
border-block: 1px solid var(--border);
}
.explorer-controls {
display: grid;
grid-template-columns: minmax(240px, 0.7fr) minmax(0, 1.3fr);
gap: var(--space-panel);
align-items: center;
min-height: 86px;
}
.search-wrap {
position: relative;
}
.search-label {
position: absolute;
top: 50%;
left: var(--space-group);
color: var(--gold-dim);
font-size: 10px;
font-weight: var(--weight-semibold);
letter-spacing: var(--tracking-widest);
transform: translateY(-50%);
pointer-events: none;
}
.search-input {
width: 100%;
min-height: 46px;
padding: 11px 48px 11px 104px;
border: 1px solid var(--border);
border-radius: var(--radius-md);
background: var(--bg-page);
color: var(--fg-body);
font-family: var(--font-body);
font-size: var(--text-sm);
outline: none;
transition: border-color var(--transition-hover), box-shadow var(--transition-hover);
}
.search-input::placeholder {
color: var(--fg-muted);
}
.search-input:focus {
border-color: var(--gold-bright);
box-shadow: var(--shadow-gold);
}
.search-key {
position: absolute;
top: 50%;
right: var(--space-component);
padding: 2px 6px;
border: 1px solid var(--border-subtle);
border-radius: var(--radius-sm);
color: var(--fg-muted);
font-family: var(--font-mono);
font-size: 9px;
transform: translateY(-50%);
pointer-events: none;
}
.category-nav {
display: flex;
justify-content: flex-end;
gap: var(--space-element);
overflow-x: auto;
scrollbar-width: thin;
}
.category-nav a {
display: inline-flex;
flex: 0 0 auto;
align-items: center;
gap: var(--space-element);
min-height: 38px;
padding: 7px 10px;
border: 1px solid transparent;
border-radius: var(--radius-sm);
color: var(--fg-caption);
font-family: var(--font-mono);
font-size: 10px;
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
transition: color var(--transition-hover), border-color var(--transition-hover), background var(--transition-hover);
}
.category-nav a:hover {
border-color: var(--gold-dim);
background: rgba(215, 153, 33, 0.12);
color: var(--fg-heading);
}
.category-count {
color: var(--gold-bright);
}
main {
padding-block: var(--space-region) var(--space-canvas);
}
.gallery-section {
scroll-margin-top: 116px;
padding-block: 0 var(--space-zone);
}
.gallery-section + .gallery-section {
padding-top: var(--space-region);
border-top: 1px solid var(--border-subtle);
}
.section-heading {
display: grid;
grid-template-columns: 70px minmax(220px, 0.75fr) minmax(280px, 1fr);
gap: var(--space-panel);
align-items: start;
margin-bottom: var(--space-block);
}
.section-index {
padding-top: 6px;
color: var(--gold-dim);
font-size: var(--text-xs);
letter-spacing: var(--tracking-widest);
}
.section-heading h2 {
margin: 0;
font-size: clamp(24px, 3vw, 36px);
letter-spacing: var(--tracking-wide);
}
.section-heading p {
max-width: 610px;
margin: 3px 0 0;
color: var(--fg-caption);
font-size: var(--text-sm);
line-height: var(--leading-loose);
}
.card-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: var(--space-group);
}
.preview-card {
position: relative;
display: flex;
min-height: 226px;
flex-direction: column;
padding: var(--space-panel);
overflow: hidden;
border: 1px solid var(--border);
border-radius: var(--radius-md);
background:
linear-gradient(135deg, rgba(250, 189, 47, 0.045), transparent 48%),
var(--bg-surface);
transition:
background var(--transition-hover),
border-color var(--transition-hover),
box-shadow var(--transition-hover),
color var(--transition-hover);
}
.preview-card::after {
content: "";
position: absolute;
right: -64px;
bottom: -86px;
width: 190px;
height: 190px;
border: 1px solid rgba(215, 153, 33, 0.13);
transform: rotate(45deg);
transition: border-color var(--transition-hover), transform var(--transition-hover);
}
.preview-card:hover {
border-color: var(--gold-dim);
box-shadow: 0 0 0 3px rgba(215, 153, 33, 0.2);
}
.preview-card:hover::after {
border-color: rgba(250, 189, 47, 0.42);
transform: rotate(45deg) translate(-4px, -4px);
}
.preview-card:active {
border-color: var(--gold-bright);
background: rgba(215, 153, 33, 0.19);
box-shadow: none;
transition-duration: 55ms;
}
.card-topline {
position: relative;
z-index: 1;
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-component);
margin-bottom: var(--space-block);
}
.card-index {
color: var(--fg-muted);
font-size: 10px;
letter-spacing: var(--tracking-widest);
}
.card-badge {
padding: 3px 7px;
border: 1px solid var(--gold-dim);
border-radius: var(--radius-sm);
color: var(--gold-bright);
font-family: var(--font-mono);
font-size: 8px;
letter-spacing: var(--tracking-wider);
line-height: 1.4;
text-transform: uppercase;
}
.preview-card h3 {
position: relative;
z-index: 1;
margin-bottom: var(--space-component);
color: var(--fg-heading);
font-size: var(--text-xl);
}
.preview-card p {
position: relative;
z-index: 1;
max-width: 520px;
margin-bottom: var(--space-panel);
color: var(--fg-secondary);
font-size: var(--text-sm);
line-height: var(--leading-normal);
}
.card-footer {
position: relative;
z-index: 1;
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: var(--space-group);
margin-top: auto;
}
.card-meta {
display: flex;
flex-wrap: wrap;
gap: var(--space-element);
}
.meta-item {
color: var(--fg-muted);
font-family: var(--font-mono);
font-size: 9px;
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
}
.meta-item + .meta-item::before {
content: "◆";
margin-right: var(--space-element);
color: var(--gold-muted);
font-size: 6px;
vertical-align: 1px;
}
.card-arrow {
display: grid;
width: 34px;
height: 34px;
flex: 0 0 auto;
place-items: center;
border: 1px solid var(--border);
border-radius: var(--radius-sm);
color: var(--gold-bright);
font-family: var(--font-mono);
transition: background var(--transition-hover), border-color var(--transition-hover), color var(--transition-hover);
}
.preview-card:hover .card-arrow {
border-color: var(--gold-bright);
background: var(--gold-bright);
color: var(--bg-shell);
}
.empty-state {
display: none;
padding: var(--space-region) var(--space-panel);
border: 1px solid var(--border);
border-left: 2px solid var(--gold-dim);
background: var(--bg-surface);
}
.empty-state strong {
display: block;
margin-bottom: var(--space-element);
color: var(--fg-heading);
font-family: var(--font-display);
font-size: var(--text-lg);
}
.empty-state span {
color: var(--fg-caption);
font-family: var(--font-mono);
font-size: var(--text-sm);
}
.footer {
border-top: 1px solid var(--border);
background: var(--bg-shell);
}
.footer-inner {
display: flex;
align-items: center;
justify-content: space-between;
min-height: 116px;
gap: var(--space-panel);
}
.footer-note {
margin: 0;
color: var(--fg-caption);
font-family: var(--font-mono);
font-size: var(--text-xs);
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
}
.footer-note strong {
color: var(--fg-heading);
font-weight: var(--weight-medium);
}
.to-top {
color: var(--gold-bright);
font-family: var(--font-mono);
font-size: var(--text-xs);
letter-spacing: var(--tracking-wider);
text-transform: uppercase;
}
[hidden] {
display: none !important;
}
@media (max-width: 980px) {
.hero {
grid-template-columns: 1fr;
}
.stats {
max-width: 600px;
}
.explorer-controls {
grid-template-columns: 1fr;
gap: var(--space-component);
padding-block: var(--space-group);
}
.category-nav {
justify-content: flex-start;
padding-bottom: 2px;
}
.section-heading {
grid-template-columns: 50px 1fr;
}
.section-heading p {
grid-column: 2;
}
}
@media (max-width: 720px) {
.shell {
padding-inline: 18px;
}
.system-state {
display: none;
}
.hero h1 {
font-size: clamp(42px, 15vw, 64px);
}
.stats {
width: 100%;
}
.section-heading {
display: block;
}
.section-index {
display: block;
margin-bottom: var(--space-element);
}
.section-heading p {
margin-top: var(--space-component);
}
.card-grid {
grid-template-columns: 1fr;
}
.preview-card {
min-height: 214px;
}
.footer-inner {
align-items: flex-start;
flex-direction: column;
justify-content: center;
}
}
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
*, *::before, *::after {
transition-duration: 0.01ms !important;
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
}
}
</style>
</head>
<body id="top">
<a class="skip-link" href="#gallery">Skip to gallery</a>
<header class="masthead">
<div class="shell masthead-bar">
<a class="brand" href="index.html" aria-label="Cybersteel preview index">
<span class="brand-name">Cybersteel</span>
<span class="brand-context">Preview Index</span>
</a>
<div class="system-state" aria-label="Reference gallery status">
<span class="state-light" aria-hidden="true"></span>
Reference set online
</div>
</div>
<div class="shell hero">
<div>
<div class="eyebrow">Design system reference</div>
<h1>Preview<br>Index</h1>
<p class="hero-copy">
Explore the complete visual language through <strong>16 focused references</strong>.
Start with the foundations, inspect the type system, then move through structure,
effects, components, and live interaction states.
</p>
</div>
<div class="stats" aria-label="Gallery summary">
<div class="stat"><span class="stat-value">16</span><span class="stat-label">Reference pages</span></div>
<div class="stat"><span class="stat-value">04</span><span class="stat-label">System groups</span></div>
<div class="stat"><span class="stat-value">07</span><span class="stat-label">Live demos</span></div>
<div class="stat"><span class="stat-value">00</span><span class="stat-label">Remote assets</span></div>
</div>
</div>
</header>
<div class="explorer-bar">
<div class="shell explorer-controls">
<div class="search-wrap">
<label class="search-label" for="preview-search">Search</label>
<input class="search-input" id="preview-search" type="search" placeholder="Color, type, states…" autocomplete="off" spellcheck="false">
<span class="search-key" aria-hidden="true">/</span>
</div>
<nav class="category-nav" aria-label="Preview categories">
<a href="#foundations">Foundations <span class="category-count">03</span></a>
<a href="#typography">Typography <span class="category-count">04</span></a>
<a href="#structure">Structure <span class="category-count">03</span></a>
<a href="#components">Components <span class="category-count">06</span></a>
</nav>
</div>
</div>
<main class="shell" id="gallery">
<section class="gallery-section" id="foundations" data-section>
<div class="section-heading">
<span class="section-index">01 / 04</span>
<h2>Foundations</h2>
<p>Core color primitives. Review the base surfaces, accent ramps, and semantic roles before applying the system.</p>
</div>
<div class="card-grid">
<a class="preview-card" href="colors-base.html" data-card data-search="foundations color base palette background foreground surfaces text pairings gruvbox">
<div class="card-topline"><span class="card-index">REF—01</span></div>
<h3>Base Palette</h3>
<p>Background and foreground ramps, default pairings, contextual text, and surface combinations.</p>
<div class="card-footer">
<div class="card-meta"><span class="meta-item">Color</span><span class="meta-item">Surfaces</span></div>
<span class="card-arrow" aria-hidden="true"></span>
</div>
</a>
<a class="preview-card" href="colors-accents.html" data-card data-search="foundations color accent gold red green blue teal orange aqua purple swatches ramps">
<div class="card-topline"><span class="card-index">REF—02</span></div>
<h3>Accent Colors</h3>
<p>Bright, dim, and muted ramps for gold, red, green, blue, orange, aqua, and purple.</p>
<div class="card-footer">
<div class="card-meta"><span class="meta-item">Color</span><span class="meta-item">Ramps</span></div>
<span class="card-arrow" aria-hidden="true"></span>
</div>
</a>
<a class="preview-card" href="colors-semantic.html" data-card data-search="foundations semantic color primary success danger warning info disabled buttons text roles">
<div class="card-topline"><span class="card-index">REF—03</span></div>
<h3>Semantic Colors</h3>
<p>Primary, success, danger, warning, info, and disabled roles shown across text and controls.</p>
<div class="card-footer">
<div class="card-meta"><span class="meta-item">Color</span><span class="meta-item">Roles</span></div>
<span class="card-arrow" aria-hidden="true"></span>
</div>
</a>
</div>
</section>
<section class="gallery-section" id="typography" data-section>
<div class="section-heading">
<span class="section-index">02 / 04</span>
<h2>Typography</h2>
<p>IBM Plex Sans carries the primary hierarchy. IBM Plex Mono handles code, logs, aligned data, and opt-in terminal surfaces.</p>
</div>
<div class="card-grid">
<a class="preview-card" href="type-display.html" data-card data-search="typography display ibm plex sans hero heading subheading hierarchy scale">
<div class="card-topline"><span class="card-index">REF—04</span></div>
<h3>Display Type</h3>
<p>Plex Sans display hierarchy across hero, heading, subheading, body, and light text treatments.</p>
<div class="card-footer">
<div class="card-meta"><span class="meta-item">Plex Sans</span><span class="meta-item">Display</span></div>
<span class="card-arrow" aria-hidden="true"></span>
</div>
</a>
<a class="preview-card" href="type-body.html" data-card data-search="typography body ibm plex sans scale prose paragraph labels captions">
<div class="card-topline"><span class="card-index">REF—05</span></div>
<h3>Body Type</h3>
<p>Readable body sizing, weights, labels, captions, and supporting text within the core type scale.</p>
<div class="card-footer">
<div class="card-meta"><span class="meta-item">Plex Sans</span><span class="meta-item">Body</span></div>
<span class="card-arrow" aria-hidden="true"></span>
</div>
</a>
<a class="preview-card" href="type-mono.html" data-card data-search="typography mono terminal ibm plex mono code logs data timestamps console">
<div class="card-topline"><span class="card-index">REF—06</span></div>
<h3>Mono / Terminal</h3>
<p>Plex Mono specimens for terminal output, code, logs, timestamps, and aligned operational data.</p>
<div class="card-footer">
<div class="card-meta"><span class="meta-item">Plex Mono</span><span class="meta-item">Data</span></div>
<span class="card-arrow" aria-hidden="true"></span>
</div>
</a>
<a class="preview-card" href="type-sans.html" data-card data-search="typography sans mono mode comparison opt-in terminal default hierarchy">
<div class="card-topline"><span class="card-index">REF—07</span></div>
<h3>Sans vs. Mono Mode</h3>
<p>Side-by-side comparison of the default Sans system and the opt-in, fully terminal-styled Mono mode.</p>
<div class="card-footer">
<div class="card-meta"><span class="meta-item">Modes</span><span class="meta-item">Comparison</span></div>
<span class="card-arrow" aria-hidden="true"></span>
</div>
</a>
</div>
</section>
<section class="gallery-section" id="structure" data-section>
<div class="section-heading">
<span class="section-index">03 / 04</span>
<h2>Structure &amp; Effects</h2>
<p>Layout rhythm and surface construction: the spacing scale, crisp border geometry, radius choices, and flat elevation model.</p>
</div>
<div class="card-grid">
<a class="preview-card" href="spacing-tokens.html" data-card data-search="structure spacing tokens grid rhythm 4px 8px chip element component group panel section">
<div class="card-topline"><span class="card-index">REF—08</span></div>
<h3>Spacing Tokens</h3>
<p>The complete 496px spacing scale, labeled by token and demonstrated in practical layout contexts.</p>
<div class="card-footer">
<div class="card-meta"><span class="meta-item">Spacing</span><span class="meta-item">8px Grid</span></div>
<span class="card-arrow" aria-hidden="true"></span>
</div>
</a>
<a class="preview-card" href="borders-radius.html" data-card data-search="structure effects border borders radius radii corners 6px spinner animation shape">
<div class="card-topline"><span class="card-index">REF—09</span><span class="card-badge">Animated</span></div>
<h3>Borders &amp; Radius</h3>
<p>Structural and semantic borders plus the radius scale across buttons, cards, inputs, and a loading spinner.</p>
<div class="card-footer">
<div class="card-meta"><span class="meta-item">Borders</span><span class="meta-item">Shape</span></div>
<span class="card-arrow" aria-hidden="true"></span>
</div>
</a>
<a class="preview-card" href="shadows-elevation.html" data-card data-search="structure effects shadows elevation flat surfaces hover press interactive cards border background">
<div class="card-topline"><span class="card-index">REF—10</span><span class="card-badge">Interactive</span></div>
<h3>Shadows &amp; Elevation</h3>
<p>Flat elevation through background and border changes, with interactive card hover and press behavior.</p>
<div class="card-footer">
<div class="card-meta"><span class="meta-item">Elevation</span><span class="meta-item">Effects</span></div>
<span class="card-arrow" aria-hidden="true"></span>
</div>
</a>
</div>
</section>
<section class="gallery-section" id="components" data-section>
<div class="section-heading">
<span class="section-index">04 / 04</span>
<h2>Components &amp; States</h2>
<p>Reusable interface patterns and their behavior. Hover, focus, press, validation, loading, and disabled states are live where marked.</p>
</div>
<div class="card-grid">
<a class="preview-card" href="components-buttons.html" data-card data-search="components buttons primary secondary danger ghost hover press interactive states controls">
<div class="card-topline"><span class="card-index">REF—11</span><span class="card-badge">Interactive</span></div>
<h3>Buttons</h3>
<p>Primary, secondary, and danger controls with the three-step default, hover, and press treatment.</p>
<div class="card-footer">
<div class="card-meta"><span class="meta-item">Controls</span><span class="meta-item">Motion</span></div>
<span class="card-arrow" aria-hidden="true"></span>
</div>
</a>
<a class="preview-card" href="components-inputs.html" data-card data-search="components forms inputs select focus error success validation interactive halo fields">
<div class="card-topline"><span class="card-index">REF—12</span><span class="card-badge">Interactive</span></div>
<h3>Form Inputs</h3>
<p>Text and select controls with focus, error, success, validation, and transition behavior.</p>
<div class="card-footer">
<div class="card-meta"><span class="meta-item">Forms</span><span class="meta-item">Validation</span></div>
<span class="card-arrow" aria-hidden="true"></span>
</div>
</a>
<a class="preview-card" href="components-cards.html" data-card data-search="components cards stat deploy alert surface clickable hover halo press interactive">
<div class="card-topline"><span class="card-index">REF—13</span><span class="card-badge">Interactive</span></div>
<h3>Cards</h3>
<p>Static data surfaces and clickable cards, including stat, alert, deploy, hover, and press treatments.</p>
<div class="card-footer">
<div class="card-meta"><span class="meta-item">Surfaces</span><span class="meta-item">States</span></div>
<span class="card-arrow" aria-hidden="true"></span>
</div>
</a>
<a class="preview-card" href="components-badges.html" data-card data-search="components badges status online offline degraded error running complete failed labels indicators">
<div class="card-topline"><span class="card-index">REF—14</span></div>
<h3>Badges &amp; Status</h3>
<p>System, process, and neutral indicators for online, degraded, running, complete, failed, and labeled states.</p>
<div class="card-footer">
<div class="card-meta"><span class="meta-item">Status</span><span class="meta-item">Labels</span></div>
<span class="card-arrow" aria-hidden="true"></span>
</div>
</a>
<a class="preview-card" href="components-nav.html" data-card data-search="components navigation nav tabs top side hover active divider interactive states">
<div class="card-topline"><span class="card-index">REF—15</span><span class="card-badge">Interactive</span></div>
<h3>Navigation</h3>
<p>Top-tab and side-navigation explorations with active selection, divider, and hover behavior.</p>
<div class="card-footer">
<div class="card-meta"><span class="meta-item">Navigation</span><span class="meta-item">Patterns</span></div>
<span class="card-arrow" aria-hidden="true"></span>
</div>
</a>
<a class="preview-card" href="components-states.html" data-card data-search="components states hover focus press release transition spinner loading disabled interactive motion buttons">
<div class="card-topline"><span class="card-index">REF—16</span><span class="card-badge">Interactive</span></div>
<h3>Component States</h3>
<p>Live hover, focus, press, release, disabled, loading, spinner, and timing references in one matrix.</p>
<div class="card-footer">
<div class="card-meta"><span class="meta-item">States</span><span class="meta-item">Motion</span></div>
<span class="card-arrow" aria-hidden="true"></span>
</div>
</a>
</div>
</section>
<div class="empty-state" id="empty-state" role="status" aria-live="polite">
<strong>No matching references.</strong>
<span>Clear the search or use another system term.</span>
</div>
</main>
<footer class="footer">
<div class="shell footer-inner">
<p class="footer-note"><strong>Cybersteel</strong> / Local reference gallery / No remote dependencies</p>
<a class="to-top" href="#top">Return to top ↑</a>
</div>
</footer>
<script>
(function () {
var input = document.getElementById('preview-search');
var cards = Array.prototype.slice.call(document.querySelectorAll('[data-card]'));
var sections = Array.prototype.slice.call(document.querySelectorAll('[data-section]'));
var emptyState = document.getElementById('empty-state');
function filterGallery() {
var query = input.value.trim().toLowerCase();
var visibleCount = 0;
cards.forEach(function (card) {
var matches = !query || card.getAttribute('data-search').indexOf(query) !== -1 || card.textContent.toLowerCase().indexOf(query) !== -1;
card.hidden = !matches;
if (matches) visibleCount += 1;
});
sections.forEach(function (section) {
var hasVisibleCards = section.querySelector('[data-card]:not([hidden])');
section.hidden = !hasVisibleCards;
});
emptyState.style.display = visibleCount ? 'none' : 'block';
}
input.addEventListener('input', filterGallery);
document.addEventListener('keydown', function (event) {
if (event.key === '/' && document.activeElement !== input) {
event.preventDefault();
input.focus();
}
if (event.key === 'Escape' && document.activeElement === input) {
input.value = '';
filterGallery();
input.blur();
}
});
}());
</script>
</body>
</html>