/* ============================================================
   WALKER — prototype v2(全黑底版)
   ============================================================ */

:root {
  --bg: #050507;
  --ink: #f2f0ec;
  --ink-soft: rgba(242, 240, 236, 0.55);
  --hair: rgba(255, 255, 255, 0.12);
  --accent: #e6193c;

  /* 几何无衬线体系(Nikki 用的是 Futura PT,这里用它的免费复刻 Jost)。
     界面小字沿用 Helvetica Neue —— Mac/iPhone 上是系统自带,零加载。 */
  --font-frame: "Jost", "Helvetica Neue", "Noto Sans SC", "Noto Sans JP", Arial, sans-serif;
  --font-display: "Jost", "Helvetica Neue", "Noto Sans SC", "Noto Sans JP", Arial, sans-serif;
  --font-narrative: "Jost", "Helvetica Neue", "Noto Sans SC", "Noto Sans JP", Arial, sans-serif;
  --font-mono: "Helvetica Neue", "Jost", "Noto Sans SC", Arial, sans-serif;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-frame);
  font-size: 15px;
  font-weight: 400;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* 全站大写 */
  text-transform: uppercase;
}

/* 关于页的长段落保持原样,全大写会读不下去 */
.page .narrative { text-transform: none; }

body[data-theme="dark"] {
  --bg: #050507;
  --ink: #f2f0ec;
  --ink-soft: rgba(242, 240, 236, 0.55);
  --hair: rgba(255, 255, 255, 0.12);
  background: var(--bg);
  color: var(--ink);
}

/* Lenis 惯性滚动激活时,关掉浏览器自带的平滑滚动避免叠加 */
html.lenis { scroll-behavior: auto; }
.lenis.lenis-smooth { scroll-behavior: auto; }

a { color: inherit; text-decoration: none; }
::selection { background: var(--accent); color: #fff; }
img { display: block; max-width: 100%; }

/* 版权保护:图片不可拖走、不可选中(挡不住截图,但能挡住随手保存) */
img, video {
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
  user-select: none;
}

/* ---------- 页面过渡(四种模式,transitions.html 里选) ---------- */

body[data-transition="fade"] { animation: pageIn 0.55s cubic-bezier(0.25, 0.1, 0.25, 1) both; }

@keyframes pageIn {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}

body[data-transition="fade"].leaving {
  opacity: 0;
  transform: translateY(-10px);
  transition: opacity 0.28s cubic-bezier(0.4, 0, 0.6, 1), transform 0.28s cubic-bezier(0.4, 0, 0.6, 1);
}

/* 遮罩层(blackout / curtain 共用)。默认必须透明 */
#wipe {
  position: fixed;
  inset: 0;
  z-index: 999;
  pointer-events: none;
  background: #050507;
  opacity: 0;
}

body[data-transition="curtain"] #wipe { opacity: 1; }

/* 兜底:一旦判定"不该有黑幕",直接不渲染它。
   display 不参与 CSS 过渡,所以永远不会被冻结在全黑那一帧。 */
#wipe.off { display: none !important; }

body[data-transition="blackout"] #wipe {
  opacity: 0;
  transition: opacity 0.42s cubic-bezier(0.4, 0, 0.6, 1);
}

body[data-transition="blackout"].leaving #wipe { opacity: 1; }

body[data-transition="curtain"] #wipe {
  transform: translateX(-101%);
  transition: transform 0.44s cubic-bezier(0.65, 0, 0.35, 1);
}

body[data-transition="curtain"].leaving #wipe { transform: translateX(0); }

body[data-transition="cut"] #wipe { display: none; }

@media (prefers-reduced-motion: reduce) {
  body[data-transition] { animation: none; }
  #wipe { display: none !important; }
  .reveal { transition: none; opacity: 1; transform: none; }
}

/* ---------- 顶部导航(共用) ---------- */

#site-nav {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 16px 40px;
  border-bottom: 1px solid var(--hair);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px);
}

.nav-brand {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(19px, 1.7vw, 24px);
  letter-spacing: 0.08em;
}

/* 桌面:菜单和语言并排放在右边(手机上这个容器会变成下拉面板) */
.nav-drop { display: flex; align-items: center; gap: 26px; }

.nav-links { display: flex; gap: 24px; }

.nav-links a {
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
}

.nav-links a:hover { border-bottom-color: var(--accent); color: var(--accent); }

.lang { display: flex; gap: 10px; font-size: 12px; color: var(--ink-soft); }

.lang button {
  background: none; border: none; font: inherit; color: inherit;
  cursor: pointer; padding: 0; letter-spacing: 0.08em;
}

.lang button.active { color: var(--ink); text-decoration: underline; text-underline-offset: 4px; }

/* ============================================================
   幻灯片式面板(deck):一次滚轮 = 翻一整页
   .deck-on 由 JS 在确认 GSAP + Observer 就绪后加到 <html>,
   没加载成功时页面退回普通竖向滚动,内容照样能看。
   ============================================================ */

.deck-on, .deck-on body { height: 100%; overflow: hidden; }

/* 用 dvh:iOS Safari 的 100vh 含了会自动收起的地址栏,底部内容会被切掉 */
.deck-on #deck {
  position: fixed;
  inset: 0;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

.deck-on .panel { position: absolute; inset: 0; }

.deck-on .site-foot { display: none; }

.panel {
  position: relative;
  min-height: 100vh;
  min-height: 100dvh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  will-change: transform;
  background: var(--bg);
}

/* 世界摘要面板:内容(标题+简介+封面行)矮屏下可能比一屏还高。
   原来 justify-content:center 会让上下两头一起被 .panel 的
   overflow:hidden 裁掉,卡在正中间的一截,翻页手势又抢走了
   本该用来滚动的那次滑动——两个问题加一起就是"只看得到中间、
   想滑动看全反而直接翻页"。改成顶对齐 + 允许内部滚动,配合
   js/motion.js 里 initDeck() 的边界判断(滚到头了才真的翻页)。 */
.panel--world {
  justify-content: flex-start;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.panel--world .panel-inner {
  padding-top: clamp(84px, 13vh, 132px);
  padding-bottom: 48px;
}

.panel-inner {
  position: relative;
  z-index: 2;
  padding: 0 clamp(20px, 4vw, 56px);
  width: 100%;
}

/* 翻页时压在下面那一页上的暗幕 */
.panel-dim {
  position: absolute;
  inset: 0;
  z-index: 3;
  background: #000;
  opacity: 0;
  pointer-events: none;
}

/* 右侧页码点 */
.deck-dots {
  position: fixed;
  right: clamp(14px, 2vw, 26px);
  top: 50%;
  transform: translateY(-50%);
  z-index: 150;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.deck-dots button {
  width: 8px; height: 8px;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.45);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  transition: background 0.35s ease, border-color 0.35s ease, transform 0.35s ease;
}

.deck-dots button.on {
  background: var(--accent);
  border-color: var(--accent);
  transform: scale(1.35);
}

/* ---------- 落地页:开屏 ---------- */

.hero, .panel--hero {
  position: relative;
  overflow: hidden;
  color: #fff;
}

.hero-media {
  position: absolute; inset: 0;
  background:
    radial-gradient(120% 90% at 18% 12%, #1b2fd4 0%, transparent 52%),
    radial-gradient(130% 100% at 85% 80%, #e6193c 0%, transparent 58%),
    #07070a;
}

.hero-media img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}

.hero-media::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0.15) 0%, transparent 40%, rgba(0,0,0,0.62) 100%);
}

/* ---------- 首屏满屏叠卡 ----------
   五个世界各占一竖条铺满整屏,鼠标滑到哪条,哪条展开占大半屏。
   卡片之间有细缝和投影,像一叠错开的卡纸。 */

.panel--hero { padding: 0; justify-content: stretch; }

/* 叠卡不贴边:四周留白,让它像摊在桌面上的一组照片,而不是一张壁纸 */
.fan {
  position: absolute;
  inset: clamp(60px, 8.5vh, 104px) clamp(14px, 3.4vw, 62px) clamp(54px, 8vh, 92px);
  display: flex;
  gap: 0;
}

.fan-card {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  display: block;
  background: #0a0a0c;
}

.fan-card + .fan-card {
  border-left: 1px solid rgba(255, 255, 255, 0.16);
  box-shadow: -26px 0 54px rgba(0, 0, 0, 0.55);
}

.fan-media { position: absolute; inset: 0; }

/* 照片跟着竖条本身的宽度走。
   之前固定 62vw,竖条只有 100 来像素时等于把照片放大六七倍、只看得到中间一条,
   现在按竖条尺寸裁切,展开时自然露出更多。多张时叠在一起由 JS 做轮播。 */
.fan-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  max-width: none;
  transform: scale(1.02); /* 只留一点点余量,免得边缘出现缝 */
}

/* 轮播:第一张先亮着,其余等 JS 接管(JS 没跑起来时也只会看到第一张) */
.fan-img { opacity: 0; }
.fan-img:first-of-type { opacity: 1; }

.fan-dim {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0.25) 0%, rgba(0,0,0,0.15) 45%, rgba(0,0,0,0.85) 100%), #000;
  opacity: 0.34;
  pointer-events: none;
}

.fan-label {
  position: absolute;
  left: clamp(14px, 1.4vw, 26px);
  bottom: clamp(60px, 9vh, 110px);
  right: 12px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  pointer-events: none;
  text-shadow: 0 2px 16px rgba(0, 0, 0, 0.9);
}

.fan-no {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.24em;
  color: var(--accent);
}

.fan-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(20px, 2.4vw, 46px);
  line-height: 0.98;
  text-transform: uppercase;
  color: #fff;
}

.fan-sub {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  color: rgba(255, 255, 255, 0.85);
  white-space: nowrap;
}

/* ---------- 首屏中央的名字 ----------
   名字压在照片正中(Nikki 的做法),四周留白让它有呼吸(Karel 的克制)。 */

.hero-mark {
  position: absolute;
  inset: 0;
  z-index: 4;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(10px, 1.6vh, 20px);
  pointer-events: none;
  text-align: center;
  padding: 0 6vw;
}

/* 名字克制:是一个字标,不是一张海报。字距拉开撑住画面。 */
.hero-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(clamp(24px, 3.4vw, 52px) * var(--scale-hero-name, 1));
  line-height: 1;
  letter-spacing: 0.16em;
  text-indent: 0.16em; /* 抵消末字后多出的字距,保证真正居中 */
  text-transform: uppercase;
  color: #fff;
  text-shadow: 0 6px 50px rgba(0, 0, 0, 0.5);
}

.hero-tag {
  font-family: var(--font-frame);
  font-weight: 400;
  font-size: clamp(10px, 0.8vw, 12px);
  letter-spacing: 0.32em;
  text-indent: 0.32em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.82);
  text-shadow: 0 2px 22px rgba(0, 0, 0, 0.9);
}

/* ---------- 首页底部:联系方式小图标 ---------- */

.social {
  position: fixed;
  left: clamp(16px, 3.4vw, 62px);
  bottom: calc(clamp(16px, 2.6vh, 30px) + env(safe-area-inset-bottom));
  z-index: 160;
  display: flex;
  align-items: center;
  gap: 4px;
}

.social a {
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.65);
  transition: color 0.3s ease, transform 0.3s ease;
}

.social a:hover { color: var(--accent); transform: translateY(-2px); }

.social svg { width: 17px; height: 17px; display: block; }

/* 窄屏:改成竖向五行。
   之前把标签挪到"每条自己的垂直居中",结果和全屏居中的名字撞在一起
   (名字飘在正中央,不管挪到哪条,总有一条的居中位置正好在屏幕中央)。
   现在改回贴在每条底部——和桌面版同一个逻辑,只是数值按手机高度重新给,
   这样标签和名字天然分居上下,不会叠字。 */
@media (max-width: 700px) {
  .fan {
    flex-direction: column;
    inset: 58px 10px calc(46px + env(safe-area-inset-bottom));
  }
  .fan-card + .fan-card {
    border-left: none;
    border-top: 1px solid rgba(255, 255, 255, 0.16);
    box-shadow: 0 -18px 36px rgba(0, 0, 0, 0.5);
  }
  .fan-media img { width: 100%; }
  .fan-label {
    bottom: 10px;
    top: auto;
    transform: none;
    left: 14px;
    right: 14px;
    align-items: flex-start;
    text-align: left;
    gap: 2px;
  }
  .fan-name { font-size: clamp(15px, 4.6vw, 20px); }
  .fan-sub { font-size: 9.5px; }
}

.hero-cue {
  position: absolute;
  z-index: 2;
  right: clamp(20px, 4vw, 56px); bottom: 26px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  color: rgba(255,255,255,0.75);
  animation: cue 2.4s ease-in-out infinite;
}

@keyframes cue {
  0%, 100% { transform: translateY(0); opacity: 0.75; }
  50% { transform: translateY(6px); opacity: 1; }
}

/* ---------- 首屏:手机端专用(概念 2 · Reel 的视觉语言) ----------
   桌面维持原本的叠卡首屏不变;手机(≤700px)首屏换成
   全屏封面轮播 + 巨字世界名 + 跳转药丸 + 底部跑马灯,
   数据仍来自 content.json(js/render.js 的 renderReelMobile),
   动效见 js/motion.js 的 initReelMobile。
   翻页系统(向下滑进入各世界详情面板)完全不受影响,
   药丸和轮播只是首屏内部的展示层。 */
.reel-mobile { display: none; }

@media (max-width: 700px) {
  .fan, .hero-mark { display: none; }

  .reel-mobile {
    display: block;
    position: absolute;
    inset: 0;
    z-index: 1;
    /* 整块首屏都是滑动切换的手势区(见 js/motion.js initReelSwipe),
       不能让浏览器自己也把上下滑动理解成"页面滚动"去抢手势——不加
       这个的话,往上滑那个方向经常会被浏览器自己的滚动/回弹手势
       先一步吃掉,表现出来就是"只有一个方向能切,另一个方向没反应"。 */
    touch-action: none;
  }

  .reel-slide {
    position: absolute; inset: 0;
    opacity: 0;
    transition: opacity 1.5s ease;
  }
  .reel-slide.on { opacity: 1; }
  /* 之前这里叠了一层大范围的线性+径向暗幕,主图被压得看不清。
     现在只在顶部(导航条下面)和底部(跑马灯)留一点点暗,中间大片
     留透明,文字的可读性靠下面 .reel-item 自己的 text-shadow 撑住,
     不再靠糊住整张照片来换可读性。 */
  .reel-slide::after {
    content: "";
    position: absolute; inset: 0;
    z-index: 1;
    background: linear-gradient(180deg, rgba(0,0,0,.26) 0%, transparent 22%, transparent 60%, rgba(0,0,0,.5) 100%);
  }

  /* 一个世界内部自己的 hero 图轮播——每个世界一叠图,同一时间只有
     一张 .on,交叉淡入淡出切换。世界级的显示/隐藏(.reel-slide.on)
     和世界内部"现在轮到第几张图"(.reel-slide-img.on)是两层独立的
     开关,具体轮到第几张、什么时候轮完一圈交给 js/motion.js 的
     initReelMobile 算,这里只管淡入淡出的视觉。 */
  .reel-slide-img {
    position: absolute; inset: 0;
    opacity: 0;
    background-size: cover;
    background-position: center;
    transition: opacity 1.1s ease;
  }
  .reel-slide-img.on { opacity: 1; }

  .reel-grain {
    position: absolute; inset: 0; z-index: 2; pointer-events: none;
    opacity: .13; mix-blend-mode: overlay;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  }

  .reel-center {
    position: relative; z-index: 3; height: 100%;
    /* 不用 justify-content:center——列表里当前世界是第一项,后面还跟着
       四个小字,整块居中会把"第一项"顶到中心以上,越往下加内容越明显。
       改成 flex-start + 手动 padding-top,这样 padding-top 数值直接
       等于列表顶部的位置,好精确控制"当前世界"这行落在屏幕哪。 */
    display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
    text-align: center;
    padding: 0 8vw;
    padding-top: calc(54vh - 53px); /* 略低于数学正中,视觉上更"落地";53px ≈ 大字槽位高度的一半 */
    padding-bottom: 64px; /* 给底部跑马灯留位置,内容不被压住 */
    overflow-y: auto; /* 矮屏(如 SE)兜底:内容超高时可以滚,不会被裁掉 */
  }

  /* 五个世界的先后顺序固定不变(不会因为切换而重排)。"大字槽位"
     是屏幕上一个固定坐标;每次切换,整份列表按固定顺序整体挪动一行
     ——当前世界那一条走到槽位、放大,原来在槽位的那条挪到上面
     变小,后面的依次跟着往上顶一行,道理跟一个转动的价目表/老虎机
     差不多。每一条的具体偏移量由 js/motion.js initReelMobile 用
     transform 直接算(REEL_ROW_H 一个常量控制行距),这里只负责
     "允许绝对定位、允许过渡"。 */
  .reel-list {
    position: relative;
    width: 100%;
    height: 0;
  }

  .reel-item {
    all: unset;
    box-sizing: border-box;
    position: absolute;
    left: 0; right: 0; top: 0;
    cursor: pointer;
    display: block;
    width: 100%;
    text-align: center;
    color: rgba(255, 255, 255, 0.65);
    font-family: var(--font-display);
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    font-size: 15px;
    line-height: 1.3;
    padding: 4px 0;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.7); /* 暗幕拿掉了,小字也要靠这个才认得清 */
    transition: transform 0.5s cubic-bezier(0.22, 0.85, 0.3, 1),
      font-size 0.5s cubic-bezier(0.22, 0.85, 0.3, 1), color 0.4s ease;
  }

  .reel-item-cat {
    display: block;
    font-family: var(--font-mono);
    font-weight: 400;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    font-size: 10px;
    color: rgba(255, 255, 255, 0.85);
    text-shadow: 0 2px 8px rgba(0, 0, 0, 0.75);
    max-height: 0;
    opacity: 0;
    overflow: hidden;
    transition: max-height 0.4s ease, opacity 0.3s ease, margin-top 0.4s ease;
  }

  .reel-item.on {
    color: #fff;
    font-size: clamp(38px, 13vw, 62px);
    text-shadow: 0 4px 22px rgba(0, 0, 0, 0.8);
  }
  .reel-item.on .reel-item-cat {
    max-height: 20px;
    opacity: 1;
    margin-top: 5px;
  }

  /* 点进这个世界 —— 列表只负责预览切换,真正的"进入"靠这条独立的链接,
     href 跟着当前预览的世界变(见 js/motion.js initReelMobile 的 show()) */
  .reel-enter {
    /* 和 .reel-item 共用同一套绝对定位坐标系,位置由 initReelMobile
       算(永远落在当前"整叠列表"最下面那一条的下方一点)。 */
    position: absolute;
    left: 0; right: 0; top: 0;
    display: block;
    text-align: center;
    font-family: var(--font-mono);
    font-size: 10.5px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: #fff;
    text-shadow: 0 2px 8px rgba(0, 0, 0, 0.75);
    padding: 4px 2px;
    transition: transform 0.5s cubic-bezier(0.22, 0.85, 0.3, 1), border-color 0.25s ease, color 0.25s ease;
  }
  .reel-enter::after {
    content: "";
    display: block;
    width: 34px;
    height: 1px;
    margin: 4px auto 0;
    background: rgba(255, 255, 255, 0.55);
    transition: background 0.25s ease;
  }
  .reel-enter:hover::after, .reel-enter:active::after { background: var(--accent); }
  .reel-enter:hover, .reel-enter:active { color: var(--accent); }

  .reel-ticker-wrap {
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
    overflow: hidden;
    border-top: 1px solid rgba(255, 255, 255, 0.14);
    background: rgba(5, 5, 6, 0.55);
    backdrop-filter: blur(6px);
    padding: 9px 0 calc(9px + env(safe-area-inset-bottom));
  }
  .reel-ticker {
    display: flex; gap: 36px; white-space: nowrap;
    width: max-content;
    animation: reel-tick 24s linear infinite;
  }
  .reel-ticker span {
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 0.14em;
    color: rgba(255, 255, 255, 0.62);
    text-transform: uppercase;
  }
  .reel-ticker span b { color: #fff; font-weight: 600; }

  @keyframes reel-tick {
    from { transform: translateX(0); }
    to { transform: translateX(-50%); }
  }

  /* 联系方式图标原来贴底,现在底部多了一条跑马灯,把图标抬到它上面 */
  .social { bottom: calc(46px + env(safe-area-inset-bottom)); }
}

@media (prefers-reduced-motion: reduce) {
  .reel-slide { transition: none; }
  .reel-ticker { animation: none; }
}

/* ---------- 落地页:世界区块 ---------- */

.wsec {
  padding: 12vh 40px 10vh;
  border-top: 1px solid var(--hair);
}

.wsec[data-theme="dark"], .wsec[data-theme="light"] {
  background: transparent;
  color: var(--ink);
}

.wsec-head {
  display: flex;
  align-items: baseline;
  gap: 22px;
  flex-wrap: wrap;
}

.wsec-no {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.22em;
  color: var(--accent);
}

.wsec-name {
  font-family: var(--font-display);
  font-size: calc(clamp(38px, 6.2vw, 92px) * var(--scale-world-title, 1));
  font-weight: 800;
  letter-spacing: -0.01em;
  line-height: 1;
  text-transform: uppercase;
}

.wsec-name:hover { color: var(--accent); }

/* 巨字的遮罩框:GSAP 让字从框底"抬"进来 */
.wsec-head a { display: inline-block; overflow: hidden; vertical-align: bottom; }

.wsec-label { font-size: 13px; color: var(--ink-soft); }

.wsec-intro {
  font-family: var(--font-narrative);
  max-width: 34em;
  margin-top: 14px;
  color: var(--ink-soft);
  font-size: clamp(14px, 1.15vw, 17px);
}

/* ---------- 封面卡 ---------- */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: calc(18px * var(--scale-card-gap, 1));
  margin-top: 36px;
}

/* 世界页的项目网格:方形缩略图 + 图下细字,克制干净 */
.cards.cards-big {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  max-width: 1560px;
  gap: 34px 22px;
  margin-top: 0;
}

.card-lg .card-text { gap: 4px; margin-top: 2px; }

@media (max-width: 1400px) {
  .cards.cards-big { grid-template-columns: repeat(3, minmax(0, 1fr)); max-width: 1180px; }
}

@media (max-width: 1100px) {
  .cards.cards-big { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 620px) {
  .cards.cards-big { gap: 20px 12px; }
}

/* 变体 A:lead — 首项大图,编辑部头条式 */
.cards--lead { grid-template-columns: repeat(4, 1fr); }

.cards--lead .card:first-child { grid-column: span 2; grid-row: span 2; }

.cards--lead .card:first-child .card-title { font-size: 16px; }

/* 变体 B:band — 横向胶片带,可左右滑动 */
.cards--band {
  display: flex;
  overflow-x: auto;
  padding-bottom: 16px;
  scroll-snap-type: x proximity;
  scrollbar-width: thin;
}

.cards--band .card { flex: 0 0 300px; scroll-snap-align: start; }

.cards--band .card:nth-child(even) { margin-top: 34px; }

.cards--band .card-enter { flex: 0 0 220px; min-height: auto; }

/* 面板内:一行卡片,高度按屏高走,保证整页不超出一屏 */
.cards--row {
  display: flex;
  gap: clamp(10px, 1vw, 16px);
  margin-top: clamp(16px, 3vh, 34px);
  align-items: flex-start;
}

.cards--row .card { flex: 1 1 0; min-width: 0; }

.cards--row .card-media { aspect-ratio: auto; height: clamp(140px, 30vh, 340px); }

.cards--row .card-enter { min-height: clamp(140px, 30vh, 340px); flex: 0 0 clamp(120px, 12vw, 190px); }

/* 变体 C:stagger — 错落拼贴,轻微倾斜 */
.cards--stagger { grid-template-columns: repeat(4, 1fr); padding-bottom: 30px; }

.cards--stagger .card { transition: transform 0.4s ease; }

.cards--stagger .card:nth-child(odd) { transform: translateY(30px) rotate(-0.8deg); }

.cards--stagger .card:nth-child(even) { transform: translateY(-4px) rotate(0.7deg); }

.cards--stagger .card:hover { transform: translateY(-6px) rotate(0deg); }

.card { display: flex; flex-direction: column; gap: 10px; }

.card-media {
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border-radius: 2px;
}

/* 世界页项目卡:比例由后台每个世界的「封面比例」决定 */
.card-lg .card-media { aspect-ratio: var(--cover-ratio, 9 / 16); }

/* 视频世界的封面卡:竖版 */
.card--v .card-media { aspect-ratio: 9 / 16; }
.card-lg.card--v .card-media { aspect-ratio: var(--cover-ratio, 9 / 16); }

/* 图片比框高一点,留出 GSAP 视差上下移动的余量 */
.card-media img {
  position: absolute;
  left: 0; top: -6%;
  width: 100%; height: 112%;
  object-fit: cover;
  will-change: transform;
}

.card-media .play {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  color: rgba(255,255,255,0.9);
}

.card-text { display: flex; flex-direction: column; gap: 2px; }

.card-title { font-family: var(--font-mono); font-weight: 600; font-size: 13px; letter-spacing: 0.04em; }

.card:hover .card-title { color: var(--accent); }

.card-meta { font-family: var(--font-mono); font-size: 10px; color: var(--ink-soft); letter-spacing: 0.06em; }

.card-enter {
  align-items: center;
  justify-content: center;
  border: 1px solid var(--hair);
  border-radius: 2px;
  min-height: 200px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  transition: all 0.3s ease;
}

.card-enter:hover { border-color: var(--accent); color: var(--accent); }

/* ---------- 滚动渐显(GSAP 接管前的兜底) ---------- */

.reveal { opacity: 0; transform: translateY(28px); transition: opacity 0.7s ease, transform 0.7s ease; }
.reveal.in { opacity: 1; transform: none; }

/* ---------- 顶部滚动进度条 ---------- */

#scroll-progress {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: 0 50%;
  z-index: 200;
  pointer-events: none;
}

/* ---------- 世界页 / 项目页 ---------- */

.world-hero { padding: 10vh 40px 6vh; max-width: 1200px; }

.world-kicker {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.22em;
  color: var(--accent);
}

.world-title {
  font-family: var(--font-display);
  font-size: clamp(52px, 9vw, 130px);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 0.98;
  margin-top: 14px;
}

.world-intro {
  font-family: var(--font-narrative);
  font-size: 17px;
  color: var(--ink-soft);
  max-width: 34em;
  margin-top: 26px;
}

.world-stats { display: flex; gap: 40px; margin-top: 38px; font-family: var(--font-mono); font-size: 12px; color: var(--ink-soft); }

.world-stats b { display: block; font-size: 26px; color: var(--ink); font-family: var(--font-frame); }

.series { padding: 4vh 40px 10vh; }

/* 项目页 */
.proj-hero { padding: 8vh 40px 4vh; max-width: 1200px; }

.proj-back { font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.08em; color: var(--ink-soft); }

.proj-back:hover { color: var(--accent); }

.proj-title { font-family: var(--font-display); font-size: clamp(34px, 5vw, 72px); font-weight: 800; letter-spacing: -0.01em; margin-top: 20px; }

.proj-meta { font-family: var(--font-mono); font-size: 11px; color: var(--ink-soft); margin-top: 10px; letter-spacing: 0.08em; }

/* ---------- 项目内页的照片墙 ----------
   参考 Karel:整块居中,横竖照片无缝拼接、不留缝隙、不裁切。
   基础是纯 CSS 多列排版(JS 没跑起来时的保底)。
   JS 就绪后(js/motion.js initPhotoWall)会把 .ph 重新分进
   三个真正的 flex 列,并且让横构图集中摆在中间那一列——
   这一步 CSS 做不到(多列排版只按"先到先填满当前列"分配,
   不知道哪张是横图),所以交给 JS 算好再搬。 */
.grid {
  column-count: 3;
  column-gap: 0;
  max-width: 1500px;
  margin: 0 auto;
}

@media (max-width: 1100px) { .grid { column-count: 2; } }
@media (max-width: 380px) { .grid { column-count: 1; } }

/* JS 接管后:关掉多列排版,换成真正的三个列容器 */
.grid.js-cols {
  display: flex;
  column-count: initial;
  align-items: flex-start;
}

.grid-col {
  display: flex;
  flex-direction: column;
  flex: 1 1 0;
  min-width: 0;
}

.ph {
  position: relative;
  overflow: hidden;
  display: block;
  break-inside: avoid;
  page-break-inside: avoid;
  margin: 0;
  line-height: 0;
  /* 照片之间零间距、无缝拼贴,但黑白照片贴着深色背景时会看不出彼此的分界。
     用极细的内描边代替真正的留白——不破坏无缝拼贴的观感,又能分清每张图的边缘。 */
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.09);
}

.ph span {
  position: relative;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  color: rgba(255, 255, 255, 0.55);
}

/* 项目页里的真照片 / 视频:按原比例铺满一列,不裁切 */
.ph img, .ph video {
  width: 100%;
  height: auto;
  display: block;
}

/* 没有真照片时的色块占位,靠内联 aspect-ratio 撑出高度 */
.ph.is-placeholder { line-height: 1.6; }

.ph .play-lg { position: absolute; inset: 0; }

.ph .play-lg {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 30px; color: rgba(255,255,255,0.85);
  opacity: 1;
  transition: opacity 0.3s ease;
  pointer-events: none;
}

/* 视频正在自动播放时,播放图标淡出;暂停/还没滚到时淡入回来 */
.ph:has(video[data-wall-video].is-playing) .play-lg { opacity: 0; }

/* 点视频弹出来的大播放器:居中、带声音、原生控制条(自带全屏按钮) */
.video-lightbox {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  background: #050506;
  padding: 4vh 4vw;
}
.video-lightbox[hidden] { display: none; }
.video-lightbox video {
  max-width: 100%;
  max-height: 100%;
  outline: none;
}
.video-lightbox .lb-close {
  position: absolute;
  top: max(20px, env(safe-area-inset-top));
  right: max(20px, env(safe-area-inset-right));
  width: 40px; height: 40px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.1); border: none; color: #fff;
  font-size: 22px; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.video-lightbox .lb-close:hover { background: rgba(255, 255, 255, 0.22); }

/* 比例与跨列 */
.r32 { aspect-ratio: 3 / 2; }
.r23 { aspect-ratio: 2 / 3; }
.r11 { aspect-ratio: 1 / 1; }
.r169 { aspect-ratio: 16 / 9; }
.r916 { aspect-ratio: 9 / 16; }
.c2 { grid-column: span 2; }
.c3 { grid-column: span 3; }
.c4 { grid-column: span 4; }

/* 色彩占位 */
.wash-red { background: radial-gradient(120% 120% at 30% 20%, #d92a48 0%, #6b0415 55%, #130308 100%); }
.wash-blue { background: radial-gradient(120% 120% at 70% 15%, #3550e0 0%, #0d1770 55%, #04061c 100%); }
.wash-green { background: radial-gradient(130% 130% at 50% 10%, #26bd5c 0%, #084a1f 55%, #041407 100%); }
.wash-violet { background: radial-gradient(120% 120% at 40% 80%, #9a35e6 0%, #330960 60%, #0d0416 100%); }
.wash-bw { background: linear-gradient(160deg, #c9c9c9 0%, #6f6f6f 35%, #161616 100%); }
.wash-amber { background: radial-gradient(110% 110% at 50% 90%, #e8a040 0%, #6b3a0e 55%, #170b03 100%); }
.wash-rose { background: radial-gradient(110% 110% at 50% 30%, #f2c4cc 0%, #c98a96 55%, #6b4a52 100%); }
.wash-sky { background: linear-gradient(180deg, #8fb2c7 0%, #d9e2d4 78%, #efe9dc 100%); }

.grain::after {
  content: "";
  position: absolute; inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  opacity: 0.14;
  mix-blend-mode: overlay;
  pointer-events: none;
}

/* 翻页 */
.world-next {
  border-top: 1px solid var(--hair);
  padding: 56px 40px 80px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  color: var(--ink-soft);
}

.world-next a {
  display: inline-block;
  margin-top: 10px;
  font-family: var(--font-display);
  font-size: clamp(26px, 4vw, 50px);
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.world-next a:hover { color: var(--accent); }

/* ---------- 项目页底部:横向可滑动浏览这个世界里所有项目 ----------
   原来这里只有一行"下一个项目"的文字链接,访客看不到封面长什么样。
   现在摆一条可以左右滑的卡片带,每张都是封面图+标题,点哪张跳哪个。
   纯 CSS 的 overflow-x + scroll-snap 做滑动,不需要额外的 JS 手势。 */
.proj-more {
  border-top: 1px solid var(--hair);
  padding: 48px 0 80px;
}

.proj-more-head {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0 40px 18px;
}

.proj-scroll {
  display: flex;
  gap: 14px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  padding: 0 40px 12px;
  -webkit-overflow-scrolling: touch;
}

.proj-scroll-card {
  flex: 0 0 auto;
  width: clamp(140px, 28vw, 210px);
  scroll-snap-align: start;
}

.proj-scroll-media {
  position: relative;
  aspect-ratio: 3 / 4;
  border-radius: 4px;
  overflow: hidden;
  background: #0a0a0c;
}

.proj-scroll-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s ease;
}

.proj-scroll-card:hover .proj-scroll-media img { transform: scale(1.045); }

.proj-scroll-title {
  display: block;
  margin-top: 9px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  letter-spacing: 0.03em;
  color: var(--ink);
}

.proj-scroll-card.current { opacity: 0.55; }
.proj-scroll-card.current .proj-scroll-title { color: var(--ink-soft); }
.proj-scroll-card.current:hover .proj-scroll-media img { transform: none; }

/* ---------- info / shop ---------- */

.page { padding: 10vh 40px; max-width: 820px; }

.page h1 { font-family: var(--font-display); font-size: clamp(36px, 5vw, 64px); font-weight: 800; letter-spacing: -0.01em; }

.page .narrative {
  font-family: var(--font-narrative);
  font-size: 17px;
  line-height: 1.9;
  margin-top: 32px;
  color: var(--ink-soft);
}

.page .narrative em { color: var(--ink); font-style: normal; }

.page .contact-block { margin-top: 48px; font-family: var(--font-mono); font-size: 13px; }

.page .contact-block a { border-bottom: 1px solid var(--hair); padding-bottom: 2px; }

.page .contact-block a:hover { color: var(--accent); border-color: var(--accent); }


.site-foot {
  border-top: 1px solid var(--hair);
  padding: 40px;
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-soft);
  letter-spacing: 0.08em;
  flex-wrap: wrap;
  gap: 12px;
}

.site-foot a:hover { color: var(--accent); }

/* ---------- 响应式 ---------- */

/* 手机:面板里的卡片改成两列,免得四张挤成一条 */
@media (max-width: 700px) {
  .cards--row { flex-wrap: wrap; }
  .cards--row .card { flex: 1 1 calc(50% - 6px); }
  .cards--row .card-media { height: clamp(118px, 19vh, 200px); }
  .cards--row .card-enter {
    flex: 1 1 calc(50% - 6px);
    min-height: clamp(118px, 19vh, 200px);
    /* 卡片数量是单数时,"更多"这张会自己另起一行、只有它一个——
       auto margin 把它推到那一行的右边(用户明确要"右下角"),
       两张卡片正常配对占满一行时,没有多余空间,这条不会有效果。 */
    margin-left: auto;
  }
  .deck-dots { right: 10px; gap: 11px; }
}

@media (max-width: 900px) {
  .wsec, .series, .world-hero, .proj-hero, .world-next, .page, .site-foot { padding-left: 20px; padding-right: 20px; }
  .cards, .cards--lead, .cards--stagger { grid-template-columns: repeat(2, 1fr); gap: calc(12px * var(--scale-card-gap, 1)); }
  .cards--stagger .card:nth-child(odd) { transform: translateY(14px); }
  .cards--band .card { flex-basis: 220px; }
  .hero-cue { right: 20px; }
  .proj-more-head { margin-left: 20px; margin-right: 20px; }
  .proj-scroll { padding-left: 20px; padding-right: 20px; }
}

/* ============================================================
   手机端
   ============================================================
   导航收成菜单按钮;所有可点的东西撑到 44×44;
   避开 iPhone 的刘海与底部横条;字号整体上调。 */

.nav-toggle { display: none; }

@media (max-width: 820px) {
  /* --- 导航:一行装下,菜单收进按钮 --- */
  #site-nav {
    padding: 8px 10px 8px 14px;
    flex-wrap: nowrap;
    gap: 8px;
    padding-top: calc(8px + env(safe-area-inset-top));
  }

  .nav-brand { font-size: 18px; letter-spacing: 0.05em; }

  .nav-toggle {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 5px;
    width: 44px;
    height: 44px;
    padding: 0;
    background: none;
    border: none;
    cursor: pointer;
    flex: 0 0 auto;
  }

  .nav-toggle span {
    display: block;
    width: 19px;
    height: 1.5px;
    background: var(--ink);
    transition: transform 0.3s ease, opacity 0.3s ease;
  }

  #site-nav.open .nav-toggle span:first-child { transform: translateY(3.25px) rotate(45deg); }
  #site-nav.open .nav-toggle span:last-child { transform: translateY(-3.25px) rotate(-45deg); }

  .nav-drop {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    display: none;
    flex-direction: column;
    padding: 4px 14px calc(18px + env(safe-area-inset-bottom));
    background: color-mix(in srgb, var(--bg) 97%, transparent);
    backdrop-filter: blur(14px);
    border-bottom: 1px solid var(--hair);
  }

  #site-nav.open .nav-drop { display: flex; }

  .nav-links {
    flex-direction: column;
    gap: 0;
    width: 100%;
  }

  .nav-links a {
    padding: 13px 2px;
    font-size: 13px;
    letter-spacing: 0.18em;
    border-bottom: 1px solid var(--hair);
    border-top: none;
  }

  .nav-links a:hover { border-bottom-color: var(--hair); }

  .lang { gap: 4px; margin-top: 14px; }

  .lang button {
    min-width: 52px;
    min-height: 44px;
    font-size: 13px;
    border: 1px solid var(--hair);
    border-radius: 6px;
  }

  .lang button.active { border-color: var(--accent); color: var(--accent); text-decoration: none; }

  /* --- 页码点:视觉不变,点击区撑到 44×44 --- */
  .deck-dots { right: 0; gap: 0; }

  .deck-dots button {
    width: 44px;
    height: 44px;
    border: none;
    background: none;
    border-radius: 0;
    position: relative;
    transform: none;
  }

  .deck-dots button::before {
    content: "";
    position: absolute;
    top: 50%;
    right: 15px;
    width: 8px;
    height: 8px;
    margin-top: -4px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.5);
    transition: background 0.35s ease, border-color 0.35s ease, transform 0.35s ease;
  }

  /* 桌面版 .deck-dots button.on 直接把整颗按钮涂成 --accent(桌面按钮本身
     就是 8px 的小红点);这条规则不受 max-width 限制,手机上也会生效,
     和这里的 44×44 点击区(border-radius:0)叠在一起,变成一整块实心红方块。
     手机上真正的可见小圆点是下面的 ::before,这里要把继承来的红底清掉。 */
  .deck-dots button.on { transform: none; background: none; }

  .deck-dots button.on::before {
    background: var(--accent);
    border-color: var(--accent);
    transform: scale(1.4);
  }

  /* --- 避开刘海与底部横条 --- */
  .hero-cue { bottom: calc(14px + env(safe-area-inset-bottom)); }
  .panel-inner { padding-left: max(16px, env(safe-area-inset-left)); padding-right: max(16px, env(safe-area-inset-right)); }

  /* 世界详情面板(下滑进来的那几页)用 justify-content:center 整块居中,
     但导航条是浮在最上面的独立元素(sticky + 高 z-index),不占布局空间——
     内容一旦比较高,居中之后顶部的巨字标题会顶到导航条底下去,和菜单叠在
     一起。这里给面板本身留出导航条的高度,居中范围从导航条下面开始算。 */
  .panel--world { padding-top: calc(64px + env(safe-area-inset-top)); }

  /* --- 字号:小字整体上调,10~11px 在手机上读不了 --- */
  .card-meta, .hero-cue, .proj-meta, .site-foot { font-size: 12px; }
  .card-title { font-size: 14px; }
  .wsec-label { font-size: 13px; }
  .world-kicker { font-size: 12px; }
  .ph span { font-size: 11px; }

  /* 项目页照片墙的手机单列已经由 700px 断点的 .grid 规则 +
     js/motion.js 的 initPhotoWall() 一起处理,这里不用再管 */

  /* --- 正文页 --- */
  .page { padding-top: 16vh; }
  .page .narrative { font-size: 16px; }

  /* 联系方式是要被点的,撑到能用手指点中 */
  .page .contact-block a {
    display: inline-block;
    padding: 11px 0;
    min-height: 44px;
  }

  .site-foot { gap: 6px 20px; }
  .site-foot a { display: inline-block; padding: 10px 0; }

  /* 翻页大字链接、返回链接:同样撑到能点中 */
  .world-next a { display: inline-block; padding: 4px 0; }
  .proj-back { display: inline-block; padding: 10px 0; min-height: 44px; }
}

@media (max-width: 700px) {
  /* Reel 首屏自带底部跑马灯(见上面 .reel-ticker-wrap),
     再叠一个"向下滑"提示会跟跑马灯撞在一起 —— 藏掉,
     跑马灯本身 + 翻页点已经足够暗示"这里还有更多" */
  .hero-cue { display: none; }
}

/* 键盘焦点:纯黑底上默认焦点框几乎看不见,统一用品牌红 */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}
