Refine Commands section: fisheye alignment, category ordering, install step

- Shrink fisheye list to 400px and vertically center it so items align
  with magazine spread content area
- Sharpen fisheye mask gradient for cleaner edge fade
- Prevent spread-flow ("leads to" etc.) from wrapping to multiple lines
- Sort fisheye/spread commands by category order instead of arbitrary
- Add beta badges to fisheye items
- Remove border-right on spread-identity and border-top on demo caption
- Add "Teach it your design" as step 2 in Get Started section
- Make spread-command-name nowrap, remove word-break/hyphens

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Paul Bakaus
2026-03-31 11:01:49 -07:00
co-authored by Claude Opus 4.6
parent 39930a4186
commit 107aa8b7e1
4 changed files with 84 additions and 31 deletions
+20 -8
View File
@@ -129,10 +129,11 @@
}
.fisheye-list {
position: relative;
height: 520px;
height: 400px;
align-self: center;
overflow: hidden;
mask-image: linear-gradient(to bottom, transparent 2%, black 12%, black 88%, transparent 98%);
-webkit-mask-image: linear-gradient(to bottom, transparent 2%, black 12%, black 88%, transparent 98%);
mask-image: linear-gradient(to bottom, transparent 0%, black 10%, black 90%, transparent 100%);
-webkit-mask-image: linear-gradient(to bottom, transparent 0%, black 10%, black 90%, transparent 100%);
}
.fisheye-scroll {
height: 100%;
@@ -172,6 +173,19 @@
.fisheye-item.is-active .fisheye-slash {
color: var(--color-accent);
}
.fisheye-beta {
font-family: var(--font-body);
font-size: 0.45rem;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--color-ash);
border: 1px solid var(--color-mist);
border-radius: 3px;
padding: 1px 4px;
margin-left: 0.35em;
vertical-align: middle;
}
.magazine-viewport {
position: relative;
height: 520px;
@@ -210,7 +224,6 @@
justify-content: center;
gap: var(--spacing-md);
padding-right: var(--spacing-lg);
border-right: 1px solid var(--color-mist);
}
.spread-category-label {
font-family: var(--font-body);
@@ -221,6 +234,7 @@
color: var(--spread-accent);
}
.spread-command-name {
white-space: nowrap;
font-family: var(--font-display);
font-size: clamp(3rem, 5.5vw, 5.5rem);
font-weight: 600;
@@ -228,8 +242,6 @@
color: var(--color-ink);
margin: 0;
letter-spacing: -0.02em;
word-break: break-word;
hyphens: auto;
}
.spread-command-name .spread-slash {
color: var(--spread-accent);
@@ -259,8 +271,9 @@
display: flex;
align-items: center;
gap: 6px;
flex-wrap: wrap;
flex-wrap: nowrap;
margin-top: var(--spacing-xs);
overflow: hidden;
}
.spread-flow-label {
font-family: var(--font-body);
@@ -362,7 +375,6 @@
color: var(--color-ash);
text-align: center;
padding: var(--spacing-sm) var(--spacing-md);
border-top: 1px solid var(--color-mist);
background: var(--color-paper);
}
.spread-demo-area .demo-container {
+22 -8
View File
@@ -36,10 +36,11 @@
/* Fisheye command list */
.fisheye-list {
position: relative;
height: 520px;
height: 400px;
align-self: center;
overflow: hidden;
mask-image: linear-gradient(to bottom, transparent 2%, black 12%, black 88%, transparent 98%);
-webkit-mask-image: linear-gradient(to bottom, transparent 2%, black 12%, black 88%, transparent 98%);
mask-image: linear-gradient(to bottom, transparent 0%, black 10%, black 90%, transparent 100%);
-webkit-mask-image: linear-gradient(to bottom, transparent 0%, black 10%, black 90%, transparent 100%);
}
.fisheye-scroll {
@@ -84,6 +85,21 @@
color: var(--color-accent);
}
.fisheye-beta {
font-family: var(--font-body);
font-size: 0.45rem;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--color-ash);
border: 1px solid var(--color-mist);
border-radius: 3px;
padding: 1px 4px;
margin-left: 0.35em;
vertical-align: middle;
}
/* The viewport that clips to one spread at a time */
.magazine-viewport {
position: relative;
@@ -130,7 +146,6 @@
justify-content: center;
gap: var(--spacing-md);
padding-right: var(--spacing-lg);
border-right: 1px solid var(--color-mist);
}
.spread-category-label {
@@ -143,6 +158,7 @@
}
.spread-command-name {
white-space: nowrap;
font-family: var(--font-display);
font-size: clamp(3rem, 5.5vw, 5.5rem);
font-weight: 600;
@@ -150,8 +166,6 @@
color: var(--color-ink);
margin: 0;
letter-spacing: -0.02em;
word-break: break-word;
hyphens: auto;
}
.spread-command-name .spread-slash {
@@ -186,8 +200,9 @@
display: flex;
align-items: center;
gap: 6px;
flex-wrap: wrap;
flex-wrap: nowrap;
margin-top: var(--spacing-xs);
overflow: hidden;
}
.spread-flow-label {
@@ -305,7 +320,6 @@
color: var(--color-ash);
text-align: center;
padding: var(--spacing-sm) var(--spacing-md);
border-top: 1px solid var(--color-mist);
background: var(--color-paper);
}
+16 -2
View File
@@ -252,7 +252,7 @@
<div class="section-header" data-reveal>
<span class="section-number">04</span>
<h2 class="section-title">Get Started</h2>
<p class="section-subtitle">Two steps to impeccable design.</p>
<p class="section-subtitle">Three steps to impeccable design.</p>
</div>
<div class="install-steps">
@@ -348,10 +348,24 @@
</details>
</div>
<!-- Step 2: Subscribe -->
<!-- Step 2: Set up design context -->
<div class="install-step" data-reveal>
<div class="install-step-header">
<span class="install-step-number">2</span>
<div class="install-step-meta">
<h3 class="install-step-title">Teach it your design</h3>
<p class="install-step-desc">Run once to set up your project's design context.</p>
</div>
</div>
<div class="install-terminal" style="margin-top: var(--spacing-sm);">
<code class="install-cmd" style="font-family: var(--font-mono); font-size: 0.875rem; color: var(--color-charcoal); display: block; padding: var(--spacing-sm) var(--spacing-md); background: var(--color-cream); border-radius: 6px; border: 1px solid var(--color-mist);"><span style="color: var(--color-accent);">/</span>impeccable teach</code>
</div>
</div>
<!-- Step 3: Subscribe -->
<div class="install-step" data-reveal>
<div class="install-step-header">
<span class="install-step-number">3</span>
<div class="install-step-meta">
<h3 class="install-step-title">Stay up to date</h3>
<p class="install-step-desc">New skills, pattern updates, and design tips.</p>
+26 -13
View File
@@ -79,26 +79,40 @@ function renderDesktopLayout(container, commands) {
}
magazineState.currentIndex = startIndex;
// Build ordered list with category separators for nav
// Filter out deprecated shims, then sort by category
const deprecated = new Set(['teach-impeccable', 'frontend-design', 'impeccable']);
const filteredCommands = commands.filter(c => !deprecated.has(c.id));
const categoryOrder = ['diagnostic', 'quality', 'adaptation', 'enhancement', 'intensity', 'system'];
const categoryLabelsShort = {
'diagnostic': 'Diagnose', 'quality': 'Quality', 'adaptation': 'Adapt',
'enhancement': 'Enhance', 'intensity': 'Intensity', 'system': 'System'
};
const grouped = {};
commands.forEach(cmd => {
filteredCommands.forEach(cmd => {
const cat = commandCategories[cmd.id] || 'other';
if (!grouped[cat]) grouped[cat] = [];
grouped[cat].push(cmd);
});
// Filter out deprecated shims
const deprecated = new Set(['teach-impeccable', 'frontend-design']);
const filteredCommands = commands.filter(c => !deprecated.has(c.id));
const orderedCommands = [];
const headerIndices = [];
categoryOrder.forEach(cat => {
if (!grouped[cat]) return;
headerIndices.push({ index: orderedCommands.length, label: categoryLabelsShort[cat] || cat });
orderedCommands.push(...grouped[cat]);
});
// Use ordered list for everything
filteredCommands.length = 0;
filteredCommands.push(...orderedCommands);
magazineState.commands = filteredCommands;
// Build spreads HTML
// Build spreads HTML (after ordering so indices match fisheye)
const spreadsHTML = filteredCommands.map((cmd, i) => renderSpread(cmd, i, i === startIndex)).join('');
// Build fisheye list
const fisheyeHTML = filteredCommands.map((cmd, i) => {
const cat = commandCategories[cmd.id] || 'other';
return `<button class="fisheye-item${i === startIndex ? ' is-active' : ''}" data-index="${i}" data-id="${cmd.id}" data-cat="${cat}"><span class="fisheye-slash">/</span>${cmd.id}</button>`;
const isBeta = betaCommands.includes(cmd.id);
return `<button class="fisheye-item${i === startIndex ? ' is-active' : ''}" data-index="${i}" data-id="${cmd.id}" data-cat="${cat}"><span class="fisheye-slash">/</span>${cmd.id}${isBeta ? '<span class="fisheye-beta">BETA</span>' : ''}</button>`;
}).join('');
container.innerHTML = `
@@ -116,7 +130,7 @@ function renderDesktopLayout(container, commands) {
initSpreadDemo(startIndex);
// Set up interactions
setupFisheyeList(filteredCommands);
setupFisheyeList(filteredCommands, headerIndices);
setupMagazineKeyboard(filteredCommands);
setupMagazineIntersection(container);
}
@@ -246,7 +260,7 @@ function goToSpread(newIndex, commands) {
}, 500);
}
function setupFisheyeList(commands) {
function setupFisheyeList(commands, headerIndices = []) {
const list = document.getElementById('fisheye-list');
const scroll = list?.querySelector('.fisheye-scroll');
const items = list ? [...list.querySelectorAll('.fisheye-item')] : [];
@@ -318,8 +332,7 @@ function setupFisheyeList(commands) {
let y = offset;
items.forEach((item, i) => {
const h = heights[i];
const dist = Math.abs(i - center);
const scale = getScale(dist);
const scale = getScale(Math.abs(i - center));
const opacity = 0.25 + (scale - MIN_SCALE) / (1 - MIN_SCALE) * 0.75;
item.style.top = `${y}px`;