/* =========================================================
   《转生成为栗子球》Demo — 视觉系统
   所有颜色 / 文字 / 坐标来自 theme.json，本文件只负责“怎么画”
   ========================================================= */

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: #000;
  overflow: hidden;
  font-family: var(--font);
  -webkit-user-select: none;
  user-select: none;
  overscroll-behavior: none;
}

#viewport {
  position: fixed;
  inset: 0;
  overflow: hidden;      /* 舞台按宽度贴合后高度会超出，超出的部分在这里被裁掉 */
  background: #0b0b0b;
}

/* 定位与缩放由 fitStage() 写进 transform：
   translate(水平居中偏移, -裁切量) scale(缩放)。
   transform-origin 必须是左上角，否则 translate 与 scale 的先后会互相干扰。 */
#stage {
  position: absolute;
  left: 0;
  top: 0;
  width: 750px;
  height: 1624px;
  transform-origin: 0 0;
  background: var(--c-yellow);
  overflow: hidden;
  color: var(--c-ink);
  font-family: var(--font);
  font-weight: 900;
  letter-spacing: 1px;
}

/* 全局黑色外框（原型图每屏都有的一圈粗黑边） */
#stage::after {
  content: '';
  position: absolute;
  inset: 0;
  border: 6px solid var(--c-ink);
  pointer-events: none;
  z-index: 200;
}

#scenes, #overlays { position: absolute; inset: 0; }
/* overlays 只是弹窗/提示的挂载容器，自身必须放行鼠标命中，否则整页按钮都点不了 */
#overlays { pointer-events: none; }
#overlays > * { pointer-events: auto; }

/* ---------------------------------------------------------
   场景与背景
   --------------------------------------------------------- */
.scene {
  position: absolute;
  inset: 0;
  overflow: hidden;
}
.scene.enter { animation: sceneIn .26s cubic-bezier(.2, .8, .3, 1) both; }
@keyframes sceneIn {
  from { transform: translateY(26px); }
  to   { transform: translateY(0); }
}

.bg { position: absolute; inset: 0; background: var(--c-yellow); }
.bg .halftone {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle at 50% 50%, rgba(20, 20, 20, .16) 1.5px, transparent 1.7px);
  background-size: 10px 10px;
  pointer-events: none;
}
.bg .burst {
  position: absolute;
  inset: 0;
  background: url(../assets/pattern/burst.svg) center center / 100% 100% no-repeat;
}
/* 栗子球剪影水印：铺在黄底上，位于射线之下 */
.bg .watermark {
  position: absolute;
  inset: 0;
  background: url(../assets/pattern/watermark.svg) center top / 1325px 1855px no-repeat;
  pointer-events: none;
}

/* ---------------------------------------------------------
   通用：黑标签条
   --------------------------------------------------------- */
.tag {
  position: absolute;
  display: flex;
  align-items: center;
  background: var(--c-ink);
  color: #fff;
  font-weight: 900;
  font-size: 38px;
  letter-spacing: 3px;
  padding: 0 46px 0 26px;
  clip-path: polygon(0 0, 100% 0, 93% 100%, 0 100%);
  transform: rotate(-2.2deg);
  white-space: nowrap;
}

/* ---------------------------------------------------------
   通用：做旧贴纸按钮
   --------------------------------------------------------- */
.btn {
  position: absolute;
  display: block;
  padding: 0;
  margin: 0;
  border: 6px solid var(--c-ink);
  border-radius: 12px;
  background: var(--c-paper);
  cursor: pointer;
  box-shadow: 0 9px 0 var(--c-ink);
  transition: transform .07s ease, box-shadow .07s ease;
  font-family: inherit;
  touch-action: manipulation;
}
.btn .face {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  border-radius: 5px;
  overflow: hidden;
}
/* 网点只落在按钮左右两端，中间留白给文字（对齐原型图） */
.btn .face::before,
.btn .face::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  width: 104px;
  background-image: radial-gradient(circle at 50% 50%, rgba(20, 20, 20, .3) 1.6px, transparent 1.9px);
  background-size: 11px 11px;
  pointer-events: none;
}
.btn .face::before { left: 0; }
.btn .face::after { right: 0; }
.btn .label {
  position: relative;
  z-index: 3;
  color: var(--c-ink);
  font-weight: 900;
  font-size: 44px;
  letter-spacing: 4px;
  line-height: 1;
}
.btn::before, .btn::after {
  content: '';
  position: absolute;
  width: 42px;
  height: 42px;
  background: var(--c-accent);
  pointer-events: none;
}
.btn::before { left: -6px; top: -6px; clip-path: polygon(0 0, 100% 0, 0 100%); }
.btn::after  { right: -6px; bottom: -6px; clip-path: polygon(100% 100%, 0 100%, 100% 0); }
.btn:active { transform: translateY(7px); box-shadow: 0 2px 0 var(--c-ink); }
.btn:focus-visible { outline: 4px dashed var(--c-ink); outline-offset: 8px; }
.btn.disabled, .btn.off {
  opacity: .42;
  filter: grayscale(.5);
  pointer-events: none;
}

/* 右上角小图标（? / ⚙） */
.icon-sticker {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 5px solid var(--c-ink);
  border-radius: 8px;
  background: var(--c-paper);
  box-shadow: 4px 5px 0 var(--c-ink);
  cursor: pointer;
  transition: transform .07s ease, box-shadow .07s ease;
  overflow: hidden;
}
.icon-sticker::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  width: 26px;
  height: 26px;
  background: var(--c-accent);
  clip-path: polygon(0 0, 100% 0, 0 100%);
}
.icon-sticker:active { transform: translateY(4px) !important; box-shadow: 0 1px 0 var(--c-ink); }
.icon-sticker .glyph { font-size: 44px; font-weight: 900; line-height: 1; }
.icon-sticker svg { width: 46px; height: 46px; display: block; }

/* 皮肤工坊：元素被换成上传图片后，图片接管整块元素 */
.studio-img { max-width: 100%; max-height: 100%; object-fit: cover; display: block; }
/* 整块覆盖：图片铺满元素，原内容整体隐藏（按钮、图标按钮、标签、卡格都走这条）
   不要再给 .icon-sticker / .back-btn 单独锁尺寸 —— 那样只会换掉里面的箭头，
   按钮底框还留着，等于「分层替换」。用户要的是整个按钮当成一张图。 */
.has-studio-img { overflow: hidden; }
.has-studio-img > .studio-img {
  width: 100% !important;
  height: 100% !important;
  max-width: none !important;
  max-height: none !important;
  display: block;
}
/* 「去框线」：保留元素尺寸，只把自带的边框 / 底色 / 投影清掉，方便放整张图。
   border-width 归零，图片才能真的铺到最外沿，而不是缩在原来那圈黑边里。 */
.studio-img-bare {
  border-width: 0 !important;
  border-color: transparent !important;
  background-color: transparent !important;
  box-shadow: none !important;
  /* 页签这类元素自带的斜切外形也算「原图的一部分」，换图后不该再把新图裁一刀 */
  clip-path: none !important;
}
.studio-img-bare::before, .studio-img-bare::after { display: none !important; }
/* 整块覆盖时，元素自带的那张背景图 / 内边距也要撤掉：
   padding 留着的话图片只有内容盒那么宽，四周会空出原来那一圈「底色」。 */
.has-studio-img.studio-img-bare {
  background-image: none !important;
  padding: 0 !important;
}

/* 整块换图后浮在图上的文字层（主按钮 / 页签 / 弹窗标题 / 回合徽章）：
   图归图、字归字 —— 文字收进这层浮层，默认水平垂直居中；
   位置由皮肤工坊「文字对齐」调（九宫对齐 + 像素微调）。
   pointer-events:none 不挡按钮点击。 */
.studio-img-label {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

/* ---- 图层拆分：卡片 / 记录条的「底图」与「文字」分开 ----
   换图只落到 data-img-host 这一层，文字层保持原样，可以单独改字。 */
.cell-art, .li-art {
  position: absolute;
  inset: 0;
  display: block;
  border-radius: inherit;
  overflow: hidden;
  z-index: 0;
}
/* 卡面＝两张整张卡图：常态 card_n（白卡 + 黑框 + 椭圆），选中 card_s（黑块 + 黄✓）。
   边框、椭圆、✓ 全在图里，CSS 一道框都不画 —— 这样永远不会出现「自绘的框压在图上」。
   切图只换 background-image，卡格尺寸、位置、卡名文字一个字都不动。 */
.cell-art {
  border-radius: 22px;
  background-image: url("data:image/png;base64,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");
  background-size: 100% 100%;
  background-repeat: no-repeat;
  background-position: center center;
}
.card-cell.sel .cell-art { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUoAAAGfCAYAAAA52puZAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAOdEVYdFNvZnR3YXJlAEZpZ21hnrGWYwAAE3FJREFUeAHt3b9vlHl+wPEv7O4td7dazFVXRGIoIkXXYLotIjHuckoBK6VJhfkLgCI1dpWTUqzpLk0wVZIKu4hOW2GUJh3e5pTOg5TiqgVW+4v95cxnzLDDeOyP53me+WVeL+m7tge8jDG8+X6f7/M8c6bM1lJ3LL8aF7uj9er98up94O3R6Y7nr8Zudzx99Xb31WMzc6ZMX7s7rpWDILYLQC5iudMd26/eTtW0QtkuB3FcLQezSICqYna51R0PypSiOelQtrvjbjFzBCaj0x3r3bFZJmhSobzeHZ8UxxmB6eiUCQbzbGlWuzsedcfDIpLA9LS643537JWDQ3yNeqc0I447/nN3/LEIJDA70aJY0ba647PS0G55E6Fsd8efuuPvCsB8iLNqIpgvysGOeS11Q3mrO/6j2MkG5k9/dhkelxrqbObE8YDVAjD/Ylb5cTnY9BlblVBGpWPDZrkALI5Od6yUCrEcN5QiCSyyTqkQy3FCOdFItlqtsry83Ht7+fLl148Bp9/z58974+nTp2V3d7d0Op3e2wnplDFjOU4on5QGI7m0tNQL440bN8r169d7HwP0RTh3dnbK9vZ22dra6n3coE53XCknPH3opKGMq2xulwbELDHiePv2bXEETmxzc7Osr6/3ZpsNiSnrlZP8xJOEMq7VXis1RSDv3r1bVldXC0BVDQdzozvuZD8pC2WrHFwSVEsE0gwSaFKDwVwtB3ciOtJxoYyqxXHJVqkoZpEPHz7sHYsEaFpE8ubNm71jmTXEccpYgneO+gnHXZkT125XviwxjkPGAVg718CkxCq1fzjv8ePKF9+cKwcb1UfOKo8KZascXJpYSSy1NzY2yrlz5wrApLXb7V40P/3001JRq/z80hOHHLX03isVl9wRybW1tQIwbXHcMpbiFcUS/FIZccrQqBnlaql4DbdIArMU+yE1ZpaxBH5ZRry8xKhQxk13x96evnXrVvnDH/5QAGbpo48+6r2teMwyjlX+a3d8O/jg8NJ7tRzcFWgssWHz5MkTp/8Ac2NlZaXqbni8pMTa4APDoYxrudtlTHt7e3a3gbkSpw5duXKlyqWP8QkXBh8YfM2cVqkQyTguKZLAvIkuffLJJ6WCWBq3Bx8YnFGOfSPeeCIxmwSYVxWX4Dvl4A5DPYMzynYZU8wmAeZZxU61y8Cm9pmBBx+VMZhNAoui4qwybpYRN814PaO8XsZkNgksihqzyp7+jHLs3W473cAiuXDhwrg74K93v2NGeWiHJxN3JBdJYJHErR7HFG3s3frsbKnw8g7Xrl0rAIvk6tWrpYLqoYw7dQAskv4dhsb0OpStcT4rltyW3cAiqnAT8Vb8J0J5eZzPcrdyYFFV6Fevj/3NnEn+QgBz4fLlseaFodfHsUPpDkHAoqpw2DCCtzT2McqLFy8WgEVUcX/l/NkxP8GMEnjrjB1KgLeNUAIkhBIgIZQACaEESAglQEIoARJCCZAQSoCEUAIkhBIgIZQACaEESAglQEIoARJCCZAQSoCEUAIkhBIgIZQACaEESAglQOLdMmPPnz8vOzs75fHjx6XT6fRGPAa8XeKlsPtjeXm5XL16tbTb7TIPZhLKCOGDBw/K1tZWL5IAg6INfdevX++NGzdulFnaH2c8evRov6pnz57tr62t7Xf/xdgf99c1DOPtHq1Wa39zc3O/jr29vSq/9sUy7idVDeXGxoZAGoZRe0QwI3jTDOXEl96xzP7444+PXWK/++67vfHOO++8HsDbpdux8tNPP5Uff/yx/PDDD+X777/vfTws9jEuXbpUuqvTcvfu3TINEw1lfEErKyu9t8POnDlTzp07V375y1/23geISdJ77733+uOI5jfffFNevnx56OdGKHd3d8v9+/d7G0CTNLHTg46KZEQx4njhwoXyq1/9SiSBI0U4P/jgg14v3n///UM/Hps+0ZlJnykzkVAeFclYXkf5BRIYx9mzZ3vB/PDDD3vvD4pZ5aRj2Xgo48mOimQss8+fP3/oiwQ4qViWR0di0jUoYnnnzp0yKY1XK57scCRjBvnrX/+6ANQVk62YWQ7HcnNzs9y7d69MQqOhjCcaY1B/wwagKXHobtQyPDZ4Rm0e19VoKNfX19/8n3e/CDNJYBIilrEMH9zviEN/wx1qQmOhjJnkcMnjiwCYlJiMxaG9QdGiOGbZ6K9TGjJc8djKt3EDTFoc3hs+Xhn3kmhSIyWLq25GbeAATMOoWWWTpws1EsrheptNAtMUpw0NH6vc3t4uTWlsRjlo1Bn0AJMUS/BBTd7CsXYo46Dp4LI7qj54rSbANAx3Z65C+fTp0zc+Hj6oCjAN0Z7B5XeTr5bQyIxykFukAbMQkRzeG2nq5PPaoRwutk0cYFaGJ2pzG0p3BQJmZbg/L168KE0w/QNICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAiSEEiAhlAAJoQRICCVAQigBEkIJkBBKgIRQAqfG/v7+Gx+fP3++NKF2KFut1hsf//jjjwVgFn766ac3Pl5aWipNqB3KixcvvvHx8BMFmJbhidrwRK6q2qFcXl5+4+Pvv/++AEzbDz/88MbSO2aTcxXKweltPFGxBKZteDY5PImro5HNnOEnFGUHmKZvv/32jY9v3LhRmtJIKIef0DfffONYJTA1MTkbnqC12+3SlEZCef369UPL75cvXxaAaRieTUYkmzo+GRoJZUTy9u3bbzxmVglMw3fffXdoYnb37t3SpMZOOL9169ahWeVXX31VACYlJmPDnYmZZJPL7tBYKEfNKqP0w1NigKZ8/fXXh1aujx49Kk1r9BLGmO4O74BH7R2vBJoWkRxuS6xsmzw22df4td4PHz48dNnQl19+aWYJNCYiGfsggyKQGxsbZRIaD2U82fv37x96PGaWw18YwDhimf3FF1+MjOQkltx9E7l7UJwuNCqW8a/As2fP3DgDGFsss58/f37oyr9+JCex5O57t0zI6upq7+3NmzffeDz+RYgv9v333++N9957rwAcJcIYM8hRl0ZPI5JhovejjFg+efJk5BcR/zrEFDpmmLEsj98E510C0YHY04gufP75571OjIpknAI0jUiGic0o+2IXPL6Y9fX1srm5eejH+78pg5s9Z8+6nzC8jU4yWYrN4tjdXltbK9O0P87oRm+/qu6O+H63/vvj/pqGYRgxurPI/b29vf2q4nMr/LoXpzp1i02e7hPtzTD7xzABjtO/mCUO401rqT3sTDko5onFE23q8qDY1NnZ2SmPHz8uu7u7vRGPAW+vCGMcsotx7dq1Ri9H7HQ65dKlS2VMrYkfozxO/IbELDNGX4RSLOHtNIvZ4knMNJSjRDybekEggCbYXgZICCVAQigBEkIJkJi7zRzqi1OuPvvsM6dcTUHs0vZPZ7l69eqhl2/mdBDKUyLOD7t3717vMlFhnJ74fQ9bW1uvH4uLKeKVSZt+OQJmx9J7wUUU4w5NcRJt3LRUJGcv/rFaWVnpfV/6IWWxCeUCe/DgQS+Qo242wuzF9yW+P3FDGBabUC6o+MsXSzwzyPkXd7m5c+dOYXEJ5QKKSE77FlPUE4dFYjnOYhLKBSOSiyvORhi+4z+LQSgXSOysiuRii+OWcXYCi0UoF0TsnjrOdTrEP3Z2wxeLUC6ImIX4y3U69E/pYnEI5QKIQE7qhd2ZjTheGYPFIJQLwF+o02l7e7uwGIRyATj434wb//DXpfVXH5R54XLTxSGUcy6W3XFjC+qJSG7+y9+WR//++7mJZUTS93YxCOWci7sAUU8/kiEiOU+x9P1dDEI558w46hmMZN88xdL3dzEI5ZxzSlB1oyLZNy+x9P1dDELJqXRcJPvmIZZCuRiEklPnJJHsm7djlswnoeRUGSeSfWJJRig5NapEsk8sOY5QcirUiSRkhJKF10QkO//3ZVn5xz/13sIwoWShiSTTIJQsLJFkWoSShSSSTJNQsnBEkmkTShaKSDILQkljln/3m7L04S/KpIgksyKUNCIiGSdsx5hELEWSWRJKautHMgI5+H5TRJJZE0pqGRXGJmMpkswDoaSy44LYRCxFknkhlFRykhDWiaVIMk+EkrGNE8AqsRRJ5o1QMpYq4Rvnc0SSeTR2KL0O8durzlL6JJ8rksyrsUP54sWLwtup/dFva23OHBdLkWQaqr5GkRklJ7bxb38u6/eelDpGxVIkmZaqE72xQ+l1iN9uaxu7jcZSJJmmqjPKd8uYvLwmEctw99aVUlXE8sl/Xav9GjUiyTiqTvTMKKmkiZmlSDJtdULZGecT4hjlzs5OgSZiWZVIMq5YDVcM5YtK51E+fvy4QJhFLEWSKmpM8J6PPaMMm5ubBfqmGUuRpKrt7e1SQe80nwjl0zKmmMJafjNoGrEUSaqKZm1tbZUKemv1s/13xvXgwYMCgyYZS5GkjoqRDL0TLystvUMsv518zrBJxFIkqevevXulonozyrC+vl5gWJOxFEnqikjWOP97J/7Tn1FWmhpubGw4r5KRmoilSFJXBDI6VcPrGWWotB0U7ty5U2CUOrEUSZoQq94as8mI5Otd7/4DlcTud431P6dclViKJE2IfZSapzK+PmG8H8rNUsPt27edLsSRxomlSNKEmEU2sIfyequ8H8qYXu6UGm7evOmGGRzpJLEUSZoQZ+OsrKzU7VGnDDRx8BLGyscpe//X7pNq4MlxikUsb/7Tf5fdP3/+xuPPv/iuF9Erf78tktTSUCTDzlE/sNQdz7pjv85otVr7e3t7+zRjdXV1v+73ZB7H0oe/2G9/9Nv95d/9ZqGed9Mj/r7QjGfPnu0vLy839b1ZLgMGZ5Sx/K41qwxmlpxEzCJ3/ucvh2aXUEW/Ow2drrhbhja4h+8etFkaEE/6ypUrLnMEJi42khuMZDh0Gs9wKHdKzU2dvjhW0F022uQBJiZ2thtewXbKiAnjqPtRNnpdYpzHFF+I2SXQlJhFXrp0qaytrZWGjezfqFDulIZmlX1R+5hdxhcmmEBV/WX2hPZBOuWIw49H3eH8ZpmAwWDWvFAdeEvEYbzoRT+QE7y45cjV9JlytLXuuFsmrLudX9rtdrl69WpptVq9j/lZHON1R/nTK/7M7+3tFX7Wf22beMmZeDulq/42yzETxONCGedVxqUUrTJl8YcnBgevGue+n6fX0tKSycErEcj4sz6DP++d7lgpx9yb97hQhnZ3PCoAp1fMJDeP+wnvlON1ykFM2wXg9NksJzjTJ5tR9sWssl0ATo9Od1wpJ7hx+UlDObPjlQAT0CnJcclBJw1laJWDmWWrACy2mEme+JrHs+XkOt3xcan4+joAcyI2b8a6MHycGWVfnMsQM8ulArBY0h3uUcaZUfZFiWPa2ikAiyFWwpUiGarMKPtaxTFLYP51ysFhw8r3YcvOozxO/0a/re74mwIwfyKOv++O/y011AlliFj+Z3FSOjB/4ga8sdz+S6mpztJ7WKtYigOz1z8euVUaUmUz5yid7rhUGr7xL8AYYhYZHWoskqHu0nuUne6Iu/NeKEOvZAYwITvlYBb5x+74tjSsyaX3KO1ycE/LdgFo3k45WMXulAmadCj7WuXgRsA3CkB9O2UKgeybVij7WuVgdnmjmGUC49npjsfdsVGmfCn1tEM5qFUOYhnjarFbDrwpYrhTDuK4WWZ4n4lZhnJYXDu+/Gq0uuPyq8cGB3B6PC8/x2/31fuflYMzaHbLHF0m/f8Q4bJISZf5CgAAAABJRU5ErkJggg=="); }
.li-art { border-radius: 19px; }
.card-cell .oval, .log-item .li-text { z-index: 2; }
.log-item .li-text { position: relative; display: block; }
/* 底板换图后，原来的气泡尖角 / 框线 / 底色一律让位，画面上只剩这张新图。
   拆出来的底板层（.cell-art / .li-art / .opt-art / .end-art / .ev-art）也挂这个类，
   否则它的 ::before / ::after 会压在插入的图片上面。 */
.has-split-art {
  border-width: 0 !important;
  background-color: transparent !important;
  /* 卡面默认是 background-image 画的整张卡（card_n / card_s），
     换了自定义卡图之后必须一起让位，否则透明处的底图会从新图下面透出来。 */
  background-image: none !important;
  box-shadow: none !important;
}
.has-split-art::before, .has-split-art::after { display: none !important; }

/* 点九切图（聊天气泡自适应高度）：底图由九宫格边框画，行内 padding 由脚本
   按四条切片边距逐条写入 —— 文字的上下左右留白正好等于气泡的圆角 + 描边，
   行高 = 文字行高 + 上下边距，一行矮、两行高，气泡跟着走。 */

/* 返回按钮 */
.back-btn {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 5px solid var(--c-ink);
  border-radius: 10px;
  background: var(--c-paper);
  box-shadow: 4px 5px 0 var(--c-ink);
  cursor: pointer;
  transition: transform .07s ease, box-shadow .07s ease;
}
.back-btn::before {
  content: '';
  position: absolute;
  right: -1px;
  bottom: -1px;
  width: 26px;
  height: 26px;
  background: var(--c-accent);
  clip-path: polygon(100% 100%, 0 100%, 100% 0);
}
.back-btn svg { width: 44px; height: 38px; display: block; }
.back-btn:active { transform: translateY(4px) rotate(9deg); box-shadow: 0 1px 0 var(--c-ink); }

/* ---------------------------------------------------------
   ① 首页
   --------------------------------------------------------- */
.hero {
  position: absolute;
  background: var(--c-paper);
  border: 6px solid var(--c-ink);
  border-radius: 10px;
  padding: 14px;
  box-shadow: 16px 18px 0 var(--c-ink);
}
.hero .inner {
  height: 100%;
  padding: 6px;
  border: 3px solid #DAD4C4;
  border-radius: 6px;
  background: var(--c-paper);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.hero img { width: 100%; height: 100%; object-fit: contain; transform: scale(1.06); }
.hero .hole {
  position: absolute;
  right: 18px;
  top: 18px;
  width: 26px;
  height: 26px;
  border: 3px solid #B7B1A2;
  border-radius: 50%;
  background: var(--c-yellow);
}

.title-line {
  position: absolute;
  text-align: center;
  font-weight: 900;
  color: #fff;
  -webkit-text-stroke: 11px var(--c-ink);
  paint-order: stroke fill;
  line-height: 1;
  letter-spacing: 4px;
  text-shadow: 0 10px 0 var(--c-ink);
}
.title-line span { position: relative; }

.note {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 10px 16px;
  border-radius: 8px;
  background: transparent;
  font-size: 18px;
  font-weight: 700;
  line-height: 1.5;
  color: rgba(20, 20, 20, .72);
  letter-spacing: .5px;
}

/* ---------------------------------------------------------
   ② 选择卡牌
   --------------------------------------------------------- */
.counter {
  position: absolute;
  text-align: right;
  font-size: 46px;
  font-weight: 900;
  letter-spacing: 2px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: flex-end;
}

.card-cell {
  position: absolute;
  background: transparent;
  border: 0;
  border-radius: 22px;
  padding: 0;
  cursor: pointer;
  transition: transform .1s ease, background .1s ease;
  font-family: inherit;
}
.card-cell .oval {
  position: absolute;
  inset: 12px;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px 10px;
  text-align: center;
  font-size: 30px;
  font-weight: 900;
  line-height: 1.22;
  letter-spacing: 1px;
  color: var(--c-ink);
  transition: color .1s ease;
}
/* 选中态：card_s 的黑块中心比卡面中心偏上（块 y 16%~78%，中心 47%），
   文字框下边收 16px 把字顶上去，正好落在黑块正中。 */
.card-cell.sel .oval { inset: 12px 12px 28px; color: #fff; }
.card-cell.sel { transform: translateY(-2px); }
.card-cell:active { transform: translateY(2px) scale(.98); }

/* ---------------------------------------------------------
   ③ 卡牌说明
   --------------------------------------------------------- */
.detail-panel {
  position: absolute;
  background: var(--c-paper);
  border: 6px solid var(--c-ink);
  border-radius: 12px;
  box-shadow: 16px 18px 0 var(--c-ink);
  overflow: hidden;
}
.detail-panel .dots {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle at 50% 50%, rgba(20, 20, 20, .14) 1.3px, transparent 1.5px);
  background-size: 12px 12px;
  pointer-events: none;
}
.art-box {
  position: absolute;
  background: #EDE7DA;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.art-box img { width: 92%; height: auto; }
.effect {
  position: absolute;
  text-align: center;
  text-wrap: balance;
  white-space: pre-line;
  font-size: 33px;
  font-weight: 900;
  line-height: 1.65;
  letter-spacing: 1px;
}

/* ---------------------------------------------------------
   ④⑥ 游戏中：HUD
   --------------------------------------------------------- */
.game-head {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  /* 只做布局，不画底色：页眉的黄色 / 点阵 / 斜边分隔线统一在 .bg 里画，
     否则工坊换整页背景图时会剩一条系统黄带盖住新稿子的页眉。 */
  background: transparent;
  overflow: hidden;
}
.bg .head-halftone {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  background-image: radial-gradient(circle at 50% 50%, rgba(20, 20, 20, .17) 1.5px, transparent 1.7px);
  background-size: 13px 13px;
  pointer-events: none;
}
.bg .divider {
  position: absolute;
  left: 0;
  right: 0;
  height: 6px;
  background: var(--c-ink);
  pointer-events: none;
}
.hud-avatar {
  position: absolute;
  border: 5px solid var(--c-ink);
  border-radius: 10px;
  background: var(--c-paper);
  display: flex;
  align-items: center;
  justify-content: center;
}
.hud-avatar img { width: 96%; height: 96%; object-fit: contain; }
.turn-badge {
  position: absolute;
  background: var(--c-ink);
  color: #fff;
  font-size: 21px;
  font-weight: 900;
  letter-spacing: 1px;
  padding: 5px 9px;
  border-radius: 5px;
  line-height: 1.1;
  white-space: nowrap;
}
.hud-bars { position: absolute; }
/* 行只为排版而存在（左侧给词条留位）：本身不接收点击，
   否则它的盒子会盖在独立词条上方，点词条变成拖整条进度条 */
.hud-row {
  position: absolute;
  display: flex;
  align-items: center;
  gap: 10px;
  pointer-events: none;
}
.hud-row .bar { pointer-events: auto; }
/* 数值条（2026-11-11 v3）：白底圆角框 + 12 个等宽圆角方块，亮格实心、暗格留白缝。
   满格 12 / 最低 0，一格 = 1 点。高度 / 圆角 / 描边 / 内衬 / 格间距 / 格圆角
   都由 theme.bars 写进内联样式或 CSS 变量，这里只给默认值。 */
.bar {
  flex: 1;
  display: flex;
  align-items: stretch;
  gap: var(--seg-gap, 4px);
  box-sizing: border-box;
  height: 44px;
  padding: 4px;
  border: 4px solid var(--c-ink);
  border-radius: 14px;
  background: #fff;
  overflow: hidden;
}
.bar .seg {
  flex: 1 1 0;
  min-width: 0;
  border-radius: 5px;
  background: #fff;
  box-shadow: inset 0 0 0 1px rgba(20, 20, 20, .10);
  transition: background .16s ease, box-shadow .16s ease;
}
.bar .seg.on {
  background: var(--c-bar-on);
  box-shadow: none;
}
/* 词条（生命 / 攻击 / 防御 / 卡组）：独立文本元素，各自 data-k，不跟进度条图片绑定 */
.hud-stat-label {
  position: absolute;
  font-weight: 900;
  letter-spacing: 1px;
  white-space: nowrap;
  color: var(--c-ink);
  text-align: left;
}

/* 事件卡名标签（随机 / 抉择共用一套外观，位置也同一点） */
.chip {
  position: absolute;
  display: flex;
  align-items: center;
  gap: 9px;
  background: #F7F4EE;
  border: 3px solid var(--c-ink);
  border-radius: 12px;
  padding: 0 14px;
  font-size: 24px;
  font-weight: 900;
  letter-spacing: 1px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chip img { width: 22px; height: 22px; flex: none; }

/* 事件页的「获得【标签】」角标已移除（创作者 2026-11-14 决定），相关样式一并删除 */

/* 事件卡图 */
.art-card {
  position: absolute;
  background: var(--c-paper);
  border: 5px solid var(--c-ink);
  border-radius: 18px;
  padding: 16px;
  box-shadow: 14px 16px 0 rgba(20, 20, 20, .16);
}
.art-card .inner {
  height: 100%;
  border: 2px solid #D8D2C2;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.art-card img { width: 100%; height: auto; }
.art-card .hole {
  position: absolute;
  right: 16px;
  top: 16px;
  width: 24px;
  height: 24px;
  border: 3px solid #BFB9AA;
  border-radius: 50%;
  background: var(--c-paper);
}

/* 事件插画「整卡」模式（assets/art/cards/*.png）：
   图本身就是成品卡面 —— 自带卡纸、黑框、圆孔、投影与倾斜角。
   容器此时只负责位置与尺寸，必须把 chrome 全部让位，否则会出现
   框中框、孔套孔、双层投影，图里那张卡的边角也会被内衬裁掉。 */
.art-card.art-card--full {
  background: transparent;
  border: 0;
  padding: 0;
  box-shadow: none;
}
.art-card.art-card--full .inner {
  border: 0;
  border-radius: 0;
  overflow: visible;
}
.art-card.art-card--full .inner img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.art-card.art-card--full .hole { display: none; }

/* 事件插画入场：每切到一个新事件，插图在三维空间里绕竖直轴（Y 轴）逆时针翻一整圈
   （对应 Keynote「旋转」preset：持续 0.70 秒、方向 从左到右）。
   是 3D 翻转，不是画面内平面自转：perspective() 写在变换里，镜头与背景固定，
   卡片靠近镜头的半侧放大、远离的半侧缩小，转到 ±90° 时收成一条侧棱，
   后半圈能看到背面 —— 有立体感、不是指针式打转。
   rotateY 取负角：卡片右缘先向镜头转来（俯视逆时针），与「从左到右」一致。
   挂在图片层 .inner 上，不挂在 .art-card 上：容器带着 layout 给的倾斜角
   （inline transform），两者写同一层会互相顶掉；.inner 转完回到 0°，
   与容器角度叠加后仍是原来的斜度，不留跳变。 */
.art-card .inner { transform-origin: 50% 50%; }
.art-card.art-spin .inner {
  animation: artSpinY .7s cubic-bezier(.42, 0, .24, 1) 1 both;
  transform-style: preserve-3d;
  backface-visibility: visible;   /* 后半圈要显示背面，否则过 90° 整块消失 */
}
@keyframes artSpinY {
  from { transform: perspective(900px) rotateY(0deg); }
  to   { transform: perspective(900px) rotateY(-360deg); }
}
/* 画心模式（带框容器）旋转时四角会顶出卡框，动画期间裁一下；
   整卡模式容器没有框，不能让卡面边角被切掉 */
.art-card.art-spin:not(.art-card--full) { overflow: hidden; }

/* 事件文字块拆成三层，各管各的：
   .ev-art    底板 —— 想给文字垫一张纸 / 一块色块，换图只换这一层
   .ev-text   文字 —— 绑定事件表 event.<回合>.text，改字不碰图
   .ev-corner 左右角标 —— 两张独立的图，可以分别替换             */
.event-text {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  text-wrap: balance;
  font-size: 33px;
  font-weight: 900;
  line-height: 1.6;
  letter-spacing: 1px;
}
.ev-art {
  position: absolute;
  inset: 0;
  display: block;
  border-radius: 12px;
  z-index: 1;
}
.ev-text { position: relative; z-index: 2; display: block; width: 100%; }
.ev-corner {
  position: absolute;
  top: 50%;
  width: 30px;
  height: 30px;
  margin-top: -15px;
  z-index: 3;
  display: block;
}
.ev-corner-l { left: -2px; }
.ev-corner-r { right: -2px; }
.nb { white-space: nowrap; }

/* ---------------------------------------------------------
   ⑤ 地图（手绘卷轴 · 分层）
   背景 = 地图与纸面；山洞 / 村庄 / 两块标签 / 标题各是一层 <img>，
   每层都能在皮肤工坊单独换图（见 js/map-art.js 的 data URI）
   --------------------------------------------------------- */
.map-bg { background-color: var(--c-paper); }
.map-layer {
  position: absolute;
  display: block;
  pointer-events: none;   /* 点击交给上面那层透明热区 */
  user-select: none;
  -webkit-user-drag: none;
}
/* 皮肤工坊里反过来：图层恢复可点击（能选中 / 拖动 / 换图），
   透明热区让位（否则整块热区盖住下面的图，工坊里点什么都选不中，
   还会在预览里误触进关）。正常游玩不加 in-studio，行为不变。 */
.in-studio .map-layer { pointer-events: auto; }
.in-studio .map-hot { pointer-events: none; }
/* 弹窗背景层同理：游玩态 pointer-events:none（点弹窗任意处都算点遮罩），
   编辑态恢复可点 —— 否则结算弹窗的背景（win.bg / lose.bg）在工坊里点不中、拖不动 */
.in-studio .m-bg { pointer-events: auto; }
/* 点山洞 → 山洞与它的标签一起放大一下，作为「进去了」的反馈 */
.map-going .map-cave,
.map-going .map-label-cave { animation: mapGo .46s ease both; }
@keyframes mapGo {
  0%   { transform: scale(1); }
  60%  { transform: scale(1.035); }
  100% { transform: scale(1.07); opacity: .92; }
}
/* 透明热区：盖在地标上，不参与视觉 */
.map-hot {
  position: absolute;
  padding: 0;
  margin: 0;
  border: none;
  background: transparent;
  cursor: pointer;
  border-radius: 28px;
  transition: background .15s ease, opacity .2s ease;
  touch-action: manipulation;
}
.map-hot:active { background: rgba(255, 223, 97, .26); }
.map-hot.off { pointer-events: none; }

/* ---------------------------------------------------------
   ⑥ 选择事件
   --------------------------------------------------------- */
/* 选项也拆两层：.opt-art 是整块「点阵底 + 椭圆」的底板（可整张换图），
   .opt-text 是选项文字（绑定事件表的选项文案，不跟着图走） */
.opt {
  position: absolute;
  padding: 0;
  border: none;
  background: transparent;
  box-shadow: none;
  cursor: pointer;
  transition: transform .07s ease;
  font-family: inherit;
  -webkit-appearance: none;
  appearance: none;
}
.opt-art {
  position: absolute;
  inset: 0;
  display: block;
  border: 5px solid var(--c-ink);
  border-radius: 14px;
  background: var(--c-paper);
  box-shadow: 0 8px 0 var(--c-ink);
  overflow: hidden;
  transition: box-shadow .07s ease;
  z-index: 1;
}
.opt-art::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle at 50% 50%, rgba(20, 20, 20, .30) 1.5px, transparent 1.7px);
  background-size: 9px 9px;
}
.opt-art::after {
  content: '';
  position: absolute;
  inset: 12px;
  border: 4px solid var(--c-ink);
  border-radius: 50% / 46%;
  background: var(--c-paper);
}
.opt-text {
  position: absolute;
  inset: 12px;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 8px 18px;
  font-size: 28px;
  font-weight: 900;
  line-height: 1.4;
  text-wrap: balance;
  letter-spacing: 1px;
  color: var(--c-ink);
}
.opt:active { transform: translateY(6px); }
.opt:active .opt-art { box-shadow: 0 2px 0 var(--c-ink); }

/* ---------------------------------------------------------
   ⑦ 本世记录
   --------------------------------------------------------- */
/* 原型图里「回合数」只是手写括号 + 粗字，没有边框和底板 */
.record-badge {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  background: transparent;
  border: none;
  box-shadow: none;
  font-size: 46px;
  font-weight: 900;
  letter-spacing: 2px;
  transform: rotate(-1.5deg);
  white-space: nowrap;
  text-align: right;
}
/* 结局条：黑标签 + 结局表原文，贴在日志上方
   拆两层：.end-art 是整条白底黑框（可整张换图），.end-text 是文字（不跟着图走） */
.end-line {
  position: absolute;
  display: flex;
  align-items: center;
  font-weight: 900;
}
.end-art {
  position: absolute;
  inset: 0;
  display: block;
  background: var(--c-paper);
  border: 5px solid var(--c-ink);
  border-radius: 18px;
  box-shadow: 0 8px 0 rgba(0, 0, 0, .28);
  z-index: 1;
}
.end-text {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 20px;
  width: 100%;
}
.end-line .k {
  flex: none;
  background: var(--c-ink);
  color: var(--c-paper);
  font-size: 26px;
  letter-spacing: 2px;
  padding: 6px 14px;
  border-radius: 6px;
  white-space: nowrap;
}
.end-line .v {
  flex: 1;
  font-size: 31px;
  line-height: 1.28;
  letter-spacing: 1px;
  color: var(--c-ink);
}
.record-list {
  position: absolute;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 4px 14px 22px 0;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(#000 calc(100% - 34px), transparent);
  mask-image: linear-gradient(#000 calc(100% - 34px), transparent);
}
.record-list::-webkit-scrollbar { width: 0; height: 0; }
.log-item {
  position: relative;
  background: var(--c-paper);
  border: 5px solid var(--c-ink);
  border-radius: 24px;
  padding: 16px 26px;
  margin-bottom: 18px;
  font-size: 34px;
  font-weight: 900;
  line-height: 1.5;
  letter-spacing: 1px;
  text-align: left;
}
/* 原型图的记录条带一个小尖角（对话气泡状），朝左上 */
.log-item::before {
  content: '';
  position: absolute;
  left: 26px;
  top: -17px;
  width: 30px;
  height: 17px;
  background: var(--c-paper);
  border-left: 5px solid var(--c-ink);
  border-top: 5px solid var(--c-ink);
  transform: skewX(-42deg);
}
.log-item.new { animation: pop .28s ease both; }
@keyframes pop {
  from { transform: translateY(10px) scale(.96); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

/* ---------------------------------------------------------
   弹窗
   --------------------------------------------------------- */
.mask {
  position: absolute;
  inset: 0;
  z-index: 100;
  background: var(--c-mask);
  animation: fadeIn .15s ease both;
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
.mask.out { animation: fadeOut .14s ease both; }
@keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }

/* 弹窗外壳只负责定位与内边距；底色 / 描边 / 投影 / 点阵都在 .m-bg 这一层。
   这一层就是工坊里的「弹窗背景」槽位（键 modal.<kind>.bg），换图即整块换底。 */
.modal {
  position: absolute;
  background: transparent;
  border: 0;
  border-radius: 14px;
  padding: 42px 30px 34px;
}
.m-bg {
  position: absolute;
  inset: 0;
  background: var(--c-paper);
  border: 6px solid var(--c-ink);
  border-radius: 14px;
  box-shadow: 0 16px 0 rgba(0, 0, 0, .35);
  z-index: 0;
  pointer-events: none;
}
.modal .dots {
  position: absolute;
  inset: 0;
  border-radius: 8px;
  background-image: radial-gradient(circle at 50% 50%, rgba(20, 20, 20, .13) 1.3px, transparent 1.5px);
  background-size: 11px 11px;
  pointer-events: none;
}
.m-tag {
  position: absolute;
  left: -8px;
  top: -34px;
  background: var(--c-ink);
  color: #fff;
  font-size: 38px;
  font-weight: 900;
  letter-spacing: 3px;
  padding: 10px 46px 10px 26px;
  clip-path: polygon(0 0, 100% 0, 92% 100%, 0 100%);
  transform: rotate(-2deg);
  z-index: 3;
  white-space: nowrap;
}
.m-close {
  position: absolute;
  right: -26px;
  top: -36px;
  width: 80px;
  height: 80px;
  padding: 0;
  border: 5px solid var(--c-ink);
  border-radius: 10px;
  background: var(--c-paper);
  box-shadow: 4px 5px 0 var(--c-ink);
  cursor: pointer;
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 40px;
  font-weight: 900;
  line-height: 1;
  font-family: inherit;
}
.m-close::before {
  content: '';
  position: absolute;
  right: -1px;
  top: -1px;
  width: 24px;
  height: 24px;
  background: var(--c-accent);
  clip-path: polygon(100% 0, 0 0, 100% 100%);
}
.m-close:active { transform: translateY(4px); box-shadow: 0 1px 0 var(--c-ink); }
.m-body {
  position: relative;
  z-index: 1;
  max-height: 900px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  font-size: 30px;
  font-weight: 900;
  line-height: 1.7;
}
.m-body::-webkit-scrollbar { width: 0; }
.m-body p { margin: 0 0 6px; }

.setting-row {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 20px 0;
  font-size: 34px;
  font-weight: 900;
}
.setting-row .sl { flex: 1; }
.toggle {
  border: 4px solid var(--c-ink);
  border-radius: 8px;
  background: var(--c-paper);
  padding: 8px 24px;
  font-size: 30px;
  font-weight: 900;
  font-family: inherit;
  cursor: pointer;
  min-width: 96px;
  transition: background .12s ease, color .12s ease, transform .07s ease;
}
.toggle:active { transform: translateY(3px); }
.toggle.on { background: var(--c-ink); color: #fff; }

.modal .btn { position: relative; width: 100%; height: 104px; }
/* 结算按钮拆层后直接挂在面板上，由 place() 绝对定位（btn-win / btn-lose 各一个键） */
.modal .m-result-btn { position: absolute; z-index: 1; }

/* 没有标题牌的弹窗（卡牌发动提醒）：顶部不再为标题牌留位置 */
.modal.no-tag { padding: 34px 30px 30px; }

/* 退出游戏二次确认：一句话 + 一个确认按钮 */
.exit-body {
  margin: 6px 0 30px;
  font-size: 34px;
  font-weight: 900;
  line-height: 1.6;
}

/* 结算弹窗（通关成功 / 挑战失败）：背景 / 标题 / 正文 / 按钮拆成四层，
   正文由 place() 绝对定位（win-body / lose-body 各一个键，与标题 / 按钮互不牵连） */
.result-body {
  position: absolute;
  margin: 0;
  box-sizing: border-box;
  text-align: center;
  font-size: 36px;
  font-weight: 900;
  line-height: 1.65;
  z-index: 1;
}
.result-body.lose { color: var(--c-ink); }
.result-body.win { color: var(--c-ink); }
.result-body.win::after {
  content: '';
  display: block;
  width: 120px;
  height: 6px;
  margin: 22px auto 0;
  background: var(--c-accent);
  border-radius: 3px;
}
.m-result-btn { margin-top: 0; }

/* 卡牌发动提醒：五层拆分（弹窗底 / 卡板 / 名条 / 插画 / 技能文字），
   每层一个 layout 键、绝对定位在面板上（place 坐标相对面板 padding 盒），
   工坊里单独拖 / 缩 / 换图 / 改字，互不牵连（与结算弹窗拆层同构） */
.fire-card {
  position: absolute;
  background: var(--c-paper);
  border: 7px solid var(--c-ink);
  box-shadow: 12px 14px 0 var(--c-ink);
}
.fire-tag {
  position: absolute;
  display: flex;
  align-items: center;
  background: var(--c-ink);
  color: #fff;
  font-weight: 900;
  font-size: 34px;
  letter-spacing: 3px;
  padding: 8px 42px 8px 22px;
  clip-path: polygon(0 0, 100% 0, 93% 100%, 0 100%);
  transform: rotate(-2.2deg);
  white-space: nowrap;
  z-index: 3;
}
.fire-art {
  position: absolute;
  background: #EDE7DA;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.fire-art img { width: 86%; height: auto; }
.fire-text {
  position: absolute;
  text-align: center;
  text-wrap: balance;
  white-space: pre-line;
  font-size: 32px;
  font-weight: 900;
  line-height: 1.65;
  letter-spacing: 1px;
}

/* toast / 飘字 */
.toast {
  position: absolute;
  left: 50%;
  bottom: 140px;
  transform: translateX(-50%);
  background: var(--c-ink);
  color: #fff;
  font-size: 28px;
  font-weight: 900;
  padding: 16px 30px;
  border-radius: 10px;
  z-index: 300;
  animation: toastIn .18s ease both;
  white-space: nowrap;
}
@keyframes toastIn { from { opacity: 0; transform: translate(-50%, 12px); } to { opacity: 1; transform: translate(-50%, 0); } }

.float-num {
  position: absolute;
  font-size: 30px;
  font-weight: 900;
  color: var(--c-danger);
  text-shadow: 0 2px 0 #fff, 0 0 6px #fff;
  pointer-events: none;
  z-index: 150;
  animation: floatUp .95s ease-out both;
  white-space: nowrap;
}
.float-num.plus { color: #1F7A4C; }
@keyframes floatUp {
  0%   { opacity: 0; transform: translate(-50%, 6px); }
  25%  { opacity: 1; transform: translate(-50%, -8px); }
  100% { opacity: 0; transform: translate(-50%, -62px); }
}

/* 启动错误 */
#boot-error {
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  max-width: 520px;
  padding: 28px 32px;
  background: #fffdf6;
  border: 4px solid #141414;
  border-radius: 12px;
  font-family: "PingFang SC", sans-serif;
  font-size: 15px;
  line-height: 1.7;
  color: #141414;
  z-index: 999;
}
#boot-error h2 { margin: 0 0 10px; font-size: 20px; }
#boot-error code { background: #ffdf61; padding: 2px 6px; border-radius: 4px; }

/* 游戏中（④⑥）白色纸面区域：
   它是 .bg 的子层（不是独立一层），工坊换整页背景图时会被一起隐藏，
   所以「换背景」= 整页一次换完，不会只变顶部那条页眉带。 */
.bg .paper {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: var(--c-paper);
  background-image: radial-gradient(circle at 50% 50%, rgba(20, 20, 20, .05) 1.4px, transparent 1.6px);
  background-size: 12px 12px;
  pointer-events: none;
}

/* ---------------------------------------------------------
   皮肤工坊入口（常驻右下角，不随舞台缩放）
   --------------------------------------------------------- */
#studio-dock {
  position: fixed;
  right: 14px;
  bottom: 14px;
  width: 46px;
  height: 46px;
  padding: 0;
  border-radius: 50%;
  border: 2px solid rgba(20, 20, 20, .16);
  background: rgba(255, 253, 246, .74);
  color: #141414;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  opacity: .38;
  z-index: 9998;
  transition: opacity .18s ease, transform .18s ease, background .18s ease;
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}
#studio-dock:hover,
#studio-dock:focus-visible { opacity: 1; transform: translateY(-2px); background: rgba(255, 253, 246, .96); }
#studio-dock:active { transform: scale(.94); }
#studio-dock svg { width: 22px; height: 22px; }
@media (pointer: coarse) {
  #studio-dock { width: 40px; height: 40px; opacity: .3; }
  #studio-dock svg { width: 19px; height: 19px; }
}
