Files
hoelee-blog/src/styles/global.css
T

1650 lines
39 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ============================================================
hoelee-blog — global design system
Brand colors sourced from www.hoelee.com (Kadence palette).
Priority: reading experience → SEO → brand → everything else.
============================================================ */
:root {
/* Brand palette (from hoelee.com Kadence global palette) */
--brand: #295cff; /* primary — cobalt/royal blue */
--brand-strong: #1c0d5a; /* deep indigo — dark bg anchor, headings */
--brand-soft: #0e94ff; /* lighter cyan-blue — hover/links */
--ink: #1a1a1a; /* near-black text (never pure #000) */
--paper: #ffffff; /* near-white bg (never pure #fff for large areas) */
--surface: #f6f8fb; /* cool light gray — cards, code bg */
--surface-2: #eef2f7; /* slightly deeper gray — borders on light */
--border: #e1ebee; /* cool light border (palette7) */
--muted: #57575d; /* secondary text (palette5) */
--faint: #636363; /* tertiary text (palette6) */
/* Semantic (correct/wrong in tutorials) */
--good: #13612e; /* green (palette11) */
--warn: #f5a524; /* amber (palette15) */
--bad: #b82105; /* red (palette13) */
/* Typography */
--font-sans: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif;
--font-mono: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', Consolas, Menlo, Monaco, monospace;
--fs-base: 17px;
--lh-body: 1.7;
/* Layout */
--measure: 70rem; /* global container width (nav, footer, all pages) */
--radius: 8px;
/* Bento cards — RGB triplet of the surface colour, so the thumbnail scrim
fades into the card in BOTH themes (a hardcoded dark blend turned muddy
grey on the light theme: measured pill contrast 1.96:1). */
--card-veil: 246, 248, 251;
--pill-bg: rgba(15, 20, 28, 0.05);
--bento-visual-opacity: 0.3;
color-scheme: light dark;
}
/* Dark theme */
html[data-theme='dark'] {
--brand: #6d8dff;
--brand-soft: #60a5fa;
--brand-strong: #c9c2ff;
--ink: #e5e7eb;
--paper: #111827;
--surface: #1f2937;
--surface-2: #263244;
--border: #2a3345;
--muted: #9ca3af;
--faint: #6b7280;
--good: #4ade80;
--warn: #fbbf24;
--bad: #f87171;
--card-veil: 31, 41, 55;
--pill-bg: rgba(15, 20, 28, 0.5);
--bento-visual-opacity: 0.35;
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
margin: 0;
font-family: var(--font-sans);
font-size: var(--fs-base);
line-height: var(--lh-body);
color: var(--ink);
background: var(--paper);
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
/* ---------- Layout ---------- */
.wrap {
max-width: var(--measure);
margin: 0 auto;
padding: 2rem 1.5rem 5rem;
overflow-wrap: break-word;
}
.wrap > * { min-width: 0; }
/* ---------- Header / nav ---------- */
.site-header {
position: sticky;
top: 0;
z-index: 10;
background: color-mix(in srgb, var(--paper) 88%, transparent);
backdrop-filter: blur(10px);
border-bottom: 1px solid var(--border);
}
.nav {
max-width: var(--measure);
margin: 0 auto;
padding: 0.9rem 1.5rem;
display: flex;
align-items: center;
flex-wrap: wrap;
row-gap: 0.4rem;
gap: 1rem;
}
.nav .brand {
display: inline-flex;
align-items: center;
gap: 0.55rem;
font-weight: 700;
font-size: 1.02rem;
color: var(--ink);
text-decoration: none;
margin-right: auto;
letter-spacing: -0.01em;
white-space: nowrap;
}
/* Brand mark: the three-colour Hoelee mark, rasterised from the vector source
with a transparent background (public/images/hoelee-mark-96.png = 96 px, so
it stays sharp at 26 CSS px on a 3x screen). It is decorative — the name text
next to it is the accessible label. */
.nav .brand-mark {
width: 26px;
height: 26px;
display: block;
flex: none;
}
.nav .brand .brand-name { color: var(--ink); }
.nav .brand:hover .brand-name { color: var(--brand); }
.nav .brand .dot { color: var(--brand); }
.nav .nav-link {
color: var(--muted);
text-decoration: none;
font-size: 0.92rem;
font-weight: 500;
white-space: nowrap;
}
.nav .nav-link:hover { color: var(--brand); }
.nav-links {
display: flex;
align-items: center;
gap: 1rem;
margin: 0;
padding: 0;
list-style: none;
}
.theme-toggle {
background: none;
border: 1px solid var(--border);
color: var(--muted);
border-radius: var(--radius);
padding: 0.25rem 0.6rem;
font-size: 0.85rem;
line-height: 1.35;
cursor: pointer;
font-family: var(--font-sans);
}
.theme-toggle:hover { color: var(--brand); border-color: var(--brand); }
.search-toggle {
background: none;
border: 1px solid var(--border);
color: var(--muted);
border-radius: var(--radius);
padding: 0.25rem 0.6rem;
font-size: 0.95rem;
line-height: 1.35;
cursor: pointer;
font-family: var(--font-sans);
padding-inline: 0.7rem;
display: inline-flex;
align-items: center;
justify-content: center;
}
.search-toggle:hover { color: var(--brand); border-color: var(--brand); }
.search-hint { font-size: 0.85rem; margin-right: 0.35rem; }
.search-key {
font-family: var(--font-mono);
font-size: 0.68rem;
color: var(--faint);
border: 1px solid var(--border);
border-radius: 4px;
padding: 0 0.25rem;
margin-left: 0.1rem;
}
.lang-switch {
color: var(--muted);
text-decoration: none;
font-size: 0.85rem;
font-weight: 500;
line-height: 1.35;
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 0.25rem 0.55rem;
}
.lang-switch:hover { color: var(--brand); border-color: var(--brand); }
/* ---------- Typography ---------- */
h1, h2, h3, h4 {
color: var(--ink);
line-height: 1.25;
letter-spacing: -0.02em;
font-weight: 700;
scroll-margin-top: 5rem;
}
h1 { font-size: 2rem; margin: 0 0 1rem; }
h2 { font-size: 1.4rem; margin: 2.25rem 0 0.75rem; }
h3 { font-size: 1.15rem; margin: 1.75rem 0 0.5rem; }
p { margin: 0 0 1rem; }
a { color: var(--brand); text-decoration: none; }
a:hover { color: var(--brand-soft); }
article a { text-decoration: underline; text-underline-offset: 2px; }
/* Raw HTML in a post body keeps its source width — a 1920px CDN <video> or a
full-size <img> overflows the column and forces a horizontal scrollbar. Cap
everything to the text column; `height:auto` preserves the intrinsic ratio
(never set a fixed aspect-ratio here, clips have different shapes). */
article video,
article iframe {
display: block;
width: 100%;
max-width: 100%;
height: auto;
margin: 1.75rem 0;
border-radius: var(--radius);
border: 1px solid var(--border);
background: #000;
}
article img {
max-width: 100%;
height: auto;
}
/* ---------- Technical Deep Dive Accordion (details/summary) ---------- */
article details.tech-deep-dive {
margin: 1.75rem 0;
padding: 1rem 1.25rem;
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
transition: all 0.2s ease;
}
article details.tech-deep-dive[open] {
padding-bottom: 1.25rem;
}
article details.tech-deep-dive > summary {
cursor: pointer;
font-weight: 600;
font-size: 0.95rem;
color: var(--brand);
user-select: none;
outline: none;
list-style: none;
display: flex;
align-items: center;
gap: 0.5rem;
}
article details.tech-deep-dive > summary::-webkit-details-marker {
display: none;
}
article details.tech-deep-dive > summary::before {
content: '▶';
font-size: 0.75rem;
transition: transform 0.2s ease;
color: var(--brand-soft);
}
article details.tech-deep-dive[open] > summary::before {
transform: rotate(90deg);
}
article details.tech-deep-dive > summary:hover {
color: var(--brand-soft);
}
article details.tech-deep-dive[open] > summary {
margin-bottom: 1rem;
border-bottom: 1px dashed var(--border);
padding-bottom: 0.65rem;
}
time { color: var(--faint); font-size: 0.88rem; }
/* Light theme: the v2 artwork is a near-black viewport, so on a white page it reads as
a hard-edged slab with no separation from the paper. The consultant's ruling
(2026-10-19, option A) is a hairline + soft ambient shadow, so it reads as a
deliberate "dark hardware display case" card. Dark theme needs neither — there the
art merges into the page, which is the effect we want. */
html:not([data-theme='dark']) .article-banner,
html:not([data-theme='dark']) .post-list .thumb,
html:not([data-theme='dark']) .thumb {
border-color: rgba(15, 23, 42, 0.12);
box-shadow: 0 10px 30px -10px rgba(15, 23, 42, 0.25);
}
/* ---------- Article ---------- */
.article-banner {
margin: 0 0 2rem;
border-radius: var(--radius);
overflow: hidden;
border: 1px solid var(--border);
line-height: 0;
}
.article-banner img {
width: 100%;
height: auto;
display: block;
}
/* Desktop: the banner is a 16:9 figure. At full column width (1070px) it stands
602px tall — 67% of a 900px viewport, pushing the whole article below the fold.
Capping the width (rather than cropping) keeps the art intact: 720px -> ~405px,
which is 45% of the viewport. */
@media (min-width: 900px) {
.article-banner { max-width: 720px; margin-left: auto; margin-right: auto; }
}
.article-head {
margin-bottom: 2rem;
padding-bottom: 1.5rem;
border-bottom: 1px solid var(--border);
}
.article-head .meta {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.75rem;
color: var(--muted);
font-size: 0.9rem;
margin: 0.5rem 0 1rem;
}
.article-head .meta .sep { color: var(--border); }
/* ---------- Tags & categories ---------- */
.tag {
display: inline-block;
padding: 0.12em 0.55em;
border-radius: 4px;
font-family: var(--font-mono);
font-size: 0.76rem;
margin: 0 0.35rem 0.35rem 0;
text-decoration: none;
}
a.tag {
background: var(--surface);
border: 1px solid var(--border);
color: var(--brand);
}
a.tag:hover {
border-color: var(--brand);
background: rgba(109, 141, 255, 0.12);
color: var(--brand-soft);
}
span.tag {
color: var(--faint);
background: transparent;
border: 1px dashed var(--border);
}
/* ---------- Code ---------- */
code {
font-family: var(--font-mono);
font-size: 0.85em;
background: var(--surface);
padding: 0.15em 0.4em;
border-radius: 5px;
}
pre {
background: var(--surface);
border: 1px solid var(--border);
padding: 1.1rem 1.25rem;
border-radius: var(--radius);
overflow-x: auto;
line-height: 1.55;
margin: 1.25rem 0;
position: relative;
}
pre code {
background: none;
padding: 0;
font-size: 0.88rem;
}
.code-block { position: relative; }
.copy-btn {
position: absolute;
top: 0.6rem;
right: 0.6rem;
background: var(--surface-2);
color: var(--muted);
border: 1px solid var(--border);
border-radius: 6px;
padding: 0.15rem 0.55rem;
font-size: 0.75rem;
font-family: var(--font-sans);
cursor: pointer;
opacity: 0;
transition: opacity 0.15s;
}
.code-block:hover .copy-btn { opacity: 1; }
.copy-btn.copied { color: var(--good); border-color: var(--good); }
/* ---------- Author card ---------- */
.author-card {
display: flex;
gap: 1rem;
align-items: center;
margin: 2.5rem 0;
padding: 1.25rem;
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
}
.author-card .avatar {
width: 64px;
height: 64px;
border-radius: 50%;
object-fit: cover;
border: 1px solid var(--border);
box-shadow: 0 0 0 1px color-mix(in srgb, var(--brand) 25%, transparent);
flex-shrink: 0;
display: block;
}
.author-card .author-body { min-width: 0; }
.author-card .who { font-weight: 600; margin: 0; }
.author-card .bio { color: var(--muted); font-size: 0.9rem; margin: 0.25rem 0 0.5rem; }
.author-card .links { display: flex; gap: 0.75rem; font-size: 0.85rem; flex-wrap: wrap; }
.author-card .author-split { font-size: 0.82rem; color: var(--muted); margin: 0.6rem 0 0; }
.author-card .author-split a { color: var(--muted); }
.author-card .author-split a:hover { color: var(--brand); }
/* ---------- About ---------- */
.about-hero {
display: flex;
gap: 1.75rem;
align-items: flex-start;
margin: 0.5rem 0 2.25rem;
padding-bottom: 1.75rem;
border-bottom: 1px solid var(--border);
}
.about-photo {
width: 190px;
height: 190px;
border-radius: var(--radius);
border: 1px solid var(--border);
/* The headshot's own dark-blue background sits close to the page background, so a
faint brand ring + shadow is what actually separates it from the UI. */
box-shadow: 0 0 0 1px color-mix(in srgb, var(--brand) 30%, transparent),
0 10px 28px rgba(0, 0, 0, 0.35);
object-fit: cover;
flex-shrink: 0;
display: block;
}
.about-hero h1 { margin-bottom: 0.6rem; }
.about-hero h1 .handle { color: var(--muted); font-weight: 500; }
.about-lede { font-size: 1.02rem; color: var(--muted); margin-bottom: 0.75rem; }
.about-links { font-size: 0.9rem; margin-bottom: 0.5rem; }
.about-open { font-size: 0.9rem; color: var(--muted); margin: 0; }
.proof-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 0.85rem;
margin: 1rem 0 1.25rem;
}
.proof-card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 0.85rem 0.9rem;
}
.proof-card .n { display: block; font-size: 1.45rem; font-weight: 700; line-height: 1.15; }
.proof-card .l { display: block; font-size: 0.78rem; color: var(--muted); margin-top: 0.25rem; }
.stack-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
margin: 1rem 0 1.5rem;
}
.stack-grid h3 { font-size: 0.95rem; margin: 0 0 0.4rem; }
.stack-grid ul { margin: 0; padding-left: 1.1rem; }
.stack-grid li { font-size: 0.88rem; color: var(--muted); margin: 0.15rem 0; }
.sme-block {
background: var(--surface);
border: 1px solid var(--border);
border-left: 3px solid var(--brand);
border-radius: var(--radius);
padding: 1rem 1.1rem;
margin: 1rem 0 1.5rem;
}
.sme-block p { margin: 0.4rem 0; }
.contact-split { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.25rem; margin-top: 1rem; }
.contact-split h3 { font-size: 0.95rem; margin: 0 0 0.35rem; }
.contact-split p { margin: 0.2rem 0; font-size: 0.9rem; color: var(--muted); }
/* ---------- Dual-Track Work With Me Grid ---------- */
.work-with-me-section {
margin: 2.5rem 0 3rem;
}
.section-sub {
font-size: 1rem;
color: var(--muted);
margin: -0.25rem 0 1.5rem;
}
.dual-track-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
gap: 1.5rem;
margin: 1.5rem 0 2rem;
}
.track-card {
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 1.75rem;
border-radius: var(--radius);
border: 1px solid var(--border);
background: var(--surface);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.04);
}
.track-business {
border-top: 4px solid #10b981; /* 翡翠绿:商业增长与 ROI */
}
.track-hiring {
border-top: 4px solid #3b82f6; /* 科技蓝:架构与工程稳健 */
}
.track-badge {
display: inline-block;
font-size: 0.82rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.04em;
margin-bottom: 0.6rem;
}
.track-business .track-badge {
color: #10b981;
}
.track-hiring .track-badge {
color: #3b82f6;
}
.track-header h3 {
margin: 0 0 0.6rem;
font-size: 1.25rem;
line-height: 1.35;
color: var(--ink);
}
.track-header p {
font-size: 0.95rem;
color: var(--muted);
line-height: 1.55;
margin: 0;
}
.track-body {
margin: 1.25rem 0;
display: flex;
flex-direction: column;
gap: 0.6rem;
}
.track-body h4 {
font-size: 0.95rem;
margin: 0.6rem 0 0.2rem;
color: var(--ink);
font-weight: 600;
}
.track-body ul, .track-body ol {
margin: 0;
padding-left: 1.25rem;
}
.track-body li {
font-size: 0.9rem;
line-height: 1.55;
color: var(--muted);
margin: 0.35rem 0;
}
.track-body li strong {
color: var(--ink);
}
.proof-links {
list-style: none !important;
padding-left: 0 !important;
}
.proof-links li {
margin: 0.45rem 0;
}
.proof-links a {
color: var(--brand-soft);
text-decoration: none;
font-weight: 500;
}
.proof-links a:hover {
color: var(--brand);
text-decoration: underline;
}
.track-cta {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
margin-top: 1.25rem;
padding-top: 1.25rem;
border-top: 1px solid var(--border);
}
/* ---------- What I Actually Run in Production ---------- */
.stack-section {
margin: 3rem 0;
}
.stack-card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 1.25rem 1.4rem;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.stack-card h3 {
font-size: 1.05rem;
margin: 0 0 0.5rem;
color: var(--ink);
}
.stack-card p {
font-size: 0.9rem;
line-height: 1.55;
color: var(--muted);
margin: 0 0 0.85rem;
}
.stack-proof {
font-size: 0.85rem;
padding-top: 0.65rem;
border-top: 1px dashed var(--border);
display: flex;
align-items: center;
gap: 0.5rem;
}
.stack-proof span {
color: var(--muted);
font-weight: 600;
}
.stack-proof a {
color: var(--brand);
text-decoration: none;
font-weight: 600;
}
.stack-proof a:hover {
text-decoration: underline;
}
/* ---------- Engineering Philosophy / Guardrails ---------- */
.principles-section {
margin: 3rem 0 2rem;
}
.principles-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 1.25rem;
margin-top: 1rem;
}
.principle-item {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 1.25rem 1.35rem;
}
.principle-item strong {
display: block;
font-size: 0.98rem;
color: var(--ink);
margin-bottom: 0.45rem;
line-height: 1.4;
}
.principle-item p {
margin: 0;
font-size: 0.88rem;
color: var(--muted);
line-height: 1.55;
}
/* ---------- Related posts ---------- */
.related { margin-top: 3rem; padding-top: 1.5rem; border-top: 1px solid var(--border); }
.related-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
margin-top: 1rem;
}
.related-card {
display: flex;
flex-direction: column;
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
overflow: hidden;
color: var(--ink);
text-decoration: none;
}
/* The post's own OG share card doubles as the card image, so the art matches
the language of the page (see the ogImage note in posts/[...slug].astro). */
.related-thumb {
display: block;
width: 100%;
height: auto;
aspect-ratio: 1200 / 630;
object-fit: cover;
background: var(--border);
border-bottom: 1px solid var(--border);
}
.related-card:hover { border-color: var(--brand); }
.related-body { padding: 0.8rem 0.9rem; display: flex; flex-direction: column; flex: 1; }
.related-badge {
align-self: flex-start;
display: inline-block;
font-size: 0.68rem;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--brand);
background: var(--surface);
border: 1px solid var(--border);
border-radius: 999px;
padding: 0.1em 0.6em;
margin-bottom: 0.45rem;
}
.related-card h3 {
margin: 0 0 0.3rem;
font-size: 0.92rem;
/* keep card heights comparable across a row */
display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.related-card time { font-size: 0.78rem; margin-top: auto; padding-top: 0.4rem; }
/* ---------- Home hero ---------- */
.hero {
margin: 0.5rem 0 2.2rem;
padding-bottom: 1.75rem;
border-bottom: 1px solid var(--border);
}
.hero-id { display: flex; align-items: center; gap: 1rem; margin-bottom: 0.75rem; }
.hero-photo {
width: 72px;
height: 72px;
border-radius: 50%;
border: 1px solid var(--border);
box-shadow: 0 0 0 1px color-mix(in srgb, var(--brand) 30%, transparent);
object-fit: cover;
flex-shrink: 0;
display: block;
}
.hero h1 { margin: 0; font-size: 1.85rem; line-height: 1.25; }
.hero-sub { font-size: 1.02rem; color: var(--muted); max-width: 62ch; margin: 0 0 0.25rem; line-height: 1.6; }
/* Tech Stack Pills */
.hero-pills {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.45rem;
margin: 0.85rem 0 0;
}
.hero-pills-label {
font-size: 0.78rem;
color: var(--faint);
font-family: var(--font-mono);
margin-right: 0.15rem;
}
.tech-pill {
display: inline-flex;
align-items: center;
font-size: 0.78rem;
font-family: var(--font-mono);
color: var(--muted);
background: var(--surface);
border: 1px solid var(--border);
border-radius: 999px;
padding: 0.18rem 0.65rem;
text-decoration: none;
transition: all 0.2s ease;
}
.tech-pill:hover {
color: var(--brand);
border-color: var(--brand);
background: color-mix(in srgb, var(--brand) 10%, transparent);
}
/* CTA buttons & RSS note */
.hero-cta {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
margin: 0;
}
.btn {
display: inline-flex;
align-items: center;
font-size: 0.88rem;
color: var(--ink);
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 0.52rem 0.95rem;
text-decoration: none;
transition: border-color 0.2s ease, color 0.2s ease, background 0.2s ease, transform 0.15s ease, box-shadow 0.2s ease;
}
.btn:hover {
border-color: var(--brand);
color: var(--brand);
}
.btn-primary {
background: var(--brand);
color: #ffffff !important;
border-color: var(--brand);
font-weight: 600;
box-shadow: 0 2px 8px color-mix(in srgb, var(--brand) 30%, transparent);
}
.btn-primary:hover {
background: var(--brand-soft);
border-color: var(--brand-soft);
color: #ffffff !important;
transform: translateY(-1px);
box-shadow: 0 4px 14px color-mix(in srgb, var(--brand) 45%, transparent);
}
.hero-note { font-size: 0.82rem; color: var(--faint); margin: 0; }
/* Visual block (Banner + Lightbox + Infra Stats Grid) */
.hero-visual {
display: flex;
flex-direction: column;
gap: 0.75rem;
min-width: 0;
}
.hero-banner-card {
position: relative;
display: block;
width: 100%;
padding: 0;
margin: 0;
border: 1px solid var(--border-color, rgba(128, 128, 128, 0.2));
background: var(--surface);
border-radius: 12px;
overflow: hidden;
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.15);
cursor: zoom-in;
text-align: left;
transition: border-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease;
}
.hero-banner-card:hover {
border-color: color-mix(in srgb, var(--brand) 40%, var(--border));
box-shadow: 0 14px 36px -10px rgba(0, 0, 0, 0.25);
transform: translateY(-1px);
}
.hero-banner-img {
width: 100%;
height: auto;
aspect-ratio: 16 / 9;
display: block;
object-fit: cover;
}
.hero-banner-zoom-badge {
position: absolute;
bottom: 0.65rem;
right: 0.65rem;
z-index: 2;
padding: 0.25rem 0.6rem;
font-size: 0.75rem;
font-weight: 500;
color: #ffffff;
background: rgba(15, 23, 42, 0.82);
backdrop-filter: blur(6px);
border: 1px solid rgba(255, 255, 255, 0.18);
border-radius: 6px;
pointer-events: none;
transition: background 0.2s ease, border-color 0.2s ease;
}
.hero-banner-card:hover .hero-banner-zoom-badge {
background: var(--brand);
border-color: rgba(255, 255, 255, 0.35);
}
/* 4-Stat Infra Grid */
.hero-infra-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 0.75rem;
}
.infra-stat-card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 0.7rem 0.9rem;
display: flex;
flex-direction: column;
justify-content: center;
transition: border-color 0.2s ease, background 0.2s ease;
}
.infra-stat-card:hover {
border-color: color-mix(in srgb, var(--brand) 35%, var(--border));
}
.infra-stat-val {
font-size: 1.3rem;
font-weight: 700;
line-height: 1.2;
color: var(--ink);
letter-spacing: -0.02em;
font-family: var(--font-mono);
}
.infra-stat-label {
font-size: 0.76rem;
color: var(--muted);
margin-top: 0.2rem;
line-height: 1.35;
}
/* Architecture Lightbox Dialog */
.arch-lightbox {
border: none;
border-radius: 12px;
background: transparent;
padding: 0;
max-width: 94vw;
max-height: 94vh;
margin: auto;
box-shadow: 0 25px 60px rgba(0, 0, 0, 0.6);
outline: none;
}
.arch-lightbox::backdrop {
background: rgba(0, 0, 0, 0.85);
backdrop-filter: blur(8px);
}
.arch-lightbox-inner {
position: relative;
display: flex;
flex-direction: column;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
overflow: hidden;
}
.arch-lightbox-close {
position: absolute;
top: 0.75rem;
right: 0.75rem;
z-index: 2;
width: 36px;
height: 36px;
border-radius: 50%;
border: 1px solid var(--border);
background: rgba(0, 0, 0, 0.6);
color: #fff;
font-size: 1.4rem;
line-height: 1;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: background 0.2s, transform 0.15s;
}
.arch-lightbox-close:hover {
background: var(--brand);
transform: scale(1.05);
}
.arch-lightbox img {
width: 100%;
max-height: 82vh;
object-fit: contain;
display: block;
}
.arch-lightbox-caption {
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
padding: 0.65rem 1rem;
font-size: 0.82rem;
color: var(--muted);
border-top: 1px solid var(--border);
background: var(--paper);
}
.arch-lightbox-hint {
font-size: 0.75rem;
color: var(--faint);
}
/* Desktop layout: >= 960px */
@media (min-width: 960px) {
.hero {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: auto 1fr;
grid-template-areas:
"intro visual"
"actions visual";
gap: 1.5rem 2rem;
align-items: stretch;
}
.hero-intro {
grid-area: intro;
}
.hero-actions {
grid-area: actions;
display: flex;
flex-direction: column;
justify-content: flex-end;
gap: 0.75rem;
}
.hero-visual {
grid-area: visual;
}
}
/* Mobile & Tablet: < 960px */
@media (max-width: 959px) {
.hero {
display: flex;
flex-direction: column;
gap: 1.25rem;
}
.hero-banner-card {
border-radius: 8px;
}
.hero-actions {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
}
/* Section Header with Category Shortcuts */
.section-head-with-nav {
display: flex;
align-items: baseline;
justify-content: space-between;
flex-wrap: wrap;
gap: 0.75rem 1rem;
margin: 2.25rem 0 0.75rem;
}
.section-head-with-nav h2 {
margin: 0;
}
.section-nav-pills {
display: inline-flex;
flex-wrap: wrap;
gap: 0.4rem;
align-items: center;
}
.section-nav-pill {
font-size: 0.76rem;
font-family: var(--font-mono);
color: var(--muted);
background: var(--surface);
border: 1px solid var(--border);
border-radius: 999px;
padding: 0.15rem 0.6rem;
text-decoration: none;
transition: all 0.2s ease;
}
.section-nav-pill:hover {
color: var(--brand);
border-color: var(--brand);
background: color-mix(in srgb, var(--brand) 10%, transparent);
}
.section-nav-all {
color: var(--brand);
border-color: color-mix(in srgb, var(--brand) 30%, var(--border));
}
.section-nav-all:hover {
background: var(--brand);
color: #ffffff;
border-color: var(--brand);
}
/* ---------- Featured 2x2 Cyber-Bento Grid ---------- */
.featured-bento-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 1.15rem;
margin: 1rem 0 2.5rem;
}
@media (max-width: 680px) {
.featured-bento-grid {
grid-template-columns: 1fr;
}
}
.bento-card {
position: relative;
display: flex;
flex-direction: column;
justify-content: space-between;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
padding: 1.3rem;
overflow: hidden;
color: var(--ink);
text-decoration: none;
transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
isolation: isolate;
}
.bento-card:hover {
transform: translateY(-2px);
border-color: var(--brand);
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.4), 0 0 20px -5px rgba(109, 141, 255, 0.25);
color: var(--ink);
}
.bento-visual {
position: absolute;
top: 0;
right: 0;
width: 65%;
height: 140px;
z-index: -1;
opacity: var(--bento-visual-opacity);
transition: opacity 0.25s ease, transform 0.35s ease;
pointer-events: none;
}
.bento-card:hover .bento-visual {
opacity: 0.55;
transform: scale(1.04);
}
.bento-visual img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: right center;
}
.bento-visual-scrim {
position: absolute;
inset: 0;
background:
linear-gradient(90deg, var(--surface) 0%, rgba(var(--card-veil), 0.6) 45%, transparent 100%),
linear-gradient(0deg, var(--surface) 0%, rgba(var(--card-veil), 0.4) 55%, transparent 100%);
}
.bento-content {
display: flex;
flex-direction: column;
height: 100%;
gap: 0.65rem;
}
.bento-top-meta {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.5rem;
flex-wrap: wrap;
}
.featured-badge {
font-family: var(--font-mono);
font-size: 0.72rem;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--brand);
background: rgba(109, 141, 255, 0.12);
border: 1px solid rgba(109, 141, 255, 0.3);
padding: 0.15rem 0.55rem;
border-radius: 999px;
}
.bento-metric-pill {
display: inline-flex;
align-items: center;
gap: 0.38rem;
font-family: var(--font-mono);
font-size: 0.72rem;
color: var(--muted);
background: var(--pill-bg);
border: 1px solid var(--border);
padding: 0.15rem 0.55rem;
border-radius: 6px;
}
.pulse-dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--good);
box-shadow: 0 0 6px var(--good);
animation: bento-pulse 2.4s ease-in-out infinite;
}
@keyframes bento-pulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.55; transform: scale(0.82); }
}
@media (prefers-reduced-motion: reduce) {
.pulse-dot { animation: none; }
}
.bento-card h3 {
font-size: 1.08rem;
line-height: 1.38;
color: var(--ink);
margin-top: 0.15rem;
}
.bento-card p {
font-size: 0.88rem;
line-height: 1.55;
color: var(--muted);
flex-grow: 1;
}
.bento-cta {
font-family: var(--font-mono);
font-size: 0.78rem;
color: var(--brand);
margin-top: 0.35rem;
transition: transform 0.15s ease;
}
.bento-card:hover .bento-cta {
color: var(--brand-soft);
transform: translateX(3px);
}
/* ---------- Collapsible long code blocks ---------- */
.code-block { position: relative; }
.code-block.is-collapsed pre { max-height: 420px; overflow: hidden; }
.code-block.is-collapsed::after {
content: '';
position: absolute;
left: 0; right: 0;
bottom: 2.4rem;
height: 5rem;
pointer-events: none;
background: linear-gradient(to bottom, transparent, var(--paper));
}
.code-expand {
display: block;
width: 100%;
margin-top: 0.35rem;
font: inherit;
font-size: 0.82rem;
color: var(--muted);
background: var(--surface);
border: 1px solid var(--border);
border-radius: 6px;
padding: 0.35rem;
cursor: pointer;
}
.code-expand:hover { color: var(--brand); border-color: var(--brand); }
/* ---------- Archive ---------- */
.archive-lead, .archive-meta { color: var(--muted); font-size: 0.92rem; }
.archive-meta { margin: 0 0 1rem; }
/* ---------- 404 ---------- */
.notfound-actions {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.75rem;
margin: 1.5rem 0 2rem;
}
.notfound-btn {
font: inherit;
color: var(--ink);
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 0.45rem 0.9rem;
cursor: pointer;
}
.notfound-btn:hover { border-color: var(--brand); color: var(--brand); }
.notfound-row .body { padding-block: 0.6rem; }
/* ---------- Post list ---------- */
.post-list { list-style: none; padding: 0; margin: 0; }
.post-list li {
padding: 1.25rem 0;
border-bottom: 1px solid var(--border);
}
.post-list li:last-child { border-bottom: none; }
.post-list h2 { margin: 0 0 0.3rem; font-size: 1.25rem; }
.post-list .meta { color: var(--faint); font-size: 0.85rem; margin-bottom: 0.5rem; }
.post-list .meta .sep { color: var(--border); }
.post-list .updated { color: var(--brand); font-weight: 500; }
.post-list p { color: var(--muted); margin: 0.4rem 0 0; }
/* Post list card: thumbnail (left) + text (right) on desktop */
.post-list .post-row {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
align-items: start;
}
.post-list .thumb {
display: block;
border-radius: var(--radius);
overflow: hidden;
line-height: 0;
border: 1px solid var(--border);
background: var(--surface);
}
.post-list .thumb img {
width: 100%;
height: auto;
display: block;
aspect-ratio: 1200 / 630;
object-fit: cover;
}
@media (min-width: 1024px) {
.post-list .post-row {
grid-template-columns: 400px 1fr;
gap: 2rem;
align-items: center;
}
}
/* ---------- Page head (lead paragraphs on listing pages) ---------- */
.page-head h1 { margin: 0 0 0.75rem; }
.lede {
color: var(--muted);
font-size: 1.05rem;
max-width: 46rem;
margin: 0 0 1.75rem;
}
p.lede { margin-bottom: 1.75rem; }
/* ---------- Category grid ---------- */
.category-grid {
list-style: none;
padding: 0;
margin: 0;
display: grid;
grid-template-columns: 1fr;
gap: 1.25rem;
}
.category-card {
display: flex;
flex-direction: column;
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
overflow: hidden;
text-decoration: none;
color: var(--ink);
height: 100%;
}
a.category-card:hover { border-color: var(--brand); }
.category-card .art {
line-height: 0;
border-bottom: 1px solid var(--border);
background: #0d1220;
}
.category-card .art svg,
.category-card .art img,
.category-card .art picture {
width: 100%;
height: auto;
aspect-ratio: 16 / 9;
object-fit: cover;
display: block;
transition: transform 0.25s ease;
}
a.category-card:hover .art img {
transform: scale(1.02);
}
.category-card .body {
padding: 1.05rem 1.2rem 1.2rem;
display: flex;
flex-direction: column;
flex: 1;
}
.category-card h2 {
margin: 0 0 0.45rem;
font-size: 1.15rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.category-card h2 .dot {
width: 0.5em;
height: 0.5em;
border-radius: 50%;
flex-shrink: 0;
}
.category-card p {
color: var(--muted);
margin: 0 0 0.75rem;
font-size: 0.93rem;
line-height: 1.6;
}
.category-card .count {
margin-top: auto;
font-family: var(--font-mono);
font-size: 0.8rem;
color: var(--faint);
}
.category-card .count .n { color: var(--brand); font-weight: 600; }
.category-card.is-empty { opacity: 0.82; }
.category-card.is-empty .count { color: var(--warn); }
.category-card.is-empty .count .n { color: var(--warn); }
@media (min-width: 640px) {
.category-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
.category-grid { grid-template-columns: repeat(3, 1fr); }
}
/* ---------- Category detail hero art ---------- */
.cat-art-wrap {
margin: 1.1rem 0 0 0;
border: 1px solid var(--border);
border-radius: var(--radius);
overflow: hidden;
line-height: 0;
background: #0d1220;
}
.cat-art-wrap svg,
.cat-art-wrap img,
.cat-art-wrap picture {
width: 100%;
height: auto;
aspect-ratio: 16 / 9;
object-fit: cover;
display: block;
}
.cat-count {
margin: 1.25rem 0 1.75rem;
font-family: var(--font-mono);
font-size: 0.85rem;
color: var(--faint);
}
/* ---------- Callouts (correct / wrong in tutorials) ---------- */
.callout {
border-left: 3px solid var(--brand);
background: var(--surface);
padding: 0.75rem 1rem;
border-radius: 0 var(--radius) var(--radius) 0;
margin: 1.25rem 0;
}
.callout.good { border-left-color: var(--good); }
.callout.warn { border-left-color: var(--warn); }
.callout.bad { border-left-color: var(--bad); }
/* ---------- Footer ---------- */
.site-footer {
max-width: var(--measure);
margin: 0 auto;
padding: 1.5rem;
border-top: 1px solid var(--border);
color: var(--faint);
font-size: 0.85rem;
display: flex;
flex-wrap: wrap;
gap: 0.75rem 1rem;
justify-content: space-between;
}
.site-footer span:last-child {
display: flex;
flex-wrap: wrap;
gap: 0.25rem 1rem;
}
.site-footer a { color: var(--muted); text-decoration: none; }
.site-footer a:hover { color: var(--brand); }
/* ---------- Utility ---------- */
.sr-only {
position: absolute; width: 1px; height: 1px;
padding: 0; margin: -1px; overflow: hidden;
clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
/* ---------- Mobile ---------- */
@media (max-width: 600px) {
.wrap { padding: 1.5rem 1.25rem 4rem; }
/* Two-row header: brand + search/lang/theme on row 1, the four section links
on row 2. Without the grouped list the links wrapped one at a time and
pushed the right-hand controls past the viewport edge at 320–390 px. */
.nav { padding: 0.7rem 1.25rem; gap: 0.55rem 0.7rem; }
.nav .brand { order: 1; font-size: 0.95rem; gap: 0.45rem; }
.nav .brand-mark { width: 22px; height: 22px; }
.search-toggle, .lang-switch, .theme-toggle { order: 2; }
.search-toggle { padding-inline: 0.55rem; }
.lang-switch { padding: 0.25rem 0.45rem; }
.theme-toggle { padding: 0.25rem 0.5rem; }
.nav-links { order: 3; flex: 0 0 100%; gap: 0.9rem; flex-wrap: wrap; row-gap: 0.35rem; }
h1 { font-size: 1.7rem; }
h2 { font-size: 1.25rem; }
/* Related grid: one full-width card per row on phones, first four only. */
.related-grid { grid-template-columns: 1fr; gap: 0.85rem; }
.related-extra { display: none; }
.featured-bento-grid { grid-template-columns: 1fr; }
.proof-grid { grid-template-columns: repeat(2, 1fr); }
.stack-grid, .contact-split { grid-template-columns: 1fr; }
.about-hero { flex-direction: column; gap: 1rem; }
.about-photo { width: 140px; height: 140px; }
.dual-track-grid { grid-template-columns: 1fr; }
.track-cta { flex-direction: column; }
.track-cta .btn { width: 100%; justify-content: center; }
.search-hint, .search-key { display: none; }
.author-card { flex-direction: column; align-items: flex-start; }
}
/* ---------- Creative Lab Strip (GPU & Multimodal Lab) ---------- */
.creative-lab-strip {
margin-top: 3.5rem;
padding: 1.75rem;
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
}
.lab-strip-header {
margin-bottom: 1.5rem;
}
.lab-strip-title-wrap {
display: flex;
align-items: center;
gap: 0.65rem;
margin-bottom: 0.4rem;
}
.lab-strip-badge {
font-family: var(--font-mono);
font-size: 0.75rem;
font-weight: 600;
color: #ff7ab6;
background: rgba(255, 122, 182, 0.12);
border: 1px solid rgba(255, 122, 182, 0.3);
border-radius: 9999px;
padding: 0.15rem 0.6rem;
letter-spacing: 0.04em;
text-transform: uppercase;
}
.lab-strip-header h2 {
margin: 0;
font-size: 1.35rem;
}
.lab-strip-sub {
color: var(--muted);
font-size: 0.95rem;
margin: 0;
max-width: 46rem;
line-height: 1.5;
}
.lab-cards-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1.25rem;
margin-bottom: 1.25rem;
}
.lab-card {
display: flex;
flex-direction: column;
background: var(--surface-subtle, rgba(255, 255, 255, 0.02));
border: 1px solid var(--border);
border-radius: var(--radius);
overflow: hidden;
text-decoration: none;
color: inherit;
transition: transform 0.15s ease, border-color 0.15s ease;
}
.lab-card:hover {
transform: translateY(-2px);
border-color: var(--brand);
}
.lab-card-thumb {
width: 100%;
aspect-ratio: 1200 / 630;
overflow: hidden;
background: var(--surface);
line-height: 0;
}
.lab-card-thumb img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.lab-card-body {
padding: 1rem;
display: flex;
flex-direction: column;
flex: 1;
}
.lab-card-tag {
font-family: var(--font-mono);
font-size: 0.75rem;
color: var(--faint);
margin-bottom: 0.4rem;
}
.lab-card-body h3 {
font-size: 1rem;
line-height: 1.35;
margin: 0 0 0.5rem;
color: var(--ink);
}
.lab-card-body p {
font-size: 0.85rem;
line-height: 1.45;
color: var(--muted);
margin: 0;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
@media (max-width: 768px) {
.lab-cards-grid {
grid-template-columns: 1fr;
}
}