/* ============================================================
   V客网站导航 · 前台样式
   设计参考：蓝凌增值应用（左侧分类 + 彩色渐变 banner 卡片网格）
   响应式：手机(≤640) / 平板(641~1024) / 桌面(≥1025)

   规范（所有页面必须沿用，不要再另起一套）：
   · 圆角   --radius(16) / 14 / 10
   · 阴影   --shadow / --shadow-hover
   · 过渡   统一用 --dur / --dur-fast + --ease / --ease-out
   · 焦点   键盘可达元素统一 :focus-visible → --ring
   ============================================================ */

/* hidden 属性必须真的把它藏住。
   ⛔ 别删这条：作者样式里的 display（如 .brand-mark{display:flex}）会盖掉浏览器
      默认的 [hidden]{display:none}，一旦被盖掉，「图片兜底」那几个 <span hidden>
      就会和图片一起显示出来。图片加载全挂时由 site.js 摘掉 hidden 揭示它们。 */
[hidden] { display: none !important; }

:root {
  --bg: #f4f6fb;
  --panel: #ffffff;
  --ink: #1f2533;
  --ink-2: #5b6577;
  --ink-3: #9aa3b2;
  --line: #eef1f6;
  --line-2: #e3e8f0;
  --brand: #2d8cf0;
  --brand-2: #5b8def;
  --g1: #2d8cf0;
  --g2: #9b6bff;
  --radius: 16px;
  --glass: rgba(255, 255, 255, .72);
  --shadow: 0 6px 22px rgba(31, 37, 51, .07);
  --shadow-sm: 0 3px 12px rgba(31, 37, 51, .06);
  --shadow-hover: 0 14px 34px rgba(45, 140, 240, .20);
  --ring: 0 0 0 3px rgba(45, 140, 240, .18);
  --dur-fast: .14s;
  --dur: .22s;
  --ease: cubic-bezier(.4, 0, .2, 1);
  --ease-out: cubic-bezier(.22, .61, .36, 1);
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

html, body {
  margin: 0;
  padding: 0;
  max-width: 100%;
  background: var(--bg);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Microsoft YaHei", "PingFang SC", sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* ---------------------------------------------------------------
   防横向溢出（移动端左右滑动的根因）—— 必须用 overflow-x: clip
   而不是 hidden：
     hidden 会把 html / body 变成「滚动容器」，于是 position: sticky
     的参照物从「视口」变成「body 的滚动区」，而 body 自己从不滚动
     → 左侧分类栏、顶栏、页脚全部粘不住（看起来就是「优化没生效」）。
     clip 只做裁剪、不建立滚动容器，横向不溢出与 sticky 可以同时成立。
   --------------------------------------------------------------- */
html, body { overflow-x: clip; }
/* 老浏览器不支持 clip 时兜底：宁可放弃 sticky，也不能整页左右滑动 */
@supports not (overflow: clip) {
  html { overflow-x: hidden; }
}

/* ---------------------------------------------------------------
   页脚贴底（数据量少时页脚「浮在半空」的根因就在这）
   ⛔ 只给 .footer 写 position:sticky; bottom:0 是不够的 ——
      sticky 只在元素「本应被推到视口之外」时才产生粘附位移。
      数据多、页面能滚动时它看着没问题；一旦数据少到撑不满一屏
      （筛选后只剩几条、空结果、手机端单列），页脚就停在**内容结尾**
      处，下面露出一整块背景色，看起来就是「底部位置不对」。
   正解：body 设为纵向 flex 容器 + min-height 占满一屏，
      .layout 用 flex:1 吃掉剩余空间 —— 内容不足时页脚被顶到视口底部，
      内容超出时 .layout 按内容撑高、页脚回到正常流末尾（原有的
      sticky 粘底行为继续负责滚动过程中的贴底）。
   --------------------------------------------------------------- */
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
/* 移动端地址栏收起 / 展开时视口高度会变，dvh 跟随可视高度，
   避免页脚在 iOS Safari 上被 100vh 顶到视口外（多出一小截滚动）。 */
@supports (min-height: 100dvh) {
  body { min-height: 100dvh; }
}
/* sticky 元素不能是 flex 的收缩项，否则内容超长时会被压扁 */
.topbar, .footer { flex: none; }

a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }
button { font-family: inherit; }

/* 键盘可达元素的统一焦点环（鼠标点击不会出现，只有 Tab 才显示） */
.card:focus-visible,
.cat-item:focus-visible,
.hot-card:focus-visible,
.admin-link:focus-visible,
.pg-btn:focus-visible,
.empty-reset:focus-visible,
.to-top:focus-visible {
  outline: none;
  box-shadow: var(--ring);
}

/* SVG 图标统一样式 */
.ico {
  width: 1em; height: 1em; flex: none;
  display: inline-block; vertical-align: -0.15em;
  fill: currentColor;
}
.ico-fire { color: #ff7a45; font-size: 18px; }

/* ---------------- 磨砂玻璃 ---------------- */
.glass {
  background: var(--glass);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  backdrop-filter: saturate(180%) blur(14px);
}

/* ---------------- 顶部栏 ---------------- */
.topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  background: rgba(255, 255, 255, .92);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--line);
  transition: box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
/* 滚动后才给顶栏投影：静止时「贴住」内容，滚起来才有层次 */
.topbar.is-scrolled {
  border-bottom-color: var(--line-2);
  box-shadow: 0 6px 22px rgba(31, 37, 51, .07);
}
.topbar-inner {
  position: relative;   /* 手机端搜索展开时以整条顶栏为定位容器（见下） */
  max-width: 1280px;
  margin: 0 auto;
  height: 62px;
  padding: 0 20px;
  display: flex;
  align-items: center;
  gap: 18px;
}
.brand { display: flex; align-items: center; gap: 12px; flex: none; min-width: 0; }
.brand-logo { height: 34px; width: auto; }
.brand-mark {
  width: 36px; height: 36px; border-radius: 10px;
  background: linear-gradient(135deg, var(--brand), var(--brand-2));
  color: #fff; font-weight: 800; font-size: 20px;
  display: flex; align-items: center; justify-content: center;
  flex: none;
  box-shadow: 0 4px 12px rgba(45, 140, 240, .28);
}
/* 品牌区的 logo / 名称 / 副标题：拉开一点行距与列距，避免三者糊成一团 */
.brand-text { display: flex; flex-direction: column; gap: 3px; line-height: 1.2; min-width: 0; }
.brand-text b { font-size: 17px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.brand-text i { font-style: normal; font-size: 12px; color: var(--ink-3); }

/* 搜索入口：默认收缩成一颗圆形图标按钮，靠左紧挨品牌；
   鼠标悬停 / 键盘聚焦 / 点了它（触屏没有 hover）/ 框里有内容时向右展开。
   展开宽度的过渡是「自然不突兀」的关键：宽度 + 背景 + 阴影同步过渡，
   不做淡入淡出的「闪一下」。 */
.searchbox {
  position: relative;
  flex: 0 0 auto;
  width: 42px;
  height: 42px;
  border-radius: 999px;
  background: #f4f7fc;
  border: 1px solid var(--line);
  overflow: hidden;
  cursor: pointer;
  transition: width var(--dur) var(--ease), background var(--dur) var(--ease),
              border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.searchbox:hover,
.searchbox:focus-within,
.searchbox.is-open,
.searchbox.has-value {
  width: 296px;
  background: #fff;
  border-color: rgba(45, 140, 240, .45);
  box-shadow: var(--ring);
  cursor: text;
}
.searchbox input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  outline: none;
  background: transparent;
  padding: 0 16px 0 42px;
  font-size: 14px;
  color: var(--ink);
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease);
}
.searchbox:hover input,
.searchbox:focus-within input,
.searchbox.is-open input,
.searchbox.has-value input { opacity: 1; }
.searchbox input::placeholder { color: var(--ink-3); }
.search-ico {
  position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
  width: 17px; height: 17px; color: var(--ink-3); pointer-events: none;
  transition: color var(--dur) var(--ease);
}
.searchbox:hover .search-ico,
.searchbox:focus-within .search-ico,
.searchbox.is-open .search-ico { color: var(--brand); }

/* ---------------- 视图切换（列表大图展示模式） ----------------
   三种模式：卡片（默认）/ 大图 / 列表。模式存在 <html data-view>：
     · 由 <head> 里那段内联脚本在读 localStorage 后**先于 body 渲染**打上，避免首屏闪一下再切；
     · 点按钮时 site.js 再改一次并回写 localStorage。
   ⛔ 只在 >640px 生效：手机端本来就有自己的两列紧凑布局，混进来只会打架。 */
.view-switch {
  flex: none;
  margin-left: auto;              /* 顶到最右（原由 .admin-link 承担，见下） */
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border-radius: 999px;
  background: #f4f7fc;
  border: 1px solid var(--line);
}
.vs-label { font-size: 12px; color: var(--ink-3); padding: 0 7px 0 6px; white-space: nowrap; }
.vs-btn {
  display: inline-flex; align-items: center; gap: 5px;
  min-height: 30px; padding: 4px 11px;
  border: 0; border-radius: 999px; background: transparent;
  font-family: inherit; font-size: 12.5px; color: var(--ink-2);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease);
}
.vs-btn svg { width: 14px; height: 14px; flex: none; }
.vs-btn:hover { color: var(--brand); background: rgba(45, 140, 240, .08); }
.vs-btn.is-on { background: #fff; color: var(--brand); font-weight: 600; box-shadow: 0 1px 4px rgba(31, 37, 51, .12); }
.vs-btn:focus-visible { outline: none; box-shadow: var(--ring); }

.admin-link {
  flex: none;
  margin-left: 10px;   /* 右侧让位给视图切换，由 .view-switch 的 auto 外边距顶到最右 */
  font-size: 13px;
  color: var(--brand);
  border: 1px solid rgba(45, 140, 240, .35);
  padding: 7px 14px;
  border-radius: 999px;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), transform var(--dur) var(--ease-out);
}
.admin-link:hover { background: rgba(45, 140, 240, .08); border-color: rgba(45, 140, 240, .6); transform: translateY(-1px); }
.admin-link:active { transform: translateY(0); }

.notice {
  max-width: 1280px;
  margin: 0 auto;
  padding: 8px 20px;
  font-size: 13px;
  color: #8a6d3b;
  background: linear-gradient(90deg, #fff7e6, #fffdf8);
  border-top: 1px solid #f6e6c2;
  display: flex; align-items: center; gap: 10px;
}
.notice-tag {
  flex: none;
  background: #ffb020; color: #fff; font-size: 11px;
  padding: 2px 8px; border-radius: 6px;
}

/* ---------------- 布局 ---------------- */
.layout {
  max-width: 1280px;
  /* ⛔ width:100% 不能删 —— 它是「首页缩成一条窄列」的解药。
     body 为了页脚贴底被设成了 flex column 容器（见文件上方注释），
     而 **flex 项的交叉轴 auto 外边距会抢走全部剩余空间**：
     align-items:stretch 因此失效（补 align-self:stretch 也没用，
     auto 外边距优先），.layout 退化成 fit-content —— 宽度由「内容最宽处」
     决定，再被 margin:auto 居中。实测 1635px 视口里 .layout 只有 729px、
     1635→ 侧栏 220 + 内容 447，整个首页看着像被挤在中间一条。
     显式写 width:100% 后：宽度以百分比定义（不再依赖 stretch），
     仍被 max-width:1280 夹住，margin:auto 只负责居中。 */
  width: 100%;
  margin: 22px auto;
  padding: 0 20px;
  display: grid;
  /* ⛔ 每一条轨道都必须写 minmax(0, …)，不能只写 1fr。
     1fr 的隐式最小尺寸是 auto（= 内容最小宽度），左侧分类横滑条里的
     .cat-item 是 white-space:nowrap，几千像素的「最小内容宽度」会被算进去，
     整条轨道被撑到 900+px —— 页面右侧内容被 overflow-x:clip 裁掉，
     而因为不出现滚动条，看起来「没毛病」。
     手机端实测：不加 minmax(0,…) 时 .sidebar 宽 969px、卡片被裁一半。 */
  grid-template-columns: 220px minmax(0, 1fr);
  gap: 22px;
  align-items: start;
  /* 吃掉 body(flex column) 里除顶栏/页脚之外的全部剩余高度：
     数据不足一屏时把页脚顶到视口底部；数据超一屏时 flex-basis:auto 让它
     按内容自然撑高（0 的收缩系数保证不会被压扁）。 */
  flex: 1 0 auto;
}

/* ---------------- 左侧分类（悬浮 + 磨砂玻璃，固定不随滚动） ---------------- */
.sidebar {
  position: sticky;
  top: 84px;
  border-radius: var(--radius);
  box-shadow: 0 8px 30px rgba(31, 37, 51, .10);
  border: 1px solid rgba(255, 255, 255, .6);
  padding: 14px 10px;
  max-height: calc(100vh - 110px);
  overflow-y: auto;
  overflow-x: hidden;
}
.sidebar::-webkit-scrollbar { width: 6px; }
.sidebar::-webkit-scrollbar-thumb { background: #dbe2ec; border-radius: 999px; }
.side-title {
  font-size: 13px; color: var(--ink-3); font-weight: 600;
  padding: 4px 12px 10px;
  display: flex; align-items: center; gap: 7px;
}
.side-title .ico { font-size: 15px; }
.cat-nav { list-style: none; margin: 0; padding: 0; }
.cat-group { margin-bottom: 4px; }
.cat-item {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px;
  padding: 9px 12px;
  border-radius: 10px;
  font-size: 14px;
  color: var(--ink-2);
  cursor: pointer;
  position: relative;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease),
              box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease-out);
}
.cat-name { display: flex; align-items: center; gap: 7px; min-width: 0; }
.cat-name .ico { font-size: 15px; }
.cat-item:hover { background: rgba(45, 140, 240, .09); color: var(--brand); transform: translateX(2px); }
.cat-item:active { transform: translateX(2px) scale(.985); }
.cat-item.is-active {
  background: linear-gradient(135deg, var(--brand), var(--brand-2));
  color: #fff; font-weight: 600;
  box-shadow: 0 6px 16px rgba(45, 140, 240, .32);
  transform: none;
}
.cat-root { font-weight: 600; color: var(--ink); }
.cat-root.is-active { color: #fff; }
.cat-count {
  font-size: 12px; color: var(--ink-3);
  background: rgba(148, 163, 184, .16); border-radius: 999px; padding: 1px 8px; flex: none;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.cat-item.is-active .cat-count { background: rgba(255, 255, 255, .25); color: #fff; }
/* 二级分类：用虚线导轨交代层级，比单纯缩进更清晰 */
.cat-sub {
  list-style: none; margin: 2px 0 2px 15px; padding: 0 0 0 9px;
  border-left: 1px dashed rgba(148, 163, 184, .38);
}
.cat-sub .cat-item { font-size: 13px; padding: 7px 12px; }

/* ---------------- 主内容 ---------------- */
.content { min-width: 0; }

/* Banner（渐变 / 轮播） */
.banner {
  border-radius: var(--radius);
  color: #fff;
  background: linear-gradient(120deg, var(--g1, #2d8cf0) 0%, var(--g2, #9b6bff) 100%);
  box-shadow: var(--shadow);
  margin-bottom: 22px;
  position: relative;
  overflow: hidden;
  min-height: 190px;
}
.banner::after {
  content: ""; position: absolute; right: -60px; top: -60px; z-index: 1;
  width: 220px; height: 220px; border-radius: 50%;
  background: rgba(255, 255, 255, .12);
}
.banner::before {
  content: ""; position: absolute; right: 90px; bottom: -80px; z-index: 1;
  width: 160px; height: 160px; border-radius: 50%;
  background: rgba(255, 255, 255, .10);
}
.banner-track {
  position: absolute; inset: 0; z-index: 0;
  display: flex;
  transition: transform .6s cubic-bezier(.4, 0, .2, 1);
  will-change: transform;
}
.banner-slide { flex: 0 0 100%; height: 100%; }
.banner-slide img { width: 100%; height: 100%; object-fit: cover; }
.banner-shade {
  position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(90deg, rgba(12, 20, 38, .62) 0%, rgba(12, 20, 38, .28) 55%, rgba(12, 20, 38, 0) 100%);
}
.banner-inner { position: relative; z-index: 2; padding: 34px 32px; }
.banner h1 {
  margin: 0 0 8px; font-size: 28px; font-weight: 800; letter-spacing: .5px;
  text-shadow: 0 2px 12px rgba(12, 20, 38, .18);
}
/* 分类名之后跟随的「数量」角标：随 h1 字号等比缩放（em 单位），玻璃质感小药丸，
   与分类区块标题那枚「N 个」药丸视觉一致；vertical-align:middle 让它与名称垂直居中，不再跟文字挤在一起。 */
.banner h1 .banner-count {
  display: inline-flex; align-items: center; vertical-align: middle;
  margin-left: .34em;
  font-size: .46em; font-weight: 600; letter-spacing: 0; line-height: 1.5;
  color: #fff;
  background: rgba(255, 255, 255, .20);
  border: 1px solid rgba(255, 255, 255, .34);
  border-radius: 999px;
  padding: 0 .66em;
  text-shadow: none;
}
.banner h1 .banner-count[hidden] { display: none; }
.banner p { margin: 0; font-size: 14px; opacity: .94; max-width: 70ch; }
.banner-dots {
  position: absolute; z-index: 3; right: 22px; bottom: 16px;
  display: flex; align-items: center; gap: 8px;
}
.banner-dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: rgba(255, 255, 255, .5); cursor: pointer;
  transition: width var(--dur) var(--ease), background var(--dur) var(--ease);
}
.banner-dot:hover { background: rgba(255, 255, 255, .8); }
.banner-dot.is-on { width: 24px; border-radius: 999px; background: #fff; }
/* 只有 0/1 张轮播图时不显示圆点（JS 也会兜底隐藏，这里保证首屏不闪） */
.banner-dots[data-count="1"], .banner-dots[data-count="0"] { display: none; }

/* 热门推荐横滑 */
.hot-strip { margin-bottom: 22px; }
.strip-head {
  font-size: 16px; font-weight: 700; margin-bottom: 12px;
  display: flex; align-items: center; gap: 7px;
}
.hot-scroll {
  display: flex; gap: 12px; overflow-x: auto; overflow-y: hidden;
  padding: 2px 2px 8px;
  scrollbar-width: thin;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
}
.hot-scroll::-webkit-scrollbar { height: 6px; }
.hot-scroll::-webkit-scrollbar-thumb { background: #d7deea; border-radius: 999px; }
.hot-scroll::-webkit-scrollbar-thumb:hover { background: #c2cddd; }
.hot-card {
  flex: 0 0 auto;
  width: 132px;
  background: var(--panel);
  border-radius: 14px;
  padding: 18px 12px 16px;
  text-align: center;
  box-shadow: var(--shadow);
  border: 1px solid transparent;
  scroll-snap-align: start;
  transition: transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.hot-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 14px 30px rgba(45, 140, 240, .18);
  border-color: rgba(45, 140, 240, .2);
}
.hot-card:active { transform: translateY(-1px); }
.hot-ico, .hot-ico-img {
  width: 46px; height: 46px; border-radius: 12px; margin: 0 auto 12px;
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; color: #fff; font-size: 20px; object-fit: cover;
  background: linear-gradient(135deg, var(--c1, #2d8cf0), var(--c2, #5b8def));
  transition: transform var(--dur) var(--ease-out);
}
.hot-card:hover .hot-ico, .hot-card:hover .hot-ico-img { transform: scale(1.06); }
.hot-card b { display: block; font-size: 14px; margin-bottom: 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hot-card i { font-style: normal; font-size: 11px; color: var(--ink-3); display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* 分类区块 */
.cat-section { margin-bottom: 26px; }
.section-head {
  display: flex; align-items: center; gap: 10px; margin: 4px 2px 14px;
  position: relative; padding-left: 12px;
}
.section-head::before {
  content: ""; position: absolute; left: 0; top: 3px; bottom: 3px; width: 4px; border-radius: 4px;
  background: linear-gradient(180deg, var(--brand), var(--brand-2));
}
.section-head h2 { margin: 0; font-size: 19px; letter-spacing: .2px; }
.section-sub { font-size: 13px; color: var(--ink-3); }
.section-count {
  font-size: 12px; color: var(--ink-3); margin-left: auto;
  background: rgba(148, 163, 184, .13); border-radius: 999px; padding: 2px 10px;
  white-space: nowrap;
}
.section-count b { color: var(--ink-2); font-weight: 700; }

/* 分类区块的「加载更多 / 收起」：
   「全部网站」下每个分类只铺开「每页条数」张，余量靠这里逐个展开。
   做成一条细分隔线 + 居中按钮，视觉上不抢卡片，但一眼能看出还有内容。 */
.sec-more {
  margin-top: 14px;
  display: flex; align-items: center; justify-content: center; gap: 10px;
}
.sec-more[hidden] { display: none; }
.sec-more-btn {
  border: 1px solid var(--line);
  background: #fff;
  color: var(--ink-2);
  font-size: 13px; font-weight: 600;
  padding: 7px 20px;
  border-radius: 999px;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease),
              background var(--dur-fast) var(--ease), transform var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease);
}
.sec-more-btn:hover {
  color: var(--brand);
  border-color: rgba(45, 140, 240, .5);
  background: #f4f8ff;
  transform: translateY(-1px);
  box-shadow: 0 6px 16px rgba(45, 140, 240, .14);
}
.sec-more-btn:active { transform: translateY(0) scale(.97); }
.sec-more-btn:focus-visible { outline: none; box-shadow: var(--ring); }
.sec-more-hint { font-size: 12px; color: var(--ink-3); }

/* 卡片网格 */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 16px;
}
.card {
  background: var(--panel);
  border-radius: var(--radius);
  padding: 16px 16px 15px;
  display: flex;
  gap: 15px;               /* logo 与右侧文字之间留出呼吸感 */
  align-items: flex-start;
  box-shadow: var(--shadow);
  border: 1px solid transparent;
  position: relative;
  overflow: hidden;
  transition: transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
/* 左侧主题色竖条：卡片之间靠它区分「属于哪个色系」 */
.card::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  background: linear-gradient(180deg, var(--c1, var(--brand)), var(--c2, var(--brand-2)));
  opacity: .95;
  transition: width var(--dur) var(--ease);
}
.card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-hover);
  border-color: rgba(45, 140, 240, .22);
}
.card:hover::before { width: 5px; }
.card:active { transform: translateY(-1px) scale(.995); }
.card.is-top { border-color: rgba(255, 176, 32, .45); }
/* 「置顶」是右上角的绝对定位角标（top:0;right:0）。给标题行右侧留出角标宽度，
   保证「推荐 / 标签」永远落在角标左边，不会被它压住（窄卡片上尤其明显）。
   宽卡片上标题本就有富余空间，这条不产生任何视觉位移。 */
.card.is-top .card-title { padding-right: 44px; }
.card-top-flag {
  position: absolute; top: 0; right: 0; z-index: 2;
  font-size: 11px; color: #fff; font-weight: 600;
  background: linear-gradient(135deg, #ff9a3d, #ff7a45);
  padding: 2px 10px 2px 12px; border-bottom-left-radius: 10px;
}

.card-ico {
  flex: none; width: 46px; height: 46px; border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, var(--c1, #2d8cf0), var(--c2, #5b8def));
  color: #fff; font-weight: 700; font-size: 20px;
  overflow: hidden;
  transition: transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease);
}
.card:hover .card-ico { transform: scale(1.06); box-shadow: 0 6px 16px rgba(31, 37, 51, .16); }
.card-ico img { width: 100%; height: 100%; object-fit: cover; }
.card-cover { border-radius: 0; }
/* 列表大图：卡片顶部的封面横幅。默认 display:none —— 只有「大图」视图才放它出来，
   所以卡片/列表视图完全不受影响（多出来的这个空元素不占位、不参与布局）。 */
.card-banner { display: none; }
.card-initial { font-size: 20px; }

.card-body { min-width: 0; flex: 1; }
.card-title { display: flex; align-items: center; gap: 8px; min-width: 0; }
.card-title b {
  font-size: 15px; font-weight: 650; letter-spacing: .2px;
  min-width: 0;            /* ⛔ 允许标题收缩（否则窄卡片上会把 .tag 挤出，撞上右上角「置顶」角标） */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: color var(--dur) var(--ease);
}
.card:hover .card-title b { color: var(--c1, var(--brand)); }
.card-desc {
  margin: 9px 0 0; font-size: 12.5px; color: var(--ink-2); line-height: 1.55;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  min-height: 39px;
}
.card-foot {
  margin-top: 12px; padding-top: 10px;
  border-top: 1px dashed var(--line);
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
.card-host {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; color: var(--ink-3);
  min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.card-host .ico { font-size: 12px; }
.card-click { font-size: 11.5px; color: var(--brand); flex: none; font-weight: 600; }

.tag {
  flex: none; font-size: 11px; font-style: normal; padding: 1px 7px; border-radius: 6px;
  background: #eef2f8; color: var(--ink-2);
}
.tag-success { background: #e6f7ed; color: #1aa260; }
.tag-warning { background: #fff3e0; color: #e08a00; }
.tag-danger  { background: #fdeaea; color: #e23d3d; }
.tag-primary { background: #e7f0ff; color: #2d8cf0; }
.tag-info    { background: #eef2f8; color: #5b6577; }

/* 主题色兜底映射（前台一般由卡片 inline style 直接给出 --c1/--c2） */
.theme-blue   { --c1:#2d8cf0; --c2:#5b8def; }
.theme-violet { --c1:#7c5cff; --c2:#a06bff; }
.theme-teal   { --c1:#16c2c2; --c2:#22d3b0; }
.theme-orange { --c1:#ff9a3d; --c2:#ff7a45; }
.theme-green  { --c1:#36c26b; --c2:#5fd08a; }
.theme-red    { --c1:#ff5b6e; --c2:#ff7d8a; }
.theme-gold   { --c1:#f0b429; --c2:#f5c94e; }
.theme-cyan   { --c1:#22b8cf; --c2:#3bc9db; }
.theme-pink   { --c1:#f06595; --c2:#faa2c1; }
.theme-indigo { --c1:#5c7cfa; --c2:#748ffc; }
.theme-slate  { --c1:#495057; --c2:#868e96; }
.theme-amber  { --c1:#f59f00; --c2:#ffd43b; }
.theme-rose   { --c1:#f03e3e; --c2:#ff8787; }
.theme-sky    { --c1:#339af0; --c2:#66d9e8; }
/* 2026-10-09 扩充（与 HomeController.ThemeMap / admin themePresets.js 同源） */
.theme-mint     { --c1:#2bc4a0; --c2:#4ee0b8; }
.theme-lime     { --c1:#82c91e; --c2:#a9e34b; }
.theme-coral    { --c1:#ff7f50; --c2:#ff9d7a; }
.theme-navy     { --c1:#2b4c8c; --c2:#3f6bb5; }
.theme-plum     { --c1:#8e44ad; --c2:#b06fd0; }
.theme-sand     { --c1:#d9a441; --c2:#eac26e; }
.theme-steel    { --c1:#5a7d9a; --c2:#86a7c0; }
.theme-cherry   { --c1:#e03131; --c2:#ff6b6b; }
.theme-forest   { --c1:#2f9e44; --c2:#51cf66; }
.theme-lavender { --c1:#9775fa; --c2:#b197fc; }

/* ---------------- 空状态 ---------------- */
.empty-tip {
  display: flex; flex-direction: column; align-items: center;
  text-align: center; padding: 52px 20px 46px;
  color: var(--ink-3);
  background: var(--panel);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}
.empty-tip[hidden] { display: none; }
.empty-ico { width: 52px; height: 52px; color: #c9d2de; margin-bottom: 10px; }
.empty-title { margin: 0; font-size: 15px; font-weight: 650; color: var(--ink-2); }
.empty-tip2 { margin: 5px 0 0; font-size: 13px; }
.empty-reset {
  margin-top: 16px;
  border: 1px solid rgba(45, 140, 240, .35);
  background: #fff; color: var(--brand);
  padding: 8px 20px; border-radius: 999px; font-size: 13px; cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), transform var(--dur) var(--ease-out);
}
.empty-reset:hover { background: rgba(45, 140, 240, .07); border-color: rgba(45, 140, 240, .6); transform: translateY(-1px); }
.empty-reset:active { transform: translateY(0); }

/* ---------------- 分页 ---------------- */
.pager-wrap {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px 16px; flex-wrap: wrap;
  margin: 20px 0 34px;
  padding: 12px 16px;
  background: var(--panel);
  border-radius: 14px;
  box-shadow: var(--shadow-sm);
}
.pager-wrap[hidden] { display: none; }
/* 分组模式（「全部网站」）：没有「全局第几页」，只保留每页条数选择 ——
   它在这里的含义是「每个分类铺开多少张」。 */
.pager-wrap.is-group .pager-main { display: none; }
.pager-wrap.is-group { justify-content: center; }
.pager-info { font-size: 13px; color: var(--ink-3); }
.pager-info b { color: var(--ink); font-weight: 700; font-variant-numeric: tabular-nums; }
.pager-main { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.pg-btn {
  min-width: 34px; height: 34px; padding: 0 10px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: #fff;
  color: var(--ink-2);
  font-size: 13.5px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease), transform var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease);
}
.pg-btn:hover:not(:disabled):not(.is-on) {
  border-color: rgba(45, 140, 240, .5);
  color: var(--brand);
  background: #f4f8ff;
  transform: translateY(-1px);
}
.pg-btn:active:not(:disabled) { transform: translateY(0) scale(.95); }
.pg-btn:disabled { opacity: .42; cursor: not-allowed; }
.pg-num.is-on {
  background: linear-gradient(135deg, var(--brand), var(--brand-2));
  border-color: transparent; color: #fff;
  box-shadow: 0 6px 14px rgba(45, 140, 240, .3);
  cursor: default;
}
.pg-icon { padding: 0; }
.pg-icon svg { width: 16px; height: 16px; }
.pg-gap { padding: 0 2px; color: var(--ink-3); user-select: none; }
.pager-size { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--ink-3); }
.pager-size select {
  height: 34px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background-color: #fff;
  color: var(--ink);
  font-size: 13px;
  padding: 0 28px 0 10px;
  outline: none;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239aa3b2' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 8px center;
  background-size: 14px 14px;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.pager-size select:hover { border-color: var(--line-2); }
.pager-size select:focus { border-color: var(--brand); box-shadow: var(--ring); }

/* ---------------- 回到顶部 ---------------- */
.to-top {
  position: fixed; right: 22px; bottom: 76px; z-index: 40;
  width: 42px; height: 42px; border-radius: 14px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, .92);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: var(--ink-2);
  cursor: pointer;
  box-shadow: 0 8px 22px rgba(31, 37, 51, .13);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease-out),
              color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.to-top[hidden] { display: none; }
.to-top:hover { color: var(--brand); border-color: rgba(45, 140, 240, .45); transform: translateY(-2px); }
.to-top:active { transform: translateY(0) scale(.94); }
.to-top svg { width: 18px; height: 18px; }

/* ---------------- 页脚（常驻底部 + 磨砂玻璃） ----------------
   两层保障：
   ① body(flex column) + .layout(flex:1)  → 内容不足一屏时页脚也被顶到视口底部（见文件上方注释）；
   ② position:sticky + bottom:0          → 内容超过一屏、页面滚动时页脚粘在视口底部。
   margin-top 只负责页脚与内容之间的最小呼吸间距，不再承担「推到底部」的职责。 */
.footer {
  position: sticky;
  bottom: 0;
  z-index: 25;
  margin-top: 10px;
  border-top: 1px solid var(--line);
}
.footer-inner {
  max-width: 1280px; margin: 0 auto; padding: 16px 20px;
  display: flex; flex-wrap: wrap; gap: 6px 20px; align-items: center; justify-content: center;
  font-size: 12px; color: var(--ink-3);
}
.foot-item { white-space: nowrap; }
.foot-copy { color: var(--ink-2); font-weight: 600; }
.foot-icp { color: var(--ink-3); }

/* ---------------- 首屏入场（JS 加上 .vk-ready 后才生效） ----------------
   放在 JS 里加类，是为了「JS 没跑起来时内容照常可见」——绝不把内容默认设成透明。 */
@keyframes vkIn {
  from { opacity: 0; transform: translateY(9px); }
  to   { opacity: 1; transform: none; }
}
html.vk-ready .cat-section { animation: vkIn .34s var(--ease-out) both; }
html.vk-ready .card { animation: vkIn .34s var(--ease-out) both; }
html.vk-ready .hot-card { animation: vkIn .34s var(--ease-out) both; }

/* ---------------- 移动端底部吸底导航栏（≤640 才显示，桌面/平板隐藏） ---------------- */
.m-tabbar { display: none; }

/* ---------------- 列表视图模式（卡片 / 大图 / 列表） ----------------
   模式由 <html data-view="card|cover|list"> 决定（默认 card，即老样子）。
   ⛔ 整块只在 >640px 生效：手机端本来就有自己那套「两列紧凑 + 吸底导航」布局，
      让 data-view 插进来会出现两套规则互相打架（列数 / 内边距 / 图标尺寸全不一致）。
      所以手机上等于永远按「卡片」渲染，用户切过大图也不会把手机端弄乱。 */
@media (min-width: 641px) {

  /* —— 大图：封面横幅 + 左上角悬浮图标（没有封面就用主题渐变兜底） —— */
  html[data-view="cover"] .card-grid { grid-template-columns: repeat(auto-fill, minmax(258px, 1fr)); }
  html[data-view="cover"] .card { flex-direction: column; gap: 0; padding: 0; align-items: stretch; }
  /* 左侧竖色条改到顶部：竖条压在横图上不协调 */
  html[data-view="cover"] .card::before {
    left: 0; right: 0; top: 0; bottom: auto; width: auto; height: 4px;
    background: linear-gradient(90deg, var(--c1, var(--brand)), var(--c2, var(--brand-2)));
  }
  html[data-view="cover"] .card:hover::before { width: auto; height: 4px; }
  html[data-view="cover"] .card-banner {
    display: block; position: relative; width: 100%;
    aspect-ratio: 16 / 9; min-height: 118px; overflow: hidden;
    background: linear-gradient(135deg, var(--c1, #2d8cf0), var(--c2, #5b8def));
  }
  html[data-view="cover"] .card-banner img { width: 100%; height: 100%; object-fit: cover; }
  html[data-view="cover"] .card-ico {
    position: absolute; left: 14px; top: 14px; z-index: 2;
    width: 40px; height: 40px; border-radius: 11px; font-size: 17px;
    border: 2px solid rgba(255, 255, 255, .92);
    box-shadow: 0 4px 14px rgba(15, 20, 30, .22);
    transition: none;
  }
  html[data-view="cover"] .card:hover .card-ico { transform: none; box-shadow: 0 4px 14px rgba(15, 20, 30, .22); }
  /* 没设图标、只设了封面的站点：图标格原本拿封面当方图用，大图视图下封面已经在横幅上了，
     这里改回「首字」占位，避免同一张图上下重复出现两次。 */
  html[data-view="cover"] .card-ico.is-cover > img { display: none; }
  html[data-view="cover"] .card-ico.is-cover > .card-initial { display: inline !important; }
  html[data-view="cover"] .card-body { padding: 14px 15px 15px; width: 100%; }
  html[data-view="cover"] .card-title b { font-size: 15px; }
  html[data-view="cover"] .card-desc { margin-top: 8px; min-height: 0; }
  html[data-view="cover"] .card-top-flag { z-index: 3; }

  /* —— 列表：单行一条，只看图标 / 名称 / 域名，扫描最快 —— */
  html[data-view="list"] .card-grid { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  html[data-view="list"] .card { padding: 10px 14px; gap: 12px; align-items: center; border-radius: 12px; }
  html[data-view="list"] .card::before { width: 3px; }
  html[data-view="list"] .card-ico { width: 36px; height: 36px; border-radius: 10px; font-size: 16px; }
  html[data-view="list"] .card-body { display: flex; align-items: center; gap: 14px; }
  html[data-view="list"] .card-title { flex: 0 1 auto; max-width: 42%; }
  html[data-view="list"] .card-desc { display: none; }
  html[data-view="list"] .card-foot { margin: 0 0 0 auto; padding: 0; border-top: 0; flex: 0 0 auto; gap: 14px; }
  html[data-view="list"] .card-host { font-size: 12px; }
}

/* ---------------- 响应式 ---------------- */

/* 平板：保留左侧分栏（200px），卡片更宽松、间距更大，呈现「分栏 + 多列」 */
@media (max-width: 1024px) {
  .layout { grid-template-columns: 200px minmax(0, 1fr); gap: 18px; }
  .card-grid { grid-template-columns: repeat(auto-fill, minmax(212px, 1fr)); }
  .banner { min-height: 168px; }
  .banner-inner { padding: 26px 22px; }
  .banner h1 { font-size: 23px; }
  .cat-item { padding: 10px 13px; }
  .card { padding: 15px 15px 14px; }
}

/* 手机：侧栏改为顶部横滑分类，卡片两列 */
@media (max-width: 640px) {
  .topbar-inner { height: 54px; padding: 0 12px; gap: 10px; }
  .brand-text i { display: none; }
  .brand-text b { font-size: 15px; }
  /* 手机上顶栏挤不下横向展开的搜索框：展开时让它**覆盖**整条顶栏，
     而不是把品牌与入口挤变形（那是「优化后反而更乱」的典型来源）。 */
  .searchbox { width: 40px; height: 40px; }
  .searchbox:hover,
  .searchbox:focus-within,
  .searchbox.is-open,
  .searchbox.has-value {
    position: absolute; left: 12px; right: 12px; top: 50%; transform: translateY(-50%);
    width: auto; max-width: none; z-index: 5;
  }
  .searchbox input { padding: 0 14px 0 38px; font-size: 13px; }
  .search-ico { left: 11px; }
  .admin-link { padding: 6px 10px; font-size: 12px; margin-left: auto; }
  /* 手机上视图切换整块隐藏（顶栏挤不下，且 ≤640 一律按「卡片」渲染，见上方 @media (min-width:641px)），
     隐藏后由 .admin-link 的 auto 外边距重新把入口顶到最右。 */
  .view-switch { display: none; }
  /* 给底部吸底导航栏（54px + 安全区）预留同等高度，内容永不藏到它背后 */
  body { padding-bottom: calc(54px + env(safe-area-inset-bottom, 0)); }
  html { scroll-padding-top: 110px; }   /* 锚点/滚动落点避开吸顶的顶栏 + 分类条 */
  .layout { grid-template-columns: minmax(0, 1fr); margin: 12px auto; padding: 0 12px; gap: 14px; }
  /* 移动端：分类条吸顶，粘在顶栏（54px）正下方，滚动时始终可切换分类 */
  .sidebar {
    position: sticky; top: 54px; z-index: 20;
    max-height: none; overflow: visible;
    padding: 10px;
    min-width: 0;   /* 配合 .layout 的 minmax(0,1fr)，别让横滑分类条把页面撑宽 */
    box-shadow: 0 8px 30px rgba(31, 37, 51, .10);
  }
  .side-title { display: none; }
  .cat-nav {
    display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px;
    min-width: 0;
    -webkit-overflow-scrolling: touch;
  }
  .cat-group { margin-bottom: 0; flex: none; }
  .cat-item { white-space: nowrap; padding: 9px 13px; min-height: 38px; }
  .cat-item:hover { transform: none; }
  .cat-sub { display: none; }   /* 手机上折叠二级，避免过长 */
  .content { margin-top: 0; }
  .banner { min-height: 150px; border-radius: 14px; }
  .banner-inner { padding: 20px 16px; }
  .banner h1 { font-size: 20px; }
  .banner p { font-size: 12px; }
  .banner-dots { right: 14px; bottom: 12px; }
  .card-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .card { padding: 13px 12px; gap: 11px; border-radius: 12px; align-items: center; }
  .card:hover { transform: none; }
  .card-ico { width: 40px; height: 40px; font-size: 16px; border-radius: 10px; }
  .card:hover .card-ico { transform: none; }
  .card-title b { font-size: 13px; }
  .card-desc { font-size: 11.5px; min-height: 34px; margin-top: 7px; }
  .card-foot { margin-top: 9px; padding-top: 8px; }
  .sec-more { margin-top: 12px; }
  .sec-more-btn { padding: 6px 16px; font-size: 12.5px; }
  .section-head h2 { font-size: 16px; }
  .hot-card { width: 110px; }
  .hot-card:hover { transform: none; }
  .footer-inner { padding: 12px; gap: 4px 14px; }
  /* 分页条在手机上堆成两行：上面页码、下面条数选择，避免被挤压换行错位 */
  .pager-wrap { flex-direction: column; align-items: stretch; gap: 10px; padding: 12px; margin-bottom: 24px; }
  .pager-info { text-align: center; }
  .pager-main { justify-content: center; }
  .pager-size { justify-content: center; }
  /* 页脚在移动端改为普通流（不再吸底），让出底部给固定导航栏，避免两层叠一起 */
  .footer { position: static; margin-top: 14px; }
  /* 回到顶部按钮抬到吸底导航栏上方 */
  .to-top { right: 14px; bottom: calc(54px + env(safe-area-inset-bottom, 0) + 14px); width: 38px; height: 38px; border-radius: 12px; }
  /* 移动端底部吸底导航栏 */
  .m-tabbar {
    display: flex;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 45;
    height: 54px; padding-bottom: env(safe-area-inset-bottom, 0);
    background: rgba(255, 255, 255, .94);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
    backdrop-filter: saturate(180%) blur(12px);
    border-top: 1px solid var(--line);
    box-shadow: 0 -6px 20px rgba(31, 37, 51, .08);
  }
  .m-tab {
    flex: 1 1 0; min-height: 54px;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 2px; border: 0; background: transparent; cursor: pointer;
    color: var(--ink-3); font-family: inherit;
    transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
  }
  .m-tab:active { background: rgba(45, 140, 240, .08); }
  .m-tab.is-active { color: var(--brand); }
  .m-tab svg { width: 22px; height: 22px; flex: none; }
  .m-tab span { font-size: 11px; line-height: 1; }
}

/* 小屏手机（紧凑单列）：卡片单列、触控区更大、字号再缩 */
@media (max-width: 480px) {
  .card-grid { grid-template-columns: 1fr; }
  .card { padding: 14px 13px; gap: 12px; }
  .card-ico { width: 42px; height: 42px; }
  .footer-inner { font-size: 11px; }
}

/* 尊重系统「减少动态效果」：动画与平滑滚动全部退化为直切 */
@media (prefers-reduced-motion: reduce) {
  html.vk-ready .cat-section,
  html.vk-ready .card,
  html.vk-ready .hot-card { animation: none; }
  .banner-track { transition: none; }
  .card:hover, .hot-card:hover, .pg-btn:hover:not(:disabled), .to-top:hover { transform: none; }
}

/* ===== 前台访问验证闸门 ===== */
/* 未验证 / 未知状态时隐藏主内容（绝不向未授权用户展示站点内容） */
html[data-auth="locked"] .layout,
html:not([data-auth]) .layout,
html[data-auth="locked"] .footer,
html:not([data-auth]) .footer { visibility: hidden; }

#vkAuthGate { display: none; }
html[data-auth="locked"] #vkAuthGate { display: flex; }

.auth-gate {
  position: fixed; inset: 0; z-index: 9999;
  align-items: center; justify-content: center;
  /* ⛔ 渐变必须走 var(--ag)：它在视图里被 inline style 下发（Settings.AuthGradientCss 单一来源）。
     兜底值与 .auth-logo / .auth-btn 保持同一套蓝紫，避免「预置方案失效」时整页褪成默认蓝。 */
  background: var(--ag, linear-gradient(135deg, #667eea 0%, #764ba2 100%));
  padding: 24px;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
}
/* 背景图层：只有配了背景图才渲染这个 div。没配图时 .auth-gate 自身的 --ag 渐变直接生效。 */
.auth-gate-bg {
  position: absolute; inset: 0; z-index: 0;
  background-size: cover; background-position: center; background-repeat: no-repeat;
}
/* 背景图之上压一层暗色遮罩：保证白色卡片与卡片上的文字始终有足够对比度，
   否则用户传一张浅色大图会导致标题几乎看不见。 */
.auth-gate.has-bg::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: rgba(16, 22, 40, .46);
}
.auth-card {
  position: relative; z-index: 2;
  width: 100%; max-width: 380px;
  background: #fff; border-radius: 18px; padding: 34px 30px 28px;
  box-shadow: 0 24px 70px rgba(20, 25, 45, .35); text-align: center;
}
.auth-brand { margin-bottom: 14px; }
.auth-logo-img {
  display: block; width: 52px; height: 52px; margin: 0 auto;
  border-radius: 14px; object-fit: contain;
}
.auth-logo {
  display: inline-flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; border-radius: 14px;
  background: var(--ag, linear-gradient(135deg, #667eea 0%, #764ba2 100%));
  color: #fff; font-size: 25px; font-weight: 800;
  box-shadow: 0 8px 20px rgba(45, 140, 240, .4);
}
.auth-title { font-size: 20px; font-weight: 700; color: #1f2533; margin: 8px 0 4px; }
.auth-sub { font-size: 13px; color: #8a93a6; margin: 0 0 22px; line-height: 1.6; }
.auth-form { display: flex; flex-direction: column; gap: 12px; }
.auth-input {
  width: 100%; height: 46px; padding: 0 16px; box-sizing: border-box;
  border: 1.5px solid #e3e8f0; border-radius: 12px;
  font-size: 16px; color: #1f2533; outline: none;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.auth-input:focus { border-color: #2d8cf0; box-shadow: 0 0 0 3px rgba(45, 140, 240, .15); }
.auth-input::placeholder { color: #b6bfcc; }
.auth-btn {
  width: 100%; height: 46px; border: none; border-radius: 12px; cursor: pointer;
  background: var(--ag, linear-gradient(135deg, #667eea 0%, #764ba2 100%));
  color: #fff; font-size: 16px; font-weight: 600;
  box-shadow: 0 8px 18px rgba(45, 140, 240, .35);
  transition: transform .12s ease, box-shadow .15s ease, opacity .15s ease;
}
.auth-btn:hover { transform: translateY(-1px); }
.auth-btn:active { transform: translateY(0); }
.auth-btn:disabled { opacity: .65; cursor: default; transform: none; }
.auth-msg { min-height: 18px; margin: 2px 0 0; font-size: 13px; color: #e5484d; }
.auth-tip { margin: 16px 0 0; font-size: 12px; color: #aab2c2; line-height: 1.6; }

@media (max-width: 480px) {
  .auth-card { padding: 28px 20px 24px; border-radius: 16px; }
}
