<style>
:root {
--ink: #3e2155;
--purple: #672c72;
--muted: #6b6880;
--eyebrow: #6d648f;
--page: #f2eef8;
--hair: rgba(62, 33, 85, 0.12);
--hair-soft: rgba(62, 33, 85, 0.07);
--green: #178055;
--blue: #1f5f9b;
--amber: #9a6207;
--font: "Satoshi", ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
}
.wrap {
font-family: var(--font);
color: var(--ink);
background: var(--page);
padding: 36px 24px 72px;
max-width: 1180px;
margin: 0 auto;
line-height: 1.5;
}
h1 {
font-size: 30px;
font-weight: 800;
margin: 0 0 8px;
letter-spacing: -0.01em;
}
.lede {
color: var(--muted);
max-width: 66ch;
margin: 0 0 6px;
}
.note {
background: #fff;
border: 1px solid var(--hair);
border-radius: 12px;
padding: 16px 20px;
margin: 22px 0 40px;
max-width: 74ch;
}
.note p {
margin: 0;
color: var(--muted);
font-size: 14px;
}
.note strong {
color: var(--ink);
}
h2 {
font-size: 13px;
text-transform: uppercase;
letter-spacing: .09em;
color: var(--eyebrow);
margin: 46px 0 2px;
font-weight: 700;
}
.opt-name {
font-size: 22px;
font-weight: 800;
margin: 0 0 4px;
}
.opt-note {
color: var(--muted);
font-size: 14px;
margin: 0 0 6px;
max-width: 70ch;
}
.opt-cost {
color: var(--eyebrow);
font-size: 12.5px;
margin: 0 0 18px;
}
.row {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
align-items: start;
}
/* ---------- shared card anatomy ---------- */
.c {
background: #fff;
padding: 16px;
}
.c__eyebrow {
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: .08em;
color: var(--eyebrow);
margin: 0 0 4px;
}
.c__title {
font-size: 15px;
font-weight: 700;
margin: 0 0 6px;
}
.c__body {
font-size: 13.5px;
color: var(--muted);
margin: 0;
}
.c__foot {
margin-top: 14px;
padding-top: 12px;
border-top: 1px solid var(--hair-soft);
}
.c__action {
font-size: 13.5px;
font-weight: 700;
color: var(--purple);
text-decoration: none;
}
.c__action:hover {
text-decoration: underline;
}
.figure {
font-size: 34px;
font-weight: 800;
letter-spacing: -0.02em;
font-variant-numeric: tabular-nums;
}
.chip {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 2px 9px;
border-radius: 999px;
font-size: 12px;
font-weight: 700;
border: 1px solid currentColor;
margin-left: 8px;
vertical-align: 6px;
}
.disc {
width: 26px;
height: 26px;
border-radius: 999px;
display: grid;
place-items: center;
flex: 0 0 auto;
}
.dot {
width: 10px;
height: 10px;
border-radius: 999px;
}
.tool {
display: flex;
align-items: center;
gap: 11px;
font-size: 13.5px;
color: #55506b;
}
.tool+.tool {
margin-top: 10px;
}
.meter {
display: flex;
gap: 2px;
height: 18px;
max-width: 210px;
}
.meter i {
flex: 1;
border-radius: 0;
font-style: normal;
font-size: 9px;
font-weight: 800;
color: #fff;
display: grid;
place-items: center;
opacity: .16;
}
.meter i:first-child {
border-radius: 4px 0 0 4px;
}
.meter i:last-child {
border-radius: 0 4px 4px 0;
}
.meter i.on {
opacity: 1;
box-shadow: 0 0 0 2px rgba(62, 33, 85, .55);
border-radius: 3px;
position: relative;
}
/* ---------- A: squared corner ---------- */
.a .c {
border: 1px solid var(--hair);
border-radius: 14px 14px 14px 3px;
}
/* ---------- B: tab header ---------- */
.b .c {
border: 1px solid var(--hair);
border-radius: 12px;
position: relative;
padding-top: 24px;
}
.b .c__eyebrow {
position: absolute;
top: -1px;
left: 14px;
background: var(--ink);
color: #fff;
padding: 3px 10px 4px;
border-radius: 0 0 8px 8px;
margin: 0;
letter-spacing: .09em;
}
.b .c--stage .c__eyebrow {
background: var(--tone, var(--ink));
}
/* ---------- C: plate header ---------- */
.cc .c {
border: 1px solid var(--hair);
border-radius: 12px;
padding: 0;
overflow: hidden;
}
.cc .plate {
padding: 9px 16px;
border-bottom: 1px solid var(--hair);
background: repeating-linear-gradient(135deg, rgba(103, 44, 114, .045) 0 6px, transparent 6px 12px);
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
}
.cc .plate .c__eyebrow {
margin: 0;
}
.cc .inner {
padding: 14px 16px 16px;
}
.cc .c__foot {
margin: 14px -16px -16px;
padding: 12px 16px;
border-top: 1px solid var(--hair-soft);
background: rgba(103, 44, 114, .02);
}
/* ---------- D: the stack ---------- */
/* Texture is fractal noise baked into a data URI, not a live SVG filter.
The reference applies feTurbulence and feSpecularLighting as a filter; on a
dashboard carrying thirty cards that is thirty filter passes a frame, so
the noise is rasterised once and tiled. Same matte paper surface, none of
the cost. Tinted toward the brand purple rather than left grey, so even the
grain belongs to us. */
.d .c {
position: relative;
border: 1px solid var(--hair);
border-radius: 14px 14px 14px 3px;
/* The plane behind is a hard-edged shadow rather than a pseudo-element.
The card is rotated, and a transform creates a stacking context, which
traps a negative-z-index layer INSIDE the card and draws its edge across
the face. A shadow always paints behind the background, so the stack
reads and the card stays clean. Fill first, hairline second and one pixel
larger, so the plane has an outline. */
box-shadow:
5px 5px 0 0 rgba(103, 44, 114, .05),
5px 5px 0 1px rgba(62, 33, 85, .07);
/* The pile leans. A hair only: enough to read as stacked by hand, not
enough to look like a broken grid. Alternates so a row does not skew. */
transform: rotate(-0.55deg);
transition: transform 160ms ease, box-shadow 160ms ease;
}
.d .c:nth-child(even) {
transform: rotate(0.5deg);
}
/* Picking one up squares it and lifts the plane. The card you are acting on
is the one that is straight, which beats a border colour for saying
"active". */
.d .c:hover,
.d .c:focus-within {
transform: rotate(0deg);
box-shadow:
8px 8px 0 0 rgba(103, 44, 114, .06),
8px 8px 0 1px rgba(62, 33, 85, .09);
}
/* Noise sits above the white and below the text. The card's transform makes
it a stacking context, so a negative z-index here lands between the
background and the content, which is exactly where grain belongs. */
.d .c::before {
content: "";
position: absolute;
inset: 0;
z-index: -1;
border-radius: inherit;
pointer-events: none;
opacity: .45;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0.404 0 0 0 0 0.173 0 0 0 0 0.447 0 0 0 0.5 0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
background-size: 140px 140px;
}
@media (prefers-reduced-motion: reduce) {
.d .c {
transition: none;
}
}
.d.row {
row-gap: 26px;
column-gap: 24px;
}
/* ---------- E: the glass ---------- */
/* Glass needs something behind it. backdrop-filter blurs what it sits over,
and our page is a flat tint, so on today's dashboard this would render as
a plain translucent rectangle. The field below is the price of admission:
a soft brand wash the cards have something to do with. */
.e-field {
position: relative;
padding: 26px;
border-radius: 18px;
background:
radial-gradient(60% 80% at 12% 18%, rgba(103, 44, 114, .30), transparent 60%),
radial-gradient(50% 70% at 88% 26%, rgba(31, 95, 155, .26), transparent 62%),
radial-gradient(55% 75% at 62% 92%, rgba(23, 128, 85, .22), transparent 64%),
linear-gradient(160deg, #f6f2fb 0%, #efe9f6 100%);
}
.e .c {
background: rgba(255, 255, 255, .62);
-webkit-backdrop-filter: blur(18px) saturate(1.5);
backdrop-filter: blur(18px) saturate(1.5);
/* The squared corner stays. Glass on its own is everyone's; glass with our
silhouette is ours. */
border-radius: 14px 14px 14px 3px;
border: 1px solid rgba(255, 255, 255, .72);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, .9),
0 10px 24px -12px rgba(62, 33, 85, .35);
}
/* Contrast on glass is not a taste call, and it costs us something.
Measured against the darkest point the field puts under a card (#c6b0ce):
at 62% white the heading holds 10.59 and body 5.33, but the house eyebrow
lavender lands at 4.25, under the 4.5 threshold. Opaque enough to rescue
it is 80% white, at which point it is not glass any more. So on glass the
eyebrow darkens to the body ink instead. That is a real concession: the
eyebrow is a house colour and this is the one surface that cannot use it. */
.e .c__body {
color: #5b5872;
}
.e .c__eyebrow {
color: #5b5872;
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) .wrap {
background: #17131f;
color: #efe9f5;
}
:root:not([data-theme="light"]) .c,
:root:not([data-theme="light"]) .note {
background: #241d30;
border-color: #3a3049 !important;
}
:root:not([data-theme="light"]) .c__title {
color: #efe9f5;
}
}
:root[data-theme="dark"] .wrap {
background: #17131f;
color: #efe9f5;
}
:root[data-theme="dark"] .c,
:root[data-theme="dark"] .note {
background: #241d30;
border-color: #3a3049 !important;
}
:root[data-theme="dark"] .c__title {
color: #efe9f5;
}
</style>
<div class="wrap">
<h1>A card idiom for TubeSpanner</h1>
<p class="lede">Five candidates, each shown on the same three real cards: a shortcut, channel health, and an outcome headline.</p>
<div class="note">
<p><strong>What makes a card ours is not decoration.</strong> A coloured rail, a tinted panel and a rounded box with a shadow are what every tool ships, which is why the current cards read as generic. The signature has to be either the <strong>silhouette</strong> (the shape you recognise before you read it) or the <strong>anatomy</strong> (where things always sit). Colour stays where it already works: the icon disc, the grade meter, the chips.</p>
</div>
<!-- ============ A ============ -->
<h2>Option A</h2>
<p class="opt-name">The squared corner</p>
<p class="opt-note">Every card is 14px rounded except one corner, cut to 3px. It reads as a tag or a tooled part rather than a generic box, and it is recognisable across the estate at any size, in any colour, at a glance. Nothing else changes.</p>
<p class="opt-cost">Cost: one line of CSS. Works on every existing card immediately. No markup change.</p>
<div class="row a">
<div class="c">
<p class="c__eyebrow">Shortcut</p>
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--green) 14%,#fff)"><span class="dot" style="background:var(--green)"></span></span> Post to social media</div>
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--purple) 14%,#fff)"><span class="dot" style="background:var(--purple)"></span></span> Video script templates</div>
</div>
<div class="c">
<p class="c__eyebrow">Channel health</p>
<p class="c__title">Retention is dragging this down most</p>
<div class="meter" style="margin:10px 0 4px">
<i style="background:#b42318">F</i><i class="on" style="background:#c2410c">D</i><i style="background:#9a6207">C</i><i style="background:#4f7a12">B</i><i style="background:#1b7a3e">A</i><i style="background:#12703f">A+</i>
</div>
<p class="c__body">3 of 4 measured.</p>
<div class="c__foot"><a class="c__action" href="#">Full audit</a></div>
</div>
<div class="c">
<p class="c__eyebrow" style="color:var(--green)">Since you last looked</p>
<p class="c__title"><span class="figure" style="color:var(--green)">72</span><span class="chip" style="color:var(--green)">+22</span></p>
<p class="c__body">Packaging moved from 50 to 72.</p>
<div class="c__foot"><a class="c__action" href="#" style="color:var(--green)">See what changed</a></div>
</div>
</div>
<!-- ============ B ============ -->
<h2>Option B</h2>
<p class="opt-name">The tab</p>
<p class="opt-note">The eyebrow leaves the card body and becomes a tab hanging off the top edge, like a divider in a drawer. It gives every card a named handle, and the tab is where a state or a workflow stage can take colour without washing anything.</p>
<p class="opt-cost">Cost: the eyebrow becomes required. A card with nothing to name it looks unfinished, which is a real constraint on empty states.</p>
<div class="row b">
<div class="c c--stage" style="--tone:var(--green)">
<p class="c__eyebrow">Promote</p>
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--green) 14%,#fff)"><span class="dot" style="background:var(--green)"></span></span> Post to social media</div>
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--green) 14%,#fff)"><span class="dot" style="background:var(--green)"></span></span> Mailing lists</div>
</div>
<div class="c">
<p class="c__eyebrow">Channel health</p>
<p class="c__title">Retention is dragging this down most</p>
<div class="meter" style="margin:10px 0 4px">
<i style="background:#b42318">F</i><i class="on" style="background:#c2410c">D</i><i style="background:#9a6207">C</i><i style="background:#4f7a12">B</i><i style="background:#1b7a3e">A</i><i style="background:#12703f">A+</i>
</div>
<p class="c__body">3 of 4 measured.</p>
<div class="c__foot"><a class="c__action" href="#">Full audit</a></div>
</div>
<div class="c c--stage" style="--tone:var(--green)">
<p class="c__eyebrow">Win</p>
<p class="c__title"><span class="figure" style="color:var(--green)">72</span><span class="chip" style="color:var(--green)">+22</span></p>
<p class="c__body">Packaging moved from 50 to 72.</p>
<div class="c__foot"><a class="c__action" href="#" style="color:var(--green)">See what changed</a></div>
</div>
</div>
<!-- ============ C ============ -->
<h2>Option C</h2>
<p class="opt-name">The plate</p>
<p class="opt-note">The header becomes a plate: its own band, hairline-separated, faintly hatched at the brand purple so it reads as an engraved label on an instrument rather than a heading in a box. The action sits in a matching footer, so every card has a top and a bottom and the middle is only ever content.</p>
<p class="opt-cost">Cost: the most markup. Cards need a header and body wrapper, so it is a component rather than a class.</p>
<div class="row cc">
<div class="c">
<div class="plate">
<p class="c__eyebrow">Shortcuts</p><span style="font-size:11px;color:var(--eyebrow)">6 of 34</span>
</div>
<div class="inner">
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--green) 14%,#fff)"><span class="dot" style="background:var(--green)"></span></span> Post to social media</div>
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--purple) 14%,#fff)"><span class="dot" style="background:var(--purple)"></span></span> Video script templates</div>
</div>
</div>
<div class="c">
<div class="plate">
<p class="c__eyebrow">Channel health</p><span style="font-size:11px;color:var(--eyebrow)">3 of 4</span>
</div>
<div class="inner">
<p class="c__title">Retention is dragging this down most</p>
<div class="meter" style="margin:10px 0 0">
<i style="background:#b42318">F</i><i class="on" style="background:#c2410c">D</i><i style="background:#9a6207">C</i><i style="background:#4f7a12">B</i><i style="background:#1b7a3e">A</i><i style="background:#12703f">A+</i>
</div>
<div class="c__foot"><a class="c__action" href="#">Full audit</a></div>
</div>
</div>
<div class="c">
<div class="plate">
<p class="c__eyebrow" style="color:var(--green)">Since you last looked</p>
</div>
<div class="inner">
<p class="c__title" style="margin-bottom:2px"><span class="figure" style="color:var(--green)">72</span><span class="chip" style="color:var(--green)">+22</span></p>
<p class="c__body">Packaging moved from 50 to 72.</p>
<div class="c__foot"><a class="c__action" href="#" style="color:var(--green)">See what changed</a></div>
</div>
</div>
</div>
<!-- ============ D ============ -->
<h2>Option D</h2>
<p class="opt-name">The stack</p>
<p class="opt-note">The squared corner from A, plus the layered-card technique from your reference. Fractal noise gives a matte paper grain, tinted toward the brand purple so even the texture belongs to us. A second plane sits offset behind it, so depth comes from a layer rather than a blurred drop shadow, and the card itself leans a hair. Hovering squares it: the one you are acting on is the one that is straight, which beats a border colour for saying "active". A card sitting on more cards is a fair description of a toolkit.</p>
<p class="opt-cost">Cost: still CSS only, no markup change. The noise is baked into a data URI and tiled rather than applied as a live SVG filter, because a filter on every card is a filter pass per card per frame. Needs a larger grid gap for the offset layer and the lean, so the shortcut row goes from 16px to about 24px.</p>
<div class="row d">
<div class="c">
<p class="c__eyebrow">Shortcut</p>
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--green) 14%,#fff)"><span class="dot" style="background:var(--green)"></span></span> Post to social media</div>
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--purple) 14%,#fff)"><span class="dot" style="background:var(--purple)"></span></span> Video script templates</div>
</div>
<div class="c">
<p class="c__eyebrow">Channel health</p>
<p class="c__title">Retention is dragging this down most</p>
<div class="meter" style="margin:10px 0 4px">
<i style="background:#b42318">F</i><i class="on" style="background:#c2410c">D</i><i style="background:#9a6207">C</i><i style="background:#4f7a12">B</i><i style="background:#1b7a3e">A</i><i style="background:#12703f">A+</i>
</div>
<p class="c__body">3 of 4 measured.</p>
<div class="c__foot"><a class="c__action" href="#">Full audit</a></div>
</div>
<div class="c">
<p class="c__eyebrow" style="color:var(--green)">Since you last looked</p>
<p class="c__title"><span class="figure" style="color:var(--green)">72</span><span class="chip" style="color:var(--green)">+22</span></p>
<p class="c__body">Packaging moved from 50 to 72.</p>
<div class="c__foot"><a class="c__action" href="#" style="color:var(--green)">See what changed</a></div>
</div>
</div>
<!-- ============ E ============ -->
<h2>Option E</h2>
<p class="opt-name">The glass</p>
<p class="opt-note">A frosted surface over a brand field, keeping the squared corner so it is ours rather than everyone's. The field is not decoration here, it is what makes the treatment legible: on a flat page a frosted card is just a pale rectangle.</p>
<p class="opt-cost">Cost: real, and worth knowing before choosing it. The page needs a gradient field behind the content, which is a change to the whole dashboard rather than to cards. Every glass surface is a live blur of what is under it, so this belongs on a few large panels, not on 46px shortcut rows. And the eyebrow lavender fails contrast on a translucent surface, so on glass it has to darken to the body ink: the one surface in the product that cannot use a house colour.</p>
<div class="e-field">
<div class="row e">
<div class="c">
<p class="c__eyebrow">Shortcut</p>
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--green) 14%,#fff)"><span class="dot" style="background:var(--green)"></span></span> Post to social media</div>
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--purple) 14%,#fff)"><span class="dot" style="background:var(--purple)"></span></span> Video script templates</div>
</div>
<div class="c">
<p class="c__eyebrow">Channel health</p>
<p class="c__title">Retention is dragging this down most</p>
<div class="meter" style="margin:10px 0 4px">
<i style="background:#b42318">F</i><i class="on" style="background:#c2410c">D</i><i style="background:#9a6207">C</i><i style="background:#4f7a12">B</i><i style="background:#1b7a3e">A</i><i style="background:#12703f">A+</i>
</div>
<p class="c__body">3 of 4 measured.</p>
<div class="c__foot"><a class="c__action" href="#">Full audit</a></div>
</div>
<div class="c">
<p class="c__eyebrow" style="color:var(--green)">Since you last looked</p>
<p class="c__title"><span class="figure" style="color:var(--green)">72</span><span class="chip" style="color:var(--green)">+22</span></p>
<p class="c__body">Packaging moved from 50 to 72.</p>
<div class="c__foot"><a class="c__action" href="#" style="color:var(--green)">See what changed</a></div>
</div>
</div>
</div>
<div class="note" style="margin-top:48px">
<p><strong>My recommendation is now E, the glass, with C's footer rule.</strong> D failed on contact: half a degree of lean survives three cards in a mock and reads as a broken grid across a real row of six, and the grain looks like dirt rather than paper at 46px. A and B remain the safe fallbacks. E is the only one that looks like a decision rather than a default, but it is also the only one that changes the page and not just the card, so it should be chosen with the three costs open: the dashboard needs a gradient field behind the content, glass belongs on large panels rather than 46px rows because each one is a live blur, and the eyebrow lavender fails contrast on a translucent surface, so on glass it darkens to the body ink.</p>
</div>
</div>
{{!
The five candidates the glass surface was chosen from, kept so the
decision can be re-read rather than re-argued. The rejected four matter
as much as the winner: each was rejected for a stated reason.
}}
<style>
:root {
--ink: #3e2155;
--purple: #672c72;
--muted: #6b6880;
--eyebrow: #6d648f;
--page: #f2eef8;
--hair: rgba(62, 33, 85, 0.12);
--hair-soft: rgba(62, 33, 85, 0.07);
--green: #178055;
--blue: #1f5f9b;
--amber: #9a6207;
--font: "Satoshi", ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
* { box-sizing: border-box; }
body { margin: 0; }
.wrap {
font-family: var(--font);
color: var(--ink);
background: var(--page);
padding: 36px 24px 72px;
max-width: 1180px;
margin: 0 auto;
line-height: 1.5;
}
h1 { font-size: 30px; font-weight: 800; margin: 0 0 8px; letter-spacing: -0.01em; }
.lede { color: var(--muted); max-width: 66ch; margin: 0 0 6px; }
.note {
background: #fff; border: 1px solid var(--hair); border-radius: 12px;
padding: 16px 20px; margin: 22px 0 40px; max-width: 74ch;
}
.note p { margin: 0; color: var(--muted); font-size: 14px; }
.note strong { color: var(--ink); }
h2 { font-size: 13px; text-transform: uppercase; letter-spacing: .09em; color: var(--eyebrow); margin: 46px 0 2px; font-weight: 700; }
.opt-name { font-size: 22px; font-weight: 800; margin: 0 0 4px; }
.opt-note { color: var(--muted); font-size: 14px; margin: 0 0 6px; max-width: 70ch; }
.opt-cost { color: var(--eyebrow); font-size: 12.5px; margin: 0 0 18px; }
.row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; align-items: start; }
/* ---------- shared card anatomy ---------- */
.c { background: #fff; padding: 16px; }
.c__eyebrow { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--eyebrow); margin: 0 0 4px; }
.c__title { font-size: 15px; font-weight: 700; margin: 0 0 6px; }
.c__body { font-size: 13.5px; color: var(--muted); margin: 0; }
.c__foot { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--hair-soft); }
.c__action { font-size: 13.5px; font-weight: 700; color: var(--purple); text-decoration: none; }
.c__action:hover { text-decoration: underline; }
.figure { font-size: 34px; font-weight: 800; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.chip {
display: inline-flex; align-items: center; gap: 6px; padding: 2px 9px; border-radius: 999px;
font-size: 12px; font-weight: 700; border: 1px solid currentColor; margin-left: 8px; vertical-align: 6px;
}
.disc { width: 26px; height: 26px; border-radius: 999px; display: grid; place-items: center; flex: 0 0 auto; }
.dot { width: 10px; height: 10px; border-radius: 999px; }
.tool { display: flex; align-items: center; gap: 11px; font-size: 13.5px; color: #55506b; }
.tool + .tool { margin-top: 10px; }
.meter { display: flex; gap: 2px; height: 18px; max-width: 210px; }
.meter i { flex: 1; border-radius: 0; font-style: normal; font-size: 9px; font-weight: 800; color: #fff; display: grid; place-items: center; opacity: .16; }
.meter i:first-child { border-radius: 4px 0 0 4px; }
.meter i:last-child { border-radius: 0 4px 4px 0; }
.meter i.on { opacity: 1; box-shadow: 0 0 0 2px rgba(62,33,85,.55); border-radius: 3px; position: relative; }
/* ---------- A: squared corner ---------- */
.a .c { border: 1px solid var(--hair); border-radius: 14px 14px 14px 3px; }
/* ---------- B: tab header ---------- */
.b .c { border: 1px solid var(--hair); border-radius: 12px; position: relative; padding-top: 24px; }
.b .c__eyebrow {
position: absolute; top: -1px; left: 14px;
background: var(--ink); color: #fff; padding: 3px 10px 4px;
border-radius: 0 0 8px 8px; margin: 0; letter-spacing: .09em;
}
.b .c--stage .c__eyebrow { background: var(--tone, var(--ink)); }
/* ---------- C: plate header ---------- */
.cc .c { border: 1px solid var(--hair); border-radius: 12px; padding: 0; overflow: hidden; }
.cc .plate {
padding: 9px 16px; border-bottom: 1px solid var(--hair);
background: repeating-linear-gradient(135deg, rgba(103,44,114,.045) 0 6px, transparent 6px 12px);
display: flex; align-items: center; justify-content: space-between; gap: 10px;
}
.cc .plate .c__eyebrow { margin: 0; }
.cc .inner { padding: 14px 16px 16px; }
.cc .c__foot { margin: 14px -16px -16px; padding: 12px 16px; border-top: 1px solid var(--hair-soft); background: rgba(103,44,114,.02); }
/* ---------- D: the stack ---------- */
/* Texture is fractal noise baked into a data URI, not a live SVG filter.
The reference applies feTurbulence and feSpecularLighting as a filter; on a
dashboard carrying thirty cards that is thirty filter passes a frame, so
the noise is rasterised once and tiled. Same matte paper surface, none of
the cost. Tinted toward the brand purple rather than left grey, so even the
grain belongs to us. */
.d .c {
position: relative;
border: 1px solid var(--hair);
border-radius: 14px 14px 14px 3px;
/* The plane behind is a hard-edged shadow rather than a pseudo-element.
The card is rotated, and a transform creates a stacking context, which
traps a negative-z-index layer INSIDE the card and draws its edge across
the face. A shadow always paints behind the background, so the stack
reads and the card stays clean. Fill first, hairline second and one pixel
larger, so the plane has an outline. */
box-shadow:
5px 5px 0 0 rgba(103, 44, 114, .05),
5px 5px 0 1px rgba(62, 33, 85, .07);
/* The pile leans. A hair only: enough to read as stacked by hand, not
enough to look like a broken grid. Alternates so a row does not skew. */
transform: rotate(-0.55deg);
transition: transform 160ms ease, box-shadow 160ms ease;
}
.d .c:nth-child(even) { transform: rotate(0.5deg); }
/* Picking one up squares it and lifts the plane. The card you are acting on
is the one that is straight, which beats a border colour for saying
"active". */
.d .c:hover, .d .c:focus-within {
transform: rotate(0deg);
box-shadow:
8px 8px 0 0 rgba(103, 44, 114, .06),
8px 8px 0 1px rgba(62, 33, 85, .09);
}
/* Noise sits above the white and below the text. The card's transform makes
it a stacking context, so a negative z-index here lands between the
background and the content, which is exactly where grain belongs. */
.d .c::before {
content: "";
position: absolute;
inset: 0;
z-index: -1;
border-radius: inherit;
pointer-events: none;
opacity: .45;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0.404 0 0 0 0 0.173 0 0 0 0 0.447 0 0 0 0.5 0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
background-size: 140px 140px;
}
@media (prefers-reduced-motion: reduce) {
.d .c { transition: none; }
}
.d.row { row-gap: 26px; column-gap: 24px; }
/* ---------- E: the glass ---------- */
/* Glass needs something behind it. backdrop-filter blurs what it sits over,
and our page is a flat tint, so on today's dashboard this would render as
a plain translucent rectangle. The field below is the price of admission:
a soft brand wash the cards have something to do with. */
.e-field {
position: relative;
padding: 26px;
border-radius: 18px;
background:
radial-gradient(60% 80% at 12% 18%, rgba(103, 44, 114, .30), transparent 60%),
radial-gradient(50% 70% at 88% 26%, rgba(31, 95, 155, .26), transparent 62%),
radial-gradient(55% 75% at 62% 92%, rgba(23, 128, 85, .22), transparent 64%),
linear-gradient(160deg, #f6f2fb 0%, #efe9f6 100%);
}
.e .c {
background: rgba(255, 255, 255, .62);
-webkit-backdrop-filter: blur(18px) saturate(1.5);
backdrop-filter: blur(18px) saturate(1.5);
/* The squared corner stays. Glass on its own is everyone's; glass with our
silhouette is ours. */
border-radius: 14px 14px 14px 3px;
border: 1px solid rgba(255, 255, 255, .72);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, .9),
0 10px 24px -12px rgba(62, 33, 85, .35);
}
/* Contrast on glass is not a taste call, and it costs us something.
Measured against the darkest point the field puts under a card (#c6b0ce):
at 62% white the heading holds 10.59 and body 5.33, but the house eyebrow
lavender lands at 4.25, under the 4.5 threshold. Opaque enough to rescue
it is 80% white, at which point it is not glass any more. So on glass the
eyebrow darkens to the body ink instead. That is a real concession: the
eyebrow is a house colour and this is the one surface that cannot use it. */
.e .c__body { color: #5b5872; }
.e .c__eyebrow { color: #5b5872; }
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) .wrap { background: #17131f; color: #efe9f5; }
:root:not([data-theme="light"]) .c, :root:not([data-theme="light"]) .note { background: #241d30; border-color: #3a3049 !important; }
:root:not([data-theme="light"]) .c__title { color: #efe9f5; }
}
:root[data-theme="dark"] .wrap { background: #17131f; color: #efe9f5; }
:root[data-theme="dark"] .c, :root[data-theme="dark"] .note { background: #241d30; border-color: #3a3049 !important; }
:root[data-theme="dark"] .c__title { color: #efe9f5; }
</style>
<div class="wrap">
<h1>A card idiom for TubeSpanner</h1>
<p class="lede">Five candidates, each shown on the same three real cards: a shortcut, channel health, and an outcome headline.</p>
<div class="note">
<p><strong>What makes a card ours is not decoration.</strong> A coloured rail, a tinted panel and a rounded box with a shadow are what every tool ships, which is why the current cards read as generic. The signature has to be either the <strong>silhouette</strong> (the shape you recognise before you read it) or the <strong>anatomy</strong> (where things always sit). Colour stays where it already works: the icon disc, the grade meter, the chips.</p>
</div>
<!-- ============ A ============ -->
<h2>Option A</h2>
<p class="opt-name">The squared corner</p>
<p class="opt-note">Every card is 14px rounded except one corner, cut to 3px. It reads as a tag or a tooled part rather than a generic box, and it is recognisable across the estate at any size, in any colour, at a glance. Nothing else changes.</p>
<p class="opt-cost">Cost: one line of CSS. Works on every existing card immediately. No markup change.</p>
<div class="row a">
<div class="c">
<p class="c__eyebrow">Shortcut</p>
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--green) 14%,#fff)"><span class="dot" style="background:var(--green)"></span></span> Post to social media</div>
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--purple) 14%,#fff)"><span class="dot" style="background:var(--purple)"></span></span> Video script templates</div>
</div>
<div class="c">
<p class="c__eyebrow">Channel health</p>
<p class="c__title">Retention is dragging this down most</p>
<div class="meter" style="margin:10px 0 4px">
<i style="background:#b42318">F</i><i class="on" style="background:#c2410c">D</i><i style="background:#9a6207">C</i><i style="background:#4f7a12">B</i><i style="background:#1b7a3e">A</i><i style="background:#12703f">A+</i>
</div>
<p class="c__body">3 of 4 measured.</p>
<div class="c__foot"><a class="c__action" href="#">Full audit</a></div>
</div>
<div class="c">
<p class="c__eyebrow" style="color:var(--green)">Since you last looked</p>
<p class="c__title"><span class="figure" style="color:var(--green)">72</span><span class="chip" style="color:var(--green)">+22</span></p>
<p class="c__body">Packaging moved from 50 to 72.</p>
<div class="c__foot"><a class="c__action" href="#" style="color:var(--green)">See what changed</a></div>
</div>
</div>
<!-- ============ B ============ -->
<h2>Option B</h2>
<p class="opt-name">The tab</p>
<p class="opt-note">The eyebrow leaves the card body and becomes a tab hanging off the top edge, like a divider in a drawer. It gives every card a named handle, and the tab is where a state or a workflow stage can take colour without washing anything.</p>
<p class="opt-cost">Cost: the eyebrow becomes required. A card with nothing to name it looks unfinished, which is a real constraint on empty states.</p>
<div class="row b">
<div class="c c--stage" style="--tone:var(--green)">
<p class="c__eyebrow">Promote</p>
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--green) 14%,#fff)"><span class="dot" style="background:var(--green)"></span></span> Post to social media</div>
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--green) 14%,#fff)"><span class="dot" style="background:var(--green)"></span></span> Mailing lists</div>
</div>
<div class="c">
<p class="c__eyebrow">Channel health</p>
<p class="c__title">Retention is dragging this down most</p>
<div class="meter" style="margin:10px 0 4px">
<i style="background:#b42318">F</i><i class="on" style="background:#c2410c">D</i><i style="background:#9a6207">C</i><i style="background:#4f7a12">B</i><i style="background:#1b7a3e">A</i><i style="background:#12703f">A+</i>
</div>
<p class="c__body">3 of 4 measured.</p>
<div class="c__foot"><a class="c__action" href="#">Full audit</a></div>
</div>
<div class="c c--stage" style="--tone:var(--green)">
<p class="c__eyebrow">Win</p>
<p class="c__title"><span class="figure" style="color:var(--green)">72</span><span class="chip" style="color:var(--green)">+22</span></p>
<p class="c__body">Packaging moved from 50 to 72.</p>
<div class="c__foot"><a class="c__action" href="#" style="color:var(--green)">See what changed</a></div>
</div>
</div>
<!-- ============ C ============ -->
<h2>Option C</h2>
<p class="opt-name">The plate</p>
<p class="opt-note">The header becomes a plate: its own band, hairline-separated, faintly hatched at the brand purple so it reads as an engraved label on an instrument rather than a heading in a box. The action sits in a matching footer, so every card has a top and a bottom and the middle is only ever content.</p>
<p class="opt-cost">Cost: the most markup. Cards need a header and body wrapper, so it is a component rather than a class.</p>
<div class="row cc">
<div class="c">
<div class="plate"><p class="c__eyebrow">Shortcuts</p><span style="font-size:11px;color:var(--eyebrow)">6 of 34</span></div>
<div class="inner">
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--green) 14%,#fff)"><span class="dot" style="background:var(--green)"></span></span> Post to social media</div>
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--purple) 14%,#fff)"><span class="dot" style="background:var(--purple)"></span></span> Video script templates</div>
</div>
</div>
<div class="c">
<div class="plate"><p class="c__eyebrow">Channel health</p><span style="font-size:11px;color:var(--eyebrow)">3 of 4</span></div>
<div class="inner">
<p class="c__title">Retention is dragging this down most</p>
<div class="meter" style="margin:10px 0 0">
<i style="background:#b42318">F</i><i class="on" style="background:#c2410c">D</i><i style="background:#9a6207">C</i><i style="background:#4f7a12">B</i><i style="background:#1b7a3e">A</i><i style="background:#12703f">A+</i>
</div>
<div class="c__foot"><a class="c__action" href="#">Full audit</a></div>
</div>
</div>
<div class="c">
<div class="plate"><p class="c__eyebrow" style="color:var(--green)">Since you last looked</p></div>
<div class="inner">
<p class="c__title" style="margin-bottom:2px"><span class="figure" style="color:var(--green)">72</span><span class="chip" style="color:var(--green)">+22</span></p>
<p class="c__body">Packaging moved from 50 to 72.</p>
<div class="c__foot"><a class="c__action" href="#" style="color:var(--green)">See what changed</a></div>
</div>
</div>
</div>
<!-- ============ D ============ -->
<h2>Option D</h2>
<p class="opt-name">The stack</p>
<p class="opt-note">The squared corner from A, plus the layered-card technique from your reference. Fractal noise gives a matte paper grain, tinted toward the brand purple so even the texture belongs to us. A second plane sits offset behind it, so depth comes from a layer rather than a blurred drop shadow, and the card itself leans a hair. Hovering squares it: the one you are acting on is the one that is straight, which beats a border colour for saying "active". A card sitting on more cards is a fair description of a toolkit.</p>
<p class="opt-cost">Cost: still CSS only, no markup change. The noise is baked into a data URI and tiled rather than applied as a live SVG filter, because a filter on every card is a filter pass per card per frame. Needs a larger grid gap for the offset layer and the lean, so the shortcut row goes from 16px to about 24px.</p>
<div class="row d">
<div class="c">
<p class="c__eyebrow">Shortcut</p>
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--green) 14%,#fff)"><span class="dot" style="background:var(--green)"></span></span> Post to social media</div>
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--purple) 14%,#fff)"><span class="dot" style="background:var(--purple)"></span></span> Video script templates</div>
</div>
<div class="c">
<p class="c__eyebrow">Channel health</p>
<p class="c__title">Retention is dragging this down most</p>
<div class="meter" style="margin:10px 0 4px">
<i style="background:#b42318">F</i><i class="on" style="background:#c2410c">D</i><i style="background:#9a6207">C</i><i style="background:#4f7a12">B</i><i style="background:#1b7a3e">A</i><i style="background:#12703f">A+</i>
</div>
<p class="c__body">3 of 4 measured.</p>
<div class="c__foot"><a class="c__action" href="#">Full audit</a></div>
</div>
<div class="c">
<p class="c__eyebrow" style="color:var(--green)">Since you last looked</p>
<p class="c__title"><span class="figure" style="color:var(--green)">72</span><span class="chip" style="color:var(--green)">+22</span></p>
<p class="c__body">Packaging moved from 50 to 72.</p>
<div class="c__foot"><a class="c__action" href="#" style="color:var(--green)">See what changed</a></div>
</div>
</div>
<!-- ============ E ============ -->
<h2>Option E</h2>
<p class="opt-name">The glass</p>
<p class="opt-note">A frosted surface over a brand field, keeping the squared corner so it is ours rather than everyone's. The field is not decoration here, it is what makes the treatment legible: on a flat page a frosted card is just a pale rectangle.</p>
<p class="opt-cost">Cost: real, and worth knowing before choosing it. The page needs a gradient field behind the content, which is a change to the whole dashboard rather than to cards. Every glass surface is a live blur of what is under it, so this belongs on a few large panels, not on 46px shortcut rows. And the eyebrow lavender fails contrast on a translucent surface, so on glass it has to darken to the body ink: the one surface in the product that cannot use a house colour.</p>
<div class="e-field">
<div class="row e">
<div class="c">
<p class="c__eyebrow">Shortcut</p>
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--green) 14%,#fff)"><span class="dot" style="background:var(--green)"></span></span> Post to social media</div>
<div class="tool"><span class="disc" style="background:color-mix(in srgb,var(--purple) 14%,#fff)"><span class="dot" style="background:var(--purple)"></span></span> Video script templates</div>
</div>
<div class="c">
<p class="c__eyebrow">Channel health</p>
<p class="c__title">Retention is dragging this down most</p>
<div class="meter" style="margin:10px 0 4px">
<i style="background:#b42318">F</i><i class="on" style="background:#c2410c">D</i><i style="background:#9a6207">C</i><i style="background:#4f7a12">B</i><i style="background:#1b7a3e">A</i><i style="background:#12703f">A+</i>
</div>
<p class="c__body">3 of 4 measured.</p>
<div class="c__foot"><a class="c__action" href="#">Full audit</a></div>
</div>
<div class="c">
<p class="c__eyebrow" style="color:var(--green)">Since you last looked</p>
<p class="c__title"><span class="figure" style="color:var(--green)">72</span><span class="chip" style="color:var(--green)">+22</span></p>
<p class="c__body">Packaging moved from 50 to 72.</p>
<div class="c__foot"><a class="c__action" href="#" style="color:var(--green)">See what changed</a></div>
</div>
</div>
</div>
<div class="note" style="margin-top:48px">
<p><strong>My recommendation is now E, the glass, with C's footer rule.</strong> D failed on contact: half a degree of lean survives three cards in a mock and reads as a broken grid across a real row of six, and the grain looks like dirt rather than paper at 46px. A and B remain the safe fallbacks. E is the only one that looks like a decision rather than a default, but it is also the only one that changes the page and not just the card, so it should be chosen with the three costs open: the dashboard needs a gradient field behind the content, glass belongs on large panels rather than 46px rows because each one is a live blur, and the eyebrow lavender fails contrast on a translucent surface, so on glass it darkens to the body ink.</p>
</div>
</div>
/* No context defined. */
The five candidates the glass surface was chosen from on 2026-08-02, kept so the decision can be re-read rather than re-argued. A squared corner, B tab header, C plate header, D the stack, E glass. E was chosen. The rejections are the useful part: a left accent rail is the most recognisable machine-made pattern going and we use it nowhere else, a full-bleed tinted card reads as a status banner bolted onto the page, and the stack failed on contact - half a degree of lean survives three cards in a mock and reads as a broken grid across a real row of six, while the paper grain looks like dirt at 46px. The squared corner survived from A into E and is the part that makes the surface ours rather than a trend.