/* 全站通用交互组件样式，与 ui.js 配套：
   .gr-toast（消息提示条）/ .gr-loading（遮罩等待）/ .gr-dialog（弹窗骨架）/ .gr-btn（弹窗按钮）。
   弹窗骨架原来叫 .wb-dialog 且只写在 pay-dialog.css 里（当时只有两处收银台在用），
   2026-09-20 统一到本文件；pay-dialog.css 只保留收银台专有的 .wb-pay-* / .wb-spin / .wb-ok-icon。
   本文件只写 gr- 前缀的浮层类，不写页面级选择器，任何页面引入即可使用。 */

/* 气泡提示：屏幕居中的悬浮条（「操作被拦下」这类提示）。
   position:fixed + translate 居中，不参与文档流，所以不会被商品行的排版挤没；
   平时 [hidden] 完全不占位。z-index 取 3000：页面里其它浮层最高只到 80。 */
.gr-toast {
    position: fixed;
    left: 50%;
    top: 50%;
    z-index: 3000;
    max-width: 86vw;
    box-sizing: border-box;
    padding: 12px 20px;
    border-radius: 999px;
    background: rgba(38, 38, 38, .92);
    color: #fff;
    font-size: 13px;
    font-weight: 600;
    line-height: 1.6;
    text-align: center;
    box-shadow: 0 10px 30px rgba(0, 0, 0, .2);
    opacity: 0;
    transform: translate(-50%, -50%) scale(.96);
    transition: opacity .18s ease, transform .18s ease;
    pointer-events: none
}

.gr-toast.on {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
    pointer-events: auto;
    cursor: pointer
}

/* 遮罩等待：提交/跳转期间的整页转圈，压住页面但低于提示条 */
.gr-loading {
    position: fixed;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 2900;
    display: none;
    align-items: center;
    justify-content: center;
    gap: 10px;
    background: rgba(17, 24, 39, .45);
    color: #fff;
    font-size: 14px;
    font-weight: 600
}

.gr-loading.on {
    display: flex
}

.gr-spin {
    display: inline-block;
    width: 18px;
    height: 18px;
    border: 2px solid rgba(255, 255, 255, .35);
    border-top-color: #fff;
    border-radius: 50%;
    animation: gr-spin .8s linear infinite
}

@keyframes gr-spin {
    to {
        transform: rotate(360deg)
    }
}

/* 弹窗骨架：规则内容与拆分前（.wb-dialog）完全一致，只把类名前缀换成通用的 gr- */
.gr-dialog {
    width: min(720px, 92vw);
    max-height: 88vh;
    border: 0;
    border-radius: 16px;
    padding: 0;
    box-shadow: 0 28px 80px #17233d44
}

.gr-dialog::backdrop {
    background: #11182788
}

.gr-dialog-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 18px 22px;
    border-bottom: 1px solid #edf0f4
}

.gr-dialog-head h2 {
    margin: 0;
    font-size: 19px
}

.gr-dialog-close {
    border: 0;
    background: #f3f4f6;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    font-size: 19px;
    line-height: 1;
    cursor: pointer
}

.gr-dialog-body {
    padding: 20px 22px;
    max-height: calc(88vh - 72px);
    overflow-y: auto
}

/* 确认框/输入框：比业务弹窗窄，正文 +（可选）输入框 + 底部按钮 */
.gr-dialog-ask {
    width: min(420px, 92vw)
}

.gr-dialog-text {
    margin: 0;
    color: #3c4658;
    line-height: 1.7;
    white-space: pre-wrap
}

.gr-dialog-input {
    width: 100%;
    box-sizing: border-box;
    margin-top: 12px;
    padding: 10px 12px;
    border: 1px solid #d8dee6;
    border-radius: 8px;
    font-size: 15px;
    font-family: inherit
}

.gr-dialog-input:focus {
    border-color: #e3262e;
    outline: none
}

.gr-dialog-foot {
    display: flex;
    justify-content: flex-end;
    gap: 12px;
    margin-top: 20px
}

.gr-btn {
    border: 1px solid #d8dbe0;
    background: #fff;
    color: #313a46;
    border-radius: 10px;
    padding: 9px 18px;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer
}

.gr-btn.primary {
    border-color: #c51b21;
    background: #c51b21;
    color: #fff
}

.gr-btn:disabled {
    opacity: .6;
    cursor: not-allowed
}

/* 多选一（GRUI.choose）：把「请输入 1 / 2 / 3」换成可以直接点的动作列表 */
.gr-choices {
    display: grid;
    gap: 10px;
    margin-top: 14px
}

.gr-choice {
    display: block;
    width: 100%;
    box-sizing: border-box;
    padding: 12px 16px;
    border: 1px solid #d8dee6;
    border-radius: 10px;
    background: #fff;
    text-align: left;
    font-family: inherit;
    cursor: pointer
}

.gr-choice:hover {
    border-color: #e3262e
}

.gr-choice b {
    display: block;
    font-size: 15px;
    color: #2b3444
}

.gr-choice em {
    display: block;
    margin-top: 4px;
    font-size: 13px;
    font-style: normal;
    color: #7b8491
}

.gr-choice.primary {
    border-color: #c51b21;
    background: #fff5f5
}

/* 列表分页器（GRUI.pager）：前台所有列表统一 20 条/页，由后端 page/page_size 驱动。
   按钮必须显式写 display（commerce.css 的 body button{display:inline-flex} 会接管 <button> 排版）；
   类选择器特异性高于 body button，这里按站点按钮观感自己定。 */
.gr-pager {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 16px
}

/* display:flex 会盖掉 [hidden] 的 display:none，必须显式让隐藏生效 */
.gr-pager[hidden] {
    display: none
}

.gr-pager-total,
.gr-pager-jump {
    color: #6b7480;
    font-size: 13px
}

.gr-pager-total {
    margin-right: auto
}

.gr-page {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 32px;
    height: 30px;
    padding: 0 8px;
    border: 1px solid #d8dbe0;
    border-radius: 6px;
    background: #fff;
    color: #313a46;
    font-size: 13px;
    line-height: 1;
    cursor: pointer
}

.gr-page:hover {
    border-color: #c51b21;
    color: #c51b21
}

.gr-page.on {
    border-color: #c51b21;
    background: #c51b21;
    color: #fff;
    font-weight: 700;
    cursor: default
}

.gr-pager-gap {
    color: #9aa3ae;
    padding: 0 2px
}
@media(max-width:560px) {
   .gr-pager {
      justify-content: center
   }

   .gr-pager-total,
   .gr-pager-jump {
      width: 100%;
      text-align: center;
      margin: 0
   }
}

/* ---------- 筛选/搜索后保持滚动位置（见 ui.js 同名段落） ----------
   恢复完成前先把页面藏住，否则会「先看到页首、再跳回原位」。1.5s 兜底由 JS 移除，不会一直白着。
   只挂在 <html> 上、只在有位置要还原时才加，不影响正常浏览。 */
html.gr-scroll-hold body {
  visibility: hidden
}

/* ---------- 下拉框增强（GRUI.enhanceSelect） ----------
   原生 <select> 的弹出面板由系统绘制，改不了样式；这里在其上叠一个同款触发器 + 自定义面板。
   触发器观感对齐弹窗表单的输入框（44px 高 / 8px 圆角 / #dfe3e9 边框 / 聚焦主色）。
   select 本体压成 1px 透明：保留聚焦与表单校验能力，**不能用 display:none**（会被跳过校验，
   form.reportValidity 遇到不可聚焦的必填项会直接报错、且提示位置会飘到 1px 元素上）。 */
.gr-select {
   position: relative;
   display: block
}

.gr-select > select {
   position: absolute !important;
   width: 1px !important;
   height: 1px !important;
   min-height: 1px !important;
   padding: 0 !important;
   margin: 0 !important;
   border: 0 !important;
   opacity: 0;
   pointer-events: none
}

.gr-select-trigger {
   /* commerce.css 有一条带 !important 的 body button{display:inline-flex;min-height:42px}，
      会把这个触发器压成 42px 高、与同表单的 input（44px）差 2px —— 与 .merchant-form-grid
      处理 input 的做法一致，这里用 !important 覆盖回表单口径。 */
   display: flex !important;
   align-items: center;
   justify-content: space-between;
   gap: 10px;
   width: 100%;
   box-sizing: border-box;
   min-height: 44px !important;
   padding: 10px 12px !important;
   border: 1px solid #dfe3e9;
   border-radius: 8px;
   background: #fff;
   color: #313a46;
   font-family: inherit;
   font-size: 14px;
   font-weight: 400;
   line-height: 1.5;
   text-align: left;
   cursor: pointer;
   transition: border-color .16s, box-shadow .16s
}

/* 自绘下拉箭头（不引图标库）：细线 chevron。形状是 border-right + border-bottom 拼成的「┘」，
   绕中心旋转即可换向，两端与尖端始终对称、不用再补位移：
     收起 -45° → 尖端朝右（提示「点开」）；展开 +45° → 尖端朝下（面板在下方）。 */
.gr-select-trigger:after {
   content: '';
   flex: 0 0 auto;
   width: 7px;
   height: 7px;
   margin-right: 4px;
   border-right: 2px solid #8a93a0;
   border-bottom: 2px solid #8a93a0;
   transform: rotate(-45deg);
   transition: transform .16s ease, border-color .16s ease
}

.gr-select.open .gr-select-trigger {
   border-color: #c51b21;
   box-shadow: 0 0 0 3px #c51b211a
}

.gr-select.open .gr-select-trigger:after {
   border-color: #c51b21;
   transform: rotate(45deg)
}

.gr-select-label {
   min-width: 0;
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap
}

/* 面板必须浮在弹窗最上层：位置由 JS 算（positionPanel），所以用 position:fixed 而不是 absolute ——
   absolute 会被 .gr-dialog-body 的 overflow:auto 裁掉、并跟着正文一起滚；
   fixed 元素不受祖先 overflow 裁剪（祖先没有 transform/filter），能完整显示在触发器旁边。
   overscroll-behavior:contain 保证滚到面板尽头时不会把滚动「传染」给外层弹窗。 */
.gr-select-panel {
   position: fixed;
   top: 0;
   left: 0;
   z-index: 4000;
   max-height: 260px;
   overflow-y: auto;
   overscroll-behavior: contain;
   padding: 6px;
   border: 1px solid #e6e9ee;
   border-radius: 10px;
   background: #fff;
   box-shadow: 0 16px 36px #17233d26
}

/* display 由 JS 控制（hidden 属性），这里保证 [hidden] 真的不占位 */
.gr-select-panel[hidden] {
   display: none
}

.gr-option {
   /* 同上：选项也是 <button>，靠 !important 拿回本组件自己的行高（否则每项被撑到 42px） */
   display: flex !important;
   align-items: center;
   justify-content: space-between;
   gap: 10px;
   width: 100%;
   box-sizing: border-box;
   min-height: 0 !important;
   padding: 9px 10px !important;
   border: 0;
   border-radius: 8px;
   background: transparent;
   color: #313a46;
   font-family: inherit;
   font-size: 14px;
   font-weight: 400;
   line-height: 1.4;
   text-align: left;
   cursor: pointer
}

.gr-option span {
   min-width: 0;
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap
}

.gr-option:hover {
   background: #f5f6f8
}

.gr-option.on {
   color: #c51b21;
   font-weight: 700
}

/* 选中项的 ✓ 勾（与页面里其它「已选中」标记同款） */
.gr-option.on:after {
   content: '';
   flex: 0 0 auto;
   width: 5px;
   height: 9px;
   margin-right: 5px;
   border-right: 2px solid #c51b21;
   border-bottom: 2px solid #c51b21;
   transform: rotate(45deg)
}
