auto-save 2026-04-18 13:05 (+6, ~3, -6)

This commit is contained in:
2026-04-18 13:05:15 +08:00
parent 7a1c957bd1
commit 7035d0a5c5
15 changed files with 154 additions and 13 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 740 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 546 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 829 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 694 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

View File

@@ -449,6 +449,80 @@ section {
letter-spacing: 0.2em;
}
/* ---------- Reader extras (章末延伸图) ---------- */
.reader-extras {
margin: 64px 0 40px;
padding: 32px 0 0;
border-top: 1px solid var(--border);
}
.reader-extras-label {
color: var(--gold);
font-size: 11px;
letter-spacing: 0.4em;
text-transform: uppercase;
margin-bottom: 24px;
}
.reader-extras-grid {
display: grid;
grid-template-columns: 1fr;
gap: 28px;
}
.reader-extra {
margin: 0;
cursor: zoom-in;
transition: transform 0.3s ease;
}
.reader-extra:hover { transform: translateY(-2px); }
.reader-extra img {
width: 100%;
aspect-ratio: 16/10;
object-fit: cover;
background: var(--bg-card);
border: 1px solid var(--border);
}
.reader-extra figcaption {
padding: 16px 0 0;
}
.reader-extra-cap {
font-family: 'Songti SC', serif;
font-size: 19px;
font-weight: 600;
color: var(--fg);
margin-bottom: 4px;
}
.reader-extra-sub {
color: var(--gold);
font-size: 11px;
letter-spacing: 0.3em;
text-transform: uppercase;
}
/* ---------- Gallery extras divider ---------- */
.gallery-extras-heading {
display: flex;
align-items: center;
gap: 20px;
margin: 80px 0 32px;
color: var(--gold);
font-family: 'Songti SC', serif;
font-size: 22px;
font-weight: 700;
}
.gallery-extras-heading::before, .gallery-extras-heading::after {
content: '';
flex: 1;
height: 1px;
background: linear-gradient(90deg, transparent, var(--gold-soft), transparent);
}
.gallery-extras-sub {
text-align: center;
color: var(--fg-dim);
font-size: 12px;
letter-spacing: 0.3em;
margin: -16px 0 40px;
text-transform: uppercase;
}
/* ---------- Footer ---------- */
footer {
padding: 64px 24px 40px;
@@ -675,6 +749,10 @@ footer p { margin: 8px 0; }
<h2 class="section-title">命运的二十二帧。</h2>
<p style="color: var(--fg-soft); max-width: 620px; margin: -24px 0 40px;">从毕业即过时,到代码之王——画面随男主心境推进:冷灰蓝 → 工业寒夜 → 红色告警 → 深黑金巅峰。点击任一幅放大查看。</p>
<div class="gallery-grid" id="gallery-grid"></div>
<div class="gallery-extras-heading">扩集画面 · EXTRA</div>
<div class="gallery-extras-sub">扩写之后新生的关键时刻 · 6 幅</div>
<div class="gallery-grid" id="gallery-extras"></div>
</div>
</section>
@@ -696,22 +774,38 @@ const CHAPTERS = [
{ n: 3, title: '她说你这样没有未来', img: 'ch03_you_have_no_future.jpg', volume: '第一卷 · 被时代埋掉的人', hint: '贫穷与理想,裂痕第一道' },
{ n: 4, title: '全世界都在笑他', img: 'ch04_the_world_laughed_at_him.jpg', volume: '第一卷 · 被时代埋掉的人', hint: '韩锐风光无限,他在出租屋里修服务器' },
{ n: 5, title: '被裁员的人没有资格谈梦想', img: 'ch05_laid_off_no_dreams.jpg', volume: '第一卷 · 被时代埋掉的人', hint: '第一份工作失去,跌入谷底' },
{ n: 6, title: '旧电脑与冷泡面', img: 'ch06_old_computer_cold_noodles.jpg', volume: '第二卷 · 寒冬里独自敲键盘', hint: '低端外包,熬夜,凄惨地活着' },
{ n: 6, title: '旧电脑与冷泡面', img: 'ch06_old_computer_cold_noodles.jpg', volume: '第二卷 · 寒冬里独自敲键盘', hint: '低端外包,熬夜,凄惨地活着',
extras: [
{ file: 'extra/ch06_panic_night.jpg', cap: '第三天夜里 · 被自己的恐惧按在地上', sub: 'PTSD 原点' }
] },
{ n: 7, title: '只有她递来一把伞', img: 'ch07_she_brought_an_umbrella.jpg', volume: '第二卷 · 寒冬里独自敲键盘', hint: '苏青禾登场,一点温柔的光' },
{ n: 8, title: '爱也会输给房租', img: 'ch08_love_lost_to_rent.jpg', volume: '第二卷 · 寒冬里独自敲键盘', hint: '林晚乔正式离开,情感谷底' },
{ n: 9, title: '没人相信的底层能力', img: 'ch09_no_one_believed_him.jpg', volume: '第二卷 · 寒冬里独自敲键盘', hint: '想推销离线开发,被当笑话' },
{ n: 10, title: '十年一梦,满身风雪', img: 'ch10_ten_years_in_snow.jpg', volume: '第二卷 · 寒冬里独自敲键盘', hint: '在行业边缘漂泊多年' },
{ n: 10, title: '十年一梦,满身风雪', img: 'ch10_ten_years_in_snow.jpg', volume: '第二卷 · 寒冬里独自敲键盘', hint: '在行业边缘漂泊多年',
extras: [
{ file: 'extra/ch10_cafe_read_alone.jpg', cap: '他给自己读完一场没有听众的演讲', sub: '40 岁 · 平静庄严' }
] },
{ n: 11, title: '聪明人都不会手写代码了', img: 'ch11_no_one_writes_code_anymore.jpg', volume: '第三卷 · 黑箱时代的裂缝', hint: '传统工程师彻底绝迹' },
{ n: 12, title: '第一次异常', img: 'ch12_first_anomaly.jpg', volume: '第三卷 · 黑箱时代的裂缝', hint: '核心系统零星故障,被当波动' },
{ n: 13, title: '无人能读懂的补丁', img: 'ch13_unreadable_patch.jpg', volume: '第三卷 · 黑箱时代的裂缝', hint: '大平台自修复越修越乱' },
{ n: 14, title: '世界停电的那一天', img: 'ch14_the_day_the_world_went_dark.jpg',volume: '第三卷 · 黑箱时代的裂缝', hint: '金融交通医疗能源连锁崩塌' },
{ n: 14, title: '世界停电的那一天', img: 'ch14_the_day_the_world_went_dark.jpg',volume: '第三卷 · 黑箱时代的裂缝', hint: '金融交通医疗能源连锁崩塌',
extras: [
{ file: 'extra/ch14_linwanqiao_window.jpg', cap: '她认出了那只黑色帆布包', sub: '旧情视角 · 一面落地窗' }
] },
{ n: 15, title: '求他出山的人排到了楼下', img: 'ch15_people_queued_to_beg_him.jpg', volume: '第三卷 · 黑箱时代的裂缝', hint: '昔日嘲笑他的人开始低头' },
{ n: 16, title: '一人重启一座城', img: 'ch16_one_man_restart_a_city.jpg', volume: '第四卷 · 旧时代火种', hint: '凭古法工程修复核心调度' },
{ n: 16, title: '一人重启一座城', img: 'ch16_one_man_restart_a_city.jpg', volume: '第四卷 · 旧时代火种', hint: '凭古法工程修复核心调度',
extras: [
{ file: 'extra/ch16_victory_night_alone.jpg', cap: '庆功夜 · 锁门独饮', sub: '成功的空旷 · 那接下来呢' }
] },
{ n: 17, title: '财团、公权与资本都在抢他', img: 'ch17_everyone_is_fighting_for_him.jpg',volume: '第四卷 · 旧时代火种', hint: '沈知意、国家机构、巨头同时伸手' },
{ n: 18, title: '她们都在等他一句话', img: 'ch18_they_wait_for_his_answer.jpg', volume: '第四卷 · 旧时代火种', hint: '情感线全面升温' },
{ n: 19, title: '代码之王', img: 'ch19_king_of_code.jpg', volume: '第四卷 · 旧时代火种', hint: '组建离线工程联盟,重塑秩序' },
{ n: 20, title: '坐拥繁花,归来仍是少年', img: 'ch20_among_flowers_still_young.jpg', volume: '第四卷 · 旧时代火种', hint: '站上巅峰,事业情感双圆满' },
{ n: 0, title: '终章 · 写代码的人,重新定义世界', img: 'epilogue_redefine_the_world.jpg', volume: '终章', hint: 'AI 重新成为工具而非拐杖' },
{ n: 0, title: '终章 · 写代码的人,重新定义世界', img: 'epilogue_redefine_the_world.jpg', volume: '终章', hint: 'AI 重新成为工具而非拐杖',
extras: [
{ file: 'extra/ring_classroom_10yrs_later.jpg', cap: '十年后 · 新一代走进教室', sub: '环状收尾 · 黑板三字:写 代 码' },
{ file: 'extra/s2_blank_second_page.jpg', cap: '我 怕 的——', sub: '第二部 · 序章 · 留白' }
] },
];
function renderChapterList() {
@@ -751,6 +845,27 @@ function renderGallery() {
</div>
</div>`;
}).join('');
// Extras gallery — new scenes born from expansion
const extrasWrap = document.getElementById('gallery-extras');
if (extrasWrap) {
const extraItems = [];
CHAPTERS.forEach(ch => {
if (!ch.extras) return;
const num = ch.n === 0 ? '终章' : `${ch.n}`;
ch.extras.forEach(ex => {
extraItems.push({ ...ex, num, chTitle: ch.title });
});
});
extrasWrap.innerHTML = extraItems.map(ex => `
<div class="gallery-item" onclick="openLightbox('./images/${ex.file}')">
<img src="./images/${ex.file}" alt="${ex.cap}" loading="lazy">
<div class="gallery-meta">
<div class="gallery-cap">${ex.cap}</div>
<div class="gallery-sub">${ex.num} · ${ex.sub}</div>
</div>
</div>`).join('');
}
}
function jumpToChapter(idx) {
@@ -804,12 +919,27 @@ function renderNovel(md) {
}
return '<p>' + escapeHtml(line) + '</p>';
}).join('\n');
const extrasHtml = (ch && ch.extras) ? `
<div class="reader-extras">
<div class="reader-extras-label">章末延伸画面 · Extra</div>
<div class="reader-extras-grid">
${ch.extras.map(ex => `
<figure class="reader-extra" onclick="openLightbox('./images/${ex.file}')">
<img src="./images/${ex.file}" alt="${ex.cap}" loading="lazy">
<figcaption>
<div class="reader-extra-cap">${ex.cap}</div>
<div class="reader-extra-sub">${ex.sub}</div>
</figcaption>
</figure>`).join('')}
</div>
</div>` : '';
out.push(`
<article class="reader-chapter" id="chapter-${idx}">
<div class="reader-chapter-num">${isEpilogue ? 'EPILOGUE' : 'CHAPTER ' + num}</div>
<h2 class="reader-chapter-title">${title}</h2>
${imgPath ? `<img class="reader-chapter-img" src="${imgPath}" alt="${title}" loading="lazy" onclick="openLightbox('${imgPath}')" style="cursor: zoom-in;">` : ''}
<div class="reader-chapter-body">${paragraphs}</div>
${extrasHtml}
${idx < sections.length - 1 ? '<div class="chapter-divider">· · ·</div>' : ''}
</article>
`);