/* ============================================
   effects.css — 所有视觉特效样式
   ============================================ */

/* ---- Smooth Scroll ---- */
html { scroll-behavior: smooth; }

/* ---- Card Glow ---- */
.card {
    --glow-x: 50%;
    --glow-y: 50%;
}
.card::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: radial-gradient(
        600px circle at var(--glow-x) var(--glow-y),
        rgba(0, 212, 170, 0.06),
        transparent 40%
    );
    opacity: 0;
    transition: opacity 0.3s ease;
    pointer-events: none;
}
.card:hover::after { opacity: 1; }

/* ---- Back to Top ---- */
.back-top {
    position: fixed;
    bottom: 32px;
    right: 16px;
    width: 42px;
    height: 42px;
    background: var(--accent);
    border: none;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #080B12;
    cursor: pointer;
    opacity: 0;
    transform: translateY(12px);
    transition: all 0.3s var(--ease);
    z-index: 100;
    pointer-events: none;
    box-shadow: 0 4px 20px rgba(0, 212, 170, 0.4);
}
.back-top.show {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}
.back-top:hover {
    box-shadow: 0 4px 24px rgba(0, 212, 170, 0.6);
    transform: translateY(-2px);
}

/* ---- Typewriter ---- */
.hero-title .tw-cursor {
    display: inline-block;
    width: 3px;
    height: 0.85em;
    background: var(--accent);
    margin-left: 4px;
    vertical-align: text-bottom;
    animation: tw-blink 0.8s step-end infinite;
}
@keyframes tw-blink {
    50% { opacity: 0; }
}

/* ---- Scroll Reveal ---- */
.reveal {
    opacity: 0;
    transform: translateY(24px);
    transition: opacity 0.5s ease, transform 0.5s ease;
}
.reveal.visible {
    opacity: 1;
    transform: translateY(0);
}

/* ---- Click Ripple ---- */
.click-ripple {
    position: fixed;
    border-radius: 50%;
    background: rgba(0, 212, 170, 0.25);
    transform: scale(0);
    animation: ripple-expand 0.6s ease-out forwards;
    pointer-events: none;
    z-index: 9998;
}
@keyframes ripple-expand {
    to {
        transform: scale(4);
        opacity: 0;
    }
}

/* ---- Star Canvas ---- */
#starCanvas {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 0;
    opacity: 0;
    transition: opacity 0.35s ease;
}

body.app-ready #starCanvas {
    opacity: 1 !important;
}

/* 首屏加载期间不启动装饰层，避免加载页外观中途变化。 */
.effect-canvas {
    opacity: 0 !important;
    transition: opacity 0.35s ease;
}

body.app-ready .effect-canvas {
    opacity: 1 !important;
}

/* ---- CRT Scanlines Overlay ---- */
body::after {
    content: '';
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 9997;
    background: repeating-linear-gradient(
        0deg,
        transparent,
        transparent 2px,
        rgba(0, 212, 170, 0.015) 2px,
        rgba(0, 212, 170, 0.015) 4px
    );
    opacity: 0;
}

body.app-ready::after {
    animation: scanline-flicker 8s ease-in-out infinite;
}
@keyframes scanline-flicker {
    0%, 100% { opacity: 0.6; }
    50% { opacity: 1; }
}

/* ---- Custom Cursor (圆点+光环) ---- */
body { cursor: none; }
a, button, .card, .cat-btn, .back-top, .search-clear,
.mermaid-zoom-btn, .zoom-close, .back-btn, .logo { cursor: none; }

/* 可选文字区域强制显示 I 形光标（优先级高于 .card 的 cursor: none） */
body p, body h1, body h2, body h3, body h4, body h5, body h6,
body li, body blockquote, body td, body th, body label,
body figcaption, body dt, body dd, body code, body span,
body input, body textarea { cursor: text !important; }

.cursor-dot {
    position: fixed;
    top: 0;
    left: 0;
    width: 6px;
    height: 6px;
    background: #00D4AA;
    border-radius: 50%;
    pointer-events: none;
    z-index: 10001;
    transform: translate(-50%, -50%);
    box-shadow: 0 0 8px rgba(0, 212, 170, 0.6);
    transition: width 0.2s, height 0.2s, background 0.2s;
}

.cursor-ring {
    position: fixed;
    top: 0;
    left: 0;
    width: 36px;
    height: 36px;
    border: 1.5px solid rgba(0, 212, 170, 0.4);
    border-radius: 50%;
    pointer-events: none;
    z-index: 10000;
    transform: translate(-50%, -50%);
    transition: width 0.25s ease, height 0.25s ease, border-color 0.25s ease, background 0.25s ease;
}

.cursor-dot.hover {
    width: 14px;
    height: 14px;
    background: #00D4AA;
    box-shadow: 0 0 20px rgba(0, 212, 170, 0.8), 0 0 40px rgba(0, 212, 170, 0.3);
}

.cursor-ring.hover {
    width: 48px;
    height: 48px;
    border-width: 2px;
    border-color: #00D4AA;
    background: rgba(0, 212, 170, 0.12);
    box-shadow: 0 0 20px rgba(0, 212, 170, 0.15), inset 0 0 12px rgba(0, 212, 170, 0.06);
}

/* 文字可选状态：圆点变 I 形光标，光环隐藏 */
.cursor-dot.on-text {
    width: 2px;
    height: 20px;
    border-radius: 1px;
    background: #00D4AA;
    box-shadow: 0 0 6px rgba(0, 212, 170, 0.5), 0 0 2px rgba(0, 212, 170, 0.8);
    animation: cursor-blink 1.2s ease-in-out infinite;
}
.cursor-dot.on-text::before,
.cursor-dot.on-text::after {
    content: '';
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    width: 8px;
    height: 2px;
    background: #00D4AA;
    border-radius: 1px;
    box-shadow: 0 0 4px rgba(0, 212, 170, 0.4);
}
.cursor-dot.on-text::before { top: 0; }
.cursor-dot.on-text::after { bottom: 0; }

.cursor-ring.on-text {
    opacity: 0 !important;
    transition: opacity 0.15s ease;
}

@keyframes cursor-blink {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.4; }
}



/* ---- Skeleton Screen ---- */
@keyframes skeleton-shimmer {
    0% { background-position: -200px 0; }
    100% { background-position: calc(200px + 100%) 0; }
}
.skeleton-line {
    height: 14px;
    border-radius: 4px;
    background: linear-gradient(90deg, var(--border) 25%, var(--border-hover) 37%, var(--border) 63%);
    background-size: 200px 100%;
    animation: skeleton-shimmer 1.5s ease-in-out infinite;
}
.skeleton-tag {
    width: 60px;
    height: 22px;
    border-radius: 100px;
    background: linear-gradient(90deg, var(--border) 25%, var(--border-hover) 37%, var(--border) 63%);
    background-size: 200px 100%;
    animation: skeleton-shimmer 1.5s ease-in-out infinite;
    margin-bottom: 16px;
}
.skeleton-title {
    width: 75%;
    height: 20px;
    margin-bottom: 10px;
}
.skeleton-desc {
    width: 90%;
    margin-bottom: 8px;
}
.skeleton-desc-short {
    width: 55%;
    margin-bottom: 20px;
}
.skeleton-foot {
    width: 30%;
    height: 12px;
}

/* ---- Page Transition ---- */
#app {
    transition: opacity 0.25s ease, transform 0.25s ease;
}
#app.page-exit {
    opacity: 0;
    transform: translateY(8px);
}

/* ---- Anchor Highlight Flash ---- */
@keyframes anchor-flash {
    0% { background-color: rgba(0, 212, 170, 0.15); }
    100% { background-color: transparent; }
}
.anchor-highlight {
    animation: anchor-flash 1.5s ease-out;
    border-radius: 4px;
}

/* ---- 3D Card Tilt ---- */
.card {
    transform-style: preserve-3d;
    will-change: transform;
}



/* ---- Neon Border Flow (霓虹边框跑马灯) ---- */
.card {
    --border-angle: 0deg;
}
.card.neon-hover {
    border-color: transparent;
    background:
        linear-gradient(var(--bg-card), var(--bg-card)) padding-box,
        conic-gradient(from var(--border-angle),
            transparent 0%,
            var(--accent) 10%,
            transparent 20%,
            transparent 50%,
            rgba(0, 212, 170, 0.4) 60%,
            transparent 70%
        ) border-box;
    animation: neon-spin 2s linear infinite;
}
@keyframes neon-spin {
    to { --border-angle: 360deg; }
}
/* 需要 @property 来动画化自定义属性 */
@property --border-angle {
    syntax: '<angle>';
    initial-value: 0deg;
    inherits: false;
}

/* ---- Image Lightbox ---- */
.lightbox-overlay {
    position: fixed;
    inset: 0;
    background: rgba(8, 11, 18, 0.92);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    z-index: 300;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: zoom-out;
    animation: zoomFadeIn 0.25s var(--ease);
}
.lightbox-overlay img {
    max-width: 92vw;
    max-height: 88vh;
    border-radius: var(--r-m);
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}
.md img {
    cursor: zoom-in;
    transition: transform 0.2s ease;
}
.md img:hover {
    transform: scale(1.02);
}



/* ---- Hero Gradient Animation ---- */
@keyframes gradient-flow {
    0%, 100% { background-position: 0% 50%; }
    50% { background-position: 100% 50%; }
}
.hero-title .accent-animated {
    background: linear-gradient(135deg, var(--accent), #00F0C0, #00B4FF, var(--accent));
    background-size: 300% 300%;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    animation: gradient-flow 4s ease infinite;
}

/* ---- Code Block Glow (代码块呼吸光晕) ---- */
.md pre {
    transition: box-shadow 0.4s ease;
}
.md pre:focus-within,
.md pre:hover {
    box-shadow:
        0 0 20px rgba(0, 212, 170, 0.08),
        0 0 40px rgba(0, 212, 170, 0.04);
}

/* ---- Link Underline Draw (链接下划线绘制) ---- */
.md a {
    position: relative;
    border-bottom: none;
}
.md a::after {
    content: '';
    position: absolute;
    bottom: -1px;
    left: 0;
    width: 100%;
    height: 1px;
    background: var(--accent);
    transform: scaleX(0);
    transform-origin: right;
    transition: transform 0.3s ease;
}
.md a:hover::after {
    transform: scaleX(1);
    transform-origin: left;
}

/* ---- Card Border Trace (卡片悬停边框描线) ---- */
.card {
    --trace: 0;
}
.card.trace-hover {
    border-color: transparent;
    background:
        linear-gradient(var(--bg-card), var(--bg-card)) padding-box,
        conic-gradient(
            from calc(var(--trace) * 360deg),
            transparent 0%,
            var(--accent) 4%,
            transparent 12%,
            transparent 100%
        ) border-box;
    animation: card-trace 0.8s ease-in-out forwards;
}
@keyframes card-trace {
    from { --trace: 0; }
    to   { --trace: 1; }
}
@property --trace {
    syntax: '<number>';
    initial-value: 0;
    inherits: false;
}

/* ---- Reading Rail (阅读进度侧边指示器) ---- */
.reading-rail {
    position: fixed;
    left: 24px;
    top: 120px;
    bottom: 80px;
    width: 3px;
    background: var(--border);
    border-radius: 2px;
    z-index: 100;
    opacity: 0;
    transition: opacity 0.3s ease;
    pointer-events: none;
}
.reading-rail.show { opacity: 1; }
.reading-rail-dot {
    position: absolute;
    top: 0;
    left: -3px;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 8px rgba(0, 212, 170, 0.6), 0 0 16px rgba(0, 212, 170, 0.2);
    transition: top 80ms linear;
}
@media (max-width: 1024px) {
    .reading-rail { display: none; }
}

/* ---- Touch Device: restore native cursor & disable mouse-only effects ---- */
@media (hover: none) {
    body, body * { cursor: auto !important; }
    .cursor-dot, .cursor-ring { display: none !important; }

    .card:hover::after { opacity: 0; }
    .md a:hover::after { transform: scaleX(0); }
    .md img:hover { transform: none; }
    .card.neon-hover { animation: none; border-color: var(--border); background: var(--bg-card); }
    .card.trace-hover { animation: none; border-color: var(--border); background: var(--bg-card); }

    /* Disable CRT scanlines on touch devices */
    body::after { display: none; }
}

@media (max-width: 640px) {
    .back-top { bottom: 20px; right: 16px; }
}

/* ---- Card Stagger Exit ---- */
.card.card-exit {
    opacity: 0;
    transform: translateY(-10px) scale(0.97);
    transition: opacity 0.18s ease, transform 0.18s ease;
}
