Editorial hero: demo floats top-right on wide viewports

Two visual fixes to the skill detail demo block.

1. Remove the 24px padding from .split-content. This padding was the
   'persistent indentation' visible in the screenshot: it created a
   white band between the container border and demo content that had
   its own card background. The overdrive demo (which fills the
   container via absolute canvases and 100% divs) lost some of its
   bleed to the padding; the polish-style demos (small centered cards)
   don't need it because .split-content already uses flex centering.

2. Restructure the skill detail header into a .skill-detail-hero
   wrapper that holds both the header text and the demo block.
   - At >=1100px viewport: switch to a grid (minmax(0,1fr) auto),
     text column on the left, demo on the right, align-items:center
     so the eyebrow/title/tagline center with the demo vertically.
     The demo floats as an editorial hero element alongside the title.
   - Below 1100px: stack (demo under the header) with clamp-based
     spacing between them. Same visual as before, just now inside the
     hero wrapper.
   - skill-detail-hero--has-demo class so skills without a demo
     (/shape) keep the single-column layout with no grid quirks.
This commit is contained in:
Paul Bakaus
2026-04-08 11:30:09 -07:00
parent b0c829a20e
commit b3a23e651e
2 changed files with 46 additions and 10 deletions
+35 -2
View File
@@ -1042,7 +1042,9 @@ main#main {
display: flex;
align-items: center;
justify-content: center;
padding: var(--spacing-md);
/* No padding: demos that fill the container (overdrive) need full
bleed, and demos with smaller content (polish, bolder) already
center themselves via flex. */
}
.split-after {
@@ -1107,10 +1109,41 @@ main#main {
SKILL DETAIL
============================================ */
.skill-detail-header {
/* Editorial hero: on wide viewports, text header on the left and the
before/after demo floats to the right as a hero module. On narrow
viewports everything stacks. */
.skill-detail-hero {
margin-bottom: clamp(2.5rem, 5vw, 3.5rem);
}
@media (min-width: 1100px) {
.skill-detail-hero--has-demo {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
gap: clamp(var(--spacing-lg), 4vw, var(--spacing-2xl));
align-items: start;
}
.skill-detail-hero--has-demo .skill-detail-header {
margin-bottom: 0;
align-self: center;
}
.skill-detail-hero--has-demo .skill-demo {
/* 500px visible container + 64px padding buffer stays 564px total.
Keep the eyebrow and labels vertically centered with the title.
Cancel the narrow-viewport stacking margin. */
align-self: center;
margin-top: 0;
}
}
/* Stacked spacing between header and demo on narrow viewports; overridden
by the grid gap when the hero switches to two columns at >=1100px. */
.skill-detail-hero--has-demo .skill-demo {
margin-top: clamp(2rem, 4vw, 2.5rem);
}
.skill-detail-eyebrow {
font-family: var(--font-mono);
font-size: 0.75rem;
+11 -8
View File
@@ -114,16 +114,19 @@ ${refBody}
${skill.argumentHint ? `<span class="skill-meta-chip skill-meta-args">${escapeHtml(skill.argumentHint)}</span>` : ''}
</div>`;
const hasDemo = demoHtml.trim().length > 0;
return `
<article class="skill-detail">
<header class="skill-detail-header">
<p class="skill-detail-eyebrow"><a href="/skills">Skills</a> / ${escapeHtml(categoryLabel)}</p>
<h1 class="skill-detail-title"><span class="skill-detail-title-slash">/</span>${escapeHtml(skill.id)}</h1>
<p class="skill-detail-tagline">${escapeHtml(tagline)}</p>
${metaStrip}
</header>
${demoHtml}
<div class="skill-detail-hero${hasDemo ? ' skill-detail-hero--has-demo' : ''}">
<header class="skill-detail-header">
<p class="skill-detail-eyebrow"><a href="/skills">Skills</a> / ${escapeHtml(categoryLabel)}</p>
<h1 class="skill-detail-title"><span class="skill-detail-title-slash">/</span>${escapeHtml(skill.id)}</h1>
<p class="skill-detail-tagline">${escapeHtml(tagline)}</p>
${metaStrip}
</header>
${demoHtml}
</div>
${editorialHtml ? `<section class="skill-detail-editorial prose">\n${editorialHtml}\n</section>` : ''}