/* =============================================================================
 * 05-pages.css — 多页拆分版新增样式
 * -----------------------------------------------------------------------------
 * 1) 页面切换动画（每页只有一屏，加载即淡入）
 * 2) 项目入口页（index.html）的排版
 * 页面本体的样式仍然由 Tailwind 运行时 + 03-base.css 提供，此处不重复定义。
 * ========================================================================== */

/* ---------------------------------------------------------------- 1. 页面加载 */

/* 拆分后每个 HTML 就是一个页面，区块自带 .active，这里补一段轻量淡入，
   替代原来 SPA 的内存路由转场。 */
.page.active {
  animation: pageIn .22s ease both;
}

@keyframes pageIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .page.active { animation: none; }
}

/* ---------------------------------------------------------------- 1b. 嵌入模式 */
/* 带 ?embed=1 打开时（canvas.html 的画布缩略图），去掉宿主外壳只留页面内容。
   样式写在文件里而不是由父页注入 —— 本地 file:// 下无法跨文档改 DOM。 */

body.is-embed #navfab,
body.is-embed #navpanel,
body.is-embed .phone-frame,
body.is-embed #boot {
  display: none !important;
}

body.is-embed {
  background: #FBF9F5;
  overflow: hidden;
}

body.is-embed #stage {
  padding: 0;
  height: 100%;
}

body.is-embed #phone {
  height: 100%;
  width: 100%;
  aspect-ratio: auto;
  border-radius: 0;
  clip-path: none;
}

/* 缩略图不需要入场动画，避免画布上 20 个框同时闪一下 */
body.is-embed .page.active { animation: none; }

/* ---------------------------------------------------------------- 2. 入口页 */

:root {
  --hub-ink:      #1b1c1a;
  --hub-muted:    #5F6167;
  --hub-faint:    #6F7176;
  --hub-bg:       #F2F0EB;
  --hub-card:     #FFFFFF;
  --hub-line:     #E4E1DA;
  --hub-cream:    #F9F1E8;
  --hub-blue:     #244EC6;
  --hub-blue-dk:  #1B3A96;
  --hub-gold:     #C5A059;
  --hub-gold-dk:  #775a19;
}

body.hub {
  margin: 0;
  background: var(--hub-bg);
  color: var(--hub-ink);
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'PingFang SC',
               'Microsoft YaHei', sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow: auto;
}

/* 入口页需要恢复滚动条（03-base.css 把全局滚动条设成了 0） */
body.hub::-webkit-scrollbar { width: 10px !important; height: 10px !important; }
body.hub::-webkit-scrollbar-thumb { background: #D5D1C8; border-radius: 5px; }
body.hub { scrollbar-width: thin; }

.hub-wrap {
  max-width: 1080px;
  margin: 0 auto;
  padding: 56px 32px 72px;
}

/* ---- 头部 ---- */
.hub-hero {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 28px;
  padding-bottom: 28px;
  border-bottom: 1px solid var(--hub-line);
}

.hub-brand {
  display: flex;
  align-items: center;
  gap: 18px;
}

.hub-brand img {
  width: 54px;
  height: 54px;
  object-fit: contain;
}

.hub-brand h1 {
  margin: 0;
  font-size: 25px;
  font-weight: 700;
  letter-spacing: -.01em;
}

.hub-brand p {
  margin: 5px 0 0;
  font-size: 12px;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--hub-faint);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
}

.hub-stats {
  display: flex;
  gap: 26px;
  flex-wrap: wrap;
}

.hub-stats span {
  font-size: 12px;
  color: var(--hub-muted);
  letter-spacing: .02em;
}

.hub-stats b {
  display: block;
  font-size: 22px;
  line-height: 1.3;
  color: var(--hub-blue-dk);
  font-weight: 700;
}

/* ---- 入口动作按钮 ---- */
.hub-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 26px;
}

.hub-btn {
  flex: 1 1 260px;
  display: block;
  padding: 15px 20px 16px;
  background: var(--hub-card);
  border: 1px solid var(--hub-line);
  border-radius: 12px;
  text-decoration: none;
  color: inherit;
  transition: .16s;
}

.hub-btn b {
  display: block;
  font-size: 15px;
  font-weight: 600;
}

.hub-btn span {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  color: var(--hub-muted);
  line-height: 1.5;
}

.hub-btn:hover {
  border-color: #C9D3F0;
  transform: translateY(-2px);
  box-shadow: 0 10px 26px -14px rgba(24, 25, 27, .3);
}

.hub-btn.primary {
  background: #1b1c1a;
  border-color: #1b1c1a;
  color: #fff;
}

.hub-btn.primary span { color: rgba(255, 255, 255, .66); }

.hub-btn.primary:hover {
  background: #000;
  box-shadow: 0 12px 28px -14px rgba(0, 0, 0, .5);
}

/* ---- 逻辑线 ---- */
.hub-flow {
  margin-top: 36px;
  padding: 26px 28px 10px;
  background: linear-gradient(180deg, var(--hub-cream), #FDFAF6);
  border: 1px solid #EFE6D6;
  border-radius: 16px;
}

.hub-flow h2 {
  margin: 0 0 4px;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .02em;
}

.hub-flow .hub-flow-note {
  margin: 0 0 20px;
  font-size: 12px;
  color: var(--hub-muted);
  line-height: 1.6;
}

.hub-line {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  padding: 11px 0;
  border-top: 1px dashed #E7DED0;
}

.hub-line:first-of-type { border-top: 0; }

.hub-line-label {
  flex: 0 0 92px;
  font-size: 11px;
  font-weight: 600;
  color: var(--hub-gold-dk);
  letter-spacing: .04em;
}

.hub-node {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 6px 11px;
  background: #fff;
  border: 1px solid #E9E1D3;
  border-radius: 8px;
  font-size: 12.5px;
  color: var(--hub-ink);
  text-decoration: none;
  transition: .15s;
  white-space: nowrap;
}

.hub-node em {
  font-style: normal;
  font-size: 11px;
  color: var(--hub-faint);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
}

.hub-node:hover {
  border-color: var(--hub-blue);
  color: var(--hub-blue-dk);
  box-shadow: 0 3px 10px -4px rgba(36, 78, 198, .3);
}

.hub-arrow {
  color: #C9BFAE;
  font-size: 12px;
  padding: 0 2px;
}

/* ---- 分组 ---- */
.hub-group { margin-top: 44px; }

.hub-group > h2 {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 0 0 16px;
  font-size: 15px;
  font-weight: 600;
}

.hub-group > h2 span {
  font-size: 11px;
  font-weight: 400;
  color: var(--hub-faint);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  letter-spacing: .06em;
}

.hub-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 14px;
}

.hub-card {
  position: relative;
  display: block;
  padding: 16px 18px 15px;
  background: var(--hub-card);
  border: 1px solid var(--hub-line);
  border-radius: 12px;
  text-decoration: none;
  color: inherit;
  transition: .16s;
}

.hub-card:hover {
  border-color: #C9D3F0;
  transform: translateY(-2px);
  box-shadow: 0 10px 26px -14px rgba(24, 25, 27, .3);
}

.hub-idx {
  position: absolute;
  top: 15px;
  right: 16px;
  font-size: 11px;
  color: #8C8E96;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
}

.hub-cn {
  display: block;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.005em;
}

.hub-en {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  color: var(--hub-faint);
  letter-spacing: .1em;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
}

.hub-file {
  display: inline-block;
  margin-top: 12px;
  padding: 3px 8px;
  background: #F5F4F0;
  border-radius: 6px;
  font-size: 11px;
  color: #5F6167;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
}

.hub-card.is-tab .hub-file {
  background: #EFF3FF;
  color: var(--hub-blue-dk);
}

.hub-tag {
  display: inline-block;
  margin-left: 7px;
  padding: 2px 7px;
  background: #FBF3E2;
  color: var(--hub-gold-dk);
  border-radius: 5px;
  font-size: 11px;
  vertical-align: 1px;
}

/* ---- 页脚 ---- */
.hub-foot {
  margin-top: 56px;
  padding-top: 22px;
  border-top: 1px solid var(--hub-line);
  font-size: 12px;
  color: var(--hub-faint);
  line-height: 1.9;
}

.hub-foot code {
  padding: 2px 6px;
  background: #EAE8E2;
  border-radius: 5px;
  font-size: 11px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  color: #5C5E63;
}

@media (max-width: 720px) {
  .hub-wrap { padding: 34px 20px 52px; }
  .hub-line-label { flex: 0 0 100%; margin-bottom: 4px; }
  .hub-grid { grid-template-columns: 1fr; }
}

/* ------------------------------------------------ 3. 首页板块便当盒（bento） */
/* 首页原来的分段 Tab（正在进行中 / 待开始的）换成这组正方形便当盒按钮：
   每个格子 = 图标 + 文字标签，右上角带数量角标，点击切换下方对应板块。

   ⚠ 两格共用同一套配色（白底 + 炭黑图标），选中**只靠边框与描边**区分。
     不要再给 [aria-selected="true"] 换底色 —— 同一排格子颜色不一致时，
     读起来像两个不同层级的控件，而不是同一组里的一个选项。

   样式全部收敛在这里、不掺 Tailwind 类，是为了让切换逻辑只动一个
   aria-selected —— 老写法要来回替换一长串 className，改样式时极易漏改一边。 */

.board-grid {
  display: grid;
  /* 4 列 → 每格占 1/4 行宽。格子是正方形，所以边长约为原来的 1/2、面积 1/4。
     未占满的格子留空，以后加板块直接往后排即可。 */
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}

.board-tile {
  --bt-bg: #FFFFFF;
  --bt-fg: #45474A;
  --bt-ico: #18191B;
  --bt-border: #E8DCC4;
  --bt-count-bg: #F1EFEA;
  --bt-count-fg: #62646A;

  position: relative;
  aspect-ratio: 1 / 1;              /* 正方形 */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 8px;
  border: 1px solid var(--bt-border);
  border-radius: 0.625rem;
  background: var(--bt-bg);
  color: var(--bt-fg);
  box-shadow: 0 1px 2px rgba(24, 25, 27, .04);
  cursor: pointer;
  overflow: hidden;
  transition: border-color .18s, box-shadow .18s, transform .12s;
}

.board-tile:active { transform: scale(.96); }

.board-tile:focus-visible {
  outline: 2px solid #8A6A1F;
  outline-offset: 2px;
}

/* 选中态：配色与未选中**完全一致**，只用香槟色边框 + 外描边做指示 */
.board-tile[aria-selected="true"] {
  --bt-border: #C5A059;
  box-shadow: 0 0 0 1px #C5A059, 0 3px 8px -4px rgba(197, 160, 89, .55);
}

.board-tile .bt-ico {
  position: relative;
  width: 20px;
  height: 20px;
  color: var(--bt-ico);
}

.board-tile .bt-label {
  position: relative;
  font-family: 'Hanken Grotesk', Inter, 'PingFang SC', 'Microsoft YaHei', sans-serif;
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: .01em;
}

.board-tile .bt-count {
  position: absolute;
  top: 5px;
  right: 5px;
  min-width: 16px;
  height: 15px;
  padding: 0 5px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  background: var(--bt-count-bg);
  color: var(--bt-count-fg);
  /* 细描边：白底格上单靠 #F1EFEA 太浅，会读成普通文字而不是角标 */
  box-shadow: inset 0 0 0 1px rgba(24, 25, 27, .07);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: .02em;
}

/* 板块内容面板：由便当盒切换显隐 */
.feed-panel { display: block; }
.feed-panel.is-off { display: none; }

/* ------------------------------------------------- 4. 板块内快速筛选栏 */
/* 只有「资源」板块带筛选栏，形式是下拉式：按钮显示「维度」或「维度: 值」，
   点开是一个选项菜单。维度、当前值、选项全部写在 HTML 上
   （.filter-item 的 data-dim / data-value / data-default，选项在 .filter-menu 里），
   JS 只负责开关菜单、回写按钮文字、以及按各维度的当前值过滤卡片。

   ⚠ 这一栏用 flex-wrap 换行，**不要**改成 overflow-x 滚动：
     一旦成为滚动容器，下拉菜单会被它裁掉（overflow-x:auto 会把 overflow-y 也变成 auto）。
     宁可多占一行，也不要菜单被裁。 */

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.filter-item { position: relative; }

.filter-chip {
  height: 32px;
  padding: 0 12px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid #E8DCC4;
  border-radius: 9999px;
  background: #FFFFFF;
  color: #62646A;
  font-family: 'Hanken Grotesk', Inter, 'PingFang SC', 'Microsoft YaHei', sans-serif;
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .16s, border-color .16s, color .16s, transform .1s;
}

.filter-chip:active { transform: scale(.97); }

.filter-chip:focus-visible {
  outline: 2px solid #8A6A1F;
  outline-offset: 2px;
}

/* 已设值（非默认）或菜单展开时高亮 —— 沿用便当盒那套「香槟边框 = 选中」的语言 */
.filter-item.is-set .filter-chip,
.filter-item.is-open .filter-chip {
  background: #F8F4EC;
  border-color: #C5A059;
  color: #18191B;
}

/* 下拉箭头：纯 CSS 画的三角，不依赖任何图标字体 */
.filter-chip .fc-caret {
  width: 0;
  height: 0;
  border-left: 3.5px solid transparent;
  border-right: 3.5px solid transparent;
  border-top: 4.5px solid currentColor;
  opacity: .45;
  transition: transform .18s;
}

.filter-item.is-open .fc-caret { transform: rotate(180deg); }

.filter-menu {
  display: none;
  position: absolute;
  z-index: 30;
  top: calc(100% + 6px);
  left: 0;
  min-width: 132px;
  padding: 4px;
  border: 1px solid #E8DCC4;
  border-radius: 0.625rem;
  background: #FFFFFF;
  box-shadow: 0 10px 24px -10px rgba(24, 25, 27, .28);
}

.filter-item.is-open .filter-menu { display: block; }

.filter-opt {
  width: 100%;
  min-height: 30px;
  padding: 0 10px;
  display: flex;
  align-items: center;
  border: 0;
  border-radius: 0.5rem;
  background: transparent;
  color: #45474A;
  font-family: 'Hanken Grotesk', Inter, 'PingFang SC', 'Microsoft YaHei', sans-serif;
  font-size: 12px;
  font-weight: 400;
  line-height: 1;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .14s;
}

.filter-opt:hover { background: #F5F3EF; }

.filter-opt[aria-selected="true"] {
  background: #F8F4EC;
  color: #18191B;
  font-weight: 600;
}

/* ------------------------------------------------- 5. 首页卡片固定尺寸 */
/* 卡片标题有 1 行也有 2 行，行数不同会让卡片高矮不一（76px vs 98px），
   列表看起来参差。这里把标题区固定预留「两行」的高度，卡片就自然齐平了。

   为什么用 min-height 而不是 height：
     · height 是硬约束 —— 万一某张卡片的标签行折了行，内容会被裁掉（看不见的那种坏）；
     · min-height 只保证下限，真出现折行时卡片正常长高，不会丢内容。
   实测 15 张卡片此时均为 98px；一旦这个值被改小，卡片会立刻显出高矮差。 */

.feed-card-title {
  /* 同时钉住 line-height：否则字体或 Tailwind 配置变动会让「两行」不再是 44px，
     预留高度跟着失准，又会出现高矮不一。 */
  line-height: var(--feed-title-lh);
  min-height: calc(var(--feed-title-lh) * 2);
}

.feed-card {
  --feed-title-lh: 22px;

  /* 兜底：万一标题被编辑层改过、或将来加了个子元素，卡片也不会比标准值矮 */
  min-height: calc(var(--feed-title-lh) * 2 + 54px);
}

/* ------------------------------------------------- 6. 登录页装饰光环 */
/* 2026-10-07 用户指令：登录页背景不要黄色，改回原来的白色。
   原先此处定义过暖金 mesh 渐变（radial-gradient + blur），导致整屏泛黄；现已整段移除，
   .mesh-gradient-aura 恢复为「未定义 → 不可见」，页面底色由 main 的 bg-surface 白色承担。
   ⚠️ 勿再为此类补回金色光晕。画布点云（login.js 的金色点 rgba(191,161,95)）是独立装饰，保留。 */
