@charset "UTF-8";
/* ==========================================================================
   千岩服务平台 · H5 专有样式（**不来自小程序，是浏览器环境必需的部分**）
   --------------------------------------------------------------------------
   职责边界（很重要，避免与自动生成的小程序样式打架）：

     app.css        ← 本文件：H5 **专有**的东西
                      · 浏览器兼容重置（小程序没有的）
                      · 小程序没有原生对应物的交互组件（Toast / 弹窗 / 加载 / 骨架屏）
                      · H5 实现细节（轮播位移、跑马灯动画、底部安全区）
                      · 响应式工具类（.desktop-only / .mobile-only）

     mp-mobile.css  ← **自动生成**（tools-docs/build/wxss-to-css.js）
                      小程序全部外观。**不要手改**，要改去改 weapp/miniprogram。

     desktop.css    ← 宽屏（≥768px）布局覆盖。

   引入顺序必须是 app.css → mp-mobile.css → desktop.css：
     小程序样式在后，可覆盖本文件里同名的中性默认值；
     宽屏覆盖在最后。
   ========================================================================== */

/* ==========================================================================
   1. 浏览器重置（小程序没有这些坑）
   ========================================================================== */

* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html { -webkit-text-size-adjust: 100%; }

/* 🔴 [hidden] 必须能压过任何作者样式
   HTML 的 hidden 属性只靠 UA 样式表的 `display:none`，**作者样式的 display
   一定能覆盖它**（作者 > UA，与选择器权重无关）。
   本项目多次用 hidden 控制浮层显隐（如分类页的筛选弹窗），
   若某处写了 display:flex，浮层就会「默认可见」——实测踩过这个坑。 */
[hidden] { display: none !important; }

img { max-width: 100%; }

/* 小程序 <input> 天然继承字体；浏览器要显式声明 */
input, button, textarea, select { font-family: inherit; font-size: inherit; color: inherit; }
button { cursor: pointer; border: none; background: none; }

/* 去掉 iOS 上 input 的默认内阴影与圆角 */
input[type="text"], input[type="search"], input[type="tel"], textarea {
  -webkit-appearance: none; appearance: none; border-radius: 0;
}
input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; }

a { text-decoration: none; color: inherit; }

/* ==========================================================================
   1.5 移动端导航栏（模拟小程序的**原生**导航栏）
   --------------------------------------------------------------------------
   小程序每页都有原生导航栏（`app.json` 的 navigationBar* 配置）：
     navigationBarBackgroundColor: #0d0d0d（深色）
     navigationBarTextStyle: white
     高度 ≈ 44px（另加状态栏）
   原生导航栏**不属于页面 DOM**，所以它没有 WXSS —— 这是 H5 必须自己补的部分。

   ⚠️ 状态栏高度用 env(safe-area-inset-top) 模拟（iOS 刘海屏）；
      非刘海屏该值为 0，此时导航栏贴着屏幕顶端，与小程序一致。
   ========================================================================== */

.mnav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 900;
  padding-top: env(safe-area-inset-top);
  height: calc(44px + env(safe-area-inset-top));
  background: #0d0d0d; color: #fff;
  display: flex; align-items: center; justify-content: center;
}
.mnav-title {
  font-size: 17px; font-weight: 600; letter-spacing: .5px;
  max-width: 60%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mnav-back {
  position: absolute; left: 0; top: env(safe-area-inset-top); bottom: 0;
  width: 56px; display: flex; align-items: center; justify-content: flex-start;
  padding-left: 12px; background: none; border: none; cursor: pointer;
  color: #fff; font-size: 26px; line-height: 1;
}
.mnav-back:active { opacity: .6; }

/* 固定导航栏不占文档流，给 body 补等高留白。
   ⚠️ 只加在「有导航栏」的页面上（用 .has-mnav 标记），
      否则没有导航栏的页面会多出一块空白。 */
body.has-mnav { padding-top: calc(44px + env(safe-area-inset-top)); }

/* 宽屏用顶部导航替代，移动端导航栏隐藏 */
@media (min-width: 768px) {
  .mnav { display: none !important; }
  body.has-mnav { padding-top: 0; }
}

/* ==========================================================================
   2. H5 实现细节（小程序由组件天然提供，浏览器要自己写）
   ========================================================================== */

/* ---- 轮播：小程序用 <swiper>（天然裁剪溢出），H5 用 translateX + 显式裁剪容器 ----
   ⚠️ .banner-viewport 是 H5 专有的一层，不可省：
      小程序 <swiper> 会裁剪超出的一屏；H5 若只把 .banner 设成 overflow:hidden，
      裁剪发生在 padding 盒边界，相邻一屏仍会从 .banner 的 padding 区渗出来（实测黑边）。 */
.banner-viewport { overflow: hidden; height: 100%; border-radius: 10px; }
.banner-track {
  display: flex;
  height: 100%;
  transition: transform .45s cubic-bezier(.22, .61, .36, 1);
  will-change: transform;
}
.banner-track .banner-item { flex: 0 0 100%; }

/* 指示点（小程序 swiper 的 indicator-dots，H5 需自绘） */
.banner-dots {
  position: absolute; left: 0; right: 0; bottom: 18px;
  display: flex; justify-content: center; gap: 6px; z-index: 20;
}
.banner-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: rgba(255, 255, 255, .4); transition: all .3s;
}
.banner-dot.on { width: 16px; border-radius: 3px; background: #ffd700; }

/* .banner 需要作为定位上下文（指示点绝对定位） */
.banner { position: relative; }
.banner-item { position: relative; }

/* ---- 公告跑马灯：小程序用 notice-marquee.js 计算位移，H5 用 CSS 变量 ----
   位移量由 page-index.js 实测溢出宽度后写入 --scroll-distance */
.notice-marquee.marquee-run { animation: noticeScroll 14s linear infinite; }
@keyframes noticeScroll {
  0%, 8%    { transform: translateX(0); }
  92%, 100% { transform: translateX(var(--scroll-distance, 0px)); }
}

/* ==========================================================================
   3. 小程序没有原生对应物的交互组件
      （小程序用 wx.showToast / wx.showModal / wx.showLoading，H5 要自己实现）
   ========================================================================== */

#toast-host {
  position: fixed; inset: 0; z-index: 1000000;
  pointer-events: none; display: flex; align-items: center; justify-content: center;
}
.toast {
  max-width: 76%; padding: 12px 20px; border-radius: 12px;
  background: rgba(26, 26, 46, .88); color: #fff; font-size: 14px; text-align: center;
  animation: toastIn .18s ease-out;
}
@keyframes toastIn { from { opacity: 0; transform: scale(.94) translateY(6px); } }

.modal-mask {
  position: fixed; inset: 0; z-index: 1000000;
  display: flex; align-items: center; justify-content: center;
  background: rgba(15, 20, 35, .55); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  padding: 22px;
}
.modal {
  width: 100%; max-width: 400px; background: #fff; border-radius: 16px;
  padding: 20px; max-height: 80vh; overflow: auto;
  animation: toastIn .2s ease-out;
}
.modal-title { font-size: 17px; font-weight: 700; text-align: center; margin-bottom: 12px; }
.modal-body { font-size: 14px; color: #3d5a80; line-height: 1.7; }
.modal-actions { display: flex; gap: 10px; margin-top: 18px; }

/* 加载中 / 骨架屏 */
.loading { text-align: center; padding: 32px; color: #6d7b8a; font-size: 14px; }
.spinner {
  width: 26px; height: 26px; margin: 0 auto 10px;
  border: 3px solid rgba(101, 176, 232, .25); border-top-color: #65B0E8;
  border-radius: 50%; animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* 空状态 */
.empty { text-align: center; padding: 56px 20px; color: #6d7b8a; }
.empty-icon { font-size: 46px; opacity: .35; margin-bottom: 12px; }

/* H5 通用按钮（弹窗与工具类使用；页面主体按钮请用小程序同名 class） */
.btn {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 46px; border-radius: 8px;
  font-size: 16px; font-weight: 600; cursor: pointer;
  background: linear-gradient(135deg, #65B0E8, #498AC7); color: #fff;
  transition: transform .12s, opacity .12s;
}
.btn:active { transform: scale(.98); opacity: .92; }
.btn[disabled] { opacity: .5; pointer-events: none; }
.btn-ghost {
  background: rgba(255, 255, 255, .85); color: #3d5a80;
  border: 1px solid rgba(101, 176, 232, .3);
}
.btn-danger { background: linear-gradient(135deg, #f2807a, #e74c3c); }
.btn-sm { height: 36px; font-size: 14px; width: auto; padding: 0 16px; border-radius: 8px; }
.modal-actions .btn { flex: 1; }

/* H5 通用表单（编辑资料弹窗使用） */
.field { margin-bottom: 14px; }
.field-label { font-size: 13px; color: #3d5a80; margin-bottom: 6px; font-weight: 600; }
.input, .textarea {
  width: 100%; border: 1px solid rgba(101, 176, 232, .3); border-radius: 8px;
  padding: 11px 13px; font-size: 15px; background: rgba(255, 255, 255, .9);
  color: #1a1a2e; outline: none;
}
.input:focus, .textarea:focus { border-color: #65B0E8; background: #fff; }
.textarea { min-height: 78px; resize: vertical; }

/* 固定底部输入条（聊天页） */
.chat-input-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 600;
  display: flex; gap: 8px; align-items: center;
  padding: 9px 12px calc(9px + env(safe-area-inset-bottom));
  background: rgba(255, 255, 255, .96);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  border-top: 1px solid rgba(101, 176, 232, .2);
}

/* 页脚（备案信息） */
.footer {
  text-align: center; padding: 22px 14px calc(22px + env(safe-area-inset-bottom));
  font-size: 11px; color: rgba(61, 90, 128, .72);
}

/* ==========================================================================
   3.5 扫码支付弹窗（H5 专有 —— 小程序没有这个形态，故不进 mp-mobile.css）
   --------------------------------------------------------------------------
   用途：**非微信浏览器**（电脑 / 手机自带浏览器）里没有 WeixinJSBridge，
        无法调起 JSAPI，改为展示微信支付的 code_url 二维码让用户扫码。
   样式沿用 order-confirm 的玻璃弹窗语言（.privacy-card / .privacy-btn），
   这里只补二维码相关的部分。
   ========================================================================== */

.qr-card { max-width: 320px; }

.qr-box {
  display: flex; flex-direction: column; align-items: center;
  gap: 8px; padding: 4px 0 12px;
}

/* 二维码底板：白底 + 圆角 + 内边距（二维码四周必须有静默区，不能贴边） */
.qr-canvas-wrap {
  padding: 8px; background: #fff; border-radius: 12px;
  box-shadow: 0 2px 10px rgba(30, 64, 175, .12);
  line-height: 0;   /* 去掉 canvas 基线空隙 */
}
.qr-canvas { display: block; width: 220px; height: 220px; }

.qr-amount-row { font-size: 13px; color: #6d7b8a; }
.qr-amount { font-size: 20px; font-weight: 700; color: #EF4444; margin-left: 2px; }
.qr-orderno-row {
  font-size: 11px; color: #94A3B8;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.qr-orderno { color: #1a1a2e; font-weight: 600; }

/* 轮询状态：等待 / 成功 / 需人工，三色区分（用户一眼知道现在什么情况） */
.qr-status { font-size: 13px; font-weight: 600; min-height: 18px; }
.qr-status.waiting { color: #2563EB; }
.qr-status.ok { color: #16A34A; }
.qr-status.err { color: #DC2626; }

.qr-hint {
  font-size: 11px; color: #94A3B8; line-height: 1.6;
  text-align: center; padding: 0 4px;
}

/* ==========================================================================
   4. 响应式工具类
   --------------------------------------------------------------------------
   布局差异优先用 desktop.css 的媒体查询表达；
   只有"结构上完全不同、无法靠重排实现"的元素才用这两个类显隐。
   ========================================================================== */

/* 宽屏专属：默认隐藏，desktop.css 在 ≥768px 打开 */
.desktop-only,
.cat-side { display: none; }

/* 移动端专属：宽屏隐藏 */
@media (min-width: 768px) {
  .mobile-only { display: none !important; }
}
