- Replace the flat dither backdrop with a lit, rotating torus drawn the way donut.c does it: a z-buffer per cell and a luminance ramp from a dot to a solid block, sized against the shorter viewport axis. The dither field stays underneath as dust. It leads on the landing page and fades back where there is reading to do, and a scrim keeps the projects heading legible over it. - Thicken the glass: one .surface treatment with a heavier blur, more transparency and an SVG film grain, shared by the header, hero, cards, panels and footer. - Give the landing page labelled contact cards for LinkedIn, Gitea and email in place of three bare icons. - Drop the status chips from project cards and entry headers. - Remove the light theme, its toggle and theme.js outright. - Add restrained motion: underlines growing from the left on links and nav items, a lift on cards, buttons and contact cards, and tags brightening with their card. All of it is off under prefers-reduced-motion. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
435 lines
8.0 KiB
CSS
Executable File
435 lines
8.0 KiB
CSS
Executable File
.projects-page,
|
|
.entry-page {
|
|
padding-top: 40px;
|
|
}
|
|
|
|
/* The page header sits on the background; only cards get a surface. */
|
|
.projects-hero {
|
|
position: relative;
|
|
isolation: isolate;
|
|
margin-bottom: 40px;
|
|
max-width: 760px;
|
|
}
|
|
|
|
/* Soft scrim so the heading stays readable over the ASCII field, without
|
|
putting the text in a box. */
|
|
.projects-hero::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: -28px -10px -20px -10px;
|
|
z-index: -1;
|
|
pointer-events: none;
|
|
background: radial-gradient(
|
|
ellipse at 30% 50%,
|
|
rgba(11, 12, 15, 0.92),
|
|
rgba(11, 12, 15, 0.6) 45%,
|
|
transparent 75%
|
|
);
|
|
}
|
|
|
|
.projects-hero h1,
|
|
.entry-title {
|
|
font-size: clamp(1.5rem, 3vw, 2.1rem);
|
|
line-height: 1.2;
|
|
margin: 0 0 14px;
|
|
}
|
|
|
|
.projects-intro,
|
|
.entry-summary {
|
|
margin: 0;
|
|
max-width: 720px;
|
|
color: var(--muted);
|
|
font-size: 0.92rem;
|
|
}
|
|
|
|
.eyebrow {
|
|
margin: 0 0 10px;
|
|
font-size: 12px;
|
|
letter-spacing: 0.18em;
|
|
text-transform: uppercase;
|
|
color: var(--secondary);
|
|
font-weight: 500;
|
|
}
|
|
|
|
.content-section {
|
|
margin-bottom: 44px;
|
|
}
|
|
|
|
.section-heading {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: baseline;
|
|
gap: 14px;
|
|
margin: 0 0 18px;
|
|
padding-bottom: 10px;
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
|
|
.section-heading h2 {
|
|
margin: 0;
|
|
font-size: 1.05rem;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.section-heading__right {
|
|
display: flex;
|
|
align-items: baseline;
|
|
gap: 16px;
|
|
}
|
|
|
|
.section-count {
|
|
font-size: 12px;
|
|
color: var(--muted);
|
|
}
|
|
|
|
.content-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
gap: 16px;
|
|
}
|
|
|
|
.updates-grid {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.content-card.is-hidden {
|
|
display: none;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------- cards */
|
|
|
|
.content-card {
|
|
padding: 22px;
|
|
border-radius: var(--radius);
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 100%;
|
|
scroll-margin-top: 90px;
|
|
transition:
|
|
border-color 0.24s var(--ease),
|
|
box-shadow 0.24s var(--ease),
|
|
transform 0.24s var(--ease);
|
|
}
|
|
|
|
.content-card:hover {
|
|
border-color: var(--border-strong);
|
|
transform: translateY(-3px);
|
|
box-shadow:
|
|
0 26px 60px rgba(0, 0, 0, 0.46),
|
|
inset 0 1px 0 rgba(255, 255, 255, 0.09);
|
|
}
|
|
|
|
.content-card.featured {
|
|
border-color: rgba(235, 82, 52, 0.28);
|
|
}
|
|
|
|
.content-card.featured:hover {
|
|
border-color: rgba(235, 82, 52, 0.55);
|
|
box-shadow:
|
|
0 26px 60px rgba(0, 0, 0, 0.46),
|
|
0 0 32px rgba(235, 82, 52, 0.1),
|
|
inset 0 1px 0 rgba(255, 255, 255, 0.09);
|
|
}
|
|
|
|
.card-meta {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: 12px;
|
|
margin: 0 0 14px;
|
|
font-size: 11.5px;
|
|
color: var(--muted);
|
|
}
|
|
|
|
.card-kicker {
|
|
color: var(--secondary);
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
font-size: 11px;
|
|
}
|
|
|
|
.content-card h3 {
|
|
margin: 0 0 10px;
|
|
font-size: 1.1rem;
|
|
line-height: 1.3;
|
|
}
|
|
|
|
.card-summary {
|
|
color: var(--muted);
|
|
margin: 0 0 16px;
|
|
font-size: 0.86rem;
|
|
flex: 1;
|
|
}
|
|
|
|
.tag-list,
|
|
.entry-tag-list {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 6px;
|
|
}
|
|
|
|
.tag,
|
|
.entry-tag {
|
|
display: inline-flex;
|
|
padding: 2px 8px;
|
|
border-radius: var(--radius);
|
|
font-size: 11px;
|
|
color: var(--muted);
|
|
background: var(--bar);
|
|
border: 1px solid var(--border);
|
|
transition:
|
|
color 0.2s var(--ease),
|
|
border-color 0.2s var(--ease);
|
|
}
|
|
|
|
.content-card:hover .tag {
|
|
color: var(--primary);
|
|
border-color: var(--border-strong);
|
|
}
|
|
|
|
.card-links,
|
|
.entry-links {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 18px;
|
|
align-items: center;
|
|
}
|
|
|
|
.card-links {
|
|
margin-top: 18px;
|
|
padding-top: 16px;
|
|
border-top: 1px solid var(--border);
|
|
}
|
|
|
|
/* Text links share one hover: colour plus an underline growing from the left. */
|
|
.card-link,
|
|
.entry-back,
|
|
.inline-button,
|
|
.section-link,
|
|
.honor-inline-link {
|
|
position: relative;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
color: var(--muted);
|
|
font-size: 13px;
|
|
}
|
|
|
|
.card-link::after,
|
|
.entry-back::after,
|
|
.inline-button::after,
|
|
.section-link::after,
|
|
.honor-inline-link::after {
|
|
content: "";
|
|
position: absolute;
|
|
left: 0;
|
|
bottom: -2px;
|
|
height: 1px;
|
|
width: 100%;
|
|
background: var(--secondary);
|
|
transform: scaleX(0);
|
|
transform-origin: left;
|
|
transition: transform 0.24s var(--ease);
|
|
}
|
|
|
|
.card-link:hover,
|
|
.entry-back:hover,
|
|
.inline-button:hover,
|
|
.section-link:hover,
|
|
.honor-inline-link:hover {
|
|
color: var(--secondary);
|
|
}
|
|
|
|
.card-link:hover::after,
|
|
.entry-back:hover::after,
|
|
.inline-button:hover::after,
|
|
.section-link:hover::after,
|
|
.honor-inline-link:hover::after {
|
|
transform: scaleX(1);
|
|
}
|
|
|
|
.card-link-primary,
|
|
.inline-button-primary {
|
|
color: var(--primary);
|
|
}
|
|
|
|
.projects-toggle-shell {
|
|
display: flex;
|
|
justify-content: center;
|
|
margin-top: 24px;
|
|
}
|
|
|
|
.projects-toggle {
|
|
font-family: var(--mono);
|
|
display: inline-flex;
|
|
align-items: center;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius);
|
|
padding: 8px 20px;
|
|
font-size: 13px;
|
|
background: var(--bar);
|
|
color: var(--muted);
|
|
cursor: pointer;
|
|
transition:
|
|
color 0.2s var(--ease),
|
|
border-color 0.2s var(--ease),
|
|
transform 0.2s var(--ease);
|
|
}
|
|
|
|
.projects-toggle:hover {
|
|
color: var(--bright);
|
|
border-color: var(--border-strong);
|
|
transform: translateY(-1px);
|
|
}
|
|
|
|
.site-footer {
|
|
margin-bottom: 28px;
|
|
}
|
|
|
|
/* ----------------------------------------------------------- entry page */
|
|
|
|
/* The article column sets the page width, so the card hugs its text. */
|
|
.entry-page.page-shell {
|
|
width: min(880px, calc(100% - 32px));
|
|
}
|
|
|
|
.entry-shell {
|
|
border-radius: var(--radius);
|
|
padding: 32px 34px 38px;
|
|
}
|
|
|
|
.entry-header {
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.entry-back {
|
|
margin-bottom: 26px;
|
|
}
|
|
|
|
.entry-meta {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: 14px;
|
|
margin-bottom: 14px;
|
|
font-size: 11.5px;
|
|
color: var(--muted);
|
|
}
|
|
|
|
.entry-pill-primary {
|
|
color: var(--secondary);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.1em;
|
|
font-size: 11px;
|
|
}
|
|
|
|
.entry-links {
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.entry-content {
|
|
margin-top: 30px;
|
|
padding-top: 26px;
|
|
border-top: 1px solid var(--border);
|
|
font-size: 0.92rem;
|
|
}
|
|
|
|
.entry-content h1,
|
|
.entry-content h2,
|
|
.entry-content h3,
|
|
.entry-content h4 {
|
|
margin-top: 32px;
|
|
margin-bottom: 10px;
|
|
line-height: 1.3;
|
|
font-size: 1.02rem;
|
|
}
|
|
|
|
.entry-content p,
|
|
.entry-content li {
|
|
color: var(--primary);
|
|
}
|
|
|
|
.entry-content ul,
|
|
.entry-content ol {
|
|
padding-left: 20px;
|
|
}
|
|
|
|
.entry-content li {
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.entry-content li::marker {
|
|
color: var(--secondary);
|
|
}
|
|
|
|
.entry-content a {
|
|
color: var(--secondary);
|
|
border-bottom: 1px solid rgba(235, 82, 52, 0.3);
|
|
}
|
|
|
|
.entry-content a:hover {
|
|
border-bottom-color: var(--secondary);
|
|
}
|
|
|
|
.entry-content blockquote {
|
|
margin: 18px 0;
|
|
padding: 12px 16px;
|
|
border-left: 2px solid var(--secondary);
|
|
background: var(--bar);
|
|
border-radius: 0 var(--radius) var(--radius) 0;
|
|
color: var(--muted);
|
|
}
|
|
|
|
.entry-content code {
|
|
background: var(--bar);
|
|
border: 1px solid var(--border);
|
|
border-radius: 3px;
|
|
padding: 1px 5px;
|
|
font-size: 0.86rem;
|
|
}
|
|
|
|
.entry-content pre {
|
|
padding: 16px 18px;
|
|
overflow-x: auto;
|
|
background: rgba(0, 0, 0, 0.26);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius);
|
|
font-size: 0.84rem;
|
|
line-height: 1.55;
|
|
}
|
|
|
|
.entry-content pre code {
|
|
background: transparent;
|
|
border: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
.entry-empty {
|
|
text-align: center;
|
|
padding: 40px 18px;
|
|
}
|
|
|
|
@media only screen and (max-width: 860px) {
|
|
.projects-page,
|
|
.entry-page {
|
|
padding-top: 28px;
|
|
}
|
|
|
|
.entry-page.page-shell {
|
|
width: min(880px, calc(100% - 20px));
|
|
}
|
|
|
|
.entry-shell {
|
|
padding: 22px 20px 26px;
|
|
}
|
|
|
|
.content-section {
|
|
margin-bottom: 34px;
|
|
}
|
|
|
|
.section-heading {
|
|
flex-direction: column;
|
|
align-items: start;
|
|
gap: 6px;
|
|
}
|
|
}
|