/* ============================================================
 * lixq.net —— 门户样式
 * 设计基调：纯色（无渐变）、极简留白、克制配色。
 * 布局：整页不滚动（打开即完整一屏）；底部抽屉由滚轮上滑弹出，
 *       覆盖下半屏，抽屉内部独立滚动，用小卡片装下全部服务与项目。
 * ============================================================ */

/* ---------- 主题变量 ---------- */
:root {
  /* 布局 */
  --nav-h: 60px;            /* 顶栏高度 */
  --handle-h: 46px;         /* 抽屉抓手区高度（也是拖拽热区） */
  --vh: 100vh;              /* 视口高度（有 dvh 时被覆盖） */
  --drawer-max: 50vh;       /* 抽屉可拖到的最高处＝默认高度（拉上来直接拉满） */
  --hero-drop: 48px;        /* 上半区（含诗词）整体再往下压一点；加大＝诗词更靠近页面中线 */
  --hero-h: calc(100vh - var(--nav-h) - var(--drawer-max) + var(--hero-drop));
                            /* 上半区高度；hero 贴着它的底边排，加大它＝内容整体下移 */
  --card-h: 74px;           /* 卡片高度（JS 会按可用空间在 54~84 之间微调） */
  --verse-lines: 4;         /* 诗词预留区：能容纳四行（七律＝四行） */
  --verse-line: 2;          /* 诗词行高倍数（恒定，不随行数变） */
  --verse-fs: 17px;         /* 诗词字号 */
  --verse-shift: 0;         /* 诗词整体右移量。0 = 文字墨迹居中（实测 467.6 = 中轴）；
                               >0 会把文字推向右侧，让逗号所在格落在中轴上 */
  /* 联系方式(GitHub / Zhihu)的横向排布。
     两词宽度不等，所以「外边缘对称」和「缝对称」只能二选一 —— 我们选缝对称：
     两个链接各占一个等宽格位（格位本身关于中轴对称），格位内部让文字朝中间的缝贴齐，
     于是缝的左端 = 中轴−gap/2、右端 = 中轴+gap/2，缝的中点严格等于中轴。
     代价：GitHub 更宽，会往左多伸出去一点，外边缘不对称 —— 这是唯一解。 */
  --socials-slot: 68px;     /* 单个格位宽度，必须 ≥ gap/2 + 最长那个词；只影响悬停热区，不影响位置 */
  --socials-gap: 28px;      /* 两词之间的净间距，缝严格以此为宽并居中 */

  --theme-ease: cubic-bezier(0.37, 0, 0.63, 1); /* 正弦式缓入缓出：两头都软，没有突兀的起停 */
  --veil-in: 0.3s;                            /* ① 遮罩淡入：整页融成一色（兜底方案用） */
  --veil-shift: 2.4s;                         /* ② 多段色阶 + 内容逐渐显影的时长 */

  /* 配色（浅色，默认）：暖调乳白纸感，不是纯白 */
  --bg: #f6f4ee;            /* 页面底色：带暖调的乳白，明显不是 #ffffff */
  --bg-elevated: #ebe8e0;   /* 抽屉底色：再沉一档 */
  --bg-card: #fdfcfa;       /* 卡片 / 下拉：最亮的一档，但仍是暖白 */
  --hover-bg: rgba(40, 34, 20, 0.05);
  --text: #1c1b18;          /* 主文字：够黑 */
  --text-secondary: #42434a;/* 次级（诗词、联系方式）：明显加深，不再是浅灰 */
  --text-tertiary: #737580; /* 三级（版权等）：也加深 */
  --border: #e0dcd2;        /* 暖调分隔线 */
  --border-strong: #c9c3b5;
  --accent: #3b6ef0;
  --accent-contrast: #ffffff;
  --status-online: #1f9250;
  --status-wip: #c8890a;
  --status-planned: #8b8f9c;
  --status-offline: #d13a30;
  --shadow: 0 10px 30px rgba(40, 34, 20, 0.09);
  --sheet-shadow: 0 -10px 34px rgba(40, 34, 20, 0.11);  /* 保持大模糊：阴影要够得着诗词横线 */
}

html[data-theme="dark"] {
  --bg: #121621;
  --bg-elevated: #171c28;
  --bg-card: #1f2534;
  --hover-bg: rgba(255, 255, 255, 0.06);
  --text: #b3bdcf;        /* 主文字：柔和，不用近白（近白在暗底上太刺眼） */
  --text-secondary: #949eb2;
  --text-tertiary: #666f81;
  --border: #272e3f;
  --border-strong: #39415a;
  --accent: #4d7cfe;
  --accent-contrast: #ffffff;
  --status-online: #34c77b;
  --status-wip: #f0b429;
  --status-planned: #666f81;
  --status-offline: #f15b4c;
  --shadow: 0 12px 36px rgba(0, 0, 0, 0.35);
  --sheet-shadow: 0 -12px 40px rgba(0, 0, 0, 0.45);
}

/* 未手动指定主题时，跟随系统 */
@media (prefers-color-scheme: dark) {
  html:not([data-theme]) {
    --bg: #121621;
    --bg-elevated: #171c28;
    --bg-card: #1f2534;
    --hover-bg: rgba(255, 255, 255, 0.06);
    --text: #b3bdcf;        /* 主文字：柔和，不用近白（近白在暗底上太刺眼） */
    --text-secondary: #949eb2;
    --text-tertiary: #666f81;
    --border: #272e3f;
    --border-strong: #39415a;
    --accent: #4d7cfe;
    --accent-contrast: #ffffff;
    --status-online: #34c77b;
    --status-wip: #f0b429;
    --status-planned: #666f81;
    --status-offline: #f15b4c;
    --shadow: 0 12px 36px rgba(0, 0, 0, 0.35);
    --sheet-shadow: 0 -12px 40px rgba(0, 0, 0, 0.45);
  }
}

/* 移动端地址栏会伸缩，用 dvh 跟随真实可视高度 */
@supports (height: 100dvh) {
  :root {
    --vh: 100dvh;
    --drawer-max: 50dvh;
    --hero-h: calc(100dvh - var(--nav-h) - var(--drawer-max) + var(--hero-drop));
  }
}

/* ---------- 基础 ---------- */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

[hidden] {
  display: none !important;
}

html {
  background-color: var(--bg);
  transition: background-color 0.25s var(--theme-ease);
}

html,
body {
  overscroll-behavior: none; /* 关掉整页回弹，滚动权交给抽屉 */
}

body {
  font: 16px/1.7 -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
    "Hiragino Sans GB", "Microsoft YaHei", Helvetica, Arial, sans-serif;
  color: var(--text);
  background-color: var(--bg);
  transition: background-color 0.25s var(--theme-ease),
              color 0.25s var(--theme-ease);
  height: var(--vh);
  overflow: hidden;            /* 整页不滚动 */
  display: flex;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a {
  color: inherit;
  text-decoration: none;
}

ul {
  list-style: none;
}

button {
  font: inherit;
  color: inherit;
}

::selection {
  background: var(--accent);
  color: var(--accent-contrast);
}

/* 遮罩淡出：与色阶**同一条曲线**（opacity = 1 − 行程 p，19 档、每档等时）。
   这样“字显露了多少”与“背景走了多远”永远严格同步 ——
   背景两端慢，字的显露也两端慢，不会再有“字比背景冲”的感觉。 */
@keyframes veil-fade {
  0%     { opacity: 1.0; }
  5.56%  { opacity: 0.973; }
  11.11% { opacity: 0.937; }
  16.67% { opacity: 0.893; }
  22.22% { opacity: 0.841; }
  27.78% { opacity: 0.782; }
  33.33% { opacity: 0.717; }
  38.89% { opacity: 0.647; }
  44.44% { opacity: 0.574; }
  50%    { opacity: 0.5; }
  55.56% { opacity: 0.426; }
  61.11% { opacity: 0.353; }
  66.67% { opacity: 0.283; }
  72.22% { opacity: 0.218; }
  77.78% { opacity: 0.159; }
  83.33% { opacity: 0.107; }
  88.89% { opacity: 0.063; }
  94.44% { opacity: 0.027; }
  100%   { opacity: 0.0; }
}

/* ---------- 主题切换遮罩 ----------
   点切换时（JS 驱动，约 0.3 + 1.6 秒）：
     ① 遮罩淡入 —— 一整块当前底色盖住全页，文字/卡片/边框全部看不见，浑然一体
     ② 盖严之后换 data-theme，同时遮罩一边逐层走色阶、一边淡出，
        文字于是跟着背景一起、逐渐显影出来，而不是最后突然跳出来。

   ⚠️ 为什么用「一叠纯色层互相淡入淡出」而不是直接动画 background-color：
     background-color 是**绘制属性**，全屏动画要每帧重绘整个图层；浏览器按
     分块(tile)重绘，就会出现「某处先变、再向四周蔓延」的观感 —— 盯着中间看时
     特别明显。而 opacity 是**合成属性**，由 GPU 统一处理，整屏严格同步。
     所以色阶做成 N 层纯色，每层只动 opacity，逐层接力淡入。 */
.theme-veil {
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--veil-in) var(--theme-ease);   /* ① 淡入 */
}

/* ① 融成一色：整页被当前底色盖住 */
.theme-veil.is-on {
  opacity: 1;
}

/* ② 色阶各层与遮罩自身同步淡出：底层常亮，上层依次接力 */
.theme-veil.is-out {
  opacity: 0;
  animation: veil-fade var(--veil-shift) linear forwards;
}

/* 每一层纯色（由 JS 按 OKLab 色阶生成） */
.theme-veil span {
  position: absolute;
  inset: 0;
  display: block;
  opacity: 0;
}

/* 最底层＝起始底色，始终不透明，其余层在它上面依次淡入 */
.theme-veil span:first-child {
  opacity: 1;
}

/* 系统开了"减弱动态效果"时不做遮罩，直接瞬切 */
@media (prefers-reduced-motion: reduce) {
  .theme-veil {
    display: none;
  }
}

/* ---------- 顶部导航 ---------- */
.site-header {
  position: relative;
  flex: none;
  z-index: 60;
  background-color: var(--bg);
  border-bottom: 1px solid var(--border);
}

.site-header__inner {
  max-width: 1000px;
  margin: 0 auto;
  padding: 0 24px;
  height: var(--nav-h);
  /* 用 grid 而不是 space-between：三列固定，中间那列才在页面真正的中轴上。
     原来两侧宽度不等（lixq ≈40px vs 右侧按钮 ≈84px），导航被推偏了。 */
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
}

.wordmark {
  font-size: 19px;
  font-weight: 700;
  letter-spacing: 0.5px;
  color: var(--text);
  transition: opacity 0.18s ease;
}

/* 左上角 logo 的可点提示：只用透明度，不引入颜色，深浅色下都是同一个观感。
   行为 = 回首页（等同刷新），与 DeepSeek 一致；账户入口不放这里，放最右边。 */
.wordmark:hover {
  opacity: 0.62;
}

.site-nav__list {
  display: flex;
  gap: 4px;
}

.site-nav__link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  font-size: 15px;
  color: var(--text-secondary);
  background: none;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: color 0.18s ease, background-color 0.18s ease;
}

.site-nav__link:hover {
  color: var(--text);
  background-color: var(--hover-bg);
}

/* 下拉菜单 */
.has-dropdown {
  position: relative;
}

.dropdown {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  min-width: 200px;
  padding: 6px;
  background-color: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity 0.16s ease, transform 0.16s ease, visibility 0.16s ease;
}

.has-dropdown:hover .dropdown,
.has-dropdown:focus-within .dropdown,
.has-dropdown.is-open .dropdown {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.dropdown__link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 12px;
  font-size: 14px;
  color: var(--text-secondary);
  border-radius: 8px;
  transition: color 0.15s ease, background-color 0.15s ease;
}

.dropdown__link:hover {
  color: var(--text);
  background-color: var(--hover-bg);
}

.dropdown__link--disabled {
  color: var(--text-tertiary);
  cursor: default;
}

.dropdown__status {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: none;
}

/* 头部操作区 */
.header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  justify-self: end;   /* grid 第三列靠右 */
}

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  padding: 0;
  color: var(--text-secondary);
  background: none;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: color 0.18s ease, background-color 0.18s ease;
}

.theme-toggle:hover {
  color: var(--text);
  background-color: var(--hover-bg);
}

.theme-toggle svg {
  width: 18px;
  height: 18px;
  display: block;
}

.menu-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 38px;
  height: 38px;
  padding: 9px;
  background: none;
  border: none;
  border-radius: 8px;
  cursor: pointer;
}

.menu-toggle span {
  display: block;
  height: 2px;
  width: 100%;
  background-color: var(--text-secondary);
  border-radius: 1px;
  transition: transform 0.2s ease, opacity 0.2s ease;
}

/* ---------- 上半屏（hero 区） ----------
 * 高度固定为「整页 − 顶栏 − 抽屉默认高度」，hero 在这一块里**贴着底边**排，
 * 于是诗词下横线正好落在页面中线（＝抽屉升起来时的顶边）：
 *   · 诗词永远不会被抽屉盖住
 *   · 联系方式紧贴其下，必然落在抽屉覆盖区里
 * 抽屉滑上滑下时这块完全不动（子元素只有绝对定位的悬浮层）。 */
.stage {
  flex: none;
  min-height: var(--hero-h);
  display: flex;
  align-items: flex-end;     /* hero 整组贴着上半区底边排 */
  justify-content: center;
  padding: 10px 24px;
}

.hero {
  position: relative;
  /* 必须显式给宽度：否则 flex 项的宽度由内容 max-content 推导，
     而 .verse 的 width: min(560px, 100%) 又反过来参照它 —— 两者互相依赖、
     基准不确定，诗词框 / 联系方式 / 顶栏就会各按各的中轴算，对不齐。 */
  width: 100%;
  max-width: 760px;
  text-align: center;
}

.hero__name {
  /* 固定尺寸，不用 vw：否则横向拖窗口时大字会连续变大变小，
     hero 高度随之变化 → 诗词竖向位置变 → 抽屉顶边也跟着变。
     竖向布局必须与宽度无关。窄屏改用下面的离散断点，不连续。 */
  font-size: 58px;
  font-weight: 700;
  letter-spacing: 1px;
  color: var(--text);
  line-height: 1.1;
}

/* 窄屏降档：离散跳变，不做连续缩放 */
@media (max-width: 820px) {
  .hero__name { font-size: 48px; }
}
@media (max-width: 560px) {
  .hero__name { font-size: 40px; }
}

/* ---------- 诗词区 ----------
 * .verse 是「预留区」：高度固定＝四行，横线就在它的上下两条边 —— 位置永远不动；
 * 诗词在其中垂直居中。横线就是一条干净的细线，不加阴影。 */
.verse {
  position: relative;
  width: min(560px, 100%);   /* 比参考站点更短一些 */
  margin: 20px auto 0;
  min-height: calc(var(--verse-lines) * var(--verse-line) * var(--verse-fs));
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* 上下横线本身（位置固定） */
.verse::before,
.verse::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background-color: var(--border-strong);
  pointer-events: none;
}

.verse::before {
  top: 0;
}

.verse::after {
  bottom: 0;
}

.verse__body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  margin: 0;
  /* 标点悬挂补偿量，默认 0（＝文字墨迹居中，实测正好在中轴上）。
     若想让「逗号所在格」落在中轴而不是让整行居中，把它调成 1em 左右 —— 但那会让
     文字整体右偏半格（8.5px），实测会偏离中轴，所以默认关闭。 */
  padding-left: var(--verse-shift, 0);
  font-size: var(--verse-fs);
  line-height: var(--verse-line);  /* 恒定行距：横线位置不变，紧凑感才一致 */
  letter-spacing: 0.06em;
  text-align: center;
  color: var(--text-secondary);
  white-space: pre-line;     /* 保留配置里的换行 */
}

/* ---------- 联系方式 + 地址 ----------
 * 绝对定位挂在 hero 下方：不参与布局（所以不会把上半区撑高、
 * 也不会影响抽屉的默认高度），就贴在诗词下横线下面一点。 */
.stage-foot {
  position: absolute;
  top: calc(100% + 26px);   /* 联系方式紧贴诗词下横线之下（位置固定，不随抽屉变化）*/
  left: 0;
  right: 0;
  z-index: 30;              /* 低于抽屉(40)：抽屉升上来就盖住它 */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 13px;
  text-align: center;
}

.socials {
  display: flex;
  gap: 0;                  /* 间距全部由格位内部留白产生，见 .social */
}

/* 等宽格位 + 文字朝缝对齐。
   两个格位加起来是 2×slot、整体居中，所以格位之间的分界线正好落在中轴上；
   GitHub 右对齐并右留 gap/2，Zhihu 左对齐并左留 gap/2，
   于是文字之间的那道缝就是 [中轴−gap/2, 中轴+gap/2] —— 中点严格在中轴。
   注意：这里绝不能用 text-align:center，居中会让窄的那个词两侧都有余量，
   缝就会偏向宽词一侧（正是之前偏右 3.75px 的原因）。 */
.social {
  display: inline-block;
  box-sizing: border-box;
  width: var(--socials-slot);
  font-size: 14px;
  color: var(--text);
  transition: color 0.18s ease;
}

.socials > li:first-child .social {
  text-align: right;
  padding-right: calc(var(--socials-gap) / 2);
}

.socials > li:last-child .social {
  text-align: left;
  padding-left: calc(var(--socials-gap) / 2);
}

/* 下划线仍然贴着文字本身，不跟着格位拉长 */
.social__label {
  border-bottom: 1px dotted var(--text-tertiary);
  padding-bottom: 1px;
  transition: color 0.18s ease, border-color 0.18s ease;
}

a.social {
  cursor: pointer;
}

a.social:hover .social__label {
  color: var(--accent);
  border-bottom: 1px solid var(--accent);             /* 悬停时点线变实线 */
}

.place {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--text);                                 /* 同样加深 */
}

.place__icon {
  width: 14px;
  height: 14px;
  flex: none;
}

.copyright {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 26px;             /* 固定在最底部，不随上面的内容移动 */
  z-index: 30;              /* 与联系方式同层，低于抽屉 */
  text-align: center;
  font-size: 12px;
  letter-spacing: 0.5px;
  color: var(--text-tertiary);
}

/* ---------- 底部抽屉 ----------
 * 高度驱动：把「上半区以下」的空间按 --drawer-h 占住，锚在页面底部。
 * 抓手可上下拖拽（0 ~ --drawer-max），滚轮下滑则弹到默认高度。 */
.sheet {
  position: relative;
  flex: none;
  margin-top: auto;      /* 始终贴在页面底部 */
  height: 0;             /* 由 JS 设置为具体像素 */
  min-height: 0;
  z-index: 40;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background-color: var(--bg-elevated);
  border-top: 1px solid var(--border);
  border-radius: 16px 16px 0 0;
  box-shadow: var(--sheet-shadow);
  transition: height 0.42s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.sheet.is-instant {
  transition: none;      /* 拖拽中不做补间，跟手 */
}

.sheet.is-collapsed {
  border-top-color: transparent;
  box-shadow: none;
}

.sheet__handle {
  flex: none;
  height: var(--handle-h);
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  cursor: grab;
  touch-action: none;    /* 拖拽时不要触发浏览器滚动 */
  -webkit-user-select: none;
  user-select: none;
}

.sheet__handle:active {
  cursor: grabbing;
}

/* ---------- 选择 / 复制 ----------
   只有两类东西不可选中：
     · .site-header —— 导航按钮是控件，不是内容
     · .theme-veil  —— 切换主题用的全屏遮罩
   其余全部（标题、诗词、联系方式、地址、版权、抽屉里的卡片）都可正常选中复制。
   ⚠️ 不要用 pointer-events:none 来表示"不可点"——那会让鼠标根本进不去，
      文字也就无法被选中（曾经因此导致地址选不中）。 */
.site-header,
.theme-veil {
  -webkit-user-select: none;
  user-select: none;
}

.sheet__grabber {
  width: 42px;
  height: 4px;
  border-radius: 2px;
  background-color: var(--border-strong);
  transition: background-color 0.2s ease;
}

.sheet__handle:hover .sheet__grabber {
  background-color: var(--text-tertiary);
}

/* 抽屉自己的滚动区 */
.sheet__body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain; /* 滚到头不把滚动传给页面 */
  -webkit-overflow-scrolling: touch;
  padding: 4px 24px 22px;
  /* 滚动条常驻预留（左右各一格）：内容超出时滚动条出现、缩回时消失，
     都不会再改变内容宽度，于是拉上拉下时内容不会左右跳动。 */
  scrollbar-gutter: stable both-edges;
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
}

/* 抽屉内容与顶栏/hero 同宽居中，避免贴到屏幕边缘 */
.sheet__inner {
  max-width: 1000px;
  margin: 0 auto;
}

.sheet__body::-webkit-scrollbar {
  width: 8px;
}

.sheet__body::-webkit-scrollbar-thumb {
  background-color: var(--border-strong);
  border-radius: 4px;
}

.sheet__body::-webkit-scrollbar-track {
  background: transparent;
}

.sheet__title {
  position: relative;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 1px;
  color: var(--text-secondary);
  margin: 10px 0 6px;
  padding-left: 11px;
}

.sheet__title:first-child {
  margin-top: 2px;
}

.sheet__title::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 12px;
  border-radius: 2px;
  background-color: var(--accent);
}

/* ---------- 小卡片 ---------- */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
  gap: 10px;
}

.card {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  height: var(--card-h);
  padding: 8px 13px;
  background-color: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 11px;
  transition: transform 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
}

a.card:hover {
  transform: translateY(-2px);
  border-color: var(--accent);
  box-shadow: var(--shadow);
}

.card--disabled {
  cursor: default;
}

.card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.card__name {
  font-size: 13.5px;
  line-height: 1.3;
  font-weight: 600;
  color: var(--text);
  letter-spacing: 0.3px;
}

.card__status {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: none;
}

.card__status--online { background-color: var(--status-online); }
.card__status--wip { background-color: var(--status-wip); }
.card__status--planned { background-color: var(--status-planned); }
.card__status--offline { background-color: var(--status-offline); }

.card__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 18px;
}

.card__status-label {
  font-size: 10px;
  line-height: 1.45;
  padding: 1px 6px;
  border-radius: 20px;
  color: var(--text-secondary);
  background-color: var(--bg-elevated);
  border: 1px solid var(--border);
}

.card__arrow {
  font-size: 13px;
  color: var(--accent);
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity 0.18s ease, transform 0.18s ease;
}

a.card:hover .card__arrow {
  opacity: 1;
  transform: translateX(0);
}

/* ---------- 入场动画 ---------- */
.no-js .reveal {
  opacity: 1;
  transform: none;
}

.reveal {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}

.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .sheet,
  .stage-foot,
  .card,
  .site-nav__link,
  .theme-toggle {
    transition: none;
  }
}

/* 屏幕不够高时整体收紧，保证上半区（大字＋四行诗词）装得下，
   这样抽屉才能始终拿到完整的默认高度 */
@media (max-height: 720px) {
  :root {
    --verse-line: 1.9;      /* 在 :root 上改，.verse 的预留高度才会跟着一起变 */
    --verse-fs: 15px;
  }
  .hero__name {
    font-size: 44px;
  }
}

/* ---------- 移动端 ---------- */
@media (max-width: 767px) {
  :root {
    --card-h: 68px;      /* 窄屏卡片略矮 */
  }

  /* 窄屏导航改为绝对定位（脱离网格流），此时表头只剩两项，用 flex 两端对齐 */
  .site-header__inner {
    display: flex;
    justify-content: space-between;
  }

  .site-nav {
    position: absolute;
    top: var(--nav-h);
    left: 0;
    right: 0;
    background-color: var(--bg);
    border-bottom: 1px solid var(--border);
    padding: 8px 24px 20px;
    display: none;
  }

  .site-nav.is-open {
    display: block;
  }

  .site-nav__list {
    flex-direction: column;
    gap: 2px;
  }

  .site-nav__link {
    width: 100%;
    justify-content: space-between;
    font-size: 16px;
    padding: 12px 4px;
  }

  .dropdown {
    position: static;
    min-width: 0;
    border: none;
    box-shadow: none;
    padding: 0 0 4px 8px;
    opacity: 1;
    visibility: visible;
    transform: none;
    display: none;
  }

  .has-dropdown.is-open .dropdown {
    display: block;
  }

  .dropdown__link {
    padding: 9px 12px;
    font-size: 15px;
  }

  .menu-toggle {
    display: flex;
  }

  .menu-toggle[aria-expanded="true"] span:nth-child(1) {
    transform: translateY(6px) rotate(45deg);
  }

  .menu-toggle[aria-expanded="true"] span:nth-child(2) {
    opacity: 0;
  }

  .menu-toggle[aria-expanded="true"] span:nth-child(3) {
    transform: translateY(-6px) rotate(-45deg);
  }

    .sheet__body {
    padding: 2px 18px 26px;
  }

  .grid {
    grid-template-columns: repeat(auto-fill, minmax(142px, 1fr));
    gap: 9px;
  }

  .card {
    padding: 10px 13px;
  }
}

/* ---------- 无 JS（或 JS 未接管）时的降级布局 ----------
   内容本来就在 HTML 里，这里只是把"抽屉"这个交互壳子拆掉，
   让服务与项目直接平铺成一条正常的滚动页面。见 index.html 里的看门狗。 */
.no-js body {
  display: block;
  height: auto;
  overflow: visible;
}
.no-js .site-nav,
.no-js .menu-toggle,
.no-js .theme-toggle,
.no-js .theme-veil,
.no-js .sheet__handle {
  display: none;
}
.no-js .stage {
  min-height: 0;
  align-items: center;
  padding: 48px 24px 24px;
}
.no-js .stage-foot {
  position: static;
  margin-top: 32px;
}
.no-js .copyright {
  position: static;
  margin: 24px 0 40px;
}
.no-js .sheet {
  position: static;
  height: auto;
  margin-top: 0;
  border-radius: 0;
  box-shadow: none;
  transform: none;
}
.no-js .sheet__body {
  overflow: visible;
}
