/* ===== 首页整屏吸附滚动（仅桌面端 >720px） ===== */
/* --fp-rise：淡入上浮的位移量。「逃生舱」容器的下内边距要不小于它，两处必须联动，
   所以抽成变量：改这一个值即可，别再在 transform 里写字面量。
   --fp-pad-b：容器「自己本来的下内边距」，默认 0；有自带内边距的容器（如
   .hero-inner）在自己身上覆盖它，供下面的 max() 判据取用。**必须带单位**——
   写成无单位的 0 会让 max(0, 16px) 类型不一致而整条声明失效。
   注意这个默认值必须挂在祖先（:root）上：若挂在 .fullpage-slide > .container
   那条规则里，(0,2,0) 会盖过 .hero-inner 的 (0,1,0)，hero 反而读不到自己的值。 */
:root { --fp-rise: 16px; --fp-pad-b: 0px; }
#fullpage-dots { display: none; }

@media (min-width: 720.02px) {
  html { scroll-snap-type: y mandatory; }
  html.fp-jump { scroll-snap-type: none !important; }

  .fullpage-slide {
    height: calc(100vh - 84px);
    scroll-snap-align: start;
    scroll-snap-stop: always;
    scroll-margin-top: 84px;
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }
  #contact { scroll-margin-top: 84px; }

  .fullpage-slide[data-slide-index="0"],
  .fullpage-slide[data-slide-index="1"],
  .fullpage-slide[data-slide-index="2"] {
    justify-content: center;
    justify-content: safe center;
  }

  .fullpage-slide[data-slide-index="3"] > section#contact {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    align-items: safe center;
  }
  .fullpage-slide[data-slide-index="3"] > footer { flex: 0 0 auto; }

  /* 矮视口滚动逃生舱：精确选择器，避免误伤 .nav-inner / .footer-inner */
  .fullpage-slide > .container,
  .fullpage-slide[data-slide-index="3"] > section#contact {
    max-height: 100%;
    overflow-y: auto;
  }
  /* 未激活的屏，内容带着 translateY(--fp-rise) 等着淡入上浮。transform 位移会被
     算进滚动溢出区，于是上面这条 overflow-y:auto 在「这屏还没滚到位」时会冒出一条
     幽灵滚动条（内容并没有真的超出），位移那一截还会被裁掉。
     判据是「容器自身下内边距 ≥ --fp-rise」：容器把自己原本的下内边距报进
     --fp-pad-b，这里取它和 --fp-rise 的较大者——本来就够宽裕的（如 hero 的 32px）
     保持原值不被压缩，谁哪天改小了也会被自动垫到 --fp-rise，不会静默退化。

     两条使用须知，别踩：
     ① 本规则**无条件**以 (0,2,0) 接管所有 .fullpage-slide > .container 的
        padding-bottom。将来给某个 slide 直接子容器加下内边距时，必须同时把值报进
        --fp-pad-b，否则会被这里静默压成 --fp-rise。（这个坑已经犯过两次）
     ② 覆盖范围**只有** .container。第 4 屏的 #contact 是另一个滚动容器，它靠
        .section 的 32px（> --fp-rise）自带余量豁免，属于静态假设、不在自愈范围内：
        哪天 .section 的 32px 被改到小于 --fp-rise，那一屏的幽灵滚动条会悄悄回来，
        届时需要把 #contact 也纳入本规则并为它申报 --fp-pad-b。
     .soon-inner 不是 .fullpage-slide 的直接子元素，天然不在本选择器内。 */
  .fullpage-slide > .container {
    padding-bottom: max(var(--fp-pad-b), var(--fp-rise));
  }

  /* 紧凑内边距：原为长页面自然流设计，整屏场景下收紧以降低矮视口溢出概率 */
  /* 两个 32px 要一起改：前者供上面的 max() 判据，后者是实际上下内边距。
     这里刻意不写成 padding: var(--fp-pad-b) 20px —— 简写里含 var() 会让整条
     声明延迟解析，变量一旦写错（如漏单位）四边内边距会一起归零、hero 直接塌版；
     写死字面量则最坏只是上下不对称，不会破版。 */
  .hero-inner { --fp-pad-b: 32px; padding: 32px 20px; }
  .section { padding: 32px 0; }
  .section-tight { padding: 24px 0; }

  /* ===== 右侧小点导航 ===== */
  #fullpage-dots {
    position: fixed;
    right: 24px;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    flex-direction: column;
    gap: 10px;
  }
  .fullpage-dot {
    width: 24px;
    height: 24px;
    padding: 0;
    border: none;
    border-radius: 50%;
    cursor: pointer;
    background: transparent;
    -webkit-appearance: none;
    appearance: none;
    position: relative;
  }
  .fullpage-dot::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 8px;
    height: 8px;
    margin: -4px 0 0 -4px;
    border-radius: 50%;
    background: #fff;
    opacity: .35;
  }
  .fullpage-dot:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }
  .fullpage-dot.is-current::before { opacity: 1; transform: scale(1.3); }

  /* ===== 内容错峰浮现 ===== */
  html.fp-js-ready .fp-stagger [data-fp-order]:not(.btn) {
    opacity: 0;
    transform: translateY(var(--fp-rise));
    transition-property: opacity, transform;
    transition-duration: .5s, .5s;
    transition-timing-function: ease, ease;
  }
  /* :where() 压低特异度到只剩 .btn（0,1,0）——必须和下面的激活态规则同一量级，
     否则不管哪条先写，特异度更高的隐藏态会永远盖过激活态，按钮永久不可见 */
  :where(html.fp-js-ready .fp-stagger [data-fp-order]).btn {
    opacity: 0;
    transition-property: opacity;
    transition-duration: .5s;
    transition-timing-function: ease;
  }
  .fp-stagger [data-fp-order="1"] { transition-delay: 0ms; }
  .fp-stagger [data-fp-order="2"] { transition-delay: 100ms; }
  .fp-stagger [data-fp-order="3"] { transition-delay: 200ms; }
  .fp-stagger [data-fp-order="4"] { transition-delay: 300ms; }
  .fp-stagger [data-fp-order="5"] { transition-delay: 400ms; }
  .fullpage-slide.is-active .fp-stagger [data-fp-order]:not(.btn) {
    opacity: 1;
    transform: translateY(0);
  }
  /* 特异度同为 (0,1,0)，激活态规则在文件里写在隐藏态之后，同级靠源码顺序胜出；
     同时仍低于 .btn-primary:hover 的 (0,2,0)，hover 变暗效果不受影响 */
  :where(.fullpage-slide.is-active .fp-stagger [data-fp-order]).btn { opacity: 1; }
}

/* 本块必须留在文件最后，块内两处都靠"写在更后面"胜出、对顺序敏感：
   ① .btn 的 opacity 规则特异度和桌面态激活/隐藏规则一样都是 (0,1,0)；
   ② 下面那条 padding-bottom 与桌面态补偿规则同为 (0,2,0)。
   把其中任何一条挪到前面（哪怕只是"归类整理"）都会让它被压住而失效 */
@media (prefers-reduced-motion: reduce) and (min-width: 720.02px) {
  html { scroll-behavior: auto; }
  /* 本分支下 transform 被强制 none，没有位移要容纳，补偿就是纯多余的上下不对称，
     还会让矮视口逃生舱提前 --fp-rise 触发。这里退回容器自带的下内边距——
     不能写死 0，否则会把 hero 本来的 32px 一并抹掉。
     ⚠️ 本条取到 hero 的 32px，依赖 --fp-pad-b 在桌面态那个媒体查询里被声明，
        两处断点必须保持一致（都是 720.02px）；只改一边会让减动效用户的 hero
        下内边距静默变成 0 */
  .fullpage-slide > .container { padding-bottom: var(--fp-pad-b); }
  .fp-stagger [data-fp-order]:not(.btn) {
    transition: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  /* opacity 不加 !important、且用 :where() 把特异度压到 (0,1,0)：
     必须仍然低于 .btn-primary:hover 的 (0,2,0)，否则 hover 变暗会失效 */
  :where(.fp-stagger [data-fp-order]).btn {
    transition: none !important;
    opacity: 1;
  }
}
