/* ============================================================
 * 星露谷物语 · 攻略站 —— 暖色田园主题
 * ============================================================ */
:root {
  --bg: #f4ead7;
  --bg-deep: #ecdfc6;
  --panel: #fdf6e8;
  --card: #fffaf0;
  --border: #e5d5b6;
  --border-strong: #d7c19a;
  --text: #43352a;
  --muted: #9a8567;
  --wood: #6b4526;
  --wood-deep: #57361d;
  --accent: #5f9e3f;          /* 星露谷绿 */
  --accent-soft: #7cb342;
  --gold: #e0a53a;
  --red: #b5453a;
  --danger: #c0503f;
  --success: #5f9e3f;
  /* 季节色 */
  --spring: #7cb342;
  --summer: #ef9f27;
  --fall: #d9773c;
  --winter: #6f9fc4;
  --radius: 6px;
  --radius-sm: 5px;
  --shadow: 0 6px 20px rgba(107, 69, 38, 0.14);
  /* 星露谷 UI 质感三件套：木框 / 羊皮纸 / 物品栏格子 */
  --frame: #a9764a;
  --frame-dark: #8a5c34;
  --parchment: #fffaf0;
  --parchment-deep: #f6e8cd;
  --slot: #d9a066;
  --slot-hi: rgba(255, 255, 255, 0.52);
  --slot-lo: rgba(104, 62, 28, 0.30);
  --font: "PingFang SC", "Microsoft YaHei", "Noto Sans SC", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  /* 布局尺寸：侧栏宽度与品牌栏高度。
   * 侧栏吸顶要正好贴在品牌栏下沿，所以这两个值必须成对使用 */
  --side-w: 224px;
  --head-h: 62px;
  /* 内容区上限：5 列需要内宽 ≥ 1256px（5×240 + 4×14），加左右各 20 内边距 → 1320。
   * 定成 1320 而不是更大，是为了**封顶 5 列**——6 列时卡片会窄到 240px 以下，读着累。 */
  --page-max: 1320px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background:
    radial-gradient(1000px 500px at 0% 0%, rgba(224, 165, 58, 0.10), transparent 60%),
    radial-gradient(900px 500px at 100% 0%, rgba(95, 158, 63, 0.12), transparent 55%),
    /* 极淡的棋盘格，呼应游戏界面的网格底纹 */
    repeating-conic-gradient(rgba(107, 69, 38, 0.030) 0% 25%, transparent 0% 50%) 0 0 / 10px 10px,
    var(--bg);
  color: var(--text);
  font-family: var(--font);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}

/* ===== 顶部整体（品牌栏 + 横向导航） ===== */
.site-head {
  position: sticky;
  top: 0;
  z-index: 50;
  backdrop-filter: blur(10px);
  background: rgba(253, 246, 232, 0.96);
  border-bottom: 2px solid var(--border-strong);
  box-shadow: 0 2px 10px rgba(107, 69, 38, 0.08);
}
.topbar { background: transparent; }
.topbar-inner {
  /* 品牌栏改成**通栏**：导航搬进侧栏后，品牌与侧栏左缘对齐，
   * 比"相对整个视口居中"（会与内容区错开一截）看着整齐。 */
  max-width: none;
  margin: 0;
  padding: 12px 20px;
  display: flex;
  align-items: center;
  gap: 16px;
}
.brand { display: flex; align-items: center; gap: 10px; }
.brand-logo {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  font-size: 24px;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.2));
}
.brand-logo img { width: 100%; height: 100%; object-fit: contain; display: block; }
.brand-name {
  font-size: 19px;
  font-weight: 800;
  letter-spacing: 1px;
  color: var(--wood-deep);
}
.brand-name small {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  margin-left: 8px;
  letter-spacing: 3px;
}

.topbar-search { margin-left: auto; position: relative; }
.topbar-search input {
  width: 100%;
  max-width: 420px;
  background: var(--panel);
  border: 1.5px solid var(--border-strong);
  color: var(--text);
  font-family: var(--font);
  padding: 10px 16px;
  border-radius: 999px;
  font-size: 14px;
  outline: none;
  transition: border-color 0.18s, box-shadow 0.18s;
}
.topbar-search input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(95, 158, 63, 0.2);
}
.search-drop {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  width: 320px;
  max-width: 90vw;
  background: var(--card);
  border: 1.5px solid var(--border-strong);
  border-radius: 12px;
  box-shadow: 0 12px 30px rgba(107, 69, 38, 0.22);
  overflow: hidden;
  z-index: 60;
}
.search-drop[hidden] { display: none; }
.search-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  cursor: pointer;
  font-size: 14px;
  border-bottom: 1px solid var(--border);
}
.search-item:last-child { border-bottom: none; }
.search-item:hover { background: #f6ecd7; }
.search-item .mod-tag {
  font-size: 12px;
  color: var(--wood);
  background: #f0e3c8;
  padding: 1px 8px;
  border-radius: 4px;
}
.search-item .name { font-weight: 600; }
.search-empty { padding: 14px 16px; color: var(--muted); font-size: 13px; }

/* ===== 左侧模块侧栏 =====
 * 为什么从横向标签栏改成竖向侧栏：17 个模块横排需要约 1700px，
 * **只有 ≥1920 的屏幕能一眼看全**，1600/1440/1366 都已经在横向滚动；
 * 而计划里还有武器/建筑/工具/动物，按每个约 100px 算要 2100px——横排已经到顶了。
 * 竖排的好处不只是"装得下"：内容区原来被 max-width:1240px 框住，
 * 1920 屏上两侧各有 340px 纯空白，侧栏正好用这块空间，宽屏上卡片列数反而变多。
 * 侧栏可**独立滚动**（模块多了只滚动自己那一列，不顶掉内容区）。 */
.layout {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
}
.nav {
  display: flex;
  /* 默认按竖向侧栏排版；<640px 时整行 flex 变纵向，它就自动变回横向滚动条 */
  flex-direction: column;
  flex-wrap: nowrap;
  justify-content: flex-start;
  align-items: stretch;
  gap: 2px;
  padding: 14px 12px 18px;
  border-top: none;
  border-right: 2px solid rgba(0, 0, 0, 0.22);
  /* 木板纹理：横排时是竖向拼缝，竖排时改成横向拼缝（同一块木板转 90°）。
   * ⚠️ 缝的周期必须**等于条目行距**（条目高 42 + 间距 2 = 44），并且把 2px 的线
   * 放在每一段的末尾 [42,44)——这样线正好落在两个条目之间的空隙里。
   * 原来写 46px 与行距不同周期，越往下越错位，"模块和线对不齐"就是这么来的。 */
  background:
    repeating-linear-gradient(0deg, transparent 0 42px, rgba(0, 0, 0, 0.13) 42px 44px),
    linear-gradient(180deg, #7d5531, var(--wood-deep));
  /* ⚠️ 缝那一层必须是 local：背景默认贴在元素的盒子上、**不随内容滚动**，
   * 而侧栏内容超出一屏时会独立滚动——那样条目在动、缝不动，滚两下就又错位了。
   * local 让第一层（缝）跟着内容走，第二层（木色渐变）保持 scroll 铺满整列。
   * 注意：必须写在 background 简写**之后**，简写会把 attachment 重置回 scroll。 */
  background-attachment: local, scroll;
  box-shadow: inset -3px 0 0 rgba(0, 0, 0, 0.22), inset 2px 0 0 rgba(255, 255, 255, 0.06);
  /* 独立滚动：模块多了只滚这一列 */
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.32) rgba(0, 0, 0, 0.16);
  /* 吸顶在品牌栏之下，随页面滚动保持可见 */
  position: sticky;
  top: var(--head-h);
  flex: 0 0 var(--side-w);
  width: var(--side-w);
  height: calc(100vh - var(--head-h));
}
/* 横排时（窄屏）用首尾 auto margin 居中；竖排时不需要，故限定在纵向媒体查询里 */
.nav-item {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
  /* ⚠️ 高度必须固定成 42px：它 + 2px 间距 = 44px 的行距，
   * 侧栏木板缝的周期就是按这个数画的（改这里要同步改 .nav 的背景）。 */
  height: 42px;
  padding: 0 10px;
  border: none;
  background: transparent;
  color: #f0e2c8;
  font-family: var(--font);
  font-size: 14.5px;
  border-radius: 7px;
  cursor: pointer;
  text-align: left;
  white-space: nowrap;
  flex: 0 0 auto;
  transition: background 0.16s ease, color 0.16s ease, transform 0.16s ease, box-shadow 0.16s ease;
}
.nav-item .mod-icon { width: 26px; height: 26px; }
/* 条目数徽标：横排时完全没有地方放，竖排才排得下 */
.nav-item .nav-count {
  margin-left: auto;
  padding-left: 8px;
  font-size: 12px;
  font-weight: 700;
  color: rgba(255, 235, 205, 0.5);
  font-variant-numeric: tabular-nums;
}
.nav-item:hover { background: rgba(255,255,255,0.12); color: #fff; }
/* 侧栏标题：居中 + 加重。
 * ⚠️ 高度固定 28px：28 + .nav 的 14px 上内边距 = 42px，正好让**第一个条目落在 44px 处**
 * （与木板缝的周期对齐）。改字号/行高不影响这条，因为高度是写死的。 */
.nav-title {
  height: 28px;
  /* ⚠️ 必须 flex: 0 0 auto：.nav 是 flex 纵向容器，内容超出一屏时子项默认会**被压缩**
   * （实测标题从 28px 缩到 18px），它一缩，下面所有条目就整体上移、与木板缝错开。
   * .nav-item 早就写了 flex: 0 0 auto，标题这里漏了。 */
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  /* 字间距会让整行视觉左偏，用等量的左内边距补回来 */
  letter-spacing: 6px;
  padding-left: 6px;
  font-size: 13px;
  font-weight: 800;
  color: rgba(255, 240, 214, 0.92);
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.45), 0 0 10px rgba(255, 214, 150, 0.18);
  border-bottom: 1px solid rgba(0, 0, 0, 0.22);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.07);
  user-select: none;
}
/* 选中态做成游戏里的「标签页」：内高光 + 底部压边。
 * ⚠️ 竖排里**不加 translateY(-1px)**：那 1px 上浮会让选中项压到上方的木板缝上，
 * 与"条目和缝对齐"直接冲突。横排（≤640）时再把它加回来——那里本来就是标签页形态。 */
.nav-item.is-active {
  background: linear-gradient(180deg, #93c25a, var(--accent));
  color: #fff;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.28);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.38),
    inset 0 -3px 0 rgba(0, 0, 0, 0.18),
    0 3px 0 rgba(0, 0, 0, 0.30);
}

/* ===== 页面 / 模块 ===== */
.page {
  max-width: var(--page-max);
  margin: 24px auto;
  padding: 0 20px;
}
/* 内容列：侧栏的 flex 兄弟。要能收缩（否则长内容会把侧栏挤扁）；
 * 页脚也在这一列里——见 index.html 的注释（sticky 粘附范围必须覆盖页脚） */
.main-col {
  flex: 1 1 auto;
  min-width: 0;
}
.module { animation: fadeIn 0.22s ease; }
.module[hidden] { display: none; }
@keyframes fadeIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

.module-head { margin-bottom: 16px; }
.module-head h2 {
  margin: 0 0 4px;
  font-size: 26px;
  color: var(--wood-deep);
  letter-spacing: 1px;
  display: flex;
  align-items: center;
  gap: 12px;
  /* 游戏 UI 文字的硬描边感 */
  text-shadow: 2px 2px 0 rgba(169, 118, 74, 0.24);
}
.module-head h2 .mod-icon { width: 48px; height: 48px; flex: 0 0 auto; }
.module-head .sub { margin: 0 0 0 60px; color: var(--muted); font-size: 14px; }

/* ===== 模块图标（真实游戏贴图 + emoji 兜底） ===== */
.mod-icon {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  line-height: 1;
}
/* 模块图标同样「贴图在上、emoji 兜底」，但**兜底默认收起**：
 * 导航图标只有 24px，贴图的透明区会把 emoji 透出来（与物品图标同一个问题，见 #80）。 */
.mod-icon img { width: 100%; height: 100%; object-fit: contain; display: block; }
.mod-icon-fallback { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 1.05em; line-height: 1; }
.has-img .mod-icon-fallback { display: none; }
.has-img.icon-failed .mod-icon-fallback { display: flex; }

/* ===== 工具栏（筛选/搜索） ===== */
.toolbar { margin-bottom: 16px; display: flex; flex-direction: column; gap: 10px; }
.toolbar input[type="text"], .toolbar input[type="search"] {
  width: 100%;
  background: var(--panel);
  border: 1.5px solid var(--border-strong);
  color: var(--text);
  font-family: var(--font);
  padding: 10px 16px;
  border-radius: var(--radius-sm);
  font-size: 14px;
  outline: none;
  transition: border-color 0.18s, box-shadow 0.18s;
}
.toolbar input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(95,158,63,0.18); }
.filter-row { display: flex; flex-wrap: wrap; gap: 8px; }
.filter-chip {
  background: linear-gradient(180deg, var(--parchment), var(--parchment-deep));
  border: 2px solid var(--frame);
  color: var(--wood);
  padding: 6px 14px;
  border-radius: var(--radius);
  font-size: 13px;
  cursor: pointer;
  font-family: var(--font);
  box-shadow: 0 2px 0 rgba(87, 54, 29, 0.20);
  transition: all 0.15s ease;
}
.filter-chip:hover { border-color: var(--accent); color: var(--accent); transform: translateY(-1px); }
.filter-chip.is-active {
  background: linear-gradient(180deg, #93c25a, var(--accent));
  border-color: #4d8631;
  color: #fff;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.35),
    inset 0 -2px 0 rgba(0, 0, 0, 0.18),
    0 2px 0 rgba(0, 0, 0, 0.28);
  transform: translateY(-1px);
}

/* ===== 通用卡片网格 ===== */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 14px;
}
.card {
  position: relative;
  background: linear-gradient(180deg, var(--parchment), var(--parchment-deep));
  border: 2px solid var(--frame);
  border-radius: var(--radius);
  padding: 14px;
  box-shadow:
    inset 0 0 0 2px #fff8e6,
    0 3px 0 rgba(87, 54, 29, 0.22),
    var(--shadow);
  transition: transform 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease;
}
.card.clickable { cursor: pointer; }
.card.clickable:hover {
  transform: translateY(-3px);
  border-color: var(--accent-soft);
  box-shadow: 0 10px 24px rgba(107, 69, 38, 0.2);
}
.card h3 { margin: 0 0 6px; font-size: 16px; color: var(--wood-deep); }
.card .muted { color: var(--muted); font-size: 13px; }
.card .meta { font-size: 13px; color: var(--wood); margin: 4px 0; line-height: 1.6; }
.card .foot { margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--border); font-size: 13px; }

/* 物品栏格子：星露谷背包槽质感。
 * 源图 48×48 按 1:1 呈现（不缩放 = 像素不错位），内高光 + 内暗边 + 外木框。 */
.item-icon {
  position: relative;
  width: 48px;
  height: 48px;
  border-radius: 5px;
  background: linear-gradient(180deg, #e3ae77, var(--slot));
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 10px;
  overflow: hidden;
  box-shadow:
    inset 2px 2px 0 var(--slot-hi),
    inset -2px -2px 0 var(--slot-lo),
    0 0 0 2px var(--frame);
}
/* 贴图与兜底：**兜底默认收起，只有贴图真的加载失败时才展开**
 * （js/main.js 的 onerror 给容器加 .icon-failed）。判据用显式的 .has-img 标记，
 * 因为纯 emoji 图标（.emoji-icon）没有贴图，兜底就是它的内容，必须照常显示。
 *
 * 为什么不能像早先那样「兜底常驻、压在贴图下层」：官方贴图是带 alpha 通道的 PNG，
 * object-fit:contain 还会给长条物体留白，于是**兜底的每个像素都会从贴图的透明区透出来**
 * ——实测 617 张贴图在格子内平均有 48.5% 的面积在露兜底图，一半贴图超过 50%，
 * 最严重的 copper.png / skeletal-tail.png 达 88.7%（见 docs/PROBLEMS.md #80）。 */
.has-img .icon-fallback { display: none; }
.has-img.icon-failed .icon-fallback { display: flex; }

/* 建筑用的大图标位（96×96）。
 * 为什么需要：建筑的图源是**游戏截图**（铁匠铺 768×544、赌场 896×449、镇长庄园 576×896），
 * 不是 48×48 的像素精灵。硬塞进 48×48 要除以 16~32，实测 52 张里 14 张缩完最大边不到 30px，
 * 基本看不清。放大格子后多数只需 /2~/8，既能保持**整数倍缩放**（R23），又认得出来。
 * ⚠️ 里面再写 width/height:auto + max-*，是**禁止 contain 把小图放大**：
 * 例如 56×28 的图在 96×96 里会被拉到 96×48，那就成了非整数放大。 */
.item-icon.icon-lg {
  width: 96px;
  height: 96px;
}
.item-icon.icon-lg .icon-img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.icon-img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  image-rendering: pixelated;   /* NPC 立绘 128px → 64px 为整数 2 倍缩放 */
}
.icon-fallback {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.icon-fallback svg { width: 40px; height: 40px; display: block; }

/* NPC 头像 */
.npc-icon { width: 64px; height: 64px; }
.npc-fallback { font-size: 28px; line-height: 1; }
.modal-head .item-icon { margin: 0; flex: 0 0 auto; }

/* 高亮（全局搜索跳转） */
.card.is-highlight {
  outline: 3px solid var(--gold);
  outline-offset: 2px;
  animation: pulse 1.2s ease 2;
}
@keyframes pulse {
  0%, 100% { box-shadow: var(--shadow); }
  50% { box-shadow: 0 0 0 6px rgba(224, 165, 58, 0.35); }
}

/* ===== 徽章 ===== */
.badge {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 600;
  border: 1px solid transparent;
  line-height: 1.6;
}
.badge.spring { background: rgba(123,179,66,0.16); color: #5a8a2e; border-color: rgba(123,179,66,0.4); }
.badge.summer { background: rgba(239,159,39,0.16); color: #c47f0f; border-color: rgba(239,159,39,0.4); }
.badge.fall   { background: rgba(217,119,60,0.16); color: #b05a22; border-color: rgba(217,119,60,0.4); }
.badge.winter { background: rgba(111,159,196,0.18); color: #46769b; border-color: rgba(111,159,196,0.45); }
.badge.all    { background: rgba(154,133,103,0.14); color: #7a6548; border-color: rgba(154,133,103,0.35); }
.badge.green  { background: rgba(95,158,63,0.14); color: #4a7a2f; border-color: rgba(95,158,63,0.35); }
.badge.gold   { background: rgba(224,165,58,0.16); color: #b07f15; border-color: rgba(224,165,58,0.4); }
.badge.red    { background: rgba(192,80,63,0.14); color: #a23c30; border-color: rgba(192,80,63,0.35); }
.badge.brown  { background: rgba(107,69,38,0.12); color: #6b4526; border-color: rgba(107,69,38,0.3); }

/* 金币图标 */
.gold-text { color: #b07f15; font-weight: 700; }
.gold-text::before { content: "🪙 "; font-weight: 400; }

/* 难度星星 */
.stars { color: var(--gold); letter-spacing: 1px; font-size: 12px; }

/* ===== 列表行（任务/事件） ===== */
.list { display: flex; flex-direction: column; gap: 12px; }
.list-item {
  position: relative;
  background: linear-gradient(180deg, var(--parchment), var(--parchment-deep));
  border: 2px solid var(--frame);
  border-radius: var(--radius);
  padding: 14px 16px;
  box-shadow:
    inset 0 0 0 2px #fff8e6,
    0 3px 0 rgba(87, 54, 29, 0.22),
    var(--shadow);
}
.list-item h3 { margin: 0 0 4px; font-size: 16px; color: var(--wood-deep); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.list-item .desc { color: var(--muted); font-size: 14px; line-height: 1.7; margin: 6px 0 0; }
.list-item .kv { display: flex; flex-wrap: wrap; gap: 6px 18px; margin-top: 8px; font-size: 13px; color: var(--wood); }
.list-item .kv b { color: var(--text); font-weight: 600; }

/* ===== NPC 头像 ===== */
.avatar {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 26px;
  margin-bottom: 12px;
  border: 2px solid var(--border-strong);
  background: linear-gradient(135deg, #f7ecd6, #eee0c2);
}
.npc-card .loc { font-size: 12px; color: var(--accent-soft); margin: 0 0 8px; font-weight: 600; }

/* ===== 空状态 ===== */
.empty-state { grid-column: 1 / -1; text-align: center; color: var(--muted); padding: 60px 0; }
.empty-state .icon { font-size: 40px; }

/* ===== 弹窗 ===== */
.modal-mask {
  position: fixed;
  inset: 0;
  background: rgba(58, 40, 22, 0.55);
  backdrop-filter: blur(3px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  padding: 20px;
}
.modal-mask[hidden] { display: none; }
.modal {
  position: relative;
  /* 游戏对话框：厚木框 + 内浅描边 + 羊皮纸底 */
  background: linear-gradient(180deg, var(--parchment), var(--parchment-deep));
  border: 3px solid var(--frame);
  border-radius: var(--radius);
  max-width: 560px;
  width: 100%;
  max-height: 84vh;
  overflow: auto;
  box-shadow:
    inset 0 0 0 3px #fff8e6,
    0 24px 70px rgba(58, 40, 22, 0.45);
  animation: fadeIn 0.2s ease;
}
.modal-close {
  position: absolute;
  top: 14px;
  right: 14px;
  background: linear-gradient(180deg, #f7ead2, #eedcbb);
  border: 2px solid var(--frame);
  color: var(--wood);
  width: 32px;
  height: 32px;
  border-radius: var(--radius);
  cursor: pointer;
  font-size: 14px;
  box-shadow: 0 2px 0 rgba(87, 54, 29, 0.22);
  transition: all 0.15s;
}
.modal-close:hover { color: #fff; background: var(--red); border-color: var(--red); }
.modal-content { padding: 26px; }
.modal-head { display: flex; gap: 16px; align-items: center; margin-bottom: 16px; }
.modal-head .avatar { margin: 0; flex: 0 0 auto; }
.modal-head h3 { margin: 0 0 4px; font-size: 22px; color: var(--wood-deep); }
.modal-head .role { color: var(--muted); font-size: 14px; margin: 0; }
.modal-section { margin-bottom: 16px; }
.modal-section h4 {
  margin: 0 0 8px;
  font-size: 13px;
  letter-spacing: 2px;
  color: var(--accent-soft);
}
.modal-section p, .modal-section li { font-size: 14px; line-height: 1.7; color: var(--text); }
.modal-section ul { margin: 0; padding-left: 20px; }
.modal-section .muted { color: var(--muted); }
.chip-list { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
  background: linear-gradient(180deg, #fbf1dd, #f2e3c6);
  border: 1.5px solid var(--border-strong);
  padding: 2px 10px;
  border-radius: 4px;
  font-size: 12px;
  color: var(--wood);
  /* 物品名不能被拆行（「巧克力蛋糕」曾断成「巧克力／蛋糕」）；
     chip 本身在 .chip-list 里换行，粒度已经足够 */
  white-space: nowrap;
}
/* 占位说明（如「不可送礼」）：不是物品，视觉上要弱于真实条目，也不可点 */
.chip-plain {
  background: none;
  border-style: dashed;
  color: var(--muted);
  cursor: default;
}

/* ===== 收集包（社区中心） ===== */
.bundle-card { min-height: 150px; }
.bundle-card.is-done { border-color: var(--accent); }
.bundle-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin: 0 0 14px;
}
.bundle-hint { margin: 0; font-size: 13px; color: var(--muted); }
.bundle-reset {
  font: inherit;
  font-size: 13px;
  color: var(--wood);
  background: linear-gradient(180deg, #fbf1dd, #f2e3c6);
  border: 1.5px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 5px 12px;
  cursor: pointer;
}
.bundle-reset:hover { border-color: var(--danger); color: var(--danger); }
.bundle-reset.is-armed { background: var(--danger); border-color: var(--danger); color: #fff; font-weight: 700; }

/* 进度条 */
.bundle-progress { display: flex; align-items: center; gap: 8px; margin: 8px 0 4px; }
.bundle-bar {
  flex: 1;
  height: 10px;
  border-radius: 5px;
  background: #e6d5b6;
  border: 1px solid var(--border-strong);
  overflow: hidden;
}
.bundle-bar i {
  display: block;
  height: 100%;
  background: linear-gradient(180deg, var(--accent-soft), var(--accent));
  transition: width 0.18s ease;
}
.bundle-count { font-size: 12px; color: var(--muted); white-space: nowrap; }

/* 物品勾选：做成游戏里的物品栏格子质感 */
.bundle-items { display: flex; flex-wrap: wrap; gap: 5px; margin: 8px 0 2px; }
.bundle-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font: inherit;
  font-size: 12px;
  line-height: 1.4;
  color: var(--wood);
  background: linear-gradient(180deg, #fdf6e6, #f3e6ca);
  border: 1.5px solid var(--border-strong);
  border-radius: 4px;
  padding: 3px 8px 3px 4px;
  cursor: pointer;
  text-align: left;
}
.bundle-item:hover { border-color: var(--slot); background: linear-gradient(180deg, #fffaea, #f7ecd4); }
.bundle-item:focus-visible { outline: 3px solid var(--accent); outline-offset: 1px; }
.bundle-item .bundle-box {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  flex: 0 0 16px;
  border-radius: 3px;
  background: var(--slot);
  box-shadow: inset 1px 1px 0 var(--slot-hi), inset -1px -1px 0 var(--slot-lo);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
}
.bundle-item.is-done {
  color: var(--muted);
  border-color: var(--accent);
  background: linear-gradient(180deg, #f0f7e6, #e4f0d4);
}
.bundle-item.is-done .bundle-item-text { text-decoration: line-through; }
.bundle-item.is-done .bundle-box { background: var(--accent); }
.bundle-price { font-size: 13px; color: #b07f15; font-weight: 700; }

/* 详情弹窗里的所需物品清单：条目多（工匠包 12 项、蟹笼包 10 项）时单列会拖得很长，
 * 宽屏下自动分列，窄屏回落到单列。 */
.bundle-need {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 6px 14px;
}
.bundle-need-row { display: flex; align-items: center; gap: 8px; }
.bundle-need-row.is-done .bundle-need-name { color: var(--muted); text-decoration: line-through; }
.bundle-need-name { font-size: 13px; color: var(--wood); }
.or-text { color: var(--muted); font-size: 12px; }
/* 产出机器 chip：与物品 chip 区分（蓝灰调） */
.chip-machine {
  background: linear-gradient(180deg, #eef3f8, #dfe8f1);
  border-color: #a8bccd;
  color: #46617a;
}
/* 博物馆捐赠进度条与奖励门槛 */
.museum-bar { margin-bottom: 12px; }
.museum-progress { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.museum-rewards { display: flex; flex-wrap: wrap; gap: 6px; }
/* 调料/食用增益 chip：与物品 chip 区分开，用暖金色 */
.chip-buff {
  background: linear-gradient(180deg, #fff4dd, #f8e6c0);
  border-color: var(--gold);
  color: #8a6516;
  font-weight: 600;
}
.buff-list { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 2px; }
.bundle-quality {
  font-size: 11px;
  color: #b07f15;
  border: 1px solid var(--gold);
  border-radius: 3px;
  padding: 0 4px;
}

/* ===== 页脚 ===== */
.footer {
  text-align: center;
  color: var(--muted);
  font-size: 13px;
  padding: 28px 20px 20px;
}
.footer code {
  background: #f3e6cb;
  border: 1px solid var(--border-strong);
  padding: 1px 6px;
  border-radius: 5px;
  font-size: 12px;
}

/* ===== 工具栏控件（排序 / 提示） ===== */
.control-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.sort-select {
  appearance: none;
  -webkit-appearance: none;
  background: linear-gradient(180deg, var(--parchment), var(--parchment-deep)) url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%238a5c34'/%3E%3C/svg%3E") no-repeat right 14px center;
  border: 2px solid var(--frame);
  color: var(--wood);
  font-family: var(--font);
  font-size: 13px;
  padding: 6px 34px 6px 14px;
  border-radius: var(--radius);
  cursor: pointer;
  outline: none;
  box-shadow: 0 2px 0 rgba(87, 54, 29, 0.20);
  transition: border-color 0.18s, box-shadow 0.18s, color 0.18s;
}
.sort-select:hover { border-color: var(--accent); color: var(--accent); }
.sort-select:focus-visible { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(95, 158, 63, 0.18); }
.toolbar-hint { font-size: 12px; color: var(--muted); }

/* 标题里的「当前显示 N 条」 */
.shown-count { color: var(--accent); font-weight: 600; }

/* ===== 农作物每日收益 ===== */
.profit-row { display: flex; align-items: baseline; gap: 6px; margin-bottom: 6px; }
.profit-num {
  font-size: 20px;
  font-weight: 800;
  color: #b07f15;
  line-height: 1;
  /* 等宽数字，让各卡片数值纵向对齐，接近游戏数值面板观感 */
  font-variant-numeric: tabular-nums;
  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.7);
}
.profit-num::before { content: "🪙"; font-size: 13px; font-weight: 400; margin-right: 3px; }
/* 负收益（如向日葵：种子价高于售价，靠掉落种子回本）——标红警示而非当成普通数字 */
.profit-num.is-negative { color: var(--danger); }
.profit-num.is-negative::before { content: "⚠️"; }
.neg-text { color: var(--danger); font-weight: 700; }
.neg-text::before { content: "⚠️ "; font-weight: 400; }
.profit-unit { font-size: 12px; color: var(--muted); }
.profit-tag {
  margin-left: auto;
  font-size: 11px;
  color: var(--wood);
  background: linear-gradient(180deg, #fbf1dd, #f2e3c6);
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  padding: 1px 8px;
  white-space: nowrap;
}

/* ===== 详情弹窗：键值表 ===== */
.detail-kv { display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 8px; }
.kv-cell {
  background: var(--card);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 12px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.kv-k { font-size: 12px; color: var(--muted); }
.kv-v { font-size: 14px; font-weight: 600; color: var(--text); overflow-wrap: anywhere; }
.emoji-icon .icon-fallback { font-size: 28px; line-height: 1; }

/* ===== 交叉跳转 chip（怪物掉落物 → 对应条目） ===== */
.chip-link {
  cursor: pointer;
  border-style: dashed;
  border-color: var(--accent-soft);
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.chip-link:hover, .chip-link:focus-visible {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  text-decoration: none;
  outline: none;
}

/* ===== 可点击列表行（任务/节日/事件） ===== */
.list-item.clickable {
  cursor: pointer;
  transition: transform 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease;
}
.list-item.clickable:hover {
  transform: translateY(-2px);
  border-color: var(--accent-soft);
  box-shadow: 0 10px 24px rgba(107, 69, 38, 0.2);
}
.list-item.is-highlight {
  outline: 3px solid var(--gold);
  outline-offset: 2px;
  animation: pulse 1.2s ease 2;
}

/* ===== 键盘可达性 ===== */
.card.clickable:focus-visible,
.list-item.clickable:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}
.modal-close:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

/* ===== 响应式 =====
 * 侧栏的三档退化（同一份 DOM，只切 flex 方向与宽度，不维护两套结构）：
 *   ≥1121  完整侧栏（贴图 + 名称 + 条目数）
 *   ≤1120  图标条（只留贴图，名称与条目数隐藏，靠 title 提示）
 *   ≤640   整行 flex 变纵向 → 导航自动变回顶部的横向滚动条
 * 为什么图标条的断点取 1120 而不是 1024：1024 处**正好卡在临界点上**
 * （可用内宽 745px，而 3 列卡片需要 748px，差 3px 掉成 2 列）。提到 1120 后，
 * 1121 用完整侧栏与 1120 用图标条都稳定给 3 列，跨界不跳档。 */
@media (max-width: 1120px) {
  :root { --side-w: 64px; }
  /* 上内边距归零：标题藏起来后，第一个条目直接从 0 开始，
   * 才能继续与 44px 一格的木板缝对齐（否则整体错开 14px） */
  .nav { padding: 0 8px 14px; align-items: center; }
  .nav-title { display: none; }
  /* 只留图标；名称与计数藏起来（title 属性仍然可读） */
  .nav-label, .nav-item .nav-count { display: none; }
  /* 高度保持 42px（行距 44 不能变，否则木板缝又对不上） */
  .nav-item { justify-content: center; padding: 0; }
  .nav-item .mod-icon { width: 26px; height: 26px; }
}

@media (max-width: 640px) {
  /* 导航回到顶部横排：flex 变纵向，nav 排在 .page 之前 */
  .layout { flex-direction: column; align-items: stretch; }
  .nav {
    position: static;
    width: auto;
    height: auto;
    flex-direction: row;
    align-items: center;
    gap: 4px;
    padding: 10px 16px;
    border-right: none;
    border-top: 1px solid rgba(0,0,0,0.12);
    box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.07), inset 0 -3px 0 rgba(0, 0, 0, 0.28);
    background:
      repeating-linear-gradient(90deg, rgba(0, 0, 0, 0.10) 0 2px, transparent 2px 44px),
      linear-gradient(180deg, #7d5531, var(--wood-deep));
    overflow-x: auto;
    overflow-y: hidden;
  }
  /* 横排时整组居中：首尾 auto margin 均分剩余空间，溢出时自动塌成 0。
   * **不能**用 justify-content:center + overflow——溢出时左侧内容会滚不到（经典裁切坑）。 */
  .nav-item:first-child { margin-left: auto; }
  .nav-item:last-child { margin-right: auto; }
  .nav-item { padding: 8px 14px; font-size: 14px; justify-content: flex-start; }
  .nav-item .mod-icon { width: 24px; height: 24px; }
  /* ⚠️ 必须把名称放回来：上面 ≤1120 的图标条规则把 .nav-label 藏了，
   * 这里只切回横排是不够的——否则手机上是一条"只有图标"的导航（踩过一次） */
  .nav-label { display: inline; }
  /* 横排是标签页形态，把"轻微上浮"加回来（竖排里它会让选中项压到木板缝上） */
  .nav-item.is-active { transform: translateY(-1px); }
}

@media (max-width: 860px) {
  .topbar-inner { flex-wrap: wrap; }
  .topbar-search { width: 100%; margin-left: 0; }
  .topbar-search input { max-width: none; }
  .detail-kv { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); }
  .grid { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 10px; }
  .control-row { gap: 8px; }
}
