mirror of
https://github.com/Nutlope/hallmark.git
synced 2026-08-14 12:35:33 +02:00
Merge the clear duplicates (gradient text into the gradient gate, macrostructure- repeat into the structural-fingerprint gate, the overflow-x:clip mandate into the horizontal-scroll gate, emoji-icon into the icon-libraries gate), collapse the five contrast gates to two, the five input-state gates to one, and the four hero gates to two. No coverage lost. Renumber 1–57 and update every gate-number and gate-total reference across SKILL.md, the reference docs, the landing copy, and the example builds.
584 lines
18 KiB
CSS
584 lines
18 KiB
CSS
/* Hallmark · route: custom · structure: tape-transport — sticky waveform-timeline nav over a vertical reel of recording "tracks" (no hero, no 3-up, no CTA template) · idea: "the section nav IS a drawn waveform-timeline you scrub; scroll = playback position, the played part lights up" · paper: oklch(17% 0.018 250) · accent: oklch(81% 0.155 178) · display: Fraunces · body: Spline Sans · gates: all-pass · v1.1 */
|
||
/* Hallmark · pre-emit critique: P5 H5 E5 S5 R4 V5 */
|
||
/* · contrast: pass (46–50) · nav: bespoke waveform-timeline · footer: Ft transport · slop: pass (51–55)
|
||
* · honest: pass (56) · chrome: pass (57) · tokens: pass (58) · responsive: pass (59) · icons: pass (60)
|
||
* · mobile: pass (36, 59, 61–69) */
|
||
|
||
/* ── Reset ─────────────────────────────────────────── */
|
||
*, *::before, *::after { box-sizing: border-box; }
|
||
* { margin: 0; padding: 0; }
|
||
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-behavior: smooth; }
|
||
html, body { overflow-x: clip; }
|
||
html { scroll-padding-top: calc(var(--dock) + var(--space-md)); }
|
||
body {
|
||
background: var(--paper);
|
||
color: var(--ink);
|
||
font-family: var(--font-body);
|
||
font-size: var(--text-md);
|
||
line-height: var(--leading-body);
|
||
-webkit-font-smoothing: antialiased;
|
||
text-rendering: optimizeLegibility;
|
||
}
|
||
img, svg, video { display: block; max-width: 100%; }
|
||
a { color: inherit; text-decoration: none; }
|
||
ul, ol { list-style: none; }
|
||
.mono { font-family: var(--font-mono); letter-spacing: var(--track-mono); font-variant-numeric: tabular-nums; }
|
||
|
||
/* Focus · instant, no fade, visible on any panel */
|
||
:focus-visible {
|
||
outline: 2px solid var(--focus);
|
||
outline-offset: 3px;
|
||
border-radius: 2px;
|
||
}
|
||
|
||
.skip {
|
||
position: fixed;
|
||
top: var(--space-sm);
|
||
left: var(--space-sm);
|
||
z-index: var(--z-skip);
|
||
padding: var(--space-2xs) var(--space-sm);
|
||
background: var(--accent);
|
||
color: var(--accent-ink);
|
||
font-weight: 600;
|
||
border-radius: var(--radius);
|
||
transform: translateY(-160%);
|
||
}
|
||
.skip:focus { transform: translateY(0); }
|
||
|
||
/* ── Layout primitives ─────────────────────────────── */
|
||
.shell {
|
||
width: 100%;
|
||
max-width: var(--max-w);
|
||
margin-inline: auto;
|
||
padding-inline: var(--gutter);
|
||
}
|
||
|
||
/* timecode + name stamp that opens every section (vertical stack — gate 54) */
|
||
.stamp {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: var(--space-xs);
|
||
font-size: var(--text-xs);
|
||
letter-spacing: var(--track-wide);
|
||
text-transform: uppercase;
|
||
color: var(--ink-mute);
|
||
}
|
||
.stamp__t {
|
||
font-family: var(--font-mono);
|
||
letter-spacing: var(--track-mono);
|
||
color: var(--accent);
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.stamp--ink { color: var(--ink-soft); }
|
||
|
||
.lede {
|
||
font-size: var(--text-lg);
|
||
line-height: var(--leading-snug);
|
||
color: var(--ink);
|
||
max-width: var(--measure);
|
||
}
|
||
|
||
/* ── Banner ────────────────────────────────────────── */
|
||
.banner {
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: var(--z-header);
|
||
height: var(--header-h);
|
||
background: var(--banner-glass);
|
||
backdrop-filter: blur(10px);
|
||
-webkit-backdrop-filter: blur(10px);
|
||
border-bottom: var(--hairline) solid var(--rule-soft);
|
||
}
|
||
.banner__inner {
|
||
height: 100%;
|
||
max-width: var(--max-w);
|
||
margin-inline: auto;
|
||
padding-inline: var(--gutter);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: var(--space-md);
|
||
}
|
||
.wordmark {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-2xs);
|
||
min-width: 0;
|
||
}
|
||
.wordmark__rec {
|
||
width: 9px; height: 9px;
|
||
border-radius: 50%;
|
||
background: var(--amber);
|
||
box-shadow: 0 0 0 0 var(--amber);
|
||
flex: none;
|
||
animation: rec 2.6s var(--ease) infinite;
|
||
}
|
||
.wordmark__name {
|
||
font-family: var(--font-display);
|
||
font-weight: 560;
|
||
font-size: var(--text-lg);
|
||
letter-spacing: var(--track-tight);
|
||
line-height: 1;
|
||
white-space: nowrap;
|
||
}
|
||
.wordmark__by {
|
||
font-size: var(--text-2xs);
|
||
letter-spacing: var(--track-wide);
|
||
text-transform: uppercase;
|
||
color: var(--ink-mute);
|
||
white-space: nowrap;
|
||
}
|
||
.banner__clock {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: var(--space-2xs);
|
||
font-family: var(--font-mono);
|
||
font-size: var(--text-xs);
|
||
letter-spacing: var(--track-mono);
|
||
font-variant-numeric: tabular-nums;
|
||
white-space: nowrap;
|
||
}
|
||
.banner__pos { color: var(--accent); font-weight: 500; }
|
||
.banner__total { color: var(--ink-faint); }
|
||
.banner__here {
|
||
font-family: var(--font-body);
|
||
letter-spacing: var(--track-wide);
|
||
text-transform: uppercase;
|
||
font-size: var(--text-2xs);
|
||
color: var(--ink-soft);
|
||
padding-left: var(--space-2xs);
|
||
border-left: var(--hairline) solid var(--rule);
|
||
}
|
||
|
||
/* ── The waveform-timeline · the navigation ────────── */
|
||
.timeline {
|
||
position: sticky;
|
||
top: var(--header-h);
|
||
z-index: var(--z-timeline);
|
||
height: var(--timeline-h);
|
||
background:
|
||
linear-gradient(180deg, var(--timeline-top), var(--timeline-bot));
|
||
backdrop-filter: blur(10px);
|
||
-webkit-backdrop-filter: blur(10px);
|
||
border-bottom: var(--hairline) solid var(--rule);
|
||
}
|
||
.timeline__inner {
|
||
position: relative;
|
||
height: 100%;
|
||
max-width: var(--max-w);
|
||
margin-inline: auto;
|
||
padding: var(--space-sm) var(--gutter) var(--space-md);
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
}
|
||
.timeline__lede {
|
||
position: absolute;
|
||
top: var(--space-2xs);
|
||
right: var(--gutter);
|
||
font-size: var(--text-2xs);
|
||
letter-spacing: var(--track-wide);
|
||
text-transform: uppercase;
|
||
color: var(--ink-faint);
|
||
}
|
||
|
||
/* the drawn wave */
|
||
.wave {
|
||
position: relative;
|
||
height: 46px;
|
||
margin-bottom: var(--space-sm);
|
||
}
|
||
.wave__svg {
|
||
position: absolute;
|
||
inset: 0;
|
||
width: 100%; height: 100%;
|
||
}
|
||
.wave__svg .bar { fill: var(--ink-faint); }
|
||
/* the "played" portion lights up — a clip driven by --p (0–1) set in JS */
|
||
.wave__played {
|
||
position: absolute;
|
||
inset: 0;
|
||
z-index: 1;
|
||
pointer-events: none;
|
||
background: linear-gradient(90deg, var(--accent-deep), var(--accent));
|
||
-webkit-mask: var(--wave-mask);
|
||
mask: var(--wave-mask);
|
||
-webkit-mask-size: 100% 100%;
|
||
mask-size: 100% 100%;
|
||
clip-path: inset(0 calc(100% - var(--p, 0) * 100%) 0 0);
|
||
filter: drop-shadow(0 0 6px var(--accent-dim));
|
||
}
|
||
.wave__playhead {
|
||
position: absolute;
|
||
top: -6px; bottom: -6px;
|
||
left: 0;
|
||
width: 2px;
|
||
z-index: 2;
|
||
background: var(--accent);
|
||
box-shadow: 0 0 8px 1px var(--accent);
|
||
transform: translateX(calc(var(--p, 0) * (100cqw - 2px)));
|
||
pointer-events: none;
|
||
}
|
||
.wave { container-type: inline-size; }
|
||
|
||
/* markers = the actual links */
|
||
.markers {
|
||
position: relative;
|
||
display: block;
|
||
height: 30px;
|
||
}
|
||
.marker {
|
||
position: absolute;
|
||
left: var(--at);
|
||
top: 0;
|
||
transform: translateX(-50%);
|
||
display: inline-flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 1px;
|
||
padding: var(--space-3xs) var(--space-2xs);
|
||
border-radius: var(--radius);
|
||
white-space: nowrap;
|
||
color: var(--ink-mute);
|
||
transition: color var(--dur) var(--ease), background-color var(--dur) var(--ease);
|
||
}
|
||
.marker::before {
|
||
content: "";
|
||
position: absolute;
|
||
top: calc(-1 * var(--space-sm) - 4px);
|
||
width: 1px; height: var(--space-sm);
|
||
background: var(--rule);
|
||
}
|
||
.marker__t {
|
||
font-family: var(--font-mono);
|
||
font-size: var(--text-2xs);
|
||
letter-spacing: var(--track-mono);
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.marker__n {
|
||
font-size: var(--text-2xs);
|
||
letter-spacing: 0.02em;
|
||
}
|
||
.marker:hover { color: var(--ink); background: var(--paper-3); }
|
||
.marker[aria-current="true"] { color: var(--accent); }
|
||
.marker[aria-current="true"]::before { background: var(--accent); height: calc(var(--space-sm) + 2px); }
|
||
.marker[aria-current="true"] .marker__t { color: var(--accent); }
|
||
|
||
/* hide the lesser markers on very small screens, keep them reachable via skip + scroll */
|
||
@media (max-width: 34rem) {
|
||
.timeline__lede { display: none; }
|
||
.marker__n { display: none; }
|
||
}
|
||
|
||
/* ── 00:00 · Signal ────────────────────────────────── */
|
||
section[tabindex] { scroll-margin-top: var(--dock); }
|
||
section[tabindex]:focus { outline: none; }
|
||
|
||
.signal { padding-block: var(--space-xl) var(--space-2xl); }
|
||
.signal__grid {
|
||
display: grid;
|
||
grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
|
||
column-gap: var(--space-2xl);
|
||
row-gap: var(--space-xl);
|
||
align-items: start;
|
||
}
|
||
.signal .stamp { grid-column: 1 / -1; }
|
||
.signal__title {
|
||
grid-column: 1;
|
||
font-family: var(--font-display);
|
||
font-weight: 460;
|
||
/* sized so the three-line statement clears the fold at 1280×800 — still the page's largest type */
|
||
font-size: clamp(2.75rem, 6.4vw, 4.75rem);
|
||
line-height: var(--leading-tight);
|
||
letter-spacing: var(--track-tight);
|
||
overflow-wrap: anywhere;
|
||
min-width: 0;
|
||
text-wrap: balance;
|
||
}
|
||
.signal__em { color: var(--accent); }
|
||
.signal__body {
|
||
grid-column: 2;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-md);
|
||
align-self: end;
|
||
}
|
||
.signal__note { color: var(--ink-soft); max-width: var(--measure); }
|
||
|
||
.reel {
|
||
grid-column: 1 / -1;
|
||
margin-top: var(--space-lg);
|
||
display: grid;
|
||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||
gap: var(--space-md);
|
||
padding-top: var(--space-lg);
|
||
border-top: var(--hairline) solid var(--rule);
|
||
}
|
||
.reel dt {
|
||
font-size: var(--text-2xs);
|
||
letter-spacing: var(--track-wide);
|
||
text-transform: uppercase;
|
||
color: var(--ink-faint);
|
||
margin-bottom: var(--space-3xs);
|
||
}
|
||
.reel dd { font-size: var(--text-sm); color: var(--ink-soft); }
|
||
.reel dd.mono { color: var(--ink); }
|
||
|
||
/* ── The works · reel of tracks ────────────────────── */
|
||
.reelworks { border-top: var(--hairline) solid var(--rule); }
|
||
.track {
|
||
padding-block: var(--space-2xl);
|
||
border-bottom: var(--hairline) solid var(--rule-soft);
|
||
}
|
||
.track__grid {
|
||
display: grid;
|
||
grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
|
||
column-gap: var(--space-2xl);
|
||
row-gap: var(--space-lg);
|
||
align-items: start;
|
||
}
|
||
/* alternate the reading offset so the reel doesn't march in lockstep */
|
||
.track--b .track__head { grid-column: 2; grid-row: 1; }
|
||
.track--b .track__loc { grid-column: 2; grid-row: 2; }
|
||
.track--b .track__copy { grid-column: 1; grid-row: 1 / 3; align-self: center; }
|
||
.track--b .minwave { grid-column: 1 / -1; }
|
||
|
||
.track__head { grid-column: 1; } /* eyebrow + heading stacked (gate 54) */
|
||
.track__title {
|
||
font-family: var(--font-display);
|
||
font-weight: 460;
|
||
font-size: var(--text-3xl);
|
||
line-height: var(--leading-tight);
|
||
letter-spacing: var(--track-tight);
|
||
margin-top: var(--space-xs);
|
||
overflow-wrap: anywhere;
|
||
min-width: 0;
|
||
text-wrap: balance;
|
||
}
|
||
.track__loc { grid-column: 1; font-size: var(--text-sm); color: var(--accent-deep); }
|
||
.track__copy {
|
||
grid-column: 2;
|
||
grid-row: 1 / 3;
|
||
align-self: center;
|
||
font-size: var(--text-lg);
|
||
line-height: var(--leading-snug);
|
||
color: var(--ink-soft);
|
||
max-width: var(--measure);
|
||
}
|
||
.minwave {
|
||
grid-column: 1 / -1;
|
||
margin-top: var(--space-sm);
|
||
padding: var(--space-md);
|
||
background: var(--paper-2);
|
||
border: var(--hairline) solid var(--rule-soft);
|
||
border-radius: var(--radius-lg);
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-2xs);
|
||
}
|
||
.minwave svg { width: 100%; height: 56px; }
|
||
.minwave .bar { fill: var(--ink-faint); }
|
||
.minwave .bar--hot { fill: var(--accent-deep); }
|
||
.minwave figcaption { font-size: var(--text-2xs); color: var(--ink-mute); align-self: flex-end; }
|
||
|
||
/* ── 33:20 · Method ────────────────────────────────── */
|
||
.method {
|
||
background: var(--paper-2);
|
||
padding-block: var(--space-3xl);
|
||
border-bottom: var(--hairline) solid var(--rule);
|
||
}
|
||
.method__grid {
|
||
display: grid;
|
||
grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
|
||
column-gap: var(--space-2xl);
|
||
row-gap: var(--space-xl);
|
||
align-items: start;
|
||
}
|
||
.method__head { grid-column: 1; }
|
||
.method__title {
|
||
font-family: var(--font-display);
|
||
font-weight: 460;
|
||
font-size: var(--text-2xl);
|
||
line-height: var(--leading-tight);
|
||
letter-spacing: var(--track-tight);
|
||
margin-top: var(--space-xs);
|
||
}
|
||
.method__lede {
|
||
grid-column: 1;
|
||
color: var(--ink-soft);
|
||
font-size: var(--text-lg);
|
||
line-height: var(--leading-snug);
|
||
max-width: 34ch;
|
||
}
|
||
.notes {
|
||
grid-column: 2;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
.note {
|
||
display: grid;
|
||
grid-template-columns: auto minmax(0, 1fr);
|
||
gap: var(--space-md);
|
||
padding-block: var(--space-md);
|
||
border-top: var(--hairline) solid var(--rule);
|
||
}
|
||
.note:first-child { border-top: 0; padding-top: 0; }
|
||
.note__k { color: var(--accent); font-size: var(--text-sm); padding-top: 0.2em; }
|
||
.note p { color: var(--ink-soft); max-width: var(--measure); }
|
||
|
||
/* ── 40:00 · Studio (closing) ──────────────────────── */
|
||
.studio {
|
||
padding-block: var(--space-3xl) var(--space-4xl);
|
||
background:
|
||
radial-gradient(120% 90% at 88% 0%, var(--studio-bloom), transparent 60%),
|
||
var(--paper);
|
||
}
|
||
.studio__grid {
|
||
display: grid;
|
||
grid-template-columns: minmax(0, 1fr);
|
||
gap: var(--space-md);
|
||
max-width: 50rem;
|
||
}
|
||
.studio .stamp { margin-bottom: var(--space-2xs); }
|
||
.studio__title {
|
||
font-family: var(--font-display);
|
||
font-weight: 560;
|
||
font-size: var(--text-4xl);
|
||
line-height: var(--leading-tight);
|
||
letter-spacing: var(--track-tight);
|
||
overflow-wrap: anywhere;
|
||
min-width: 0;
|
||
}
|
||
.studio__copy { color: var(--ink-soft); font-size: var(--text-lg); line-height: var(--leading-snug); max-width: var(--measure); }
|
||
.studio__actions {
|
||
margin-top: var(--space-md);
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
gap: var(--space-sm);
|
||
}
|
||
|
||
/* ── Button · 8 states ─────────────────────────────── */
|
||
.btn {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-height: 46px;
|
||
padding: 0 var(--space-lg);
|
||
background: var(--accent);
|
||
color: var(--accent-ink);
|
||
font-weight: 600;
|
||
font-size: var(--text-sm);
|
||
letter-spacing: 0.01em;
|
||
line-height: 1;
|
||
white-space: nowrap;
|
||
border: var(--hairline) solid transparent;
|
||
border-radius: var(--radius);
|
||
transition: background-color 0.22s var(--ease), color 0.22s var(--ease), border-color 0.22s var(--ease);
|
||
}
|
||
.btn:hover { background: var(--accent-deep); }
|
||
.btn:active { background: var(--accent-deep); transform: translateY(1px); }
|
||
.btn[aria-disabled="true"], .btn:disabled {
|
||
opacity: 0.55; cursor: not-allowed; background: var(--ink-faint); color: var(--paper);
|
||
}
|
||
.btn--ghost {
|
||
background: transparent;
|
||
color: var(--ink);
|
||
border-color: var(--rule);
|
||
}
|
||
.btn--ghost:hover { background: var(--paper-3); border-color: var(--ink-faint); }
|
||
.btn--ghost:active { background: var(--paper-3); }
|
||
|
||
/* ── Footer · transport bar ────────────────────────── */
|
||
.transport {
|
||
background: var(--paper-sink);
|
||
border-top: var(--hairline) solid var(--rule);
|
||
padding-block: var(--space-xl);
|
||
}
|
||
.transport__inner {
|
||
display: grid;
|
||
grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
|
||
gap: var(--space-lg) var(--space-2xl);
|
||
align-items: start;
|
||
}
|
||
.transport__mark {
|
||
font-family: var(--font-display);
|
||
font-size: var(--text-lg);
|
||
font-weight: 460;
|
||
line-height: var(--leading-snug);
|
||
color: var(--ink);
|
||
}
|
||
.transport__t {
|
||
display: block;
|
||
font-family: var(--font-mono);
|
||
font-size: var(--text-2xs);
|
||
letter-spacing: var(--track-wide);
|
||
color: var(--accent-deep);
|
||
margin-bottom: var(--space-2xs);
|
||
}
|
||
.transport__addr {
|
||
font-style: normal;
|
||
font-size: var(--text-sm);
|
||
line-height: var(--leading-body);
|
||
color: var(--ink-soft);
|
||
}
|
||
.transport__addr a { color: var(--ink); border-bottom: var(--hairline) solid var(--rule); }
|
||
.transport__addr a:hover { color: var(--accent); border-color: var(--accent); }
|
||
.transport__fine {
|
||
grid-column: 1 / -1;
|
||
padding-top: var(--space-md);
|
||
border-top: var(--hairline) solid var(--rule-soft);
|
||
font-size: var(--text-2xs);
|
||
color: var(--ink-faint);
|
||
}
|
||
|
||
/* ── Responsive ────────────────────────────────────── */
|
||
@media (max-width: 56rem) {
|
||
.signal__grid,
|
||
.track__grid,
|
||
.method__grid,
|
||
.transport__inner { grid-template-columns: minmax(0, 1fr); }
|
||
|
||
.signal__title,
|
||
.signal__body { grid-column: 1; }
|
||
.signal__body { align-self: start; }
|
||
|
||
.track__head, .track__loc, .track__copy,
|
||
.track--b .track__head, .track--b .track__loc, .track--b .track__copy, .track--b .minwave {
|
||
grid-column: 1;
|
||
grid-row: auto;
|
||
align-self: start;
|
||
}
|
||
.method__head, .method__lede, .notes { grid-column: 1; }
|
||
.reel { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||
}
|
||
|
||
@media (max-width: 34rem) {
|
||
:root { --timeline-h: 104px; }
|
||
.banner__by { display: none; }
|
||
.wordmark__by { display: none; }
|
||
.banner__here { display: none; }
|
||
.reel { grid-template-columns: minmax(0, 1fr); }
|
||
}
|
||
|
||
/* ── Reduced motion · timeline becomes plain anchor links ── */
|
||
@media (prefers-reduced-motion: reduce) {
|
||
html { scroll-behavior: auto; }
|
||
*, *::before, *::after {
|
||
animation-duration: 0.001ms !important;
|
||
animation-iteration-count: 1 !important;
|
||
transition-duration: 0.001ms !important;
|
||
}
|
||
.wordmark__rec { animation: none; }
|
||
/* No traveling playhead / fill: show the wave statically, hide the moving parts. */
|
||
.wave__played { display: none; }
|
||
.wave__playhead { display: none; }
|
||
.marker[aria-current="true"] { background: var(--paper-3); }
|
||
}
|
||
|
||
/* the REC pulse — the only ambient loop, amber tape-light */
|
||
@keyframes rec {
|
||
0%, 70%, 100% { box-shadow: 0 0 0 0 var(--amber-glow); }
|
||
35% { box-shadow: 0 0 0 5px var(--amber-glow-out); }
|
||
}
|