/* 诗境 Poemorama — 中式典雅风格
   配色：墨色背景 + 宣纸暖白 + 朱砂红点缀。
   颜色语义：exact=青绿 / misplaced=赭黄 / none=灰。 */

:root {
  --ink: #1a1714;          /* 墨底 */
  --ink-2: #241f1b;        /* 卡片底 */
  --ink-3: #2f2823;        /* 浅一层 */
  --paper: #f3ead8;        /* 宣纸暖白（主文字） */
  --paper-dim: #c9bda7;    /* 次要文字 */
  --paper-faint: #8a8170;  /* 更弱 */
  --cinnabar: #c5443b;     /* 朱砂红 */
  --cinnabar-soft: #d56b5f;
  --gold: #c9a45c;         /* 描金 */

  --ok: #5fa36a;           /* exact 青绿 */
  --ok-bg: #2c4631;
  --mis: #cf9a45;          /* misplaced 赭黄 */
  --none: #6b6358;         /* none 灰 */

  --line: rgba(201, 189, 167, 0.18);
  --radius: 12px;
  --shadow: 0 6px 24px rgba(0, 0, 0, 0.35);

  --serif: 'Noto Serif SC', 'Songti SC', 'STSong', 'SimSun', serif;
  --sans: 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', sans-serif;
  --mono: 'DejaVu Sans Mono', 'Menlo', 'Consolas', monospace;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background:
    radial-gradient(1200px 600px at 50% -10%, #2a231d 0%, var(--ink) 55%) fixed;
  color: var(--paper);
  font-family: var(--serif);
  -webkit-font-smoothing: antialiased;
  min-height: 100%;
}

#app { min-height: 100vh; position: relative; z-index: 1; }

.page {
  max-width: 920px;
  margin: 0 auto;
  padding: 24px 18px 64px;
}
/* 游戏页 = 全屏舞台：全景铺满、底板浮于其上，整页不滚动。 */
.game-page {
  position: fixed;
  inset: 0;
  max-width: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
}

button { font-family: inherit; cursor: pointer; }

.btn {
  border: 1px solid var(--line);
  background: var(--ink-3);
  color: var(--paper);
  padding: 9px 18px;
  border-radius: 999px;
  font-size: 15px;
  transition: transform 0.12s ease, background 0.2s ease, border-color 0.2s ease;
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn.primary {
  background: var(--cinnabar);
  border-color: var(--cinnabar);
  color: #fff5ee;
  box-shadow: 0 4px 14px rgba(197, 68, 59, 0.35);
}
.btn.primary:hover { background: var(--cinnabar-soft); }
.btn.ghost { background: transparent; }
.btn:disabled { opacity: 0.45; cursor: not-allowed; transform: none; }
.btn.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  padding: 0;
}
.btn.icon-btn svg {
  width: 19px;
  height: 19px;
}

/* ---------- 主页全景背景（随机选一张，慢速平移）---------- */
#bg-panorama {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  background: var(--ink); /* 图片加载前的兜底 */
}
/* 绝对定位（非 flex 子项），避免被父级 flex 压缩，保证 track 保持整宽可平移。 */
.bg-track {
  position: absolute;
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  animation: bgPan 180s linear infinite;
  will-change: transform;
}
/* 内层负责垂直起伏：与外层水平平移分属不同元素、不同轴向，互不干扰。
   alternate 让它在 ±3vh 之间来回（仅占视口高度 3%，视角仍大致横向）。 */
.bg-bob {
  display: flex; /* 内部横向排列两张图 */
  animation: bgBob 16s ease-in-out infinite alternate;
  will-change: transform;
}
/* vmax 兼顾横竖屏：宽高都大于视口，绝无留白。 */
.bg-image {
  width: 300vmax;
  height: auto;
  flex-shrink: 0;
  display: block;
  filter: blur(3px) brightness(0.6);
  pointer-events: none;
  user-select: none;
}
/* 水平平移自身宽度的 50%（= 一张图宽）：第二张与第一张相同，无缝循环。
   translateY(-50%) 始终保留以维持垂直居中。 */
@keyframes bgPan {
  from { transform: translateY(-50%) translateX(0); }
  to { transform: translateY(-50%) translateX(-50%); }
}
/* 垂直起伏：±3vh 的微小上下漂移，缓动让两端不生硬。 */
@keyframes bgBob {
  from { transform: translateY(-3vh); }
  to { transform: translateY(3vh); }
}
/* 渐变遮罩：上下压暗、中间稍亮，保证标题和选本卡片可读。 */
#bg-panorama::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgba(26, 23, 20, 0.85) 0%,
    rgba(26, 23, 20, 0.45) 35%,
    rgba(26, 23, 20, 0.55) 65%,
    rgba(26, 23, 20, 0.9) 100%
  );
}
/* 全景背景激活后，body 自身的渐变背景让位（避免叠加发暗）。 */
body.has-bg-panorama {
  background: none;
}

/* ---------- 加载 / 致命错误 ---------- */
.loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  min-height: 70vh;
  color: var(--paper-dim);
}
.spinner {
  width: 36px; height: 36px;
  border: 3px solid var(--line);
  border-top-color: var(--cinnabar);
  border-radius: 50%;
  animation: spin 0.9s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.fatal { color: var(--cinnabar-soft); max-width: 520px; text-align: center; line-height: 1.7; }

/* ---------- 选本页 ---------- */
.app-header { text-align: center; margin: 36px 0 30px; }
.app-title {
  font-size: 40px; font-weight: 700; letter-spacing: 0.12em;
  margin: 0; color: var(--paper);
}
.app-title .title-en {
  display: block; font-size: 15px; letter-spacing: 0.4em;
  color: var(--gold); font-weight: 400; margin-top: 8px; text-transform: uppercase;
}
.app-sub { color: var(--paper-dim); margin: 14px 0 0; font-size: 16px; letter-spacing: 0.05em; }
.entry-actions { display: flex; justify-content: center; gap: 10px; margin-top: 18px; }

.collection-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 18px;
  margin-top: 14px;
}
.collection-card {
  text-align: left;
  background: linear-gradient(160deg, var(--ink-2), var(--ink));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px 20px 22px;
  color: var(--paper);
  box-shadow: var(--shadow);
  transition: transform 0.16s ease, border-color 0.2s ease;
  position: relative;
  overflow: hidden;
}
.collection-card::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  background: var(--cinnabar); opacity: 0.85;
}
.collection-card:not(:disabled):hover { transform: translateY(-3px); border-color: var(--gold); }
.collection-card:disabled { opacity: 0.4; cursor: not-allowed; }
.cc-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; }
.cc-badge {
  font-size: 12px; padding: 3px 10px; border-radius: 999px;
  border: 1px solid var(--line); color: var(--paper-dim);
}
.cc-badge.cc-anthology { color: var(--gold); border-color: rgba(201, 164, 92, 0.4); }
.cc-badge.cc-textbook { color: var(--ok); border-color: rgba(95, 163, 106, 0.4); }
.cc-count { font-size: 13px; color: var(--paper-faint); }
.cc-title { margin: 0 0 8px; font-size: 21px; font-weight: 600; letter-spacing: 0.04em; }

/* 入口说明与规则弹层。 */
.entry-modal {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(0, 0, 0, 0.62);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
}
.entry-panel {
  width: min(520px, 100%);
  max-height: min(82dvh, 680px);
  overflow-y: auto;
  padding: 26px 24px 22px;
  color: var(--paper);
  background: linear-gradient(160deg, var(--ink-2), var(--ink));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.entry-content h2 { margin: 0 0 16px; font-size: 22px; color: var(--gold); }
.entry-content p { margin: 0 0 12px; color: var(--paper-dim); line-height: 1.8; }
.entry-content p:last-child { margin-bottom: 0; }
.entry-panel .entry-actions { margin-top: 22px; }
.rule-mark { font-weight: 600; }
.rule-mark.exact { color: var(--ok); }
.rule-mark.mis { color: var(--mis); }
.rule-mark.none { color: var(--paper-faint); }

/* ---------- 游戏页 ---------- */
/* 浮层玻璃顶栏：悬浮在全屏全景顶部。 */
.game-topbar {
  position: absolute;
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  max-width: calc(100% - 28px);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 14px;
  background: rgba(18, 16, 14, 0.32);
  backdrop-filter: blur(2px) saturate(1.3);
  -webkit-backdrop-filter: blur(2px) saturate(1.3);
  border: 1px solid var(--line);
  border-radius: 999px;
  box-shadow: var(--shadow);
  z-index: 20;
}
.game-topbar .btn.ghost {
  color: rgba(243, 232, 216, 0.92);
  border-color: rgba(201, 189, 167, 0.18);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}
.game-topbar .btn.ghost:hover {
  border-color: rgba(201, 164, 92, 0.34);
}
.bar-mid {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 15px;
  color: rgba(238, 228, 211, 0.84);
  letter-spacing: 0.05em;
  max-width: 46vw;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.28);
}
.collection-title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.style-id {
  flex: none;
  padding: 2px 7px;
  border: 1px solid rgba(201, 164, 92, 0.5);
  border-radius: 999px;
  color: var(--gold);
  background: rgba(201, 164, 92, 0.2);
  font-family: var(--sans);
  font-size: inherit;
  font-weight: 600;
  letter-spacing: 0;
  line-height: 1.3;
}
.style-id.style-animation {
  border-color: rgba(140, 193, 91, 0.62);
  background: rgba(78, 123, 47, 0.34);
  color: #c6eea9;
}
.style-id.style-geometric {
  border-color: rgba(73, 173, 190, 0.62);
  background: rgba(25, 111, 128, 0.34);
  color: #9de2ed;
}
.style-id.style-minecraft {
  border-color: rgba(178, 119, 74, 0.62);
  background: rgba(113, 70, 42, 0.38);
  color: #deb184;
}
.style-placeholder { visibility: hidden; }
.bar-right { text-align: right; }
.tries-info {
  font-family: var(--mono);
  font-size: 13px;
  color: rgba(225, 214, 196, 0.72);
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.24);
}

/* 全景：铺满整屏，作为背景主视觉。 */
.viewer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: 0;
  overflow: hidden;
  background: #000;
  border: none;
  z-index: 0;
}
/* 让 Pannellum 容器随父级全屏。 */
.viewer .pnlm-container, .viewer .pnlm-ui, .viewer .pnlm-render-container { width: 100% !important; height: 100% !important; }
.viewer-error { display: flex; align-items: center; justify-content: center; height: 100%; color: var(--paper-faint); }

/* 1:1 降级平铺图：可横向拖动 */
.flat-pan { width: 100%; height: 100%; overflow-x: auto; overflow-y: hidden; cursor: grab; scrollbar-width: none; }
.flat-pan::-webkit-scrollbar { display: none; }
.flat-pan.grabbing { cursor: grabbing; }
.flat-pan img { height: 100%; width: auto; max-width: none; display: block; user-select: none; }

/* ---------- 底部玻璃底板（悬停展开）---------- */
/* 毛玻璃只落在「有内容的输入卡片」上（.dock-rail），左右留白完全透明、直接透出全景。
   - .dock-rail：玻璃卡片和横向滚动视口；
   - .dock-anchor：横向内容，内部 card-grid 是 3 行 x 2 列；
   默认收起（只露输入行），鼠标悬停才展开历史（可滚动）。 */
.dock {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  background: transparent; /* 容器透明：玻璃只在居中卡片上 */
  pointer-events: none;
  z-index: 10;
}
.dock.layout-pending {
  visibility: hidden;
}
.dock-inner {
  display: flex;
  flex-direction: column;
  align-items: flex-start; /* JS 用真实 margin-left 固定基准行左边界，避免滚动视口被视觉平移。 */
  justify-content: flex-end;
  flex: 1;
  min-height: 0;
  gap: 0;
  padding: 0;
  pointer-events: none;
}
/* 居中的毛玻璃卡片：只盖住「居中有字的那一列」，两侧留白完全透明。
   历史（可滚）与当前输入行都装在这张卡片里，玻璃由它统一提供。
   横向滚动挂在整张卡片上，保证历史、输入行、底部文案一起移动。 */
.dock-rail {
  position: relative;
  display: flex;
  flex-direction: column;
  width: var(--rail-width, max-content);
  max-width: none;
  margin-left: var(--rail-left, 0px);
  padding: 0;
  box-sizing: border-box;
  background: rgba(18, 16, 14, 0.32);
  backdrop-filter: blur(2px) saturate(1.3);
  -webkit-backdrop-filter: blur(2px) saturate(1.3);
  border: 1px solid var(--line);
  border-radius: 18px 18px 0 0; /* 下角不圆：与屏幕底边贴合 */
  box-shadow: none;
  overflow-x: hidden;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: rgba(201, 164, 92, 0.55) transparent;
  pointer-events: auto;
  transition: background 0.25s ease;
}
.dock-rail.has-x-scroll { overflow-x: auto; }
.dock-rail::-webkit-scrollbar { height: 8px; }
.dock-rail::-webkit-scrollbar-track { background: transparent; }
.dock-rail::-webkit-scrollbar-thumb { background: rgba(201, 164, 92, 0.55); border-radius: 999px; }
.dock.layout-pending .dock-rail,
.dock.layout-pending .dock-scroll,
.dock:not(.layout-ready) .dock-rail,
.dock:not(.layout-ready) .dock-scroll {
  transition: none !important;
}
.dock-anchor {
  width: var(--anchor-width, max-content);
  max-width: none;
  overflow-x: hidden;
  overflow-y: hidden;
  padding-left: var(--dock-pad-left);
  padding-right: var(--dock-pad-right);
  box-sizing: border-box;
  display: block;
  position: relative;
  cursor: text;
}
.dock:has(.dock-rail:hover) .dock-rail,
.dock:focus-within .dock-rail,
.dock.history-pinned .dock-rail {
  background: rgba(18, 16, 14, 0.42);
}

/* 历史区「钉住」按钮：浮于卡片右上角，钉住后历史不折叠。仅在历史展开（悬停/聚焦/钉住）
   时显形，避免折叠态与输入行重叠；abspos 锚定 .dock-rail，不随横向滚动移动。 */
.hist-pin {
  position: absolute;
  top: 5px;
  right: 8px;
  z-index: 3;
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: rgba(18, 16, 14, 0.55);
  color: var(--paper-dim);
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, color 0.2s ease, border-color 0.2s ease, background 0.2s ease, transform 0.15s ease;
}
.hist-pin svg { width: 14px; height: 14px; transition: transform 0.2s ease; }
.hist-pin:hover {
  color: var(--gold);
  border-color: rgba(201, 164, 92, 0.5);
  background: rgba(201, 164, 92, 0.16);
}
.hist-pin:active { transform: scale(0.94); }
.dock.has-history:has(.dock-rail:hover) .hist-pin,
.dock.has-history:focus-within .hist-pin,
.dock.history-pinned .hist-pin {
  opacity: 1;
  pointer-events: auto;
}
/* 钉住态：金色高亮 + 图标旋转，表「已钉住」。 */
.dock.history-pinned .hist-pin {
  color: var(--gold);
  border-color: rgba(201, 164, 92, 0.6);
  background: rgba(201, 164, 92, 0.2);
}
.dock.history-pinned .hist-pin svg { transform: rotate(35deg); }

/* 历史区（虚线之上）：自身透明，玻璃由外层 .dock-rail 提供。
   默认折叠（max-height 0、透明），悬停展开并可滚动。
   注意：折叠态用 0 纵向 padding（border-box 下 padding 仍会撑高，会破坏 max-height:0
   的折叠），悬停时再加纵向留白。scrollbar-gutter: stable 让滚动条始终预留空间，使历史
   行与下方当前行对齐。 */
.dock-scroll {
  grid-column: 1;
  grid-row: 1;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  width: 100%;
  padding: 0;
  margin-top: 0; /* 折叠态贴顶，不留空隙 */
  overflow-x: hidden;
  overflow-y: auto;
  max-height: 0;
  opacity: 0;
  background: transparent; /* 全透明：不留玻璃，直接露出全景 */
  scrollbar-width: thin;
  scrollbar-color: transparent transparent; /* 滚动条默认透明：展开过渡中不闪现（见下 .scroll-ready） */
  scrollbar-gutter: stable;
  transition: max-height 0.28s ease, opacity 0.22s ease, padding 0.28s ease, margin 0.28s ease;
}
/* 展开（悬停 或 输入聚焦/打字时）：高度展开到约 3.5 行。滚动条不在此刻出现，
   等 .scroll-ready（高度过渡结束后由 JS 加）再显形，避免短历史闪一下滚动条又消失。 */
.dock:has(.dock-rail:hover) .dock-scroll,
.dock:focus-within .dock-scroll,
.dock.history-pinned .dock-scroll {
  max-height: calc(var(--cell) * 1.14 * 3.5 + 44px);
  opacity: 1;
  padding: 14px 0 12px; /* 展开才有留白：滚动区上下各留一点 margin，行不贴卡片边 */
  margin-top: 18px; /* 下移滚动条，让它避开卡片顶部 18px 圆角（padding 移不动 gutter，只能用 margin） */
}
/* 高度过渡结束后才让滚动条显形：短历史展开时不会闪一下滚动条又消失。 */
.dock.scroll-ready .dock-scroll { scrollbar-color: rgba(201, 164, 92, 0.6) transparent; }
.dock-scroll::-webkit-scrollbar { width: 8px; }
.dock-scroll::-webkit-scrollbar-track { background: transparent; }
.dock-scroll::-webkit-scrollbar-thumb { background: transparent; border-radius: 8px; } /* 默认透明：展开过渡中不闪现 */
.dock.scroll-ready .dock-scroll::-webkit-scrollbar-thumb { background: rgba(201, 164, 92, 0.6); }
.dock.scroll-ready .dock-scroll::-webkit-scrollbar-thumb:hover { background: rgba(201, 164, 92, 0.8); }
/* 历史为空时的占位提示。 */
.dock-empty {
  width: 100%;
  color: rgba(235, 225, 208, 0.78);
  font-size: 14px;
  letter-spacing: 0.06em;
  padding: 14px 0;
  text-align: center;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.52);
}
.base-empty {
  padding: 0;
  box-sizing: border-box;
}
/* 新历史行入场（仅新追加的行会播放，已有的不重建、不重播）。 */
.dock-scroll .g-row { animation: rowIn 0.25s ease; }
.history-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
@keyframes rowIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* 当前输入行区（虚线之下）：自身透明，玻璃由外层 .dock-rail 提供。
   border-top 虚线即分隔历史与输入的那条线（折叠/无历史时收掉，避免孤零零一条）；
   虚线下方留白较大（padding-top 16px）。
   对齐技巧：历史区 .dock-scroll 的滚动条经 scrollbar-gutter:stable 在右侧恒预留 8px，
   使历史行整体左移 4px；此处把右内边距比左多 8px（右 54 / 左 46），让当前行也左移 4px，
   二者严格对齐（deltaCell≈0）。不设 overflow：行末「↵」落在右侧内边距内（约 54px 足够），
   自然位于玻璃卡片里、不再溢出框外，也不会被裁剪。 */
.card-grid {
  display: grid;
  grid-template-columns: max-content max-content;
  grid-template-rows: auto auto auto;
  column-gap: 6px;
  width: max-content;
}
.base-column {
  grid-column: 1;
  grid-row: 2;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  width: var(--base-row-width, max-content);
  box-sizing: border-box;
  padding: 0;
  border-top: 1px dashed transparent;
  background: transparent;
  transition: border-color 0.25s ease, padding 0.28s ease;
}
/* 历史展开且有记录时：输入行与历史之间留出间隔 + 虚线分隔，不再紧挨着。
   has-history 由 JS 在 syncHistoryRows 按 wanted>0 切换；空历史/折叠态不画线、不留白。
   base-column 与 right-extension 同步下移 14px：否则 extra 格/↵ 不随 base 行下移，
   会比正常输入格偏高（right-extension 装 extra 格 + 提交按钮）。 */
.dock.has-history:has(.dock-rail:hover) .base-column,
.dock.has-history:focus-within .base-column,
.dock.has-history.history-pinned .base-column,
.dock.has-history:has(.dock-rail:hover) .right-extension,
.dock.has-history:focus-within .right-extension,
.dock.has-history.history-pinned .right-extension {
  border-top-color: var(--line);
  padding-top: 14px;
}
.prompt-zone {
  grid-column: 1;
  grid-row: 3;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  width: var(--base-row-width, max-content);
  padding: 6px 0 20px; /* 底部给整卡片横向滚动条留位置 */
  box-sizing: border-box;
}
.card-grid {
  padding-top: 16px;
  border-top: 1px dashed var(--line);
  transition: border-color 0.25s ease;
}
.right-extension {
  grid-column: 2;
  grid-row: 2;
  display: flex;
  align-items: center;
  gap: 6px;
  width: max-content;
  box-sizing: border-box;
  padding-top: 0;
  border-top: 1px dashed transparent;
  transition: border-color 0.25s ease, padding 0.28s ease;
}
/* 折叠态（无历史可分隔）时收掉虚线，避免卡片顶部悬一条孤线。 */
.dock:not(:has(.dock-rail:hover)):not(:focus-within):not(.history-pinned) .card-grid { border-top-color: transparent; }
.dock.solved-mode .card-grid {
  padding-top: 12px;
  border-top-color: transparent;
}
.dock.solved-mode:not(:has(.dock-rail:hover)):not(:focus-within):not(.history-pinned) .dock-scroll {
  max-height: 0;
  opacity: 0;
  padding-top: 0;
  padding-bottom: 0;
  margin-top: 0;
}


/* 提示文字在极透玻璃上加投影，保证可读。 */
.hint-line,
.submit-tip {
  width: 100%;
  margin-left: 0;
  margin-right: 0;
  padding-left: 0;
  padding-right: 0;
  box-sizing: border-box;
  text-align: center;
  color: rgba(239, 229, 212, 0.86);
  font-size: 14px;
  letter-spacing: 0.06em;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.62), 0 0 10px rgba(0, 0, 0, 0.18);
}
.hint-line[hidden], .submit-tip[hidden] { display: none !important; }

/* ---------- Wordle 网格 ----------
   --cell / --cell-sep 由 JS 按本题格子数注入到 .dock-inner（历史区与当前行的共同
   祖先），保证两者继承同一组尺寸、整行不换行。这里给默认值兜底。 */
.dock-inner {
  --cell: 56px;
  --cell-sep: 22px;
  --dock-pad-left: clamp(10px, 4vw, 46px);
  --dock-pad-right: clamp(12px, 5vw, 54px);
}
.g-row { position: relative; display: flex; flex-wrap: nowrap; justify-content: center; gap: 6px; width: max-content; max-width: none; }
.dock-scroll .g-row { justify-content: flex-start; }
.dock-anchor .g-row { justify-content: flex-start; }
.g-row.solved-row { cursor: default; }

.g-cell {
  position: relative;
  width: var(--cell); height: calc(var(--cell) * 1.14);
  flex: 0 0 auto;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  border: 1.5px solid var(--line);
  border-radius: 8px;
  background: var(--ink-2);
  padding-bottom: 4px;
  transition: background 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease, transform 0.12s ease;
}
.g-cell.sep {
  width: var(--cell-sep); border: none; background: transparent;
  justify-content: center; color: var(--paper-faint);
}
.sep-mark {
  font-size: 21px;
  opacity: 0.82;
  color: rgba(234, 223, 205, 0.9);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.48);
}
.g-cell.cell-filled { background: var(--ink-3); }
.g-cell.cell-pass { background: var(--ok-bg); border-color: var(--ok); }
.g-cell.cell-extra {
  background: rgba(76, 24, 20, 0.42);
  border-color: rgba(197, 68, 59, 0.52);
  box-shadow: inset 0 0 0 1px rgba(197, 68, 59, 0.08);
}
.g-cell.cell-extra .py-seg,
.g-cell.cell-extra .py-tone-mark {
  color: rgba(213, 107, 95, 0.72);
}
.g-cell.cell-extra .cell-han {
  color: rgba(243, 234, 216, 0.94);
}

/* 当前输入行汉字格：点击可定位光标（指针提示为文本光标）。 */
.g-row.current .g-cell.han { cursor: text; }
/* 待输入格压深底色 + 加重描边：毛玻璃底板半透时，深色实格与玻璃几乎同色、边线又极淡，
   会“看不出哪里是输入位置”。把当前行未激活的输入格压成更深的实色并加重边线，让输入位置
   在全景上清晰可辨；光标格（.cursor）走自己的金色态，故排除。 */
.g-row.current .g-cell.han:not(.cursor) {
  background: #15110b;
  border-color: rgba(201, 189, 167, 0.36);
}
.g-row.current .g-cell.han:hover {
  border-color: rgba(201, 164, 92, 0.5);
}

.cell-py {
  display: flex; align-items: center; justify-content: center;
  gap: 0; height: calc(var(--cell) * 0.32); line-height: 1;
  padding-top: calc(var(--cell) * 0.08); /* 给叠加调号留顶部空间，避免被裁 */
}
.py-row { display: inline-flex; align-items: baseline; }
.py-seg {
  font-family: var(--mono); font-size: calc(var(--cell) * 0.21); letter-spacing: -0.02em;
  color: var(--paper-dim);
}
/* 承调元音：相对定位容器，调号绝对定位叠在其上方中央（声调标在正确元音上）。 */
.py-vowel {
  position: relative;
  display: inline-flex;
  align-items: baseline;
  line-height: 1;
}
.py-tone-mark {
  position: absolute;
  top: calc(var(--cell) * -0.1);
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--mono);
  font-size: calc(var(--cell) * 0.22);
  line-height: 1;
  color: var(--paper-dim);
  pointer-events: none;
}
.cell-han {
  font-size: calc(var(--cell) * 0.54); line-height: 1; font-weight: 500; color: var(--paper);
  margin-top: 2px;
}
.cell-empty { display: block; height: calc(var(--cell) * 0.54); }

/* 状态色。声母/韵母/声调未命中（none）只留灰、不画删除线，与 wechat 端一致。 */
.c-exact { color: var(--ok) !important; }
.c-mis { color: var(--mis) !important; }
.c-none { color: var(--none) !important; }
.c-none-char { color: var(--paper-faint) !important; }
.cell-pass .cell-han, .cell-pass .py-seg, .cell-pass .py-tone-mark { color: #eafff0 !important; }

/* ---------- 直接在格子里输入 ---------- */
.hint-line,
.submit-tip { align-self: stretch; }
.base-row {
  justify-content: flex-start;
}
/* 隐形输入框：铺满网格区，文字透明（真正显示靠格子），
   仅用于接收键盘 / 输入法（IME），让中文候选浮窗出现在打字处附近。 */
.cell-input {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: transparent;
  caret-color: transparent;
  font-family: var(--serif);
  /* 字号放在当前输入行附近，让 IME 候选浮窗贴近打字位置；文字本身透明不可见 */
  font-size: 24px;
  text-align: center;
  outline: none;
  /* 让点击/拖动落到下层网格之上，但又不挡视觉 */
  z-index: 2;
}
.cell-input::selection { background: transparent; }
/* 隐形 input 只负责键盘输入与承载 IME 候选浮窗，不拦截鼠标：
   pointer-events:none 让点击/拖选穿透到下层格子，从而能精确定位光标、
   并让「选中复制」落在格子大字上（对齐美观）。键盘焦点由 mousedown 主动给。 */
.cell-input {
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
}
.dock-anchor.input-off .cell-input { display: none; }

/* 历史猜测行：只让「汉字 + 标点」可选中复制，得到干净诗句；
   拼音/声调等辅助标注不参与选区（否则复制出来会混进字母）。 */
.g-row { user-select: none; -webkit-user-select: none; }
.g-row:not(.current) .cell-han,
.g-row:not(.current) .sep-mark {
  user-select: text;
  -webkit-user-select: text;
}
/* 当前输入行的已输入汉字也可选中复制（拖选由其上的隐形 input 提供，
   但格子大字同样标记可选，作为双保险，仍排除拼音/声调辅助字符）。 */
.g-row.current .cell-han {
  user-select: text;
  -webkit-user-select: text;
}

/* 光标位置 = 「当前待填格」的高亮（不再用竖线 caret，靠格子本身表达）。
   不在输入（隐形 input 失焦）时金框变暗；正在输入时金框正常亮。
   底色用实色深金（而非半透）：半透金色会与玻璃背景同色，看不出“输入位置在哪”。 */
.g-cell.cursor {
  border-color: rgba(201, 164, 92, 0.35); /* 不在输入：暗金边 */
  background: #2c2113;
}
/* 正在输入时光标格保持常亮，并带柔和闪烁的金色光晕（像文本光标呼吸）；
   hover 也写一份（且排在 hover 规则之后），否则更高权重的 .g-row.current .g-cell.han:hover
   会把它压成半透明、反而变暗。 */
.dock-anchor.focused .g-cell.cursor,
.dock-anchor.focused .g-cell.cursor:hover {
  border-color: var(--gold); /* 正在输入：正常亮 */
  background: #2c2113;
  animation: cursorGlow 1.1s ease-in-out infinite;
}
/* 光标格的光晕：聚焦打字时柔和闪烁（明暗呼吸），像文本光标。 */
@keyframes cursorGlow {
  0%, 100% { box-shadow: 0 0 3px 0 rgba(201, 164, 92, 0.15); }
  50% { box-shadow: 0 0 12px 2px rgba(201, 164, 92, 0.5); }
}

/* 已填满：行末的「可提交」标记（代替「光标在末尾」的表达）。
   绝对定位浮在行右侧外缘，不参与 flex 居中，避免挤动汉字格的对齐。 */
.row-end-mark {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  height: calc(var(--cell) * 0.9);
  min-width: calc(var(--cell) * 0.52);
  padding: 0 5px;
  border-radius: 8px;
  border: 1.5px solid var(--gold); /* 实线，更像可点按钮 */
  color: var(--gold);
  font-family: var(--mono);
  font-size: calc(var(--cell) * 0.4);
  line-height: 1;
  background: rgba(201, 164, 92, 0.12);
  white-space: nowrap;
  pointer-events: auto; /* 可点击：当作提交按钮 */
  cursor: pointer;
  user-select: none;
  transition: background 0.15s ease, transform 0.15s ease, border-color 0.15s ease;
}
.row-end-mark.ready:hover {
  background: rgba(201, 164, 92, 0.32);
  border-color: var(--gold);
  transform: scale(1.06);
}
.row-end-mark.ready:active {
  background: rgba(201, 164, 92, 0.44);
  transform: scale(0.96);
}
.row-end-mark.ready:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
.row-end-mark.disabled {
  opacity: 0.35;
  cursor: default;
  pointer-events: none;
}
.row-end-mark.cursor {
  opacity: 1;
  border-color: rgba(201, 164, 92, 0.7);
  background: #2c2113;
}
.dock-anchor.focused .row-end-mark.cursor {
  border-color: var(--gold);
  background: #2c2113;
  box-shadow: 0 0 12px 2px rgba(201, 164, 92, 0.5);
}

.submit-tip {
  text-align: center;
  margin: 0;
  color: rgba(230, 219, 201, 0.78);
  font-size: 13px;
  letter-spacing: 0.05em;
}
.submit-tip kbd,
.hint-line kbd {
  font-family: var(--mono);
  font-size: 12px;
  background: rgba(77, 61, 39, 0.72);
  border: 1px solid rgba(201, 164, 92, 0.3);
  border-radius: 5px;
  padding: 1px 7px;
  color: rgba(243, 233, 216, 0.9);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.28);
}

/* ---------- 结算（居中浮层遮罩，全景隐约可见）---------- */
.result-area {
  display: none; /* 默认隐藏，由 .show 显示 */
}
.result-area.show {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  position: fixed;
  inset: 0;
  z-index: 50;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  animation: rise 0.3s ease;
  overflow-y: auto;
}
.result-area.show.pinned {
  align-items: flex-start;
  justify-content: flex-end;
  padding: 82px 18px 18px;
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  pointer-events: none;
  overflow: visible;
}
.result-panel {
  background: linear-gradient(160deg, var(--ink-2), var(--ink));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 26px 24px;
  box-shadow: var(--shadow);
  text-align: center;
  width: 100%;
  max-width: 580px;
  max-height: 86dvh;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(201, 164, 92, 0.5) transparent;
}
.result-area.show.pinned .result-panel {
  width: min(420px, calc(100vw - 36px));
  max-width: none;
  max-height: min(74dvh, 680px);
  padding: 18px 18px 16px;
  text-align: left;
  background: rgba(26, 23, 20, 0.84);
  backdrop-filter: blur(18px) saturate(1.15);
  -webkit-backdrop-filter: blur(18px) saturate(1.15);
  pointer-events: auto;
}
.result-panel::-webkit-scrollbar { width: 8px; }
.result-panel::-webkit-scrollbar-thumb { background: rgba(201, 164, 92, 0.4); border-radius: 8px; }
@keyframes rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
.result-panel.win { border-color: var(--ok); }
.result-panel.lose { border-color: rgba(197, 68, 59, 0.5); }
.verdict { font-size: 20px; font-weight: 600; letter-spacing: 0.08em; margin-bottom: 8px; }
.win .verdict { color: var(--ok); }
.lose .verdict { color: var(--cinnabar-soft); }
.answer-line { font-size: 24px; color: var(--paper); margin-bottom: 20px; letter-spacing: 0.05em; line-height: 1.5; }

.poem-card {
  text-align: center;
  border-top: 1px solid var(--line);
  padding-top: 18px;
  margin: 0 auto;
  max-width: 600px;
}
.poem-title { margin: 0 0 4px; font-size: 22px; font-weight: 600; color: var(--gold); letter-spacing: 0.08em; }
.poem-meta { font-size: 14px; color: var(--paper-dim); margin-bottom: 16px; }
.poem-body { line-height: 2; font-size: 17px; color: var(--paper-dim); }
.poem-line { margin: 0; transition: color 0.2s ease; }
.poem-line.hot { color: var(--paper); background: rgba(197, 68, 59, 0.14); border-radius: 4px; }
.poem-ctx { margin-top: 16px; font-size: 13px; color: var(--paper-faint); letter-spacing: 0.05em; }

.result-actions { display: flex; gap: 12px; justify-content: center; margin-top: 24px; flex-wrap: wrap; }
.result-area.show.pinned .verdict,
.result-area.show.pinned .answer-line,
.result-area.show.pinned .poem-card {
  text-align: left;
}
.result-area.show.pinned .answer-line {
  font-size: 20px;
  margin-bottom: 14px;
}
.result-area.show.pinned .poem-card {
  padding-top: 14px;
}
.result-area.show.pinned .poem-title {
  font-size: 18px;
}
.result-area.show.pinned .poem-meta,
.result-area.show.pinned .poem-body,
.result-area.show.pinned .poem-ctx {
  font-size: 13px;
  line-height: 1.8;
}
.result-area.show.pinned .result-actions {
  justify-content: flex-start;
  margin-top: 18px;
}

/* ---------- Toast ---------- */
.toast {
  position: fixed; left: 50%; bottom: 40px; transform: translateX(-50%) translateY(20px);
  background: var(--ink-3); color: var(--paper);
  border: 1px solid var(--line); border-radius: 999px;
  padding: 10px 22px; font-size: 15px;
  opacity: 0; pointer-events: none; transition: opacity 0.25s ease, transform 0.25s ease;
  z-index: 50; box-shadow: var(--shadow);
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ---------- 抖动 ---------- */
.shake { animation: shake 0.42s cubic-bezier(0.36, 0.07, 0.19, 0.97) both; }
@keyframes shake {
  10%, 90% { transform: translateX(-1px); }
  20%, 80% { transform: translateX(2px); }
  30%, 50%, 70% { transform: translateX(-4px); }
  40%, 60% { transform: translateX(4px); }
}

/* ---------- 响应式 ---------- */
@media (max-width: 560px) {
  .app-title { font-size: 32px; }
  /* 格子尺寸由 JS 按容器宽度自适应，这里不再写死，避免长句换行。 */
  .answer-line { font-size: 20px; }
  .entry-panel { padding: 22px 18px 18px; }
  .bar-mid { font-size: 13px; max-width: 38vw; }
  .style-id { padding: 1px 6px; }
  .game-topbar { gap: 8px; padding: 7px 11px; }
  .style-id.no-tries { position: absolute; right: 0; }
  .result-area.show.pinned {
    padding: 72px 12px 12px;
  }
  .result-area.show.pinned .result-panel {
    width: calc(100vw - 24px);
  }
}
/* 低矮视口：把底板抬高一点，给当前打字行留够空间。 */
@media (max-height: 700px) {
  .dock { height: clamp(320px, 54dvh, 560px); }
}
