Greasy Fork

Greasy Fork is available in English.

Via 浏览器 404 和网络连接失败页面美化

为 Via 浏览器错误页面(404 Not Found 和网络连接失败)注入美化,404 页面采用幻境风格,网络连接失败页面采用生命美学与科幻风格,支持日夜模式自动切换

当前为 2025-04-20 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Via 浏览器 404 和网络连接失败页面美化
// @namespace    https://viayoo.com/
// @version      1.11
// @description  为 Via 浏览器错误页面(404 Not Found 和网络连接失败)注入美化,404 页面采用幻境风格,网络连接失败页面采用生命美学与科幻风格,支持日夜模式自动切换
// @author       是小白呀 & Grok
// @match        *://*/*
// @license      MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // 提取错误页面中的 URL(用于网络连接失败页面)
    function extractErrorUrl() {
        const bodyText = document.body ? document.body.innerText : '';
        const urlMatch = bodyText.match(/(https?:\/\/[^\s]+)/i);
        return urlMatch ? urlMatch[0] : '未知地址';
    }

    // 提取错误代码和服务器信息(用于 404 页面)
    function extractErrorInfo() {
        const bodyText = document.body ? document.body.innerText : '';
        const errorCodeMatch = bodyText.match(/net::ERR_[A-Z_]+/) || document.title.match(/404 Not Found/) || ['404 Not Found'];
        const serverMatch = bodyText.match(/nginx/i) ? 'nginx' : '';
        return {
            errorCode: errorCodeMatch[0],
            server: serverMatch
        };
    }

    // 检查是否为 404 错误页面(严格匹配“404 Not Found”和“nginx”)
    function checkFor404Page() {
        let has404 = false;
        let hasNginx = false;

        // 检查标题
        if (/404 Not Found/i.test(document.title)) {
            has404 = true;
        }
        // 检查 body 内容
        if (document.body) {
            const text = document.body.innerText || '';
            if (/404 Not Found/i.test(text)) {
                has404 = true;
            }
            if (/nginx/i.test(text)) {
                hasNginx = true;
            }
        }
        // 必须同时满足“404 Not Found”和“nginx”
        return has404 && hasNginx;
    }

    // 检查是否为网络连接失败页面
    function checkForConnectionErrorPage() {
        // 排除 404 页面
        if (checkFor404Page()) {
            return false;
        }
        // 快速检查标题
        if (/无法打开|Error/i.test(document.title)) {
            return true;
        }
        // 检查 body 内容
        if (document.body) {
            const text = document.body.innerText || '';
            if (/net::ERR_|网页无法打开|无法连接|ERR_NAME_NOT_RESOLVED/i.test(text)) {
                return true;
            }
            // 空页面
            if (document.body.innerHTML.trim() === '') {
                return true;
            }
        }
        return false;
    }

    // 替换 404 错误页面(幻境风格)
    function replace404Page() {
        const { errorCode, server } = extractErrorInfo();
        document.documentElement.innerHTML = `
            <!DOCTYPE html>
            <html lang="zh-CN">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>迷失幻境</title>
                <style>
                    * {
                        margin: 0;
                        padding: 0;
                        box-sizing: border-box;
                        font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
                    }
                    body {
                        height: 100vh;
                        display: flex;
                        justify-content: center;
                        align-items: center;
                        overflow: hidden;
                        position: relative;
                        margin: 0;
                    }
                    /* 夜间模式(幻境风格) */
                    @media (prefers-color-scheme: dark) {
                        body {
                            background: radial-gradient(ellipse at center, #1a1a3a 0%, #0a0a1a 70%, #000000 100%);
                        }
                        .fog-layer {
                            background: linear-gradient(45deg, rgba(74, 0, 224, 0.1), rgba(0, 210, 255, 0.1));
                            animation: fogFlow 20s infinite linear;
                        }
                        .mist {
                            background: radial-gradient(circle, rgba(74, 0, 224, 0.2) 0%, rgba(74, 0, 224, 0) 70%);
                            filter: blur(30px);
                        }
                        .fragment {
                            border: 1px solid rgba(100, 100, 255, 0.3);
                            box-shadow: 0 0 20px rgba(74, 0, 224, 0.4);
                        }
                        .star-dust {
                            background: #b8b8ff;
                        }
                        .ripple {
                            border: 2px solid rgba(100, 100, 255, 0.2);
                            box-shadow: 0 0 20px rgba(74, 0, 224, 0.3);
                        }
                        .btn-particle {
                            background: #b8b8ff;
                        }
                        h1, .icon, .error-code, .server {
                            background: linear-gradient(135deg, #8e2de2, #4a00e0, #00d2ff);
                            -webkit-background-clip: text;
                            background-clip: text;
                            color: transparent;
                            text-shadow: 0 0 15px rgba(74, 0, 224, 0.5);
                        }
                        p {
                            color: #b8b8ff;
                            text-shadow: 0 0 10px rgba(74, 0, 224, 0.3);
                        }
                        .btn {
                            background: linear-gradient(135deg, #4a00e0, #8e2de2);
                            box-shadow: 0 4px 15px rgba(74, 0, 224, 0.4);
                        }
                        .btn:hover {
                            box-shadow: 0 8px 20px rgba(74, 0, 224, 0.6);
                        }
                    }
                    /* 白天模式(幻境风格) */
                    @media (prefers-color-scheme: light) {
                        body {
                            background: radial-gradient(ellipse at center, #e6e6fa 0%, #f0f0ff 70%, #ffffff 100%);
                        }
                        .fog-layer {
                            background: linear-gradient(45deg, rgba(79, 209, 197, 0.1), rgba(246, 224, 94, 0.1));
                            animation: fogFlow 20s infinite linear;
                        }
                        .mist {
                            background: radial-gradient(circle, rgba(246, 224, 94, 0.3) 0%, rgba(246, 224, 94, 0) 70%);
                            filter: blur(25px);
                        }
                        .fragment {
                            border: 1px solid rgba(79, 209, 197, 0.3);
                            box-shadow: 0 0 20px rgba(246, 224, 94, 0.4);
                        }
                        .star-dust {
                            background: #f6e05e;
                        }
                        .ripple {
                            border: 2px solid rgba(79, 209, 197, 0.2);
                            box-shadow: 0 0 20px rgba(246, 224, 94, 0.3);
                        }
                        .btn-particle {
                            background: #f6e05e;
                        }
                        h1, .icon, .error-code, .server {
                            background: linear-gradient(135deg, #4fd1c5, #f6e05e, #63b3ed);
                            -webkit-background-clip: text;
                            background-clip: text;
                            color: transparent;
                            text-shadow: 0 0 15px rgba(246, 224, 94, 0.5);
                        }
                        p {
                            color: #2d3748;
                            text-shadow: 0 0 10px rgba(246, 224, 94, 0.3);
                        }
                        .btn {
                            background: linear-gradient(135deg, #4fd1c5, #f6e05e);
                            box-shadow: 0 4px 15px rgba(79, 209, 197, 0.3);
                        }
                        .btn:hover {
                            box-shadow: 0 8px 20px rgba(79, 209, 197, 0.5);
                        }
                    }
                    /* 幻境元素 */
                    .fog-layer {
                        position: absolute;
                        width: 200%;
                        height: 200%;
                        top: -50%;
                        left: -50%;
                        opacity: 0.3;
                        z-index: 0;
                    }
                    .mist {
                        position: absolute;
                        width: 200px;
                        height: 200px;
                        border-radius: 50%;
                        animation: float 12s infinite ease-in-out;
                        opacity: 0.5;
                        z-index: 1;
                    }
                    .mist:nth-child(2) {
                        top: 20%;
                        left: 30%;
                        animation-delay: 0s;
                    }
                    .mist:nth-child(3) {
                        top: 50%;
                        left: 70%;
                        width: 150px;
                        height: 150px;
                        animation-delay: 4s;
                    }
                    .mist:nth-child(4) {
                        top: 80%;
                        left: 40%;
                        width: 180px;
                        height: 180px;
                        animation-delay: 8s;
                    }
                    .fragment {
                        position: absolute;
                        background: transparent;
                        opacity: 0.6;
                        animation: float 15s infinite ease-in-out, rotate 10s infinite linear;
                        z-index: 2;
                    }
                    .fragment.triangle {
                        width: 0;
                        height: 0;
                        border-left: 20px solid transparent;
                        border-right: 20px solid transparent;
                        border-bottom: 35px solid rgba(255, 255, 255, 0.2);
                    }
                    .fragment.pentagon {
                        width: 30px;
                        height: 30px;
                        clip-path: polygon(50% 0%, 100% 38%, 82% 100%, 18% 100%, 0% 38%);
                        background: rgba(255, 255, 255, 0.2);
                    }
                    .star-dust {
                        position: absolute;
                        width: 2px;
                        height: 2px;
                        border-radius: 50%;
                        animation: drift 6s infinite ease-in-out;
                        animation-delay: calc(var(--delay) * 1s);
                    }
                    .ripple {
                        position: absolute;
                        width: 100px;
                        height: 100px;
                        border-radius: 50%;
                        opacity: 0;
                        animation: ripple 5s infinite ease-out;
                        z-index: 1;
                    }
                    .ripple:nth-child(2) { animation-delay: 0s; }
                    .ripple:nth-child(3) { animation-delay: 1.5s; }
                    .ripple:nth-child(4) { animation-delay: 3s; }
                    .btn-particle {
                        position: absolute;
                        width: 3px;
                        height: 3px;
                        border-radius: 50%;
                        animation: orbit 4s infinite ease-in-out;
                        z-index: 3;
                    }
                    .content {
                        position: relative;
                        z-index: 3;
                        text-align: center;
                        animation: fadeIn 1s ease-out;
                    }
                    .icon-wrapper {
                        position: relative;
                        display: inline-block;
                    }
                    .error-code, .server {
                        font-size: 18px;
                        margin: 8px 0;
                        animation: float 6s infinite ease-in-out;
                    }
                    .server {
                        font-size: 14px;
                    }
                    h1 {
                        font-size: 28px;
                        font-weight: 600;
                        margin: 0 0 12px;
                        animation: gradientShift 8s ease infinite;
                        background-size: 200% 200%;
                    }
                    p {
                        font-size: 16px;
                        line-height: 1.5;
                        margin: 0 0 20px;
                    }
                    .btn-wrapper {
                        position: relative;
                        display: inline-block;
                    }
                    .btn {
                        padding: 10px 24px;
                        font-size: 14px;
                        font-weight: 500;
                        color: #ffffff;
                        border: none;
                        border-radius: 30px;
                        cursor: pointer;
                        transition: all 0.3s ease;
                        animation: pulse 2s infinite;
                    }
                    .btn:hover {
                        transform: translateY(-3px);
                    }
                    .icon {
                        font-size: 48px;
                        margin-bottom: 16px;
                        animation: breathe 3s infinite ease-in-out;
                    }
                    @keyframes fogFlow {
                        0% { transform: translateX(0); }
                        100% { transform: translateX(-50%); }
                    }
                    @keyframes float {
                        0% { transform: translate(0, 0); }
                        33% { transform: translate(5px, 10px); }
                        66% { transform: translate(-5px, -10px); }
                        100% { transform: translate(0, 0); }
                    }
                    @keyframes rotate {
                        0% { transform: rotate(0deg); }
                        100% { transform: rotate(360deg); }
                    }
                    @keyframes drift {
                        0% { transform: translate(0, 0); opacity: 0.3; }
                        50% { transform: translate(20px, -10px); opacity: 1; }
                        100% { transform: translate(0, 0); opacity: 0.3; }
                    }
                    @keyframes ripple {
                        0% { width: 100px; height: 100px; opacity: 0.5; transform: translate(-50%, -50%); }
                        100% { width: 300px; height: 300px; opacity: 0; transform: translate(-50%, -50%); }
                    }
                    @keyframes orbit {
                        0% { transform: translate(0, 0); opacity: 0.5; }
                        50% { transform: translate(15px, 10px); opacity: 1; }
                        100% { transform: translate(0, 0); opacity: 0.5; }
                    }
                    @keyframes fadeIn {
                        from { opacity: 0; transform: translateY(20px); }
                        to { opacity: 1; transform: translateY(0); }
                    }
                    @keyframes breathe {
                        0% { opacity: 0.7; transform: scale(1); }
                        50% { opacity: 1; transform: scale(1.2); }
                        100% { opacity: 0.7; transform: scale(1); }
                    }
                    @keyframes pulse {
                        0% { transform: scale(1); }
                        50% { transform: scale(1.05); }
                        100% { transform: scale(1); }
                    }
                    @keyframes gradientShift {
                        0% { background-position: 0% 50%; }
                        50% { background-position: 100% 50%; }
                        100% { background-position: 0% 50%; }
                    }
                    @media (max-width: 600px) {
                        h1 {
                            font-size: 24px;
                        }
                        p {
                            font-size: 14px;
                        }
                        .btn {
                            padding: 8px 20px;
                            font-size: 13px;
                        }
                        .icon {
                            font-size: 40px;
                        }
                        .error-code {
                            font-size: 16px;
                        }
                        .server {
                            font-size: 12px;
                        }
                        .fragment.triangle {
                            border-left: 15px solid transparent;
                            border-right: 15px solid transparent;
                            border-bottom: 25px solid rgba(255, 255, 255, 0.2);
                        }
                        .fragment.pentagon {
                            width: 20px;
                            height: 20px;
                        }
                        .ripple {
                            width: 80px;
                            height: 80px;
                        }
                        @keyframes ripple {
                            0% { width: 80px; height: 80px; opacity: 0.5; transform: translate(-50%, -50%); }
                            100% { width: 200px; height: 200px; opacity: 0; transform: translate(-50%, -50%); }
                        }
                    }
                </style>
            </head>
            <body>
                <!-- 流动迷雾层 -->
                <div class="fog-layer"></div>
                <!-- 迷雾效果 -->
                <div class="mist"></div>
                <div class="mist"></div>
                <div class="mist"></div>
                <!-- 幻境碎片 -->
                <div class="fragment triangle" style="top: 15%; left: 20%; animation-delay: 0s;"></div>
                <div class="fragment pentagon" style="top: 25%; left: 80%; animation-delay: 2s;"></div>
                <div class="fragment triangle" style="top: 70%; left: 30%; animation-delay: 4s;"></div>
                <div class="fragment pentagon" style="top: 60%; left: 85%; animation-delay: 6s;"></div>
                <div class="fragment triangle" style="top: 40%; left: 10%; animation-delay: 8s;"></div>
                <div class="fragment pentagon" style="top: 20%; left: 50%; animation-delay: 10s;"></div>
                <div class="fragment triangle" style="top: 80%; left: 70%; animation-delay: 12s;"></div>
                <!-- 中心涟漪 -->
                <div class="ripple" style="top: 50%; left: 50%;"></div>
                <div class="ripple" style="top: 50%; left: 50%;"></div>
                <div class="ripple" style="top: 50%; left: 50%;"></div>
                <!-- 中心内容 -->
                <div class="content">
                    <div class="icon-wrapper">
                        <div class="icon">✨</div>
                        <div class="btn-particle" style="animation-delay: 0s;"></div>
                        <div class="btn-particle" style="animation-delay: 1s;"></div>
                        <div class="btn-particle" style="animation-delay: 2s;"></div>
                    </div>
                    <h1>迷失幻境</h1>
                    <div class="error-code">${errorCode}</div>
                    <div class="server">${server}</div>
                    <p>路径已断,迷雾笼罩,尝试返回现实吧。</p>
                    <div class="btn-wrapper">
                        <button class="btn" onclick="history.back()">返回现实</button>
                        <div class="btn-particle" style="animation-delay: 0s;"></div>
                        <div class="btn-particle" style="animation-delay: 1s;"></div>
                        <div class="btn-particle" style="animation-delay: 2s;"></div>
                    </div>
                </div>
                <script>
                    // 随机星尘粒子
                    function addStarDust() {
                        for (let i = 0; i < 50; i++) {
                            const dust = document.createElement('div');
                            dust.className = 'star-dust';
                            dust.style.left = Math.random() * 100 + '%';
                            dust.style.top = Math.random() * 100 + '%';
                            dust.style.setProperty('--delay', Math.random() * 4);
                            document.body.appendChild(dust);
                        }
                    }
                    addStarDust();
                    // 监听主题切换
                    window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
                        document.querySelectorAll('.star-dust').forEach(dust => dust.remove());
                        addStarDust();
                    });
                </script>
            </body>
            </html>
        `;
    }

    // 替换网络连接失败页面(科幻风格,生命美学日间模式)
    function replaceConnectionErrorPage(errorUrl) {
        document.documentElement.innerHTML = `
            <!DOCTYPE html>
            <html lang="zh-CN">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>连接中断</title>
                <style>
                    * {
                        margin: 0;
                        padding: 0;
                        box-sizing: border-box;
                        font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
                    }
                    body {
                        height: 100vh;
                        display: flex;
                        justify-content: center;
                        align-items: center;
                        color: #e0e0ff;
                        overflow: hidden;
                        position: relative;
                        margin: 0;
                    }
                    /* 夜间模式(科幻风格) */
                    @media (prefers-color-scheme: dark) {
                        body {
                            background: radial-gradient(ellipse at center, #1a1a3a 0%, #0a0a1a 70%, #000000 100%);
                        }
                        .stars {
                            position: fixed;
                            top: 0;
                            left: 0;
                            width: 100%;
                            height: 100%;
                            background: transparent url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><circle cx="50" cy="50" r="0.5" fill="white" opacity="0.8"/></svg>') repeat;
                            z-index: 1;
                        }
                        .star {
                            position: absolute;
                            width: 2px;
                            height: 2px;
                            background: white;
                            border-radius: 50%;
                            animation: twinkle 4s infinite;
                            animation-delay: calc(var(--delay) * 1s);
                        }
                        .big-dipper {
                            position: fixed;
                            top: 10%;
                            left: 5%;
                            width: 100px;
                            height: 60px;
                            z-index: 1;
                        }
                        .big-dipper-star {
                            position: absolute;
                            width: 3px;
                            height: 3px;
                            background: #b8b8ff;
                            border-radius: 50%;
                            animation: twinkle 3s infinite;
                        }
                        .big-dipper-star:nth-child(1) { left: 20px; top: 10px; }
                        .big-dipper-star:nth-child(2) { left: 35px; top: 15px; }
                        .big-dipper-star:nth-child(3) { left: 50px; top: 20px; }
                        .big-dipper-star:nth-child(4) { left: 65px; top: 25px; }
                        .big-dipper-star:nth-child(5) { left: 55px; top: 40px; }
                        .big-dipper-star:nth-child(6) { left: 45px; top: 50px; }
                        .big-dipper-star:nth-child(7) { left: 35px; top: 60px; }
                        .tao-flow {
                            background: radial-gradient(circle, rgba(74, 0, 224, 0.3) 0%, rgba(74, 0, 224, 0) 70%);
                            filter: blur(20px);
                        }
                        .container {
                            background: rgba(10, 10, 30, 0.8);
                            backdrop-filter: blur(10px);
                            border: 1px solid rgba(100, 100, 255, 0.2);
                            box-shadow: 0 8px 30px rgba(74, 0, 224, 0.3);
                        }
                        h1, .icon {
                            background: linear-gradient(135deg, #8e2de2, #4a00e0, #00d2ff);
                            -webkit-background-clip: text;
                            background-clip: text;
                            color: transparent;
                        }
                        p {
                            color: #b8b8ff;
                        }
                        .btn {
                            background: linear-gradient(135deg, #4a00e0, #8e2de2);
                            box-shadow: 0 4px 15px rgba(74, 0, 224, 0.4);
                        }
                        .btn:hover {
                            box-shadow: 0 8px 20px rgba(74, 0, 224, 0.6);
                        }
                        .failed-url {
                            background: rgba(20, 20, 50, 0.5);
                            color: #b8b8ff;
                        }
                        .error-code {
                            color: #8888cc;
                        }
                    }
                    /* 白天模式(生命美学风格,基于 1.8 版本) */
                    @media (prefers-color-scheme: light) {
                        body {
                            background: radial-gradient(ellipse at center, #e8f5e9 0%, #f1f8e9 70%, #ffffff 100%); /* 浅绿到白色,模拟自然光晕 */
                        }
                        .stars {
                            position: fixed;
                            top: 0;
                            left: 0;
                            width: 100%;
                            height: 100%;
                            background: transparent url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><circle cx="50" cy="50" r="0.5" fill="#c8e6c9" opacity="0.4"/></svg>') repeat; /* 淡绿星点 */
                            z-index: 1;
                            animation: twinkle 6s infinite alternate;
                        }
                        .tao-flow {
                            background: radial-gradient(circle, rgba(165, 214, 167, 0.3) 0%, rgba(255, 245, 157, 0) 70%); /* 淡绿到浅金色 */
                            filter: blur(15px);
                        }
                        .tao-flow:nth-child(2) {
                            top: 20%;
                            left: 50%;
                            width: 150px;
                            height: 150px;
                            animation-delay: 3s;
                            transform: translateX(-50%);
                        }
                        .tao-flow:nth-child(3) {
                            top: 50%;
                            left: 50%;
                            width: 180px;
                            height: 180px;
                            animation-delay: 6s;
                            transform: translateX(-50%);
                        }
                        .container {
                            background: rgba(255, 255, 255, 0.85); /* 更柔和的透明效果 */
                            backdrop-filter: blur(12px);
                            border: 1px solid rgba(165, 214, 167, 0.3); /* 淡绿边框 */
                            box-shadow: 0 8px 30px rgba(165, 214, 167, 0.2); /* 淡绿阴影 */
                        }
                        h1, .icon {
                            background: linear-gradient(135deg, #a5d6a7, #fff59d, #aed581); /* 淡绿到浅金色渐变 */
                            -webkit-background-clip: text;
                            background-clip: text;
                            color: transparent;
                        }
                        p {
                            color: #37474f; /* 深灰色文字 */
                        }
                        .btn {
                            background: linear-gradient(135deg, #a5d6a7, #fff59d); /* 淡绿到浅金色按钮 */
                            box-shadow: 0 4px 15px rgba(165, 214, 167, 0.3);
                        }
                        .btn:hover {
                            box-shadow: 0 8px 20px rgba(165, 214, 167, 0.5);
                        }
                        .failed-url {
                            background: rgba(240, 244, 195, 0.5); /* 浅金色背景 */
                            color: #455a64; /* 深灰色文字 */
                        }
                        .error-code {
                            color: #78909c; /* 浅灰色 */
                        }
                    }
                    /* 通用样式(科幻风格) */
                    .tao-flow {
                        position: absolute;
                        width: 200px;
                        height: 200px;
                        border-radius: 50%;
                        animation: float 12s infinite ease-in-out;
                        opacity: 0.6;
                        z-index: 2;
                    }
                    .container {
                        position: absolute;
                        top: 50%;
                        left: 50%;
                        transform: translate(-50%, -50%);
                        z-index: 3;
                        text-align: center;
                        padding: 24px;
                        border-radius: 16px;
                        width: 90%;
                        max-width: 400px;
                        animation: fadeIn 0.6s ease-out;
                    }
                    h1 {
                        font-size: 26px;
                        font-weight: 600;
                        margin: 0 0 12px;
                        animation: gradientShift 8s ease infinite;
                        background-size: 200% 200%;
                    }
                    p {
                        font-size: 15px;
                        line-height: 1.5;
                        margin: 0 0 20px;
                    }
                    .btn {
                        display: inline-block;
                        padding: 10px 24px;
                        font-size: 14px;
                        font-weight: 500;
                        color: #ffffff;
                        border: none;
                        border-radius: 30px;
                        cursor: pointer;
                        transition: all 0.3s ease;
                    }
                    .btn:hover {
                        transform: translateY(-3px);
                    }
                    .failed-url {
                        font-size: 13px;
                        margin: 16px 0;
                        padding: 8px 12px;
                        border-radius: 8px;
                        word-break: break-all;
                    }
                    .error-code {
                        font-size: 12px;
                        margin-top: 12px;
                    }
                    .icon {
                        font-size: 48px;
                        margin-bottom: 16px;
                        animation: pulse 2s infinite;
                    }
                    @keyframes twinkle {
                        0% { opacity: 0.3; }
                        50% { opacity: 1; }
                        100% { opacity: 0.3; }
                    }
                    @keyframes float {
                        0% { transform: translate(0, 0); }
                        33% { transform: translate(30px, 30px); }
                        66% { transform: translate(-30px, -20px); }
                        100% { transform: translate(0, 0); }
                    }
                    @keyframes fadeIn {
                        from { opacity: 0; }
                        to { opacity: 1; }
                    }
                    @keyframes pulse {
                        0% { transform: scale(1); }
                        50% { transform: scale(1.1); }
                        100% { transform: scale(1); }
                    }
                    @keyframes gradientShift {
                        0% { background-position: 0% 50%; }
                        50% { background-position: 100% 50%; }
                        100% { background-position: 0% 50%; }
                    }
                    @media (max-width: 600px) {
                        .container {
                            padding: 16px;
                            width: 90%;
                            max-width: 340px;
                            left: 50%;
                            transform: translate(-50%, -50%);
                        }
                        h1 {
                            font-size: 22px;
                        }
                        p {
                            font-size: 14px;
                        }
                        .btn {
                            padding: 8px 20px;
                            font-size: 13px;
                        }
                        .icon {
                            font-size: 40px;
                        }
                        .big-dipper {
                            width: 80px;
                            height: 48px;
                        }
                    }
                </style>
            </head>
            <body>
                <div class="stars"></div>
                <div class="big-dipper">
                    <div class="big-dipper-star"></div>
                    <div class="big-dipper-star"></div>
                    <div class="big-dipper-star"></div>
                    <div class="big-dipper-star"></div>
                    <div class="big-dipper-star"></div>
                    <div class="big-dipper-star"></div>
                    <div class="big-dipper-star"></div>
                </div>
                <div class="tao-flow"></div>
                <div class="tao-flow"></div>
                <div class="container">
                    <div class="icon">⚡️</div>
                    <h1>连接中断</h1>
                    <p>无法感知星辰脉动,请检查网络或稍后重试。</p>
                    <button class="btn" onclick="window.location.reload()">重新连接</button>
                    <div class="failed-url">目标地址: ${errorUrl}</div>
                    <div class="error-code">错误代码: net::ERR_CONNECTION_ABORTED</div>
                </div>
                <script>
                    // 随机星星闪烁
                    function addRandomStars() {
                        if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
                            for (let i = 0; i < 20; i++) {
                                const star = document.createElement('div');
                                star.className = 'star';
                                star.style.left = Math.random() * 100 + 'vw';
                                star.style.top = Math.random() * 100 + 'vh';
                                star.style.setProperty('--delay', Math.random() * 4);
                                document.body.appendChild(star);
                            }
                        }
                    }
                    addRandomStars();
                    // 监听主题切换
                    window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
                        document.querySelectorAll('.star').forEach(star => star.remove());
                        addRandomStars();
                    });
                </script>
            </body>
            </html>
        `;
    }

    // 快速注入机制
    function initInjection() {
        // 优先检查 404 页面
        if (checkFor404Page()) {
            replace404Page();
            return true;
        }
        // 再检查网络连接失败页面
        if (checkForConnectionErrorPage()) {
            const errorUrl = extractErrorUrl();
            replaceConnectionErrorPage(errorUrl);
            return true;
        }
        return false;
    }

    // 立即检查
    initInjection();

    // 早期高频检查
    let attempts = 0;
    const maxAttempts = 20; // 最多检查 1 秒(50ms x 20)
    const earlyCheckInterval = setInterval(() => {
        if (initInjection()) {
            clearInterval(earlyCheckInterval);
        } else if (attempts >= maxAttempts) {
            clearInterval(earlyCheckInterval);
        }
        attempts++;
    }, 50);

    // 监听 DOM 变化
    const observer = new MutationObserver((mutations, obs) => {
        if (initInjection()) {
            obs.disconnect();
        }
    });

    // 尽早观察 documentElement
    observer.observe(document.documentElement, { childList: true, subtree: true });

    // 页面加载完成时再检查
    document.addEventListener('DOMContentLoaded', () => {
        initInjection();
    }, { once: true });
})();