/* ============================================================================
   ui-interact.css — 梦一城 · 交互与动效组件层 v2（源自「大厂风格 UI/交互/动效提示词库」）
   ----------------------------------------------------------------------------
   来源：把提示词库里**可量化**的部分落成代码
     · 6.1 色彩    → --ui-* 已在 ui-tokens.css，这里只补新增项
     · 6.2 排版    → tabular-nums / 四级字重 / 行高 1.5 / 辅助 12px
     · 6.3 圆角阴影 → 卡片 8–16、按钮胶囊、输入框 6–8、阴影 0 2px 8px rgba(0,0,0,.06)
     · 第 4 章交互  → 转场 300ms cb(.25,.1,.25,1) / 表单聚焦蓝光 / 错误抖动 /
                      底部面板 350ms 弹簧 / 确认框 scale .95→1 200ms / Toast 1.8s
     · 第 5 章动效  → 按钮按下 scale .97 150ms / 卡片悬浮 lift 4px 250ms cb(.2,.8,.2,1) /
                      数字滚动 1.2s / 折线 dashoffset 1.5s / 环形 1s + 100ms 错峰 /
                      滚动进场 stagger 100ms 600ms ease-out

   铁律：
     1. 全部 .ui-* 选择器，**零全局元素选择器** —— 丢进任何老页面都不会污染既有样式
     2. 只【新增】变量，不覆盖 ui-tokens.css 的旧值（新 pr 有意保留旧名）
     3. 依赖 ui-tokens.css 先加载；缺了也能降级（这里有 fallback）
   引入：<link rel="stylesheet" href="/ui-interact.css">
   ========================================================================== */

:root{
  /* ── 6.3 阴影：按大厂通用口径补齐两档 ─────────────────────── */
  --ui-sh-base:0 2px 8px rgba(0,0,0,.06);      /* 静止态 */
  --ui-sh-hover:0 8px 24px rgba(0,0,0,.10);    /* 悬浮态 */

  /* ── 6.3 圆角：补齐三档标准值 ─────────────────────────────── */
  --ui-r-input:8px;        /* 输入框 6–8px，取 8 */
  --ui-r-card-sm:8px;      /* 紧凑小卡 */
  --ui-r-card-lg:16px;     /* 大卡上限 */

  /* ── 6.3 间距：8 栅格 + 卡片 16 + 页面 16–20 ──────────────── */
  --ui-gap-card:16px;
  --ui-pad-page-m:16px;

  /* ── 第 4/5 章动效时长与缓动（全部按文档原文取值） ────────── */
  --ui-t-press:150ms;      /* 按钮按下 */
  --ui-t-page:300ms;       /* 页面转场 */
  --ui-t-back:250ms;       /* 返回手势（ease-out） */
  --ui-t-hover:250ms;      /* 卡片悬浮 */
  --ui-t-form:300ms;       /* 按钮可用性切换 */
  --ui-t-sheet:350ms;      /* 底部面板上滑 */
  --ui-t-dialog:200ms;     /* 确认框 */
  --ui-t-toast:1800ms;     /* Toast 停留 */
  --ui-t-fade:200ms;       /* 通用淡出 */
  --ui-t-count:1200ms;     /* KPI 数字滚动 */
  --ui-t-chart:1500ms;     /* 折线自绘 */
  --ui-t-donut:1000ms;     /* 环形扫入 */
  --ui-t-reveal:600ms;     /* 滚动进场 */
  --ui-stagger-page:100ms; /* 滚动进场错峰 */
  --ui-stagger-list:50ms;  /* 列表错峰 */
  --ui-t-skeleton:1400ms;  /* 骨架微光周期 */

  --ui-e-spring:cubic-bezier(.34,1.56,.64,1);   /* 回弹 */
  --ui-e-page:cubic-bezier(.25,.1,.25,1);       /* 转场，文档原文 */
  --ui-e-out2:cubic-bezier(.2,.8,.2,1);         /* 卡片悬浮，文档原文 */
  --ui-dim:rgba(0,0,0,.4);                      /* 面板遮罩 + blur */
}

/* ============================================================================
   6.2 排版工具
   ========================================================================== */
.ui-num,
.ui-num td,
.ui-num th{
  font-variant-numeric:tabular-nums;
  -webkit-font-feature-settings:"tnum" 1;
  font-feature-settings:"tnum" 1;
}
.ui-lh{line-height:1.5}
.ui-w4{font-weight:400}.ui-w5{font-weight:500}
.ui-w6{font-weight:600}.ui-w7{font-weight:700}
.ui-aux{font-size:12px;color:var(--ui-ink-3,#86909C)}

@media (max-width:640px){
  .ui-page{padding:var(--ui-pad-page-m)}
}

/* ============================================================================
   5.1 按钮按下 + 卡片悬浮（文档原文参数，但只作用于 .ui-*，不动全局）
   ========================================================================== */
.ui-btn{
  transition:transform var(--ui-t-press) var(--ui-e-out,cubic-bezier(.2,.8,.2,1)),
             filter var(--ui-t-press) var(--ui-e-out,cubic-bezier(.2,.8,.2,1)),
             background-color var(--ui-t-press) ease,
             box-shadow var(--ui-t-press) ease,
             opacity var(--ui-t-form) ease;
}
.ui-btn:active:not(:disabled):not([disabled]){
  transform:scale(.97);
  filter:brightness(.95);
}
.ui-btn.is-loading{pointer-events:none;opacity:.75}

/* 文档：卡片悬浮 lift 4px + 阴影 0 2px 8px → 0 12px 24px，250ms */
.ui-card--hover{
  transition:transform var(--ui-t-hover) var(--ui-e-out2),
             box-shadow var(--ui-t-hover) var(--ui-e-out2);
  box-shadow:var(--ui-sh-base);
}
@media (hover:hover){
  .ui-card--hover:hover{
    transform:translateY(-4px);
    box-shadow:0 12px 24px rgba(0,0,0,.10);
  }
}

/* ============================================================================
   5.1 图标按钮 / Tab 指示器滑动（300ms 弹簧）
   ========================================================================== */
.ui-iconbtn{
  display:inline-flex;align-items:center;justify-content:center;
  width:32px;height:32px;border:0;background:transparent;border-radius:8px;
  color:var(--ui-ink-2,#4E5969);cursor:pointer;
  transition:background var(--ui-t-hover) ease,transform var(--ui-t-hover) var(--ui-e-spring);
}
.ui-iconbtn:hover{background:rgba(0,0,0,.05);transform:rotate(5deg)}

.ui-tabs{position:relative;display:flex;gap:4px;padding:4px;background:var(--ui-surface-2,#F7F8FA);border-radius:999px}
.ui-tabs__pill{
  position:absolute;top:4px;bottom:4px;left:0;border-radius:999px;
  background:var(--ui-surface,#fff);box-shadow:var(--ui-sh-base);
  transition:transform var(--ui-t-page) var(--ui-e-spring),width var(--ui-t-page) var(--ui-e-spring);
  pointer-events:none;
}
.ui-tabs__item{position:relative;z-index:1;flex:1;text-align:center;padding:6px 14px;
  font-size:13px;color:var(--ui-ink-2,#4E5969);cursor:pointer;border:0;background:transparent;
  border-radius:999px;transition:color var(--ui-t-page) ease}
.ui-tabs__item.is-on{color:var(--ui-primary,#165DFF);font-weight:600}

/* ============================================================================
   4.3 表单：浮动标签 + 聚焦蓝光 + 校验通过勾 + 错误抖动
   用法：<label class="ui-field"><input placeholder=" "><span class="ui-field__label">名称</span></label>
   ========================================================================== */
.ui-field{position:relative;display:block}
.ui-field>input,
.ui-field>textarea,
.ui-field>select{
  width:100%;height:40px;padding:0 12px;
  border:1px solid var(--ui-line-input,#D9DCE2);border-radius:var(--ui-r-input);
  background:var(--ui-surface,#fff);color:var(--ui-ink-1,#1D2129);font-size:14px;
  transition:border-color var(--ui-t-page) ease,box-shadow var(--ui-t-page) ease;
}
.ui-field>textarea{height:auto;min-height:88px;padding:10px 12px;resize:vertical}
.ui-field>input:focus,
.ui-field>textarea:focus,
.ui-field>select:focus{
  outline:none;
  border-color:var(--ui-primary,#165DFF);
  box-shadow:0 0 0 3px var(--ui-primary-ring,rgba(22,93,255,.14));
}
.ui-field__label{
  position:absolute;left:10px;top:11px;padding:0 4px;
  background:var(--ui-surface,#fff);color:var(--ui-ink-3,#86909C);font-size:14px;
  pointer-events:none;transform-origin:left center;
  transition:transform var(--ui-t-page) var(--ui-e-out2),color var(--ui-t-page) ease,font-size var(--ui-t-page) ease;
}
/* 浮动起来：依赖 placeholder=" " 触发 :placeholder-shown */
.ui-field>input:focus+.ui-field__label,
.ui-field>input:not(:placeholder-shown)+.ui-field__label,
.ui-field>textarea:focus+.ui-field__label,
.ui-field>textarea:not(:placeholder-shown)+.ui-field__label{
  transform:translateY(-20px) scale(.86);
  color:var(--ui-primary,#165DFF);
}
.ui-field__ok,.ui-field__msg{position:absolute;right:10px;top:12px;font-size:13px;opacity:0;transform:translateX(4px);
  transition:opacity var(--ui-t-dialog) ease,transform var(--ui-t-dialog) ease;pointer-events:none}
.ui-field.is-ok>.ui-field__ok{opacity:1;transform:none;color:var(--ui-ok,#00B42A)}
.ui-field.is-err>input,.ui-field.is-err>textarea{border-color:var(--ui-danger,#F53F3F)}
.ui-field.is-err>.ui-field__msg{
  position:static;display:block;margin-top:4px;padding:0 2px;opacity:1;transform:none;
  color:var(--ui-danger,#F53F3F);font-size:12px;
}
.ui-field.is-shake{animation:ui-shake 220ms ease}
@keyframes ui-shake{
  0%,100%{transform:translateX(0)}
  25%{transform:translateX(-2px)}
  75%{transform:translateX(2px)}
}
.ui-field.is-ok>input{border-color:var(--ui-ok,#00B42A)}

/* ============================================================================
   4.4 Bottom sheet / Dialog（文档原文：350ms 弹簧上滑 + 遮罩 rgba(0,0,0,.4) blur）
   ========================================================================== */
.ui-dim{
  position:fixed;inset:0;z-index:var(--ui-z-dialog,3200);
  background:var(--ui-dim);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);
  opacity:0;pointer-events:none;transition:opacity var(--ui-t-page) ease;
}
.ui-dim.is-open{opacity:1;pointer-events:auto}

.ui-sheet{
  position:fixed;left:0;right:0;bottom:0;z-index:calc(var(--ui-z-dialog,3200) + 1);
  padding:16px 16px calc(16px + env(safe-area-inset-bottom));
  background:var(--ui-surface,#fff);border-radius:16px 16px 0 0;box-shadow:0 -8px 32px rgba(0,0,0,.14);
  transform:translateY(100%);
  transition:transform var(--ui-t-sheet) var(--ui-e-spring);
}
.ui-sheet.is-open{transform:translateY(0)}
.ui-sheet__grab{width:36px;height:4px;margin:-6px auto 12px;border-radius:999px;background:var(--ui-line,#E5E6EB)}

.ui-dialog{
  position:fixed;z-index:calc(var(--ui-z-dialog,3200) + 2);
  left:50%;top:50%;min-width:300px;max-width:calc(100vw - 32px);
  padding:20px;background:var(--ui-surface,#fff);border-radius:var(--ui-r-card-lg);
  box-shadow:0 12px 40px rgba(0,0,0,.18);
  transform:translate(-50%,-50%) scale(.95);opacity:0;pointer-events:none;
  transition:transform var(--ui-t-dialog) var(--ui-e-out2),opacity var(--ui-t-dialog) ease;
}
.ui-dialog.is-open{transform:translate(-50%,-50%) scale(1);opacity:1;pointer-events:auto}
.ui-dialog__act{display:flex;justify-content:flex-end;gap:10px;margin-top:18px}

/* ============================================================================
   4.4 Toast：勾的描边 400ms 画出来
   ========================================================================== */
.ui-toast__ico{width:18px;height:18px;margin-right:8px;vertical-align:-3px}
.ui-toast__ico path{
  stroke:var(--ui-ok,#00B42A);stroke-width:2.4;fill:none;
  stroke-linecap:round;stroke-linejoin:round;
  stroke-dasharray:24;stroke-dashoffset:24;
  animation:ui-draw 400ms ease forwards;
}
@keyframes ui-draw{to{stroke-dashoffset:0}}

/* ============================================================================
   4.2 骨架屏：文档口径 1.4s 微光 + 成功 200ms 交叉淡入
   ========================================================================== */
.ui-skel{
  position:relative;overflow:hidden;background:#E5E6EB;border-radius:var(--ui-r-card-sm);
}
.ui-skel::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(90deg,rgba(255,255,255,0) 0%,rgba(255,255,255,.85) 50%,rgba(255,255,255,0) 100%);
  animation:ui-shimmer var(--ui-t-skeleton) infinite;
}
@keyframes ui-shimmer{0%{transform:translateX(-100%)}100%{transform:translateX(100%)}}
.ui-skel.is-done{animation:ui-fadeout var(--ui-t-fade) ease forwards}
@keyframes ui-fadeout{to{opacity:0;visibility:hidden}}

/* 旋转加载 */
.ui-spin{
  width:16px;height:16px;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;
  border-radius:50%;display:inline-block;vertical-align:-2px;
  animation:ui-spin 700ms linear infinite;
}
.ui-spin--dark{border-color:rgba(0,0,0,.15);border-top-color:var(--ui-primary,#165DFF)}
@keyframes ui-spin{to{transform:rotate(360deg)}}

/* ============================================================================
   5.2 滚动进场（配合 ui-reveal.js；无 JS 时保持可见，不会白屏）
   ========================================================================== */
.ui-reveal{opacity:1}
.ui-reveal[data-ui-reveal]{
  opacity:0;
  transition:opacity var(--ui-t-reveal) ease-out,transform var(--ui-t-reveal) ease-out;
}
.ui-reveal[data-ui-reveal="up"]{transform:translateY(40px)}
.ui-reveal[data-ui-reveal="left"]{transform:translateX(-40px)}
.ui-reveal[data-ui-reveal="right"]{transform:translateX(40px)}
.ui-reveal.is-in{opacity:1;transform:none}

/* 5.3 图表：折线自绘 + 数据点弹出 + 环形扫入 */
.ui-chart-path{
  stroke-dasharray:var(--ui-len,1000);stroke-dashoffset:var(--ui-len,1000);
  animation:ui-drawpath var(--ui-t-chart) ease-in-out forwards;
}
@keyframes ui-drawpath{to{stroke-dashoffset:0}}
.ui-chart-dot{
  transform-box:fill-box;transform-origin:center;
  animation:ui-pop 300ms var(--ui-e-spring) backwards;
}
@keyframes ui-pop{0%{transform:scale(0)}60%{transform:scale(1.2)}100%{transform:scale(1)}}
.ui-chart-arc{
  transform-box:fill-box;transform-origin:center;
  animation:ui-sweep var(--ui-t-donut) ease-out backwards;
}
@keyframes ui-sweep{from{transform:rotate(-90deg) scale(0)}to{transform:rotate(0) scale(1)}}

/* ============================================================================
   无障碍：尊重系统降低动效设置 —— 关掉位移与缩放，只保留淡入淡出
   ========================================================================== */
@media (prefers-reduced-motion:reduce){
  .ui-reveal[data-ui-reveal]{opacity:1;transform:none;transition:opacity 120ms linear}
  .ui-btn:active:not(:disabled){transform:none}
  .ui-card--hover,.ui-sheet,.ui-dialog,.ui-tabs__pill{transition-duration:1ms}
  .ui-skel::after{animation:none}
  .ui-spin{animation-duration:1.6s}
}
