facelift: the scroll story - bento capabilities, dossier cards, series badges, GitOps receipt

02 Capabilities becomes a 4-col bento (Edge AI 2x2 flagship w/ magenta corner radial, Platform
wide, magenta-flavoured security tile, Observability row-completer) driven by span/flavor fields
in skills.ts. 03 Selected Work becomes dossier cards: house-style SVG thumbnails (per-project
motif via DossierThumb), DOSSIER/00N corner tags, 'the argument' line from the outcome field,
chip tags, mono meta footer. 04 Writing cards gain the security-series badge (data/series.ts)
and sit three across. Section numbers glow cyan; a circuit divider (gradient hairlines + two
diamonds) closes the hero. Footer opens with the GitOps receipt - git sha + build date baked at
build time via lib/build-info.ts, zero runtime calls.
This commit is contained in:
2026-07-03 19:43:45 +10:00
parent 65ba1ec7dc
commit 8d955aa802
13 changed files with 505 additions and 156 deletions
+126 -66
View File
@@ -1,94 +1,154 @@
---
// One bento tile in the capabilities grid — size/flavour driven by the data
// (span: hero 2×2 flagship · wide 2×1 · full row · default 1×1).
import type { SkillGroup } from "../data/skills";
interface Props {
group: SkillGroup;
}
const { group } = Astro.props;
const spanClass =
group.span === "hero"
? "tile--hero"
: group.span === "wide"
? "tile--wide"
: group.span === "full"
? "tile--full"
: "";
---
<article class="skill card" data-reveal>
<h3 class="skill__title">{group.title}</h3>
<p class="skill__blurb">{group.blurb}</p>
<ul class="skill__items">
<article
class:list={["tile", spanClass, group.flavor === "magenta" && "tile--magenta"]}
data-reveal
>
{group.span === "hero" && <div class="tile__corner" aria-hidden="true" />}
{group.flag && <p class="tile__flag mono">{group.flag}</p>}
<h3 class="tile__title">{group.title}</h3>
<p class="tile__blurb">{group.blurb}</p>
<ul class="tile__chips mono" role="list">
{group.items.map((item) => (
<li class="chip"><span class="chip__node" aria-hidden="true"></span>{item}</li>
<li class:list={["chip", group.span === "hero" && "chip--lit"]}>{item}</li>
))}
</ul>
</article>
<style>
.skill {
padding: var(--space-5);
.tile {
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
gap: var(--space-3);
gap: 12px;
padding: 28px;
background: var(--panel);
border: 1px solid var(--border-accent);
border-radius: 10px;
backdrop-filter: var(--panel-blur);
-webkit-backdrop-filter: var(--panel-blur);
transition:
border-color 180ms var(--ease),
box-shadow 180ms var(--ease);
}
.skill__title {
font-size: var(--step-1);
.tile:hover {
border-color: var(--border-accent-hover);
box-shadow: var(--glow-card);
}
.skill__title::before {
content: "# ";
color: var(--accent);
font-family: var(--font-mono);
.tile--magenta {
border-color: var(--border-magenta);
}
.skill__blurb {
color: var(--text-dim);
font-size: var(--step--1);
line-height: 1.5;
}
.skill__items {
list-style: none;
padding: 0;
margin: var(--space-2) 0 0;
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
.tile--magenta:hover {
border-color: rgba(232, 121, 249, 0.5);
box-shadow: var(--glow-card-magenta);
}
/* Circuit-node chips — a glowing cyan→magenta node + mono label, wired to the
board palette. Gradient border via padding-box/border-box layering so the
radius survives. Lights to a full gradient outline + glow on hover. */
.chip {
--chip-grad: linear-gradient(100deg, var(--accent), var(--accent-2));
display: inline-flex;
align-items: center;
gap: 0.45rem;
font-family: var(--font-mono);
font-size: 0.72rem;
letter-spacing: 0.01em;
.tile--hero {
grid-column: span 2;
grid-row: span 2;
padding: 32px;
gap: 16px;
border-color: rgba(63, 186, 245, 0.2);
}
.tile--wide {
grid-column: span 2;
}
.tile--full {
/* "full" = the row-completer: 3 columns, sharing its row with the 1×1 before it */
grid-column: span 3;
}
.tile__corner {
position: absolute;
inset: 0;
background: radial-gradient(
500px 320px at 85% 100%,
rgba(232, 121, 249, 0.1),
transparent 70%
);
pointer-events: none;
}
.tile__flag {
position: relative;
margin: 0;
font-size: 11px;
letter-spacing: 0.14em;
color: var(--accent-2);
}
.tile__title {
position: relative;
margin: 0;
font-family: var(--font-display);
font-size: 19px;
font-weight: 600;
color: var(--text-strong);
}
.tile--hero .tile__title {
font-size: 26px;
}
.tile__blurb {
position: relative;
margin: 0;
font-size: 14px;
line-height: 1.6;
color: var(--text-secondary);
text-wrap: pretty;
}
.tile--hero .tile__blurb {
font-size: 15px;
color: var(--text-dim);
padding: 0.3rem 0.62rem 0.3rem 0.55rem;
border-radius: 7px;
border: 1px solid var(--accent-line);
background: color-mix(in srgb, var(--surface-2) 88%, var(--accent) 12%);
transition: color 0.2s var(--ease), transform 0.2s var(--ease),
border-color 0.2s var(--ease), box-shadow 0.2s var(--ease),
background 0.2s var(--ease);
max-width: 420px;
}
/* The node: a small cyan→magenta square that glows, like a lit via/pad. */
.chip__node {
flex: none;
width: 6px;
height: 6px;
border-radius: 2px;
background: var(--chip-grad);
box-shadow: 0 0 7px var(--accent-glow);
.tile__chips {
position: relative;
list-style: none;
display: flex;
flex-wrap: wrap;
gap: 7px;
margin: auto 0 0;
padding: 0;
font-size: 11.5px;
color: var(--text-dim);
}
.chip:hover {
color: var(--text);
transform: translateY(-1px);
border-color: transparent;
/* dark fill (padding-box) inside a live gradient border (border-box) */
background: linear-gradient(var(--surface-2), var(--surface-2)) padding-box,
var(--chip-grad) border-box;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.32), 0 0 16px var(--accent-glow);
.chip {
border: 1px solid rgba(126, 139, 161, 0.25);
border-radius: var(--radius-chip);
padding: 4px 9px;
}
@media (prefers-reduced-motion: reduce) {
.chip {
transition: none;
}
.chip:hover {
transform: none;
.chip--lit {
font-size: 12px;
color: var(--text-body-strong);
border-color: rgba(63, 186, 245, 0.3);
padding: 5px 10px;
}
/* bento collapses gracefully on narrow screens (grid goes 2-col then 1-col
in the parent; spans clamp automatically via grid auto-placement) */
@media (max-width: 720px) {
.tile--hero,
.tile--wide,
.tile--full {
grid-column: 1 / -1;
grid-row: auto;
}
}
</style>