The consultant-approved "one art, four targets" work existed only in the
working tree. Commit it so the 72-post rollout is reproducible from the repo
instead of from one session's scratch files.
- template-v2.html / v2.1 / v2.2: the iteration the consultant reviewed, plus
the accepted frosted-bento layout (736x536 card, blueprint grid, full-width
evidence bar, self-fitting headline script that reports "FIT <n>px").
- render_sample_suite{,_v2,_v3}.mjs + fit-title-probe.mjs: how the two sample
posts were rendered for rounds 2-4 (kept for provenance).
- generate_prompts_catalog.py + prompts_catalog.json: the 72 per-post prompts
and their visual metaphors, extracted from the posts themselves.
- render_from_art.mjs (new): the batch renderer. One zero-text base frame per
post -> banner 1600x900 webp (+jpg fallback), social card 1200x630 (EN and
zh-<slug>), thumbs 800x420 and 400x210. Cards are filled from frontmatter +
art-meta.json; a missing evidence line or a headline that never settles is a
hard failure, never a silently-degraded card.
- art-meta.json: the per-slug input contract. Two slugs wired; 70 still need
base art (GPU) and a hand-written evidence line.
- README: documents the pipeline, the measured format choice (558 KB PNG ->
84 KB mozjpeg q85) and the PostList thumb-helper trap when ogImage moves to
.jpg.
Proof the renderer reproduces the accepted output: re-rendering the two sample
posts yields banner + 800px thumb files BYTE-IDENTICAL to the consultant's
delivery (sha256 16e6a7b0, f3b29f38, c4e28291, 8095ec6c), and all four cards
report FIT, 2-3 title lines, 2 description lines, 0 overflow in x and y.
341 lines
9.1 KiB
HTML
341 lines
9.1 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="{{LANG}}">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<style>
|
|
:root {
|
|
--bg-base: #090d16;
|
|
--primary: #4d82ff;
|
|
--primary-bright: #6d8dff;
|
|
--accent-green: #3fb950;
|
|
--accent-red: #ff7b72;
|
|
--text-main: #f8fafc;
|
|
--text-sub: #cbd5e1;
|
|
--text-muted: #94a3b8;
|
|
--text-dim: #64748b;
|
|
}
|
|
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
html, body {
|
|
width: 1200px;
|
|
height: 630px;
|
|
overflow: hidden;
|
|
background: var(--bg-base);
|
|
font-family: "Space Grotesk", "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
|
|
color: var(--text-main);
|
|
-webkit-font-smoothing: antialiased;
|
|
}
|
|
|
|
.canvas {
|
|
position: relative;
|
|
width: 1200px;
|
|
height: 630px;
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 44px 52px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* 1. 底层:将 AI 3D 底图适度放大 18% 并向中轴线微移,消除中间与右上角空洞 */
|
|
.bg-artwork {
|
|
position: absolute;
|
|
top: -9%;
|
|
right: -4%;
|
|
width: 116%;
|
|
height: 118%;
|
|
object-fit: cover;
|
|
object-position: right center;
|
|
z-index: 1;
|
|
}
|
|
|
|
/* 2. 中层 A:柔和过渡遮罩(告别死纯黑,保留底层微光与空间感) */
|
|
.scrim-overlay {
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 2;
|
|
background:
|
|
radial-gradient(circle at 18% 22%, rgba(77, 130, 255, 0.14) 0%, transparent 48%),
|
|
radial-gradient(circle at 80% 50%, rgba(9, 13, 22, 0.0) 0%, rgba(9, 13, 22, 0.55) 58%, rgba(9, 13, 22, 0.90) 82%),
|
|
linear-gradient(90deg, rgba(9, 13, 22, 0.84) 0%, rgba(9, 13, 22, 0.78) 42%, rgba(9, 13, 22, 0.28) 68%, rgba(9, 13, 22, 0.05) 100%);
|
|
}
|
|
|
|
/* 3. 中层 B:CSS 编程级蓝图坐标网格(确保左侧绝不死黑单调) */
|
|
.blueprint-grid {
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 2;
|
|
background-image:
|
|
linear-gradient(to right, rgba(109, 141, 255, 0.05) 1px, transparent 1px),
|
|
linear-gradient(to bottom, rgba(109, 141, 255, 0.05) 1px, transparent 1px);
|
|
background-size: 36px 36px;
|
|
mask-image: linear-gradient(90deg, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.5) 55%, transparent 85%);
|
|
-webkit-mask-image: linear-gradient(90deg, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.5) 55%, transparent 85%);
|
|
}
|
|
|
|
/* 外框蓝图装饰线与十字准星 */
|
|
.blueprint-accents {
|
|
position: absolute;
|
|
inset: 20px;
|
|
border: 1px solid rgba(109, 141, 255, 0.10);
|
|
border-radius: 16px;
|
|
pointer-events: none;
|
|
z-index: 3;
|
|
}
|
|
.crosshair {
|
|
position: absolute;
|
|
width: 15px;
|
|
height: 15px;
|
|
opacity: 0.45;
|
|
}
|
|
.crosshair::before, .crosshair::after {
|
|
content: "";
|
|
position: absolute;
|
|
background: var(--primary-bright);
|
|
}
|
|
.crosshair::before { top: 7px; left: 0; width: 15px; height: 1px; }
|
|
.crosshair::after { left: 7px; top: 0; width: 1px; height: 15px; }
|
|
.ch-tr { top: 22px; right: 26px; }
|
|
.ch-br { bottom: 22px; right: 26px; }
|
|
|
|
/* 4. 顶层:左侧半透明磨砂亚克力 Bento 容器卡 */
|
|
.bento-card {
|
|
position: relative;
|
|
z-index: 4;
|
|
width: 736px;
|
|
height: 536px;
|
|
padding: 38px 44px;
|
|
border-radius: 18px;
|
|
background: linear-gradient(145deg, rgba(21, 29, 46, 0.82) 0%, rgba(13, 18, 30, 0.74) 100%);
|
|
border: 1px solid rgba(109, 141, 255, 0.24);
|
|
box-shadow:
|
|
0 24px 48px rgba(0, 0, 0, 0.55),
|
|
inset 0 1px 0 rgba(255, 255, 255, 0.12);
|
|
backdrop-filter: blur(16px);
|
|
-webkit-backdrop-filter: blur(16px);
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
/* Bento 卡片顶部蓝色微光装饰条 */
|
|
.bento-card::before {
|
|
content: "";
|
|
position: absolute;
|
|
top: -1px;
|
|
left: 44px;
|
|
width: 96px;
|
|
height: 2px;
|
|
background: linear-gradient(90deg, var(--primary-bright), transparent);
|
|
}
|
|
|
|
/* --- 第一段 (Top):分类徽章 + 核心技术标签 --- */
|
|
.top-row {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 12px;
|
|
}
|
|
.badge-group {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
}
|
|
.cat-badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 6px 14px;
|
|
border-radius: 999px;
|
|
background: rgba(77, 130, 255, 0.2);
|
|
border: 1px solid rgba(109, 141, 255, 0.5);
|
|
color: #a5c0ff;
|
|
font-family: "JetBrains Mono", "Fira Code", monospace;
|
|
font-size: 13px;
|
|
font-weight: 700;
|
|
letter-spacing: 1px;
|
|
text-transform: uppercase;
|
|
}
|
|
.cat-badge .dot {
|
|
width: 7px;
|
|
height: 7px;
|
|
border-radius: 50%;
|
|
background: var(--accent-green);
|
|
box-shadow: 0 0 8px var(--accent-green);
|
|
}
|
|
.top-tags {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
font-family: "JetBrains Mono", "Fira Code", monospace;
|
|
font-size: 13px;
|
|
}
|
|
.top-tags span {
|
|
background: rgba(15, 21, 35, 0.75);
|
|
border: 1px solid rgba(56, 72, 99, 0.7);
|
|
padding: 4px 10px;
|
|
border-radius: 6px;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
/* --- 第二段 (Center):大标题 + 2行摘要 + 100%等宽终端证据条 --- */
|
|
.center-block {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 16px;
|
|
margin: auto 0;
|
|
}
|
|
.title {
|
|
font-weight: 800;
|
|
font-size: {{TITLE_SIZE}}px;
|
|
line-height: 1.22;
|
|
letter-spacing: -0.02em;
|
|
color: #ffffff;
|
|
display: -webkit-box;
|
|
-webkit-line-clamp: 3;
|
|
-webkit-box-orient: vertical;
|
|
overflow: hidden;
|
|
text-shadow: 0 2px 16px rgba(0, 0, 0, 0.5);
|
|
}
|
|
|
|
/* 新增:2 行文章核心摘要,彻底消除纵向空洞 */
|
|
.desc {
|
|
font-size: 18px;
|
|
line-height: 1.5;
|
|
color: var(--text-sub);
|
|
font-weight: 400;
|
|
display: -webkit-box;
|
|
-webkit-line-clamp: 2;
|
|
-webkit-box-orient: vertical;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* 100% 撑满 Bento 容器的终端证据栏,消除右侧阶梯空缺 */
|
|
.evidence-strip {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
width: 100%;
|
|
margin-top: 4px;
|
|
padding: 13px 18px;
|
|
border-radius: 10px;
|
|
background: rgba(9, 13, 22, 0.85);
|
|
border: 1px solid rgba(77, 130, 255, 0.28);
|
|
border-left: 3px solid var(--primary-bright);
|
|
font-family: "JetBrains Mono", "Fira Code", monospace;
|
|
font-size: 15.5px;
|
|
line-height: 1.4;
|
|
color: #e2e8f0;
|
|
}
|
|
.evidence-strip .prompt {
|
|
color: var(--accent-green);
|
|
font-weight: 700;
|
|
}
|
|
.evidence-strip .text {
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
/* --- 第三段 (Bottom):个人品牌锁定 --- */
|
|
.bottom-row {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding-top: 18px;
|
|
border-top: 1px solid rgba(255, 255, 255, 0.09);
|
|
}
|
|
.author-lockup {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 14px;
|
|
}
|
|
.author-avatar {
|
|
width: 44px;
|
|
height: 44px;
|
|
border-radius: 50%;
|
|
object-fit: cover;
|
|
border: 2px solid var(--primary-bright);
|
|
}
|
|
.author-meta {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 2px;
|
|
}
|
|
.author-name {
|
|
font-size: 17px;
|
|
font-weight: 700;
|
|
color: #ffffff;
|
|
}
|
|
.author-name .handle {
|
|
font-weight: 500;
|
|
color: var(--text-muted);
|
|
font-size: 14px;
|
|
margin-left: 6px;
|
|
}
|
|
.author-role {
|
|
font-family: "JetBrains Mono", monospace;
|
|
font-size: 12px;
|
|
letter-spacing: 0.5px;
|
|
color: var(--primary-bright);
|
|
}
|
|
.domain-pill {
|
|
font-family: "JetBrains Mono", monospace;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
color: #cbd5e1;
|
|
background: rgba(77, 130, 255, 0.12);
|
|
border: 1px solid rgba(109, 141, 255, 0.3);
|
|
padding: 6px 14px;
|
|
border-radius: 8px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="canvas">
|
|
<!-- 1. Ideogram 4 背景图(自动放大 18% 并居中偏右) -->
|
|
<img class="bg-artwork" src="{{BG_IMAGE_SRC}}" alt="">
|
|
|
|
<!-- 2. 柔和渐变遮罩 + 编程级蓝图网格 + 准星 -->
|
|
<div class="scrim-overlay"></div>
|
|
<div class="blueprint-grid"></div>
|
|
<div class="blueprint-accents">
|
|
<div class="crosshair ch-tr"></div>
|
|
<div class="crosshair ch-br"></div>
|
|
</div>
|
|
|
|
<!-- 3. 左侧半透明磨砂 Bento 容器 -->
|
|
<div class="bento-card">
|
|
<!-- Top -->
|
|
<div class="top-row">
|
|
<div class="badge-group">
|
|
<div class="cat-badge"><span class="dot"></span>{{CATEGORY}}</div>
|
|
<div class="top-tags">{{TAGS_HTML}}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Center -->
|
|
<div class="center-block">
|
|
<h1 class="title">{{TITLE_HTML}}</h1>
|
|
<p class="desc">{{DESCRIPTION}}</p>
|
|
<div class="evidence-strip">
|
|
<span class="prompt">$</span>
|
|
<span class="text">{{EVIDENCE_SUMMARY}}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Bottom -->
|
|
<div class="bottom-row">
|
|
<div class="author-lockup">
|
|
<img class="author-avatar" src="{{AVATAR_PATH}}" alt="Lee Teong Hoe">
|
|
<div class="author-meta">
|
|
<div class="author-name">Lee Teong Hoe <span class="handle">· Mr Hoelee</span></div>
|
|
<div class="author-role">BUILD · OPERATE · DOCUMENT</div>
|
|
</div>
|
|
</div>
|
|
<div class="domain-pill">blog.hoelee.com</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|