/* ============================================================
   nori · Live2D 看板娘样式
   ------------------------------------------------------------
   命名空间：所有选择器都在 .nori- 前缀下，不污染主站任何类名。
   主体尺寸用 CSS 变量集中控制，方便后续调整。
   ============================================================ */

.nori-root {
  /* 宽度由 JS 按主站头像圆环净空实时写入，这里的初值只是兜底 */
  --nori-w: 256px;
  --nori-h: 458px;
  --nori-drag-x: 0px;
  --nori-drag-y: 0px;
  --nori-bubble-bg: rgba(255, 255, 255, 0.86);
  --nori-bubble-fg: #1b2233;
  --nori-bubble-bd: rgba(120, 140, 180, 0.28);

  position: fixed;
  left: 0;
  bottom: 0;
  width: var(--nori-w);
  height: var(--nori-h);
  z-index: 60;                           /* 低于主站浮层（主题按钮等），高于背景层 */
  pointer-events: none;                  /* 只有画布和按钮吃事件，不挡主站点击 */
  opacity: 0;
  transform: translateY(24px);
  transition: opacity .7s cubic-bezier(.22,.8,.3,1),
              transform .7s cubic-bezier(.22,.8,.3,1);
  will-change: opacity, transform;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

.nori-root[data-state="ready"] {
  opacity: 1;
  transform: translateY(0);
}

/* 加载失败：整块消失，不留空位 */
.nori-root[data-state="error"] {
  display: none !important;
}

/* 收起 / 窄屏隐藏 */
.nori-root.is-hidden {
  opacity: 0;
  transform: translateY(28px) scale(.96);
  pointer-events: none !important;
}

/* ---------- 舞台 ---------- */
.nori-stage {
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* 入场时从下方轻推上来 */
  transform: translateY(0);
}

.nori-canvas {
  position: absolute;
  inset: 0;
  width: 100% !important;
  height: 100% !important;
  display: block;
  pointer-events: auto;                  /* 只有它接收指针交互 */
  cursor: grab;
  touch-action: none;
  /* 拖拽摆动 + 呼吸抬升 */
  transform: translate(calc(var(--nori-drag-x) * .35), calc(var(--nori-drag-y) * .25));
  transition: transform .18s ease-out;
  filter: drop-shadow(0 18px 26px rgba(10, 16, 34, 0.30));
}

.nori-root.is-grab .nori-canvas {
  cursor: grabbing;
  transition: transform .04s linear;     /* 拖拽中即时跟手 */
}

/* 脚下接地阴影，让模型"站"在页面上而不是飘着 */
.nori-shadow {
  position: absolute;
  left: 50%;
  bottom: 6px;
  width: 168px;
  height: 22px;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at center,
              rgba(8, 14, 30, 0.34) 0%,
              rgba(8, 14, 30, 0.16) 45%,
              rgba(8, 14, 30, 0) 72%);
  filter: blur(3px);
  pointer-events: none;
  z-index: -1;
}

/* ---------- 对话气泡 ---------- */
.nori-bubble {
  position: absolute;
  /* 台词气泡。位置策略由 JS 通过 CSS 变量写入（见 updateBubbleSide）：
       --nori-bubble-x / --nori-bubble-y  气泡左上角相对画布的偏移
       --nori-bubble-w                    气泡宽度（按可用净空自适应）
     关键：必须给**固定宽度**（不是 max-width 让内容自己撑）——
     绝对定位元素在窄容器里靠 max-width 收缩，中文会被压成竖排。 */
  width: var(--nori-bubble-w, 190px);
  box-sizing: border-box;
  padding: 10px 13px;
  border-radius: 14px;
  left: var(--nori-bubble-x, calc(100% - 46px));
  top: var(--nori-bubble-y, 12%);
  background: var(--nori-bubble-bg);
  color: var(--nori-bubble-fg);
  border: 1px solid var(--nori-bubble-bd);
  box-shadow: 0 10px 26px rgba(12, 20, 40, 0.20);
  font-size: 13px;
  line-height: 1.6;
  font-weight: 500;
  backdrop-filter: blur(14px) saturate(1.5);
  -webkit-backdrop-filter: blur(14px) saturate(1.5);
  pointer-events: none;
  opacity: 0;
  /* 尖角默认在左下：指向画布右下方的她 */
  border-bottom-left-radius: 4px;
  transform: translate(-6px, 6px) scale(.94);
  transform-origin: 0 100%;
  transition: opacity .26s ease, transform .32s cubic-bezier(.34,1.4,.5,1);
  /* 台词是短句，保持整词换行 */
  white-space: normal;
  word-break: keep-all;
  overflow-wrap: break-word;
}

/* 贴在画布内侧右上时，尖角改到右下，仍朝向她头部 */
.nori-root[data-bubble-anchor="inside"] .nori-bubble {
  border-bottom-left-radius: 14px;
  border-bottom-right-radius: 4px;
  transform: translate(6px, 6px) scale(.94);
  transform-origin: 100% 100%;
}

/* 气泡按视口高度微调宽度，矮屏窄一点 */
@media (min-width: 1440px) and (max-height: 820px) {
  .nori-bubble { width: 172px; font-size: 12.5px; }
}

.nori-bubble[hidden] { display: none; }

.nori-bubble.is-show {
  opacity: 1;
  transform: translate(0, 0) scale(1);
}

/* 气泡跟随主题：深色主题用半透明深底更协调 */
:root:not([data-theme="light"]) .nori-root {
  --nori-bubble-bg: rgba(22, 30, 48, 0.82);
  --nori-bubble-fg: #eaf0ff;
  --nori-bubble-bd: rgba(150, 175, 225, 0.22);
}

:root:not([data-theme="light"]) .nori-hint {
  color: rgba(235, 242, 255, 0.92);
  background: rgba(22, 30, 48, 0.58);
  border-color: rgba(150, 175, 225, 0.20);
}

:root:not([data-theme="light"]) .nori-close {
  color: rgba(235, 242, 255, 0.88);
  background: rgba(22, 30, 48, 0.58);
  border-color: rgba(150, 175, 225, 0.22);
}

/* ---------- 提示 ---------- */
.nori-hint {
  position: absolute;
  left: 50%;
  bottom: 10px;
  transform: translateX(-50%);
  padding: 5px 11px;
  border-radius: 999px;
  font-size: 11px;
  letter-spacing: .04em;
  color: rgba(255, 255, 255, 0.92);
  background: rgba(20, 28, 46, 0.55);
  border: 1px solid rgba(160, 180, 220, 0.20);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  white-space: nowrap;
  pointer-events: none;
  opacity: .92;
  transition: opacity .9s ease;
}

.nori-hint.is-dim {
  opacity: 0;
}

/* ---------- 收起按钮 ---------- */
.nori-close {
  position: absolute;
  right: 10px;
  top: 10px;
  width: 26px;
  height: 26px;
  padding: 0;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid rgba(160, 180, 220, 0.26);
  background: rgba(20, 28, 46, 0.52);
  color: rgba(255, 255, 255, 0.88);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  cursor: pointer;
  pointer-events: auto;
  opacity: 0;
  transform: scale(.85);
  transition: opacity .3s ease, transform .3s ease,
              background-color .2s ease, color .2s ease;
}

.nori-close svg {
  width: 12px;
  height: 12px;
}

/* 悬停整块时才露出按钮，平时不打扰 */
.nori-root:hover .nori-close {
  opacity: 1;
  transform: scale(1);
}

.nori-close:hover {
  background: rgba(232, 96, 112, 0.85);
  border-color: rgba(232, 96, 112, 0.9);
  color: #fff;
}

/* ============================================================
   响应式尺寸
   ------------------------------------------------------------
   高度：按视口高度分档（矮屏收一档，避免盖住首屏正文）。
   宽度：由 JS 按「主站头像圆环左边界」实时写入 --nori-w，
        因为圆环位置取决于居中容器的 max-width，纯 CSS 分档
        在 1024~1440 段会算错（实测 1024 时圆环右边界仅 292px）。
   ============================================================ */

/* 矮视口收高度 */
@media (min-width: 1440px) and (max-height: 820px) {
  .nori-root { --nori-h: 400px; }
  .nori-shadow { width: 142px; }
}

@media (min-width: 1440px) and (max-height: 720px) {
  .nori-root { --nori-h: 350px; }
  .nori-shadow { width: 124px; }
  .nori-bubble { font-size: 12px; max-width: 178px; }
}

/* 高视口放开一些 */
@media (min-width: 1440px) and (min-height: 1000px) {
  .nori-root { --nori-h: 500px; }
}

/* ============================================================
   浅色主题适配
   主站用 [data-theme="light"]，这里跟随切换气泡配色。
   浅色下模型本身不需要滤镜（它自带贴图），但接地阴影要变浅。
   ============================================================ */
:root[data-theme="light"] .nori-root {
  --nori-bubble-bg: rgba(255, 255, 255, 0.94);
  --nori-bubble-fg: #202a3d;
  --nori-bubble-bd: rgba(110, 130, 170, 0.24);
}

:root[data-theme="light"] .nori-shadow {
  background: radial-gradient(ellipse at center,
              rgba(40, 55, 90, 0.20) 0%,
              rgba(40, 55, 90, 0.09) 45%,
              rgba(40, 55, 90, 0) 72%);
}

:root[data-theme="light"] .nori-hint {
  color: rgba(30, 40, 60, 0.88);
  background: rgba(255, 255, 255, 0.80);
  border-color: rgba(110, 130, 170, 0.22);
}

:root[data-theme="light"] .nori-close {
  color: rgba(30, 40, 60, 0.80);
  background: rgba(255, 255, 255, 0.80);
  border-color: rgba(110, 130, 170, 0.24);
}

:root[data-theme="light"] .nori-canvas {
  filter: drop-shadow(0 16px 22px rgba(40, 55, 90, 0.20));
}

/* ============================================================
   无障碍：尊重系统的"减少动效"偏好
   模型仍需渲染（否则功能就没了），但去掉浮入/拖拽过渡。
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .nori-root,
  .nori-canvas,
  .nori-bubble,
  .nori-close,
  .nori-hint {
    transition-duration: .01ms !important;
  }
  .nori-canvas {
    transform: none !important;
  }
}

/* ============================================================
   兜底：即使 JS 未及时隐藏，窄屏 / 触摸设备也不显示
   （JS 里已有闸门，这里是 CSS 层面的双保险）
   ============================================================ */
@media (max-width: 1439px) {
  .nori-root { display: none !important; }
}

@media (pointer: coarse) {
  .nori-root { display: none !important; }
}
