/* ============================================================
   摄影师博客 · 特效库
   背景 / 光标 / 边框 / 文字 / 图片 / 滚动 六大类
   由主题 manifest 指定启用哪些特效，元素挂对应 class 即可生效
   ============================================================ */

/* ---------- 通用：性能与降级 ---------- */
.fx-canvas{position:fixed;inset:0;z-index:0;pointer-events:none}
.fx-layer{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
body.fx-on > *:not(.fx-layer):not(.fx-canvas):not(.site-header):not(.tab-bar):not(.cur-el):not(.cur-el-dot):not(.cur-el-ring){position:relative;z-index:1}
@media (prefers-reduced-motion:reduce){.fx-canvas,.fx-layer{display:none}}

/* ============ 一、背景特效 ============ */

/* 极光流动（CSS 光斑） */
.fx-aurora::before{
  content:"";position:fixed;inset:-20%;z-index:-2;pointer-events:none;
  background:
    radial-gradient(38% 32% at 22% 28%, color-mix(in srgb,var(--primary) 34%,transparent), transparent 70%),
    radial-gradient(32% 30% at 78% 22%, color-mix(in srgb,var(--accent) 32%,transparent), transparent 70%),
    radial-gradient(40% 36% at 62% 78%, color-mix(in srgb,var(--primary) 22%,transparent), transparent 72%);
  filter:blur(34px);animation:auroraMove 22s ease-in-out infinite alternate;
}
@keyframes auroraMove{
  0%{transform:translate3d(-2%,-1%,0) rotate(0deg) scale(1)}
  50%{transform:translate3d(3%,2%,0) rotate(4deg) scale(1.06)}
  100%{transform:translate3d(-1%,3%,0) rotate(-3deg) scale(1.02)}
}

/* 流动渐变 */
.fx-flow::before{
  content:"";position:fixed;inset:-40% 0 0 0;z-index:-2;pointer-events:none;
  background:linear-gradient(115deg,
    color-mix(in srgb,var(--primary) 30%,transparent),
    color-mix(in srgb,var(--accent) 26%,transparent),
    color-mix(in srgb,var(--primary) 22%,transparent),
    color-mix(in srgb,var(--accent) 30%,transparent));
  background-size:320% 320%;animation:flowShift 18s ease-in-out infinite;filter:blur(30px);
}
@keyframes flowShift{0%{background-position:0% 50%}50%{background-position:100% 50%}100%{background-position:0% 50%}}

/* 光斑漂浮（bokeh） */
.fx-bokeh::before{
  content:"";position:fixed;inset:0;z-index:-2;pointer-events:none;overflow:hidden;
  background:radial-gradient(14% 14% at 15% 20%,color-mix(in srgb,var(--primary) 30%,transparent),transparent 70%),
    radial-gradient(10% 10% at 82% 16%,color-mix(in srgb,var(--accent) 34%,transparent),transparent 70%),
    radial-gradient(18% 18% at 24% 76%,color-mix(in srgb,var(--accent) 22%,transparent),transparent 70%),
    radial-gradient(12% 12% at 70% 82%,color-mix(in srgb,var(--primary) 26%,transparent),transparent 70%),
    radial-gradient(8% 8% at 48% 44%,color-mix(in srgb,var(--primary) 18%,transparent),transparent 70%);
  animation:bokehDrift 26s ease-in-out infinite alternate;
}
@keyframes bokehDrift{from{transform:scale(1) translate(0,0)}to{transform:scale(1.12) translate(-2%,3%)}}

/* 透视网格 */
.fx-grid::before{
  content:"";position:fixed;inset:-60% -30%;z-index:-2;pointer-events:none;
  background-image:
    linear-gradient(color-mix(in srgb,var(--primary) 14%,transparent) 1px,transparent 1px),
    linear-gradient(90deg,color-mix(in srgb,var(--primary) 14%,transparent) 1px,transparent 1px);
  background-size:44px 44px;
  transform:perspective(600px) rotateX(58deg);
  transform-origin:50% 0;
  animation:gridFlow 30s linear infinite;
  -webkit-mask-image:linear-gradient(to bottom,rgba(0,0,0,.5),transparent 78%);
          mask-image:linear-gradient(to bottom,rgba(0,0,0,.5),transparent 78%);
}
@keyframes gridFlow{to{background-position:0 44px}}

/* 圆点阵列 */
.fx-dots::before{
  content:"";position:fixed;inset:0;z-index:-2;pointer-events:none;
  background-image:radial-gradient(color-mix(in srgb,var(--primary) 26%,transparent) 1.4px,transparent 1.4px);
  background-size:26px 26px;opacity:.5;
  -webkit-mask-image:radial-gradient(70% 60% at 50% 30%,#000,transparent 75%);
          mask-image:radial-gradient(70% 60% at 50% 30%,#000,transparent 75%);
}

/* 胶片颗粒（噪点） */
.fx-grain::after{
  content:"";position:fixed;inset:0;z-index:999;pointer-events:none;opacity:.05;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation:grainShift .5s steps(4) infinite;
}
@keyframes grainShift{0%{transform:translate(0,0)}25%{transform:translate(-2%,2%)}50%{transform:translate(2%,-1%)}75%{transform:translate(-1%,-2%)}100%{transform:translate(0,0)}}

/* 光线（缓慢旋转的射线） */
.fx-lightrays::before{
  content:"";position:fixed;top:-80%;left:50%;width:180vmax;height:180vmax;z-index:-2;pointer-events:none;
  transform:translateX(-50%);
  background:repeating-conic-gradient(from 0deg,
    color-mix(in srgb,var(--primary) 7%,transparent) 0deg 6deg,
    transparent 6deg 24deg);
  animation:raysSpin 90s linear infinite;
  -webkit-mask-image:radial-gradient(circle at 50% 30%,#000 0%,transparent 62%);
          mask-image:radial-gradient(circle at 50% 30%,#000 0%,transparent 62%);
}
@keyframes raysSpin{to{transform:translateX(-50%) rotate(360deg)}}

/* 玻璃渐变网格 */
.fx-glass::before{
  content:"";position:fixed;inset:0;z-index:-2;pointer-events:none;
  background:
    linear-gradient(120deg,color-mix(in srgb,var(--primary) 16%,transparent),transparent 40%),
    linear-gradient(300deg,color-mix(in srgb,var(--accent) 16%,transparent),transparent 42%),
    color-mix(in srgb,var(--bg) 82%,white);
}

/* 视差远景层（配合 JS） */
.fx-parallax::before{
  content:"";position:fixed;inset:-12%;z-index:-2;pointer-events:none;
  background:
    radial-gradient(30% 26% at 24% 34%, color-mix(in srgb,var(--primary) 20%,transparent),transparent 70%),
    radial-gradient(26% 30% at 76% 26%, color-mix(in srgb,var(--accent) 18%,transparent),transparent 70%);
  filter:blur(20px);will-change:transform;
}

/* 墨色晕染 */
.fx-ink::before{
  content:"";position:fixed;inset:0;z-index:-2;pointer-events:none;
  background:radial-gradient(46% 34% at 28% 22%,color-mix(in srgb,var(--primary) 20%,transparent),transparent 70%),
    radial-gradient(34% 30% at 76% 72%,color-mix(in srgb,var(--accent) 16%,transparent),transparent 72%);
  filter:blur(40px) saturate(1.1);
}

/* 星野 / 雪 / 花瓣 / 尘埃 / 气泡 / 雨 / 萤火 / 极光粒子 —— 由 canvas 绘制（fx-canvas） */
.fx-starry,.fx-snow,.fx-petal,.fx-dust,.fx-bubble,.fx-rain,.fx-firefly,.fx-particle,.fx-balls{position:relative}

/* ============ 二、光标特效 ============ */
.cur-el{position:fixed;top:0;left:0;pointer-events:none;z-index:1000;will-change:transform}

/* 光标光晕 */
.cur-glow .cur-el{width:520px;height:520px;margin:-260px 0 0 -260px;border-radius:50%;
  background:radial-gradient(circle,color-mix(in srgb,var(--primary) 16%,transparent),transparent 60%);
  filter:blur(6px);transition:opacity .3s}

/* 跟随圆点 + 迟滞圆环 */
.cur-dot .cur-el-dot,.cur-dot .cur-el-ring{border-radius:50%;position:fixed;top:0;left:0;pointer-events:none;z-index:1001}
.cur-dot .cur-el-dot{width:7px;height:7px;margin:-3.5px 0 0 -3.5px;background:var(--primary);box-shadow:0 0 10px var(--primary)}
.cur-dot .cur-el-ring{width:34px;height:34px;margin:-17px 0 0 -17px;border:1.6px solid color-mix(in srgb,var(--primary) 70%,transparent);transition:width .25s,height .25s,margin .25s,border-color .25s}
.cur-dot a:hover ~ .cur-el-ring,.cur-dot .cur-el-ring.big{width:52px;height:52px;margin:-26px 0 0 -26px;border-color:var(--primary)}

/* 星尘轨迹（canvas 粒子拖尾） */
.cur-sparkle .cur-el{display:none}

/* 光带拖尾 */
.cur-trail .cur-el{width:150px;height:150px;margin:-75px 0 0 -75px;border-radius:50%;
  background:conic-gradient(from 0deg,var(--primary),var(--accent),transparent 60%,var(--primary));
  filter:blur(26px);opacity:.5;mix-blend-mode:screen}

/* 绽放光斑 */
.cur-bloom .cur-el{width:90px;height:90px;margin:-45px 0 0 -45px;border-radius:50%;
  border:1px solid color-mix(in srgb,var(--primary) 55%,transparent);
  background:radial-gradient(circle,color-mix(in srgb,var(--primary) 26%,transparent),transparent 65%);
  animation:bloomPulse 2.2s ease-in-out infinite}
@keyframes bloomPulse{0%,100%{transform:scale(1);opacity:.85}50%{transform:scale(1.25);opacity:1}}

/* 卡片磁吸（JS） */
.cur-magnet .btn,.cur-magnet .work-card,.cur-magnet .filter-bar a{transition:transform .35s var(--ease)}

/* 聚光边框跟随（JS：卡片边缘亮起） */
.cur-spot .card,.cur-spot .work-card,.cur-spot .panel{position:relative;overflow:hidden}

/* ============ 三、边框特效 ============ */

/* 流动渐变描边 */
.bd-grad{position:relative;border:1px solid transparent !important;background-clip:padding-box !important}
.bd-grad::before{content:"";position:absolute;inset:-1px;z-index:0;border-radius:inherit;padding:1px;
  background:linear-gradient(120deg,var(--primary),var(--accent),var(--primary),var(--accent));
  background-size:300% 300%;animation:bdGradFlow 6s linear infinite;
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;pointer-events:none}
@keyframes bdGradFlow{to{background-position:300% 0}}

/* 霓虹辉光 */
.bd-neon{border-color:transparent !important;box-shadow:0 0 18px color-mix(in srgb,var(--primary) 22%,transparent),inset 0 0 14px color-mix(in srgb,var(--primary) 8%,transparent);
  animation:neonPulse 3.4s ease-in-out infinite}
@keyframes neonPulse{0%,100%{box-shadow:0 0 16px color-mix(in srgb,var(--primary) 20%,transparent),inset 0 0 12px color-mix(in srgb,var(--primary) 7%,transparent)}
  50%{box-shadow:0 0 34px color-mix(in srgb,var(--primary) 40%,transparent),inset 0 0 20px color-mix(in srgb,var(--primary) 13%,transparent)}}

/* 四角括号 */
.bd-corners{position:relative}
.bd-corners::before,.bd-corners::after{content:"";position:absolute;width:26px;height:26px;transition:.4s var(--ease);z-index:2;pointer-events:none}
.bd-corners::before{top:10px;left:10px;border-top:2px solid var(--primary);border-left:2px solid var(--primary);border-top-left-radius:8px}
.bd-corners::after{bottom:10px;right:10px;border-bottom:2px solid var(--primary);border-right:2px solid var(--primary);border-bottom-right-radius:8px}
.bd-corners:hover::before{width:38px;height:38px}
.bd-corners:hover::after{width:38px;height:38px}

/* 流动虚线（行军蚁） */
.bd-dash{border:1px dashed color-mix(in srgb,var(--primary) 55%,transparent) !important;
  animation:bdDash 1.2s linear infinite}
@keyframes bdDash{to{outline:1px dashed transparent;outline-offset:0}}

/* 双层边框 */
.bd-dual{position:relative;box-shadow:0 0 0 1px color-mix(in srgb,var(--primary) 34%,transparent),0 0 0 6px color-mix(in srgb,var(--bg2) 70%,transparent),0 0 0 7px color-mix(in srgb,var(--primary) 26%,transparent),var(--shadow);transition:.4s}
.bd-dual:hover{box-shadow:0 0 0 1px var(--primary),0 0 0 9px color-mix(in srgb,var(--bg2) 60%,transparent),0 0 0 10px var(--primary),var(--shadow-lg)}

/* 光扫描过边框 */
.bd-shine{position:relative;overflow:hidden}
.bd-shine::before{content:"";position:absolute;top:-40%;left:-60%;width:44%;height:180%;transform:rotate(22deg);
  background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--primary) 26%,transparent),transparent);
  transition:left .85s var(--ease)}
.bd-shine:hover::before{left:130%}

/* 外光晕 */
.bd-halo{box-shadow:0 0 0 1px var(--line),0 0 26px color-mix(in srgb,var(--primary) 16%,transparent),0 0 60px color-mix(in srgb,var(--accent) 10%,transparent)}

/* 切割像素角 */
.bd-pixel{clip-path:polygon(0 8px,8px 8px,8px 0,calc(100% - 8px) 0,calc(100% - 8px) 8px,100% 8px,100% calc(100% - 8px),calc(100% - 8px) calc(100% - 8px),calc(100% - 8px) 100%,8px 100%,8px calc(100% - 8px),0 calc(100% - 8px));transition:clip-path .4s}
.bd-pixel:hover{clip-path:polygon(0 0,100% 0,100% 0,100% 0,100% 0,100% 0,100% 100%,100% 100%,100% 100%,0 100%,0 100%,0 100%)}

/* 手绘波浪边框 */
.bd-hand{border-radius:255px 18px 225px 18px / 18px 225px 18px 255px !important;border-width:2px !important}
.bd-hand:hover{border-radius:18px 225px 18px 255px / 255px 18px 225px 18px}

/* 3D 悬浮倾斜（JS 增强） */
.bd-tilt{transform-style:preserve-3d;will-change:transform}

/* 玻璃反光 */
.bd-glare{position:relative;overflow:hidden}
.bd-glare::after{content:"";position:absolute;inset:0;background:linear-gradient(115deg,transparent 30%,color-mix(in srgb,#fff 14%,transparent) 46%,transparent 62%);
  transform:translateX(-120%);transition:transform .9s var(--ease)}
.bd-glare:hover::after{transform:translateX(120%)}

/* ============ 四、文字特效 ============ */

/* 流动渐变文字 */
.tx-gradient{background:linear-gradient(92deg,var(--primary),var(--accent),var(--primary));background-size:240% 100%;
  -webkit-background-clip:text;background-clip:text;color:transparent;animation:txGradFlow 7s linear infinite}
@keyframes txGradFlow{to{background-position:240% 0}}

/* 霓虹文字 */
.tx-neon{color:var(--primary);text-shadow:0 0 8px color-mix(in srgb,var(--primary) 55%,transparent),0 0 26px color-mix(in srgb,var(--primary) 34%,transparent),0 0 60px color-mix(in srgb,var(--primary) 18%,transparent);
  animation:neonFlicker 4s linear infinite}
@keyframes neonFlicker{0%,100%{opacity:1}92%{opacity:1}93%{opacity:.72}94%{opacity:1}97%{opacity:.86}98%{opacity:1}}

/* 字距舒展 */
.tx-spacing{transition:letter-spacing .5s var(--ease)}
.tx-spacing:hover{letter-spacing:.18em}

/* 波浪文字（JS 拆分字符） */
.tx-wave .ch{display:inline-block;animation:txWave 2.4s ease-in-out infinite}
@keyframes txWave{0%,100%{transform:translateY(0)}35%{transform:translateY(-.16em)}}

/* 逐字上升（JS 拆分字符） */
.tx-rise .ch{display:inline-block;opacity:0;transform:translateY(1em);animation:txRise .7s var(--ease) forwards}
@keyframes txRise{to{opacity:1;transform:translateY(0)}}

/* 镂空描边文字 */
.tx-stroke{color:transparent;-webkit-text-stroke:1.2px color-mix(in srgb,var(--primary) 82%,var(--ink));
  transition:-webkit-text-stroke .4s,color .4s}
.tx-stroke:hover{color:var(--primary);-webkit-text-stroke:1.2px transparent}

/* 玻璃文字 */
.tx-glass{color:rgba(255,255,255,.92);text-shadow:0 2px 22px rgba(0,0,0,.35);font-weight:700}
.tx-glass-dark{color:color-mix(in srgb,var(--ink) 78%,transparent);text-shadow:0 1px 12px color-mix(in srgb,var(--card) 70%,transparent)}

/* 闪光扫过文字 */
.tx-shine{position:relative;overflow:hidden}
.tx-shine::after{content:"";position:absolute;top:0;bottom:0;width:38%;
  background:linear-gradient(90deg,transparent,color-mix(in srgb,#fff 70%,transparent),transparent);
  transform:skewX(-18deg);left:-60%;animation:txShine 3.4s ease-in-out infinite}
@keyframes txShine{0%,60%{left:-60%}100%{left:130%}}

/* 剪辑浮现 */
.tx-clip{clip-path:inset(0 100% 0 0);animation:txClip 1.4s var(--ease) forwards}
@keyframes txClip{to{clip-path:inset(0 0 0 0)}}

/* 打字机（JS） */
.tx-typewriter{border-right:2px solid var(--primary);animation:caretBlink .8s step-end infinite}
@keyframes caretBlink{50%{border-color:transparent}}

/* ============ 五、图片特效 ============ */

/* 灰度 → 彩色 */
.im-gray{filter:grayscale(1);transition:filter .8s var(--ease)}
.im-gray:hover{filter:grayscale(0)}

/* 缩放 + 微旋 */
.im-zoom{transition:transform 1.1s var(--ease)}
.im-zoom:hover{transform:scale(1.1) rotate(1.6deg)}

/* 光扫过图片 */
.im-shine{position:relative;overflow:hidden}
.im-shine::after{content:"";position:absolute;inset:-20%;transform:translateX(-130%) skewX(-18deg);
  background:linear-gradient(90deg,transparent,color-mix(in srgb,#fff 34%,transparent),transparent);
  transition:transform .9s var(--ease)}
.im-shine:hover::after{transform:translateX(130%) skewX(-18deg)}

/* 双色调 */
.im-duotone{filter:saturate(.4) contrast(1.12) sepia(.28) hue-rotate(8deg);transition:filter .7s var(--ease)}
.im-duotone:hover{filter:saturate(1.05) contrast(1) sepia(0) hue-rotate(0)}

/* 内框生长 */
.im-frame{position:relative}
.im-frame::after{content:"";position:absolute;inset:14px;border:1px solid color-mix(in srgb,#fff 62%,transparent);
  opacity:0;transform:scale(1.06);transition:.5s var(--ease);pointer-events:none;z-index:2}
.im-frame:hover::after{opacity:1;transform:scale(1)}

/* 胶片颗粒覆盖 */
.im-grain{position:relative}
.im-grain::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;opacity:.14;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}

/* 擦除揭示 */
.im-wipe{position:relative}
.im-wipe::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:var(--bg);clip-path:circle(0 at 50% 50%);transition:clip-path .8s var(--ease)}
.im-wipe:hover::after{clip-path:circle(140% at 50% 50%)}

/* 中心聚焦 */
.im-focus{transition:filter .6s var(--ease)}
.im-focus:hover{filter:saturate(1.25) contrast(1.08)}
.im-focus::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;opacity:0;transition:.5s;
  background:radial-gradient(circle at 50% 50%,transparent 34%,color-mix(in srgb,var(--deep) 40%,transparent) 100%)}
.im-focus:hover::after{opacity:1}

/* 聚光灯跟随（JS） */
.im-spot{position:relative;overflow:hidden}
.im-spot::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:radial-gradient(150px circle at var(--mx,50%) var(--my,50%),transparent 20%,color-mix(in srgb,var(--deep) 55%,transparent) 100%);
  opacity:0;transition:opacity .4s}
.im-spot:hover::after{opacity:1}

/* 色相漂移 */
.im-hue{transition:filter .7s var(--ease)}
.im-hue:hover{filter:hue-rotate(32deg) saturate(1.2)}

/* ============ 六、滚动显现 ============ */
.rv{opacity:0;transition:opacity .9s var(--ease),transform .9s var(--ease),filter .9s var(--ease);will-change:transform,opacity,filter}
.rv.in{opacity:1;transform:none;filter:none}
.rv-up{transform:translateY(44px)}
.rv-fade{transform:none}
.rv-left{transform:translateX(-48px)}
.rv-right{transform:translateX(48px)}
.rv-zoom{transform:scale(.86)}
.rv-rotate{transform:rotate(4deg) translateY(30px)}
.rv-blur{filter:blur(14px);transform:translateY(26px)}
.rv-clip{clip-path:inset(0 100% 0 0);opacity:1;transform:none;transition:clip-path 1.1s var(--ease)}
.rv-clip.in{clip-path:inset(0 0 0 0)}

/* ---------- 装饰小工具 ---------- */
.float-slow{animation:floatY3 7s ease-in-out infinite}
@keyframes floatY3{0%,100%{transform:translateY(0)}50%{transform:translateY(-14px)}}
.spin-slow{animation:raysSpin 26s linear infinite}
.glass{background:color-mix(in srgb,var(--card) 55%,transparent);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px)}
.grad-line{height:2px;border:0;background:linear-gradient(90deg,transparent,var(--primary),var(--accent),transparent);margin:0}
.deco-ring{position:absolute;border:1px solid color-mix(in srgb,var(--primary) 30%,transparent);border-radius:50%;pointer-events:none}
