/* ==========================================================================
   湖北理工学院计算机协会 · 招新宣传单页
   苏联构成主义 / 蓝白 / 零构建(file:// 直开)

   @layer 顺序即优先级顺序,后写的赢。改样式先找对 layer,不要用 !important。
   ========================================================================== */

/* --------------------------------------------------------------------------
   tokens —— 全站唯一取色处。改配色只改这里。
   面积纪律:70% 纸白 / 25% 蓝色实块 / 5% 黄。
   蓝色块内禁止再叠渐变、阴影、圆角 —— 一加就丢印刷感。
   -------------------------------------------------------------------------- */
@layer tokens {
  :root {
    /* 蓝阶 */
    --blue-950: #04101f;
    --blue-900: #071a3c;
    --blue-800: #0b2a66;
    --blue-700: #1039a8;      /* 主蓝:大色块 */
    --blue-600: #1b52d6;
    --blue-500: #2e6bff;
    --cyan-400: #35c4f0;

    /* 纸与墨 */
    --paper: #f1f4f9;         /* 页面底:冷纸白,略带蓝 */
    --paper-hi: #fbfcfe;
    --ink: #05080f;           /* 印刷黑,非纯黑 */
    --gray-600: #55637a;      /* 次要文字 */
    --gray-300: #a8b4c4;
    --gray-200: #d5dce6;

    /* 唯一对抗色,CTA 专用,面积 ≤5% */
    --signal: #ffd400;

    /* 双色调图调色板 —— 与 tools/stylize.py 的 SHADOW/HIGHLIGHT 绑定,
       改一处必须改两处 */
    --duo-shadow: #071a3c;
    --duo-highlight: #cfe1ff;

    /* 版式 */
    --mega-fit: 0.235;
    /* 巨型中文标题的“满宽”系数。--mega-fit × 容器宽 = 字号。
       4 字满宽:4 字 + 3 处 letter-spacing ≈ 4.25em → 1/4.25 ≈ 0.235。
       换标题字数后只调这一个数。 */

    --cut: 8cqw;              /* 斜切楔形的进深,M1 用 */

    --step--1: clamp(0.8125rem, 0.78rem + 0.16vw, 0.875rem);
    --step-0:  clamp(1rem, 0.96rem + 0.2vw, 1.0625rem);
    --step-1:  clamp(1.25rem, 1.18rem + 0.35vw, 1.5rem);
    --step-2:  clamp(1.5625rem, 1.42rem + 0.7vw, 2.25rem);
    --step-3:  clamp(2rem, 1.7rem + 1.5vw, 3.25rem);

    --gutter: clamp(1rem, 3vw, 3rem);
    --measure: 38ch;          /* 中文正文最佳行长约 35–45 字 */
    --rule: 4px;              /* 粗横线,构成主义的“杠” */
  }
}

/* --------------------------------------------------------------------------
   reset —— 现代最小集,不引外部文件
   -------------------------------------------------------------------------- */
@layer reset {
  *,
  *::before,
  *::after { box-sizing: border-box; }

  * { margin: 0; }

  html {
    /* clip 而非 hidden:hidden 会破坏内部 position:sticky */
    overflow-x: clip;
    /* 必须三个都写:Firefox 只认不带前缀的 text-size-adjust(以及 -moz- 老写法),
       而 Chrome/Edge 认 -webkit-。只写 -webkit- 的话,Firefox-Android 会启用
       移动端"文字自动放大"(text autosizing),它是按块算的 —— 于是手机上
       Firefox 会出现"某些文字比别处明显更大更粗、其它正常"。 */
    -webkit-text-size-adjust: 100%;
    -moz-text-size-adjust: 100%;
    text-size-adjust: 100%;
    scroll-behavior: smooth;
  }

  body {
    min-height: 100svh;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
  }

  img,
  picture,
  svg,
  video { display: block; max-width: 100%; }

  input,
  button,
  textarea,
  select { font: inherit; }

  p,
  h1,
  h2,
  h3,
  h4,
  h5,
  h6 { overflow-wrap: break-word; }

  ul[role='list'],
  ol[role='list'] { list-style: none; padding: 0; }
}

/* --------------------------------------------------------------------------
   base —— 字体、排版基线
   -------------------------------------------------------------------------- */
@layer base {
  /* 字体两分(设计指定):
       英文与数字 → JetBrains Mono
       中文       → JetBrains Maple Mono
     两块都用等宽,站上因此通篇对齐,构成主义的"铅字盘"读感。
     分工靠 unicode-range(拉丁 U+0000-007F 走 JBM,其余走 Maple),
     不靠字形顺序碰运气。子集由 tools/subset_font.py 生成,只含页面用到的字;
     结尾的字体栈是兜底:子集加载失败时排版不塌。 */
  @font-face {
    font-family: 'JetBrains Mono Subset';
    src: url('assets/fonts/JetBrainsMonoSubset-400.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-007F;
  }

  @font-face {
    font-family: 'JetBrains Mono Subset';
    src: url('assets/fonts/JetBrainsMonoSubset-700.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-007F;
  }

  @font-face {
    font-family: 'JetBrains Mono Subset';
    src: url('assets/fonts/JetBrainsMonoSubset-800.woff2') format('woff2');
    font-weight: 800;          /* 标题的 900 由 ExtraBold 承接 */
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-007F;
  }

  @font-face {
    font-family: 'JetBrains Maple Mono Subset';
    src: url('assets/fonts/JetBrainsMapleMonoSubset-400.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0080-10FFFF;
  }

  @font-face {
    font-family: 'JetBrains Maple Mono Subset';
    src: url('assets/fonts/JetBrainsMapleMonoSubset-700.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0080-10FFFF;
  }

  @font-face {
    font-family: 'JetBrains Maple Mono Subset';
    src: url('assets/fonts/JetBrainsMapleMonoSubset-800.woff2') format('woff2');
    font-weight: 800;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0080-10FFFF;
  }

  :root {
    --font-mono: 'JetBrains Mono Subset', 'JetBrains Maple Mono Subset',
                 'JetBrains Mono', 'JetBrains Maple Mono', ui-monospace, monospace;
    /* 同一栈:拉丁走 JetBrains Mono,中文走 JetBrains Maple Mono */
    --font-sans: var(--font-mono);
  }

  body {
    background: var(--paper);
    color: var(--ink);
    font-family: var(--font-sans);
    font-size: var(--step-0);
    line-height: 1.75;          /* 中文正文行高 */
    font-synthesis-weight: none;
  }

  /* 巨型标题:中文无衬线,满宽,负字距收紧 */
  .mega {
    font-weight: 900;
    font-size: calc(var(--mega-fit) * 100cqw);
    line-height: 0.98;
    letter-spacing: 0.04em;
    text-wrap: balance;
  }

  .kicker {
    font-size: var(--step--1);
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--gray-600);
  }

  /* 构成主义的“杠”:4px 实线,构成主义的节奏单位 */
  .rule {
    border: 0;
    border-block-start: var(--rule) solid currentColor;
  }

  /* 防止短标签在窄容器里被拆开(如「VR头显」断成「VR / 头显」) */
  .nb {
    white-space: nowrap;
  }

  /* 章节序号 + 标题的通用骨架 */
  .sec-head {
    display: grid;
    gap: 0.5rem;
    margin-block-end: clamp(1.5rem, 4vw, 3rem);
  }

  .sec-no {
    font-family: var(--font-mono);
    font-weight: 700;
    font-size: var(--step-1);
    color: var(--blue-700);
    letter-spacing: 0.08em;
  }

  .sec-title {
    font-size: var(--step-3);
    font-weight: 900;
    line-height: 1.1;
  }

  /* 焦点可见性:全站统一,不省略 */
  :focus-visible {
    outline: 3px solid var(--blue-600);
    outline-offset: 3px;
  }

  ::selection {
    background: var(--blue-700);
    color: var(--paper-hi);
  }

  /* 锚点跳转落点:sticky 导航不再盖住标题 */
  [id] {
    scroll-margin-block-start: 5.5rem;
  }
}

/* --------------------------------------------------------------------------
   layout —— 通用骨架:导航、章节容器
   -------------------------------------------------------------------------- */
@layer layout {
  .nav {
    position: sticky;
    top: 0;
    z-index: 40;
    display: flex;
    align-items: center;
    gap: var(--gutter);
    padding: 0.625rem var(--gutter);
    background: var(--paper);
    border-block-end: var(--rule) solid var(--ink);
  }

  .nav__brand {
    font-weight: 900;
    letter-spacing: 0.06em;
    text-decoration: none;
    color: var(--ink);
    white-space: nowrap;
  }

  /* 窄屏用缩写,把导航条的位置让给 00/01 那些序号 */
  .nav__brand-short {
    display: none;
  }

  @media (max-width: 40rem) {
    .nav__brand-full {
      display: none;
    }

    .nav__brand-short {
      display: inline;
    }
  }

  .nav__list {
    display: flex;
    gap: clamp(0.75rem, 2vw, 1.75rem);
    margin-inline-start: auto;
    overflow-x: auto;
  }

  .nav__link {
    font-size: var(--step--1);
    font-weight: 700;
    text-decoration: none;
    color: var(--gray-600);
    white-space: nowrap;
    padding-block: 0.25rem;
  }

  .nav__link:hover { color: var(--ink); }

  .nav__link[aria-current='true'] {
    color: var(--blue-700);
    text-decoration: underline;
    text-decoration-thickness: var(--rule);
    text-underline-offset: 0.375rem;
  }

  /* 窄屏翻页器:‹ 当前章节 › —— 手机屏太小,横滚列表换成翻页;
     宽屏不显示,用完整导航列表 */
  .nav__pager {
    display: none;
  }

  .nav__pager-btn {
    font: inherit;
    font-size: var(--step--1);
    font-weight: 700;
    line-height: 1;
    padding: 0;
    position: relative;
    width: 25px;
    height: 25px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    color: var(--ink);
    border: 2px solid var(--ink);
    touch-action: manipulation;
    cursor: pointer;
  }

  /* 视觉上就一个小箭头,但触摸区悄悄向外多 3px —— 手机上不至于点不到 */
  .nav__pager-btn::after {
    content: '';
    position: absolute;
    inset: -0.2rem;
  }

  /* 悬停样式只在真有鼠标的设备上生效:触屏点一下会残留 :hover,
     箭头会一直留个蓝底,看着像"选中了" */
  @media (hover: hover) {
    .nav__pager-btn:hover {
      background: var(--blue-700);
      border-color: var(--blue-700);
      color: var(--paper);
    }
  }

  .nav__pager-btn[aria-disabled='true'] {
    opacity: 0.3;
    cursor: default;
    background: transparent;
    border-color: var(--gray-600);
    color: var(--ink);
  }

  .nav__pager-now {
    font: inherit;
    font-size: var(--step--1);
    font-weight: 700;
    padding: 0.15rem 0.1rem;
    background: none;
    border: 0;
    color: var(--ink);
    text-decoration: underline;
    text-underline-offset: 0.28em;
    white-space: nowrap;
    cursor: pointer;
    touch-action: manipulation;
  }

  @media (max-width: 40rem) {
    .nav__list {
      /* 窄屏:不再横滚,收成"点当前章节弹出来的跳转菜单" */
      display: none;
      position: absolute;
      top: calc(100% + 0.45rem);
      inset-inline-end: var(--gutter);
      flex-direction: column;
      gap: 0;
      min-width: 11rem;
      padding: 0.3rem 0;
      background: var(--paper-hi);
      border: var(--rule) solid var(--ink);
      box-shadow: 0 0.7rem 1.6rem rgba(5, 8, 15, 0.22);
      z-index: 20;
    }

    .nav.is-open .nav__list {
      display: flex;
    }

    .nav__list li {
      display: block;
    }

    .nav__link {
      display: block;
      padding: 0.55rem 0.95rem;
      font-size: var(--step--1);
    }

    .nav__link[aria-current='true'] {
      background: var(--blue-700);
      color: var(--paper-hi);
      text-decoration: none;
    }

    .nav__pager {
      display: flex;
      align-items: center;
      gap: 0.5rem;
      margin-inline-start: auto;
    }
  }

  .sec {
    padding-block: clamp(3rem, 9vw, 7rem);
    padding-inline: var(--gutter);
  }

  .sec__inner {
    max-width: 75rem;
    margin-inline: auto;
  }
}

/* --------------------------------------------------------------------------
   hero —— #top 首屏。首屏不播入场动画,不推迟 LCP。
   构图:左侧蓝 700 斜切实块压巨型白字,图向右溢出容器,冲出画面。
   -------------------------------------------------------------------------- */
@layer hero {
  .hero {
    position: relative;
    display: grid;
    align-items: center;
    gap: clamp(2rem, 5vw, 4rem);
    padding-block: clamp(2rem, 6vw, 5rem);
    padding-inline: var(--gutter);
    /* 图不再冲出右边界:左右各留一条同宽的边距(用户 2026-10 要求),
       否则图片和蓝框一起贴死在右边缘、看着挤 */
    overflow-x: clip;
  }

  @media (min-width: 900px) {
    .hero {
      grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    }
  }

  .hero__plate {
    position: relative;
    background: var(--blue-700);
    color: var(--paper-hi);
    padding: clamp(1.25rem, 3vw, 2.5rem);
    /* M1 斜切楔形:右下角斜切 */
    clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--cut)), 0 100%);
    padding-block-end: calc(clamp(1.25rem, 3vw, 2.5rem) + var(--cut));
  }

  .hero__title {
    color: var(--paper-hi);
    /* 楔形块内的字号以块宽为基准 */
    font-size: calc(var(--mega-fit) * 100cqw * 0.62);
    max-width: 100%;
  }

  .hero__rule {
    margin-block: clamp(1rem, 2.5vw, 1.75rem);
    color: var(--paper-hi);
  }

  .hero__facts {
    font-size: var(--step-1);
    font-weight: 700;
    line-height: 1.6;
    letter-spacing: 0.02em;
  }

  /* 打字机光标:facts 结尾的闪烁方块,呼应"招新进行中"。
     纯装饰 —— 故 aria-hidden;用 background 不用 border,不占额外行高。 */
  .caret {
    display: inline-block;
    width: 0.6em;
    height: 1.05em;
    margin-inline-start: 0.18em;
    background: currentColor;
    translate: 0 0.16em;
    animation: caret-blink 1.05s steps(1, end) infinite;
  }

  @keyframes caret-blink {
    0%, 45% { opacity: 1; }
    46%, 100% { opacity: 0; }
  }

  .hero__cta {
    display: inline-flex;
    align-items: center;
    gap: 0.75rem;
    margin-block-start: clamp(1.25rem, 3vw, 2rem);
    padding: 0.875rem 1.5rem;
    background: var(--signal);
    color: var(--ink);
    font-weight: 900;
    font-size: var(--step-1);
    text-decoration: none;
    /* 黄块:不圆角、不阴影 —— 面积纪律与印刷感 */
    border: var(--rule) solid var(--ink);
  }

  .hero__cta:hover {
    background: var(--ink);
    color: var(--signal);
    border-color: var(--signal);
  }

  .hero__cta-no {
    font-family: var(--font-mono);
    font-weight: 700;
  }

  /* 图:与左边界对齐,右侧留出同宽边距(改版前它向右冲出画面 16px 贴边) */
  .hero__figure {
    position: relative;
  }

  .hero__figure img {
    width: 100%;
    height: auto;
  }

  /* M5 色块压图:蓝块必须溢出到图外,完全压在图内会变贴纸感 */
  .hero__badge {
    position: absolute;
    inset-block-end: clamp(0.75rem, 2vw, 1.5rem);
    inset-inline-start: clamp(-1.5rem, -2vw, -0.5rem);
    background: var(--blue-900);
    color: var(--paper-hi);
    padding: 0.5rem 1rem;
    font-size: var(--step--1);
    font-weight: 700;
    letter-spacing: 0.08em;
  }
}

/* --------------------------------------------------------------------------
   fixes —— 对既有层的小修正,单独列出便于追溯
   -------------------------------------------------------------------------- */
@layer fixes {
  /* --cut 与 .mega 都用 cqw,但 hero 层没声明任何 container,cqw 会退化到
     视口宽。把 hero__plate 声明为容器,标题/斜切以块宽为基准。 */
  .hero__plate {
    container-type: inline-size;
  }
}

/* --------------------------------------------------------------------------
   about —— 01 关于。M8 反白缺版在此成型
   -------------------------------------------------------------------------- */
@layer about {
  .about__lede {
    font-size: var(--step-2);
    font-weight: 700;
    line-height: 1.6;
    max-width: 24ch;
  }

  /* 协会职能:与 02 设备 的序号列共用一套语言(顶线 + 等宽序号) */
  .about__grid {
    display: grid;
    gap: clamp(1.5rem, 4vw, 3rem);
    grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
    align-items: start;
    margin-block-start: clamp(1.5rem, 4vw, 3rem);
  }

  .about__duties-h {
    font-size: var(--step--1);
    font-weight: 700;
    letter-spacing: 0.22em;
    color: var(--gray-600);
  }

  .duty-list {
    counter-reset: duty;
    display: grid;
    gap: 0;
    margin-block-start: 1rem;
  }

  .duty-list li {
    counter-increment: duty;
    display: grid;
    grid-template-columns: 2.25rem 1fr;
    gap: 0.75rem;
    align-items: baseline;
    border-block-start: 2px solid var(--gray-200);
    padding-block: 0.625rem;
    font-weight: 700;
  }

  .duty-list li::before {
    content: counter(duty, decimal-leading-zero);
    font-family: var(--font-mono);
    font-weight: 700;
    color: var(--blue-700);
  }

  .tbd-list {
    display: grid;
    gap: 0.75rem;
    margin-block-start: clamp(1.5rem, 4vw, 3rem);
    max-width: 34ch;
  }

  .tbd-list > div {
    display: grid;
    grid-template-columns: 7em 1fr;
    gap: 1rem;
    align-items: baseline;
    border-block-start: 2px solid var(--gray-200);
    padding-block: 0.625rem;
  }

  .tbd-list dt {
    font-weight: 700;
    color: var(--gray-600);
  }

  .tbd-list dd {
    font-family: var(--font-mono);
    font-size: var(--step-1);
    letter-spacing: 0.3em;
    color: var(--blue-700);
  }

  /* M8 反白缺版:虚线空位 = "待印的铅字",一眼能数出还有几处没填 */
  .tbd {
    display: inline-block;
    padding: 0.1em 0.45em;
    border: 2px dashed var(--blue-600);
    background: var(--paper-hi);
    white-space: nowrap;
  }
}

/* --------------------------------------------------------------------------
   work —— 02 设备。M6 序号列:横线分隔 + 巨型序号,无圆角无阴影
   -------------------------------------------------------------------------- */
@layer work {
  .num-list {
    display: grid;
    gap: var(--rule);
    grid-template-columns: repeat(auto-fill, minmax(min(17rem, 100%), 1fr));
  }

  .num-list li {
    display: grid;
    gap: 0.5rem;
    padding: 0.75rem;
    background: var(--paper-hi);
    border-block-start: var(--rule) solid var(--ink);
    transition: background 0.2s ease;
  }

  .num-list img {
    width: 100%;
    height: auto;
    cursor: zoom-in;
  }

  .no {
    font-family: var(--font-mono);
    font-weight: 700;
    font-size: var(--step-2);
    line-height: 1;
    color: var(--blue-700);
  }

  /* M6:hover 整行反白 */
  .num-list li:hover {
    background: var(--blue-900);
  }

  .num-list li:hover .no {
    color: var(--signal);
  }
}

/* --------------------------------------------------------------------------
   (03 现场的样式在文件后段的 @layer wall —— 它必须排在 photos 之后才能
    压过 .shot__cap 的占位与边距,故不放在这个位置)
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   training —— 04 训练。M3 放射线(右上角出射,静态)+ 三列网格 + 文件块
   -------------------------------------------------------------------------- */
@layer training {
  #training {
    position: relative;
    /* 与 02 设备 同一套卡片列表 -> 区块底色也跟设备一样用 --paper,
       否则 paper-hi 的卡片压在 paper-hi 的底上看不出卡片边界 */
    background: var(--paper);
    overflow: clip;
  }

  /* M3 放射线:自右上角出射的细条,径向遮罩淡出,不参与动画 */
  #training::before {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: repeating-conic-gradient(
      from -60deg at 100% 0%,
      transparent 0deg 8deg,
      var(--gray-200) 8deg 9deg
    );
    -webkit-mask-image: radial-gradient(
      60rem 60rem at 100% 0%,
      rgb(0 0 0 / 0.9),
      transparent 65%
    );
    mask-image: radial-gradient(
      60rem 60rem at 100% 0%,
      rgb(0 0 0 / 0.9),
      transparent 65%
    );
  }

  #training .sec__inner {
    position: relative;
  }

  .grid-3 {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(14rem, 100%), 1fr));
    gap: var(--rule);
  }

  .grid-3 img {
    width: 100%;
    height: auto;
    cursor: zoom-in;
  }

  /* 竞赛目录:蓝块压底 + 内嵌实时预览。预览用浏览器原生 PDF 阅读器
     (<embed>),零依赖、不增交付体积;PDF 的 src 由 js/pdfview.js 在
     预览区进视口时才装,1.2MB 不阻塞首屏。 */
  .docs {
    margin-block-start: clamp(2rem, 5vw, 3.5rem);
    padding: clamp(1.25rem, 3vw, 2rem);
    background: var(--blue-900);
    color: var(--paper-hi);
    max-width: 56rem;          /* 预览面要够宽才看得清 PDF */
  }

  .docs .kicker {
    color: var(--gray-300);
  }

  .pdfv {
    margin-block-start: 0.75rem;
  }

  .pdfv__tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
  }

  .pdfv__tab {
    padding: 0.5rem 0.875rem;
    background: transparent;
    color: var(--paper-hi);
    border: 2px solid var(--gray-300);
    font-weight: 700;
    font-size: var(--step--1);
    letter-spacing: 0.04em;
    cursor: pointer;
    text-align: start;
  }

  .pdfv__tab:hover {
    border-color: var(--signal);
    color: var(--signal);
  }

  .pdfv__tab[aria-selected='true'] {
    background: var(--signal);
    color: var(--ink);
    border-color: var(--signal);
  }

  /* 预览面:蓝块里贴一张"纸",阅读器自绘内容 */
  .pdfv__pane {
    position: relative;
    margin-block-start: 0.75rem;
    background: var(--paper);
    border: 2px solid var(--gray-300);
    min-height: clamp(20rem, 62vh, 36rem);
  }

  .pdfv__ph {
    padding: 1rem;
    color: var(--gray-600);
    font-size: var(--step--1);
  }

  .pdfv__embed {
    display: block;
    width: 100%;
    height: clamp(20rem, 62vh, 36rem);
  }

  .pdfv__fallback {
    margin-block-start: 0.75rem;
    font-size: var(--step--1);
    color: var(--gray-300);
  }

  .pdfv__fallback a {
    color: var(--signal);
    font-weight: 700;
    text-underline-offset: 0.25em;
  }

  .pdfv__open {
    margin-inline-end: 0.75rem;
  }

  .docs noscript ul {
    display: grid;
    gap: 0.5rem;
    margin-block-start: 0.75rem;
  }

  .docs noscript a {
    color: var(--signal);
    font-weight: 700;
  }

  .docs__note {
    color: var(--gray-300);
    font-size: var(--step--1);
  }
}

/* --------------------------------------------------------------------------
   visit —— 05 参访
   -------------------------------------------------------------------------- */
@layer visit {
  #visit img {
    width: 100%;
    height: auto;
    cursor: zoom-in;
  }
}

/* --------------------------------------------------------------------------
   photos —— 照片交互:悬停/聚焦 → 变彩色 + 轻微放大 + 显出图注。
   位置放在各章节层之后,故能压过 .num-list img / .grid-3 img / #visit img
   的尺寸与光标规则(层优先级先于特异性)。
   结构:figure.shot > span.shot__frame > (img.shot__duo + img.shot__color)
                              + figcaption.shot__cap
   彩色层由 js/photo.js 悬停时才装入 data-src —— 首屏流量与改造前一致。
   -------------------------------------------------------------------------- */
@layer photos {
  .shot {
    position: relative;
  }

  /* 裁切框:放大的图被裁在框内,不越出网格 */
  .shot__frame {
    position: relative;
    display: block;
    overflow: hidden;
  }

  .shot__frame img {
    width: 100%;
    height: auto;
    transition: transform 0.5s cubic-bezier(0.2, 0.7, 0.2, 1);
  }

  /* 彩色层:压在双色调之上,默认全透明 */
  .shot__color {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0;
    transition: opacity 0.3s ease;
    pointer-events: none;
  }

  .shot:hover .shot__color,
  .shot:focus-within .shot__color,
  .num-list li:hover .shot__color {
    opacity: 1;
  }

  /* 触屏没有 hover:彩色进度由 photo.js 按"图片在视口里的位置"逐帧写入
     --reveal(0→1),所以这里不加 transition —— 过渡曲线就是滚动本身,
     再加时间过渡反而会让它"追不上"滚动、显得一顿一顿。 */
  @media (hover: none) {
    .shot__color {
      opacity: var(--reveal, 1);
      transition: none;
    }
  }

  .shot:hover .shot__frame img,
  .shot:focus-within .shot__frame img,
  .num-list li:hover .shot__frame img {
    transform: scale(1.045);
  }

  /* 图注:占位常驻(悬停显字不跳版),字默认透明 */
  .shot__cap {
    min-height: 1.5em;
    margin-block-start: 0.4rem;
    font-size: var(--step--1);
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--gray-600);
    opacity: 0;
    translate: 0 0.25rem;
    transition: opacity 0.22s ease, translate 0.22s ease;
  }

  .shot:hover .shot__cap,
  .shot:focus-within .shot__cap,
  .num-list li:hover .shot__cap {
    opacity: 1;
    translate: 0 0;
  }

  /* 02 设备:整行反白时图注改用反白字 */
  .num-list li:hover .shot__cap {
    color: var(--paper-hi);
  }

  /* 触屏没有 hover:图注常显,否则文字永远看不到 */
  @media (hover: none) {
    .shot__cap {
      opacity: 1;
      translate: 0 0;
    }
  }

  /* 05 参访:单图限宽(原来是 #visit img 的 max-width,现在移到容器上) */
  #visit .visit__wrap {
    max-width: 56rem;
  }

  @media (prefers-reduced-motion: reduce) {
    .shot__frame img {
      transition: none;
    }
  }
}

/* --------------------------------------------------------------------------
   wall —— 03 现场:无缝拼贴墙。
   每行铺满,行内按各图的 --ar(宽高比)分配宽度,行高 = 行宽 / 该行比例和,
   于是既不裁切、也无缝隙、不倾斜:9 张连成一块整墙。
   图注改成压在图上(否则 .shot__cap 的占位会在每格底部切出条纹)。
   本层必须排在 photos 之后,才压得过 .shot__cap 的占位与边距。
   -------------------------------------------------------------------------- */
@layer wall {
  .wall {
    margin-block: clamp(1.5rem, 4vw, 3rem);
  }

  .wall__row {
    display: flex;
  }

  .wall__row .shot {
    flex: var(--ar, 1) 1 0;
    min-width: 0;
  }

  .wall .shot__cap {
    position: absolute;
    inset-inline: 0;
    inset-block-end: 0;
    min-height: 0;
    margin: 0;
    padding: 0.4rem 0.6rem;
    background: var(--blue-900);
    color: var(--paper-hi);
  }

  /* 窄屏:改 3 列等格(裁切填满)。折行方案在窄屏会留一张通栏的大图,
     节奏被打断;等格更稳,也仍是"无缝一块"。 */
  @media (max-width: 40rem) {
    .wall__row {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
    }

    .wall__row .shot {
      aspect-ratio: 1 / 1;
    }

    .wall__row .shot__frame {
      height: 100%;
    }

    .wall__row .shot__frame img {
      height: 100%;
      object-fit: cover;
    }
  }
}

/* --------------------------------------------------------------------------
   join —— 06 加入。M7 楔子插入圆:白圆环 + 黄楔子 + 二维码靶心
   楔子在二维码 z 轴之下,只从边缘探出 —— 绝不盖住码面,扫描不受影响
   -------------------------------------------------------------------------- */
@layer join {
  .sec--join {
    background: var(--blue-700);
    color: var(--paper-hi);
  }

  .sec--join .sec-no {
    color: var(--signal);
  }

  .sec--join .rule {
    color: var(--paper-hi);
  }

  .join__grid {
    display: grid;
    gap: clamp(2rem, 5vw, 4rem);
    align-items: center;
  }

  @media (min-width: 760px) {
    .join__grid {
      grid-template-columns: minmax(0, 1fr) auto;
    }
  }

  .join__group {
    font-size: var(--step-1);
    font-weight: 700;
  }

  .join__group strong {
    display: block;
    font-family: var(--font-mono);
    font-size: var(--step-3);
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--signal);
    margin-block-start: 0.375rem;
  }

  .join__hint {
    color: var(--gray-300);
    margin-block-start: 0.75rem;
  }

  .join__qr {
    position: relative;
    width: min(15rem, 62vw);
    margin-inline: auto;
    padding: 0; /* 环与楔子的定位基准 */
  }

  /* 白圆环:二维码背后的"圆" */
  .join__qr::after {
    content: '';
    position: absolute;
    inset: -14%;
    border: var(--rule) solid var(--paper-hi);
    border-radius: 50%;
    z-index: 0;
    pointer-events: none;
  }

  /* 黄楔子:从左上刺入,尖端越过圆心偏向对侧(M7 的力量感要求) */
  .join__qr::before {
    content: '';
    position: absolute;
    z-index: 0;
    top: 12%;
    left: -22%;
    width: 52%;
    aspect-ratio: 4 / 3;
    background: var(--signal);
    clip-path: polygon(0 0, 100% 38%, 8% 100%);
  }

  .join__qr img {
    position: relative;
    z-index: 1;                    /* 码面永远在最上,不被楔子盖住 */
    width: 100%;
    height: auto;
    background: var(--paper-hi);
    padding: 5%;                   /* 兜底静区:交付 PNG 是否自带白边不可知 */
  }

  .join__qr figcaption {
    position: relative;
    z-index: 1;
    text-align: center;
    font-size: var(--step--1);
    font-weight: 700;
    letter-spacing: 0.14em;
    margin-block-start: 0.75rem;
  }
}

/* --------------------------------------------------------------------------
   reveal —— 入场。html.js 由 nav.js 首行添加;JS 不跑则全部可见。
   hero 不参与(首屏不播动画,不推迟 LCP)。
   -------------------------------------------------------------------------- */
@layer reveal {
  html.js .sec {
    opacity: 0;
    translate: 0 1.5rem;
    transition: opacity 0.6s ease, translate 0.6s ease;
  }

  html.js .sec.is-in {
    opacity: 1;
    translate: 0 0;
  }
}

/* --------------------------------------------------------------------------
   lightbox —— js/lightbox.js 动态注入的 <dialog>
   -------------------------------------------------------------------------- */
@layer lightbox {
  .lightbox {
    border: none;
    padding: 0;
    background: transparent;
    /* reset 层的 `* { margin: 0 }` 会盖掉浏览器给 <dialog> 的 margin:auto,
       弹窗于是贴死在左上角(实测 dlg 落在 0,0)。这里补回来才居中。
       作者样式优先于 UA 样式,所以必须显式写,不能靠默认。 */
    margin: auto;
    max-width: min(92vw, 68rem);
    max-height: 92svh;
  }

  .lightbox::backdrop {
    background: rgb(4 16 31 / 0.9);
  }

  .lightbox__close {
    position: absolute;
    top: 0;
    inset-inline-end: 0;
    z-index: 1;
    padding: 0.625rem 1rem;
    background: var(--signal);
    color: var(--ink);
    border: none;
    border-block-end: var(--rule) solid var(--ink);
    border-inline-start: var(--rule) solid var(--ink);
    font-weight: 900;
    cursor: pointer;
  }

  .lightbox__fig {
    position: relative;
  }

  .lightbox img {
    width: 100%;
    height: auto;
    max-height: 82svh;
    object-fit: contain;
    background: var(--paper);
  }

  .lightbox figcaption {
    /* 深蓝底 + 白字 —— 用户的设计,2026-10 明确要求改回这个版本。
       备注:同一款字压深底会比浅底显胖(光渗),但这属于他的设计选择,不要自作主张换底色。
       字号/字距/字重与正文图注对齐这部分保留(那不是设计,是排版一致性)。 */
    background: var(--blue-900);
    color: var(--paper-hi);
    padding: 0.75rem 1rem;
    font-size: var(--step--1);
    font-weight: 700;
    letter-spacing: 0.04em;
  }
}

/* --------------------------------------------------------------------------
   debug —— URL 带 ?debug 时 nav.js 给 <html> 加 .debug:
   全部待填占位描红,发布前必须归零
   -------------------------------------------------------------------------- */
@layer debug {
  html.debug .tbd {
    outline: 3px solid #b8002e;
    outline-offset: 3px;
  }
}

/* --------------------------------------------------------------------------
   reduce-motion —— 系统开启后:滚动瞬时、放射线/蒙太奇带静止
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  /* 上面的规零会让光标停在"灭"的那一帧 —— 改常亮 */
  .caret {
    animation: none !important;
    opacity: 1;
  }
}
