PageSourceSearch

https://github.nb-channel.top/Beta/videos-Beta.html

html nb-channel.top collected 2026-10-06 13:15:41 UTC 82,573 bytes, 1,655 lines download raw bytes

1<!DOCTYPE html>
2<html lang="zh-CN">
3<head>
4<meta charset="UTF-8">
5<script>
6/* ===== 跨子域名登录态同步(github. / cloudflare. / pythonanywhere. 之间互通)=====
7   localStorage 是按 origin 隔离的,两个子域名各存各的,所以要借 Cookie 中转。
8   Cookie 设 Domain=.nb-channel.top,所有子域名都能读到。
9
10   这里不改页面原本的任何代码 —— 而是劫持 localStorage 的读写:
11     · 页面登录时 setItem('nb_session', ...)  → 顺手写一份到 Cookie
12     · 页面登出时 removeItem('nb_session')    → 顺手把 Cookie 清掉
13     · 页面加载时 Cookie 有、本地没有          → 自动注入进 localStorage
14   所以那 57 处登录/登出代码一行都不用动。
15
16   ⚠️ 这意味着 *.nb-channel.top 下任何一个子域名都能读到这个令牌,
17      包括 product-storage 那个 Workers。将来新增子域名前先想清楚这件事。 */
18(function () {
19    try {
20        var KEY_S = 'nb_session', KEY_U = 'nb_user';
21        var DOMAIN = '.nb-channel.top';
22        var MAXAGE = 30 * 86400;
23
24        // 只在 .nb-channel.top 域下才启用(本地开文件、或别的域名访问时保持原样)
25        if (location.hostname.indexOf('nb-channel.top') < 0) return;
26
27        function readCookie(n) {
28            var m = document.cookie.match(new RegExp('(?:^|;\\s*)' + n + '=([^;]*)'));
29            return m ? decodeURIComponent(m[1]) : null;
30        }
31        function writeCookie(n, v) {
32            document.cookie = n + '=' + encodeURIComponent(v) + ';path=/;domain=' + DOMAIN +
33                              ';max-age=' + MAXAGE + ';SameSite=Lax' +
34                              (location.protocol === 'https:' ? ';Secure' : '');
35        }
36        function dropCookie(n) {
37            document.cookie = n + '=;path=/;domain=' + DOMAIN + ';max-age=0;SameSite=Lax' +
38                              (location.protocol === 'https:' ? ';Secure' : '');
39        }
40
41        // ---- ① 页面加载时双向对齐 ----
42        [KEY_S, KEY_U].forEach(function (k) {
43            var c = readCookie(k), l = null;
44            try { l = localStorage.getItem(k); } catch (e) {}
45            if (l) {
46                if (l !== c) writeCookie(k, l);            // 本地有 → 同步出去
47            } else if (c) {
48                try { localStorage.setItem(k, c); } catch (e) {}   // 本地没有 → 采用 Cookie
49            }
50        });
51
52        // ---- ② 劫持写入:登录时同步到 Cookie ----
53        var _set = localStorage.setItem;
54        localStorage.setItem = function (k, v) {
55            try { if ((k === KEY_S || k === KEY_U) && v) writeCookie(k, v); } catch (e) {}
56            return _set.call(localStorage, k, v);
57        };
58
59        // ---- ③ 劫持删除:登出时同步清 Cookie ----
60        var _rm = localStorage.removeItem;
61        localStorage.removeItem = function (k) {
62            try { if (k === KEY_S || k === KEY_U) dropCookie(k); } catch (e) {}
63            return _rm.call(localStorage, k);
64        };
65
66        // ---- ④ 万一有人用 clear() ----
67        var _cl = localStorage.clear;
68        localStorage.clear = function () {
69            try { dropCookie(KEY_S); dropCookie(KEY_U); } catch (e) {}
70            return _cl.call(localStorage);
71        };
72    } catch (e) {}
73})();
74</script>
74
75<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
76<!-- 不发送 referer:B站图床(hdslb)防盗链,带外部站 referer 会 403 导致封面不显示 -->
77<meta name="referrer" content="no-referrer">
78<meta name="description" content="NB频道(NoBook频道)视频档案——化学物理实验、日常作死、官网与产品记录,全部来自B站「NB搞事局」。">
79<meta property="og:title" content="视频档案 · NB频道官网">
80<meta property="og:description" content="化学物理实验、日常作死、官网与产品记录——全部视频一站直达。">
81<meta name="theme-color" content="#0f172a">
82<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0' stop-color='%233b82f6'/%3E%3Cstop offset='1' stop-color='%238b5cf6'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='64' height='64' rx='14' fill='url(%23g)'/%3E%3Ctext x='32' y='43' font-family='Arial,sans-serif' font-size='26' font-weight='800' fill='%23fff' text-anchor='middle'%3ENB%3C/text%3E%3C/svg%3E">
83<title>视频档案 - NB频道官网</title>
84<script>
85    // 夜间模式:第一帧前生效(无显式选择时跟随系统)
86    (function () {
87        try {
88            var t = localStorage.getItem('theme');
89            if (t === 'dark' || (!t && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
90                document.documentElement.classList.add('dark');
91            }
92        } catch (e) {}
93    })();
94</script>
94
95<style>
96* { margin: 0; padding: 0; box-sizing: border-box; }
97:root {
98    --bg: #f7f8fa;
99    --ink: #1a1d23;
100    --ink-soft: #5a6270;
101    --ink-faint: #8b93a3;
102    --line: #e8eaee;
103    --brand: #3b82f6;
104    --brand-deep: #2563eb;
105    --card: #ffffff;
106    --radius-lg: 20px;
107    --radius-md: 14px;
108    --shadow-1: 0 1px 2px rgba(16,24,40,.04), 0 4px 12px rgba(16,24,40,.06);
109    --shadow-2: 0 2px 4px rgba(16,24,40,.05), 0 24px 48px -20px rgba(16,24,40,.18);
110}
111html.dark { color-scheme: dark; }
112html.dark {
113    --bg: #0a101f;
114    --ink: #e5eaf3;
115    --ink-soft: #9aa7bd;
116    --ink-faint: #64748b;
117    --line: rgba(148,163,184,.16);
118    --card: #101a2e;
119    --shadow-1: 0 1px 2px rgba(0,0,0,.3), 0 6px 18px rgba(0,0,0,.28);
120    --shadow-2: 0 2px 6px rgba(0,0,0,.35), 0 28px 60px -24px rgba(0,0,0,.6);
121}
122html.dark .nav { background: rgba(10,16,31,.72); border-bottom-color: rgba(148,163,184,.12); }
123html.dark .nav.scrolled { background: rgba(10,16,31,.9); }
124html.dark .logo-img { filter: brightness(1.4) saturate(1.15); }
125html.dark .vcat { background: rgba(255,255,255,.04); border-color: rgba(148,163,184,.22); color: var(--ink-soft); }
126html.dark .vcat.on { background: var(--brand); border-color: var(--brand); color: #fff; }
127html.dark .vcard .thumb { background: #0d1526; }
128html.dark .vsearch input { color: var(--ink); }
129html.dark .drawer { background: #0f1a30; }
130html.dark .drawer .d-close { background: rgba(255,255,255,.06); color: var(--ink); }
131html.dark .drawer a.d-item { color: var(--ink-soft); }
132html.dark .drawer a.d-item:hover, html.dark .drawer a.d-item.active { background: rgba(59,130,246,.14); color: #fff; }
133html.dark .drawer .d-brand { color: var(--ink); }
134html.dark .backtop { background: rgba(15,23,42,.85); color: #cbd5e1; border-color: rgba(148,163,184,.25); }
135html.dark .backtop:hover { background: var(--brand); color: #fff; }
136html.dark .footer-bottom { border-color: rgba(255,255,255,.06); }
137
138body {
139    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
140    background: var(--bg);
141    color: var(--ink);
142    line-height: 1.6;
143    -webkit-font-smoothing: antialiased;
144}
145a { text-decoration: none; color: inherit; }
146::selection { background: rgba(59,130,246,.22); }
147
148/* ============ 导航 ============ */
149.nav {
150    position: sticky; top: 0; z-index: 100;
151    display: flex; align-items: center; justify-content: space-between;
152    padding: 0 48px; height: 64px;
153    background: rgba(255,255,255,.72);
154    -webkit-backdrop-filter: blur(20px) saturate(1.5);
155    backdrop-filter: blur(20px) saturate(1.5);
156    border-bottom: 1px solid var(--line);
157}
158.nav-logo {
159    display: flex; align-items: center; gap: 10px;
160    font-size: 1.15rem; font-weight: 800; letter-spacing: .3px;
161    margin-left: 12px;
162}
163.logo-img { display: block; height: 32px; width: auto; }
164.logo-text { color: var(--ink); }
165.nav-menu { display: flex; gap: 2px; }
166.nav-menu a {
167    position: relative; padding: 10px 14px;
168    font-size: .92rem; font-weight: 500; letter-spacing: .4px;
169    color: var(--ink-soft); white-space: nowrap;
170    transition: color .3s ease;
171}
172.nav-menu a:hover { color: var(--ink); }
173.nav-menu a.active { color: var(--brand); font-weight: 600; }
174.nav-menu a::after {
175    content: ''; position: absolute; left: 14px; right: 14px; bottom: 4px;
176    height: 1px; background: var(--brand);
177    transform: scaleX(0); transform-origin: left;
178    transition: transform .35s cubic-bezier(.16,1,.3,1);
179}
180.nav-menu a:hover::after { transform: scaleX(1); }
181.nav-menu a.active::after { transform: scaleX(1); }
182.nav-menu a.nav-api { color: var(--brand); font-weight: 600; font-size: .86rem; }
183.nav-menu a.nav-api::after { background: var(--brand-deep); }
184.nav-right-group { display: flex; align-items: center; gap: 10px; }
185.theme-btn {
186    width: 38px; height: 38px; border-radius: 50%; border: 1px solid var(--line);
187    background: var(--bg); cursor: pointer; font-size: .95rem;
188    display: flex; align-items: center; justify-content: center;
189    transition: all .25s ease;
190}
191.theme-btn:hover { border-color: rgba(59,130,246,.4); transform: translateY(-1px); }
192        /* ============ 导航登录区 + 北京时间时钟(与首页一致) ============ */
193        .nav-auth-group { display: flex; gap: 8px; align-items: center; }
194        .nav-clock {
195            display: flex; flex-direction: column; align-items: flex-end;
196            margin-right: 8px; flex-shrink: 0; user-select: none; line-height: 1.35;
197        }
198        .nav-clock .nc-time {
199            font-size: 15.5px; font-weight: 800; letter-spacing: 1.5px;
200            color: var(--ink); font-variant-numeric: tabular-nums;
201        }
202        .nav-clock .nc-row { display: flex; align-items: baseline; gap: 6px; font-style: normal; }
203        .nav-clock .nc-date {
204            font-size: 10.5px; font-weight: 600; letter-spacing: .4px;
205            color: var(--ink-soft); font-variant-numeric: tabular-nums;
206        }
207        .nav-clock .nc-label {
208            font-size: 8.5px; font-weight: 600; letter-spacing: 2px;
209            color: var(--ink-faint);
210        }
211        .nav-auth {
212            padding: 8px 18px; border-radius: 999px;
213            background: rgba(255,255,255,.6); color: var(--ink);
214            border: 1px solid var(--line);
215            font-size: .88rem; font-weight: 600; cursor: pointer;
216            transition: all .25s ease; white-space: nowrap;
217        }
218        .nav-auth:hover { background: #fff; border-color: rgba(59,130,246,.4); }
219        .nav-auth.primary {
220            background: linear-gradient(135deg, var(--brand), #6366f1);
221            border-color: transparent; color: #fff;
222            box-shadow: 0 8px 20px -8px rgba(59,130,246,.5);
223        }
224        .nav-auth.primary:hover { background: linear-gradient(135deg, #2563eb, #4f46e5); color: #fff; }
225        html.dark .nav-auth { background: rgba(255,255,255,.05); color: var(--ink); border-color: rgba(148,163,184,.25); }
226        html.dark .nav-auth:hover { background: rgba(255,255,255,.1); border-color: rgba(59,130,246,.5); }
227        .drawer .d-auth { margin-top: 14px; padding-top: 16px; border-top: 1px solid var(--line); display: flex; gap: 10px; }
228        .drawer .d-auth a { flex: 1; text-align: center; padding: 11px; border-radius: 999px; font-size: .9rem; font-weight: 600; }
229        .drawer .d-auth .ga { background: var(--bg); color: var(--ink); border: 1px solid var(--line); }
230        .drawer .d-auth .gab { background: linear-gradient(135deg, var(--brand), #6366f1); color: #fff; }
231
232.nav-burger {
233    display: none; width: 38px; height: 38px; border-radius: 10px;
234    border: 1px solid var(--line); background: var(--bg);
235    font-size: .95rem; cursor: pointer; color: var(--ink);
236    align-items: center; justify-content: center;
237}
238@media (max-width: 900px) {
239    .nav-menu { display: none; }
240    .nav-burger { display: flex; } .nav-clock, .nav-auth-group { display: none; }
241}
242
243/* ============ Hero(视频档案) ============ */
244.vhero {
245    position: relative; color: #fff; overflow: hidden;
246    padding: 110px 48px 150px;
247    background:
248        radial-gradient(760px 460px at 12% 4%, rgba(59,130,246,.16), transparent 62%),
249        radial-gradient(640px 420px at 96% 60%, rgba(139,92,246,.12), transparent 60%),
250        linear-gradient(168deg, #0b1220 0%, #101c33 58%, #1c1745 100%);
251}
252.vhero::before {
253    content: ''; position: absolute; inset: 0; pointer-events: none; opacity: .5;
254    background-image: radial-gradient(rgba(255,255,255,.045) 1px, transparent 1px);
255    background-size: 34px 34px;
256    mask-image: linear-gradient(to bottom, rgba(0,0,0,.5), transparent 72%);
257    -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,.5), transparent 72%);
258}
259.vhero-inner {
260    position: relative; z-index: 2; max-width: 1180px; margin: 0 auto;
261    display: grid; grid-template-columns: 1.05fr .95fr; gap: 70px; align-items: center;
262}
263.hero-eyebrow {
264    display: block; font-size: 11px; font-weight: 400;
265    letter-spacing: 8px; color: rgba(255,255,255,.42);
266    margin-bottom: 40px;
267}
268.vhero h1 {
269    font-size: clamp(2.7rem, 5.2vw, 4.6rem);
270    font-weight: 800; letter-spacing: 10px; color: #fff; line-height: 1.12;
271}
272.vhero h1 .light { font-weight: 200; letter-spacing: 4px; color: #9cc0ff; }
273.vhero-sub {
274    margin: 34px 0 0; max-width: 460px;
275    font-size: .98rem; font-weight: 300; line-height: 2.15;
276    letter-spacing: .6px; color: rgba(255,255,255,.6);
277}
278.vhero-actions { margin-top: 48px; display: flex; gap: 44px; align-items: center; flex-wrap: wrap; }
279.hero-link {
280    font-size: .9rem; letter-spacing: 3px; font-weight: 600; color: #fff;
281    padding: 12px 2px; border-bottom: 1px solid rgba(255,255,255,.32);
282    transition: border-color .35s ease, color .35s ease;
283}
284.hero-link:hover { border-color: #7cb4ff; color: #7cb4ff; }
285/* 右侧档案卡 */
286.vhcard {
287    background: rgba(255,255,255,.045);
288    border: 1px solid rgba(255,255,255,.1);
289    border-radius: 24px; padding: 32px 30px 26px;
290    -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
291}
292.vhcard .vh-eyebrow {
293    font-size: 10px; letter-spacing: 5px; font-weight: 700;
294    color: rgba(255,255,255,.38); text-transform: uppercase; margin-bottom: 22px;
295}
296.vh-cardrows { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 26px; }
297.vh-row {
298    display: flex; align-items: baseline; justify-content: space-between;
299    padding-bottom: 9px; border-bottom: 1px dashed rgba(255,255,255,.1);
300}
301.vh-row b { font-size: 1.02rem; font-weight: 700; color: #fff; letter-spacing: .5px; }
302.vh-row span { font-size: .74rem; color: rgba(255,255,255,.5); letter-spacing: 1.5px; }
303.vh-row .cnt { color: #9cc0ff; font-size: 1.18rem; font-weight: 300; }
304.vh-foot {
305    display: flex; align-items: center; justify-content: space-between;
306    margin-top: 22px; padding-top: 18px; border-top: 1px solid rgba(255,255,255,.08);
307}
308.vh-foot .u { font-size: .78rem; color: rgba(255,255,255,.5); letter-spacing: 1px; }
309.vh-foot .d { font-size: .88rem; color: #fff; font-weight: 600; letter-spacing: .5px; }
310/* Hero → 正文柔和过渡 */
311.vhero-fade {
312    position: absolute; left: 0; right: 0; bottom: 0; height: 130px; z-index: 1;
313    background: linear-gradient(to bottom, transparent, var(--bg));
314    pointer-events: none;
315}
316
317/* ============ 正文容器 ============ */
318.vwrap { max-width: 1180px; margin: 0 auto; padding: 60px 48px 110px; }
319
320/* 档案工具条:分类 + 搜索 + 排序 */
321.vtoolbar {
322    display: flex; align-items: center; justify-content: space-between;
323    gap: 16px; flex-wrap: wrap; margin-bottom: 22px;
324}
325.vcats { display: flex; gap: 6px; flex-wrap: wrap; }
326.vcat {
327    border: 1px solid var(--line); background: var(--card); color: var(--ink-soft);
328    font-size: .86rem; font-weight: 600; letter-spacing: .5px;
329    padding: 7px 17px; border-radius: 999px; cursor: pointer;
330    transition: all .3s ease;
331}
332.vcat:hover { border-color: var(--brand); color: var(--brand); }
333.vcat.on { background: var(--brand); border-color: var(--brand); color: #fff; box-shadow: 0 8px 18px -8px rgba(59,130,246,.55); }
334.vright { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
335.vsearch {
336    display: flex; align-items: center; gap: 8px;
337    border-bottom: 1px solid var(--line); padding: 5px 2px; min-width: 220px;
338    transition: border-color .3s ease;
339}
340.vsearch:focus-within { border-color: var(--brand); }
341.vsearch input { border: none; outline: none; background: transparent; font: inherit; font-size: .9rem; color: var(--ink); width: 100%; }
342.vsearch input::placeholder { color: var(--ink-faint); }
343.vsort { display: flex; gap: 2px; }
344.vsort button {
345    border: none; background: none; font: inherit; font-size: .84rem;
346    color: var(--ink-faint); cursor: pointer; padding: 6px 13px; border-radius: 999px;
347    letter-spacing: 1.5px; transition: all .25s ease;
348}
349.vsort button:hover { color: var(--ink); }
350.vsort button.on { background: rgba(59,130,246,.12); color: var(--brand); font-weight: 700; }
351.vcount {
352    font-size: .78rem; color: var(--ink-faint); letter-spacing: 2px;
353    margin-bottom: 18px; text-transform: uppercase;
354}
355.vcount b { color: var(--brand); font-weight: 700; }
356
357/* 视频网格 */
358.video-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(255px, 1fr)); gap: 20px; }
359.vcard {
360    background: var(--card); border-radius: var(--radius-lg); overflow: hidden;
361    box-shadow: var(--shadow-1); cursor: pointer; user-select: none;
362    transition: transform .35s cubic-bezier(.16,1,.3,1), box-shadow .35s ease;
363}
364.vcard:hover { transform: translateY(-5px); box-shadow: var(--shadow-2); }
365.vcard .thumb {
366    position: relative; aspect-ratio: 16 / 10;
367    background: #eef1f6; overflow: hidden;
368}
369.vcard .thumb img {
370    position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
371    transition: transform .9s cubic-bezier(.16,1,.3,1);
372}
373.vcard:hover .thumb img { transform: scale(1.06); }
374.vcard .thumb .dur {
375    position: absolute; right: 8px; bottom: 8px; z-index: 2;
376    background: rgba(0,0,0,.72); color: #fff;
377    font-size: .72rem; padding: 2px 8px; border-radius: 999px;
378    font-variant-numeric: tabular-nums;
379}
380.vcard .thumb .play {
381    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%) scale(.82);
382    width: 46px; height: 46px; border-radius: 50%;
383    background: rgba(255,255,255,.92); color: var(--brand);
384    display: flex; align-items: center; justify-content: center;
385    font-size: .92rem; box-shadow: 0 10px 26px -8px rgba(0,0,0,.45);
386    opacity: 0; transition: all .32s cubic-bezier(.16,1,.3,1); z-index: 2;
387}
388.vcard:hover .thumb .play { opacity: 1; transform: translate(-50%, -50%) scale(1); }
389.vcard:active .thumb img { transform: scale(1.03); }
390.vcard .body { padding: 15px 16px 17px; }
391.vcard h4 {
392    font-size: .95rem; font-weight: 700; line-height: 1.45; color: var(--ink);
393    margin-bottom: 9px;
394    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
395    overflow: hidden; min-height: 2.76em;
396}
397.vcard .meta {
398    display: flex; align-items: center; gap: 12px;
399    font-size: .78rem; color: var(--ink-faint); font-variant-numeric: tabular-nums;
400}
401.vcard .meta .cat {
402    margin-left: auto; font-weight: 700; letter-spacing: 1px; color: var(--ink-soft);
403    font-size: .72rem;
404}
405.empty {
406    text-align: center; padding: 90px 20px; color: var(--ink-faint);
407    font-size: .95rem; letter-spacing: 2px;
408}
409.empty b { color: var(--ink-soft); font-weight: 700; }
410
411/* 卡片入场 */
412.reveal { opacity: 0; transform: translateY(16px); transition: opacity .7s cubic-bezier(.16,1,.3,1), transform .7s cubic-bezier(.16,1,.3,1); }
413.reveal.in { opacity: 1; transform: none; }
414@media (prefers-reduced-motion: reduce) {
415    .reveal { opacity: 1; transform: none; transition: none; }
416}
417
418/* ============ 播放弹窗 ============ */
419.vmodal { position: fixed; inset: 0; z-index: 9000; display: none; align-items: center; justify-content: center; padding: 24px; }
420.vmodal.open { display: flex; }
421.vmask { position: absolute; inset: 0; background: rgba(7,10,20,.82); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); }
422.vbox {
423    position: relative; width: min(920px, 100%); background: #0b1220;
424    border-radius: 20px; border: 1px solid rgba(255,255,255,.1); overflow: hidden;
425    box-shadow: 0 70px 140px -40px rgba(0,0,0,.85);
426    animation: vUp .38s cubic-bezier(.16,1,.3,1);
427}
428@keyframes vUp { from { opacity: 0; transform: translateY(26px) scale(.97); } to { opacity: 1; transform: none; } }
429.vhead { display: flex; align-items: center; gap: 12px; padding: 13px 18px; border-bottom: 1px solid rgba(255,255,255,.08); }
430.vhead .vt2 { color: #fff; font-size: .95rem; font-weight: 700; flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
431.vclose {
432    width: 32px; height: 32px; border-radius: 50%; border: none; cursor: pointer;
433    background: rgba(255,255,255,.08); color: rgba(255,255,255,.85); font-size: .85rem;
434    display: flex; align-items: center; justify-content: center; transition: background .25s ease;
435}
436.vclose:hover { background: rgba(255,255,255,.18); }
437.vframe { position: relative; padding-top: 56.25%; background: #000; }
438.vframe iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
439.vact { display: flex; align-items: center; gap: 10px; padding: 13px 18px; }
440.vact .hint { font-size: .74rem; color: rgba(255,255,255,.45); letter-spacing: 1px; }
441.vopen {
442    margin-left: auto; display: inline-flex; align-items: center; gap: 6px;
443    padding: 8px 20px; border-radius: 999px; font-size: .84rem; font-weight: 600; color: #fff;
444    background: rgba(0,161,214,.9); transition: background .25s ease;
445}
446.vopen:hover { background: #00a1d6; }
447body.locked { overflow: hidden; }
448
449/* ============ 页脚 ============ */
450.footer { background: linear-gradient(180deg, #0f172a 0%, #0a0f1e 100%); color: #94a3b8; padding: 64px 48px 30px; }
451.footer-grid {
452    max-width: 1180px; margin: 0 auto;
453    display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 44px;
454}
455.footer .brand { font-size: 1.1rem; font-weight: 800; color: #fff; margin-bottom: 14px; display: flex; align-items: center; gap: 10px; letter-spacing: .5px; }
456.footer .desc { font-size: .85rem; font-weight: 300; line-height: 2; margin-bottom: 20px; color: #7c8ba5; }
457.footer h5 { color: #e2e8f0; font-size: .88rem; font-weight: 700; margin-bottom: 18px; letter-spacing: 2px; }
458.footer a { display: block; color: #8fa0b8; font-size: .86rem; margin-bottom: 12px; transition: color .3s ease; }
459.footer a:hover { color: #fff; }
460.footer-bottom {
461    max-width: 1180px; margin: 44px auto 0; padding-top: 22px;
462    border-top: 1px solid rgba(255,255,255,.07);
463    font-size: .76rem; letter-spacing: 1px;
463 color: #5b6a85; text-align: center;
464}
465
466/* ============ 移动端抽屉 ============ */
467.drawer-mask { display: none; position: fixed; inset: 0; z-index: 9000; background: rgba(10,15,28,.5); }
468.drawer {
469    position: fixed; top: 0; right: 0; bottom: 0; z-index: 9001;
470    width: 300px; max-width: 84vw; background: #fff;
471    box-shadow: -20px 0 60px -30px rgba(0,0,0,.4);
472    transform: translateX(105%); transition: transform .35s cubic-bezier(.16,1,.3,1);
473    padding: 22px 20px; overflow-y: auto;
474}
475.drawer.open { transform: none; }
476.drawer .d-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; }
477.drawer .d-brand { font-weight: 800; font-size: 1.05rem; display: flex; align-items: center; gap: 8px; color: var(--ink); }
478.drawer .d-close { width: 36px; height: 36px; border-radius: 10px; border: none; background: var(--bg); font-size: .95rem; cursor: pointer; color: var(--ink); }
479.drawer a.d-item { display: block; padding: 12px 16px; border-radius: 12px; color: var(--ink-soft); font-size: .98rem; font-weight: 600; }
480.drawer a.d-item:hover, .drawer a.d-item.active { background: rgba(59,130,246,.1); color: var(--brand); }
481
482/* ============ 回到顶部 ============ */
483.backtop {
484    position: fixed; right: 26px; bottom: 26px; z-index: 5000;
485    width: 46px; height: 46px; border-radius: 50%;
486    background: rgba(255,255,255,.92); color: var(--brand);
487    border: 1px solid var(--line); cursor: pointer; font-size: 1.05rem;
488    opacity: 0; transform: translateY(12px); transition: all .3s ease;
489    box-shadow: var(--shadow-1);
490}
491.backtop.show { opacity: 1; transform: none; }
492.backtop:hover { background: var(--brand); color: #fff; }
493
494/* ============ 响应式 ============ */
495@media (max-width: 900px) {
496    .vhero { padding: 84px 24px 120px; }
497    .vwrap { padding: 44px 24px 90px; }
498    .footer { padding: 48px 24px 26px; }
499}
500@media (max-width: 760px) {
501    .nav { padding: 0 20px; }
502    .vhero { padding: 72px 20px 110px; }
503    .vhero-inner { grid-template-columns: 1fr; gap: 44px; }
504    .vhero h1 { font-size: 2.4rem; letter-spacing: 6px; }
505    .vhcard { display: none; }
506    .vhero-actions { margin-top: 38px; }
507    .vwrap { padding: 36px 20px 80px; }
508    .video-grid { grid-template-columns: repeat(2, 1fr); gap: 12px; }
509    .vcard .body { padding: 11px 12px 13px; }
510    .vcard h4 { font-size: .82rem; min-height: 0; -webkit-line-clamp: 2; margin-bottom: 6px; }
511    .vcard .meta { gap: 6px; font-size: .68rem; flex-wrap: wrap; }
512    .vcard .meta .cat { margin-left: 0; }
513    .vcard .thumb .play { width: 34px; height: 34px; font-size: .72rem; opacity: .92; transform: translate(-50%, -50%) scale(1); }
514    .vcount { margin-bottom: 14px; }
515    .vsearch { min-width: 100%; order: 3; }
516    .vtoolbar { margin-bottom: 16px; }
517    .vmodal { padding: 10px; }
518    .vbox { border-radius: 14px; }
519    .vact .hint { display: none; }
520    .vhero::before { background-size: 26px 26px; }
521    .footer-grid { grid-template-columns: 1fr; gap: 26px; }
522    .backtop { right: 18px; bottom: 18px; width: 42px; height: 42px; }
523}
524        .ui-fx-glow {
525            position: fixed; left: -999px; top: -999px; width: 240px; height: 240px;
526            border-radius: 50%; pointer-events: none; z-index: 9997;
527            transform: translate(-50%, -50%);
528            background: radial-gradient(circle, rgba(59,130,246,.18), rgba(139,92,246,.10) 45%, transparent 65%);
529            opacity: 0;
530        }
531
532
533        /* ===== Hero 入场动画(全站统一,与首页一致的错峰淡入) ===== */
534        @keyframes heroFadeUp { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
535        .vhero .hero-eyebrow, .vhero h1, .vhero .vhero-sub, .vhero .vhero-actions,
536        .vhero .pd-stats, .vhero .cl-stats, .vhero .acard, .vhero .vhcard, .vhero .com-rules {
537            animation: heroFadeUp .95s cubic-bezier(.16,1,.3,1) both;
538        }
539        .vhero .hero-eyebrow { animation-delay: .08s; }
540        .vhero h1 { animation-delay: .2s; }
541        .vhero .vhero-sub { animation-delay: .34s; }
542        .vhero .vhero-actions { animation-delay: .48s; }
543        .vhero .pd-stats, .vhero .cl-stats, .vhero .acard, .vhero .vhcard, .vhero .com-rules { animation-delay: .32s; }
544        @media (prefers-reduced-motion: reduce) {
545            .vhero .hero-eyebrow, .vhero h1, .vhero .vhero-sub, .vhero .vhero-actions,
546            .vhero .pd-stats, .vhero .cl-stats, .vhero .acard, .vhero .vhcard, .vhero .com-rules { animation: none; }
547        }
548
549        /* ===== 全站公告条(与首页一致) ===== */
550        .beta-announce {
551            display: flex; align-items: center; gap: 14px;
552            max-width: 1080px; margin: 34px auto 0; padding: 15px 24px;
553            background: var(--card);
554            border-radius: var(--radius-md);
555            box-shadow: var(--shadow-1);
556            position: relative;
557        }
558        .beta-announce::before {
559            content: ''; position: absolute; left: 0; top: 18px; bottom: 18px; width: 3px;
560            border-radius: 3px; background: var(--brand);
561        }
562        .beta-announce .ba-title {
563            flex-shrink: 0; font-size: .82rem; font-weight: 700; color: var(--brand);
564            background: rgba(59,130,246,.08); border-radius: 999px; padding: 4px 12px;
565        }
566        .beta-announce .ba-track-wrap { flex: 1; overflow: hidden; min-width: 0; }
567        .beta-announce .ba-track { display: inline-block; white-space: nowrap; will-change: transform; }
568        .beta-announce .ba-item {
569            display: inline-block; white-space: nowrap; padding-right: 80px;
570            font-size: .92rem; color: var(--ink-soft);
571        }
572        .beta-announce a { color: var(--brand); text-decoration: underline; }
573        .beta-announce a:hover { color: var(--brand-deep); }
574        html.dark .beta-announce { background: var(--card); }
575        html.dark .beta-announce .ba-item { color: var(--ink-soft); }
576        @media (max-width: 760px) { .beta-announce { align-items: flex-start; flex-wrap: wrap; } }
577        html { scroll-behavior: smooth; }
578        [id] { scroll-margin-top: 86px; }
579
580
581/* ===== 「更多功能」下拉(动画与原菜单项完全一致) ===== */
582.nav-more { position: relative; display: flex; align-items: center; }
583.nav-more-btn {
584    position: relative; padding: 10px 14px;
585    font-size: .92rem; font-weight: 500; letter-spacing: .4px;
586    color: var(--ink-soft); background: none; border: none; cursor: pointer;
587    font-family: inherit; white-space: nowrap;
588    transition: color .3s ease;
589}
590.nav-more-btn::after {
591    content: ''; position: absolute; left: 14px; right: 14px; bottom: 2px;
592    height: 1px; background: var(--brand);
593    transform: scaleX(0); transform-origin: left;
594    transition: transform .35s cubic-bezier(.16,1,.3,1);
595}
596.nav-more-btn:hover { color: var(--ink); }
597.nav-more-btn:hover::after { transform: scaleX(1); }
598.nav-more.open .nav-more-btn { color: var(--ink); }
599.nav-more.open .nav-more-btn::after { transform: scaleX(1); }
600.nav-more-btn.active { color: var(--brand); font-weight: 600; }
601.nav-more-btn.active::after { transform: scaleX(1); }
602.nav-more-panel {
603    display: none; position: absolute; top: calc(100% + 12px); right: 0;
604    min-width: 178px; padding: 8px;
605    background: var(--card); border: 1px solid var(--line);
606    border-radius: 14px; box-shadow: 0 18px 44px -20px rgba(15,23,42,.42);
607    z-index: 300;
608}
609.nav-more.open .nav-more-panel { display: block; }
610.nav-more-panel a {
611    display: block; padding: 9px 12px; border-radius: 9px;
612    font-size: .88rem; color: var(--ink-soft); text-decoration: none; white-space: nowrap;
613    transition: background .18s ease, color .18s ease;
614}
615.nav-more-panel a:hover { background: rgba(59,130,246,.1); color: var(--brand); }
616html.dark .nav-more-panel { background: #0f1a30; border-color: rgba(148,163,184,.22); }
617html.dark .nav-more-panel a:hover { background: rgba(59,130,246,.2); color: #fff; }
618
619/* ===== 移动端:也显示这条菜单栏(左右滑动看全部),不再只靠汉堡 ===== */
620@media (max-width: 900px) {
621    .nav { padding: 0 12px; gap: 6px; }
622    .nav-logo { flex: 0 0 auto; margin-left: 0; }
623    .nav-menu {
624        display: flex;
625        flex: 1 1 auto;
626        min-width: 0;
627        justify-content: flex-start;
628        gap: 0;
629        overflow-x: auto;
630        overflow-y: hidden;
631        scrollbar-width: none;
632        -ms-overflow-style: none;
633        -webkit-overflow-scrolling: touch;
634        /* 右侧渐隐,提示还能往右滑 */
635        -webkit-mask-image: linear-gradient(90deg, #000 0, #000 88%, transparent 100%);
636        mask-image: linear-gradient(90deg, #000 0, #000 88%, transparent 100%);
637    }
638    .nav-menu::-webkit-scrollbar { display: none; }
639    .nav-menu > a, .nav-menu .nav-more-btn { padding: 9px 11px; font-size: .86rem; letter-spacing: .2px; }
640    .nav-menu > a::after, .nav-menu .nav-more-btn::after { left: 11px; right: 11px; }
641    .nav-right-group { flex: 0 0 auto; gap: 6px; }
642    .theme-btn { width: 38px; height: 38px; border-radius: 11px; font-size: 1rem; }
643    .nav-burger { flex: 0 0 auto; }
644    /* 下拉面板在手机上居中一点,避免贴边被裁 */
645    .nav-more-panel { right: auto; left: 0; }
646}
647@media (max-width: 420px) {
648    .nav-menu > a, .nav-menu .nav-more-btn { padding: 9px 9px; font-size: .82rem; }
649    .nav-logo .logo-img { height: 28px; }
650}
651
652/* ===== 移动端 / APP 适配增强 ===== */
653/* 1) 安全区:APP 全屏运行时,刘海屏/底部横条不再压住内容 */
654body {
655    padding-left: env(safe-area-inset-left, 0);
656    padding-right: env(safe-area-inset-right, 0);
657}
658.nav { padding-top: env(safe-area-inset-top, 0); }
659.footer { padding-bottom: calc(24px + env(safe-area-inset-bottom, 0px)); }
660.backtop { bottom: calc(18px + env(safe-area-inset-bottom, 0px)); }
661.drawer { padding-top: calc(18px + env(safe-area-inset-top, 0px)); padding-bottom: calc(18px + env(safe-area-inset-bottom, 0px)); }
662.nav-more-panel { max-height: 70vh; overflow-y: auto; }
663.d-modal, .modal-content, .cam-modal > div, .custom-modal > div {
664    max-height: 86vh; overflow-y: auto;
665}
666
667/* 2) 触摸体验 */
668a, button, [onclick], .sort-btn, .d-item {
669    -webkit-tap-highlight-color: transparent;
670    touch-action: manipulation;
671}
672html { -webkit-text-size-adjust: 100%; }
673
674/* 3) 手机上输入框字号统一 16px:
675      小于 16px 时 iOS/部分安卓 WebView 聚焦会自动放大整页(最常见的不适配感来源) */
676@media (max-width: 900px) {
677    input:not([type=checkbox]):not([type=radio]), textarea, select {
678        font-size: 16px !important;
679    }
680    /* 关键操作按钮的最小可点区域(不影响小图标按钮) */
681    button:not(.d-close):not(.nav-burger):not(.theme-btn):not(.backtop):not(.react-btn):not(.reply-btn):not(.edit-btn):not(.delete-btn):not(.report-btn):not(.sort-btn),
682    .btn, .hero-btn, .vhero-actions a {
683        min-height: 38px;
684    }
685    /* 表格:已有横向滚动容器的保持,没有的自动兜底 */
686    .table-wrap, .scroll-x, .stock-table-wrap { -webkit-overflow-scrolling: touch; }
687    /* 长文本防溢出 */
688    .comment-content, .bn-reason, .d-item, .pd-tip { word-break: break-word;
688 overflow-wrap: anywhere; }
689}
690
691/* 4) APP(独立窗口)下:去掉选中高亮与长按菜单的干扰,正文更接近原生 */
692@media (display-mode: standalone) {
693    a, button { -webkit-user-select: none; user-select: none; }
694    .comment-content { -webkit-user-select: text; user-select: text; }
695    .backtop { display: none; }   /* APP 里用系统返回键更自然 */
696}
697
698/* ===== 手机上「更多功能」下拉的处理 =====
699   原因:窄屏导航菜单是横向滚动的,而「更多功能」排在菜单最右端,
700        初始位置在屏幕外;且菜单的 overflow 会把弹出面板裁掉。
701   处理:手机上隐藏这个下拉(核心功能在 ☰ 抽屉里都有),平板/桌面保持可用。 */
702@media (max-width: 900px) {
703    .nav-more { display: none !important; }
704    .nav-more-panel { display: none !important; }
705}
706/* 平板/桌面:面板靠右弹出时留出边距,避免贴边 */
707@media (min-width: 901px) {
708    .nav-more-panel { max-width: calc(100vw - 24px); }
709}
710
711
712/* ===== 评论富文本:粗体 / 斜体 / 行内代码(不动链接颜色) ===== */
713.comment-content b, .comment-content strong { font-weight: 800; }
714.comment-content i, .comment-content em { font-style: italic; opacity: .95; }
715.comment-content code {
716    padding: 1px 6px; border-radius: 6px;
717    background: rgba(120,120,120,.14);
718    font-family: ui-monospace, Consolas, monospace; font-size: .92em;
719}
720.md-tip { font-size: .74rem; color: var(--ink-soft, #5a6270); opacity: .7; margin-top: 6px; }
721.md-tip code { padding: 1px 4px; border-radius: 4px; background: rgba(120,120,120,.14); font-size: .95em; }
722</style>
723<link rel="manifest" href="/manifest.json">
724<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32.png">
725<link rel="apple-touch-icon" sizes="180x180" href="/images/app-icon-180.png">
726<meta name="apple-mobile-web-app-capable" content="yes">
727<meta name="mobile-web-app-capable" content="yes">
728<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
729<meta name="apple-mobile-web-app-title" content="NB频道">
730<meta name="application-name" content="NB频道">
731<!-- nb-theme: 主题包(国庆 / 科技)—— 必须在页面样式之后加载 -->
732<link rel="stylesheet" href="../css/themes.css?v=35">
733<script src="../js/theme.js?v=9"></script>
733
734</head>
735<body>
736
737<!-- 导航 -->
738<nav class="nav">
739    <a class="nav-logo" href="index-Beta.html"><img class="logo-img" src="/images/NB频道LOGO.png" alt="NB频道"></a>
740    <div class="nav-menu">
741        <a href="index-Beta.html">首页</a>
742        <a href="videos-Beta.html" class="active">视频</a>
743        <a href="about-Beta.html">关于</a>
744        <a href="rules-Beta.html">用户守则</a>
745        <a href="changelog-Beta.html">更新日志</a>
746        <a href="product-Beta.html">我的产品</a>
747        <a href="APP-Beta.html">软件/APP</a>
748        <a href="index-Beta.html#friends">友商</a>
749        <a class="nav-api" href="/api-sdk/" target="_blank" rel="noopener noreferrer" title="NB频道 API 文档">API<i>↗</i></a>
750        <div class="nav-more">
751            <button class="nav-more-btn" type="button">更多功能 ▾</button>
752            <div class="nav-more-panel">
753                <a href="stock-Beta.html">📈 虚拟股票</a>
754                <a href="messages-Beta.html">🔔 消息中心</a>
755                <a href="chat-Beta.html">👥 好友 / 私信</a>
756                <a href="bank-Beta.html">🏦 NB银行</a>
757                <a href="shop-Beta.html">🛍️ NB商店</a>
758                <a href="backpack-Beta.html">🎒 我的背包</a>
759                <a href="titles-Beta.html">🏅 称号大全</a>
760                <a href="achievements-Beta.html">🏆 成就墙</a>
761                <a href="lottery-Beta.html">📅 签到 · 转盘</a>
762                <a href="lottery_records-Beta.html">🎰 抽奖记录</a>
763                <a href="tools-Beta.html">🔧 工具</a>
764                <a href="product_share-Beta.html">📦 作品分享</a>
765                <a href="comments-Beta.html">💬 评论区</a>
766                <a href="ban-Beta.html">🚫 小黑屋</a>
767                <a href="feedback-Beta.html">🐞 漏洞/建议反馈</a>
768                <a href="vote-Beta.html">🗳️ 投票中心</a>
769            </div>
770        </div>
771    </div>
772    <div class="nav-right-group">
773        <div class="nav-clock" id="navClock" title="北京时间(UTC+8)">
774            <span class="nc-time" id="bjTime">--:--:--</span>
775            <span class="nc-row"><i class="nc-date" id="bjDate">----.--.--</i><em class="nc-label">北京时间</em></span>
776        </div>
777        <button class="theme-btn" id="themeBtn" aria-label="切换夜间模式">🌙</button>
778        <div class="nav-auth-group" id="betaAuthGroup">
779            <a class="nav-auth" id="betaProfileBtn" href="#">👤 个人中心</a>
780            <a class="nav-auth primary" id="betaAuthBtn" href="#">登录 / 注册</a>
781        </div>
782    </div>
783    <button class="nav-burger" id="navBurger" aria-label="打开菜单">☰</button>
784    <!-- 扫码:手机端右上角,在汉堡(☰)的右边。只在 APP 里显示 —— 网页端调不动摄像头。
785         整段自包含(自带样式/脚本),不依赖本页既有的 CSS 变量和导航结构。 -->
786    <a class="nav-scan" id="navScanBtn" href="scan-Beta.html" aria-label="扫一扫" title="扫一扫"><svg width="21" height="21" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 8.5V6a3 3 0 0 1 3-3h2.5"/><path d="M15.5 3H18a3 3 0 0 1 3 3v2.5"/><path d="M21 15.5V18a3 3 0 0 1-3 3h-2.5"/><path d="M8.5 21H6a3 3 0 0 1-3-3v-2.5"/><path d="M3.2 12h17.6"/></svg></a>
787    <style>
788      .nav-scan{display:none;width:42px;height:42px;border-radius:12px;cursor:pointer;background:rgba(255,255,255,.7);border:1px solid var(--line,#e2e8f0);color:var(--ink,#0f172a);align-items:center;justify-content:center;text-decoration:none;-webkit-tap-highlight-color:transparent}
789      .nav-scan svg{width:21px;height:21px;display:block}
790      .nav-scan:hover{border-color:rgba(59,130,246,.5);color:var(--brand,#3b82f6)}
791      html.dark .nav-scan{background:rgba(255,255,255,.06);border-color:rgba(148,163,184,.25);color:var(--ink,#e2e8f0)}
792      @media (max-width:900px){.nav-scan{display:flex}}
793    </style>
794    
794<script>/* 扫码入口只在 APP 里显示。旧版 APP 也显示 —— 点进去 scan-Beta.html 会提示他更新 */
795    (function(){try{if(!/NBChannelApp/i.test(navigator.userAgent||"")){var b=document.getElementById("navScanBtn");if(b)b.style.display="none";}}catch(e){}})();</script>
795
796
797</nav>
798<script>
799// ===== 在 APP 里隐藏导航菜单的 emoji =====
800// 站长要求:APP 的「更多功能」下拉菜单不要 emoji,网页端保留原样。
801//
802// APP 是 Capacitor 套壳,加载的就是本站 —— 改 HTML 会两边一起改,
803// 所以只能按 UA 区分(APP 在 UA 里注入了 NBChannelApp)。
804// 判断写法与上面「扫一扫」那段保持一致。
805(function () {
806    var isApp = false;
807    try { isApp = /NBChannelApp/i.test(navigator.userAgent || ''); } catch (e) {}
808    if (!isApp) return;              // 浏览器里 —— emoji 保持原样
809
810    // 代理对(U+1F000 以上)+ BMP 符号区 + 变体选择符 + 零宽连接符,连同后面的空格一起剥掉
811    var LEAD = /^(?:[\u2190-\u21FF\u2300-\u23FF\u2600-\u27BF\u2B00-\u2BFF\uFE0F\u200D]|[\uD83C-\uDBFF][\uDC00-\uDFFF])+\s*/;
812
813    function strip() {
814        try {
815            var as = document.querySelectorAll('.nav-more-panel a, .drawer a');
816            // ⚠️ 桌面下拉(.nav-more-panel)在手机上被 CSS 藏了,手机走的是
817            //    汉堡抽屉(.drawer)。两个都要处理,否则 APP 里会漏。
818            for (var i = 0; i < as.length; i++) {
819                var t = as[i].textContent || '';
820                var n = t.replace(LEAD, '');
821                if (n !== t) as[i].textContent = n;
822            }
823        } catch (e) {}
824    }
825    strip();
826    setTimeout(strip, 400);    // 导航若是后渲染的,补两次
827    setTimeout(strip, 1500);
828})();
829
830// ===== 导航「更多功能」下拉 =====
831(function () {
832    var box = document.querySelector('.nav-more');
833    if (!box) return;
834    var btn = box.querySelector('.nav-more-btn');
835    btn.addEventListener('click', function (e) { e.stopPropagation(); box.classList.toggle('open'); });
836    document.addEventListener('click', function () { box.classList.remove('open'); });
837    document.addEventListener('keydown', function (e) { if (e.key === 'Escape') box.classList.remove('open'); });
838    var here = (location.pathname.split('/').pop() || '').toLowerCase();
839    if (here && box.querySelector('.nav-more-panel a[href="' + here + '"]')) btn.classList.add('active');
840})();
841</script>
841
842
843
844<!-- Hero -->
845<header class="vhero">
846    <div class="vhero-inner">
847        <div class="hero-copy">
848            <span class="hero-eyebrow">VIDEO ARCHIVE · BILIBILI</span>
849            <h1>视频<span class="light">档案</span></h1>
850            <p class="vhero-sub">化学与物理实验、日常作死、官网与产品记录——每一条都认真搞事。点击任意封面即可播放,或在 B站 给个三连</p>
851            <div class="vhero-actions">
852                <a class="hero-link" href="#vlist">进入档案 ↓</a>
853                <a class="hero-link" href="https://space.bilibili.com/3493259582114264" target="_blank" rel="noopener noreferrer">B站空间 ↗</a>
854            </div>
855        </div>
856        <div class="vhcard" id="vhCard">
857            <div class="vh-eyebrow">Collection</div>
858            <div class="vh-cardrows" id="vhRows"><!-- JS 填充:分类与数量 --></div>
859            <div class="vh-foot">
860                <span class="u">LATEST UPDATE</span>
861                <span class="d" id="vhLatest">--</span>
862            </div>
863        </div>
864    </div>
865    <div class="vhero-fade"></div>
866</header>
867
868<!-- 视频档案主区 -->
869<!-- 全站公告(与首页一致;admin_config key=announcement) -->
870<div class="beta-announce" id="betaAnnounce" style="display:none;">
871    <div class="ba-title">公告</div>
872    <div class="ba-track-wrap"><div class="ba-track" id="baTrack"></div></div>
873</div>
874<main class="vwrap" id="vlist">
875    <div class="vtoolbar">
876        <div class="vcats" id="vCats">
877            <button class="vcat on" data-k="__all__">全部</button>
878        </div>
879        <div class="vright">
880            <div class="vsort">
881                <button class="on" data-sort="time">最新</button>
882                <button data-sort="hot">最热</button>
883            </div>
884            <label class="vsearch">
885                <span style="font-size:.8rem;color:var(--ink-faint);">⌕</span>
886                <input type="text" id="vSearch" placeholder="搜索视频标题" autocomplete="off">
887            </label>
888        </div>
889    </div>
890    <div class="vcount" id="vCount">正在读取视频档案…</div>
891    <div class="video-grid" id="vGrid"></div>
892    <div id="vEmpty" class="empty" style="display:none;"><b>没有找到匹配的视频</b><br>换个关键词或分类试试</div>
893</main>
894
895<!-- 页脚 -->
896<footer class="footer">
897    <div class="footer-grid">
898        <div>
899            <div class="brand"><img class="logo-img" src="/images/NB频道LOGO.png" alt="NB频道"><span class="logo-text">NB频道</span></div>
900            <p class="desc">NB频道(NoBook频道)——热爱理科(和作死)的 UP主建立的虚拟公司。化学物理实验、日常作死、虚拟经济,一个有趣的数字世界</p>
901        </div>
902        <div>
903            <h5>功能</h5>
904            <a href="stock-Beta.html">虚拟股票</a><a href="bank-Beta.html">NB银行</a><a href="comments-Beta.html">评论区</a><a href="shop-Beta.html">NB商店</a><a href="tools-Beta.html">工具</a><a href="titles-Beta.html">称号系统</a><a href="feedback-Beta.html">漏洞/建议反馈</a>
905        </div>
906        <div>
907            <h5>友商</h5>
908            <a href="https://orgent.pythonanywhere.com/" target="_blank" rel="noopener noreferrer">Orgent(已注销)</a>
909            <a href="https://45d.cn/AWM/" target="_blank" rel="noopener noreferrer">AWM</a>
910            <a href="https://fafat.uuk.pp.ua/" target="_blank" rel="noopener noreferrer">Fafat</a>
911            <a href="https://nb-qx.top/" target="_blank" rel="noopener noreferrer">Lemon(齐喜)</a>
912            <a href="https://gaohantu.cn/" target="_blank" rel="noopener noreferrer">GaoHanTu</a>
913            <a href="https://utw.pages.dev" target="_blank" rel="noopener noreferrer">Utw</a>
914            <a href="https://pipetrainingcamp.github.io/" target="_blank" rel="noopener noreferrer">PTC(GoodPTC)</a>
915            <a href="https://yoyo-user-awa.github.io/UVS/" target="_blank" rel="noopener noreferrer">UVS</a>
916            <a href="https://3f7ceb4e.pinit.eth.limo/" target="_blank" rel="noopener noreferrer">UwLS</a>
917            <a href="https://45d.cn/nb-og.top/" target="_blank" rel="noopener noreferrer">Oganesson</a>
918            <a href="https://78439049.pinit.eth.limo/" target="_blank" rel="noopener noreferrer">SOT</a>
919        </div>
920        <div>
921            <h5>联系</h5>
922            <a href="/cdn-cgi/l/email-protection#aec0cccdc6cfc0c0cbc2ee9f989d80cdc1c3"><span class="__cf_email__" data-cfemail="7f111d1c171e11111a133f4e494c511c1012">[email&#160;protected]</span></a><a href="https://space.bilibili.com/3493259582114264" target="_blank" rel="noopener noreferrer">
922B站:NB搞事局</a><a href="https://nb-channel.top" target="_blank" rel="noopener noreferrer">nb-channel.top</a>
923        </div>
924    </div>
925    <div class="footer-bottom">© 2026 NB频道 · 虚拟公司 · 制作:NB搞事局 · 由 GitHub Pages / Cloudflare / PythonAnywhere 提供支持 · 视频数据由 B站 API 同步</div><div style="margin-top:8px;font-size:0.78rem;opacity:.72;line-height:1.9;">本站所有内容(页面代码 · 图文 · 数据)版权归 <b>NB频道</b> 所有,未经书面授权禁止复制、镜像或部署到其他域名</div>
926</footer>
927
928<!-- 移动端抽屉 -->
929<div class="drawer-mask" id="drawerMask"></div>
930<aside class="drawer" id="drawer">
931    <div class="d-head">
932        <span class="d-brand"><img class="logo-img" src="/images/NB频道LOGO.png" alt="NB频道"><span class="logo-text">NB频道</span></span>
933        <button class="d-close" id="drawerClose" aria-label="关闭菜单">✕</button>
934    </div>
935        <a class="d-item" href="vote-Beta.html">投票中心</a>
936        <a class="d-item" href="stock-Beta.html">虚拟股票</a>
937        <a class="d-item" href="messages-Beta.html">消息中心</a>
938        <a class="d-item" href="chat-Beta.html">好友 / 私信</a>
939        <a class="d-item" href="bank-Beta.html">NB银行</a>
940        <a class="d-item" href="shop-Beta.html">NB商店</a>
941        <a class="d-item" href="backpack-Beta.html">我的背包</a>
942        <a class="d-item" href="titles-Beta.html">称号大全</a>
943        <a class="d-item" href="achievements-Beta.html">成就墙</a>
944        <a class="d-item" href="lottery-Beta.html">签到 · 转盘</a>
945        <a class="d-item" href="lottery_records-Beta.html">抽奖记录</a>
946        <a class="d-item" href="tools-Beta.html">工具</a>
947        <a class="d-item" href="product_share-Beta.html">作品分享</a>
948        <a class="d-item" href="comments-Beta.html">评论区</a>
949        <a class="d-item" href="ban-Beta.html">小黑屋</a>
950        <a class="d-item" href="feedback-Beta.html">漏洞/建议反馈</a>
951    <div class="d-auth">
952        <a class="ga" id="dProfileBtn" href="#">个人中心</a>
953        <a class="gab" id="dAuthBtn" href="#">登录 / 注册</a>
954    </div>
955</aside>
956
957<!-- 播放弹窗 -->
958<div class="vmodal" id="vModal">
959    <div class="vmask" id="vMask"></div>
960    <div class="vbox" role="dialog" aria-modal="true">
961        <div class="vhead">
962            <div class="vt2" id="vTitle">--</div>
963            <button class="vclose" id="vClose" aria-label="关闭">✕</button>
964        </div>
965        <div class="vframe"><iframe id="vFrame" src="about:blank" title="B站播放器" allowfullscreen allow="autoplay; fullscreen; encrypted-media; picture-in-picture"></iframe></div>
966        <div class="vact">
967            <span class="hint">如播放器空白,请直接前往 B站 观看</span>
968            <a class="vopen" id="vOpen" href="#" target="_blank" rel="noopener noreferrer">在 B站打开 ↗</a>
969        </div>
970    </div>
971</div>
972
973<!-- 回到顶部 -->
974<button class="backtop" id="backTop" aria-label="回到顶部">↑</button>
975
976<!-- 视频数据(data/videos.js 由同步脚本自动更新,勿手改) -->
vendor: 109 bytes, lines 976-977
976
977<script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script>
977<script src="/data/videos.js"></script>
vendor: 1 bytes, line 977
977
978<script>
979(function () {
980    'use strict';
981    var LIST = window.VIDEOS || [];
982    var CAT_ORDER = ['化学', '物理', '救人', '官网', '产品', '其他'];
983    var grid = document.getElementById('vGrid');
984    var countEl = document.getElementById('vCount');
985    var emptyEl = document.getElementById('vEmpty');
986    var urlCat = '';
987    try { urlCat = new URLSearchParams(location.search).get('cat') || ''; } catch (e) {}
988    if (CAT_ORDER.indexOf(urlCat) < 0) urlCat = '';
989    var state = { cat: urlCat || '__all__', q: '', sort: 'time' };
990
991    function fmtDate(ts) {
992        try {
993            return new Intl.DateTimeFormat('zh-CN', { timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit' })
994                .format(new Date(ts * 1000)).replace(/\//g, '.');
995        } catch (e) { return ''; }
996    }
997    function norm(s) { return String(s || '').replace(/\s+/g, '').toLowerCase(); }
998    function parsePlay(p) {
999        var s = String(p || '0');
1000        if (/万/.test(s)) { var n = parseFloat(s) || 0; return Math.round(n * 10000); }
1001        return parseInt(s, 10) || 0;
1002    }
1003    function esc(s) {
1004        return String(s).replace(/[&<>"']/g, function (m) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[m]; });
1005    }
1006
1007    // ---- Hero 档案卡:分类计数与最近更新 ----
1008    function fillHero() {
1009        var rows = document.getElementById('vhRows');
1010        var latest = 0;
1011        var counts = {};
1012        LIST.forEach(function (v) {
1013            counts[v.category_key] = (counts[v.category_key] || 0) + 1;
1014            if (v.pubdate > latest) latest = v.pubdate;
1015        });
1016        if (rows) {
1017            rows.innerHTML = CAT_ORDER.map(function (k) {
1018                return '<div class="vh-row"><b>' + k + '</b><span class="cnt">' + (counts[k] || 0) + ' 部</span></div>';
1019            }).join('');
1020        }
1021        var lt = document.getElementById('vhLatest');
1022        if (lt) lt.textContent = latest ? fmtDate(latest) : '--';
1023    }
1024
1025    // ---- 筛选后的视频列表 ----
1026    function filtered() {
1027        var q = norm(state.q);
1028        return LIST.filter(function (v) {
1029            if (state.cat !== '__all__' && v.category_key !== state.cat) return false;
1030            if (q && norm(v.title).indexOf(q) < 0) return false;
1031            return true;
1032        }).sort(function (a, b) {
1033            return state.sort === 'hot' ? parsePlay(b.play) - parsePlay(a.play) : b.pubdate - a.pubdate;
1034        });
1035    }
1036
1037    // ---- 渲染 ----
1038    var io = null;
1039    function ensureIO() {
1040        if (io) return;
1041        io = new IntersectionObserver(function (es) {
1042            es.forEach(function (e) { if (e.isIntersecting) { e.target.classList.add('in'); io.unobserve(e.target); } });
1043        }, { threshold: 0.05 });
1044    }
1045    function render() {
1046        var list = filtered();
1047        if (countEl) {
1048            countEl.innerHTML = LIST.length
1049                ? (state.cat === '__all__' && !state.q ? '' : '') + '共 <b>' + list.length + '</b> 部' + (state.q ? ' 匹配「' + esc(state.q) + '」' : '') + (state.cat !== '__all__' ? ' · ' + esc(state.cat) + ' 系列' : '')
1050                : '视频档案整理中…';
1051        }
1052        if (emptyEl) emptyEl.style.display = (LIST.length && !list.length) ? 'block' : 'none';
1053        if (!LIST.length) {
1054            if (grid) grid.innerHTML = '<div class="empty"><b>视频档案暂时无法读取</b><br>请稍后刷新重试</div>';
1055            return;
1056        }
1057        if (grid) {
1058            grid.innerHTML = list.map(function (v, i) {
1059                return '<div class="vcard reveal" role="button" tabindex="0" data-bvid="' + esc(v.bvid) + '" data-title="' + esc(v.title) + '" style="transition-delay:' + Math.min(i * 22, 320) + 'ms">' +
1060                    '<div class="thumb"><img loading="lazy" decoding="async" src="' + esc(v.cover) + '" alt="' + esc(v.title) + '"><span class="dur">' + esc(v.duration) + '</span><span class="play">▶</span></div>' +
1061                    '<div class="body"><h4>' + esc(v.title) + '</h4>' +
1062                    '<div class="meta"><span>' + esc(v.play) + ' 次播放</span><span>' + fmtDate(v.pubdate) + '</span><span class="cat">' + esc(v.category_name || v.category_key) + '</span></div></div>' +
1063                    '</div>';
1064            }).join('');
1065            ensureIO();
1066            Array.prototype.forEach.call(grid.querySelectorAll('.reveal'), function (el) { io.observe(el); });
1067        }
1068    }
1069
1070    // ---- 分类 chips ----
1071    var cats = document.getElementById('vCats');
1072    if (cats) {
1073        CAT_ORDER.forEach(function (k) {
1074            var b = document.createElement('button');
1075            b.className = 'vcat';
1076            b.dataset.k = k;
1077            b.textContent = k;
1078            if (k === state.cat) b.classList.add('on');
1079            cats.appendChild(b);
1080        });
1081        // ?cat=xxx 直达时:与"全部"高亮同步
1082        if (state.cat !== '__all__') {
1083            Array.prototype.forEach.call(cats.querySelectorAll('.vcat'), function (x) {
1084                x.classList.toggle('on', x.dataset.k === state.cat);
1085            });
1086        }
1087        cats.addEventListener('click', function (e) {
1088            var b = e.target.closest('.vcat');
1089            if (!b) return;
1090            state.cat = b.dataset.k;
1091            Array.prototype.forEach.call(cats.querySelectorAll('.vcat'), function (x) { x.classList.toggle('on', x === b); });
1092            render();
1093        });
1094    }
1095
1096    // ---- 排序 ----
1097    document.querySelectorAll('.vsort button').forEach(function (b) {
1098        b.addEventListener('click', function () {
1099            state.sort = b.dataset.sort;
1100            document.querySelectorAll('.vsort button').forEach(function (x) { x.classList.toggle('on', x === b); });
1101            render();
1102        });
1103    });
1104
1105    // ---- 搜索(去空格匹配,标题带字间空格也能搜到) ----
1106    var search = document.getElementById('vSearch');
1107    if (search) {
1108        var st = null;
1109        search.addEventListener('input', function () {
1110            clearTimeout(st);
1111            st = setTimeout(function () { state.q = search.value.trim(); render(); }, 180);
1112        });
1113    }
1114
1115    // ---- 播放弹窗 ----
1116    var modal = document.getElementById('vModal');
1117    var frame = document.getElementById('vFrame');
1118    var mTitle = document.getElementById('vTitle');
1119    var mOpen = document.getElementById('vOpen');
1120    function openPlayer(bvid, title) {
1121        if (!modal || !frame) return;
1122        frame.src = 'https://player.bilibili.com/player.html?bvid=' + encodeURIComponent(bvid) + '&autoplay=1&high_quality=1';
1123        if (mTitle) mTitle.textContent = title || '';
1124        if (mOpen) mOpen.href = 'https://www.bilibili.com/video/' + encodeURIComponent(bvid);
1125        modal.classList.add('open');
1126        document.body.classList.add('locked');
1127    }
1128    function closePlayer() {
1129        if (!modal) return;
1130        modal.classList.remove('open');
1131        document.body.classList.remove('locked');
1132        if (frame) frame.src = 'about:blank';   // 停止播放
1133    }
1134    if (grid) {
1135        grid.addEventListener('click', function (e) {
1136            var card = e.target.closest('.vcard');
1137            if (!card) return;
1138            openPlayer(card.dataset.bvid, card.dataset.title);
1139        });
1140        grid.addEventListener('keydown', function (e) {
1141            if ((e.key === 'Enter' || e.key === ' ') && e.target.classList.contains('vcard')) {
1142                e.preventDefault();
1143                openPlayer(e.target.dataset.bvid, e.target.dataset.title);
1144            }
1145        });
1146    }
1147    var mask = document.getElementById('vMask');
1148    if (mask) mask.addEventListener('click', closePlayer);
1149    var vc = document.getElementById('vClose');
1150    if (vc) vc.addEventListener('click', closePlayer);
1151    document.addEventListener('keydown', function (e) { if (e.key === 'Escape') closePlayer(); });
1152
1153    // ---- 入场渐显(容器与标题) ----
1154    (function () {
1155        var els = document.querySelectorAll('.hero-copy, .vhcard, .vtoolbar, .vcount');
1156        els.forEach(function (el) { el.classList.add('reveal'); });
1157        requestAnimationFrame(function () {
1158            els.forEach(function (el, i) { el.style.transitionDelay = (i * 90) + 'ms'; el.classList.add('in'); });
1159        });
1160    })();
1161
1162    fillHero();
1163    render();
1164})();
1165</script>
vendor: 1 bytes, line 1165
1165
1166<script>
1167    // ===== 登录区绑定(与首页一致:导航 + 移动端抽屉两处共用) =====
1168    function bindAuthPair(pbEl, abEl) {
1169        if (!pbEl && !abEl) return;
1170        var storedU = null;
1171        try { storedU = JSON.parse(localStorage.getItem('nb_user')); } catch (e) {}
1172        if (storedU && storedU.id) {
1173            if (abEl) {
1174                abEl.textContent = '登出账号';
1175                abEl.onclick = function () { localStorage.removeItem('nb_user'); location.reload(); };
1176            }
1177            if (pbEl) {
1178                pbEl.textContent = '👤 ' + (storedU.username || storedU.name || '个人中心');
1179                pbEl.href = 'profile-Beta.html';
1180            }
1181        } else {
1182            var loginHref = 'login-Beta.html?redirect=' + encodeURIComponent(location.href);
1183            if (abEl) { abEl.href = loginHref; abEl.textContent = '登录 / 注册'; }
1184            if (pbEl) { pbEl.href = loginHref; pbEl.textContent = '👤 个人中心'; }
1185        }
1186    }
1187    bindAuthPair(document.getElementById('betaProfileBtn'), document.getElementById('betaAuthBtn'));
1188    bindAuthPair(document.getElementById('dProfileBtn'), document.getElementById('dAuthBtn'));
1189
1190    // ===== 导航栏北京时间(与首页一致:UTC+8,日期+秒) =====
1191    (function () {
1192        var tEl = document.getElementById('bjTime');
1193        var dEl = document.getElementById('bjDate');
1194        if (!tEl) return;
1195        var fmtT = new Intl.DateTimeFormat('zh-CN', {
1196            timeZone: 'Asia/Shanghai', hour: '2-digit', minute: '2-digit',
1197            second: '2-digit', hour12: false, hourCycle: 'h23'
1198        });
1199        var fmtD = new Intl.DateTimeFormat('zh-CN', {
1200            timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit',
1201            day: '2-digit', weekday: 'short'
1202        });
1203        function tick() {
1204            var now = new Date();
1205            tEl.textContent = fmtT.format(now);
1206            if (dEl) dEl.textContent = fmtD.format(now).replace(/\//g, '.');
1207        }
1208        tick();
1209        setInterval(tick, 1000);
1210    })();
1211
1212    // ===== 导航滚动态(吸顶加深) + 回到顶部按钮 =====
1213    (function () {
1214        var nav = document.querySelector('.nav');
1215        var backTop = document.getElementById('backTop');
1216        function onScroll() {
1217            var y = window.scrollY || document.documentElement.scrollTop;
1218            if (nav) nav.classList.toggle('scrolled', y > 10);
1219            if (backTop) backTop.classList.toggle('show', y > 700);
1220        }
1221        window.addEventListener('scroll', onScroll, { passive: true });
1222        onScroll();
1223        if (backTop) backTop.addEventListener('click', function () {
1224            window.scrollTo({ top: 0, behavior: 'smooth' });
1225        });
1226    })();
1227
1228    // ===== 夜间模式切换 =====
1229    (function () {
1230        var btn = document.getElementById('themeBtn');
1231        var root = document.documentElement;
1232        function isDark() { return root.classList.contains('dark'); }
1233        function render() {
1234            if (btn) { btn.textContent = isDark() ? '☀️' : '🌙'; btn.title = isDark() ? '切换到日间模式' : '切换到夜间模式'; }
1235        }
1236        function apply(dark) {
1237            root.classList.toggle('dark', dark);
1238            try { localStorage.setItem('theme', dark ? 'dark' : 'light'); } catch (e) {}
1239            render();
1240        }
1241        if (btn) btn.addEventListener('click', function () {
1242            var dark = !isDark();
1243            if (document.startViewTransition) {
1244                try { document.startViewTransition(function () { apply(dark); }); } catch (e) { apply(dark); }
1245            } else apply(dark);
1246        });
1247        render();
1248    })();
1249
1250    // ===== 移动端抽屉 =====
1251    (function () {
1252        var burger = document.getElementById('navBurger');
1253        var drawer = document.getElementById('drawer');
1254        var mask = document.getElementById('drawerMask');
1255        var closeBtn = document.getElementById('drawerClose');
1256        if (!burger || !drawer || !mask) return;
1257        function open() { drawer.classList.add('open'); mask.style.display = 'block'; document.body.classList.add('locked'); }
1258        function close() { drawer.classList.remove('open'); mask.style.display = 'none'; document.body.classList.remove('locked'); }
1259        burger.addEventListener('click', open);
1260        closeBtn.addEventListener('click', close);
1261        mask.addEventListener('click', close);
1262        drawer.querySelectorAll('a').forEach(function (a) { a.addEventListener('click', close); });
1263    })();
1264
1265    // ===== 防查看代码(反调试,静默无提示) =====
1266    // 逃生门:URL 含 ?dev=1 或 #dev 完全放行;另支持 window.__allowDevTools = true
1267    (function () {
1268        var DEV = window.__allowDevTools ||
1269                  /(?:^|[?&#])dev=1(?=&|#|$)/.test(location.href) ||
1270                  /#dev\b/.test(location.hash);
1271        if (DEV) return;
1272        document.addEventListener('keydown', function (e) {
1273            var k = e.keyCode || e.which;
1274            var ctrl = e.ctrlKey || e.metaKey;
1275            if (k === 123 || e.key === 'F12' ||
1276                (ctrl && e.shiftKey && (k === 73 || k === 74 || k === 67)) ||
1277                (ctrl && k === 85)) {
1278                e.preventDefault();
1279                e.stopPropagation();
1280                return false;
1281            }
1282        });
1283        document.addEventListener('contextmenu', function (e) {
1284            e.preventDefault();
1285            return false;
1286        });
1287        setInterval(function () { debugger; }, 600);
1288    })();
1289</script>
vendor: 1 bytes, line 1289
1289
1290<script>
1291    // ===== 鼠标/触摸特效:跟随光晕 + 点击波纹与彩色粒子(鼠标 + 触屏都启用) =====
1292    (function () {
1293        var mqFine = window.matchMedia ? window.matchMedia('(pointer: fine)') : null;
1294        var isFine = !!(mqFine && mqFine.matches);
1295        var canTouch = ('ontouchstart' in window) ||
1296            !!(window.matchMedia && window.matchMedia('(pointer: coarse)').matches);
1297        var glow = document.createElement('div');
1298        glow.className = 'ui-fx-glow';
1299        document.body.appendChild(glow);
1300        var gx = -999, gy = -999, tx = -999, ty = -999;
1301        var colors = ['#3b82f6', '#8b5cf6', '#6366f1', '#06b6d4', '#f59e0b'];
1302        var lastTouch = 0, glowTimer = null;
1303
1304        // 光晕跟手:有精确指针(鼠标)就跟鼠标,否则跟手指
1305        if (isFine) {
1306            document.addEventListener('mousemove', function (e) { tx = e.clientX; ty = e.clientY; });
1307            document.addEventListener('mouseenter', function () { glow.style.opacity = '1'; });
1308            document.addEventListener('mouseleave', function () { glow.style.opacity = '0'; });
1309        }
1310        if (canTouch) {
1311            document.addEventListener('touchstart', function (e) {
1312                var t = e.touches[0]; if (!t) return;
1313                tx = t.clientX; ty = t.clientY;
1314                if (gx < -100) { gx = tx; gy = ty; }   // 首次别从屏幕角落滑过来
1315                glow.style.opacity = '1';
1316                if (glowTimer) { clearTimeout(glowTimer); glowTimer = null; }
1317                lastTouch = Date.now();
1318                burst(t.clientX, t.clientY, 6, 0.75);
1319            }, { passive: true });
1320            document.addEventListener('touchmove', function (e) {
1321                var t = e.touches[0]; if (!t) return;
1322                tx = t.clientX; ty = t.clientY;
1323                glow.style.opacity = '1';
1324            }, { passive: true });
1325            document.addEventListener('touchend', function () {
1326                if (glowTimer) clearTimeout(glowTimer);
1327                glowTimer = setTimeout(function () { glow.style.opacity = '0'; }, 380);
1328            }, { passive: true });
1329            document.addEventListener('touchcancel', function () { glow.style.opacity = '0'; }, { passive: true });
1330        }
1331
1332        var lx = -1e9, ly = -1e9;
1333        (function loop() {
1334            var k = isFine ? 0.14 : 0.32;   // 手指跟得紧一些
1335            gx += (tx - gx) * k;
1336            gy += (ty - gy) * k;
1337            // 静止时跳过写入:避免每帧重复改 style 白白触发样式计算
1338            if (Math.abs(gx - lx) > 0.2 || Math.abs(gy - ly) > 0.2) {
1339                glow.style.left = gx + 'px';
1340                glow.style.top = gy + 'px';
1341                lx = gx; ly = gy;
1342            }
1343            requestAnimationFrame(loop);
1344        })();
1345
1346        // ===== 点击波纹 + 彩色粒子 =====
1347        function burst(x, y, count, scale) {
1348            var ring = document.createElement('div');
1349            ring.style.cssText = 'position:fixed; left:' + x + 'px; top:' + y + 'px; width:12px; height:12px; border:2px solid rgba(59,130,246,.75); border-radius:50%; pointer-events:none; z-index:9999; transform:translate(-50%,-50%);';
1350            document.body.appendChild(ring);
1351            setTimeout(function () { if (ring.parentNode) ring.remove(); }, 900);
1352            try {
1353                ring.animate([
1354                    { transform: 'translate(-50%,-50%) scale(1)', opacity: 0.9 },
1355                    { transform: 'translate(-50%,-50%) scale(' + (5.5 * scale) + ')', opacity: 0 }
1356                ], { duration: 600, easing: 'ease-out', fill: 'forwards' });
1357            } catch (err) { ring.remove(); }
1358            for (var i = 0; i < count; i++) {
1359                var p = document.createElement('div');
1360                var size = 4 + Math.random() * 6;
1361                var ang = Math.random() * Math.PI * 2;
1362                var dist = (28 + Math.random() * 52) * scale;
1363                p.style.cssText = 'position:fixed; left:' + x + 'px; top:' + y + 'px; width:' + size + 'px; height:' + size + 'px; border-radius:50%; background:' + colors[i % colors.length] + '; pointer-events:none; z-index:9999;';
1364                document.body.appendChild(p);
1365                var dx = Math.cos(ang) * dist, dy = Math.sin(ang) * dist;
1366                var dur = 500 + Math.random() * 250;
1367                setTimeout(function (el) {
1368                    return function () { if (el.parentNode) el.remove(); };
1369                }(p), dur + 250);
1370                try {
1371                    p.animate([
1372                        { transform: 'translate(0,0) scale(1)', opacity: 1 },
1373                        { transform: 'translate(' + dx + 'px,' + dy + 'px) scale(0.1)', opacity: 0 }
1374                    ], { duration: dur, easing: 'cubic-bezier(0.15,0.8,0.25,1)', fill: 'forwards' });
1375                } catch (err) { p.remove(); }
1376            }
1377        }
1378        // 鼠标点击
1379        document.addEventListener('click', function (e) {
1380            if (Date.now() - lastTouch < 800) return;   // 触摸后浏览器会补发 click,去重
1381            burst(e.clientX, e.clientY, 8, 1);
1382        });
1383    })();
1384</script>
vendor: 1 bytes, line 1384
1384
1385<script>
1386    // ===== 全站公告条:supabase REST 单次拉取(无需加载 SDK),失败静默隐藏 =====
1387    (function () {
1388        var bar = document.getElementById('betaAnnounce');
1389        var track = document.getElementById('baTrack');
1390        if (!bar || !track) return;
1391        function esc(s) {
1392            return String(s).replace(/[&<>"']/g, function (m) {
1393                return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[m];
1394            });
1395        }
1396        function linkify(s) {
1397            return s.replace(/(https?:\/\/[^\s<>"']+)/g, '<a href="$1" target="_blank" rel="noopener noreferrer" style="color:var(--brand); text-decoration:underline;">$1</a>');
1398        }
1399        fetch('https://pbaafgjkwdbwcmsikcmg.supabase.co/rest/v1/admin_config?select=value&key=eq.announcement', {
1400            headers: {
1401                'apikey': 'sb_publishable_tv7YVJEisnvs3hvU8ImYUw_b0p6bmRg',
1402                'Authorization': 'Bearer sb_publishable_tv7YVJEisnvs3hvU8ImYUw_b0p6bmRg'
1403            }
1404        })
1405        .then(function (r) { return r.ok ? r.json() : null; })
1406        .then(function (rows) {
1407            if (!rows || !rows.length) return;
1408            var raw = String(rows[0].value || '').trim();
1409            if (!raw) return;
1410            bar.style.display = 'flex';   // 先显示再测量(display:none 时 offsetWidth 恒为 0)
1411            var one = '<span class="ba-item">' + linkify(esc(raw)) + '</span>';
1412            track.innerHTML = one;
1413            var item = track.querySelector('.ba-item');
1414            var itemW = item ? item.offsetWidth : 0;
1415            if (itemW <= 0) return;
1416            var wrapEl = bar.querySelector('.ba-track-wrap');
1417            var barW = wrapEl ? wrapEl.clientWidth : 0;
1418            var copies = Math.max(2, Math.ceil(barW / itemW) + 1);
1419            var all = '';
1420            for (var ci = 0; ci < copies; ci++) all += '<span class="ba-item">' + linkify(esc(raw)) + '</span>';
1421            track.innerHTML = all;
1422            var dur = Math.max(8, itemW / 45);
1423            if (track.animate) {
1424                track.animate(
1425                    [{ transform: 'translateX(0)' }, { transform: 'translateX(-' + itemW + 'px)' }],
1426                    { duration: dur * 1000, iterations: Infinity, easing: 'linear' }
1427                );
1428            }
1429        })
1430        .catch(function () {});
1431    })();
1432</script>
1432
1433
1434<script>
1435    // ===== 安全强制重登:本地有用户信息但无会话令牌 => 视为未登录 =====
1436    (function () {
1437        try {
1438            var u = localStorage.getItem('nb_user');
1439            var s = localStorage.getItem('nb_session');
1440            if (u && !s) {
1441                localStorage.removeItem('nb_user');
1442                location.reload();
1443            }
1444        } catch (e) {}
1445    })();
1446</script>
1446
1447
1448
1449<script>
1450// ===== APP 自更新(仅 APP 内生效) =====
1451(function () {
1452    var ua = navigator.userAgent || '';
1453    var m = /NBChannelApp\/([0-9.]+)/i.exec(ua);
1454    if (!m) return;                       // 不是 APP 环境,不打扰网页用户
1455    var localVer = m[1];
1456    var APK = '/download/NBChannel.apk';
1457
1458    function cmp(a, b) {
1459        var x = String(a).split('.').map(Number), y = String(b).split('.').map(Number);
1460        for (var i = 0; i < 3; i++) { var p = x[i] || 0, q = y[i] || 0; if (p !== q) return p - q; }
1461        return 0;
1462    }
1463
1464    var checking = false;
1465    function check(manual) {
1466        if (checking) return;
1467        checking = true;
1468        fetch('/download/version.json?t=' + Date.now(), { cache: 'no-store' })
1469            .then(function (r) { if (!r.ok) throw new Error('HTTP ' + r.status); return r.json(); })
1470            .then(function (info) {
1471                checking = false;
1472                if (!info || !info.versionName) throw new Error('版本信息不完整');
1473                if (cmp(info.versionName, localVer) > 0) showBar(info, manual);
1474                else if (manual) toast('✅ 已是最新版 v' + localVer);
1475            })
1476            .catch(function (e) {
1477                checking = false;
1478                if (manual) toast('检查更新失败:' + e.message + '\n请检查网络后重试');
1479            });
1480    }
1481
1482    // ---- 底部更新条 ----
1483    function showBar(info, manual) {
1484        if (document.getElementById('nbUpdateBar')) return;
1485        var bar = document.createElement('div');
1486        bar.id = 'nbUpdateBar';
1487        bar.style.cssText = 'position:fixed;left:0;right:0;bottom:0;z-index:99999;' +
1488            'padding:14px 16px calc(14px + env(safe-area-inset-bottom,0px));' +
1489            'background:linear-gradient(135deg,#3b82f6,#6366f1);color:#fff;' +
1490            'display:flex;align-items:center;gap:10px;font-size:.86rem;' +
1491            'box-shadow:0 -8px 28px rgba(0,0,0,.3);';
1492        bar.innerHTML =
1493            '<div style="flex:1;line-height:1.6;min-width:0;">
1493' +
1494                '<b>发现新版本 v' + info.versionName + '</b><br>' +
1495                '<span style="opacity:.9;font-size:.78rem;">当前 v' + localVer + ' · ' +
1496                (info.note || '修复与优化') + '</span>' +
1497            '</div>' +
1498            '<button id="nbUpdGo" style="background:#fff;color:#3b82f6;border:none;border-radius:999px;' +
1499                'padding:9px 18px;font-weight:800;font-family:inherit;font-size:.86rem;cursor:pointer;white-space:nowrap;">立即更新</button>' +
1500            '<button id="nbUpdNo" style="background:transparent;border:none;color:#fff;opacity:.75;' +
1501                'font-size:1.05rem;cursor:pointer;padding:4px 6px;">✕</button>';
1502        document.body.appendChild(bar);
1503        document.getElementById('nbUpdNo').onclick = function () { bar.remove(); };
1504        document.getElementById('nbUpdGo').onclick = function () {
1505            var b = this;
1506            b.textContent = '下载中…'; b.disabled = true; b.style.opacity = '.8';
1507            location.href = info.url || APK;
1508            setTimeout(function () { b.textContent = '立即更新'; b.disabled = false; b.style.opacity = '1'; }, 12000);
1509        };
1510    }
1511
1512    // ---- 轻提示 ----
1513    function toast(msg) {
1514        var t = document.createElement('div');
1515        t.style.cssText = 'position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);z-index:99999;' +
1516            'background:rgba(15,23,42,.94);color:#fff;padding:14px 20px;border-radius:14px;' +
1517            'font-size:.86rem;line-height:1.7;max-width:80vw;text-align:center;white-space:pre-line;' +
1518            'box-shadow:0 12px 36px rgba(0,0,0,.4);';
1519        t.textContent = msg;
1520        document.body.appendChild(t);
1521        setTimeout(function () { t.remove(); }, 2600);
1522    }
1523
1524    // ---- 在导航「更多功能」下拉 + 手机抽屉里注入入口 ----
1525    function inject() {
1526        var panel = document.querySelector('.nav-more-panel');
1527        if (panel && !panel.querySelector('[data-nb-upd]')) {
1528            var a = document.createElement('a');
1529            a.href = 'javascript:void(0)';
1530            a.setAttribute('data-nb-upd', '1');
1531            a.textContent = '🔄 检查更新';
1532            a.addEventListener('click', function (e) {
1533                e.preventDefault();
1534                var more = document.querySelector('.nav-more');
1535                if (more) more.classList.remove('open');
1536                check(true);
1537            });
1538            panel.insertBefore(a, panel.firstChild);
1539        }
1540        var authBox = document.querySelector('.drawer .d-auth');
1541        if (authBox && !document.querySelector('[data-nb-upd-d]')) {
1542            var d = document.createElement('a');
1543            d.className = 'd-item';
1544            d.href = 'javascript:void(0)';
1545            d.setAttribute('data-nb-upd-d', '1');
1546            d.textContent = '🔄 检查更新(v' + localVer + ')';
1547            d.addEventListener('click', function (e) { e.preventDefault(); check(true); });
1548            authBox.parentNode.insertBefore(d, authBox);
1549        }
1550    }
1551
1552    if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', inject);
1553    else inject();
1554    setTimeout(inject, 1200);      // 兜底:导航是脚本渲染时再试一次
1555
1556    // 启动自动查一次,之后每 30 分钟
1557    setTimeout(function () { check(false); }, 2000);
1558    setInterval(function () { check(false); }, 30 * 60 * 1000);
1559})();
1560</script>
1560
1561
1562<script>
1563/* ===== Android 上让 B站链接优先打开 B站 APP ===== */
1564(function () {
1565    try {
1566        if (!/Android/i.test(navigator.userAgent)) return;   // 只在安卓上改,桌面/iPhone 保持原样
1567        function toIntent(href) {
1568            var m = href.match(/space\.bilibili\.com\/(\d+)/);
1569            if (!m) return null;
1570            // intent:// 是安卓专属协议:能打开 APP 就打开,打不开就回退到 browser_fallback_url
1571            return 'intent://space/' + m[1] + '#Intent;scheme=bilibili;package=tv.danmaku.bili' +
1572                   ';S.browser_fallback_url=' + encodeURIComponent(href) + ';end';
1573        }
1574        function patch() {
1575            var links = document.querySelectorAll('a[href*="space.bilibili.com"]');
1576            for (var i = 0; i < links.length; i++) {
1577                var a = links[i];
1578                if (a.dataset.nbIntent) continue;
1579                var it = toIntent(a.getAttribute('href') || a.href);
1580                if (it) { a.setAttribute('href', it); a.dataset.nbIntent = '1'; }
1581            }
1582        }
1583        if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', patch);
1584        else patch();
1585        setTimeout(patch, 1500);
1586    } catch (e) {}
1587})();
1588
1589/* ===== 双击视频铺满屏幕 ===== */
1590(function () {
1591    try {
1592        var style = document.createElement('style');
1593        style.textContent =
1594            'video.nb-fs{position:fixed!important;left:0!important;top:0!important;' +
1595            'width:100vw!important;height:100vh!important;max-width:100vw!important;' +
1596            'max-height:100vh!important;margin:0!important;border-radius:0!important;' +
1597            'z-index:99999!important;background:#000!important;object-fit:contain!important;}' +
1598            'body.nb-fs-lock{overflow:hidden!important;}';
1599        document.head.appendChild(style);
1600
1601        var current = null;
1602        function exit() {
1603            if (!current) return;
1604            current.classList.remove('nb-fs');
1605            document.body.classList.remove('nb-fs-lock');
1606            current = null;
1607        }
1608        function enter(v) {
1609            exit();
1610            v.classList.add('nb-fs');
1611            document.body.classList.add('nb-fs-lock');
1612            current = v;
1613            try { v.play(); } catch (e) {}
1614        }
1615        // 双击:进/出全屏
1616        document.addEventListener('dblclick', function (e) {
1617            var v = e.target && e.target.closest ? e.target.closest('video') : null;
1618            if (!v) return;
1619            e.preventDefault();
1620            if (current === v) exit(); else enter(v);
1621        }, true);
1622        // 全屏状态下点空白处/按 Esc 退出
1623        document.addEventListener('click', function (e) {
1624            if (current && !(e.target.closest && e.target.closest('video'))) exit();
1625        }, true);
1626        document.addEventListener('keydown', function (e) { if (e.key === 'Escape') exit(); });
1627        // 页面切换/尺寸变化时兜底
1628        window.addEventListener('resize', function () { if (current) exit(); });
1629    } catch (e) {}
1630})();
1631</script>
1631
1632
1633<!--
1634  ══════════════════════════════════════════════════════════════════
1635   NB-CHANNEL ORIGINAL · 本页面由 NB频道 原创制作
1636   构建指纹 NBC-20261001-B1C0E3BE2CC9
1637   官方域名 nb-channel.top (github. / cloudflare. / edgeone. / pythonanywhere.)
1638   如果你在其他域名看到本页,说明该站点未经授权复制了 NB频道 的内容,
1639   欢迎举报:[email protected]
1640  ══════════════════════════════════════════════════════════════════
1641-->
1642
1643<script>/* 构建元信息(请勿删除,侵权取证用) */
1644(function () {
1645    try {
1646        var _nb = "TkJDLTIwMjYxMDAxLUIxQzBFM0JFMkNDOQ";
1647        if (typeof window !== "undefined") window.__nbBuild = _nb;
1648    } catch (e) {}
1649})();
1650</script>
vendor: 1 bytes, line 1650
1650
1651<script defer src="../js/science-tips.js?v=26"></script>
vendor: 1 bytes, line 1651
1651
1652<script src="../js/pomodoro.js?v=7" defer></script>
vendor: 1 bytes, line 1652
1652
1653<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"2694d6c1b70c42ee8414dc6303584599","r":1,"spa":2}' crossorigin="anonymous"></script>
1653
1654</body>
1655</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.