/* ==========================================================================
   fx.css · 纯 CSS 特效预设库

   与 config.js 的注册表一一对应：
     炫光 body.glow-*   · 11 套 + off
     质感 body.tex-*    · 11 套 + off
     动态 body.mo-*     · 10 套 + off
     排版 body.layout-* · 10 套
     字体 body.font-*   · 10 套

   新增一套方案 = config.js 加一条记录 + 本文件加一个规则块。
   面板会自动出现新选项，不需要改 JS。
   ========================================================================== */

/* ==========================================================================
   1. 炫光 · GLOW
   ========================================================================== */

.fx-glow {
	display: none;
}

body[class*='glow-'] .fx-glow {
	display: block;
}

body.glow-off .fx-glow {
	display: none;
}

/* 01 Ambient · 三色柔光缓慢漂移 */
body.glow-ambient .fx-glow {
	background:
		radial-gradient(46rem 30rem at 12% 8%, var(--amb-1), transparent 62%),
		radial-gradient(38rem 26rem at 88% 14%, var(--amb-2), transparent 60%),
		radial-gradient(44rem 32rem at 50% 96%, var(--amb-3), transparent 64%);
	animation: ambienceDrift 26s var(--ease-soft) infinite alternate;
}

/* 02 Sheen · 面板表面周期扫光 */
body.glow-sheen .fx-glow {
	background: radial-gradient(40rem 28rem at 20% 10%, var(--amb-1), transparent 60%);
}
body.glow-sheen .panel::after,
body.glow-sheen .spec-card::after {
	content: '';
	position: absolute;
	inset: 0;
	border-radius: inherit;
	pointer-events: none;
	background: linear-gradient(
		105deg,
		transparent 30%,
		var(--sheen) 45%,
		transparent 60%
	);
	background-size: 280% 100%;
	opacity: 0.32;
	animation: shimmer 7s linear infinite;
}

/* 03 Neon · 霓虹描边 */
body.glow-neon .fx-glow {
	background: radial-gradient(50rem 34rem at 50% 0%, var(--amb-2), transparent 66%);
}
body.glow-neon .panel,
body.glow-neon .spec-card,
body.glow-neon .stat-card {
	border-color: color-mix(in srgb, var(--c-cyan) 42%, transparent);
	box-shadow:
		0 0 0 1px color-mix(in srgb, var(--c-violet) 26%, transparent),
		0 0 34px -14px var(--c-cyan),
		0 18px 50px -30px rgba(0, 0, 0, 0.9);
}
body.glow-neon .panel-index,
body.glow-neon .stat-number {
	text-shadow: 0 0 14px color-mix(in srgb, var(--c-cyan) 65%, transparent);
}

/* 04 Breathe · 呼吸辉光 */
body.glow-breathe .fx-glow {
	background:
		radial-gradient(42rem 30rem at 24% 16%, var(--amb-1), transparent 60%),
		radial-gradient(42rem 30rem at 76% 82%, var(--amb-3), transparent 60%);
	animation: fxBreathe 7s var(--ease-soft) infinite;
}
@keyframes fxBreathe {
	0%,
	100% {
		opacity: 0.5;
		transform: scale(1);
	}
	50% {
		opacity: 1;
		transform: scale(1.08);
	}
}

/* 05 Chroma · 色散重影 */
body.glow-chroma .fx-glow {
	background: radial-gradient(46rem 30rem at 50% 6%, var(--amb-2), transparent 64%);
}
body.glow-chroma .display-title,
body.glow-chroma .stat-number,
body.glow-chroma .brand-word {
	text-shadow:
		-2px 0 0 color-mix(in srgb, var(--c-cyan) 55%, transparent),
		2px 0 0 color-mix(in srgb, var(--c-pink) 55%, transparent);
	animation: fxChroma 4.5s steps(1, end) infinite;
}
@keyframes fxChroma {
	0%,
	92%,
	100% {
		transform: translateX(0);
	}
	94% {
		transform: translateX(-1.5px);
	}
	96% {
		transform: translateX(1.5px);
	}
}

/* 06 Flare · 镜头光斑 */
body.glow-flare .fx-glow {
	background:
		radial-gradient(14rem 14rem at 82% 12%, rgba(255, 255, 255, 0.16), transparent 68%),
		radial-gradient(3rem 3rem at 82% 12%, rgba(255, 255, 255, 0.5), transparent 70%),
		linear-gradient(
			118deg,
			transparent 42%,
			color-mix(in srgb, var(--c-cyan) 22%, transparent) 50%,
			transparent 58%
		),
		radial-gradient(40rem 28rem at 18% 84%, var(--amb-3), transparent 62%);
	animation: fxFlare 14s var(--ease-soft) infinite alternate;
}
@keyframes fxFlare {
	0% {
		transform: translate3d(0, 0, 0);
		opacity: 0.8;
	}
	100% {
		transform: translate3d(-3%, 2%, 0);
		opacity: 1;
	}
}

/* 07 Scanline · 扇描扫线 */
body.glow-scanline .fx-glow {
	background: radial-gradient(44rem 30rem at 50% 10%, var(--amb-1), transparent 64%);
	overflow: hidden;
}
body.glow-scanline .fx-glow::after {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	height: 26vh;
	background: linear-gradient(
		to bottom,
		transparent,
		color-mix(in srgb, var(--c-cyan) 16%, transparent) 70%,
		color-mix(in srgb, var(--c-cyan) 42%, transparent)
	);
	animation: fxScan 6.5s linear infinite;
}
@keyframes fxScan {
	0% {
		transform: translateY(-30vh);
	}
	100% {
		transform: translateY(110vh);
	}
}

/* 08 Edge · 边缘泛光 */
body.glow-edge .fx-glow {
	box-shadow:
		inset 0 0 160px -40px var(--c-violet),
		inset 0 0 90px -30px var(--c-cyan);
}

/* 09 Spotlight · 鼠标聚光（--mx / --my 由 effects.js 实时写入） */
body.glow-spotlight .fx-glow {
	background: radial-gradient(
		circle 300px at var(--mx, 50%) var(--my, 40%),
		transparent 0%,
		transparent 42%,
		rgba(0, 0, 0, 0.42) 100%
	);
	transition: background 0.12s linear;
}

/* 10 Halo · 顶部光环 */
body.glow-halo .fx-glow {
	background:
		radial-gradient(60rem 18rem at 50% -4rem, var(--amb-2), transparent 70%),
		radial-gradient(30rem 12rem at 50% -1rem, rgba(255, 255, 255, 0.12), transparent 70%);
}

/* 11 Rim · 内描边高光 */
body.glow-rim .fx-glow {
	background: radial-gradient(42rem 28rem at 78% 90%, var(--amb-3), transparent 62%);
}
body.glow-rim .panel,
body.glow-rim .spec-card,
body.glow-rim .stat-card {
	box-shadow:
		inset 0 1px 0 rgba(255, 255, 255, 0.16),
		inset 0 0 44px -22px var(--c-cyan),
		0 22px 60px -40px rgba(0, 0, 0, 0.9);
}

/* ==========================================================================
   2. 质感 · TEXTURE
   ========================================================================== */

.fx-texture {
	display: none;
}

body[class*='tex-'] .fx-texture {
	display: block;
}

body.tex-off .fx-texture {
	display: none;
}

/* 01 Grain · 胶片噪点 */
body.tex-grain .fx-texture {
	background-image: var(--noise-url);
	opacity: var(--grain-opacity);
}

/* 02 Frost · 磨砂玻璃（作用在面板上，不是铺层） */
body.tex-frost .fx-texture {
	background-image: var(--noise-url);
	opacity: calc(var(--grain-opacity) * 0.5);
}
body.tex-frost .panel,
body.tex-frost .spec-card,
body.tex-frost .stat-card,
body.tex-frost .fx-panel {
	-webkit-backdrop-filter: blur(26px) saturate(1.5);
	backdrop-filter: blur(26px) saturate(1.5);
	background-image: linear-gradient(
		150deg,
		rgba(255, 255, 255, 0.1),
		rgba(255, 255, 255, 0.02)
	);
}

/* 03 Grid · 工程网格 */
body.tex-grid .fx-texture {
	background-image:
		linear-gradient(var(--grid-line) 1px, transparent 1px),
		linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
	background-size: 46px 46px;
	opacity: 1;
}

/* 04 Dots · 点阵 */
body.tex-dots .fx-texture {
	background-image: radial-gradient(var(--grid-line) 1.2px, transparent 1.2px);
	background-size: 22px 22px;
	opacity: 1;
}

/* 05 Diagonal · 斜纹 */
body.tex-diagonal .fx-texture {
	background-image: repeating-linear-gradient(
		45deg,
		var(--grid-line) 0 1px,
		transparent 1px 9px
	);
	opacity: 1;
}

/* 06 Circuit · 电路板 */
body.tex-circuit .fx-texture {
	background-image:
		linear-gradient(var(--grid-line) 1px, transparent 1px),
		linear-gradient(90deg, var(--grid-line) 1px, transparent 1px),
		radial-gradient(
			color-mix(in srgb, var(--c-cyan) 22%, transparent) 1.6px,
			transparent 1.6px
		);
	background-size:
		60px 60px,
		60px 60px,
		120px 120px;
	opacity: 1;
}

/* 07 Paper · 纹理纸 */
body.tex-paper .fx-texture {
	background-image:
		var(--noise-url),
		repeating-linear-gradient(0deg, var(--grid-line) 0 1px, transparent 1px 4px);
	opacity: calc(var(--grain-opacity) * 2.6);
}

/* 08 Carbon · 碳纤维 */
body.tex-carbon .fx-texture {
	background-image:
		repeating-linear-gradient(45deg, var(--grid-line) 0 2px, transparent 2px 5px),
		repeating-linear-gradient(-45deg, var(--grid-line) 0 2px, transparent 2px 5px);
	opacity: 1;
}

/* 09 Honeycomb · 蜂巢 */
body.tex-honeycomb .fx-texture {
	background-image:
		repeating-linear-gradient(60deg, var(--grid-line) 0 1px, transparent 1px 26px),
		repeating-linear-gradient(-60deg, var(--grid-line) 0 1px, transparent 1px 26px),
		repeating-linear-gradient(0deg, var(--grid-line) 0 1px, transparent 1px 45px);
	opacity: 1;
}

/* 10 Metal · 拉丝金属 */
body.tex-metal .fx-texture {
	background-image:
		repeating-linear-gradient(90deg, var(--grid-line) 0 1px, transparent 1px 3px),
		linear-gradient(
			100deg,
			transparent 20%,
			rgba(255, 255, 255, 0.05) 45%,
			transparent 70%
		);
	opacity: 1;
}

/* 11 CRT · 显像管 */
body.tex-crt .fx-texture {
	background-image:
		repeating-linear-gradient(
			0deg,
			rgba(0, 0, 0, 0.16) 0 1px,
			transparent 1px 3px
		),
		radial-gradient(120% 100% at 50% 50%, transparent 58%, rgba(0, 0, 0, 0.4) 100%);
	opacity: 1;
}

/* ==========================================================================
   3. 动态 · MOTION

   基础层（main.css）只负责 html.js .reveal { opacity: 0 } 与 .reveal.in { opacity: 1 }，
   具体进场动画全部在这里，用 animation 避开优先级厦斗。
   ========================================================================== */

body.mo-off .reveal,
html.js body.mo-off .reveal {
	opacity: 1;
	animation: none;
}

html.js body.mo-fade .reveal.in {
	animation: moFade 0.62s var(--ease) both;
}
@keyframes moFade {
	from {
		opacity: 0;
		transform: translate3d(0, 22px, 0);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

html.js body.mo-zoom .reveal.in {
	animation: moZoom 0.6s var(--ease) both;
}
@keyframes moZoom {
	from {
		opacity: 0;
		transform: scale(0.92);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

html.js body.mo-flip .reveal.in {
	animation: moFlip 0.72s var(--ease) both;
	transform-origin: 50% 100%;
}
@keyframes moFlip {
	from {
		opacity: 0;
		transform: perspective(900px) rotateX(-14deg) translate3d(0, 26px, 0);
	}
	to {
		opacity: 1;
		transform: perspective(900px) rotateX(0) translate3d(0, 0, 0);
	}
}

html.js body.mo-blur .reveal.in {
	animation: moBlur 0.72s var(--ease-soft) both;
}
@keyframes moBlur {
	from {
		opacity: 0;
		filter: blur(14px);
		transform: scale(1.03);
	}
	to {
		opacity: 1;
		filter: blur(0);
		transform: none;
	}
}

html.js body.mo-slide .reveal.in {
	animation: moSlide 0.6s var(--ease) both;
}
@keyframes moSlide {
	from {
		opacity: 0;
		transform: translate3d(-60px, 0, 0);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

html.js body.mo-spring .reveal.in {
	animation: moSpring 0.78s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
@keyframes moSpring {
	from {
		opacity: 0;
		transform: translate3d(0, 40px, 0) scale(0.96);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

html.js body.mo-unfold .reveal.in {
	animation: moUnfold 0.68s var(--ease) both;
	transform-origin: 50% 0;
}
@keyframes moUnfold {
	from {
		opacity: 0;
		transform: perspective(1000px) rotateX(-70deg);
	}
	to {
		opacity: 1;
		transform: perspective(1000px) rotateX(0);
	}
}

html.js body.mo-swing .reveal.in {
	animation: moSwing 0.8s var(--ease) both;
	transform-origin: 12% 0;
}
@keyframes moSwing {
	from {
		opacity: 0;
		transform: rotate(-4deg) translate3d(0, 24px, 0);
	}
	60% {
		opacity: 1;
		transform: rotate(1.2deg);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

html.js body.mo-glitch .reveal.in {
	animation: moGlitch 0.66s steps(1, end) both;
}
@keyframes moGlitch {
	0% {
		opacity: 0;
		transform: translate3d(-14px, 8px, 0);
		clip-path: inset(20% 0 40% 0);
	}
	28% {
		opacity: 1;
		transform: translate3d(10px, -4px, 0);
		clip-path: inset(60% 0 8% 0);
	}
	52% {
		transform: translate3d(-6px, 3px, 0);
		clip-path: inset(0 0 0 0);
	}
	100% {
		opacity: 1;
		transform: none;
		clip-path: inset(0 0 0 0);
	}
}

html.js body.mo-drift .reveal.in {
	animation:
		moFade 0.62s var(--ease) both,
		moDrift 9s var(--ease-soft) 0.7s infinite;
}
@keyframes moDrift {
	0%,
	100% {
		transform: translate3d(0, 0, 0);
	}
	50% {
		transform: translate3d(0, -7px, 0);
	}
}

/* ==========================================================================
   4. 排版 · LAYOUT

   .workspace 直接子元素固定为三块：.console / .stats / .results-panel。
   每套排版只需重新安排这三块的行列 + 改几个尺寸令牌。
   layout-off 不存在样式，因为“关掉”就等于回到 main.css 的默认 Bento。
   ========================================================================== */

/* 01 Bento · 左控台 + 右看板（与 main.css 默认一致） */
body.layout-bento {
	--maxw: 1240px;
	--ws-cols: 420px minmax(0, 1fr);
}

/* 02 Split · 均分分栏，结果表横跨两列 */
body.layout-split {
	--maxw: 1280px;
	--ws-cols: minmax(0, 1fr) minmax(0, 1fr);
}
body.layout-split .console {
	grid-column: 1;
	grid-row: 1;
	position: static;
}
body.layout-split .stats {
	grid-column: 2;
	grid-row: 1;
	align-content: start;
}
body.layout-split .results-panel {
	grid-column: 1 / -1;
	grid-row: 2;
}

/* 03 Stack · 经典竖排 */
body.layout-stack {
	--maxw: 1000px;
	--ws-cols: minmax(0, 1fr);
}
body.layout-stack .console,
body.layout-stack .stats,
body.layout-stack .results-panel {
	grid-column: 1;
	grid-row: auto;
	position: static;
}

/* 04 Wide · 全宽通栏 */
body.layout-wide {
	--maxw: 1720px;
	--ws-cols: 460px minmax(0, 1fr);
}
body.layout-wide .hero {
	--hero-cols: 1.25fr 0.75fr;
}

/* 05 Compact · 紧凑 */
body.layout-compact {
	--maxw: 1160px;
	--ws-cols: 380px minmax(0, 1fr);
	--sp-4: 12px;
	--sp-5: 18px;
	--sp-6: 24px;
	--sp-8: 34px;
	--sp-12: 44px;
	--fs-display: clamp(1.8rem, 1rem + 3.2vw, 3rem);
	--fs-body: 0.94rem;
	--row-pad: 10px 14px;
}

/* 06 Airy · 疏朗 */
body.layout-airy {
	--maxw: 1320px;
	--ws-cols: 440px minmax(0, 1fr);
	--sp-4: 22px;
	--sp-5: 34px;
	--sp-6: 44px;
	--sp-8: 66px;
	--sp-12: 96px;
	--row-pad: 20px 22px;
}

/* 07 Magazine · 控台靠右，内容区在左 */
body.layout-magazine {
	--maxw: 1300px;
	--ws-cols: minmax(0, 1fr) 380px;
}
body.layout-magazine .console {
	grid-column: 2;
	grid-row: 1 / span 2;
}
body.layout-magazine .stats,
body.layout-magazine .results-panel {
	grid-column: 1;
}
body.layout-magazine .hero {
	--hero-cols: 0.8fr 1.2fr;
}
body.layout-magazine .hero-copy {
	order: 2;
}
body.layout-magazine .hero-spec {
	order: 1;
}

/* 08 Terminal · 全局等宽、直角、高对比边框 */
body.layout-terminal {
	--maxw: 1200px;
	--ws-cols: 400px minmax(0, 1fr);
	--font-display: var(--font-mono);
	--font-ui: var(--font-mono);
	--r-sm: 0;
	--r-md: 0;
	--r-lg: 0;
	--r-xl: 0;
	--border: rgba(255, 255, 255, 0.18);
	--row-pad: 11px 16px;
}
body.layout-terminal .panel,
body.layout-terminal .stat-card,
body.layout-terminal .spec-card,
body.layout-terminal .btn {
	border-radius: 0;
}
body.layout-terminal .display-title {
	letter-spacing: -0.02em;
	text-transform: uppercase;
}

/* 09 Centered · 居中窄栏 */
body.layout-centered {
	--maxw: 860px;
	--ws-cols: minmax(0, 1fr);
}
body.layout-centered .console,
body.layout-centered .stats,
body.layout-centered .results-panel {
	grid-column: 1;
	grid-row: auto;
	position: static;
}
body.layout-centered .hero {
	--hero-cols: minmax(0, 1fr);
	text-align: center;
}
body.layout-centered .hero-spec {
	display: none;
}
body.layout-centered .hero-chips,
body.layout-centered .eyebrow {
	justify-content: center;
}

/* 10 Dense · 数据密集 */
body.layout-dense {
	--maxw: 1440px;
	--ws-cols: 360px minmax(0, 1fr);
	--row-pad: 7px 12px;
	--fs-sm: 0.79rem;
}
body.layout-dense .stats {
	grid-template-columns: repeat(4, minmax(0, 1fr));
}
body.layout-dense .stat-card {
	padding: var(--sp-3) var(--sp-4);
}
body.layout-dense .stat-number {
	font-size: clamp(1.4rem, 1rem + 1.2vw, 2rem);
}
body.layout-dense .results-table {
	font-size: 0.8rem;
}

/* ==========================================================================
   5. 字体 · TYPEFACE

   需要额外拉取的 family 由 effects.js 在选中时才注入 <link>，
   所以这里只写字体栈，首屏不为未选中的字体付费。
   font-off 同样不存在样式：关掉就是回到默认 Sora。
   ========================================================================== */

body.font-grotesk {
	--font-display: 'Space Grotesk', 'Sora', system-ui, sans-serif;
	--font-ui: 'Space Grotesk', 'Inter', 'PingFang SC', 'Microsoft YaHei', sans-serif;
	--font-eyebrow: 'Space Grotesk', sans-serif;
}

body.font-mono {
	--font-display: 'JetBrains Mono', 'SF Mono', ui-monospace, monospace;
	--font-ui: 'JetBrains Mono', 'SF Mono', ui-monospace, 'PingFang SC', monospace;
	--font-eyebrow: 'JetBrains Mono', ui-monospace, monospace;
	letter-spacing: -0.01em;
}

body.font-system {
	--font-display:
		system-ui, -apple-system, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
	--font-ui:
		system-ui, -apple-system, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
	--font-eyebrow: system-ui, -apple-system, 'Segoe UI', sans-serif;
	--font-mono: ui-monospace, 'SF Mono', 'Cascadia Mono', Consolas, monospace;
}

body.font-editorial {
	--font-display: 'Playfair Display', 'Noto Serif SC', Georgia, serif;
	--font-ui: 'Inter', 'PingFang SC', 'Microsoft YaHei', sans-serif;
	--font-eyebrow: 'Playfair Display', Georgia, serif;
}
body.font-editorial .display-title {
	letter-spacing: -0.015em;
	font-weight: 700;
}

body.font-techno {
	--font-display: 'Orbitron', 'Sora', system-ui, sans-serif;
	--font-ui: 'Inter', 'PingFang SC', 'Microsoft YaHei', sans-serif;
	--font-eyebrow: 'Orbitron', sans-serif;
}
body.font-techno .display-title,
body.font-techno .eyebrow {
	letter-spacing: 0.02em;
}

body.font-rounded {
	--font-display: 'Quicksand', 'Sora', system-ui, sans-serif;
	--font-ui: 'Quicksand', 'Inter', 'PingFang SC', 'Microsoft YaHei', sans-serif;
	--font-eyebrow: 'Quicksand', sans-serif;
}

body.font-condensed {
	--font-display: 'Archivo Narrow', 'Sora', system-ui, sans-serif;
	--font-ui: 'Archivo Narrow', 'Inter', 'PingFang SC', 'Microsoft YaHei', sans-serif;
	--font-eyebrow: 'Archivo Narrow', sans-serif;
}

body.font-humanist {
	--font-display: 'Manrope', 'Sora', system-ui, sans-serif;
	--font-ui: 'Manrope', 'Inter', 'PingFang SC', 'Microsoft YaHei', sans-serif;
	--font-eyebrow: 'Manrope', sans-serif;
}

body.font-serifcn {
	--font-display: 'Noto Serif SC', 'Playfair Display', Georgia, serif;
	--font-ui: 'Noto Serif SC', Georgia, 'Songti SC', serif;
	--font-eyebrow: 'Noto Serif SC', Georgia, serif;
}

/* ==========================================================================
   6. 无障碍兼容
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
	.fx-glow,
	.fx-glow::after,
	html.js .reveal.in {
		animation: none !important;
	}
	html.js .reveal {
		opacity: 1 !important;
	}
}

@media print {
	.fx-layer,
	#particleCanvas,
	#fxCanvas {
		display: none !important;
	}
}
