/* ==========================================================================
   布局：容器、导航、页脚、栅格
   「排列整齐」的实现在这一层：等宽栅格 + 统一间距 + 统一宽高比。
   ========================================================================== */

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--s-4);
}

.app-main {
  padding-block: var(--s-6) var(--s-8);
  min-height: calc(100vh - var(--nav-h));
}

/* --- 垂直节奏：子元素之间统一间距 --- */
.stack > * + * { margin-block-start: var(--s-4); }
.stack-lg > * + * { margin-block-start: var(--s-6); }
.stack-sm > * + * { margin-block-start: var(--s-2); }

/* --- 水平分组 --- */
.cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
}
.cluster-sm { gap: var(--s-2); }
.cluster-between { justify-content: space-between; }
.cluster-end { justify-content: flex-end; }
.push-right { margin-inline-start: auto; }

/* ==========================================================================
   顶部导航
   玻璃效果只用在这里（加弹窗），不逐卡片上，避免拖垮滚动
   ========================================================================== */

.nav {
  position: sticky;
  top: 0;
  z-index: var(--z-nav);
  height: var(--nav-h);
  display: flex;
  align-items: center;

  background: var(--glass-bg-strong);
  backdrop-filter: blur(16px) saturate(150%);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  border-bottom: 1px solid var(--glass-border);
}

/* 不支持 backdrop-filter 时退回实色，否则文字会糊在内容上 */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .nav { background: var(--bg-1); }
}
@media (prefers-reduced-transparency: reduce) {
  .nav { background: var(--bg-1); backdrop-filter: none; -webkit-backdrop-filter: none; }
}

.nav__inner {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--s-4);
  display: flex;
  align-items: center;
  gap: var(--s-4);
}

/* 品牌：整页静态辉光元素之一 */
.nav__brand {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  letter-spacing: -0.02em;
  color: var(--text-0);
  white-space: nowrap;
  flex-shrink: 0;
}
.nav__brand:hover { color: var(--text-0); }

.nav__mark {
  width: 30px;
  height: 30px;
  border-radius: var(--r-sm);
  background: var(--grad-primary);
  display: grid;
  place-items: center;
  font-size: var(--fs-sm);
  color: #fff;
  box-shadow: var(--glow-soft);
}

.nav__links {
  display: flex;
  align-items: center;
  gap: var(--s-1);
  flex-shrink: 0;
}

.nav__link {
  position: relative;
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-pill);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: hsl(var(--h, 24) 42% 70%);
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.nav__link:hover { color: hsl(var(--h, 24) 62% 84%); background: var(--bg-2); transform: translateY(-1px); }

/* 当前页：该色相的柔和渐变胶囊（与分类栏呼应） */
.nav__link.is-active {
  color: #fff;
  background: linear-gradient(135deg, hsl(var(--h, 24) 58% 58%), hsl(calc(var(--h, 24) + 30) 58% 50%));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .22), 0 6px 16px hsl(var(--h, 24) 55% 45% / .3);
}
html[data-theme="light"] .nav__link { color: hsl(var(--h, 24) 50% 40%); }
html[data-theme="light"] .nav__link.is-active { color: #fff; }

.nav__search {
  flex: 1;
  max-width: 280px;
  margin-inline: auto;
}

.nav__actions {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex-shrink: 0;
  margin-inline-start: auto;
}

@media (max-width: 860px) {
  .nav__links { display: none; }
  .nav__search { max-width: none; }
}

/* 手机：导航只留 品牌标 + 搜索 + 主题切换。
   390px 宽下把「廓形 / SILHOUETTE」两行字和 登录/注册 一起挤进来，
   搜索框会被压成一个字宽 —— 与其留个残废的搜索框，不如把位置还给搜索。
   登录/注册 收进「我的」tab：未登录时那页本来就是登录引导页。 */
@media (max-width: 640px) {
  .nav__latin { display: none; }
  /* 写成 .nav__actions .nav__auth 是为了压过 components.css 里的 .btn ——
     layout.css 在 index.html 里排在 components.css **之前**，
     两边又都是 (0,1,0)，后加载的 .btn { display: inline-flex } 会赢。
     和 .post-card:hover 遇到的是同一类坑：同特异性 + 文件顺序。 */
  .nav__actions .nav__auth { display: none; }
}

/* ==========================================================================
   手机底部 tab
   桌面整块不显示 —— 导航在顶部那条。
   断点沿用 .nav__links 隐藏的那一档（860px），保证「顶部链接消失」和
   「底部 tab 出现」是同一时刻，中间不会出现两边都没有导航的空档。
   ========================================================================== */

.tabbar { display: none; }

@media (max-width: 860px) {
  .tabbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: var(--z-nav);
    display: flex;
    background: var(--glass-bg-strong);
    backdrop-filter: blur(16px) saturate(150%);
    -webkit-backdrop-filter: blur(16px) saturate(150%);
    border-top: 1px solid var(--glass-border);
    /* iPhone 的横条区域，不占开的话 tab 会被压到横条底下 */
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }

  .tabbar__item {
    flex: 1;
    min-width: 0;
    /* 44px 是手指能可靠点中的下限，这里给到 56px */
    min-height: var(--tabbar-h);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    font-size: 11px;
    line-height: 1.2;
    color: var(--text-2);
    transition: color var(--dur-fast) var(--ease-out);
  }
  .tabbar__item svg { width: 22px; height: 22px; }
  .tabbar__item.is-active { color: var(--style-accent, var(--neon-violet)); }
  .tabbar__item:active { transform: scale(0.94); }

  /* tab 是 fixed 的，会把页面最后一段盖住 —— 正文让出这一条 */
  body { padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px)); }
}

/* 不支持 backdrop-filter 时退回实色，否则文字会糊在内容上 */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  @media (max-width: 860px) {
    .tabbar { background: var(--bg-1); }
  }
}

/* ==========================================================================
   信息流栅格 —— 整个「整齐」诉求的核心
   刻意不用瀑布流：瀑布流配霓虹色必然显乱，等宽网格才对得齐。
   ========================================================================== */

.feed-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--feed-min-col), 1fr));
  gap: var(--grid-gap);
  align-items: start;
}

/* 紧凑网格（个人主页），列更窄 */
.feed-grid--dense {
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: var(--s-3);
}

/* ==========================================================================
   双列瀑布流
   刻意**不复用** .feed-grid —— 那个类被十来个视图共用，动它等于全站一起改。
   这里只给内容浏览类页面（信息流 / 主页 / 搜索）用，后台、审核台那些密集列表
   继续走等宽网格。
   实现细节见 js/masonry.js：两列 flex + 卡片轮转追加。
   ========================================================================== */

.feed-masonry {
  display: flex;
  flex-wrap: wrap;          /* 让 appendFull 的空态能换行独占一整行 */
  align-items: flex-start;  /* 两列各自从顶部开始，不被拉平 */
  gap: var(--grid-gap);
}
.feed-masonry__col {
  flex: 1 1 0;
  min-width: 0;             /* 长文案不许把列撑爆 */
  display: flex;
  flex-direction: column;
  gap: var(--grid-gap);
}

/* 手机上两列要挤一点，20px 的间距太占地方 */
@media (max-width: 560px) {
  .feed-masonry,
  .feed-masonry__col { gap: var(--s-3); }
}

/* 三栏：主内容 + 侧栏 */
.layout-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: var(--s-5);
  align-items: start;
}
@media (max-width: 980px) {
  .layout-split { grid-template-columns: minmax(0, 1fr); }
  .layout-split > aside { display: none; }
}

/* 帖子详情：图 + 评论区 */
.layout-post {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: var(--s-5);
  align-items: start;
}
@media (max-width: 900px) {
  .layout-post { grid-template-columns: minmax(0, 1fr); }
}

/* 统计卡片行 */
.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--s-3);
}

/* --- 页脚 --- */
.site-footer {
  border-top: 1px solid var(--glass-border);
  padding-block: var(--s-5);
  margin-top: var(--s-7);
  color: var(--text-2);
  font-size: var(--fs-xs);
}
.site-footer__inner {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  align-items: center;
  justify-content: space-between;
}
.site-footer a { color: var(--text-1); }
.site-footer a:hover { color: var(--neon-cyan); }

/* 公安联网备案入口：图标 + 备案号（没填号时显示「公安备案」入口）。
   图标是 data URI，零额外请求，和颗粒背景一个路数。 */
.beian {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.beian__icon {
  width: 13px;
  height: 13px;
  flex-shrink: 0;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2 20 5v7c0 4.9-3.4 8.6-8 10-4.6-1.4-8-5.1-8-10V5z' fill='%232f6fd0'/%3E%3Cpath d='m12 6.4 1.5 3.1 3.4.3-2.5 2.2.7 3.3-3.1-1.8-3.1 1.8.7-3.3-2.5-2.2 3.4-.3z' fill='%23fff'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* --- 加载/空态 --- */
.placeholder {
  padding: var(--s-7) var(--s-4);
  text-align: center;
  color: var(--text-2);
}

/* --- 骨架屏 --- */
/* 微光用「位移的伪元素」扫过，而不是动 background-position。
   动 background-position 属于重绘型动画：每一帧都要把整块区域的像素重新画一遍。
   首屏有 8 张骨架同时在动，就是 8 块大面积逐帧重绘 —— 偏偏这个时刻主线程
   还在解析 JSON、建 DOM，两件事抢在一起，观感就是「一进首页先卡一下」。
   换成 transform 之后整条动画交给合成器，主线程和光栅线程都不参与。 */
.skeleton {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-md);
  background: var(--bg-1);
}
.skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent 0%, var(--bg-2) 50%, transparent 100%);
  transform: translate3d(-100%, 0, 0);
  animation: skeleton-shimmer 1.4s infinite linear;
}
@keyframes skeleton-shimmer {
  from { transform: translate3d(-100%, 0, 0); }
  to   { transform: translate3d(100%, 0, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .skeleton::after { animation: none; }
}
