/* ══════════════════════════════════════════════════════════════════
   音姬 · Web 版样式（端口：miniprogram/pages/nearby/nearby.wxss 的音姬部分）
   视觉基准对齐小程序端：白底+墨边圆形钮、开启态主色实底、绿点脉动、
   红色冲水钮脉冲、满屏白色胶囊文案。
   rpx→px 按 1rpx = 0.5px（390px 宽基准）。

   位置：音姬按钮挂在 .cq-hero 内（position:absolute 定位到 hero 右下），
        与小程序端「hero 搜索行右侧」一致，并**顶替原 .cq-doodle 🚽 装饰**。
        ⚠️ 勿改回 position:fixed 吸底 —— 那会跑到页面最下方 tab 上方，位置全错。
   ══════════════════════════════════════════════════════════════════ */

/* 动画层容器：本身不定位，里面都是 fixed 层 */
.cq-oto-anim-layers { position: static; }

/* ── 搜索行：搜索框收窄，右侧让位给音姬钮（对齐小程序端 .cq-search-row）──
   与小程序端同值换算：gap 16rpx→8px、按钮 88rpx→44px。 */
.cq-search-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
/* 搜索框在行内可收缩，让出右侧 44px 给音姬钮 */
.cq-search-row .cq-search { flex: 1; min-width: 0; }

/* ── 圆形马桶钮（搜索行内、搜索框右侧）── */
.cq-oto {
  /* ⚠️ 布局要点：**流内 flex 元素**，不是absolute、也不是 fixed。
     小程序端它就是 .cq-search-row 里的一个 flex 子项（.cq-flush-side），
     跟在搜索框后面。之前误做成 absolute（hero 右下角）→ 又误做成 fixed（吸底跑tab 上方），
     两种都错；正确做法就是回到 flex 行里。 */
  position: relative;
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  z-index: 6;
  font-family: var(--font-text, "Noto Sans SC", "PingFang SC", system-ui, sans-serif);
}

.cq-oto-btn {
  position: relative;
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  padding: 0;
  font-size: 24px; line-height: 1;
  background: #fff;
  border: 1px solid var(--ink, #283e44);
  border-radius: 50%;
  box-shadow: 2px 2px 0 var(--ink, #283e44);
  cursor: pointer;
  transition: transform .06s ease, box-shadow .06s ease;
}
.cq-oto-btn:active,
.cq-oto-btn.open {
  transform: translate(1px, 1px);
  box-shadow: 0 0 0 rgba(40, 60, 66, .85);
}
/* 播放态：开启态语汇——主色实底 */
.cq-oto-btn.on {
  background: var(--c-neg, #c0392b);
  border-color: var(--c-neg, #c0392b);
}
.cq-oto-btn.on .cq-oto-emoji { filter: grayscale(1) brightness(3); }

/* 播放中绿点脉动 */
.cq-oto-dot {
  position: absolute; top: -2px; right: -2px;
  width: 10px; height: 10px;
  background: #2fae5f;
  border: 1.5px solid #fff;
  border-radius: 50%;
  animation: cqOtoPulse 1.2s ease-in-out infinite;
}
@keyframes cqOtoPulse {
  0%, 100% { transform: scale(1); opacity: 1; box-shadow: 0 0 0 1px rgba(47, 174, 95, .35); }
  50%      { transform: scale(1.3); opacity: .75; box-shadow: 0 0 0 4px rgba(47, 174, 95, 0); }
}

/* ── 音效下拉选单（按钮正下方）──
   ⚠️ 挂在 body 层（.cq-flush-menu 在 animRoot 内），故用 fixed + JS 实算 left/top。
      不能靠 .cq-oto 的 absolute 定位：.cq-hero 有 overflow:hidden 会把菜单裁掉。 */
.cq-flush-menu {
  position: fixed;
  left: 0; top: 0;          /* 首帧兜底，openMenu() 里按按钮实算覆盖 */
  width: 208px;
  padding: 10px;
  background: #fffdf7;
  border: 1px solid var(--ink, #283e44);
  border-radius: 14px;
  box-shadow: 3px 3px 0 var(--ink, #283e44);
  z-index: 62;
}
.cq-flush-menu[hidden] { display: none; }
.cq-flush-menu-title {
  font-size: 11px; font-weight: 700;
  color: rgba(40, 60, 66, .55);
  padding: 0 4px 6px;
}
.cq-flush-menu-list { display: flex; flex-direction: column; gap: 2px; }
.cq-flush-menu-item {
  display: flex; align-items: center; gap: 6px;
  width: 100%;
  padding: 7px 8px;
  font: inherit; font-size: 13px; text-align: left;
  color: var(--ink, #283e44);
  background: transparent;
  border: 0; border-radius: 8px;
  cursor: pointer;
}
.cq-flush-menu-item:hover { background: rgba(40, 60, 66, .06); }
.cq-flush-menu-item.on {
  font-weight: 700;
  background: #fff7e0;
  border: 1px solid rgba(40, 60, 66, .28);
}
.cq-flush-menu-check { width: 12px; color: var(--c-neg, #c0392b); }
.cq-flush-menu-stop {
  margin-top: 6px;
  padding-top: 8px;
  border-top: 1px solid rgba(40, 60, 66, .14);
  border-radius: 0;
  color: var(--c-neg, #c0392b);
  font-weight: 700;
}
.cq-flush-menu-stop:hover { background: rgba(192, 57, 43, .08); }
.cq-flush-menu-tip {
  margin-top: 6px; padding: 0 4px;
  font-size: 10px; line-height: 1.5;
  color: rgba(40, 60, 66, .5);
}

/* ── 马桶冲水动画 ──
   ⚠️ 必须**独立 fixed 层**，不能嵌在 .cq-oto 里：.cq-oto 宽度由 44px 按钮决定，
   内嵌的 canvas 会只拿到 44px 宽（实测画布 44×389，马桶被压成一条）。
   独立成 fixed 层后宽度取视口，底部留出列表区域的位置，与小程序端「占列表区域、
   不全屏遮挡」一致。z-index 取 19（高于 .cq-bottom 的 5，低于漏水层 20）。
   */
.cq-flush-anim {
  position: fixed;
  left: 0; right: 0;
  bottom: 0;
  height: 58vh;
  min-height: 320px;
  max-height: 560px;
  z-index: 19;
  pointer-events: none;   /* 画布不吃事件；按钮热区单独开 */
}
.cq-flush-anim[hidden] { display: none; }
.cq-flush-canvas { width: 100%; height: 100%; display: block; }

/* 红色冲水钮热区：绝对定位的透明圆，位置由 JS 按 drawVortex 几何算出 */
.cq-flush-btn-hit {
  position: absolute;
  border-radius: 50%;
  background: transparent;
  border: 0; padding: 0;
  cursor: pointer;
  z-index: 2;
  pointer-events: auto;
}
.cq-flush-btn-hit[hidden] { display: none; }
/* 红色脉冲光环（纯 CSS，不占 rAF）*/
.cq-flush-btn-hit::before,
.cq-flush-btn-hit::after {
  content: '';
  position: absolute; inset: -12%;
  border: 1.5px solid var(--c-neg, #c0392b);
  border-radius: 50%;
  animation: cqOtoRipple 1.8s ease-out infinite;
}
.cq-flush-btn-hit::after { animation-delay: .9s; }
@keyframes cqOtoRipple {
  0%   { transform: scale(.82); opacity: .85; }
  70%  { transform: scale(1.35); opacity: 0; }
  100% { transform: scale(1.35); opacity: 0; }
}

/* 连按过频劝阻文案：马桶下方浮出，纸墨配色（此处非水面） */
.cq-flush-nudge {
  position: absolute;
  left: 0; right: 0; bottom: 8%;
  display: flex; justify-content: center;
  pointer-events: none;
  z-index: 4;
}
.cq-flush-nudge[hidden] { display: none; }
.cq-flush-nudge.in .cq-flush-nudge-txt { animation: cqOtoNudgeIn .24s ease-out; }
@keyframes cqOtoNudgeIn {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
.cq-flush-nudge-txt {
  font-family: var(--font-display, "Noto Sans SC", "PingFang SC", system-ui, sans-serif);
  font-size: 20px;
  font-weight: 800;
  letter-spacing: 2px;
  color: var(--ink, #283e44);
  padding: 8px 18px;
  background: #fffdf7;
  border: 1px solid var(--ink, #283e44);
  border-radius: 999px;
  box-shadow: 2px 2px 0 var(--ink, #283e44);
}

/* ── 漏水成灾动画（全屏固定层，z-index 低于吸底 tab）── */
.cq-flood-anim {
  position: fixed;
  left: 0; right: 0; top: 0; bottom: 0;
  z-index: 20;
  background: transparent;
  cursor: pointer;
}
.cq-flood-anim[hidden] { display: none; }
.cq-flood-canvas { width: 100%; height: 100%; display: block; }

/* 满屏文案：白色胶囊，居中，4 秒后自动消失 */
.cq-flood-msg {
  position: absolute; left: 0; right: 0; top: 0; bottom: 0;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
  z-index: 25;
}
.cq-flood-msg[hidden] { display: none; }
.cq-flood-msg-txt {
  font-family: var(--font-display, "Noto Sans SC", "PingFang SC", system-ui, sans-serif);
  font-size: 22px;
  font-weight: 800;
  letter-spacing: 3px;
  color: #fff;
  text-shadow: 0 1px 6px rgba(10, 40, 60, .55);
  padding: 10px 20px;
  border: 1px solid rgba(255, 255, 255, .75);
  border-radius: 999px;
  background: rgba(12, 50, 72, .28);
}

/* ── 页面正中大字提示（已切换到哪个音效）── */
.cq-flush-hint {
  position: fixed;
  left: 50%; top: 44%;
  transform: translate(-50%, -50%);
  text-align: center;
  pointer-events: none;
  z-index: 70;
}
.cq-flush-hint[hidden] { display: none; }
.cq-flush-hint.in { animation: cqOtoHintIn .22s ease-out; }
@keyframes cqOtoHintIn {
  from { opacity: 0; transform: translate(-50%, -46%); }
  to   { opacity: 1; transform: translate(-50%, -50%); }
}
.cq-flush-hint-title {
  font-size: 11px; font-weight: 700;
  letter-spacing: 2px;
  color: rgba(40, 60, 66, .55);
}
.cq-flush-hint-label {
  margin-top: 4px;
  font-family: var(--font-display, "Noto Sans SC", "PingFang SC", system-ui, sans-serif);
  font-size: 28px;
  font-weight: 800;
  color: var(--ink, #283e44);
}

/* ── 移动端微调 ──
   ⚠️ 此处**不可**再有 `.cq-oto { right/bottom }`：音姬钮已是搜索行内的流内元素，
   给它设 bottom 会把它顶出行外（实测手机 390px 下 bottom:76px → computed
   top:-76px，按钮飘到 y=49 而搜索行在 y=122，差 73px）。
   距右边距由 .cq-search-row 的 gap 控制，不在此覆盖。 */
@media (max-width: 480px) {
  .cq-flush-menu { width: 190px; }
  .cq-flush-nudge-txt { font-size: 18px; letter-spacing: 1px; }
  .cq-flood-msg-txt { font-size: 19px; letter-spacing: 2px; }
  .cq-flush-hint-label { font-size: 24px; }
}

/* ── 无障碍：尊重「减少动态效果」偏好 ── */
@media (prefers-reduced-motion: reduce) {
  .cq-oto-dot,
  .cq-flush-btn-hit::before,
  .cq-flush-btn-hit::after { animation: none; }
}