/* 首页内容流：滑动模式（抖音式）+ 双列模式（小红书式） */

/* ================================================================ 滑动模式

   iOS 上原生 scroll-snap 很脆，这些约束一条都不能违反，否则 snap 会**静默失效**
   （不报错，只是不动，极难排查）：
   - 滚动容器不能是 body/html，要是独立元素
   - 必须显式 overflow-y: scroll（不能只写 auto）+ overflow-x: hidden + 明确高度
   - 祖先链上不能有 transform / will-change: transform / 动画化的 filter
   - 不用 overscroll-behavior-y: contain，它会破坏纵向 snap
   - 不用 -webkit-overflow-scrolling: touch，现在反而可能冲突

   而且必须给 touch-action: pan-y，否则子元素的横向轮播会抢走纵向手势。
*/

/* 高度必须**同时扣掉 sat 和 sab**。
   .feed 有 margin-top: var(--sat) 把它往下推，高度里不把这段减掉的话，
   它的底部就会越到 tabbar 下面去 —— 卡片底部的正文浮层被菜单栏盖住。

   之前只在 Safari 下测所以没暴露：Safari 里 --sat 是 0，正好对齐；
   而「添加到主屏幕」后 --sat ≈ 47px，重叠就是 sat + sab ≈ 81px。

   推导：feed 底部 = sat + H，tabbar 顶部 = 100dvh - tabbar - sab，
   要两者相等 → H = 100dvh - tabbar - sab - sat。 */
.feed {
  height: calc(100dvh - var(--tabbar-h) - var(--sab) - var(--sat));
  margin-top: var(--sat);
  overflow-y: scroll;
  overflow-x: hidden;
  scroll-snap-type: y proximity; /* 不用 mandatory：见 JS 里的说明 */
  touch-action: pan-y;
  -webkit-overflow-scrolling: auto;
  background: #000;
}

/* standalone 下 100dvh 会缩水成「屏幕 - 状态栏」那 59px，导致文档超过视口、
   视口反过来缩水、底栏吸不到底。100vh 恒等于屏幕高度，不受影响。
   （必须写在 .feed 基础规则**之后** —— 同优先级下后写的胜出。） */
@media all and (display-mode: standalone) {
  .feed {
    height: calc(100vh - var(--tabbar-h) - var(--sab) - var(--sat));
  }
}

/* ⚠️ 这里**不要**再加别的 standalone 覆盖规则。
   曾经在 standalone 下把 `- sab` 去掉过（理由是「底栏被下推了一个安全区」），
   结果卡片区域高了 34px、伸到菜单栏底下，正文浮层被盖住。
   真机实测数据（iPhone 15 Pro Max / iOS 26，standalone）：
     innerHeight 873, sat 59px, sab 34px
     feed   top 59  height 762  bottom 821
     tabbar top 787 height  86  bottom 873
   821 > 787 就是那 34px 的重叠。用同一条公式算是 873-52-34-59 = 728，
   恰好等于 787-59 —— 说明**非 standalone 的公式本身就是对的**。 */

.card {
  height: 100%;
  scroll-snap-align: start;
  position: relative;
  display: flex;
  flex-direction: column;
  background: #000;
  overflow: hidden;
}

.card__media {
  flex: 1;
  position: relative;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 图片/视频的容器。不设 pointer-events:none，也不要禁用长按菜单 */
.card__media img,
.card__media video {
  max-width: 100%;
  max-height: 100%;
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

/* 视频降级：低电量模式会禁用自动播放，且 WebKit 会强制显示一个
   CSS 藏不掉的原生播放按钮。所以「封面 + 点一下播放」必须是一等状态。 */
.card__play-hint {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.card__play-hint span {
  width: 62px;
  height: 62px;
  border-radius: 50%;
  background: rgba(0, 0, 0, .55);
  backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 26px;
  color: #fff;
  padding-left: 5px; /* 视觉居中三角形 */
}

/* 横向轮播（图集内部翻页）。
   overscroll-behavior-x: contain 防止滑到边缘时触发 iOS 的边缘返回手势。

   ⚠️ touch-action 必须是 pan-x pan-y，**不能只写 pan-x**。
   轮播铺满了整个媒体区，写上 pan-x 会让「在媒体区起手的纵向拖动」被禁止，
   而媒体区占了卡片绝大部分 —— 结果就是整个 feed 在真机上翻不了页。
   实测过：只写 pan-x 时纵向 scrollTop 恒为 0，横向正常。
   两个方向都放开，由浏览器的方向锁按手势起始方向决定归属。 */
.carousel {
  display: flex;
  overflow-x: scroll;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  touch-action: pan-x pan-y;
  overscroll-behavior-x: contain;
  width: 100%;
  height: 100%;
  scrollbar-width: none;
}
.carousel::-webkit-scrollbar { display: none; }

.carousel__slide {
  flex: 0 0 100%;
  width: 100%;
  height: 100%;
  scroll-snap-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.carousel__counter {
  position: absolute;
  right: 12px;
  bottom: 12px;
  background: rgba(0, 0, 0, .6);
  color: #fff;
  font-size: 12px;
  padding: 3px 9px;
  border-radius: 999px;
  font-variant-numeric: tabular-nums;
}

/* 底部信息浮层 */
.card__overlay {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  /* .feed 的高度已经扣掉了 tabbar 和安全区，这里不用再补 */
  padding: 48px 14px 14px;
  background: linear-gradient(transparent, rgba(0, 0, 0, .78) 45%);
  color: #fff;
  pointer-events: none;
}
.card__overlay > * { pointer-events: auto; }

.card__author { font-size: 15px; font-weight: 600; margin-bottom: 6px; }
.card__desc {
  font-size: 14px;
  line-height: 1.45;
  margin: 0 0 8px;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .5);
  white-space: pre-wrap;
  word-break: break-word;
}
.card__desc.clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.card__tags { display: flex; flex-wrap: wrap; gap: 6px; }
.card__tags .chip { background: rgba(255, 255, 255, .16); color: #fff; }

.card__topbar {
  position: absolute;
  /* 卡片本身已经在状态栏下方（.feed 有 margin-top: var(--sat)），
     所以这里不用再补 --sat。26px 是让开顶部那排进度条。 */
  top: 26px;
  right: 12px;
  display: flex;
  gap: 8px;
  z-index: 3;
}

.card__icon-btn {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, .45);
  backdrop-filter: blur(8px);
  color: #fff;
  font-size: 17px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.card__icon-btn:active { transform: scale(.92); }
.card__icon-btn svg { display: block; }

/* 声音按钮里同时放了「有声」「静音」两个 SVG，靠 class 切换。
   不用改 textContent —— 那样得在两个 emoji 之间来回换，字形还不统一。 */
.card__icon-btn[data-sound] svg:nth-of-type(1) { display: none; }
.card__icon-btn[data-sound].is-on svg:nth-of-type(1) { display: block; }
.card__icon-btn[data-sound].is-on svg:nth-of-type(2) { display: none; }

/* ================================================================ 双列模式 */

.grid {
  columns: 2;
  column-gap: 10px;
  padding-bottom: 10px;
}

.grid-card {
  break-inside: avoid;
  margin-bottom: 10px;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg-elev);
  display: block;
  color: inherit;

  /* 用 <button> 而不是 <a href> —— 点卡片是「进滑动模式」这个页内动作，
     不是导航。顺带也解决了：跳页会丢掉 iOS 的手势授权，配乐每次都要重新点。
     下面是按钮的默认样式重置。 */
  width: 100%;
  padding: 0;
  border: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
  appearance: none;
}
.grid-card:active { transform: scale(.985); }

.grid-card__cover {
  width: 100%;
  display: block;
  background: var(--bg-elev-2);
  min-height: 80px;
  object-fit: cover;
}

.grid-card__body { padding: 9px 10px 11px; }

.grid-card__title {
  font-size: 13.5px;
  line-height: 1.4;
  margin: 0 0 6px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  word-break: break-word;
}

.grid-card__meta {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  font-size: 11px;
  color: var(--fg-faint);
}

.grid-card__cover-wrap { position: relative; }

.grid-card__play {
  position: absolute;
  right: 7px;
  bottom: 7px;
  background: rgba(0, 0, 0, .62);
  color: #fff;
  font-size: 11px;
  padding: 2px 7px;
  border-radius: 5px;
}

/* ================================================================ 浮动控件 */

/* 滑动模式的顶部控件：靠左，和卡片自己的按钮（靠右）在同一水平线上。
   之前是浮在右侧中部，会压到正文浮层、也挡画面。 */
.top-controls {
  position: fixed;
  top: calc(var(--sat) + 26px);
  left: 12px;
  display: flex;
  gap: 8px;
  z-index: 40;
}

/* ================================================================ 声音解锁提示 */

/* 首次进滑动模式时引导那一次点击 —— iOS 不允许无手势自动出声。
   解锁成功后由 JS 隐藏（feed.js 的 hideSoundHint）。
   只用 opacity 做淡入：**不用 transform** —— 这个项目被「overflow 和 transform
   放同一个元素上导致远端元素不光栅化」坑过一次，能不碰就不碰。居中改用
   left/right + width:fit-content + margin:auto，同样不需要 transform。 */
.sound-hint {
  position: fixed;
  top: calc(var(--sat) + 74px); /* 让开顶栏那排按钮（在 26px 处，高 38px） */
  left: 0;
  right: 0;
  width: fit-content;
  margin: 0 auto;
  padding: 7px 14px;
  border-radius: 999px;
  background: rgba(0, 0, 0, .62);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: #fff;
  font-size: 13px;
  white-space: nowrap;
  z-index: 41;
  /* 提示条本身不接手势 —— 用户点哪儿都算解锁，别让它挡住那一下 */
  pointer-events: none;
  animation: sound-hint-in .28s ease-out;
}

@keyframes sound-hint-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* ================================================================ 筛选面板 */

.sheet {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, .6);
  z-index: 60;
  display: flex;
  align-items: flex-end;
}
.sheet__panel {
  width: 100%;
  background: var(--bg-elev);
  border-radius: 18px 18px 0 0;
  padding: 16px 16px calc(var(--sab) + 20px);
  max-height: 70dvh;
  overflow-y: auto;
}
.sheet__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
  font-size: 16px;
}
.sheet__body { display: flex; flex-wrap: wrap; gap: 8px; }
