/* ============================================================
   tactile.css —— 按键手感
   ------------------------------------------------------------
   此前的问题：按键只有 hover 换一个背景色。点在屏幕上和点在水里
   一样——没有任何东西告诉你的手指"这件事发生了"。
   现实里的按键是有厚度的：木牌按下去会沉进案面，松手弹回来；
   墨落在纸上会洇开。这一层把这两件事做出来。
   时序原则（手感的关键，不是数值）：
     按下 60ms 快沉 —— 手指的感觉必须即时
     松开 320ms 带回弹 —— 物体有质量，回位要过一点再停
   ============================================================ */

/* ---------- ① 木牌：默认键 ---------- */
.btn{
  position:relative; overflow:hidden;
  padding:8px 17px;
  border:1px solid rgba(236,228,212,.26);
  border-radius:3px;
  background:linear-gradient(180deg, rgba(236,228,212,.11), rgba(236,228,212,.04));
  color:var(--on-desk);
  /* 0 2px 0 是这块木牌的厚度边，必须和按下时的位移同量 */
  box-shadow:
    0 2px 0 rgba(0,0,0,.46),
    0 3px 8px rgba(0,0,0,.30),
    inset 0 1px 0 rgba(255,255,255,.07);
  transform:translateY(0);
  transition:
    transform .32s cubic-bezier(.34,1.56,.64,1),
    box-shadow .32s var(--ease),
    background .24s var(--ease),
    color .24s var(--ease),
    border-color .24s var(--ease);
}
.btn:hover{
  transform:translateY(-1px);
  background:linear-gradient(180deg, rgba(236,228,212,.16), rgba(236,228,212,.07));
  box-shadow:
    0 3px 0 rgba(0,0,0,.46),
    0 6px 14px rgba(0,0,0,.38),
    inset 0 1px 0 rgba(255,255,255,.11);
}
/* 按下：厚度被压掉，牌面陷进去 */
.btn:active,
.btn.is-press{
  transform:translateY(2px);
  background:linear-gradient(180deg, rgba(236,228,212,.05), rgba(236,228,212,.09));
  box-shadow:
    0 0 0 rgba(0,0,0,0),
    0 1px 2px rgba(0,0,0,.34),
    inset 0 2px 5px rgba(0,0,0,.36);
  transition-duration:.06s;
  transition-timing-function:ease-out;
}

/* ---------- ② 朱漆键：盖下去的那一下 ---------- */
.btn--solid{
  background:linear-gradient(180deg, #a85245, #8d3f33);
  border-color:#7d372c;
  color:#fff8ee;
  box-shadow:
    0 2px 0 #6d2f26,
    0 3px 9px rgba(0,0,0,.40),
    inset 0 1px 0 rgba(255,255,255,.20);
}
.btn--solid:hover{
  background:linear-gradient(180deg, #b35a4c, #974537);
  box-shadow:
    0 3px 0 #6d2f26,
    0 6px 15px rgba(0,0,0,.45),
    inset 0 1px 0 rgba(255,255,255,.24);
}
.btn--solid:active,
.btn--solid.is-press{
  transform:translateY(2px);
  background:linear-gradient(180deg, #8d3f33, #963f33);
  box-shadow:
    0 0 0 #6d2f26,
    inset 0 2px 6px rgba(0,0,0,.48);
  transition-duration:.06s;
  transition-timing-function:ease-out;
}

/* ---------- ③ 印框键 / 筛选片：选中 = 盖章 ---------- */
.btn--ghost{
  background:transparent;
  border:1px dashed rgba(236,228,212,.30);
  color:var(--on-desk-soft);
  box-shadow:none;
}
.btn--ghost:hover{
  background:rgba(236,228,212,.07);
  color:var(--on-desk);
  border-color:rgba(236,228,212,.46);
  transform:translateY(-1px);
  box-shadow:0 2px 7px rgba(0,0,0,.28);
}
.btn--ghost:active,
.btn--ghost.is-press{
  transform:translateY(1px);
  box-shadow:inset 0 2px 5px rgba(0,0,0,.34);
  transition-duration:.06s;
}
/* 选中态不再是"换个边框色"，而是真的盖了个印 */
.btn--ghost.is-on{
  background:var(--seal);
  border:1px solid var(--seal);
  color:#fff8ee;
  box-shadow:0 2px 0 #6d2f26, 0 3px 9px rgba(0,0,0,.34);
}
.btn--ghost.is-on:hover{ background:#a85245; color:#fff8ee; }

/* ---------- ④ 墨涟漪：点在纸上，墨会洇开 ---------- */
.rip{
  position:absolute; z-index:1;
  border-radius:50%; pointer-events:none;
  background:radial-gradient(circle,
    rgba(36,42,46,.30) 0%, rgba(36,42,46,.14) 52%, transparent 72%);
  transform:translate(-50%,-50%) scale(0);
  opacity:.95;
  animation:rip .62s var(--ease) forwards;
}
.btn--solid .rip,
.btn--ghost.is-on .rip,
.seal-stamp .rip,
.mainnav a.is-active .rip{
  background:radial-gradient(circle,
    rgba(255,248,238,.44) 0%, rgba(255,248,238,.18) 52%, transparent 72%);
}
@keyframes rip{
  from{ transform:translate(-50%,-50%) scale(0);   opacity:.95; }
  to  { transform:translate(-50%,-50%) scale(1);   opacity:0; }
}

/* ---------- ⑤ 纸卡：抬起来 / 按下去 ---------- */
a.card{ cursor:pointer; }
a.card:hover{
  transform:translateY(-5px);
  filter:brightness(1.012);
}
a.card:active,
.card.is-press{
  transform:translateY(0) scale(.994);
  transition-duration:.08s;
  transition-timing-function:ease-out;
}
/* 卡里的"→" 在 hover 时向前挪一点，暗示这是入口 */
a.card:hover .card__go{ transform:translateX(4px); }
.card__go{ display:inline-block; transition:transform .3s var(--ease); }

/* ---------- ⑥ 导航：当前项是一条压在纸上的朱红题签 ---------- */
.mainnav a{ position:relative; }
.mainnav a::after{
  content:""; position:absolute; left:50%; bottom:1px;
  width:0; height:2px; border-radius:1px;
  background:var(--seal);
  transform:translateX(-50%);
  transition:width .32s var(--ease), opacity .32s var(--ease);
  opacity:0;
}
.mainnav a:hover::after{ width:36%; opacity:.55; }
.mainnav a.is-active::after{ width:64%; opacity:1; }

/* ---------- ⑦ 键盘：焦点必须看得见，而且和鼠标一样有反馈 ---------- */
.btn:focus-visible,
.mainnav a:focus-visible,
a.card:focus-visible,
.seal-stamp:focus-visible,
.field:focus-visible,
.slider:focus-visible{
  outline:2px solid var(--seal);
  outline-offset:3px;
  border-radius:3px;
}

/* ---------- ⑧ 禁用 / 进行中：纸被压平了 ---------- */
.btn:disabled,
.btn.is-off{
  opacity:.38;
  transform:none !important;
  box-shadow:inset 0 1px 3px rgba(0,0,0,.30);
  cursor:default;
  background:rgba(236,228,212,.05);
}
.btn.is-busy{
  cursor:progress;
  color:var(--on-desk-faint);
}
.btn.is-busy::before{
  content:""; display:inline-block; vertical-align:-1px;
  width:9px; height:9px; margin-right:7px;
  border:2px solid rgba(236,228,212,.28);
  border-top-color:var(--seal);
  border-radius:50%;
  animation:spin .7s linear infinite;
}
@keyframes spin{ to{ transform:rotate(360deg); } }

/* ---------- ⑨ 输入与滑块：同样是有厚度的东西 ---------- */
.field{
  transition:border-color .24s var(--ease), box-shadow .24s var(--ease),
             transform .24s var(--ease);
  box-shadow:inset 0 1px 3px rgba(0,0,0,.26);
}
.field:hover{ border-color:rgba(236,228,212,.34); }
.field:focus{
  border-color:var(--seal);
  box-shadow:inset 0 1px 3px rgba(0,0,0,.26), 0 0 0 3px rgba(156,74,60,.20);
  outline:none;
}
/* 滑块：轨道是纸槽的木沿，滑块是一片竹 */
.slider::-webkit-slider-runnable-track{
  height:8px;
  background:linear-gradient(180deg, #171310, #2b2520);
  border:1px solid rgba(236,228,212,.22);
  border-radius:4px;
  box-shadow:inset 0 1px 3px rgba(0,0,0,.55);
}
.slider::-webkit-slider-thumb{
  -webkit-appearance:none; appearance:none;
  width:16px; height:26px; margin-top:-10px;
  border-radius:3px;
  background:linear-gradient(180deg, #e9dfc8, #cdc2a8);
  border:1px solid #8d8471;
  box-shadow:0 2px 0 rgba(0,0,0,.40), 0 3px 7px rgba(0,0,0,.35);
  transition:transform .12s var(--ease), box-shadow .12s var(--ease);
}
.slider:hover::-webkit-slider-thumb{ transform:scaleY(1.06); }
.slider:active::-webkit-slider-thumb{
  transform:scaleY(.94);
  box-shadow:0 0 0 rgba(0,0,0,0), inset 0 2px 4px rgba(0,0,0,.4);
}
.slider::-moz-range-track{
  height:8px;
  background:linear-gradient(180deg, #171310, #2b2520);
  border:1px solid rgba(236,228,212,.22);
  border-radius:4px;
}
.slider::-moz-range-thumb{
  width:14px; height:24px; border-radius:3px;
  background:linear-gradient(180deg, #e9dfc8, #cdc2a8);
  border:1px solid #8d8471;
  box-shadow:0 2px 0 rgba(0,0,0,.40);
}
.slider:focus-visible::-webkit-slider-thumb{ box-shadow:0 0 0 3px rgba(156,74,60,.5); }

/* ---------- ⑩ 换页：抽走一张纸，铺上另一张 ---------- */
@keyframes stageSwap{
  from{ opacity:0; transform:translateY(12px) rotate(-.4deg); }
  to  { opacity:1; transform:none; }
}
.stage.is-swap{ animation:stageSwap .34s var(--ease); }

/* ---------- ⑪ 尊重系统设置 ---------- */
@media (prefers-reduced-motion: reduce){
  .btn, .btn--solid, .btn--ghost, a.card{ transition-duration:.01ms !important; }
  .btn:hover, a.card:hover{ transform:none; }
  .rip{ display:none; }
  .stage.is-swap{ animation:none; }
}
