/* ==========================================================================
   苏能教育官网 · 动效层（全站动态效果）
   依赖：base.css 的设计令牌；JS 侧为 motion.js（原生，零依赖）
   约定：
   - html.mo-js     JS 可用且动效启用（内联脚本先行添加；motion.js 在
                    prefers-reduced-motion 或 ?fit=0 像素比对模式下会移除，
                    页面回到纯静态呈现）。
   - html.mo-loaded 进场转场完成（body 由 opacity 0 → 1）。
   - 所有入场动画终态均为 identity（opacity:1 / transform 归零或缺省 var），
     配合 ?fit=0 关闭动效，静止态像素比对与改造前一致。
   - 画布为固定 px + html zoom 整页缩放：动画只用 transform/opacity，
     不用 vh/vw；视差限幅 ±60px 防露底。
   ========================================================================== */

:root {
    --mo-dur: .8s;
    --mo-dur-slow: 1s;
    --mo-ease: cubic-bezier(.22, .61, .36, 1);   /* easeOutCubic 系，与既有 sg-reveal 调性一致 */
    --mo-delay: 0s;
}

/* ---------------- 进场 / 离站转场 ---------------- */
html.mo-js body {
    opacity: 0;
    transition: opacity .5s ease;
}
html.mo-js.mo-loaded body { opacity: 1; }
html.mo-js.mo-leaving body { opacity: 0; transition: opacity .22s ease; }

/* ---------------- 滚动入场（motion.js 的 IntersectionObserver 触发 is-in）
   变体：fade / fade-up / zoom-in / slide-left(自右入) / slide-right(自左入)
   错峰：元素上写 --mo-delay（模板或内联 style） ---------------- */
html.mo-js [data-motion] { transition-delay: var(--mo-delay); }
html.mo-js [data-motion="fade"] {
    opacity: 0;
    transition: opacity var(--mo-dur-slow) var(--mo-ease);
}
html.mo-js [data-motion="fade-up"] {
    opacity: 0;
    transform: translateY(56px);
    transition: opacity var(--mo-dur) var(--mo-ease), transform var(--mo-dur) var(--mo-ease);
}
html.mo-js [data-motion="zoom-in"] {
    opacity: 0;
    transform: scale(.955);
    transition: opacity var(--mo-dur) var(--mo-ease), transform var(--mo-dur) var(--mo-ease);
}
html.mo-js [data-motion="slide-left"] {
    opacity: 0;
    transform: translateX(96px);
    transition: opacity var(--mo-dur) var(--mo-ease), transform var(--mo-dur) var(--mo-ease);
}
html.mo-js [data-motion="slide-right"] {
    opacity: 0;
    transform: translateX(-96px);
    transition: opacity var(--mo-dur) var(--mo-ease), transform var(--mo-dur) var(--mo-ease);
}
html.mo-js [data-motion].is-in { opacity: 1; transform: none; }

/* 切片块级入场：内页（sg-page--design，content 已隐藏）与品牌页切片下方只有
   .sg-sr 隐藏文本/被盖住的语义 DOM，淡入上浮安全；
   首页切片下方是完整语义 DOM（会重影），故首页切片不做入场（见 partial/slices.html）。 */
html.mo-js [data-motion="slice-up"] {
    opacity: 0;
    transform: translateY(48px);
    transition: opacity .9s var(--mo-ease), transform .9s var(--mo-ease);
}
html.mo-js [data-motion="slice-up"].is-in { opacity: 1; transform: none; }

/* ---------------- 视差（motion.js 按帧写 --mo-px，限幅 ±60px） ----------------
   仅用于首屏切片与 banner2：下方是同内容的语义 DOM/切片，位移露缝不穿帮。
   --mo-mx/--mo-my 为首屏鼠标视差分量（mousemove 写入，默认 0），
   与滚动分量合成一条 transform；放在入场变体之后，transform 以 var 版本为准。 */
html.mo-js [data-parallax] {
    transform: translate3d(var(--mo-mx, 0px), calc(var(--mo-px, 0px) + var(--mo-my, 0px)), 0);
    will-change: transform;
}

/* ---------------- 首页切片：缩放落定入场（transform-only，无重影） ----------------
   hero 切片（slice-01）专用：随首屏加载做 scale 1.035→1 落定 + 淡入。
   其余切片用下方 slice-rise（淡入上移）。 */
html.mo-js [data-motion="slice-zoom"] {
    opacity: 0;
    transform: scale(1.035);
    transform-origin: 50% 0;
    transition: opacity .9s var(--mo-ease);
}
html.mo-js [data-motion="slice-zoom"].is-in { opacity: 1; }

/* ---------------- 首页切片：淡入上移入场（经典板块动效） ----------------
   前提：切片下方的语义 DOM 已在动效模式下视觉隐藏（见下一条规则），
   切片淡入时露出的是干净的白底，不会出现 DOM 重影。 */
html.mo-js [data-motion="slice-rise"] {
    opacity: 0;
    transform: translateY(80px);
    transition: opacity .95s var(--mo-ease), transform .95s var(--mo-ease);
}
html.mo-js [data-motion="slice-rise"].is-in { opacity: 1; transform: none; }

/* ---------------- 隐藏首页切片下方的语义 DOM（防淡入重影） ----------------
   仅首页（body.sg-page--home）：这些 DOM 静止时本就被不透明切片完全盖住，
   opacity:0 对静止像素零影响；切片淡入/上移时露出白底而非半透明 DOM。
   pointer-events 不受 opacity 影响 → hero「预约试听」标签等热区仍可点击。
   mo-safe（motion.js 加载失败的内联兜底，见布局脚本）下强制恢复可见。 */
html.mo-js body.sg-page--home .sg-main > section,
html.mo-js body.sg-page--home .sg-main > .sg-faculty-band,
html.mo-js body.sg-page--home .sg-footer { opacity: 0; }
html.mo-safe body.sg-page--home .sg-main > section,
html.mo-safe body.sg-page--home .sg-main > .sg-faculty-band,
html.mo-safe body.sg-page--home .sg-footer { opacity: 1 !important; }
html.mo-safe [data-motion] { opacity: 1 !important; transform: none !important; animation: none !important; transition: none !important; }

/* ---------------- 内页切片页（sg-page--design）同理：隐藏切片下方的语义 DOM ----------------
   .sg-design-page__content 里的可见标题等语义 DOM 静止时本就被不透明切片完全盖住，
   但 body 进/离站淡出（mo-leaving / 进场淡入）期间会与切片图层双重曝光 → 残影。
   opacity:0 对静止像素零影响；CTA 热区是 content 的兄弟节点，不受影响；mo-safe 兜底恢复。 */
html.mo-js body.sg-page--design .sg-design-page__content { opacity: 0; }
html.mo-safe body.sg-page--design .sg-design-page__content { opacity: 1 !important; }

/* overflow-x: clip 裁掉 slice-zoom 入场期间的横向膨胀（~±70px），
   clip 与 hidden 不同：不产生滚动容器，position:sticky 页头不受影响 */
html.mo-js, html.mo-js body { overflow-x: clip; }

/* ---------------- 品牌矩阵带高光扫过（slices.html 内的光带节点） ----------------
   复用 mo-shine 关键帧；光带自身 pointer-events:none、不改变画面，
   由 data-motion 引擎进入视口时加 is-in 触发扫过一次。 */
.mo-shine--band {
    position: absolute;
    left: 0;
    width: var(--sg-canvas-w, 4000px);
    overflow: hidden;
    pointer-events: none;
}
.mo-shine--band::after {
    content: "";
    position: absolute;
    top: 0; bottom: 0; left: 0;
    width: 34%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .16), transparent);
    transform: translateX(-130%) skewX(-18deg);
}
html.mo-js .mo-shine--band.is-in::after {
    animation: mo-shine 1.6s var(--mo-ease) .2s 1 both;
}

/* ---------------- hero 切片 = slice-zoom 入场 + 滚动/鼠标视差 合成 ----------------
   放在本文件末尾以赢得级联：generic 的 .is-in（transform:none，特异性 0,3,1）
   会覆盖 [data-parallax]（0,2,1）的位移合成，这里用更高特异性把缩放与视差合并。
   hero 用一次性 animation 而非 transition：keyframes 里的 var 实时重解析，
   落定后 --mo-mx/--mo-px/--mo-my 的每帧更新不经过过渡（否则鼠标视差会拖影 1.1s）。 */
html.mo-js [data-parallax][data-motion="slice-zoom"] {
    transform: translate3d(var(--mo-mx, 0px), calc(var(--mo-px, 0px) + var(--mo-my, 0px)), 0) scale(1.035);
    transform-origin: 50% 0;
}
html.mo-js [data-parallax][data-motion="slice-zoom"].is-in {
    transform: translate3d(var(--mo-mx, 0px), calc(var(--mo-px, 0px) + var(--mo-my, 0px)), 0) scale(1);
    animation: mo-hero-zoom 1.1s var(--mo-ease) both;
    animation-delay: var(--mo-delay);
}
@keyframes mo-hero-zoom {
    from { transform: translate3d(var(--mo-mx, 0px), calc(var(--mo-px, 0px) + var(--mo-my, 0px)), 0) scale(1.035); }
    to   { transform: translate3d(var(--mo-mx, 0px), calc(var(--mo-px, 0px) + var(--mo-my, 0px)), 0) scale(1); }
}

/* ---------------- 页头：下滚隐藏 / 上滚显示（motion.js 切 mo-header-hide） ---------------- */
html.mo-js .sg-header {
    transition: box-shadow .3s ease, background .3s ease, transform .35s var(--mo-ease);
}
html.mo-header-hide .sg-header { transform: translateY(-100%); }

/* ---------------- 滚动进度条（布局公共节点 .mo-progress，变量由 JS 写在 html） ---------------- */
.mo-progress {
    position: fixed;
    top: 0; left: 0;
    width: 100%;
    height: 6px;
    z-index: 200;
    background: linear-gradient(90deg, var(--sg-teal), var(--sg-magenta));
    transform: scaleX(var(--mo-progress, 0));
    transform-origin: 0 50%;
    opacity: 0;
    transition: opacity .3s ease;
    pointer-events: none;
}
html.mo-progress-on .mo-progress { opacity: 1; }

/* ---------------- 返回顶部（进度环随页面滚动消耗） ---------------- */
.mo-top {
    position: fixed;
    right: 48px; bottom: 48px;
    z-index: 190;
    width: 104px; height: 104px;
    padding: 0;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 12px 40px rgba(24, 32, 44, .16);
    opacity: 0;
    visibility: hidden;
    transform: translateY(24px) scale(.9);
    transition: opacity .3s ease, transform .3s var(--mo-ease), visibility 0s linear .3s, background .25s ease;
}
html.mo-top-on .mo-top {
    opacity: 1;
    visibility: visible;
    transform: none;
    transition-delay: 0s;
}
.mo-top:hover { background: var(--sg-teal); }
.mo-top svg { position: absolute; inset: 14px; width: auto; height: auto; }
.mo-top circle, .mo-top path { fill: none; stroke-width: 3; stroke-linecap: round; }
.mo-top .mo-top__track { stroke: var(--sg-line); }
.mo-top .mo-top__ring {
    stroke: var(--sg-teal);
    stroke-dasharray: 125.7;                 /* r=20 周长 2πr ≈ 125.66 */
    stroke-dashoffset: var(--mo-ring, 125.7);
    transform: rotate(-90deg);
    transform-origin: 50% 50%;
    transition: stroke-dashoffset .15s linear;
}
.mo-top path { stroke: var(--sg-ink-2); }
.mo-top:hover path { stroke: #fff; }

/* ---------------- 首页 banner2：Ken Burns 缩放淡入（随轮播 is-show 重启） ---------------- */
html.mo-js .sg-hero-banner2.is-show img { animation: mo-kenburns 6s ease-out both; }
@keyframes mo-kenburns {
    from { transform: scale(1.06); }
    to   { transform: scale(1); }
}

/* 首页轮播指示点：active 拉长为进度条，白色填充按 6s 轮播周期走满 */
html.mo-js .sg-hero-dot.is-active {
    position: relative;
    overflow: hidden;
    width: 72px;
    border-radius: 12px;
}
html.mo-js .sg-hero-dot.is-active::after {
    content: "";
    position: absolute;
    left: 2px; top: 2px; bottom: 2px;
    width: calc(100% - 4px);
    border-radius: 10px;
    background: #fff;
    transform-origin: 0 50%;
    animation: mo-dot-fill 6s linear both;
}
@keyframes mo-dot-fill {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
}

/* ---------------- 内页 banner（column 等占位框架页） ----------------
   背景图一次 Ken Burns 落定（终态 scale(1)，不改静止版式）+ 高光扫过 */
html.mo-js .sg-inner-banner__bg img { animation: mo-banner-settle 1.8s var(--mo-ease) both; }
@keyframes mo-banner-settle {
    from { transform: scale(1.08); }
    to   { transform: scale(1); }
}
html.mo-loaded .sg-inner-banner .mo-shine::after {
    animation: mo-shine 1.5s var(--mo-ease) .5s 1 both;
}
.mo-shine {
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    z-index: 2;
}
.mo-shine::after {
    content: "";
    position: absolute;
    top: 0; bottom: 0; left: 0;
    width: 34%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .22), transparent);
    transform: translateX(-130%) skewX(-18deg);
}
@keyframes mo-shine {
    from { transform: translateX(-130%) skewX(-18deg); }
    to   { transform: translateX(260%) skewX(-18deg); }
}

/* ---------------- 计数器完成回调（main.js initCounter 加 .is-counted） ---------------- */
@keyframes mo-pop {
    0%   { transform: scale(1); }
    40%  { transform: scale(1.22); }
    100% { transform: scale(1); }
}
.is-counted i { display: inline-block; animation: mo-pop .5s var(--mo-ease); }

/* ---------------- 图内热区 hover 光晕（页脚 TEL / 内页 CTA / 品牌 Explore） ---------------- */
@keyframes mo-glow {
    from { box-shadow: 0 0 0 0 rgba(12, 148, 136, .45); }
    to   { box-shadow: 0 0 0 26px rgba(12, 148, 136, 0); }
}
@keyframes mo-glow-white {
    from { box-shadow: 0 0 0 0 rgba(255, 255, 255, .45); }
    to   { box-shadow: 0 0 0 26px rgba(255, 255, 255, 0); }
}
html.mo-js .sg-footer__tel-hot:hover,
html.mo-js .sg-design-hotspot:hover { animation: mo-glow 1.1s ease-out infinite; }
html.mo-js .sg-brand-page__hotspot:hover { animation: mo-glow-white 1.1s ease-out infinite; }

/* ---------------- 品牌页（764 竖版）：整图缓慢呼吸 ---------------- */
@keyframes mo-breathe {
    from { transform: scale(1); }
    to   { transform: scale(1.02); }
}
html.mo-js .sg-brand-page__img { animation: mo-breathe 9s ease-in-out 1.5s infinite alternate; }

/* ---------------- 导航 hover 下划线（滑动展开；active 态沿用 layout.css 既有规则） ---------------- */
.sg-nav__link::after {
    content: "";
    position: absolute;
    left: 40px; right: 40px; bottom: 0;
    height: 4px;
    border-radius: 4px;
    background: var(--sg-teal);
    transform: scaleX(0);
    transform-origin: 50% 50%;
    transition: transform .3s var(--mo-ease);
}
.sg-nav__item.is-active .sg-nav__link::after,
html.mo-js .sg-nav__item:hover .sg-nav__link::after { transform: scaleX(1); }
/* 1920 画布页头为标准页头 ×0.48，下划线同步缩小（与 layout.css:338 的 active 覆盖一致） */
body.sg-page--design1920 .sg-nav__link::after { left: 19px; right: 19px; height: 2px; border-radius: 2px; }

/* ---------------- 降级兜底：系统“减少动态效果” ----------------
   JS 侧已整体退出（移除 mo-js），此处再兜一层，保证任何规则组合下内容可见。 */
@media (prefers-reduced-motion: reduce) {
    html.mo-js body { opacity: 1 !important; transition: none !important; }
    html.mo-js [data-motion] { opacity: 1 !important; transform: none !important; transition: none !important; animation: none !important; }
    html.mo-js [data-parallax] { transform: none !important; }
    html.mo-js, html.mo-js body { overflow-x: visible !important; }
    html.mo-js body.sg-page--home .sg-main > section,
    html.mo-js body.sg-page--home .sg-main > .sg-faculty-band,
    html.mo-js body.sg-page--home .sg-footer { opacity: 1 !important; }
    html.mo-js .sg-header,
    html.mo-js .mo-progress,
    html.mo-js .mo-top,
    html.mo-js .sg-nav__link::after { transition: none !important; animation: none !important; }
    html.mo-js .sg-hero-banner2.is-show img,
    html.mo-js .sg-hero-dot.is-active::after,
    html.mo-js .sg-inner-banner__bg img,
    html.mo-js .sg-inner-banner .mo-shine::after,
    html.mo-js .sg-brand-page__img,
    html.mo-js .is-counted i { animation: none !important; }
}
