:root {
  --bg: #14161c;
  --bg-soft: #1b1e26;
  --bg-card: #22262f;
  --bg-hover: #2b303b;
  --line: #333845;
  --line-soft: #2a2e39;
  --fg: #e6e8ee;
  --fg-dim: #9aa2b4;
  --fg-faint: #6b7385;
  --accent: #f0a63c;
  --accent-soft: #f0a63c22;
  --blue: #6aa9f0;
  --green: #5fbf7f;
  --red: #e0685f;
  --purple: #b07fe0;
  --radius: 10px;
  --header-h: 60px;
}

* { box-sizing: border-box; }

/* The UA rule is `[hidden] { display: none }`, which loses to any class that
 * sets `display` - and .app-bar sets flex, so the update bar stayed on screen
 * after being told to hide, and rendered as an empty strip before it was ever
 * filled in. Put the default back where it can win. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
    "Hiragino Sans GB", "Microsoft YaHei", Roboto, sans-serif;
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--blue); text-decoration: none; }
a:hover { text-decoration: underline; }

button {
  font-family: inherit;
  font-size: inherit;
  color: inherit;
  background: none;
  border: none;
  cursor: pointer;
}

/* ---------------------------------------------------------------- header */

header {
  position: sticky;
  top: 0;
  z-index: 50;
  height: var(--header-h);
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 20px;
  background: var(--bg-soft);
  border-bottom: 1px solid var(--line);
}

.logo {
  font-weight: 700;
  font-size: 17px;
  color: var(--accent);
  white-space: nowrap;
  display: flex;
  align-items: center;
  gap: 8px;
}

.logo small {
  color: var(--fg-faint);
  font-weight: 400;
  font-size: 11px;
}

/* 原版 / 灾厄 总开关。两边是两套独立数据，所以做成站级开关而不是页面里的筛选 ——
 * 切过去整个站换主色，用户一眼就知道自己在哪个库里。 */
.mod-switch {
  display: flex; flex: 0 0 auto;
  border: 1px solid var(--line); border-radius: 8px;
  overflow: hidden;
  background: var(--bg);
}
.mod-switch button {
  padding: 5px 11px;
  font-size: 12px; color: var(--fg-dim);
  transition: background .12s, color .12s;
}
.mod-switch button + button { border-left: 1px solid var(--line); }
.mod-switch button:hover { color: var(--fg); }
.mod-switch button.on {
  background: var(--accent); color: #1a1c22; font-weight: 600;
}
.mod-switch button.on:hover { color: #1a1c22; }

nav {
  display: flex;
  gap: 2px;
  /* No auto margin here: auto margins are resolved before flex-grow, so they
   * were eating all the free space and collapsing the search box to its
   * 140px min-content width. The box growing is what right-aligns the tabs. */
  flex: 0 1 auto;
  /* The eight tabs are 601px across. Without this they stayed on one line and
   * forced the whole page to 615px wide on a phone; wrapping costs a second row
   * and keeps everything reachable. */
  flex-wrap: wrap;
  justify-content: flex-end;
}

nav button {
  padding: 7px 9px;
  border-radius: 7px;
  color: var(--fg-dim);
  font-size: 14px;
  transition: background .12s, color .12s;
}

nav button:hover { background: var(--bg-hover); color: var(--fg); }
nav button.on { background: var(--accent-soft); color: var(--accent); }

/* ---------------------------------------------------------------- search */

.search-wrap {
  position: relative;
  flex: 1 1 220px;
  min-width: 160px;
  max-width: 620px;
}

#search {
  width: 100%;
  padding: 9px 14px 9px 36px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  color: var(--fg);
  font-family: inherit;
  font-size: 14px;
  outline: none;
  transition: border-color .12s;
}

#search:focus { border-color: var(--accent); }
#search::placeholder { color: var(--fg-faint); }

.search-icon {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--fg-faint);
  pointer-events: none;
  font-size: 14px;
}

/* autocomplete */
/* The dropdown searches every column, so each group says where it came from
 * rather than mixing items, NPCs, stations and events into one list. */
.suggest {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  z-index: 60;
  box-shadow: 0 12px 32px #0009;
  display: none;
}

/* Grouped results can run to thirty rows, so the list scrolls rather than
 * hanging off the bottom of the window where the last rows cannot be clicked. */
.suggest.on { display: block; max-height: min(64vh, 560px); overflow-y: auto; overscroll-behavior: contain; }

.suggest-grp + .suggest-grp { border-top: 1px solid var(--line); }

/* The dropdown searches every column, so each group says where it came from
 * rather than mixing items, NPCs, stations and events into one list. */
.suggest-grp + .suggest-grp { border-top: 1px solid var(--line); }
.suggest-grp-t {
  display: flex; align-items: center; gap: 6px;
  padding: 6px 12px 3px; font-size: 11px; color: var(--fg-faint);
  letter-spacing: .05em;
}
.suggest-grp-t .count { margin-left: auto; font-variant-numeric: tabular-nums; }

.suggest-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  cursor: pointer;
  border-bottom: 1px solid var(--line-soft);
}

.suggest-item:last-child { border-bottom: none; }
.suggest-item:hover, .suggest-item.sel { background: var(--bg-hover); }
.suggest-item .nm { flex: 1; min-width: 0; }
.suggest-item .en { color: var(--fg-faint); font-size: 12px; }
/* 「查看全部 N 个匹配物品」是出口而不是结果，用强调色让它可点得出来 */
.suggest-item .en.more { color: var(--accent); font-weight: 600; }
.suggest-ic { width: 20px; text-align: center; font-size: 14px; opacity: .8; }
.suggest-tag {
  flex: 0 0 auto; font-size: 10px; color: var(--fg-faint);
  border: 1px solid var(--line); border-radius: 999px; padding: 1px 7px;
}
.suggest-item.event .suggest-tag,
.suggest-item.guide .suggest-tag { color: var(--accent); border-color: var(--line); }

/* ---------------------------------------------------------------- layout */

main {
  max-width: 1240px;
  margin: 0 auto;
  padding: 22px 20px 80px;
}

.page-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 18px;
  flex-wrap: wrap;
}

.page-head h1 { margin: 0; font-size: 20px; }
.count { color: var(--fg-faint); font-size: 13px; }

/* ---------------------------------------------------------------- filters */

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 16px;
  align-items: center;
}

/* Category filters are always visible - no dropdown, no disclosure triangle. */
.filters.cats {
  display: block;
  background: var(--bg-card);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: 4px 12px 10px;
}

.filter-group {
  padding: 6px 0 2px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}

.filter-group + .filter-group {
  border-top: 1px solid var(--line-soft);
}

.filter-group-label {
  flex-basis: 100%;
  font-size: 12px;
  color: var(--accent);
  opacity: .85;
  margin: 4px 0 2px;
  letter-spacing: .04em;
}

.share-bar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 14px; padding-top: 12px;
  border-top: 1px solid var(--line);
}
.share-btn {
  font: inherit; font-size: 13px; cursor: pointer;
  padding: 6px 14px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--bg-card);
  color: var(--fg);
}
.share-btn:hover { border-color: var(--accent); color: var(--accent); }
.share-note { font-size: 12px; color: var(--fg-faint); }

.src-detail { margin-top: 8px; }
.src-detail > summary { cursor: pointer; list-style: none; }
.src-detail > summary::-webkit-details-marker { display: none; }
.src-detail > summary::before { content: "▸ "; color: var(--fg-faint); }
.src-detail[open] > summary::before { content: "▾ "; }
.src-detail > summary:hover { color: var(--fg); }

.loc-strip {
  display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px;
}
.loc-card { width: 148px; }
.loc-img {
  width: 100%; height: 40px; object-fit: cover; border-radius: 6px;
  border: 1px solid var(--line); background: var(--bg-soft); display: block;
}
.loc-none {
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; color: var(--fg-faint); text-align: center;
}
.loc-none span { padding: 0 4px; }
.loc-name { font-size: 12px; color: var(--fg-dim); margin-top: 4px; }
.loc-en { display: block; font-size: 10px; color: var(--fg-faint); }
.loc-more {
  display: flex; align-items: center; justify-content: center;
  min-width: 40px; height: 56px; border-radius: 6px;
  border: 1px dashed var(--line); color: var(--fg-faint); font-size: 12px;
}
.loc-list p { margin: 2px 0; }
.loc-list p.fish { color: var(--accent); }

.pill-strong {  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}

.chip-n {
  margin-left: 5px;
  opacity: .55;
  font-size: 11px;
}

.chip {
  padding: 5px 12px;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 20px;
  color: var(--fg-dim);
  font-size: 13px;
  transition: all .12s;
}

.chip:hover { border-color: var(--fg-faint); color: var(--fg); }

.chip.on {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}

.filter-sep {
  width: 1px;
  height: 20px;
  background: var(--line);
  margin: 0 4px;
}

/* NPC class colours */
.badge.cls-boss { color: var(--accent); border-color: #f0a63c55; }
.badge.cls-bosspart { color: var(--accent); border-color: #f0a63c33; }
.badge.cls-town { color: var(--blue); border-color: #6aa9f055; }
.badge.cls-critter { color: var(--green); border-color: #5fbf7f55; }
.badge.cls-slime { color: #7ec8e3; border-color: #7ec8e344; }
.badge.cls-undead { color: #b9c4d4; border-color: #b9c4d444; }
.badge.cls-aquatic { color: #5bc8d8; border-color: #5bc8d844; }
.badge.cls-flying { color: #9fd0ff; border-color: #9fd0ff44; }
.badge.cls-goblin { color: #c8a86a; border-color: #c8a86a44; }
.badge.cls-burrowing { color: #c9a273; border-color: #c9a27344; }
.badge.cls-etherian { color: var(--purple); border-color: #b07fe044; }
.badge.cls-enemy { color: var(--red); border-color: #e0685f55; }
.badge.cls-nonentity,
.badge.cls-other { color: var(--fg-dim); }

/* Acquisition breakdown */
.acq-block {
  background: var(--bg-card);
  border: 1px solid var(--line-soft);
  border-radius: 8px;
  padding: 10px 12px;
  margin-bottom: 8px;
}

.acq-head {
  font-size: 12px;
  color: var(--accent);
  margin-bottom: 7px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.acq-block .note { margin: 0; }
.acq-block .drop-list { margin-top: 0; }

.drop-en {
  font-size: 11px;
  color: var(--fg-faint);
  margin-left: 6px;
}

/* Boss summon instructions */
.summon-zh {
  margin: 0 0 10px;
  padding: 11px 14px;
  background: var(--accent-soft);
  border-left: 3px solid var(--accent);
  border-radius: 0 8px 8px 0;
  font-size: 14px;
  line-height: 1.65;
}

.pill .icon.sm {
  vertical-align: -6px;
  margin-right: 3px;
}

/* Placeholder glyph for stations that are not real items. */
.icon-glyph {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  border: 1px solid var(--line-soft);
  border-radius: 6px;
  font-size: 18px;
  line-height: 1;
}

.icon-glyph.lg { font-size: 28px; }

/* ---------------------------------------------------------------- grid */

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(268px, 100%), 1fr));
  gap: 10px;
}

.card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: var(--bg-card);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  cursor: pointer;
  transition: border-color .12s, background .12s, transform .08s;
}

.card:hover {
  border-color: var(--accent);
  background: var(--bg-hover);
}

.card:active { transform: scale(.99); }
.card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.icon {
  width: 40px;
  height: 40px;
  flex: 0 0 40px;
  border-radius: 6px;
  background: var(--bg);
  image-rendering: pixelated;
  object-fit: contain;
}

.icon.lg { width: 64px; height: 64px; flex-basis: 64px; }
.icon.sm { width: 28px; height: 28px; flex-basis: 28px; border-radius: 4px; }

.card-body { min-width: 0; flex: 1; }

.card-name {
  font-weight: 600;
  font-size: 14px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.card-sub {
  color: var(--fg-faint);
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.badges { display: flex; gap: 4px; flex-wrap: wrap; margin-top: 3px; }

.badge {
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 11px;
  background: var(--bg);
  color: var(--fg-dim);
  border: 1px solid var(--line-soft);
}

.badge.craft { color: var(--green); border-color: #5fbf7f44; }
.badge.drop  { color: var(--purple); border-color: #b07fe044; }
.badge.hard  { color: var(--red); border-color: #e0685f44; }
.badge.boss  { color: var(--accent); border-color: #f0a63c44; }

/* ---------------------------------------------------------------- modal */

.overlay {
  position: fixed;
  inset: 0;
  background: #000a;
  z-index: 100;
  display: none;
  overflow-y: auto;
  padding: 30px 16px;
  backdrop-filter: blur(2px);
}

.overlay.on { display: block; }

.modal {
  max-width: 760px;
  margin: 0 auto;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: 14px;
  overflow: hidden;
}

.modal-head {
  display: flex;
  gap: 16px;
  padding: 20px;
  border-bottom: 1px solid var(--line);
  align-items: flex-start;
}

.modal-head .body { flex: 1; min-width: 0; }

.modal-head h2 {
  margin: 0 0 4px;
  font-size: 19px;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.en-name { color: var(--fg-faint); font-size: 13px; font-weight: 400; }

.close {
  margin-left: auto;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  color: var(--fg-dim);
  font-size: 20px;
  line-height: 1;
  flex: 0 0 32px;
}

.close:hover { background: var(--bg-hover); color: var(--fg); }

.modal-body { padding: 20px; }

.section { margin-bottom: 26px; }
.section:last-child { margin-bottom: 0; }

.section h3 {
  margin: 0 0 12px;
  font-size: 14px;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: .05em;
  display: flex;
  align-items: center;
  gap: 8px;
}

/* ------------------------------------------------------------- video link */

.video-link {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-radius: 8px;
  background: var(--bg-card);
  border: 1px solid var(--line-soft);
  text-decoration: none;
  color: inherit;
  transition: border-color .15s ease, background .15s ease;
}

.video-link:hover {
  border-color: var(--accent);
  background: var(--bg-hover, var(--bg-card));
}

.video-play {
  flex: none;
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: #fb7299;
  color: #fff;
  font-size: 12px;
  padding-left: 2px;
}

.video-title { font-weight: 600; }

.video-section .note { margin-top: 8px; }

/* ---------------------------------------------------------------- stats */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(150px, 100%), 1fr));
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
  border-radius: 8px;
  overflow: hidden;
}

.stat {
  background: var(--bg-card);
  padding: 9px 12px;
}

.stat dt {
  font-size: 11px;
  color: var(--fg-faint);
  text-transform: uppercase;
  letter-spacing: .04em;
  margin: 0;
}

.stat dd {
  margin: 2px 0 0;
  font-size: 14px;
  font-weight: 600;
}

/* ---------------------------------------------------------------- recipe */

.recipe {
  background: var(--bg-card);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: 12px;
  margin-bottom: 10px;
}

.recipe-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.ing {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px 6px 6px;
  background: var(--bg);
  border: 1px solid var(--line-soft);
  border-radius: 8px;
  cursor: pointer;
  transition: border-color .12s;
}

.ing:hover { border-color: var(--accent); }

.ing .qty {
  font-size: 12px;
  color: var(--accent);
  font-weight: 700;
}

.ing .nm { font-size: 13px; }

.plus { color: var(--fg-faint); font-size: 16px; }
.or { color: var(--accent); font-size: 12px; padding: 0 2px; }

.arrow {
  color: var(--accent);
  font-size: 18px;
  padding: 0 4px;
}

.station {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
  padding: 4px 10px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 20px;
  font-size: 12px;
  color: var(--fg-dim);
  cursor: pointer;
}

.station:hover { border-color: var(--accent); color: var(--accent); }
.station .s-ico { font-size: 13px; }

.out {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px 6px 6px;
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  border-radius: 8px;
}

/* ---------------------------------------------------------------- drops */

.part-list {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.part-list li {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 5px 10px;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 6px;
  font-size: 13px;
}

.part-n { font-variant-numeric: tabular-nums; color: var(--fg-dim); }

.drop-list { display: flex; flex-direction: column; gap: 6px; }

.drop {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  background: var(--bg-card);
  border: 1px solid var(--line-soft);
  border-radius: 8px;
  cursor: pointer;
  transition: border-color .12s;
}

.drop:hover { border-color: var(--purple); }
/* 掉落物里标出「灾厄新增」的那几件，跟原版掉落区分开 */
.drop .cal-added {
  margin-left: 6px;
  padding: 1px 5px;
  font-size: 10px;
  line-height: 1.4;
  vertical-align: 1px;
  color: #9b7ede;
  border: 1px solid #9b7ede;
  border-radius: 4px;
  opacity: .85;
}
.drop .nm { flex: 1; font-size: 13px; }
/* 掉落来源不是 NPC（环境、地点）时用首字圆标，别用地球 emoji */
.drop-initial {
  width: 30px; height: 30px; flex: 0 0 30px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; background: var(--bg); border: 1px solid var(--line-soft);
  font-size: 14px; color: var(--fg-dim);
}
.drop .meta { font-size: 12px; color: var(--fg-faint); white-space: nowrap; }
/* 商店列表沿用掉落卡片的格子，但价格是主角，得比灰色的掉落几率显眼 */
.drop .meta.drop-price { color: var(--accent); font-weight: 600; }
.drop .meta.drop-seed { font-size: 11px; white-space: normal; }

/* 铜 / 银 / 金 / 铂金按游戏里的币色分开，否则整串刷成一个金色，
 * 「2银50铜」和「2金」看着一样重，价格就没了量级感。
 * 银和铂金都偏冷色，靠亮度拉开：银压暗一档，铂金提到接近白。 */
.coin-plat { color: #eaf4ff; }
.coin-gold { color: #e2bb45; }
.coin-silver { color: #9fadbf; }
.coin-copper { color: #cf8552; }

/* --------------------------------------------------------------- events */

.ev-intro { margin: 0 0 14px; line-height: 1.7; }
.ev-list { display: flex; flex-direction: column; gap: 10px; }

.ev-card { background: var(--bg-card); border: 1px solid var(--line);
  /* scrollIntoView puts the top edge at the top of the window, where the
   * sticky header sits - so leave room for it or the title disappears. */
  scroll-margin-top: calc(var(--header-h) + 12px);
           border-radius: 10px; overflow: hidden; }
.ev-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
           padding: 11px 14px; cursor: pointer; list-style: none; }
.ev-head::-webkit-details-marker { display: none; }
.ev-n { font-size: 12px; color: var(--fg-faint); min-width: 18px;
        font-variant-numeric: tabular-nums; }
.ev-t { font-size: 16px; font-weight: 600; }
.ev-sub { font-size: 11px; color: var(--fg-faint); }
.ev-stage { font-size: 11px; color: var(--accent);
            border: 1px solid var(--line); border-radius: 999px;
            padding: 1px 9px; }
.ev-c { margin-left: auto; font-size: 11px; color: var(--fg-dim); }

.ev-body { padding: 0 14px 14px; display: flex; flex-direction: column;
           gap: 12px; }
.ev-row { display: flex; gap: 12px; align-items: flex-start; }
.ev-k { flex: 0 0 62px; font-size: 12px; color: var(--fg-faint);
        padding-top: 2px; }
.ev-v { flex: 1; min-width: 0; font-size: 13px; line-height: 1.75; }
/* 灾厄事件的难度分级是项目符号列表（火把神那种），原版事件没有这一段 */
.ev-notes { margin: 6px 0 0; padding-left: 18px; }
.ev-notes li { margin: 2px 0; }


.ev-group + .ev-group { margin-top: 9px; }.ev-group-h { font-size: 11px; color: var(--accent); margin-bottom: 4px; }
.ev-group-en { color: var(--fg-faint); margin-left: 6px; }

.ev-chips { display: flex; flex-wrap: wrap; gap: 5px; }
.ev-npc, .ev-drop, .ev-chip {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 12px; padding: 2px 9px; border-radius: 999px;
  background: var(--bg-soft); border: 1px solid var(--line-soft);
  cursor: pointer; transition: border-color .12s, color .12s;
}
.ev-npc:hover, .ev-drop:hover, .ev-chip:hover {
  border-color: var(--accent); color: var(--accent);
}
.ev-drop { border-color: var(--line); }
.ev-none { font-size: 12px; color: var(--fg-faint); }
.ev-chip { border-color: var(--accent); color: var(--accent); margin-left: 6px; }

/* ------------------------------------------------------------ Boss 攻略
 * 一个 Boss 一张折叠卡，头沿用「特殊事件」那套 .ev-head，正文自己给内边距。 */
.bg-body { padding: 12px 16px 16px; }
.bg-intro { font-size: 13px; line-height: 1.85; color: var(--fg-dim);
  margin: 0 0 4px; }

.bg-sec { margin: 22px 0 0; }
.bg-sec h3 { font-size: 15px; margin: 0 0 8px; }
.bg-sec h4 { font-size: 13px; margin: 14px 0 6px; color: var(--accent); }
.bg-sec p { margin: 0 0 8px; font-size: 13px; line-height: 1.85; }
.bg-sec ul { margin: 6px 0 0; padding-left: 18px; font-size: 13px;
  line-height: 1.85; }

.bg-tabs { display: flex; gap: 6px; flex-wrap: wrap; margin: 10px 0 14px; }
.bg-tab { font-size: 13px; padding: 5px 12px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--bg-soft);
  color: var(--fg-dim); cursor: pointer; }
.bg-tab.on { border-color: var(--accent); color: var(--accent);
  background: var(--accent-soft); }

.bg-block { border: 1px solid var(--line-soft); border-radius: 10px;
  padding: 10px 12px; margin: 0 0 10px; background: var(--bg-card); }
.bg-block-h { font-size: 12px; color: var(--accent); margin-bottom: 8px; }
.bg-group { margin: 0 0 8px; }
.bg-group:last-child { margin-bottom: 0; }
.bg-group-h { font-size: 11px; color: var(--fg-faint); margin-bottom: 4px; }
.bg-items { display: flex; flex-wrap: wrap; gap: 5px; }
.bg-item { display: inline-flex; align-items: center; gap: 4px;
  font-size: 12px; padding: 2px 9px; border-radius: 999px;
  background: var(--bg-soft); border: 1px solid var(--line-soft);
  cursor: pointer; transition: border-color .12s, color .12s; }
.bg-item:hover { border-color: var(--accent); color: var(--accent); }
.bg-notes { margin: 12px 0 0; }
.bg-notes summary { font-size: 12px; color: var(--fg-faint); cursor: pointer; }
.bg-notes li { font-size: 12px; line-height: 1.75; color: var(--fg-dim);
  margin: 4px 0; }
.bg-src { font-size: 12px; color: var(--fg-faint); margin-top: 22px; }

/* ---------------------------------------------------------------- misc */
.empty {
  text-align: center;
  padding: 70px 20px;
  color: var(--fg-faint);
}

.empty .big { font-size: 40px; margin-bottom: 12px; opacity: .5; }

/* ------------------------------------------------------- 灾厄模式
 * 只换主色，骨架、导航、间距全复用原版。切过去整个站立刻换色，
 * 不用读文字也知道自己在哪套数据里。 */
body.mod-calamity {
  --accent: #a06af0;
  --accent-soft: #a06af020;
  --blue: #8fd0ff;
}

/* 灾厄没有制作站 / 钓鱼 / 微光三栏（数据库里也没有对应内容），按钮直接收起；
 * 用 display:none 而不是删 HTML，切回原版时原样回来。 */
body.mod-calamity nav button[data-tab="stations"],
body.mod-calamity nav button[data-tab="fishing"],
body.mod-calamity nav button[data-tab="shimmer"] { display: none; }

/* 灾厄栏目顶部的说明条 */
.mod-note {
  margin: 0 0 20px;
  padding: 12px 14px;
  border: 1px solid var(--line-soft);
  border-left: 3px solid var(--accent);
  border-radius: 0 10px 10px 0;
  background: var(--accent-soft);
  font-size: 13px; line-height: 1.75; color: var(--fg-dim);
}
.mod-note b { color: var(--fg); }
.mod-note code {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 12px;
  background: var(--bg-hover);
  padding: 1px 5px; border-radius: 4px;
}

/* 灾厄卡片：没有图标（两千七百多张图会让部署包翻倍），
 * 所以改成纵排 —— 类型徽章在上，名称居中，数值钉在底部对齐。 */
.cal-card {
  flex-direction: column;
  align-items: stretch;
  gap: 4px;
  padding: 12px 14px;
}
.cal-top { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; }
.cal-glyph { font-size: 15px; line-height: 1; }
/* 配方卡片里的图标必须跟原版 .icon 同尺寸（40px），
 * 否则灾厄材料比原版材料小一圈，两张卡片摆在一起就歪了 */
.recipe .cal-ico { width: 40px; height: 40px; flex: 0 0 40px; border-radius: 6px; }
.recipe .cal-glyph { font-size: 22px; width: 40px; text-align: center; }
/* 灾厄的图标是像素画，放大时必须用 pixelated，否则缩到 22px 会糊成一团 */
.cal-ico {
  width: 30px; height: 30px;
  object-fit: contain;
  image-rendering: pixelated;
  flex: 0 0 auto;
}
.cal-card .card-name { font-size: 14px; }
.cal-nums {
  margin-top: auto;
  padding-top: 6px;
  font-size: 12px;
  color: var(--fg-dim);
  font-variant-numeric: tabular-nums;
}

/* 合并之后列表里同时有原版和灾厄条目，卡片得说清楚这一条是谁加的。
 * 「灾厄改动」标记的是原版物品 —— 灾厄只调数值，东西还是原版的。 */
.cal-src { color: #9b7ede; border-color: #9b7ede; }
.cal-chg { color: #c98a2e; border-color: #c98a2e; }
.cal-chg.bad { color: #c2604f; border-color: #c2604f; }

/* 详情顶部的改动说明：只讲改了什么，不做新旧对照 */
.cal-notes-box {
  border: 1px solid var(--line);
  border-left: 3px solid #9b7ede;
  border-radius: 8px;
  padding: 10px 12px;
  margin-bottom: 14px;
  background: var(--bg-soft);
}
.cal-notes-head { font-size: 13px; font-weight: 600; color: #9b7ede; margin-bottom: 6px; }
.cal-recipe { display: flex; flex-direction: column; gap: 8px; }
/* 合成材料 / 制作站的链接：默认跟正文同色，不要蓝色虚线那种痕迹感，
 * 靠 hover 的下划线提示可点。 */
.mat-link {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px dotted var(--line-soft);
  cursor: pointer;
  transition: color .12s, border-color .12s;
}
.mat-link:hover {
  color: var(--accent);
  border-bottom: 1px solid var(--accent);
}
.cal-recipe-row {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px;
  padding: 9px 11px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--bg-soft); font-size: 13px;
}
.cal-recipe-row .tag {
  font-size: 11px; color: #9b7ede; border: 1px solid #9b7ede;
  border-radius: 4px; padding: 1px 5px;
}
.cal-recipe-row .mats { color: var(--fg); }
.cal-recipe-row .station { color: var(--fg-dim); font-size: 12px; }
.cal-notes-head.second { margin-top: 12px; }
.cal-sell-tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
.cal-sell-tbl th {
  text-align: left; font-weight: 500; color: var(--fg-faint);
  font-size: 12px; padding: 2px 8px 4px 0;
}
.cal-sell-tbl td {
  padding: 4px 8px 4px 0; border-top: 1px solid var(--line); vertical-align: top;
}
.cal-sell-tbl .price { white-space: nowrap; font-variant-numeric: tabular-nums; }
.cal-sell-tbl .cond { color: var(--fg-dim); font-size: 12px; }
.cal-notes-box ul {
  margin: 0; padding-left: 18px;
  font-size: 13px; color: var(--fg-dim); line-height: 1.75;
}

.cal-more { display: flex; justify-content: center; padding: 22px 0 8px; }

.cal-stage { color: var(--accent); border-color: var(--accent); }
.cal-badge-mod {
  background: var(--accent); color: #1a1c22; border-color: var(--accent);
}

.tree {
  background: var(--bg-card);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: 12px 14px;
  font-size: 13px;
}

.tree-node { padding-left: 16px; border-left: 1px dashed var(--line); margin: 4px 0 4px 8px; }
.tree-node:first-child { border-left: none; margin-left: 0; padding-left: 0; }
.tree-label { color: var(--fg-dim); margin-bottom: 4px; }

.note {
  font-size: 12px;
  color: var(--fg-faint);
  line-height: 1.6;
}

.loading {
  text-align: center;
  padding: 60px;
  color: var(--fg-faint);
}

.spinner {
  width: 26px;
  height: 26px;
  margin: 0 auto 12px;
  border: 3px solid var(--line);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin .7s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--line); margin-bottom: 18px; }

.tab {
  padding: 9px 16px;
  color: var(--fg-dim);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  font-size: 14px;
}

.tab:hover { color: var(--fg); }
.tab.on { color: var(--accent); border-bottom-color: var(--accent); }

.bar {
  height: 5px;
  border-radius: 3px;
  background: var(--bg);
  overflow: hidden;
}

.bar > i { display: block; height: 100%; background: var(--accent); }

.pill-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }

.pill {
  padding: 3px 9px;
  background: var(--bg);
  border: 1px solid var(--line-soft);
  border-radius: 20px;
  font-size: 12px;
  color: var(--fg-dim);
  cursor: pointer;
}

.pill:hover { border-color: var(--accent); color: var(--accent); }

footer {
  text-align: center;
  padding: 26px;
  color: var(--fg-faint);
  font-size: 12px;
  border-top: 1px solid var(--line-soft);
}

/* -------------------------------------------------- app 下载入口与更新条 */

/* Both blocks live outside <main> because every tab render replaces main's
 * innerHTML - a bar drawn inside it would vanish on the next filter change. */

.app-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 10px 20px;
  background: var(--accent-soft);
  border-bottom: 1px solid var(--line);
  font-size: 13px;
  color: var(--fg);
}

.app-bar b { color: var(--accent); }
.app-bar .spacer { flex: 1 1 auto; }

.app-bar button {
  min-height: 32px;
  padding: 0 14px;
  border: 1px solid var(--accent);
  border-radius: 16px;
  background: none;
  color: var(--accent);
  font: inherit;
  cursor: pointer;
}

.app-bar button.go {
  background: var(--accent);
  color: #1a1c22;
  font-weight: 600;
}

.app-bar button.close {
  border-color: transparent;
  color: var(--fg-dim);
  padding: 0 8px;
}

.app-bar button.close:hover { color: var(--fg); }

/* The download entry sits at the end of the tab row but is not a tab: an <a>
 * tinted with the accent, so it reads as "go get the app" rather than "switch
 * section". No border on purpose - padding matches nav button exactly, and the
 * tab row is already the tightest thing in the header. */
nav .nav-app {
  padding: 7px 14px;
  border-radius: 7px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 14px;
  text-decoration: none;
  transition: background .12s, color .12s;
}

nav .nav-app:hover { background: var(--accent); color: #1a1c22; }

/* ---------------------------------------------------------------- mobile */

/* Ten tabs plus the logo and the 原版/灾厄 switch leave too little room for the
 * search box before about this width, so from here down the box takes its own
 * full-width row instead of being squeezed down to a couple of characters. */
@media (max-width: 1120px) {
  header {
    height: auto;
    flex-wrap: wrap;
    padding: 10px 14px;
    gap: 10px;
  }
  .search-wrap { order: 3; max-width: 100%; flex-basis: 100%; }
  /* Right-align the wrapped rows so the first row still reads as a tab bar
   * rather than a ragged block. */
  nav { margin-left: auto; justify-content: flex-end; }
  /* The header is two rows tall here, so anchor jumps need more clearance. */
  :root { --header-h: 116px; }
  .ev-card, .ls { scroll-margin-top: 128px; }
  .suggest.on { max-height: 52vh; }
  main { padding: 16px 14px 60px; }
  .grid { grid-template-columns: repeat(auto-fill, minmax(min(150px, 100%), 1fr)); }
  .modal-head { flex-wrap: wrap; }
  .stats { grid-template-columns: repeat(2, 1fr); }
}/* ------------------------------------------------------------------ guide */

.guide { max-width: 860px; margin: 0 auto; padding: 8px 0 40px; }
.guide-head { padding: 4px 0 18px; border-bottom: 1px solid var(--line); }
.guide-head h1 { font-size: 22px; margin: 0 0 6px; }
.gd-stage { margin-top: 26px; }
.gd-stage h2 {
  font-size: 17px; margin: 0 0 4px; padding-left: 10px;
  border-left: 3px solid var(--accent);
}
.gd-stage-note { margin: 0 0 16px; }
.gd-boss {
  background: var(--bg-card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px; margin-bottom: 16px;
}
.gd-boss-head { display: flex; gap: 14px; align-items: center; }
.gd-boss-head .icon {
  width: 74px; height: 74px; flex: 0 0 74px;
  border-radius: 10px; border: 1px solid var(--line);
  background: var(--bg-soft);
}
.gd-boss-head h3 { font-size: 18px; margin: 0 0 2px; }
.gd-en { font-size: 12px; color: var(--fg-faint); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.gd-meta { margin: 12px 0 4px; font-size: 13px; line-height: 1.85; }
.gd-meta p { margin: 0; }
.gd-meta b { color: var(--accent); font-weight: 600; }
.gd-gear { margin-top: 12px; border-top: 1px dashed var(--line-soft); padding-top: 10px; }
.gd-row { display: flex; gap: 10px; padding: 6px 0; align-items: flex-start; }
.gd-key { flex: 0 0 42px; font-size: 12px; color: var(--fg-faint); padding-top: 7px; text-align: right; }
.gd-items { display: flex; flex-wrap: wrap; gap: 6px; flex: 1; }
.gd-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px 4px 5px; border-radius: 8px;
  background: var(--bg-soft); border: 1px solid var(--line-soft);
  font-size: 12px;
}
/* An item chip behaves like a button: hover/focus affordance, and the cursor has
 * to say so, because it is a <span> for layout reasons. */
.gd-chip[data-item] { cursor: pointer; }
.gd-chip[data-item]:hover,
.gd-chip[data-item]:focus-visible {
  border-color: var(--accent); color: var(--accent); outline: none;
}
.gd-chip .icon { width: 22px; height: 22px; }
.gd-chip-n { max-width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gd-tips { margin: 10px 0 0; padding-left: 18px; font-size: 13px; line-height: 1.9; }
.gd-tips li { margin: 2px 0; color: var(--fg-dim); }
@media (max-width: 620px) {
  .gd-boss { padding: 12px; }
  .gd-boss-head .icon { width: 56px; height: 56px; flex-basis: 56px; }
  .gd-key { flex-basis: 34px; }
  .gd-chip-n { max-width: 92px; }
}

.gd-fight { margin-top: 12px; padding-top: 10px; border-top: 1px dashed var(--line-soft); }
.gd-fight h4 { font-size: 13px; margin: 0 0 4px; color: var(--accent); }
.gd-wiki { margin-top: 8px; }
.gd-wiki > summary { cursor: pointer; list-style: none; font-size: 12px; }
.gd-wiki > summary::-webkit-details-marker { display: none; }
.gd-wiki[open] > summary::before { content: "▾ "; }
.gd-wiki > summary::before { content: "▸ "; color: var(--fg-faint); }

.gd-gear-title { font-size: 13px; color: var(--accent); margin: 0 0 6px; }
.gd-weapons { border-top: 1px dashed var(--line-soft); padding-top: 8px; }
.gd-why {
  font-size: 11px; color: var(--fg-faint); max-width: 260px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gd-chip[data-item]:hover .gd-why { color: var(--accent); }

/* ---- guide gear: grouped by set / class, reasons on their own line ---- */


.gd-row { display: flex; gap: 10px; padding: 4px 0; align-items: flex-start; }
.gd-key {
  flex: 0 0 46px; font-size: 12px; color: var(--fg-faint);
  padding-top: 8px; text-align: right; font-weight: 600;
}
.gd-items { display: flex; flex-wrap: wrap; gap: 6px; flex: 1; align-content: flex-start; }

/* Armour: one row per set, set name printed once. */
.gd-asets { flex: 1; }
.gd-aset { display: flex; gap: 8px; align-items: flex-start; padding: 3px 0; }
.gd-aset-n {
  flex: 0 0 62px; font-size: 11px; color: var(--fg-dim);
  padding-top: 8px; text-align: right;
}
.gd-hint { font-size: 11px; color: var(--fg-faint); margin: 4px 0 0 70px; }

/* Weapons: class label, then each pick with its reason below the chip. */
.gd-weapons { border-top: 1px dashed var(--line-soft); padding-top: 8px; }
.gd-wclass { display: flex; gap: 10px; align-items: flex-start; padding: 5px 0; }
.gd-wclass-n {
  flex: 0 0 46px; font-size: 12px; color: var(--accent);
  padding-top: 8px; text-align: right; font-weight: 600;
}
.gd-wlist { flex: 1; display: flex; flex-direction: column; gap: 6px; }
.gd-witem { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.gd-why { font-size: 12px; color: var(--fg-dim); line-height: 1.5; flex: 1; min-width: 180px; }
.gd-chip[data-item]:hover .gd-why { color: var(--accent); }

.gd-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px 4px 5px; border-radius: 8px;
  background: var(--bg-soft); border: 1px solid var(--line-soft);
  font-size: 12px;
}
.gd-chip[data-item] { cursor: pointer; }
.gd-chip[data-item]:hover,
.gd-chip[data-item]:focus-visible {
  border-color: var(--accent); color: var(--accent); outline: none;
}
.gd-chip .icon { width: 22px; height: 22px; flex: 0 0 22px; }
.gd-chip-n { white-space: nowrap; }

@media (max-width: 620px) {
  .gd-key, .gd-wclass-n { flex-basis: 38px; font-size: 11px; }
  .gd-aset-n { flex-basis: 52px; }
  .gd-hint { margin-left: 60px; }
  .gd-why { min-width: 120px; font-size: 11px; }
}

/* ---- fishing column ---- */

.fishing { max-width: 900px; margin: 0 auto; padding: 8px 0 40px; }

/* Two halves of the fishing column: the wiki catch table (a lookup) and the
 * third-party article (prose). They are a switch rather than one merged page
 * because they disagree in places and merging them would hide that. */
.fg-subbar { display: flex; gap: 6px; margin: 14px 0 4px; flex-wrap: wrap; }
.fg-sub {
  display: inline-flex; align-items: baseline; gap: 7px;
  padding: 7px 14px; border-radius: 8px; border: 1px solid var(--line);
  background: var(--bg-card); color: var(--fg-dim); font-size: 14px;
  cursor: pointer; transition: border-color .12s, color .12s, background .12s;
}
.fg-sub:hover { color: var(--fg); border-color: var(--accent); }
.fg-sub.on { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.fg-sub-n { font-size: 11px; color: var(--fg-faint); font-weight: 400; }

/* ---- the reproduced article ---- */

.fg-article { max-width: 900px; margin: 0 auto; padding: 8px 0 40px; }

.fg-attr {
  display: flex; gap: 20px; align-items: flex-start; flex-wrap: wrap;
  padding: 18px 20px; margin-bottom: 14px;
  background: var(--bg-card); border: 1px solid var(--line); border-radius: var(--radius);
}
.fg-attr-main { flex: 1 1 420px; min-width: 0; }
.fg-attr-kicker { font-size: 11px; color: var(--accent); letter-spacing: .08em; margin-bottom: 6px; }
.fg-attr h1 { font-size: 21px; margin: 0 0 8px; line-height: 1.35; }
.fg-attr-by { font-size: 12px; color: var(--fg-dim); }
.fg-attr-by b { color: var(--fg); }
.fg-lv {
  display: inline-block; margin: 0 4px; padding: 0 6px; border-radius: 999px;
  font-size: 10px; color: var(--accent); border: 1px solid var(--line);
}
.fg-attr-side { flex: 0 1 320px; min-width: 0; }

.fg-src { display: block; text-decoration: none; }
.fg-src-btn {
  display: inline-block; padding: 6px 12px; border-radius: 7px;
  background: var(--accent-soft); color: var(--accent); font-size: 13px; font-weight: 600;
}
.fg-src:hover .fg-src-btn { filter: brightness(1.08); }
.fg-src-url {
  display: block; margin-top: 5px; font-size: 10px; color: var(--fg-faint);
  word-break: break-all; line-height: 1.35;
}

.fg-note {
  font-size: 13px; color: var(--fg-dim); line-height: 1.7;
  padding: 11px 14px; margin: 0 0 22px;
  background: var(--bg-soft); border-left: 3px solid var(--accent); border-radius: 0 7px 7px 0;
}
.fg-note b { color: var(--fg); }

/* The article body. Widths come from the author (width/height attributes), so
 * the figures are capped to the column and scroll rather than overflow it. */
.fg-body { font-size: 14px; line-height: 1.85; color: var(--fg); }
.fg-body h2 {
  font-size: 18px; margin: 34px 0 10px; padding-left: 10px;
  border-left: 3px solid var(--accent); scroll-margin-top: calc(var(--header-h) + 12px);
}
.fg-body h2:first-child { margin-top: 4px; }
.fg-body h3 { font-size: 15px; margin: 22px 0 8px; color: var(--fg); }
.fg-body p { margin: 9px 0; }
.fg-body b, .fg-body strong { color: var(--accent); font-weight: 600; }
.fg-body ul { margin: 9px 0; padding-left: 22px; }
.fg-body li { margin: 4px 0; }
.fg-body code {
  background: var(--bg-hover); padding: 1px 5px; border-radius: 4px;
  font-family: ui-monospace, Consolas, monospace; font-size: 12px;
}
.fg-body hr.art-rule { border: none; border-top: 1px dashed var(--line); margin: 30px 0; }

/* The figures that stayed as images - the step-by-step shots, the water-volume
 * sketch, the six animations. */
.fg-body figure, .fg-body .fg-fig { margin: 18px 0; }
.fg-body img {
  display: block; max-width: 100%; height: auto; margin: 0 auto;
  border: 1px solid var(--line); border-radius: 8px; background: var(--bg);
}
.fg-body > figcaption, .fg-body figure > figcaption {
  margin-top: 7px; text-align: center; font-size: 12px; color: var(--fg-faint);
}

/* Tables rebuilt from the article's screenshots. The original images were
 * 1300px wide, so these cap at the column and scroll horizontally on narrow
 * screens rather than shrinking the numbers until they are unreadable. */
.fg-tbl { margin: 18px 0 22px; }
.fg-tbl > figcaption {
  margin-bottom: 8px; text-align: left; font-size: 13px; font-weight: 600; color: var(--fg);
}
.fg-tbl-note {
  display: block; margin-top: 3px; font-weight: 400; font-size: 11px; color: var(--fg-faint);
  line-height: 1.6;
}
.fg-tbl .tbl-wrap, .fg-tbl table { width: 100%; }
.fg-tbl table {
  border-collapse: collapse; font-size: 12px; background: var(--bg-card);
  border: 1px solid var(--line);
}
.fg-tbl th {
  padding: 7px 9px; text-align: left; font-weight: 600; color: var(--accent);
  background: var(--bg-soft); border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.fg-tbl td {
  padding: 6px 9px; border-bottom: 1px solid var(--line-soft);
  vertical-align: top; color: var(--fg-dim); line-height: 1.6;
}
.fg-tbl td:first-child { color: var(--fg); }
.fg-tbl tr:last-child td { border-bottom: none; }
.fg-tbl tbody tr:hover { background: var(--bg-hover); }
.fg-tbl .fg-subhead td {
  padding: 7px 9px; background: var(--bg-soft); color: var(--accent);
  font-size: 11px; font-weight: 600; letter-spacing: .04em;
}

/* Item / NPC names inside the tables are buttons so they get the same hover and
 * focus behaviour as the rest of the page, and open the same modals. */
.fg-link {
  appearance: none; background: none; border: none; padding: 0; cursor: pointer;
  color: var(--accent); font: inherit; font-size: 12px; text-align: left;
}
.fg-link:hover { text-decoration: underline; }

/* Keep a wide table inside the column: let the table scroll rather than the
 * whole page, which is what the original screenshot forced anyway. */
.fg-tbl { overflow-x: auto; }
@media (max-width: 1024px) {
  .fg-body h2 { scroll-margin-top: 128px; }
}
.fg-tools { display: flex; gap: 12px; align-items: center; margin: 14px 0 18px; }
.fg-tools input {
  flex: 1; font: inherit; font-size: 13px; padding: 8px 12px;
  border-radius: 8px; border: 1px solid var(--line);
  background: var(--bg-soft); color: var(--fg);
}
.fg-tools input:focus { outline: none; border-color: var(--accent); }
.fg-h2 {
  font-size: 16px; margin: 22px 0 10px; padding-left: 10px;
  border-left: 3px solid var(--accent);
}
.fg-h2 .count { font-size: 12px; color: var(--fg-faint); font-weight: 400; margin-left: 6px; }

/* One row per fish / crate. Icon left, conditions right, whole row links. */
.fg-row {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 10px 12px; margin-bottom: 8px;
  background: var(--bg-card); border: 1px solid var(--line);
  border-radius: var(--radius); cursor: pointer;
}
.fg-row:hover { border-color: var(--accent); }
.fg-row:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.fg-row > .icon { width: 34px; height: 34px; flex: 0 0 34px; }
.fg-row-main { flex: 1; min-width: 0; }

/* A crate's drop table. Collapsed by default because all 26 open at once was
 * 22,600px - a quarter of a phone screen spent on wood and pebble. */
.fg-box {
  background: var(--bg-card); border: 1px solid var(--line);
  border-radius: var(--radius); margin-bottom: 8px;
}
.fg-box-h {
  display: flex; gap: 12px; align-items: center;
  padding: 10px 12px; cursor: pointer; list-style: none;
}
.fg-box-h::-webkit-details-marker { display: none; }
.fg-box-h:hover { border-radius: var(--radius); }
.fg-box-h::after {
  content: "▸"; color: var(--fg-faint); font-size: 12px; flex: 0 0 auto;
  transition: transform .15s;
}
.fg-box[open] > .fg-box-h { border-bottom: 1px dashed var(--line); }
.fg-box[open] > .fg-box-h::after { transform: rotate(90deg); }
.fg-box-h .icon { width: 30px; height: 30px; flex: 0 0 30px; }
.fg-box-h .fg-name { margin-bottom: 2px; }
.fg-box-more {
  flex: 0 0 auto; font-size: 11px; color: var(--accent);
  border: 1px solid var(--line); border-radius: 999px; padding: 3px 9px;
  cursor: pointer; background: var(--bg-soft);
}
.fg-box-more:hover { border-color: var(--accent); background: var(--accent-soft); }
.fg-box-body { padding: 10px 12px 12px; }
.fg-box-all {
  margin-left: 10px; font: inherit; font-size: 11px; cursor: pointer;
  background: none; border: 1px solid var(--line); color: var(--fg-dim);
  border-radius: 999px; padding: 2px 9px;
}
.fg-box-all:hover { border-color: var(--accent); color: var(--accent); }

.fg-name { font-size: 14px; margin-bottom: 4px; }
.fg-name .fg-en { font-size: 11px; color: var(--fg-faint); margin-left: 8px; }
.fg-cond { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.fg-tag {
  font-size: 11px; padding: 2px 8px; border-radius: 20px;
  background: var(--accent-soft); color: var(--accent);
  border: 1px solid var(--accent-soft);
}
.fg-cond-none { font-size: 12px; color: var(--fg-faint); }
.fg-where { font-size: 12px; color: var(--fg-dim); }
.fg-num { font-size: 11px; color: var(--fg-faint); }
.fg-warn { font-size: 11px; color: var(--red); margin: 6px 0 2px; }
.fg-en { font-size: 11px; color: var(--fg-faint); line-height: 1.6; margin: 0; }
.fg-loot { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
/* The whole loot table is listed, so each chip carries its drop chance:
   without it a 66-item row is an undifferentiated wall of names. */
.fg-chip .gd-chip-n { max-width: none; }
.fg-chip-r { font-size: 10px; color: var(--fg-faint); flex: 0 0 auto;
             font-variant-numeric: tabular-nums; }
.fg-chip[data-item]:hover .fg-chip-r { color: var(--accent); }
.fg-more { font-size: 11px; color: var(--fg-faint); align-self: center; }
/* ----------------------------------------------------------------- shimmer */
/* A conversion reads as an equation, so the two ends sit on one baseline with
 * the arrow between them and the whole row wraps as a unit. */
.sh-group { margin-bottom: 4px; }
.sh-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr));
           gap: 4px 14px; }
.sh-row { display: flex; align-items: center; gap: 8px; min-width: 0;
          padding: 3px 6px; border-radius: 6px; }
.sh-row:hover { background: var(--bg-2, rgba(255,255,255,.04)); }
.sh-side { display: inline-flex; align-items: center; gap: 6px; min-width: 0;
           cursor: pointer; border-radius: 5px; padding: 2px 4px; }
.sh-side:hover { background: rgba(255,255,255,.06); }
.sh-side .icon { width: 22px; height: 22px; flex: 0 0 22px; }
.sh-side .gd-chip-n { max-width: none; white-space: nowrap; overflow: hidden;
                      text-overflow: ellipsis;
                      /* auto means "the whole nowrap text" inside a flex
                       * container, so a long name pinned the row at its full
                       * width and pushed the page sideways on a phone. */
                      min-width: 0; }
/* The wiki's "Any Fruit" / "Any Torch" stand for a whole family: no single
   item exists to open, so they are shown but not made clickable. */
.sh-any { cursor: default; opacity: .85; font-style: italic; }
.sh-any:hover { background: none; }
/* The sides are inline-level boxes, so `min-width` on them does nothing - they
 * are sized by their content and a long name overflows the row. Making the two
 * halves flex containers turns each side into a flex item that can shrink. */
.sh-from { flex: 0 1 auto; min-width: 0; display: flex; align-items: center; }
.sh-to { flex: 0 1 auto; min-width: 0; display: flex; align-items: center; }
.sh-arrow { color: var(--accent); flex: 0 0 auto; font-size: 13px; }
.sh-note { display: flex; align-items: center; gap: 6px; min-width: 0;
           color: var(--fg-dim, #bbb); font-size: 13px; }
.sh-row-consume .sh-note span { white-space: normal; }
.sh-warn { color: var(--red); }
.sh-list { margin-top: 8px; }

/* ------------------------------------------------------------ fishing areas */
/* One area = a titled block; inside it, each kind of catch gets its own dense
 * chip grid so "here you get fish and a weapon" reads at a glance. */
.fa-block { margin: 0 0 22px; }
.fa-title { font-size: 15px; margin: 0 0 2px; display: flex; gap: 8px;
            align-items: baseline; }
.fa-note { margin: 0 0 8px; font-size: 12px; line-height: 1.6; }
.fa-kind { display: grid; grid-template-columns: 84px 1fr; gap: 10px;
           align-items: start; margin-bottom: 6px; }
.fa-kind-n { font-size: 12px; color: var(--fg-faint); padding-top: 4px;
            white-space: nowrap; }
.fa-kind .fg-loot { margin-top: 0; }
.fa-crates { font-size: 12px; color: var(--fg-faint); margin-top: 6px;
            padding-left: 94px; }
.fa-crate { display: inline-block; margin-right: 8px; color: var(--accent); }
.fg-chip-enemy .gd-chip-n { color: var(--red); }
@media (max-width: 640px) {
  .fa-kind { grid-template-columns: 1fr; gap: 2px; }
  .fa-crates { padding-left: 0; }
}

/* The shimmer grid floors each column at 320px, which is wider than the
 * viewport on a small phone and pushed the page out. One full-width column is
 * the right shape below that width. */
@media (max-width: 400px) {
  .sh-list { grid-template-columns: 1fr; }
}

/* On a phone the header was four visual rows tall - logo, two rows of tabs,
 * search - which came to 174px and ate a third of a small viewport. Putting the
 * search beside the logo and letting the tabs take the full width below brings
 * it to about 130px, and the tabs get a second row to themselves rather than
 * fighting the logo for width.
 *
 * The iframe used to check this is only 560px tall, so the percentages here look
 * worse than they are on a real phone; the absolute heights are what matter. */
@media (max-width: 620px) {
  header { gap: 8px; padding: 8px 12px 6px; }
  .logo { font-size: 14px; gap: 6px; }
  /* The version number is the first thing to go; the title already says what
   * this is. */
  .logo small { display: none; }
  /* 手机上一行放不下 logo + 切换器 + 搜索框，搜索框独占一行，
   * 切换器贴到 logo 右边，导航留在第三行。 */
  .mod-switch { order: 1; margin-left: auto; }
  .search-wrap { order: 2; flex: 1 1 100%; max-width: none; min-width: 0; }
  #search { padding: 7px 12px 7px 32px; font-size: 14px; }
  .search-icon { left: 10px; }
  nav { order: 3; flex-basis: 100%; margin-left: 0; justify-content: center; }
  nav button, nav .nav-app { padding: 6px 10px; font-size: 12px; min-height: 34px; }
  /* Chips and dots were 24-27px tall, which is a miss more often than a hit on
   * a touch screen. 32px is the smallest target that is reliably tappable. */
  .ev-npc, .ev-drop, .ev-chip { padding: 6px 9px; min-height: 32px; }
  .chip { min-height: 32px; }
  .sh-side { min-height: 30px; }
  .gt-sm, .ln { min-height: 32px; }
  .ln { width: 32px; height: 32px; }
  /* 10px is the size the dense catch chips use on a desktop; on a phone it is
   * below what most people can read without zooming. */
  .fg-chip-r { font-size: 11px; }
  .fg-tools a, .fa-note a { padding: 6px 2px; }
  /* inline-block, not inline-flex: the footer's source URL has to be allowed to
   * wrap, and an inline-level flex box is sized by its content instead - which
   * is what pushed the page 141px wide on a phone. */
  footer a { display: inline-block; padding: 8px 2px; min-height: 32px;
             word-break: break-all; overflow-wrap: anywhere; }
  .fg-link { padding: 5px 2px; min-height: 30px; }
  .gt { padding: 7px 12px; min-height: 36px; }
  .fg-sub, .fg-tools input { min-height: 38px; }
}

/* --------------------------------------------------------------------- gear */
/* A run through the world: each milestone is a column, arrows run between
 * them. Columns scroll independently so a 40-item stage does not stretch the
 * whole page. */
.gt-bar { display: flex; gap: 6px; flex-wrap: wrap; align-items: center;
          margin-top: 8px; }
.gt { font: inherit; font-size: 13px; padding: 4px 10px; border-radius: 6px;
      border: 1px solid var(--line); background: transparent; color: var(--fg);
      cursor: pointer; display: inline-flex; align-items: center; gap: 6px; }
.gt:hover { border-color: var(--accent); }
.gt.on { background: var(--accent); border-color: var(--accent); color: #10101a; }
.gt-sm { font-size: 12px; padding: 3px 8px; }

/* ---------------------------------------------------------------- 合成路线 */
.gear-gap { font-size: 12px; line-height: 1.6; margin: 10px 0 0;
            padding: 8px 10px; border-left: 2px solid var(--line);
            color: var(--fg-dim); }

/* ------------------------------------------------------------- 配装路线 */
.lo-tabs { margin-bottom: 14px; }
.lo-tabs .gt { font-size: 14px; padding: 7px 16px; }
.lo-tabs .gt .count { margin-left: 6px; }
.lo { border: 1px solid var(--line); border-radius: var(--radius);
      background: var(--bg-card); overflow: hidden; }
.lo-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
           padding: 12px 16px 10px; border-bottom: 1px solid var(--line);
           background: var(--bg-soft); }
.lo-head h2 { margin: 0; font-size: 19px; display: flex;
              align-items: baseline; gap: 8px; }
.lo-sub { font-size: 12px; color: var(--accent); font-weight: 400; }
.lo-stat { margin-left: auto; font-size: 12px; color: var(--fg-dim); }
.lo-nav { display: flex; flex-wrap: wrap; gap: 4px; padding: 10px 16px;
          border-bottom: 1px solid var(--line); }
.ln { display: inline-flex; align-items: center; justify-content: center;
      width: 24px; height: 24px; border-radius: 50%; font-size: 12px;
      text-decoration: none; color: var(--fg-dim);
      background: var(--bg); border: 1px solid var(--line); }
.ln:hover { border-color: var(--accent); color: var(--accent); }
.ls { border-bottom: 1px solid var(--line); scroll-margin-top: calc(var(--header-h) + 12px); }
.ls:last-child { border-bottom: 0; }
.ls-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
           padding: 11px 16px; cursor: pointer; list-style: none;
           background: var(--bg-soft); }
.ls-head::-webkit-details-marker { display: none; }
.ls-n { display: inline-flex; align-items: center; justify-content: center;
        width: 22px; height: 22px; flex: none; border-radius: 50%;
        font-size: 11px; font-weight: 600; color: var(--accent);
        border: 1px solid var(--accent); }
.ls-t { font-size: 14px; font-weight: 600; }
.ls-g { font-size: 12px; color: var(--fg-dim); }
.ls-c { margin-left: auto; font-size: 11px; color: var(--fg-faint); }
.ls[open] > .ls-head { border-bottom: 1px dashed var(--line); }
.ls[open] > .ls-head .ls-c { color: var(--green); }
/* min(300px, 100%), not 300px: at a 320px phone the body is ~275px wide, and a
 * hard 300px floor made the track wider than its container - the stage's items
 * were laid out at 300px and the right-hand 25px was simply cut off. */
.ls-body { padding: 14px 16px 18px; display: grid; gap: 16px;
           grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
           align-items: start; }
/* Grid and flex items default to min-width:auto, which resolves to min-content
 * and lets a nowrap child hold a track open past the viewport. */
.ls-body > * { min-width: 0; }

/* Wide enough for two columns of slot cards. Multi-column rather than a grid
 * because the cards are wildly different heights - a nine-piece slot next to a
 * fifteen-piece one left a hole half a screen tall in the second column. */
@media (min-width: 700px) {
  .ls-body { display: block; column-count: 2; column-gap: 16px; }
  .ls-body > * { break-inside: avoid; margin-bottom: 16px; }
}
@media (min-width: 1180px) {
  .ls-body { column-count: 3; }
}
.pr-group h4 { margin: 0 0 9px; font-size: 12px; letter-spacing: .04em;
               color: var(--accent); display: flex; gap: 6px;
               align-items: baseline; }
/* A slot is a section, and reads as one because it is one box - otherwise six
 * headings and six item lists float on the page with nothing grouping them. */
.pr-group { padding: 12px 13px 13px; border-radius: var(--radius);
            background: var(--bg-card); border: 1px solid var(--line-soft); }
.pr-armour { grid-column: 1 / -1; }
.pa { border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px;
      margin-bottom: 10px; background: var(--bg); position: relative; }
.pa-alt { opacity: .88; }
.pa-tag { position: absolute; top: -9px; left: 10px; font-size: 10px;
          padding: 1px 8px; border-radius: 999px; color: var(--fg-dim);
          background: var(--bg-soft); border: 1px solid var(--line); }
.pa-main { color: var(--green); border-color: var(--green); }
.pa-slot { display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
           padding: 3px 0; }
.pa-l { font-size: 11px; color: var(--fg-faint); width: 32px; flex: none; }
.pa-none { color: var(--fg-faint); }
.pa .pi-tree { flex-basis: 100%; margin-left: 38px; }

/* --------------------------------------------- UP 主攻略（美味的猫尾巴） */
.lo-boards { margin-bottom: 12px; }
.lo-boards .gt { font-size: 13px; padding: 6px 14px; }
.lo-mw { border-color: var(--accent); }
.lo-src { font-size: 12px; color: var(--accent); text-decoration: none;
          margin-left: auto; }
.lo-src:hover { text-decoration: underline; }
.mw-intro { padding: 12px 16px; border-bottom: 1px solid var(--line);
            background: var(--bg-soft); }
.mw-intro p { margin: 0 0 6px; font-size: 12px; line-height: 1.7;
              color: var(--fg-dim); }
.mw-intro p:last-child { margin-bottom: 0; }
.pi-reason { font-size: 11px; color: var(--accent); margin: 0 0 6px; }
.pi-free .pi-zh { color: var(--fg-dim); font-style: italic; }
.pi-free { opacity: .8; }
.mw-notes h4 { color: var(--purple); }
.mw-notes p { font-size: 11px; line-height: 1.7; color: var(--fg-dim);
              margin: 0 0 5px; }

/* The article's in-game screenshots, written out as text. Dashed so it reads as
 * transcribed-from-a-picture rather than as something the author wrote: it is
 * her picture, not her wording. */
.ms { padding: 12px 14px; border-radius: var(--radius);
      background: var(--bg-card); border: 1px dashed var(--line); }
.ms h4 { margin: 0 0 6px; font-size: 12px; letter-spacing: .04em;
        color: var(--fg-dim); display: flex; align-items: baseline; gap: 8px; }
.ms h4 .count { margin-left: 0; }
.ms-tail { color: var(--fg-faint); }
.ms-todo { margin: 8px 0 0; padding: 7px 10px; border-radius: 8px;
           font-size: 11px; line-height: 1.55; color: var(--fg-dim);
           border: 1px dashed var(--line); background: var(--bg-soft); }
.ms-todo b { color: var(--fg); font-weight: 600; }
.ms-todo ul { margin: 6px 0 4px; padding-left: 18px; }
.ms-todo li { margin: 1px 0; }
.ms-todo span { color: var(--fg-faint); font-size: 10px; }
.ms-shapes { margin: 0; }
.ms-group { margin-top: 10px; }
.ms-group h5 { margin: 0 0 6px; font-size: 12px; color: var(--accent);
               display: flex; align-items: baseline; gap: 8px; }
.ms-list { list-style: none; margin: 0; padding: 0;
           display: flex; flex-wrap: wrap; gap: 6px; }
.ms-list .pi { display: inline-flex; align-items: center; gap: 5px;
               padding: 4px 8px 4px 4px; min-height: 30px;
               border: 1px solid var(--line); border-radius: 999px;
               background: var(--bg-soft); cursor: pointer; }
.ms-list .pi:hover { border-color: var(--accent); }
.ms-list .pi .pi-zh { font-size: 12px; }
.ms-tree { background: var(--bg-soft); }
.pr { margin: 0 0 14px; padding: 12px 14px; border-radius: var(--radius);
      background: var(--bg-card); border: 1px solid var(--line); }
.pr-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
           margin-bottom: 10px; padding-bottom: 8px;
           border-bottom: 1px solid var(--line); }
.pr-head h3 { margin: 0; font-size: 15px; }
.pr-src { font-size: 11px; color: var(--fg-faint); }
.pr-head .count { margin-left: auto; }
.pr-slots { display: grid; gap: 12px;
            grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr)); }
.pr-slot h4 { margin: 0 0 6px; font-size: 12px; color: var(--accent);
              letter-spacing: .04em; }
/* One card per row. Two per row was tried and is not better: the group's column
 * is ~450px, so the cards drop to ~210px and the author's one-line reason
 * wraps to two, which saves no height and reads worse. The height comes down by
 * giving the slots more columns instead (see .ls-body). */
.pi-list { list-style: none; margin: 0; padding: 0;
           display: flex; flex-direction: column; gap: 6px; }
.pi { display: block; }
.pi > span:first-of-type, .pa-slot > span:first-of-type { }
.pi-zh { font-size: 13px; }
/* The reason the author wrote for this one piece. */
.pi-note { color: var(--fg-dim); }
/* A category she named once - 任意气球 - standing for everything of that kind
 * this stage can actually give you. */
.pi-cat { margin-top: 8px; border-radius: 8px; background: var(--bg-soft);
          border: 1px solid var(--line-soft); }
.pi-cat[open] { border-color: var(--line); }
/* One line until asked. The caret is a drawn triangle rather than the platform
 * marker so it sits on the same baseline as the label at every font size. */
.pi-cat-h { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
            padding: 7px 10px; min-height: 34px; cursor: pointer;
            list-style: none; }
.pi-cat-h::-webkit-details-marker { display: none; }
.pi-cat-h:hover { background: var(--bg-hover); border-radius: 7px; }
.pi-cat-caret { width: 0; height: 0; flex: 0 0 auto;
                border-left: 5px solid var(--fg-faint);
                border-top: 4px solid transparent;
                border-bottom: 4px solid transparent;
                transition: transform .15s; }
.pi-cat[open] > .pi-cat-h .pi-cat-caret { transform: rotate(90deg); }
.pi-cat-lb { font-size: 12px; color: var(--accent); font-weight: 600;
             border: 1px solid var(--accent); border-radius: 999px;
             padding: 1px 8px; }
.pi-cat-n { font-size: 11px; color: var(--fg-dim); }
/* A sample of what is inside, so a closed row still says something. Dropped
 * below the width where it would push the row onto a second line - a dropdown
 * row that wraps is no longer one row. */
.pi-cat-first { font-size: 11px; color: var(--fg-faint); margin-left: auto;
                padding-left: 10px; white-space: nowrap; overflow: hidden;
                text-overflow: ellipsis; max-width: 46%; }
@media (max-width: 700px) {
  .pi-cat-first { display: none; }
}
.pi-cat-list { padding: 2px 8px 8px; }
.pi-cat-list .pi-zh { font-size: 12px; }
/* A category block is a menu of equivalents - "这一阶段能拿到的 10 件，任选其一"
 * - so it reads as a set, not as ten separate recommendations. One per row made
 * 任意鞋 alone 544px tall, which is what set the height of the whole stage. */
.pi-cat-list { display: grid; gap: 6px;
               grid-template-columns: repeat(auto-fill, minmax(min(176px, 100%), 1fr)); }
.pi-cat-list .pi { display: grid;
                   grid-template-columns: 24px minmax(0, 1fr);
                   grid-template-areas: "ico zh" "ico src" "mat mat";
                   column-gap: 7px; row-gap: 0; align-content: start;
                   padding: 5px 7px; border-radius: 8px;
                   border: 1px solid var(--line-soft); background: var(--bg-soft); }
.pi-cat-list .pi:hover { border-color: var(--line); background: var(--bg-hover); }
.pi-cat-list .pi > .icon { grid-area: ico; width: 24px; height: 24px; align-self: start; }
.pi-cat-list .pi > .pi-zh { grid-area: zh; }
.pi-cat-list .pi > .pi-src { grid-area: src; font-size: 10px; }
.pi-cat-list .pi > .pi-tree { grid-area: mat; justify-self: start; margin-top: 4px; }
.pi-cat-list .pi-tree > summary { font-size: 10px; padding: 2px 8px; }
.pi-cat-list .mt span { font-size: 11px; }
.pi-g, .pi-mat { font-size: 10px; color: var(--fg-faint); margin-left: 5px;
                padding: 1px 5px; border-radius: 999px; background: var(--bg-soft); }
.pi-mat { color: var(--green); }

/* One listed item, as a self-contained card: the icon and the name sit on one
 * line, the author's own reason under it, where it drops from. The material
 * list gets the full width of the card under all of that.
 *
 * It used to be a wrapping flex row with the material toggle pushed to the far
 * right of whichever line it landed on, which on a 450px card put the pill in
 * the middle of empty space, at a different x for every item. A fixed grid
 * puts the same thing in the same place every time. */
.pi:not(.pi-cat) {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr);
  grid-template-areas: "ico zh" "ico note" "ico src" "mat mat";
  column-gap: 9px; row-gap: 1px; align-content: start;
  padding: 7px 9px; border-radius: 8px;
  border: 1px solid var(--line-soft); background: var(--bg-soft);
}
.pi:not(.pi-cat):hover { border-color: var(--line); background: var(--bg-hover); }
.pi:not(.pi-cat) > .icon { grid-area: ico; width: 30px; height: 30px; align-self: start; }
.pi:not(.pi-cat) > .pi-zh { grid-area: zh; align-self: center; }
.pi:not(.pi-cat) > .pi-note { grid-area: note; }
.pi:not(.pi-cat) > .pi-src { grid-area: src; }
.pi:not(.pi-cat) > .pi-tree { grid-area: mat; justify-self: start; margin-top: 5px; }
/* An unmatched name has no icon to line up with, so it drops the gutter
 * instead of indenting into empty space. */
.pi-free:not(.pi-cat) {
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "zh" "note" "src" "mat";
}
.pi-note, .pi-src { margin: 0; font-size: 11px; line-height: 1.45; }
.pi-tree { margin: 0; }
.pi-tree > summary {
  cursor: pointer; list-style: none; font-size: 11px; color: var(--accent);
  padding: 3px 9px; min-height: 30px; white-space: nowrap;
  display: inline-flex; align-items: center;
  border: 1px solid var(--line); border-radius: 999px; background: var(--bg-card);
}
.pi-tree > summary:hover { border-color: var(--accent); }
.pi-tree > summary::-webkit-details-marker { display: none; }
.pi-tree > summary::before { content: "▸ "; }
.pi-tree[open] > summary { border-color: var(--accent); }
.pi-tree[open] > summary::before { content: "▾ "; }
.pi-tree > .mt { margin-top: 4px; }
.mt { list-style: none; margin: 4px 0 0; padding: 0 0 0 8px;
      border-left: 1px solid var(--line); }
.mt li { padding: 1px 0; }
.mt span { font-size: 12px; }
.mt-det > summary { cursor: pointer; display: flex; align-items: center;
                    gap: 4px; list-style: none; }
.mt-det > summary::-webkit-details-marker { display: none; }
.mt-det > summary::before { content: "▸"; color: var(--fg-faint); }
.mt-det[open] > summary::before { content: "▾"; }
.mt-at { font-size: 11px; color: var(--fg-faint); margin-left: 5px; }
.mt-src { font-size: 11px; color: var(--green); margin-left: 5px; }
.pa { display: grid; gap: 6px; margin-bottom: 10px; padding-bottom: 10px;
      border-bottom: 1px dashed var(--line); }
.pa:last-of-type { border-bottom: 0; margin-bottom: 0; padding-bottom: 0; }
.pa-slot { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.pa-l { font-size: 11px; color: var(--fg-faint); width: 30px; flex: none; }
.pa .pi-tree { margin-left: 35px; flex-basis: 100%; }
/* The Wall of Flesh column, and the two section breaks around it. */
.fg-tag-quest { border-color: var(--accent); color: var(--accent); }
.fg-tag-junk { opacity: .75; }
.fg-row-enemy .fg-name { color: var(--red); }
.fg-detail { margin-top: 6px; }
.fg-detail > summary { cursor: pointer; list-style: none; font-size: 11px; }
.fg-detail > summary::-webkit-details-marker { display: none; }
.fg-detail > summary::before { content: "▸ "; color: var(--fg-faint); }
.fg-detail[open] > summary::before { content: "▾ "; }

/* ---------------------------------------------------------------- 合成台 */

/* A self-contained column: it reads the same data the item popup does but lays
 * it out as one panel with three modes, so nothing here is shared with the item
 * detail styles - editing this block cannot change how the rest of the site
 * looks. */

.ck-pick { max-width: 900px; margin: 28px auto 40px; }
.ck-pick h1 { font-size: 22px; margin: 0 0 8px; }

.ck-pick input {
  width: 100%; font: inherit; font-size: 14px; padding: 10px 14px;
  margin: 14px 0 16px; border-radius: 8px; border: 1px solid var(--line);
  background: var(--bg-soft); color: var(--fg);
}
.ck-pick input:focus { outline: none; border-color: var(--accent); }

/* Every item, sixty to a page. auto-fill keeps the column count responsive
 * without changing how many items a page holds - the tile count is what makes
 * every page feel the same, not the row count. */
.ck-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
  gap: 8px;
}

.ck-cell {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 10px 5px 8px;
  border: 1px solid var(--line-soft); border-radius: 8px;
  background: var(--bg-card); color: var(--fg);
  font: inherit; font-size: 12px; cursor: pointer;
  min-width: 0;
}
.ck-cell:hover { border-color: var(--accent); color: var(--accent); }
.ck-cell .icon { width: 32px; height: 32px; flex-basis: 32px; }
.ck-cell span {
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.ck-page { max-width: 720px; margin: 0 auto 44px; }

.ck-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.ck-head .icon { width: 44px; height: 44px; flex-basis: 44px; }
.ck-title { flex: 1 1 auto; min-width: 0; }
.ck-title h1 { font-size: 20px; margin: 0; line-height: 1.3; }
.ck-title .note { margin: 2px 0 0; }

.ck-back, .ck-swap {
  min-height: 34px; padding: 0 12px;
  border: 1px solid var(--line); border-radius: 8px;
  background: none; color: var(--fg-dim);
  font: inherit; font-size: 13px; cursor: pointer;
}
.ck-back:hover, .ck-swap:hover { border-color: var(--accent); color: var(--accent); }

/* Three modes, drawn as one segmented control so it reads as "the same panel,
 * different question" rather than three separate buttons. */
.ck-modes {
  display: flex; gap: 4px; margin-bottom: 12px;
  background: var(--bg-soft); border: 1px solid var(--line);
  border-radius: 9px; padding: 4px;
}
.ck-mode {
  flex: 1 1 0; min-height: 34px; border: none; border-radius: 6px;
  background: none; color: var(--fg-dim);
  font: inherit; font-size: 14px; cursor: pointer;
  transition: background .12s, color .12s;
}
.ck-mode:hover { color: var(--fg); }
.ck-mode.on { background: var(--accent-soft); color: var(--accent); }

.ck-bar { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.ck-station {
  min-height: 32px; padding: 0 12px;
  border: 1px solid var(--line); border-radius: 16px;
  background: none; color: var(--fg-dim);
  font: inherit; font-size: 13px; cursor: pointer;
}
.ck-station:hover { border-color: var(--accent); color: var(--fg); }
.ck-station.on { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }

.ck-pager {
  display: flex; align-items: center; justify-content: center; gap: 14px;
  font-size: 13px; color: var(--fg-dim); margin-bottom: 12px;
}
.ck-pager button {
  min-width: 34px; min-height: 30px;
  border: 1px solid var(--line); border-radius: 7px;
  background: none; color: var(--fg-dim); font: inherit; cursor: pointer;
}
.ck-pager button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.ck-pager button:disabled { opacity: .35; cursor: default; }

.ck-body { display: flex; flex-direction: column; gap: 10px; }

/* One recipe: materials on the left, result on the right. Stacks vertically on
 * a phone instead of squeezing the names into two narrow columns. */
.ck-card {
  display: flex; align-items: center; gap: 14px;
  background: var(--bg-card); border: 1px solid var(--line-soft);
  border-radius: 10px; padding: 14px;
}
/* align-items: flex-start keeps each chip the width of its own content.
 * Stretching is the flex column default, and a single-material recipe then
 * draws one bar across the whole column, which reads as a title rather than a
 * chip. */
.ck-side {
  display: flex; flex-direction: column; align-items: flex-start;
  gap: 6px; flex: 1 1 0; min-width: 0;
}
.ck-arrow { color: var(--fg-faint); font-size: 17px; flex: 0 0 auto; }

.ck-mat {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 34px; padding: 3px 10px 3px 5px;
  border: 1px solid var(--line); border-radius: 8px;
  font-size: 13px; color: var(--fg); max-width: 100%;
}
.ck-mat[data-ck] { cursor: pointer; }
.ck-mat[data-ck]:hover { border-color: var(--accent); color: var(--accent); }
.ck-flat { border-style: dashed; color: var(--fg-dim); }
.ck-result { border-color: var(--accent); }
/* In 用途 every card is a full recipe; this marks the ingredient you arrived
 * from, so it stays findable among the others. */
.ck-here { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.ck-nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* "9 选 1" on a family chip: which specific item does not matter, but how many
 * choices there are does - 任意木材 reads very differently from "any of 9". */
.ck-alt { color: var(--fg-faint); font-size: 11px; flex: 0 0 auto; white-space: nowrap; }
.ck-qty { color: var(--fg-dim); font-size: 12px; flex: 0 0 auto; }
.ck-result .ck-qty { color: var(--accent); }

.ck-src {
  background: var(--bg-card); border: 1px solid var(--line-soft);
  border-radius: 10px; padding: 14px;
}
.ck-src[data-ck-npc] { cursor: pointer; }
.ck-src[data-ck-npc]:hover { border-color: var(--accent); }
.ck-src-h {
  display: flex; align-items: center; gap: 8px;
  font-size: 15px; font-weight: 600; margin-bottom: 4px;
}
.ck-src .note { margin: 0; }
.ck-where { margin: 0; font-size: 14px; line-height: 1.5; color: var(--fg); }
.ck-where.fish { color: var(--blue); }

/* ------------------------------------------------------- 合成台（灾厄）
 * 版式复用上面这一套（同一个模块就该长一个样），但可点标记是 data-cal-ck，
 * 所以这几条必须单独写：原版的 [data-ck] 选择器认不到它，反之亦然。
 * 两边的样式各管各的节点，改一边不会串到另一边。 */
.ck-mat[data-cal-ck] { cursor: pointer; }
.ck-mat[data-cal-ck]:hover { border-color: var(--accent); color: var(--accent); }
.ck-src[data-npc] { cursor: pointer; }
.ck-src[data-npc]:hover { border-color: var(--accent); }
/* 选物品格子里的灾厄图标要跟原版 .icon 一样大（32px），否则两种格子
 * 混在一页里高低不齐 */
.ck-cell .cal-ico { width: 32px; height: 32px; flex: 0 0 32px; }
.ck-cell .cal-glyph { font-size: 22px; width: 32px; text-align: center; }
/* 面板头部的大图标（原版 .ck-head .icon 是 44px，这边对齐） */
.cal-ico.lg { width: 44px; height: 44px; flex: 0 0 44px; }
.ck-head .cal-glyph.lg { font-size: 30px; width: 44px; text-align: center; }

/* 「灾厄改了这条配方」之后，原版那条还画出来，但要说清楚它已经不能用了：
 * 虚线边框 + 压暗 + 产物划掉，一眼能和上面那条能用的区分开。 */
.ck-card-dead {
  border-style: dashed;
  opacity: .62;
}
.ck-card-dead .ck-side-out .ck-nm { text-decoration: line-through; }
.ck-bad { color: var(--red, #e0645c); }

/* Materials stay on the left and the result on the right at every width - that
 * left-to-right reading is the point of the panel. A phone only gets tighter
 * spacing and smaller sprites; long material names truncate rather than pushing
 * the result off the edge. */
@media (max-width: 620px) {
  .ck-card { padding: 10px; gap: 8px; }
  .ck-mat { font-size: 12px; padding: 2px 8px 2px 4px; gap: 5px; }
  .ck-mat .icon { width: 24px; height: 24px; flex-basis: 24px; }
  .ck-arrow { font-size: 14px; }
  .ck-side { gap: 5px; }
  .ck-side-out { flex: 0 0 auto; max-width: 45%; }
  .ck-title h1 { font-size: 18px; }
  .ck-head .icon { width: 38px; height: 38px; flex-basis: 38px; }
}

/* ------------------------------------------------------------ 地图查看器 */

/* A single-purpose column: one external tool, explained. Nothing here is
 * shared with the item/section styles, so editing it cannot move anything else
 * on the site. */
.map-wrap { max-width: 760px; margin: 0 auto 48px; }

.map-hero {
  background: var(--bg-card);
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  padding: 22px 22px 20px;
}

.map-head {
  display: flex; align-items: baseline; gap: 10px;
  flex-wrap: wrap; margin-bottom: 8px;
}
.map-head h2 { margin: 0; font-size: 19px; }

.map-tag {
  padding: 2px 9px;
  border: 1px solid var(--line);
  border-radius: 11px;
  color: var(--fg-dim);
  font-size: 12px;
}

.map-desc { margin: 0 0 18px; font-size: 14px; line-height: 1.7; color: var(--fg-dim); }
/* 存档路径是长串，窄屏上得允许它从任意位置断开，否则会把整页撑宽 */
.map-desc code {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 12px;
  color: var(--fg);
  background: var(--bg-soft);
  padding: 1px 5px; border-radius: 4px;
  overflow-wrap: anywhere;
}

/* 内置查看器头部：选择按钮 + 拖拽提示，同一行排开，手机上自动换行 */
.map-frame-head {
  display: flex; align-items: center; gap: 12px;
  flex-wrap: wrap; margin: 0 0 12px;
}
.map-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 40px; padding: 0 18px;
  border-radius: 9px;
  background: var(--accent);
  color: #1a1c22;
  font-size: 14px; font-weight: 600;
  cursor: pointer;
  transition: background .12s;
}
.map-btn:hover { background: #f7b954; }

.map-block { margin-top: 22px; }
.map-block h3 { margin: 0 0 10px; font-size: 15px; color: var(--fg); }

.map-list { margin: 0; padding-left: 20px; }
.map-list li { margin: 0 0 7px; font-size: 14px; line-height: 1.65; color: var(--fg-dim); }
.map-list li::marker { color: var(--accent); }
.map-list-note li::marker { color: var(--fg-faint); }
.map-list-note li { font-size: 13px; }

@media (max-width: 620px) {
  .map-hero { padding: 18px 16px 16px; }
  /* 手机上让入口按钮占满整行：它现在既是入口也是唯一的操作 */
  .map-btn { width: 100%; justify-content: center; }
  .map-list li { font-size: 13px; }
}

/* -------------------------------------------------- 地图查看器：本地存档 */

.wld-drop {
  display: flex; align-items: center; justify-content: center;
  min-height: 96px; margin: 12px 0 0;
  border: 1px dashed var(--line); border-radius: 10px;
  background: var(--bg-soft);
  transition: border-color .12s, background .12s;
}
.wld-drop.on { border-color: var(--accent); background: var(--accent-soft); }
.wld-hint { margin: 0; font-size: 13px; color: var(--fg-dim); text-align: center; }
.wld-err { color: var(--red); }

.wld-view { margin-top: 12px; }

.wld-bar {
  display: flex; align-items: center; gap: 10px;
  flex-wrap: wrap; margin-bottom: 8px;
  font-size: 13px; color: var(--fg-dim);
}
.wld-bar > span:first-child { flex: 1 1 auto; min-width: 0; }

/* 地形 / 感染 两档切换，做成连体按钮，和右边的缩放按钮区分开 */
.wld-modes {
  display: flex; flex: 0 0 auto;
  border: 1px solid var(--line); border-radius: 7px; overflow: hidden;
}
.wld-modes button {
  min-height: 30px; padding: 0 12px;
  border: none; background: none; color: var(--fg-dim);
  font: inherit; font-size: 13px; cursor: pointer;
  transition: background .12s, color .12s;
}
.wld-modes button + button { border-left: 1px solid var(--line); }
.wld-modes button:hover { color: var(--accent); }
.wld-modes button.on { background: var(--accent); color: #1a1c22; font-weight: 600; }

.wld-zoom { display: flex; gap: 6px; flex: 0 0 auto; }
.wld-zoom button {
  min-width: 32px; min-height: 30px; padding: 0 10px;
  border: 1px solid var(--line); border-radius: 7px;
  background: none; color: var(--fg-dim);
  font: inherit; font-size: 13px; cursor: pointer;
}
.wld-zoom button:hover { border-color: var(--accent); color: var(--accent); }

.wld-legend {
  display: flex; flex-wrap: wrap; gap: 6px 14px;
  margin: 10px 0 0;
  font-size: 12px; color: var(--fg-dim);
}
.wld-lg { display: inline-flex; align-items: center; gap: 5px; }
.wld-lg i {
  width: 10px; height: 10px; border-radius: 2px;
  display: inline-block; flex: 0 0 auto;
}
/* 灾厄图例里的方块面积数：数字要淡一点，别抢了方块名的位置 */
.wld-modn { color: var(--fg-faint); font-size: 11px; font-variant-numeric: tabular-nums; }

.wld-stat {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  width: 100%; margin-top: 6px;
  padding-top: 8px; border-top: 1px solid var(--line-soft);
  font-size: 12px; font-variant-numeric: tabular-nums;
}
.wld-inf { font-weight: 600; }
.wld-sep { color: var(--fg-faint); }

#wld-canvas {
  display: block; width: 100%; height: 460px;
  border: 1px solid var(--line); border-radius: 10px;
  background: #12141a;
  cursor: grab;
  touch-action: none;
}
#wld-canvas:active { cursor: grabbing; }

.wld-read {
  margin: 8px 0 0; min-height: 20px;
  font-size: 13px; color: var(--fg);
  font-variant-numeric: tabular-nums;
}
.wld-note { margin: 8px 0 0; font-size: 12px; color: var(--fg-faint); line-height: 1.7; }

/* 全屏：原生 Fullscreen API 和 CSS 兜底走同一套 .fs。画布高度改由 flex 撑满，
 * 不然 JS 设的 inline height 会把视图钉在原来那点高。 */
.wld-view.fs {
  position: fixed; inset: 0; z-index: 900;
  display: flex; flex-direction: column;
  margin: 0;
  padding: 12px 14px 14px;
  /* 全屏时顶到屏幕边缘，刘海和手势条会盖住工具条，按安全区让开 */
  padding: max(12px, env(safe-area-inset-top))
           max(14px, env(safe-area-inset-right))
           max(14px, env(safe-area-inset-bottom))
           max(14px, env(safe-area-inset-left));
  background: #12141a;
  overflow: hidden;
}
.wld-view.fs #wld-canvas {
  flex: 1 1 auto;
  height: auto;
  min-height: 0;
}
.wld-view.fs .wld-bar,
.wld-view.fs .wld-legend,
.wld-view.fs .wld-read { flex: 0 0 auto; }
body.map-fs { overflow: hidden; }

@media (max-width: 620px) {
  #wld-canvas { height: 320px; }
  .wld-bar > span:first-child { width: 100%; }
}

/* ------------------------------------------------------------ 附属模组（灾厄）
 * 只有灾厄模式有这一栏：原版那边不显示按钮，避免点进去一个空页面。
 * 类名统一 ad- 前缀，跟事件卡的 ev-、攻略的 bg- 分开，互不覆盖。 */
body:not(.mod-calamity) nav button[data-tab="addons"] { display: none; }

/* 一个模组一张折叠卡：默认全收起，点标题展开，同时只开一个 ——
 * 模组一多全铺开会很长一段，找东西反而慢。 */
.ad-list { display: flex; flex-direction: column; gap: 10px; }
.ad-card { border: 1px solid var(--line); border-radius: 12px;
  background: var(--bg-soft); }
.ad-card[open] { border-color: var(--accent); }
.ad-sum { list-style: none; cursor: pointer; display: flex; align-items: baseline;
  gap: 10px; flex-wrap: wrap; padding: 12px 16px; }
.ad-sum::-webkit-details-marker { display: none; }
.ad-sum::after { content: "▾"; margin-left: auto; font-size: 12px;
  color: var(--fg-faint); }
.ad-card[open] .ad-sum::after { transform: rotate(180deg); }
.ad-sum-zh { font-size: 15px; font-weight: 600; }
.ad-sum-en { font-size: 11.5px; color: var(--fg-faint); }
.ad-sum-n { font-size: 11.5px; color: var(--accent); }
.ad-sum-a { font-size: 11.5px; color: var(--fg-faint); }
.ad-body { padding: 0 16px 16px; border-top: 1px dashed var(--line); }
.ad-body .ad-meta { margin-top: 12px; }
.ad-meta { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 8px;
  font-size: 12px; color: var(--fg-dim); }
.ad-meta a { color: var(--accent); text-decoration: none; }
.ad-meta a:hover { text-decoration: underline; }
.ad-desc { font-size: 13px; line-height: 1.85; color: var(--fg-dim); margin: 10px 0 0; }
.ad-feats { margin: 8px 0 0; padding-left: 18px; font-size: 12.5px;
  line-height: 1.85; color: var(--fg-dim); }

.ad-groups { display: flex; gap: 6px; flex-wrap: wrap; margin: 14px 0 4px; }
.ad-group { font-size: 12.5px; padding: 4px 12px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--bg-soft);
  color: var(--fg-dim); cursor: pointer; }
.ad-group.on { border-color: var(--accent); color: var(--accent);
  background: var(--accent-soft); }
.ad-group .ad-n { margin-left: 6px; font-size: 11px; color: var(--fg-faint);
  font-variant-numeric: tabular-nums; }
.ad-group.on .ad-n { color: var(--accent); }

.ad-sec { margin-top: 18px; }
.ad-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(172px, 1fr));
  gap: 8px; margin-top: 10px; }
.ad-cell { display: flex; align-items: center; gap: 8px; padding: 6px 8px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--bg);
  cursor: pointer; text-align: left; color: inherit; font: inherit; }
.ad-cell:hover { border-color: var(--accent); }
/* 名字允许折行：「陨石光鞭」这种四字名，加上「旧版」标和伤害数字后，
 * 单行放不下会被省略号截掉，看着像名字缺了一半。 */
.ad-cell .nm { font-size: 12.5px; line-height: 1.3; min-width: 0;
  overflow: hidden; white-space: normal; word-break: break-word; }
.ad-cell .nm .en { display: block; font-size: 10.5px; color: var(--fg-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ad-cell .dmg { margin-left: auto; font-size: 11px; color: var(--fg-dim);
  font-variant-numeric: tabular-nums; }

/* 详情弹窗不另写样式：头部、属性表、配方卡、掉落卡全部复用灾厄物品详情那套
 * .modal-head / .stats / .recipe / .drop，两处看起来才是同一个模子。
 * 只有「配方组」的成员列表需要一个换行容器。 */
.ad-members { display: flex; flex-wrap: wrap; gap: 8px; }
/* 旧版物品的小标：模组当前版本已经没有这件，别让人以为还能做 */
.ad-legacy { flex: 0 0 auto; font-size: 10px; padding: 1px 5px; border-radius: 4px;
  border: 1px solid var(--line); color: var(--fg-faint); }
/* 配方组成员没有「数量」这一说，空的 qty 别撑出一段空隙 */
.ing .qty:empty { display: none; }
/* 索琳书架的「获取提示」：wiki 里是用粉色小字写的一句谜面，这里改成斜体弱化，
 * 让下面真正的「获取方式」更突出 */
.ad-hint { font-style: italic; color: var(--fg-faint); }
/* 书里的正文：用引用块样式，跟属性、获取方式这些说明文字区分开 */
.ad-quote { padding-left: 12px; border-left: 2px solid var(--line);
  font-style: normal; color: var(--fg-dim); }
/* 摸彩袋「内容」里的掉落概率，跟数量分开摆 */
.ad-rate { margin-left: auto; font-size: 11px; color: var(--fg-faint); }
/* 场景（索琳营地 / 永冻堡垒 / 永恒花园 / 流光长阶）：图是横幅，占满整行；
 * 详情顶上也铺一张，别塞进 44px 的图标位里 */
.ad-cell-wide { grid-column: 1 / -1; flex-direction: column; align-items: stretch; gap: 6px; }
.ad-cell-wide .cal-ico { width: 100%; height: 72px; object-fit: cover;
  image-rendering: auto; border-radius: 5px; }
.ad-cell-wide .cal-glyph { width: 100%; height: 72px; font-size: 26px;
  display: flex; align-items: center; justify-content: center; }
.ad-scene { margin: 0 0 14px; border-radius: 8px; overflow: hidden;
  border: 1px solid var(--line); background: var(--bg-soft, rgba(0,0,0,.15)); }
.ad-scene img { display: block; width: 100%; height: auto; }
/* 主线指南：按进度分成几个阶段，每段一列步骤 */
.ad-stage { margin: 0 0 14px; }
.ad-stage:last-child { margin-bottom: 0; }
.ad-stage h4 { margin: 0 0 6px; font-size: 12.5px; font-weight: 600;
  color: var(--accent); letter-spacing: .02em; }
.ad-stage ol { margin: 0; padding-left: 20px; }
.ad-stage li { margin: 5px 0; font-size: 13px; line-height: 1.75; color: var(--fg-dim); }
.ad-stage li::marker { color: var(--fg-faint); }
