/* ===================================================================
   树洞（mimila.cn/treehole）—— 一面紫罗兰色的墙
   ===================================================================

   用户 2026-09-22 晚上的原话：
     「树洞现在不够好看，甚至有点无趣了，来个紫色配色的吧，
       主题依旧是那样，不过这次要更花哨一些，顺便你能加一些漂亮的特效之类的」

   所以这一版做了三件事（主题没动：还是一个可以匿名说话、被看见的地方）：

     1. **换成紫色**：淡紫的纸、深紫的字、紫罗兰到品红的六档头像色。
        纸条不再是「白纸」，是「薰衣草色的便签」。
     2. **更花哨**：形状从 10 种加到 14 种（多了拱门、不规则圆、撕纸边、菱形），
        墙后面有缓慢游动的紫色光斑，卡片进场一张张浮上来、指着它会轻轻抬起来发光。
     3. **漂亮的特效**：题记上有星点闪烁、一道光缓缓扫过；卡片悬停有紫色辉光；
        圆环和菱形带一点点自转的呼吸感。

   规矩一条都没破：
     · 零依赖、不引图片（星点、光斑全是 CSS 画的）
     · 动效只用 transform / opacity（不碰 layout，手机才不卡）
     · **尊重「减弱动态效果」**：开了那个开关，所有动画一律停（最后一段统一关）
     · 手机优先：小屏关掉光斑、星点减半、异形退化成圆角方块
     · 文字对比度全部算过（≥4.5:1），断言在 tests/test_page_render.py 里
   =================================================================== */

/* ===================================================================
   1. 紫色主题变量
   ===================================================================
   亮色：薰衣草纸 + 深紫字。暗色：夜色紫纸 + 淡紫字。
   ⚠️ 这些比例不是凭眼睛挑的：纸 #F7F2FF 上的字 14:1、次要字 5.5:1、
      六个头像色配白字最低 6.0:1 —— 都过了 AA。改颜色之前先看测试。
   =================================================================== */

body.home[data-page^="treehole"] {
  /* --- 纸 --- */
  --th-paper:      #FBF8FF;
  --th-paper-1:    #FBF8FF;          /* 题记渐变的浅端 */
  --th-paper-2:    #EFE6FF;          /* 题记渐变的深端 */
  --th-gloss:      rgba(255, 255, 255, 0.85);
  --th-edge:       rgba(124, 58, 237, 0.16);   /* 纸边那一道细紫线 */

  /* --- 字 --- */
  --th-ink:        #2A1F3D;          /* 正文（14:1） */
  --th-ink-strong: #1E1630;          /* 名字、标题 */
  --th-ink-soft:   #6B5B8A;          /* 次要（5.5:1） */

  /* --- 紫色 --- */
  --th-accent:     #6D28D9;          /* 强调文字（6.5:1） */
  --th-accent-2:   #A855F7;          /* 高光/描边（不承载文字） */
  --th-accent-3:   #C026D3;          /* 品红点缀 */
  --th-fill:       rgba(124, 58, 237, 0.08);
  --th-fill-2:     rgba(124, 58, 237, 0.14);
  --th-music:      rgba(192, 38, 211, 0.10);
  --th-glow:       rgba(139, 92, 246, 0.30);   /* 悬停辉光 */

  /* --- 六档头像色（白字压上去最低 6.0:1，一个紫色家族） --- */
  --th-anon:       #7A6E93;   /* 匿名：中性灰紫（不是彩色，免得看出是谁） */
  --th-a0: #7A6E93;
  --th-a1: #5B21B6;   /* 深紫罗兰 */
  --th-a2: #4F46E5;   /* 靛蓝 */
  --th-a3: #7E22CE;   /* 紫 */
  --th-a4: #A21CAF;   /* 紫红 */
  --th-a5: #BE185D;   /* 玫红 */
}

:root[data-theme="dark"] body.home[data-page^="treehole"] {
  --th-paper:      #241C36;
  --th-paper-1:    #2A2140;
  --th-paper-2:    #1C1630;
  --th-gloss:      rgba(196, 167, 255, 0.06);
  --th-edge:       rgba(196, 167, 255, 0.14);

  --th-ink:        #EFE9FF;          /* 13.7:1 */
  --th-ink-strong: #FBF8FF;
  --th-ink-soft:   #A99BD0;          /* 6.4:1 */

  --th-accent:     #C4A7FF;
  --th-accent-2:   #D8B4FE;
  --th-accent-3:   #E879F9;
  --th-fill:       rgba(196, 167, 255, 0.10);
  --th-fill-2:     rgba(196, 167, 255, 0.18);
  --th-music:      rgba(232, 121, 249, 0.14);
  --th-glow:       rgba(168, 85, 247, 0.38);

  /* 暗色下头像色整体提亮一档（不然压在深色纸上看不清哪个是哪个） */
  --th-anon: #6B6188;
  --th-a0: #6B6188;
  --th-a1: #6D28D9;
  --th-a2: #4F46E5;
  --th-a3: #9333EA;
  --th-a4: #C026D3;
  --th-a5: #DB2777;
}

/* ===================================================================
   2. 页面底色 + 缓慢游动的紫色光斑（特效①）
   ===================================================================
   三个大光斑，只用 transform 慢速漂移。**不用 filter: blur** ——
   那个在手机上很贵，改用「边缘很软的 radial-gradient」，看着一样。
   =================================================================== */

body.home[data-page^="treehole"] {
  background-image:
    radial-gradient(900px 520px at 84% -8%, rgba(139, 92, 246, 0.16), transparent 70%),
    radial-gradient(700px 420px at 8% 12%, rgba(192, 38, 211, 0.10), transparent 72%);
  background-repeat: no-repeat;
}

:root[data-theme="dark"] body.home[data-page^="treehole"] {
  background-image:
    radial-gradient(980px 560px at 84% -8%, rgba(124, 58, 237, 0.34), transparent 70%),
    radial-gradient(760px 460px at 6% 10%, rgba(192, 38, 211, 0.20), transparent 72%);
  background-repeat: no-repeat;
}

body.home[data-page^="treehole"] .home-wrap { position: relative; }

.th-aurora {
  position: absolute;
  inset: -40px -20px auto;
  height: 620px;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
  opacity: .75;
}
.th-aurora i {
  position: absolute;
  display: block;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%,
              var(--th-accent-2), transparent 68%);
  opacity: .22;
  animation: th-drift 26s ease-in-out infinite alternate;
}
.th-aurora .g1 { width: 320px; height: 320px; left: -60px; top: 40px; }
.th-aurora .g2 { width: 260px; height: 260px; right: -50px; top: 120px;
                 animation-duration: 31s; animation-direction: alternate-reverse; }
.th-aurora .g3 { width: 200px; height: 200px; left: 46%; top: -30px;
                 background: radial-gradient(circle at 40% 40%,
                             var(--th-accent-3), transparent 70%);
                 opacity: .16; animation-duration: 37s; }

@keyframes th-drift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(38px, 26px, 0) scale(1.12); }
}

/* 墙上的东西要压在光斑上面 */
.th-wall, .th-head, .th-epigraph, .th-form, .card { position: relative; z-index: 1; }

/* ===================================================================
   3. 题记：星点闪烁 + 一道缓慢扫过的光（特效②）
   =================================================================== */

.th-epigraph {
  position: relative;
  overflow: hidden;
  margin: 0 0 16px;
  padding: 30px 22px 26px;
  border-radius: 26px;
  background-image: linear-gradient(150deg, var(--th-paper-1), var(--th-paper-2));
  border: 1px solid var(--th-edge);
  box-shadow:
    0 1px 2px rgba(46, 20, 90, 0.05),
    0 18px 40px -18px var(--th-glow);
  text-align: center;
}

/* 扫过的那道光：一条斜着的白带子慢慢横穿，很淡 */
.th-epigraph::after {
  content: "";
  position: absolute;
  top: -60%;
  left: -40%;
  width: 42%;
  height: 220%;
  background: linear-gradient(100deg,
    transparent, rgba(255, 255, 255, 0.55), transparent);
  transform: rotate(14deg);
  animation: th-sheen 9s ease-in-out infinite;
  pointer-events: none;
}
:root[data-theme="dark"] .th-epigraph::after {
  background: linear-gradient(100deg,
    transparent, rgba(196, 167, 255, 0.14), transparent);
}

@keyframes th-sheen {
  0%   { transform: translate3d(-40%, 0, 0) rotate(14deg); opacity: 0; }
  12%  { opacity: 1; }
  55%  { transform: translate3d(320%, 0, 0) rotate(14deg); opacity: 0; }
  100% { transform: translate3d(320%, 0, 0) rotate(14deg); opacity: 0; }
}

.th-epigraph p {
  position: relative;
  margin: 0;
  font-size: 15.5px;
  line-height: 2.05;
  letter-spacing: 0.012em;
  color: var(--th-ink);
}

/* 引文：一句话，字号给足、行距放松，四周留白 —— 深的话不需要多 */
.th-quote {
  position: relative;
  margin: 0;
  padding: 0 4px;
  font-size: 18.5px;
  font-weight: 600;
  line-height: 1.85;
  letter-spacing: 0.01em;
  color: var(--th-ink-strong);
  text-shadow: 0 0 22px var(--th-glow);
}
.th-quote-src {
  display: block;
  margin-top: 10px;
  font-size: 12.5px;
  font-style: normal;
  font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--th-ink-soft);
}

/* 树洞自己接的那一句：小一号、往下留白，像轻声说的 */
.th-epigraph .th-epi-last {
  position: relative;
  margin: 18px 0 0;
  font-size: 14px;
  font-weight: 500;
  color: var(--th-ink);
  opacity: .92;
}

/* 星点：一小撮在题记里闪。位置和节奏由模板给（--x/--y/--d/--s），
   一个个不一样才像星星，不像 LED 灯带 */
.th-spark {
  position: absolute;
  left: var(--x, 50%);
  top: var(--y, 50%);
  width: var(--s, 4px);
  height: var(--s, 4px);
  border-radius: 50%;
  background: var(--th-accent-2);
  box-shadow: 0 0 8px var(--th-accent-2);
  opacity: 0;
  animation: th-twinkle 4.6s ease-in-out infinite;
  animation-delay: var(--d, 0s);
  pointer-events: none;
}
.th-spark.magenta { background: var(--th-accent-3); box-shadow: 0 0 8px var(--th-accent-3); }

@keyframes th-twinkle {
  0%, 100% { opacity: 0; transform: scale(.6); }
  38%      { opacity: .9; transform: scale(1); }
  62%      { opacity: .35; transform: scale(.86); }
}

/* ===================================================================
   4. 发布卡
   =================================================================== */

.th-form { border: 1px solid var(--th-edge); }
.th-form textarea:focus,
.th-form input:focus { border-color: var(--th-accent-2); }

.th-form .btn-primary {
  background-image: linear-gradient(135deg, #5B21B6, #7C3AED);
  box-shadow: 0 8px 22px -10px var(--th-glow);
}
.th-form .btn-primary:hover {
  background-image: linear-gradient(135deg, #6D28D9, #8B5CF6);
  box-shadow: 0 10px 26px -8px var(--th-glow);
}

.th-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.th-row > .input { flex: 1; min-width: 130px; }
.th-tips { margin: 0; font-size: 12.5px; line-height: 1.7; color: var(--th-ink-soft); }
.th-tips a { color: var(--th-accent); font-weight: 600; }

/* ===================================================================
   5. 墙：12 列拼贴板
   =================================================================== */

.th-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin: 20px 2px 12px;
}
.th-head h2 {
  margin: 0;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--th-ink-strong);
}
.th-head .th-count { font-size: 12.5px; color: var(--th-ink-soft); }
.th-head .th-count a { color: var(--th-accent); }

.th-wall {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 11px;
  grid-auto-flow: dense;          /* 有洞就补上 —— 不留大片空白 */
  align-items: start;
}

/* ---- 一张纸条 ---- */
.th-card {
  position: relative;
  min-width: 0;
  padding: 14px 16px;
  border-radius: 18px;
  background-color: var(--th-paper);
  background-image:
    linear-gradient(158deg, var(--th-gloss), transparent 58%),
    linear-gradient(0deg, var(--th-fill), transparent 42%);
  border: 1px solid var(--th-edge);
  box-shadow: 0 2px 4px rgba(46, 20, 90, 0.04), 0 14px 30px -22px rgba(46, 20, 90, 0.35);
  /* 进场：一张张浮上来（--i 由模板给，最多排到第 12 张） */
  animation: th-in .5s var(--ease) both;
  animation-delay: calc(min(var(--i, 0), 12) * 45ms);
  transition: transform .26s var(--ease), box-shadow .26s var(--ease),
              border-color .26s var(--ease);
}

@keyframes th-in {
  from { opacity: 0; transform: translateY(14px) scale(.965) rotate(-.6deg); }
}

/* 指着它：轻轻抬起来、转一点点、边缘发光（特效③） */
@media (hover: hover) {
  .th-card:hover {
    transform: translateY(-4px) rotate(-.45deg);
    border-color: var(--th-accent-2);
    box-shadow: 0 4px 8px rgba(46, 20, 90, 0.06),
                0 24px 48px -20px var(--th-glow);
  }
  .th-card:hover .th-avatar { transform: scale(1.08) rotate(6deg); }
  .th-card:hover .th-link { background: var(--th-fill-2); }
}

/* 作者抬头 */
.th-who {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 9px;
  text-decoration: none;
  color: inherit;
}
.th-avatar {
  flex: none;
  width: 27px;
  height: 27px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 13.5px;
  font-weight: 700;
  color: #fff;
  background: var(--th-a1);
  box-shadow: 0 0 0 2px var(--th-paper), 0 0 0 3.5px var(--th-edge);
  transition: transform .26s var(--ease);
}
.th-avatar.a1 { background: var(--th-a1); }
.th-avatar.a2 { background: var(--th-a2); }
.th-avatar.a3 { background: var(--th-a3); }
.th-avatar.a4 { background: var(--th-a4); }
.th-avatar.a5 { background: var(--th-a5); }
.th-avatar.a0,
.th-avatar.anon { background: var(--th-anon); }

.th-name {
  font-size: 13px;
  font-weight: 650;
  color: var(--th-ink-strong);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.th-name.th-anon { color: var(--th-ink-soft); font-weight: 500; }
.th-who:hover .th-name { text-decoration: underline; text-decoration-color: var(--th-accent-2); }

.th-body {
  font-size: 14.5px;
  line-height: 1.75;
  color: var(--th-ink);
  word-break: break-word;
  white-space: pre-wrap;
}

/* ---- 纸条上的照片 ----
   ⚠️ 服务端不处理图片（这个项目不引图片库），尺寸全靠这里：
      定个最大高度 + `object-fit: cover`，再宽的图也撑不破这面墙。
      收口的形状（圆 / 环 / 三角）本来就装不下图 ——
      带图的纸条会被 `treehole._fits()` 换成装得下的形状。 */
.th-photo {
  display: block;
  width: 100%;
  max-height: 260px;
  object-fit: cover;
  margin-bottom: 10px;
  border-radius: 13px;
  background: var(--th-fill);
  box-shadow: 0 12px 26px -20px rgba(46, 20, 90, 0.7);
}
.th-shape-tall .th-photo { max-height: 340px; }
.th-shape-wide .th-photo { max-height: 220px; }

/* ---- 链接 / 音乐卡 ---- */
.th-link {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 10px;
  padding: 9px 11px;
  border-radius: 13px;
  background: var(--th-fill);
  border: 1px solid transparent;
  text-decoration: none;
  color: inherit;
  transition: background .22s var(--ease), border-color .22s var(--ease),
              transform .22s var(--ease);
}
.th-link:hover {
  border-color: var(--th-accent-2);
  transform: translateX(2px);
}
.th-link svg {
  flex: none; width: 18px; height: 18px;
  stroke: var(--th-accent); fill: none; stroke-width: 1.7;
}
.th-link-text { min-width: 0; }
.th-link-title {
  font-size: 13.5px;
  font-weight: 650;
  color: var(--th-ink-strong);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.th-link-host { font-size: 12px; color: var(--th-ink-soft); }
.th-card.th-kind-music .th-link { background: var(--th-music); }
.th-card.th-kind-music .th-link svg { stroke: var(--th-accent-3); }

/* ---- 我贴过的 ---- */
.th-mine-actions { margin-top: 8px; }
.th-del {
  background: none; border: none; padding: 0;
  font-size: 12px; color: var(--th-ink-soft); cursor: pointer;
}
.th-del:hover { color: var(--th-accent-3); text-decoration: underline; }

/* ===================================================================
   6. 形状（⚠️ 名字必须和 treehole.SHAPES 一一对应）
   =================================================================== */

.th-shape-wide   { grid-column: span 12; }
.th-shape-left   { grid-column: 1 / span 5; }
.th-shape-right  { grid-column: 8 / span 5; }
.th-shape-center { grid-column: 4 / span 6; }
.th-shape-tall   { grid-column: span 5; grid-row: span 2; }

/* 直角三角形：右下角切掉 —— 像随手撕下来的纸 */
.th-shape-tri {
  grid-column: span 4;
  clip-path: polygon(0 0, 100% 0, 0 100%);
  padding-bottom: 38px;
}
/* 凹型：右上角凹进去一块 */
.th-shape-notch {
  grid-column: span 5;
  clip-path: polygon(0 0, 72% 0, 72% 26%, 100% 26%, 100% 100%, 0 100%);
  padding-right: 26px;
}
/* 凸型：右下角多出来一块 */
.th-shape-bump {
  grid-column: span 5;
  clip-path: polygon(0 0, 100% 0, 100% 78%, 78% 78%, 78% 100%, 0 100%);
}
/* 拱门：上面是圆的 —— 像贴了一张便签在门框上 */
.th-shape-arch {
  grid-column: span 5;
  border-radius: 120px 120px 18px 18px;
  padding-top: 30px;
  text-align: center;
}
.th-shape-arch .th-who { justify-content: center; }

/* 不规则圆：手撕的圆，比方正好看 */
.th-shape-blob {
  grid-column: span 5;
  border-radius: 58% 42% 47% 53% / 47% 40% 60% 53%;
  padding: 24px 26px;
}

/* 撕纸边：上边和下边是锯齿状的（很多小折点拼出来） */
.th-shape-torn {
  grid-column: span 5;
  clip-path: polygon(0 3%, 6% 0, 13% 3.4%, 20% 0, 27% 3%, 34% .4%, 41% 3.2%,
                     48% 0, 55% 3%, 62% .6%, 69% 3.4%, 76% 0, 83% 3%, 90% .6%,
                     96% 3.2%, 100% 1%,
                     100% 97%, 94% 100%, 87% 96.6%, 80% 100%, 73% 97%,
                     66% 99.6%, 59% 96.8%, 52% 100%, 45% 97%, 38% 99.4%,
                     31% 96.6%, 24% 100%, 17% 97%, 10% 99.4%, 4% 96.8%, 0 99%);
  padding-top: 20px;
  padding-bottom: 22px;
}

/* 圆和环：只有很短的话才配得上（treehole._fits 会把长文换掉） */
.th-shape-circle {
  grid-column: span 4;
  aspect-ratio: 1;
  border-radius: 50%;
  padding: 28px 26px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-align: center;
  /* 一点点「呼吸」：极慢地放大缩小（特效④，只有圆和菱形有） */
  animation: th-in .5s var(--ease) both,
             th-breathe 7.5s ease-in-out infinite alternate;
  animation-delay: calc(min(var(--i, 0), 12) * 45ms), 0s;
}
.th-shape-circle .th-who { justify-content: center; }

@keyframes th-breathe {
  from { transform: scale(1); }
  to   { transform: scale(1.022); }
}

/* 圆环：中间镂空 —— 用 mask，不用伪元素（伪元素会被 clip 掉） */
.th-shape-ring {
  grid-column: span 4;
  aspect-ratio: 1;
  border-radius: 50%;
  padding: 36px 32px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-align: center;
  -webkit-mask-image: radial-gradient(circle, transparent 34%, #000 35%);
  mask-image: radial-gradient(circle, transparent 34%, #000 35%);
}
.th-shape-ring .th-who { justify-content: center; }

/* 菱形：转到 45° 的方块（里面的字不转，所以是「嵌在菱形里的方卡」） */
.th-shape-diamond {
  grid-column: span 4;
  clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
  padding: 40px 34px;
  text-align: center;
  animation: th-in .5s var(--ease) both,
             th-breathe 9s ease-in-out infinite alternate;
  animation-delay: calc(min(var(--i, 0), 12) * 45ms), .6s;
}
.th-shape-diamond .th-who { justify-content: center; }

/* 圆形 / 环 / 菱形里的字要小一号，不然会顶出来 */
.th-shape-circle .th-body,
.th-shape-ring .th-body,
.th-shape-diamond .th-body { font-size: 13.5px; line-height: 1.6; }
.th-shape-arch .th-body { font-size: 14px; }

/* ===================================================================
   6b. 个人主页：像素画 / 一句话 / 三枚戳（2026-09-22 第二版）
   ===================================================================
   用户那块画布：32×32，一格一格点出来（设计在 TREEHOLE.md 第 7 节③）。
   ⚠️ 画布在两页上是两种做法，**别改成另一种**：
      · 「画」的那一页 = 1024 个 button（能点、能用键盘、能拖）
      · 「看」的那一页 = 几十个 <rect> 的 SVG（同色合并，手机轻得多）
   =================================================================== */

/* ---- 看的那一页：像素画 ----
   ⚠️ **`max-width: 100%` 这一句是修 bug 加上的，别删**：
      画的宽度 = 32 × 作者选的缩放档（6/8/12）—— 12 档就是 **384px**，
      再加外框的内边距，比手机屏幕（≈350px 可用）还宽，
      表现是「电脑平板都好看，手机上一坨」+ 整页能左右拖（用户 2026-09-22 报的）。
      压住宽度、高度交给 `auto` 之后，SVG 自己按比例缩 —— 是矢量，缩了也不糊。 */
.px-art {
  display: block;
  max-width: 100%;
  /* ⚠️ `min-width: 0` 也得有：SVG 的「固有宽度」是 384px，
     flex/grid 里的元素默认**不肯缩到固有宽度以下**（min-width: auto）——
     只写 max-width 的话，320px 的小屏上它照样顶出去把整页撑宽。 */
  min-width: 0;
  height: auto;
  border-radius: 14px;
  background: var(--th-fill);
  box-shadow: 0 14px 30px -22px rgba(46, 20, 90, 0.8);
  shape-rendering: crispEdges;      /* 缩放时不糊边 —— 像素画的关键 */
}
.px-art-frame {
  display: inline-flex;
  max-width: 100%;                  /* 同上：外框也不能比屏幕宽 */
  min-width: 0;                     /* 同上：允许它比画本身的固有宽度窄 */
  padding: 8px;
  border-radius: 18px;
  background: var(--th-paper);
  border: 1px solid var(--th-edge);
}
.px-blank {
  padding: 26px 20px;
  border-radius: 18px;
  background: var(--th-fill);
  color: var(--th-ink-soft);
  font-size: 13.5px;
  line-height: 1.8;
}

/* ---- 主页头：画 + 名字 + 签名 + 戳 ---- */
.px-head {
  display: flex;
  gap: 18px;
  align-items: flex-start;
  flex-wrap: wrap;
}
/* 大屏：画和文字并排，文字占剩下的宽度（这一版用户看过，说挺好）。
   ⚠️ 手机上要**换行门槛**，那条在下面第 7 节（`max-width: 700px`）里 ——
      原因：`flex: 1` 的基准是 0，窄屏上画占满一行之后这一栏会被挤成 0 宽，
      名字、签名、戳全都看不见，页面上只剩一大块空白（用户 2026-09-22 报的）。 */
.px-head-text { min-width: 0; flex: 1; }
.px-motto {
  margin: 10px 0 0;
  font-size: 16px;
  line-height: 1.75;
  color: var(--th-ink-strong);
  text-shadow: 0 0 20px var(--th-glow);
}
.px-badge-row {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 12px;
}
.px-stamp {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--th-accent);
  background: var(--th-fill);
  border: 1px solid var(--th-edge);
}
.px-stamp svg {
  width: 15px; height: 15px;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}

/* ---- 画的那一页：调色板 ---- */
.px-palette {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.px-swatch {
  position: relative;
  width: 32px;
  height: 32px;
  padding: 0;
  border-radius: 9px;
  border: 1px solid var(--th-edge);
  background: var(--c, transparent);
  cursor: pointer;
  transition: transform .16s var(--ease), box-shadow .16s var(--ease);
}
.px-swatch:hover { transform: translateY(-2px); }
.px-swatch.on {
  box-shadow: 0 0 0 2px var(--th-paper), 0 0 0 4px var(--th-accent-2);
}
.px-eraser {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 13px;
  color: var(--th-ink-soft);
}

/* ---- 画布：32×32 的按钮矩阵 ----
   ⚠️ `touch-action: none` 是必须的：不然手指一划就变成滚页面，压根画不了。
   ⚠️ 格子大小由 --cell-size 决定（作者选的缩放档），窄屏用 clamp 自动缩到放得下。 */
.px-board {
  --cell-size: 8px;
  display: grid;
  grid-template-columns: repeat(var(--n, 32), 1fr);
  width: calc(var(--cell-size) * var(--n, 32));
  max-width: 100%;
  aspect-ratio: 1;
  padding: 6px;
  border-radius: 16px;
  border: 1px solid var(--th-edge);
  box-shadow: var(--shadow-card);
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  /* 棋盘格底：透明的格子也能看出「这儿是空的」 */
  background-color: var(--th-paper);
  background-image:
    linear-gradient(45deg, var(--th-fill) 25%, transparent 25%, transparent 75%,
                    var(--th-fill) 75%),
    linear-gradient(45deg, var(--th-fill) 25%, transparent 25%, transparent 75%,
                    var(--th-fill) 75%);
  background-size: 12px 12px;
  background-position: 0 0, 6px 6px;
}
.px-cell {
  padding: 0;
  margin: 0;
  border: none;
  background: transparent;
  cursor: crosshair;
  border-radius: 1px;
}
.px-cell.filled { box-shadow: inset 0 0 0 0.5px rgba(0, 0, 0, .08); }

/* ---- 三枚戳 / 缩放档 ---- */
.px-badges { display: flex; gap: 8px; flex-wrap: wrap; }
.px-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  border-radius: 999px;
  font-size: 13px;
  color: var(--th-ink-soft);
  background: var(--th-fill);
  border: 1px solid transparent;
  cursor: pointer;
  transition: all .18s var(--ease);
}
.px-badge input { position: absolute; opacity: 0; pointer-events: none; }
.px-badge svg {
  width: 16px; height: 16px;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
.px-badge.on {
  color: var(--th-accent);
  border-color: var(--th-accent-2);
  background: var(--th-paper);
}

.px-zooms { display: flex; gap: 8px; flex-wrap: wrap; }
.px-zoom {
  padding: 7px 13px;
  border-radius: 999px;
  font-size: 13px;
  color: var(--th-ink-soft);
  background: var(--th-fill);
  border: 1px solid transparent;
  cursor: pointer;
}
.px-zoom input { position: absolute; opacity: 0; pointer-events: none; }
.px-zoom.on {
  color: var(--th-accent);
  border-color: var(--th-accent-2);
  background: var(--th-paper);
  font-weight: 600;
}

/* ===================================================================
   6c. 排版（发布时自己挑的那四样，2026-09-22 第二版第三块）
   ===================================================================
   头像在哪 / 文字怎么对齐 / 图多大 / 纸什么颜色 —— 四组 class，144 种组合。
   ⚠️ 名字必须和 `treehole.look_classes()` 拼出来的一致，有用例盯着
      （模板里那处 class 是拼出来的，preflight 第 5 项不会检查它）。
   ⚠️ 只动**排列和颜色**，不动字号和圆角 ——
      不然「怎么选都不会丑」这句话就不成立了。
   =================================================================== */

/* ---- 头像的位置 ---- */
.look-av-top .th-who {
  /* 头像挪到文字上面：竖排，像一张名片 */
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}
.look-av-top .th-avatar { width: 34px; height: 34px; font-size: 16px; }
.look-av-right .th-who {
  flex-direction: row-reverse;       /* 头像跑到右边 */
  justify-content: flex-start;
}
.look-av-right .th-link { flex-direction: row-reverse; }
.look-av-right .th-link-text { text-align: right; }

/* ---- 文字对齐 ---- */
.look-al-center { text-align: center; }
.look-al-center .th-who { justify-content: center; }
.look-al-center .th-body { text-align: center; }
.look-al-center .th-link { justify-content: center; }
.look-al-right { text-align: right; }
.look-al-right .th-who { justify-content: flex-end; }
.look-al-right .th-link { flex-direction: row-reverse; }
.look-al-right .th-link-text { text-align: right; }

/* ---- 图的大小（三档）---- */
.look-ph-none .th-photo { display: none; }   /* 「不放图」= 藏着，不删数据 */
.look-ph-s .th-photo { max-height: 120px; }
.look-ph-m .th-photo { max-height: 220px; }
.look-ph-l .th-photo { max-height: 340px; }

/* ---- 纸的颜色（四档；字压在上面都算过对比度）---- */
.look-pa-1 {
  background-color: #F6F1FF;
  background-image: linear-gradient(158deg, rgba(255, 255, 255, .9), transparent 58%),
                    linear-gradient(0deg, rgba(124, 58, 237, .10), transparent 46%);
}
.look-pa-2 {
  background-color: #FFF8EC;
  background-image: linear-gradient(158deg, rgba(255, 255, 255, .9), transparent 58%),
                    linear-gradient(0deg, rgba(255, 168, 61, .12), transparent 46%);
}
.look-pa-3 {
  background-color: #F2F6FF;
  background-image: linear-gradient(158deg, rgba(255, 255, 255, .9), transparent 58%),
                    linear-gradient(0deg, rgba(70, 128, 255, .10), transparent 46%);
}
:root[data-theme="dark"] .look-pa-1 {
  background-color: #2A2140;
  background-image: linear-gradient(158deg, rgba(196, 167, 255, .07), transparent 58%),
                    linear-gradient(0deg, rgba(124, 58, 237, .18), transparent 46%);
}
:root[data-theme="dark"] .look-pa-2 {
  background-color: #322718;
  background-image: linear-gradient(158deg, rgba(255, 236, 200, .07), transparent 58%),
                    linear-gradient(0deg, rgba(255, 168, 61, .16), transparent 46%);
}
:root[data-theme="dark"] .look-pa-3 {
  background-color: #1E2537;
  background-image: linear-gradient(158deg, rgba(200, 220, 255, .07), transparent 58%),
                    linear-gradient(0deg, rgba(70, 128, 255, .16), transparent 46%);
}

/* ---- 发布框里那四组小按钮 ---- */
.look-row { display: flex; gap: 7px; flex-wrap: wrap; }
.look-pick {
  padding: 6px 12px;
  border-radius: 999px;
  font-size: 12.5px;
  color: var(--th-ink-soft);
  background: var(--th-fill);
  border: 1px solid transparent;
  cursor: pointer;
}
.look-pick input { position: absolute; opacity: 0; pointer-events: none; }
.look-pick:hover { color: var(--th-ink); }
/* 选中的那个：`:has()` 认得出来的浏览器直接用，认不出来的靠下面那段 JS 补 */
.look-pick:has(input:checked),
.look-pick.on {
  color: var(--th-accent);
  border-color: var(--th-accent-2);
  background: var(--th-paper);
  font-weight: 600;
}

/* ===================================================================
   6d. 举报按钮（2026-09-22 第二版第四块）
   ===================================================================
   卡片右下角一个安静的小字按钮：一次点击就够，不填理由、不留邮箱
   （门槛越高越没人按，而这一页本来就靠「有人提一嘴」）。
   ⚠️ 颜色用 `--th-ink-soft`，它和**四种纸色**都算过对比度
      （浅色最差 5.43:1、暗色最差 5.76:1；`test_page_render.py` 里真的在算）。
      **别调淡、别加 opacity**：淡到看不见就等于没这个按钮。
   ⚠️ 举报**不自动下架** —— 它只是让站长在审核页上多看到一个标记。
   =================================================================== */

.th-report { margin: 10px 0 0; text-align: right; }
.th-report button {
  /* 手指点得着：字号 12px，但上下各留 5px（按钮本身看着还是那一行小字） */
  padding: 5px 2px;
  border: 0;
  background: none;
  font: inherit;
  font-size: 12px;
  color: var(--th-ink-soft);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.th-report button:hover,
.th-report button:focus-visible { color: var(--th-accent); }

/* ===================================================================
   7. 手机：拼贴塌成两列，花哨的东西收起来
   =================================================================== */

@media (max-width: 700px) {
  .th-wall { grid-template-columns: repeat(6, 1fr); gap: 9px; }
  .th-shape-wide { grid-column: span 6; }
  .th-shape-left,
  .th-shape-right,
  .th-shape-center,
  .th-shape-tall { grid-column: span 6; grid-row: auto; }
  /* 异形在窄屏一律退化成圆角方块：小屏幕上花哨等于糊 */
  .th-shape-tri,
  .th-shape-notch,
  .th-shape-bump,
  .th-shape-arch,
  .th-shape-blob,
  .th-shape-torn,
  .th-shape-circle,
  .th-shape-ring,
  .th-shape-diamond {
    grid-column: span 3;
    aspect-ratio: auto;
    clip-path: none;
    border-radius: 16px;
    padding: 13px 14px;
    text-align: left;
    display: block;
    mask-image: none;
    -webkit-mask-image: none;
  }
  .th-shape-circle .th-who,
  .th-shape-ring .th-who,
  .th-shape-arch .th-who,
  .th-shape-diamond .th-who { justify-content: flex-start; }
  .th-shape-circle .th-body,
  .th-shape-ring .th-body,
  .th-shape-diamond .th-body { font-size: 14px; }

  /* 光斑和星点在小屏上省掉：它们不承载信息，只会让手机更累 */
  .th-aurora { display: none; }
  .th-spark:nth-child(n+7) { display: none; }
  .th-epigraph { padding: 22px 17px 20px; border-radius: 22px; }
  .th-quote { font-size: 16.5px; line-height: 1.8; }
  .th-epigraph .th-epi-last { font-size: 13.5px; margin-top: 14px; }

  /* 画布：窄屏把格子缩到放得下整块（32 × 12px 会横着溢出）。
     ⚠️ `.px-board` 还有 `max-width: 100%` 兜着 —— 这是第二道闸，
        因为作者选的档位是 JS 写在行内样式上的，能盖过这里的 clamp。 */
  .px-board { --cell-size: clamp(6px, calc((100vw - 96px) / 32), 12px); }
  .px-head { gap: 14px; }
  /* 看的那一页：手机上外框的边收窄一点，把省下的宽度给画 */
  .px-art-frame { padding: 6px; border-radius: 15px; }
  /* ⚠️ 手机上一律「画一行、文字一整行」：并排的话，画（最多 384px）挤完之后
     文字那栏只剩几个像素宽，字就全看不见了（用户报的「一坨」）。
     `flex: 1 1 100%` = 基准就是整行宽 → 它永远换到自己那一行去。 */
  .px-head-text { flex: 1 1 100%; }
}

/* ===================================================================
   8. 减弱动态效果：所有特效一起停
   ===================================================================
   ⚠️ 这一段**必须留着**（用户的系统开关就是「别动」的意思）：
      光斑、星点、扫光、呼吸、进场，一个都不留。
      别只关一半 —— 关一半的页面比全开还难受。
   =================================================================== */

@media (prefers-reduced-motion: reduce) {
  .th-aurora,
  .th-aurora i,
  .th-spark,
  .th-epigraph::after { display: none; }
  .th-card,
  .th-shape-circle,
  .th-shape-diamond { animation: none; }
  .th-card,
  .th-avatar,
  .th-link { transition: none; }
  .th-card:hover { transform: none; }
}
