/* ============================================================
   Cashier — Shopify-style standalone checkout
   独立布局(checkout/views/layout-top.tpl),不继承全站样式。
   ============================================================ */

:root {
    --cq-text: #171717;
    /* 品牌主色。只作用于"品牌面"：主按钮、选中态描边/填充、焦点圈、Apply 按钮。
       正文文字仍用 --cq-text，不跟着主色走，避免换成浅色主色后正文对比度不够。
       实际取值由 checkout/config/site.php 经 layout-top.tpl 注入 html.cashier-html 覆盖，
       换站点不需要动这个文件。 */
    --cq-primary: #171717;
    --cq-primary-hover: #333333;
    /* 主色上的文字色。默认白，但**浅色主色上白字读不清** ——
       wigshe 的 #c2a284 白字只有 2.39:1，hotbraids 的 #dfac96 只有 2.00:1（WCAG 要 4.5）。
       实际取值由 CashierCheckout 按主色亮度自动算好，经 layout-top.tpl 注入覆盖。 */
    --cq-on-primary: #ffffff;
    /* 正文字体。默认是系统栈，各站的品牌字体由 checkout/config/site.php 经
       layout-top.tpl 注入 html.cashier-html 覆盖 —— 跟 --cq-primary 同一套机制。
       站点没配 brand.font_family 时就停在这个系统栈上，不会渲染失败。 */
    --cq-font: -apple-system, "system-ui", "Segoe UI", Roboto, Helvetica, Arial, sans-serif,
        "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
    --cq-muted: #707070;
    --cq-faint: #999;
    --cq-border: #dedede;
    --cq-border-strong: #171717;
    --cq-focus: #1773b0;
    --cq-error: #d72c0d;
    --cq-error-bg: #fff4f4;
    --cq-panel: #fafafa;
    --cq-panel-border: #e6e6e6;
    /* 圆角比原来更圆滑一档，贴近 Shopify checkout 的观感 */
    --cq-radius: 10px;
    --cq-field-h: 50px;
    --cq-select-bg: #f0f5ff;
    /* 两栏内容宽度对齐 Shopify checkout：左栏表单 560、右栏摘要 460 */
    --cq-main-w: 560px;
    --cq-summary-w: 460px;
}

html.cashier-html {
    height: 100%;
}

body.cashier-body {
    min-width: 320px;
    min-height: 100%;
    margin: 0;
    padding: 0;
    color: var(--cq-text);
    background: #fff;
    font-family: var(--cq-font);
    font-size: 14px;
    font-style: normal;
    font-weight: 400;
    line-height: 1.5;
    /* 刻意不加 -webkit-font-smoothing: antialiased —— 它在 macOS 上会削掉字重，
       正是"纤细发虚"的来源。保持系统默认的次像素渲染，字形更实、更接近 Shopify。
       text-rendering: optimizeLegibility 同理去掉，它对正文没收益还可能拖慢首屏。 */
}

.cashier-page,
.cashier-page *,
.cashier-page *::before,
.cashier-page *::after {
    box-sizing: border-box;
}

.cashier-page button,
.cashier-page input,
.cashier-page select,
.cashier-page textarea {
    margin: 0;
    color: inherit;
    font: inherit;
    letter-spacing: normal;
    text-transform: none;
}

.cashier-page button { background: none; border: 0; padding: 0; cursor: pointer; }
.cashier-page select { cursor: pointer; }
.cashier-page a { color: inherit; }
.cashier-page img { max-width: 100%; }
.cashier-page h1, .cashier-page h2, .cashier-page h3,
.cashier-page p, .cashier-page dl, .cashier-page dd { margin: 0; }
.cashier-page fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }

.cashier-visually-hidden {
    position: absolute !important;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* ------------------------------------------------------------
   桌面端:右栏灰色背景通过伪元素延伸到视口右缘,
   分界线与 summary 的 border-left 严格重合(不能用 50% 渐变,
   因为左右栏是 56/44 分栏,分界不在视口中线)。
   ------------------------------------------------------------ */
@media (min-width: 1000px) {
    body.cashier-body { overflow-x: clip; }
    .cashier-summary { position: relative; }
    .cashier-summary::before {
        content: "";
        position: absolute;
        top: 0; bottom: 0; left: 0;
        width: 50vw;
        background: var(--cq-panel);
        z-index: -1;
    }
}

/* ------------------------------------------------------------
   Header
   ------------------------------------------------------------ */
.cashier-header {
    background: #fff;
    border-bottom: 1px solid var(--cq-panel-border);
}

.cashier-header__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: min(100%, calc(var(--cq-main-w) + var(--cq-summary-w)));
    margin: 0 auto;
    padding: 0 21px;
    height: 72px;
}

.cashier-logo { display: inline-flex; align-items: center; }
.cashier-logo img { display: block; width: 168px; height: auto; max-height: 40px; }

.cashier-header__right {
    display: inline-flex;
    align-items: center;
    gap: 16px;
}

.cashier-bag {
    display: inline-flex;
    width: 24px; height: 24px;
    color: var(--cq-focus);
}
.cashier-bag svg { width: 100%; height: 100%; }

/* ------------------------------------------------------------
   语言切换（启用语言 >= 2 种时才渲染）
   ------------------------------------------------------------ */
.cashier-lang {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    color: var(--cq-muted);
}
.cashier-lang > svg:first-child { width: 16px; height: 16px; flex: 0 0 16px; }
.cashier-lang__chevron { width: 14px; height: 14px; pointer-events: none; }

/* 原生 select 铺在上面并透明化：下拉列表交给系统渲染（移动端体验最好），
   外观则由左右两个 svg + 下面的文字样式控制 */
.cashier-page .cashier-lang select {
    appearance: none;
    -webkit-appearance: none;
    padding: 4px 2px;
    border: 0;
    background: transparent;
    color: var(--cq-text);
    font-size: 13px;
    cursor: pointer;
}
.cashier-page .cashier-lang select:focus-visible {
    outline: 2px solid var(--cq-focus);
    outline-offset: 2px;
    border-radius: 4px;
}

@media (min-width: 1000px) {
    .cashier-header { border-bottom: 0; }
    .cashier-header__inner {
        position: relative;
        height: 84px;
    }
    /* header 下沿分隔线只画在左栏区域 */
    .cashier-header::after {
        content: "";
        display: block;
        border-bottom: 1px solid var(--cq-panel-border);
    }
}

/* ------------------------------------------------------------
   两栏布局
   ------------------------------------------------------------ */
.cashier-layout {
    display: flex;
    flex-direction: column-reverse;
    min-height: calc(100vh - 73px);
}

.cashier-main { background: #fff; }

.cashier-main__inner {
    width: 100%;
    max-width: var(--cq-main-w);
    margin: 0 auto;
    padding: 24px 21px 48px;
}

.cashier-summary { background: var(--cq-panel); }

.cashier-summary__inner {
    width: 100%;
    max-width: var(--cq-summary-w);
    margin: 0 auto;
    padding: 21px;
}

@media (min-width: 1000px) {
    .cashier-layout {
        flex-direction: row;
        width: min(100%, calc(var(--cq-main-w) + var(--cq-summary-w)));
        margin: 0 auto;
    }
    .cashier-main {
        flex: 1 1 56%;
        background: transparent;
    }
    .cashier-main__inner {
        padding: 38px 44px 72px 21px;
        margin-right: 0;
    }
    .cashier-summary {
        flex: 1 1 44%;
        background: transparent;
        border-left: 1px solid var(--cq-panel-border);
    }
    .cashier-summary__inner {
        position: sticky;
        top: 0;
        padding: 38px 21px 38px 44px;
        max-width: none;
    }
}

/* ------------------------------------------------------------
   移动端 order summary 折叠条
   ------------------------------------------------------------ */
/* 带 .cashier-page 前缀把特异性抬到 (0,2,1)：它是 <button>，
   .cashier-page button { padding: 0 } 会把下面的左右内边距清零，移动端就贴死在屏幕边缘 */
.cashier-page .cashier-summary-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: 16px 21px;
    background: var(--cq-panel);
    border-top: 1px solid var(--cq-panel-border);
    border-bottom: 1px solid var(--cq-panel-border);
    font-size: 14px;
}

.cashier-summary-toggle__left {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    /* 不用链接蓝：这条只是展开收起，和"继续付款"之类的动作不是一个层级，
       蓝色会把视线从下面的表单上拽走 */
    color: var(--cq-text);
}

.cashier-summary-toggle__chevron { width: 14px; height: 14px; transition: transform .2s ease; }
.cashier-summary-toggle[aria-expanded="true"] .cashier-summary-toggle__chevron { transform: rotate(180deg); }
.cashier-summary-toggle strong { font-size: 16px; font-weight: 600; }

@media (max-width: 999px) {
    .cashier-summary { display: none; border-bottom: 1px solid var(--cq-panel-border); }
    .cashier-summary.cashier-summary--open { display: block; }
}

@media (min-width: 1000px) {
    /* 必须带 .cashier-page 前缀。上面的展开规则是 (0,2,0)，媒体查询不加特异性，
       (0,1,0) 的 display:none 压不过它 —— PC 上这条折叠栏一直露着就是这么来的。
       PC 右栏 .cashier-summary 常驻，折叠栏在这里是多余的重复。 */
    .cashier-page .cashier-summary-toggle { display: none; }
}

/* ------------------------------------------------------------
   区块
   ------------------------------------------------------------ */
.cashier-section { padding-top: 32px; }
.cashier-section:first-child { padding-top: 0; }
/* 快捷支付块插到最前后，Contact 不再是 :first-child 而拿到了 32px 顶距，
   加上 express 自己的下边距，OR 和 Contact 之间会空出一大片 */
.cashier-express + .cashier-section { padding-top: 0; }

.cashier-section__heading {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-bottom: 14px;
}
.cashier-section__heading__column {
    flex-direction: column;
}

.cashier-section__heading h1,
.cashier-section__heading h2 {
    font-size: 21px;
    font-weight: 600;
    letter-spacing: -.2px;
}

.cashier-section__note {
    margin: -10px 0 14px;
    color: var(--cq-muted);
    font-size: 13px;
}

.cashier-link {
    color: var(--cq-focus);
    font-size: 14px;
    font-weight: 500;
    text-decoration: underline;
    text-underline-offset: 2px;
    /* 显式声明：它常挂在 <button> 上，没有这句在部分浏览器里不显示手型，看着不像能点 */
    cursor: pointer;
    transition: color .12s ease;
}
.cashier-link:hover { color: #10557f; text-decoration-thickness: 2px; }
.cashier-link:focus-visible { outline: 2px solid var(--cq-focus); outline-offset: 2px; border-radius: 3px; }

/* ------------------------------------------------------------
   浮动标签字段
   ------------------------------------------------------------ */
.fl {
    position: relative;
    margin-bottom: 10px;
}

.fl input,
.fl select,
.fl textarea {
    display: block;
    width: 100%;
    height: var(--cq-field-h);
    padding: 20px 12px 6px;
    background: #fff;
    border: 1px solid var(--cq-border);
    border-radius: var(--cq-radius);
    /* Shopify 式层次:柔和的顶部内阴影(不能太深,否则上边框看起来变粗) */
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, .03);
    font-size: 14px;
    color: var(--cq-text);
    outline: none;
    appearance: none;
    -webkit-appearance: none;
    transition: border-color .15s ease, box-shadow .15s ease;
}

.fl textarea {
    height: auto;
    min-height: 84px;
    padding-top: 24px;
    resize: vertical;
}

.fl label {
    position: absolute;
    top: 50%;
    left: 13px;
    /* 同样以输入框高度为基准，否则字段报错时未浮起的 label 会跟着往下掉 */
    top: calc(var(--cq-field-h) / 2);
    transform: translateY(-50%);
    color: var(--cq-muted);
    font-size: 14px;
    pointer-events: none;
    transition: all .12s ease;
    white-space: nowrap;
    max-width: calc(100% - 26px);
    overflow: hidden;
    text-overflow: ellipsis;
}

.fl--textarea label { top: 26px; }

/* 浮起状态:聚焦或已填(select 由 JS 的 fl--filled 驱动)

   必须用 ~ 而不是 +：parsley 校验失败时会把 <ul class="parsley-errors-list">
   **插在 input 和 label 之间**，相邻兄弟选择器当场失效 ——
   于是一报错，标签就掉回原位、和已经填好的内容叠在一起。 */
.fl input:focus ~ label,
.fl input:not(:placeholder-shown) ~ label,
.fl input:-webkit-autofill ~ label,
.fl textarea:focus ~ label,
.fl textarea:not(:placeholder-shown) ~ label,
.fl--select select:focus ~ label,
.fl.fl--filled label,
.fl--phone label {
    top: 14px;
    font-size: 12px;
    color: var(--cq-muted);
}

/* Chrome autofill:去掉黄底,保持字段视觉一致 */
.fl input:-webkit-autofill {
    -webkit-box-shadow: 0 0 0 100px #fff inset;
    -webkit-text-fill-color: var(--cq-text);
}
.fl--textarea textarea:focus ~ label,
.fl--textarea textarea:not(:placeholder-shown) ~ label { top: 14px; }

.fl input:focus,
.fl select:focus,
.fl textarea:focus {
    border-color: var(--cq-focus);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, .03), 0 0 0 1px var(--cq-focus);
}

.fl select { padding-right: 34px; }
/* 原生下拉展开后的 option 列表不继承 select 的字号，必须单独给，
   否则 macOS/Windows 会用默认小字渲染，和输入框里的 14px 差一大截 */
.fl select,
.fl select option { font-size: 14px; }

/* 注意：.fl 里会被 parsley 插入错误提示 <ul>，容器高度随之变高。
   所有要贴着「输入框」的绝对定位元素都必须以 --cq-field-h 为基准，
   用 top:50% / top:100% 会在字段报错时整体下移（国旗跑到框外、下拉飞到别处）。 */
.fl__chevron {
    position: absolute;
    top: calc(var(--cq-field-h) / 2);
    right: 12px;
    width: 16px; height: 16px;
    transform: translateY(-50%);
    color: var(--cq-muted);
    pointer-events: none;
}

.fl--search input { padding-right: 40px; }
.fl__search-icon {
    position: absolute;
    top: calc(var(--cq-field-h) / 2);
    right: 12px;
    width: 18px; height: 18px;
    transform: translateY(-50%);
    fill: var(--cq-muted);
    pointer-events: none;
    transition: opacity .15s ease;
}

/* 检索中：搜索图标淡出，原地换成细环 spinner。
   放在同一位置而不是另起一块，避免输入时布局跳动。 */
.fl__spinner {
    position: absolute;
    top: calc(var(--cq-field-h) / 2);
    right: 13px;
    width: 16px; height: 16px;
    margin-top: -8px;
    border: 2px solid rgba(0, 0, 0, .10);
    border-top-color: var(--cq-focus);
    border-radius: 50%;
    opacity: 0;
    pointer-events: none;
    transition: opacity .15s ease;
}
.fl--search.is-loading .fl__search-icon { opacity: 0; }
.fl--search.is-loading .fl__spinner {
    opacity: 1;
    animation: cq-spin .65s linear infinite;
}
@keyframes cq-spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
    .fl--search.is-loading .fl__spinner { animation-duration: 1.8s; }
}

.fl__hint-icon {
    position: absolute;
    top: calc(var(--cq-field-h) / 2);
    right: 12px;
    width: 18px; height: 18px;
    transform: translateY(-50%);
    fill: var(--cq-faint);
    cursor: help;
}
.fl__hint-icon svg { display: block; width: 100%; height: 100%; }

/* 电话:区号固定在输入框内部左侧 */
/* 给个接近实际的初始值，JS 量出前缀真实宽度后会用内联样式覆盖。
   不留初始值的话首帧国旗会压在号码上。 */
.fl--phone input { padding-left: 88px; }

.cashier-phone-flag {
    display: block;
    width: 21px;
    height: 15px;
    border-radius: 2px;
    object-fit: cover;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, .08);
}
.cashier-phone-flag[hidden] { display: none; }

/* ---------- 电话：左侧国旗 + 区号，可下拉切换 ---------- */
/* 人在美国不代表电话是美国号，所以区号必须能独立于收货国家切换。
   padding-left 由 JS 按前缀实际宽度设置（+1 和 +1684 宽度差很多）。 */
.fl--phone .fl__hint-icon { right: 12px; }

.fl--phone .cashier-phone-country {
    position: absolute;
    /* 用固定 top/height 而不是 50% 居中：一是不受 parsley 错误撑高影响，
       二是刻意压在 20px 起，避开浮起后停在 14px 的 label */
    top: 20px;
    left: 10px;
    display: flex;
    align-items: center;
    gap: 4px;
    height: 24px;
    padding: 0 5px 0 3px;
    border-radius: 5px;
    background: transparent;
    color: var(--cq-text);
    font-size: 14px;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    z-index: 2;
}
.fl--phone .cashier-phone-code { line-height: 1; }
.fl--phone .cashier-phone-country:hover { background: #f2f2f2; }
.fl--phone .cashier-phone-country:focus-visible { outline: 2px solid var(--cq-focus); outline-offset: 1px; }
.fl--phone .cashier-phone-country svg { width: 10px; height: 10px; fill: var(--cq-muted); }
.fl--phone .cashier-phone-country img { width: 21px; height: 15px; border-radius: 2px; object-fit: cover; box-shadow: 0 0 0 1px rgba(0, 0, 0, .08); }

.cashier-phone-menu {
    position: absolute;
    top: calc(var(--cq-field-h) + 4px);
    left: 0;
    z-index: 50;
    width: 288px;
    max-width: 100%;
    background: #fff;
    border: 1px solid var(--cq-panel-border);
    border-radius: 10px;
    box-shadow: 0 12px 32px rgba(0, 0, 0, .14);
    overflow: hidden;
}
.cashier-phone-menu[hidden] { display: none; }

/* 搜索框自己带边框和圆角，四周留 8px —— 之前贴边加上浏览器默认 focus 圈，
   上下留白不均看着很怪 */
.cashier-phone-menu .cashier-phone-search {
    display: block;
    width: calc(100% - 16px);
    height: 36px;
    margin: 8px;
    padding: 0 10px;
    border: 1px solid var(--cq-border);
    border-radius: 7px;
    background: #fff;
    font-size: 14px;
    line-height: 34px;
}
.cashier-phone-menu .cashier-phone-search:focus {
    outline: none;
    border-color: var(--cq-focus);
    box-shadow: 0 0 0 1px var(--cq-focus);
}
.cashier-phone-menu .cashier-phone-list { border-top: 1px solid #f0f0f0; }

.cashier-phone-list {
    max-height: 244px;
    overflow-y: auto;
    padding: 4px 0;
}

.cashier-phone-menu .cashier-phone-option {
    display: flex;
    align-items: center;
    gap: 9px;
    width: calc(100% - 12px);
    margin: 1px 6px;
    padding: 8px 10px;
    border-radius: 7px;
    text-align: left;
    font-size: 14px;
    cursor: pointer;
}
.cashier-phone-menu .cashier-phone-option:hover { background: #f5f6f7; }
.cashier-phone-menu .cashier-phone-option[aria-selected="true"] { background: var(--cq-focus); color: #fff; }
.cashier-phone-menu .cashier-phone-option[aria-selected="true"] .cashier-phone-option__code { color: rgba(255, 255, 255, .82); }
/* object-fit 不能少：国旗 SVG 各国长宽比不一，不裁切会撑变形 */
.cashier-phone-menu .cashier-phone-option img { flex: 0 0 21px; width: 21px; height: 15px; border-radius: 2px; object-fit: cover; box-shadow: 0 0 0 1px rgba(0, 0, 0, .08); }
.cashier-phone-menu .cashier-phone-option__name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cashier-phone-menu .cashier-phone-option__code { flex: 0 0 auto; color: var(--cq-muted); font-variant-numeric: tabular-nums; }
.cashier-phone-empty { padding: 14px 12px; color: var(--cq-muted); font-size: 13px; text-align: center; }

/* ---------- 快捷登录（内联展开，不依赖弹窗库） ---------- */
.cashier-login-hint {
    margin: -2px 0 10px;
    padding: 10px 12px;
    border: 1px solid var(--cq-panel-border);
    border-radius: var(--cq-radius);
    background: var(--cq-panel);
    font-size: 13px;
    line-height: 1.45;
}
.cashier-login-box { margin-bottom: 10px; }
/* 两端对齐：登录按钮在左，忘记密码在右 */
.cashier-login-box__row { display: flex; align-items: center; justify-content: space-between; gap: 14px; }
.cashier-login-error { margin: 8px 0 0; color: var(--cq-error); font-size: 13px; }

/* 必须带父级：它是 <button>，单靠 .cashier-btn-secondary (0,1,0) 会被
   .cashier-page button { background:none; padding:0 } (0,1,1) 压成纯文字 */
.cashier-login-box .cashier-btn-secondary {
    height: 40px;
    padding: 0 22px;
    border-radius: var(--cq-radius);
    background: var(--cq-primary);
    color: var(--cq-on-primary);
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
}
.cashier-login-box .cashier-btn-secondary:hover { opacity: .88; }
.cashier-login-box .cashier-btn-secondary[disabled] { opacity: .5; cursor: default; }

/* 提交中：文字隐去、原地转圈，按钮尺寸不变以免布局跳动 */
.cashier-login-box .cashier-btn-secondary.is-busy { position: relative; color: transparent; }
.cashier-login-box .cashier-btn-secondary.is-busy::after {
    content: '';
    position: absolute;
    top: 50%; left: 50%;
    width: 16px; height: 16px;
    margin: -8px 0 0 -8px;
    border: 2px solid rgba(255, 255, 255, .35);
    border-top-color: #fff;
    border-radius: 50%;
    animation: cq-spin .65s linear infinite;
}

/* ---------- 已存地址：单行卡片，横向滚动 ---------- */
.cashier-saved { margin-bottom: 14px; }
.cashier-saved__track {
    display: flex;
    gap: 10px;
    /* 强制单行 + 横向滚动，不换行 */
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    /* 左右各留 3px：选中态的 1px 描边 + 1px 外发光会溢出卡片盒子，
       留白不够第一张卡片的左边缘就会被容器裁掉一线 */
    padding: 3px 3px 10px;
    scroll-padding-left: 3px;
    -webkit-overflow-scrolling: touch;
    /* 隐藏滚动条，改用拖拽（见 bindSavedAddressCards）。
       不用 scroll-snap：拖拽过程中吸附会和指针位置打架，手感发涩。 */
    scrollbar-width: none;
    -ms-overflow-style: none;
    cursor: grab;
}
.cashier-saved__track::-webkit-scrollbar { width: 0; height: 0; display: none; }
.cashier-saved__track.is-dragging { cursor: grabbing; scroll-behavior: auto; }
/* 拖拽时屏蔽子元素命中，避免选中文字或误触发 click */
.cashier-saved__track.is-dragging * { pointer-events: none; user-select: none; }

.cashier-saved__track .cashier-addr-card {
    position: relative;
    flex: 0 0 208px;
    /* 必须显式写 min-width:0。flex item 默认是 min-width:auto —— 不允许收缩到 min-content
       以下，而 __line1 的 white-space:nowrap 让 min-content 等于整行地址的宽度，
       于是 flex-basis:208px 被无视、地址越长卡片越宽（实测长地址那张会撑到 500px）。 */
    min-width: 0;
    /* 高度统一：行数不同（有无 address2 / 有无电话）时靠这个兜底，
       再配合 flex 容器默认的 align-items:stretch，一行里所有卡片同高。 */
    min-height: 104px;
    scroll-snap-align: start;
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 12px 13px;
    border: 1px solid transparent;
    border-radius: 12px;
    text-align: left;
    font-size: 13px;
    line-height: 1.4;
    color: var(--cq-text);
    cursor: pointer;
    transition: border-color .12s ease, box-shadow .12s ease;
}
/* 低饱和高明度色板，按顺序循环 */
.cashier-saved__track .cashier-addr-card[data-tone="0"] { background: #fdf2f8; }
.cashier-saved__track .cashier-addr-card[data-tone="1"] { background: #eff6ff; }
.cashier-saved__track .cashier-addr-card[data-tone="2"] { background: #f0fdf4; }
.cashier-saved__track .cashier-addr-card[data-tone="3"] { background: #fefce8; }
.cashier-saved__track .cashier-addr-card[data-tone="4"] { background: #faf5ff; }
.cashier-saved__track .cashier-addr-card[data-tone="5"] { background: #fff7ed; }

.cashier-saved__track .cashier-addr-card:hover { border-color: rgba(0, 0, 0, .12); }
.cashier-saved__track .cashier-addr-card[aria-checked="true"] {
    border-color: var(--cq-primary);
    box-shadow: 0 0 0 1px var(--cq-primary);
}

/* 街道行给到两行再省略：地址是卡片里唯一需要看清的信息，砍成一行经常只剩门牌号。
   右侧留出 20px 避开右上角那颗选中标记（17px + 9px 边距）。 */
.cashier-addr-card__line1 {
    font-weight: 600;
    padding-right: 20px;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    /* 长单词/长数字串（如无空格的地址）必须能断，否则又会把卡片顶宽 */
    overflow-wrap: anywhere;
}
/* 次要行各占一行，超出省略 */
.cashier-addr-card__line2,
.cashier-addr-card__meta,
.cashier-addr-card__phone {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cashier-addr-card__meta { color: var(--cq-muted); font-size: 12px; }
/* 电话钉在卡片底部：margin-top:auto 把它推到底，
   于是无论上面是一行还是三行，各卡片的电话都在同一水平线上。 */
.cashier-addr-card__phone {
    margin-top: auto;
    padding-top: 2px;
    color: var(--cq-muted);
    font-size: 12px;
    font-variant-numeric: tabular-nums;
}

.cashier-addr-card__check {
    position: absolute;
    top: 9px; right: 9px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 17px; height: 17px;
    border-radius: 50%;
    background: var(--cq-primary);
    color: var(--cq-on-primary);
    opacity: 0;
    transform: scale(.7);
    transition: opacity .12s ease, transform .12s ease;
}
.cashier-addr-card__check svg { width: 10px; height: 10px; }
.cashier-saved__track .cashier-addr-card[aria-checked="true"] .cashier-addr-card__check { opacity: 1; transform: scale(1); }

/* ---------- PayPal 快捷支付 ---------- */
.cashier-express { margin: 0 0 22px; }
.cashier-express__label {
    margin-bottom: 8px;
    color: var(--cq-muted);
    font-size: 12px;
    text-align: center;
}
.cashier-express__buttons { min-height: 50px; }
.cashier-express__divider {
    position: relative;
    margin-top: 18px;
    text-align: center;
}
.cashier-express__divider::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 0; right: 0;
    height: 1px;
    background: var(--cq-panel-border);
}
.cashier-express__divider span {
    position: relative;
    padding: 0 12px;
    background: #fff;
    color: var(--cq-muted);
    font-size: 12px;
}

/* ---------- 地址回填期间的表单占位 ---------- */
/* 选中建议后要连锁更新国家→州列表→区号→邮编掩码，同步执行会明显卡一下。
   这里盖一层半透明并禁用交互，避免用户在字段跳变的中途去点它们。 */
.cashier-fields-busy { position: relative; }
.cashier-fields-busy::after {
    content: '';
    position: absolute;
    top: -4px; left: -4px; right: -4px; bottom: -4px;
    z-index: 6;
    border-radius: var(--cq-radius);
    background: rgba(255, 255, 255, .55);
    backdrop-filter: saturate(.9);
}
.cashier-fields-busy::before {
    content: '';
    position: absolute;
    top: 50%; left: 50%;
    z-index: 7;
    width: 22px; height: 22px;
    margin: -11px 0 0 -11px;
    border: 2px solid rgba(0, 0, 0, .10);
    border-top-color: var(--cq-focus);
    border-radius: 50%;
    animation: cq-spin .65s linear infinite;
}

/* 回填完成后被改动的字段闪一下，让用户看见哪些是自动填的 */
@keyframes cq-field-flash {
    0%   { background-color: rgba(23, 115, 176, .12); }
    100% { background-color: transparent; }
}
.fl--flash input,
.fl--flash select { animation: cq-field-flash 1s ease-out; }

@media (prefers-reduced-motion: reduce) {
    .cashier-fields-busy::before { animation-duration: 1.8s; }
    .fl--flash input, .fl--flash select { animation: none; }
}

/* 校验错误 */
.fl input.parsley-error,
.fl select.parsley-error,
.fl textarea.parsley-error {
    border-color: var(--cq-error);
    background: var(--cq-error-bg);
    box-shadow: none;
}
/* 同样必须用 ~：报错时 <ul class="parsley-errors-list"> 就插在 input 和 label 之间，
   写成 + 的话这条规则恰好在唯一需要它的时候永远匹配不上 */
.fl input.parsley-error ~ label,
.fl select.parsley-error ~ label { color: var(--cq-error); }

.parsley-errors-list {
    margin: 5px 0 0;
    padding: 0;
    list-style: none;
    color: var(--cq-error);
    font-size: 12px;
}
.parsley-errors-list li { display: flex; gap: 4px; align-items: baseline; }

/* 网格 */
.cashier-grid { display: grid; gap: 10px; margin-bottom: 10px; }
.cashier-grid .fl { margin-bottom: 0; }
.cashier-grid--2 { grid-template-columns: 1fr 1fr; }
.cashier-grid--3 { grid-template-columns: 1fr 1fr 1fr; }

@media (max-width: 480px) {
    .cashier-grid--3 { grid-template-columns: 1fr 1fr; }
    .cashier-grid--3 .fl:first-child { grid-column: 1 / -1; }
}

/* 隐藏州/邮编时网格自动收缩(无 :has 支持的浏览器仅留空列,可接受) */
.cashier-grid--3:has(> .fl[style*="none"]) { grid-template-columns: 1fr 1fr; }
.cashier-grid--3:has(> .id_state[style*="none"]):has(> .cashier-zip-field[style*="none"]),
.cashier-grid--3:has(> .inv_id_state[style*="none"]):has(> .cashier-inv-zip-field[style*="none"]) { grid-template-columns: 1fr; }


/* ------------------------------------------------------------
   地址联想下拉
   ------------------------------------------------------------ */
.cashier-address-field { position: relative; }

.cashier-suggestions {
    position: absolute;
    top: calc(var(--cq-field-h) + 4px);
    left: 0;
    right: 0;
    z-index: 40;
    background: #fff;
    border: 1px solid var(--cq-panel-border);
    border-radius: 10px;
    box-shadow: 0 12px 32px rgba(0, 0, 0, .14);
    overflow: hidden;
}

.cashier-suggestions__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px 8px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--cq-muted);
}

/* 注意：下面这些都是 <button>，而全局有
   `.cashier-page button { padding: 0 }` 和 `{ margin: 0 }`，特异性 (0,1,1)。
   单靠 .cashier-xxx 这类 (0,1,0) 的选择器会被它清零 —— 必须带上父容器把特异性抬到 (0,2,0)。 */
.cashier-suggestions__head .cashier-suggestions__close {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    margin: -4px -6px -4px 0;
    padding: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--cq-muted);
    cursor: pointer;
}
.cashier-suggestions__head .cashier-suggestions__close:hover { background: #f0f0f0; color: #111; }
.cashier-suggestions__head .cashier-suggestions__close svg { width: 12px; height: 12px; }

/* 选中块左右留白 + 圆角，不通栏顶到容器边（贴边会显得拥挤） */
.cashier-suggestions .cashier-suggestion {
    display: block;
    width: calc(100% - 12px);
    /* 左缘 6+10=16px，与 SUGGESTIONS 标题的 16px 对齐；行距靠 margin 拉开 */
    margin: 2px 6px;
    padding: 11px 10px;
    text-align: left;
    font-size: 14px;
    line-height: 1.45;
    border-radius: 8px;
    cursor: pointer;
}
.cashier-suggestions .cashier-suggestion:last-of-type { margin-bottom: 6px; }

.cashier-suggestions .cashier-suggestion:hover { background: #f5f6f7; }

/* 键盘/鼠标选中态：整块反白，次要文本跟着提亮，否则在蓝底上读不清 */
.cashier-suggestions .cashier-suggestion[aria-selected="true"] {
    background: var(--cq-focus);
    color: #fff;
}
.cashier-suggestions .cashier-suggestion[aria-selected="true"] .cashier-suggestion__secondary { color: rgba(255, 255, 255, .82); }

/* 主次同一行：主体加粗、次要信息紧随其后，接近 Shopify 的排布 */
.cashier-suggestion__main { font-weight: 600; }
.cashier-suggestion__secondary { color: var(--cq-muted); }

/* Places API 政策：在不显示 Google 地图的页面上使用 Places 数据时必须展示归属。
   做到最低限度的克制 —— 小字、浅色、右下角，但不能移除。 */
.cashier-google-credit {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    padding: 7px 16px 9px;
    border-top: 1px solid #f2f2f2;
}
/* 官方灰版 logo 本身已经是低对比度，再叠 opacity 会糊；
   压到 12px 高（原始 98×18 的 2/3）是仍然认得出字形的下限 */
.cashier-google-credit img { width: 65px; height: 12px; display: block; }

/* 选中建议后正在向 Address Validation 取规范地址时的占位行 */
.cashier-suggestions__status {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 13px 16px;
    font-size: 13px;
    color: var(--cq-muted);
}
.cashier-suggestions__status::before {
    content: '';
    flex: 0 0 14px;
    width: 14px; height: 14px;
    border: 2px solid rgba(0, 0, 0, .10);
    border-top-color: var(--cq-focus);
    border-radius: 50%;
    animation: cq-spin .65s linear infinite;
}

/* ------------------------------------------------------------
   Checkbox
   ------------------------------------------------------------ */
.cashier-check {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin: 2px 0 12px;
    font-size: 14px;
    cursor: pointer;
    -webkit-user-select: none;
    user-select: none;
}

.cashier-check input[type="checkbox"] {
    flex: 0 0 18px;
    width: 18px; height: 18px;
    margin-top: 1px;
    appearance: none;
    -webkit-appearance: none;
    background: #fff;
    border: 1px solid #b5b5b5;
    border-radius: 4px;
    display: inline-grid;
    place-content: center;
    transition: background .12s ease, border-color .12s ease;
}

.cashier-check input[type="checkbox"]::before {
    content: "";
    width: 10px; height: 10px;
    transform: scale(0);
    background: #fff;
    clip-path: polygon(14% 44%, 0 60%, 40% 100%, 100% 18%, 84% 6%, 38% 71%);
    transition: transform .1s ease;
}

.cashier-check input[type="checkbox"]:checked {
    background: var(--cq-primary);
    border-color: var(--cq-primary);
}
.cashier-check input[type="checkbox"]:checked::before { transform: scale(1); }
.cashier-check input[type="checkbox"]:focus-visible { outline: 2px solid var(--cq-focus); outline-offset: 1px; }

.cashier-terms a { text-decoration: underline; text-underline-offset: 2px; }

/* ------------------------------------------------------------
   Shipping / Payment 选项列表(onepage.js 注入的 DOM)
   外层容器不带边框;每个 li 自己带边框并折叠相邻边,
   选中项整圈变蓝(z-index 抬高盖住相邻灰边)+ 浅蓝背景。
   ------------------------------------------------------------ */
#carriers2 .table_block,
#payment_selection .table_block { border: 0; border-radius: 0; overflow: visible; }

.shipment-methods,
.payment-methods {
    margin: 0;
    padding: 0;
    list-style: none;
}

.shipment-methods > li,
.payment-methods > li {
    position: relative;
    margin-top: -1px;
    border: 1px solid var(--cq-border);
    background: #fff;
    overflow: hidden;
    transition: background .12s ease, border-color .12s ease;
}

.shipment-methods > li:first-child,
.payment-methods > li:first-child { margin-top: 0; border-radius: var(--cq-radius) var(--cq-radius) 0 0; }
.shipment-methods > li:last-child,
.payment-methods > li:last-child { border-radius: 0 0 var(--cq-radius) var(--cq-radius); }
.shipment-methods > li:only-child,
.payment-methods > li:only-child { border-radius: var(--cq-radius); }

.shipment-methods > li.select,
.shipment-methods > li:has(input:checked),
.payment-methods > li.select {
    z-index: 1;
    border-color: var(--cq-focus);
    box-shadow: inset 0 0 0 1px var(--cq-focus);
    background: var(--cq-select-bg);
}

.shipment-methods .rate_label {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 15px 14px;
    cursor: pointer;
    font-size: 14px;
    line-height: 1.4;
}

.shipment-methods .carrier_delay {
    display: flex;
    flex: 1;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin: 0;
    color: var(--cq-muted);
    font-size: 13px;
}

.shipment-methods .carrier_price {
    color: var(--cq-text);
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
}

.shipment-methods .select_postcode { color: var(--cq-error); font-weight: 400; font-size: 12px; white-space: normal; }

.payment-methods .rate_label {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 15px 14px;
    cursor: pointer;
    font-size: 14px;
}

.payment-methods .rate_label > div { display: flex; align-items: center; gap: 11px; }

.payment-methods .img_box { display: flex; align-items: center; gap: 4px; }
.payment-methods .img_box img { height: 22px !important; width: auto; display: block; }

.payment-methods .form-icon { display: none; }

.payment-methods .payment_method_container { display: none; }
.payment-methods li.select .payment_method_container {
    display: block;
    padding: 16px 14px 18px;
    background: #fafafa;
    /* 选中态下用 2px 高亮色收口，和外框的 focus 边框呼应；
       原来的 1px 浅灰在蓝框里显得像一条断掉的缝 */
    border-top: 2px solid var(--cq-focus);
}

/* radio 圆点(carrier + payment 共用) */
.rate_input {
    flex: 0 0 18px;
    width: 18px; height: 18px;
    appearance: none;
    -webkit-appearance: none;
    margin: 0;
    background: #fff;
    border: 1px solid #b5b5b5;
    border-radius: 50%;
    display: inline-grid;
    place-content: center;
    transition: border-color .12s ease;
}
.rate_input::before {
    content: "";
    width: 10px; height: 10px;
    border-radius: 50%;
    background: var(--cq-primary);
    transform: scale(0);
    transition: transform .1s ease;
}
.rate_input:checked { border-color: var(--cq-text); }
.rate_input:checked::before { transform: scale(1); }

/* 支付内容区里模块注入的按钮/字段兜底样式 */
.paycontent input[type="text"],
.paycontent input[type="tel"],
.paycontent input[type="email"] {
    width: 100%;
    height: 44px;
    padding: 0 12px;
    border: 1px solid var(--cq-border);
    border-radius: var(--cq-radius);
    background: #fff;
}

/* Stripe / Klarna 的 Pay Now 是 <input type="button">（不是 submit，点击走 onclick），
   只列 button[type=submit] / input[type=submit] 会漏掉它们 —— 那两个按钮就退化成
   浏览器默认样式。它们都带 data-action="submit"，用这个属性兜住最稳，
   不用去动 modules/ 下那两个模板（老 /checkout 还在用同一份，有 UIkit）。 */
.paycontent .payment-submit,
.paycontent button[type="submit"],
.paycontent input[type="submit"],
.paycontent input[type="button"][data-action="submit"] {
    display: block;
    width: 100%;
    margin-top: 14px;
    padding: 16px;
    background: var(--cq-primary);
    color: var(--cq-on-primary);
    border: 0;
    border-radius: 999px;
    font-size: 15px;
    font-weight: 600;
    line-height: 1.2;
    cursor: pointer;
    -webkit-appearance: none;   /* iOS Safari 会给 input[type=button] 塞自己的圆角和渐变 */
            appearance: none;
}

/* ------------------------------------------------------------
   UIkit 兜底
   modules/ 下的支付模板是和老 /checkout 共用的，那边有完整 UIkit；
   cashier 不加载 UIkit，这里只补这几个模板真正用到的类。
   缺 .uk-hidden 尤其致命 —— Klarna 靠它在 widget 就绪前藏住 Pay Now 按钮。
   ------------------------------------------------------------ */
.cashier-page .uk-hidden { display: none !important; }
.cashier-page .uk-margin-top { margin-top: 15px; }

/* uk-spinner 在 UIkit 里是 JS 组件：它往空容器里注入 SVG。没有 UIkit JS 时
   Klarna / Apple Pay / Google Pay 的 spinner 容器会一直是空的，什么都看不到。
   这里给空容器画一个纯 CSS 的圈；Stripe 那个自带 inline SVG，只需要让它转起来。 */
.uk-spinner:empty::after,
[uk-spinner]:empty::after {
    content: '';
    display: block;
    width: 24px;
    height: 24px;
    margin: 0 auto;
    border: 2px solid rgba(0, 0, 0, .18);
    border-top-color: var(--cq-primary);
    border-radius: 50%;
    animation: cashier-spin .7s linear infinite;
}
.uk-spinner > svg { animation: cashier-spin .7s linear infinite; }

/* 支付表单载入占位。
   骨架内容由 cashier.js 按模块形状注入（见 paymentSkeleton），这里只管容器和条的样子。
   注意这个元素在 opc-payment-methods.tpl 里还带着 uk-spinner（老 /checkout 靠 UIkit 画转圈），
   cashier 没加载 UIkit 的 CSS，所以这里必须自己完整定义，不能指望继承到任何东西。 */
/* 内边距抄的是 paypal/payment.tpl 注入的 .content-box__row{padding:30px 20px}，
   骨架和真实内容才会占同一个盒子 */
.payLoading {
    display: none;
    padding: 30px 20px;
}
/* .cashier-skel--art 是浮动的，不收尾的话骨架容器算不到它的高度 */
.payLoading::after { content: ''; display: table; clear: both; }

.cashier-skel {
    display: block;
    margin: 0 auto;  /* 这几个模块的内容都是居中排的 */
    border-radius: var(--cq-radius);
    /* 三段渐变横向扫过 = shimmer；纯色呼吸会和下面 paycontent 的真实控件糊成一片 */
    background: linear-gradient(90deg, #ededed 25%, #f7f7f7 37%, #ededed 63%);
    background-size: 400% 100%;
    animation: cashier-shimmer 1.3s ease-in-out infinite;
}

/* 尺寸和排布都照着真实内容来（实测：图标 36×20 浮动 + 三行 13px/1.5 文字 = 57.5 高）。
   art 也跟着 float，骨架和真实内容才是同一个盒子高度，切换时不会纵向跳；
   line 靠左，否则切换瞬间还会横向跳一下。 */
.cashier-skel--art { float: left; width: 36px; height: 20px; margin: 1px 12px 0 0; }
.cashier-skel--line { width: 76%; height: 12px; margin: 0 auto 8px 0; border-radius: 6px; }
.cashier-skel--line-short { width: 54%; }
/* 48 是实测值：PayPal SDK 渲染出来的按钮约 48 高，Stripe/Klarna 的 Pay Now
   (padding 16 + 15px/1.2 行高) 也在 50 上下，45 偏矮会让切换时往下沉一截 */
.cashier-skel--button { width: 100%; height: 48px; margin: 15px 0 5px; border-radius: 4px; }
.cashier-skel--button + .cashier-skel--button { margin-top: 8px; }

@keyframes cashier-shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }

/* 骨架换成真实内容时淡入，避免两套东西硬切一下的闪 */
.paycontent--in { animation: cashier-fade-in .18s ease-out both; }
@keyframes cashier-fade-in { from { opacity: 0; } to { opacity: 1; } }

/* ------------------------------------------------------------
   PayPal「将跳转到 PayPal」说明块
   modules/paypal/payment.tpl 自带一段 <style>：.content-box__row 居中 + .icon--offsite 102×52，
   于是插画和文案都比 Klarna 那块（文案在 Stripe iframe 里，图标小、靠左、灰字）大一圈。
   这里把它压成同一种观感，**不动 modules/** —— 老 /checkout 还在用同一份模板。

   特异性说明：模块那段 <style> 是跟着 AJAX 内容注进 DOM 的，排在 cashier.css 之后，
   同特异性会输，所以全部规则带 .cashier-page .paycontent 前缀抬上去；
   <p> 那条模块写了 font-size !important，只能同样 !important + 更高特异性才压得住。
   ------------------------------------------------------------ */
.cashier-page .paycontent .content-box__row .icon--offsite {
    /* 用 float 而不是把 .blank-slate 改成 flex —— 另外五个支付块共用 .blank-slate，
       改它的排版会波及 Stripe/Klarna/ApplePay/GooglePay/信用卡 */
    width: 66px;
    height: 52px;
    margin: 1px 12px 0 0;
    background-size: contain;
}

.cashier-page .paycontent .content-box__row p {
    overflow: hidden;   /* 触发 BFC：文字排在浮动图标右侧，而不是绕到它下面 */
    margin: 0;
    color: var(--cq-muted);
    text-align: left;
    font-size: 13px !important;
    line-height: 1.5;
}

/* 浮动图标比文字高时，后面的支付按钮会被顶得错位；给容器收个尾。
   其余五个支付块内没有浮动，这条对它们是零高度、无副作用。 */
.cashier-page .paycontent .content-box__row .blank-slate::after {
    content: '';
    display: table;
    clear: both;
}

/* Apple Pay / Google Pay 的 payment.tpl 里自带一个 <span uk-spinner>：
   按钮要等各自的 SDK 探测完可用性才出现，这段等待原本是一坨不动的东西。
   cashier 只加载了 UIkit 的 JS 没有它的 CSS —— JS 照样把 svg 注进去，
   但 uk-spinner-dash 的 keyframes 不存在，画出来的圈是死的。
   所以：把注进来的 svg 藏掉，自己用 border 画一个会转的。 */
.paycontent [uk-spinner] > svg,
.paycontent [data-uk-spinner] > svg { display: none; }

/* !important 是必须的：那两个模板给 .loading 写死了 style="margin-left:-30px"（老结账的居中补偿），
   在 cashier 的窄栏里会把转圈甩到左边缘外 */
.paycontent .loading {
    display: flex;
    justify-content: center;
    padding: 10px 0;
    margin: 0 !important;
}
.paycontent [uk-spinner],
.paycontent [data-uk-spinner] {
    display: block;
    width: 24px; height: 24px;
    border: 2px solid var(--cq-border);
    border-top-color: var(--cq-text);
    border-radius: 50%;
    animation: cashier-spin .7s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
    .cashier-skel { animation: none; background: #ededed; }
    .paycontent--in { animation: none; }
}

#checkout-error-message { display: none; }
#checkout-error-message:not(:empty) {
    display: flex;
    gap: 8px;
    margin: 0 0 14px;
    padding: 12px 14px;
    background: var(--cq-error-bg);
    border: 1px solid #f1c5c0;
    border-radius: var(--cq-radius);
    color: var(--cq-error);
    font-size: 13px;
}

/* ------------------------------------------------------------
   Billing / Remember / Note
   ------------------------------------------------------------ */
.cashier-check--billing { margin-top: 16px; }

.cashier-billing {
    margin-top: 6px;
    padding: 18px 14px 6px;
    background: var(--cq-panel);
    border: 1px solid var(--cq-border);
    border-radius: var(--cq-radius);
}
.cashier-billing[hidden] { display: none; }
.cashier-billing h3 { margin-bottom: 14px; font-size: 15px; font-weight: 600; }
.cashier-billing .fl input, .cashier-billing .fl select { background: #fff; }

.cashier-remember-card {
    padding: 15px 14px 4px;
    border: 1px solid var(--cq-border);
    border-radius: var(--cq-radius);
}
.cashier-remember-card .cashier-check { margin-bottom: 12px; }
.cashier-remember-card .fl[hidden] { display: none; }

.cashier-section--final { padding-top: 24px; }

.cashier-note-field { margin-top: 4px; }

/* ------------------------------------------------------------
   主按钮(Pay now)
   ------------------------------------------------------------ */
/* 必须带 .cashier-page 前缀。顶部的 reset `.cashier-page button { background:none; border:0; padding:0 }`
   是 (0,2,0)，(0,1,0) 的这条压不过它 —— 于是 <button class="cashier-complete-button"> 会变成
   无底色、无内边距的一行纯文字（Pay now / Complete order / Log in 三处都中招）。
   同名 (0,2,0) 靠源码顺序取胜，这条在 reset 之后所以稳。 */
.cashier-page .cashier-complete-button {
    position: relative;   /* 给 .is-busy::after 的 spinner 定位 */
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    margin-top: 18px;
    padding: 17px 24px;
    background: var(--cq-primary);
    color: var(--cq-on-primary);
    border: 0;
    border-radius: 999px;
    font-size: 16px;
    font-weight: 600;
    letter-spacing: .1px;
    cursor: pointer;
    text-align: center;
    text-decoration: none;
    transition: background .12s ease, transform .05s ease;
}
.cashier-page .cashier-complete-button:hover { background: var(--cq-primary-hover); }
.cashier-page .cashier-complete-button:active { transform: scale(.995); }
.cashier-page .cashier-complete-button[disabled] { background: #9b9b9b; cursor: not-allowed; }

/* 忙态：文字让位给一颗居中的 spinner。
   底色保持黑不跟着 [disabled] 变灰 —— 付款按钮变灰读起来像"不可用/失败"，
   而这里的事实是"正在处理"，得看着还在工作。 */
.cashier-page .cashier-complete-button.is-busy,
.cashier-page .cashier-complete-button.is-busy[disabled] {
    background: var(--cq-primary);
    color: transparent;   /* 文字节点和 <span> 一起隐掉，按钮宽高不变 */
    cursor: progress;
}
.cashier-page .cashier-complete-button.is-busy::after {
    content: '';
    position: absolute;
    top: 50%; left: 50%;
    width: 20px; height: 20px;
    margin: -10px 0 0 -10px;
    border: 2px solid rgba(255, 255, 255, .35);
    border-top-color: #fff;
    border-radius: 50%;
    animation: cashier-spin .7s linear infinite;
}
/* 键盘可达性：reset 里 button 没有 outline 兜底，圆角按钮用 ring 更清楚 */
.cashier-page .cashier-complete-button:focus-visible {
    outline: 2px solid var(--cq-primary);
    outline-offset: 3px;
}

/* ------------------------------------------------------------
   提示 / 报错 / 占位
   ------------------------------------------------------------ */
.cashier-alert {
    display: flex;
    gap: 10px;
    margin-bottom: 18px;
    padding: 13px 14px;
    border-radius: var(--cq-radius);
    font-size: 13px;
}
.cashier-alert svg { flex: 0 0 18px; width: 18px; height: 18px; margin-top: 1px; }
.cashier-alert--error { background: var(--cq-error-bg); border: 1px solid #f1c5c0; color: var(--cq-error); }
.cashier-alert--error svg { fill: var(--cq-error); }
.cashier-alert p + p { margin-top: 4px; }

.cashier-placeholder {
    padding: 16px;
    background: var(--cq-panel);
    border-radius: var(--cq-radius);
    color: var(--cq-muted);
    font-size: 13px;
}

.cashier-express-review {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
    padding: 13px 14px;
    border: 1px solid var(--cq-border);
    border-radius: var(--cq-radius);
    background: var(--cq-panel);
    font-size: 13px;
}
.cashier-express-review span { color: var(--cq-muted); }

/* 快捷支付模式下 Payment 区里的确认行，替掉那个永远转不完的加载圈 */
.cashier-express-method {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 13px 14px;
    border: 1px solid var(--cq-border);
    border-radius: var(--cq-radius);
    background: var(--cq-panel);
    font-size: 13px;
    color: var(--cq-muted);
}
.cashier-express-method svg {
    flex: 0 0 18px;
    width: 18px; height: 18px;
    color: #1a7f4b;
}

/* ------------------------------------------------------------
   计费调试面板（仅 ?debug=cost）
   ------------------------------------------------------------ */
.cashier-cost {
    padding: 14px;
    border: 1px dashed var(--cq-border);
    border-radius: var(--cq-radius);
    background: var(--cq-panel);
    font-size: 13px;
}
.cashier-cost__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 10px;
}
.cashier-page .cashier-cost__head button {
    padding: 4px 10px;
    border: 1px solid var(--cq-border);
    border-radius: 999px;
    background: #fff;
    font-size: 12px;
    color: var(--cq-muted);
    cursor: pointer;
}
.cashier-cost__table { width: 100%; border-collapse: collapse; }
.cashier-cost__table th,
.cashier-cost__table td {
    padding: 6px 4px;
    text-align: right;
    border-bottom: 1px solid var(--cq-panel-border);
    /* 数字用等宽，跳数的时候列不会左右抖 */
    font-variant-numeric: tabular-nums;
}
.cashier-cost__table th:first-child,
.cashier-cost__table td:first-child { text-align: left; font-variant-numeric: normal; }
.cashier-cost__table th { font-weight: 500; color: var(--cq-muted); font-size: 12px; }
.cashier-cost__delta { color: var(--cq-muted); }
.cashier-cost__delta.is-hot { color: var(--cq-error); font-weight: 600; }
.cashier-cost__note { margin-top: 8px; color: var(--cq-muted); font-size: 12px; line-height: 1.5; }

.cashier-loader {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 2px;
    color: var(--cq-muted);
    font-size: 13px;
}
.cashier-loader > span:first-child {
    width: 18px; height: 18px;
    border: 2px solid var(--cq-border);
    border-top-color: var(--cq-text);
    border-radius: 50%;
    animation: cashier-spin .7s linear infinite;
}

@keyframes cashier-spin { to { transform: rotate(360deg); } }

#cashier-loading-mask {
    position: fixed;
    inset: 0;
    z-index: 999;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, .7);
}
.cashier-loading-mask__spinner {
    width: 34px; height: 34px;
    border: 3px solid var(--cq-border);
    border-top-color: var(--cq-text);
    border-radius: 50%;
    animation: cashier-spin .7s linear infinite;
}

/* ------------------------------------------------------------
   政策链接
   ------------------------------------------------------------ */
.cashier-policies {
    display: flex;
    gap: 16px;
    margin-top: 44px;
    padding-top: 15px;
    border-top: 1px solid var(--cq-panel-border);
    font-size: 12px;
}
.cashier-policies a {
    color: var(--cq-focus);
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* ------------------------------------------------------------
   订单摘要
   ------------------------------------------------------------ */
.cashier-products { display: flex; flex-direction: column; gap: 14px; }

.cashier-product {
    display: flex;
    align-items: center;
    gap: 14px;
}

.cashier-product__image {
    position: relative;
    flex: 0 0 64px;
    width: 64px; height: 64px;
}

.cashier-product__image img {
    width: 100%; height: 100%;
    object-fit: cover;
    border: 1px solid rgba(0, 0, 0, .1);
    border-radius: 8px;
    background: #fff;
}

.cashier-product__image span {
    position: absolute;
    top: -8px; right: -8px;
    min-width: 21px; height: 21px;
    padding: 0 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: #1a1a1a;
    color: #fff;
    border: 2px solid var(--cq-panel);
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
}

.cashier-product__details { flex: 1; min-width: 0; }
.cashier-product__details h3 { font-size: 14px; font-weight: 500; line-height: 1.35; }
.cashier-product__details p { color: var(--cq-muted); font-size: 12px; margin-top: 2px; }
.cashier-product__price { font-size: 14px; font-weight: 500; white-space: nowrap; }

/* 折扣码 */
.cashier-discount {
    display: flex;
    gap: 10px;
    align-items: stretch;
    margin-top: 21px;
}
.cashier-discount .fl { flex: 1; margin-bottom: 0; }
.cashier-discount .fl input { background: #fff; }

.cashier-discount button[name="submitAddDiscount"] {
    flex: 0 0 auto;
    padding: 0 22px;
    background: #ededed;
    color: #8a8a8a;
    border: 1px solid var(--cq-border);
    border-radius: var(--cq-radius);
    font-size: 14px;
    font-weight: 500;
    transition: background .12s ease, color .12s ease;
}
.cashier-discount button[name="submitAddDiscount"]:not([disabled]) {
    background: var(--cq-primary);
    color: var(--cq-on-primary);
    border-color: var(--cq-text);
}

.cashier-discount__error {
    margin: 8px 0 0;
    color: var(--cq-error);
    font-size: 12px;
}

.cashier-discount-list { margin-top: 12px; display: flex; flex-direction: column; gap: 6px; }
.cashier-discount-list > div {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 13px;
}
.cashier-discount-tag {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    background: #ededed;
    border-radius: 4px;
    font-weight: 500;
}
.cashier-discount-tag svg { width: 13px; height: 13px; fill: var(--cq-muted); }
.submitRemoveDiscount { color: var(--cq-muted); font-size: 17px; line-height: 1; padding: 2px 6px; }
.submitRemoveDiscount:hover { color: var(--cq-text); }

/* 合计 */
.cashier-totals {
    margin-top: 21px;
    padding-top: 4px;
    font-size: 14px;
}
.cashier-totals > div {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-top: 9px;
}
/* 折扣行靠 hidden 属性控制显隐，但上面这条 display:flex 会把浏览器默认的
   [hidden]{display:none} 顶掉 —— 不补这条，没有折扣时会露出一行 "− $0.00" */
.cashier-totals > div[hidden] { display: none; }
.cashier-totals dt { font-weight: 400; color: var(--cq-text); }
.cashier-totals dd { font-weight: 500; }
.cashier-totals__discount dd { color: var(--cq-text); }
.cashier-muted { color: var(--cq-muted); }

.cashier-totals__total {
    margin-top: 14px !important;
    padding-top: 14px;
    border-top: 1px solid var(--cq-panel-border);
}
.cashier-totals__total dt { font-size: 16px; font-weight: 600; }
.cashier-totals__total dd { font-size: 19px; font-weight: 600; }
.cashier-totals__total dd small {
    margin-right: 4px;
    color: var(--cq-muted);
    font-size: 12px;
    font-weight: 400;
}

/* ------------------------------------------------------------
   登录弹窗
   ------------------------------------------------------------ */
.cashier-modal {
    position: fixed;
    inset: 0;
    z-index: 200;
    display: none;
    align-items: center;
    justify-content: center;
}
.cashier-modal.is-open,
.cashier-modal.active { display: flex; }

.cashier-modal .modal-overlay {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, .45);
    border: 0;
    cursor: default;
}

.cashier-modal__dialog {
    position: relative;
    z-index: 1;
    width: min(92vw, 420px);
    padding: 28px 24px 24px;
    background: #fff;
    border-radius: 12px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, .25);
}

.cashier-modal__dialog h2 { margin-bottom: 16px; font-size: 19px; font-weight: 600; }

.cashier-modal__dialog .close {
    position: absolute;
    top: 12px; right: 14px;
    font-size: 22px;
    color: var(--cq-muted);
    line-height: 1;
}
.cashier-modal__dialog .close:hover { color: var(--cq-text); }
.cashier-modal__dialog .cashier-complete-button { margin-top: 6px; }

/* ------------------------------------------------------------
   空购物车页
   ------------------------------------------------------------ */
.cashier-empty-page { min-height: 100vh; background: #fff; }

.cashier-empty {
    max-width: 420px;
    margin: 0 auto;
    padding: 88px 21px;
    text-align: center;
}
.cashier-empty svg { width: 52px; height: 52px; color: #c9c9c9; }
.cashier-empty h1 { margin: 18px 0 8px; font-size: 21px; font-weight: 600; }
.cashier-empty p { color: var(--cq-muted); font-size: 14px; }
.cashier-empty .cashier-complete-button { margin-top: 24px; }

/* ------------------------------------------------------------
   Guard(checkoutguard 注入)
   ------------------------------------------------------------ */
.cashier-guard { margin-top: 2px; }
#guard-fields .fl { margin-bottom: 14px; }

/* ------------------------------------------------------------
   SweetAlert(onepage.js / checkoutguard 错误弹窗依赖,样式抽自 base.css)
   ------------------------------------------------------------ */

.sweet-overlay{background-color:rgba(0,0,0,.4);position:fixed;left:0;right:0;top:0;bottom:0;display:none;z-index:1000}.sweet-alert{background-color:#fff;width:478px;padding:17px;border-radius:5px;text-align:center;position:fixed;left:50%;top:50%;margin-left:-256px;margin-top:-200px;overflow:hidden;display:none;z-index:2000}.sweet-alert{width:auto;margin-left:0;margin-right:0;left:15px;right:15px}.sweet-alert h2{color:#575757;font-size:30px;text-align:center;font-weight:600;text-transform:none;position:relative;margin:25px 0;padding:0;line-height:25px;display:block}.sweet-alert p{color:#797979;font-size:16px;text-align:center;font-weight:300;position:relative;margin:0;padding:0;line-height:normal}.sweet-alert button{background-color:#333;color:#fff;border:0;box-shadow:none;font-size:17px;font-weight:500;border-radius:5px;padding:10px 32px;margin:26px 5px 0;cursor:pointer}.sweet-alert button:focus{outline:0;box-shadow:0 0 2px rgba(128,179,235,.5),inset 0 0 0 1px rgba(0,0,0,.05)}.sweet-alert button:hover{background-color:#222}.sweet-alert button:active{background-color:#81ccee}.sweet-alert button.cancel{background-color:#d0d0d0}.sweet-alert button.cancel:hover{background-color:#c8c8c8}.sweet-alert button.cancel:active{background-color:#b6b6b6}.sweet-alert button.cancel:focus{box-shadow:rgba(197,205,211,.8) 0 0 2px,rgba(0,0,0,.0470588) 0 0 0 1px inset!important}.sweet-alert button::-moz-focus-inner{border:0}.sweet-alert[data-has-cancel-button=false] button{box-shadow:none!important}.sweet-alert .icon{width:80px;height:80px;border:4px solid gray;border-radius:50%;margin:20px auto;padding:0;position:relative;box-sizing:content-box}.sweet-alert .icon.error{border-color:#f27474}.sweet-alert .icon.error .x-mark{position:relative;display:block}.sweet-alert .icon.error .line{position:absolute;height:5px;width:47px;background-color:#f27474;display:block;top:37px;border-radius:2px}.sweet-alert .icon.error .line.left{-webkit-transform:rotate(45deg);transform:rotate(45deg);left:17px}.sweet-alert .icon.error .line.right{-webkit-transform:rotate(-45deg);transform:rotate(-45deg);right:16px}.sweet-alert .icon.warning{border-color:#f8bb86}.sweet-alert .icon.warning .body{position:absolute;width:5px;height:47px;left:50%;top:10px;border-radius:2px;margin-left:-2px;background-color:#f8bb86}.sweet-alert .icon.warning .dot{position:absolute;width:7px;height:7px;border-radius:50%;margin-left:-3px;left:50%;bottom:10px;background-color:#f8bb86}.sweet-alert .icon.info{border-color:#c9dae1}.sweet-alert .icon.info::before{content:"";position:absolute;width:5px;height:29px;left:50%;bottom:17px;border-radius:2px;margin-left:-2px;background-color:#c9dae1}.sweet-alert .icon.info::after{content:"";position:absolute;width:7px;height:7px;border-radius:50%;margin-left:-3px;top:19px;background-color:#c9dae1}.sweet-alert .icon.success{border-color:#a5dc86}.sweet-alert .icon.success::before,.sweet-alert .icon.success::after{content:'';border-radius:50%;position:absolute;width:60px;height:120px;background:#fff;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.sweet-alert .icon.success::before{border-radius:120px 0 0 120px;top:-7px;left:-33px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:60px 60px;transform-origin:60px 60px}.sweet-alert .icon.success::after{border-radius:0 120px 120px 0;top:-11px;left:30px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:0 60px;transform-origin:0 60px}.sweet-alert .icon.success .placeholder{width:80px;height:80px;border:4px solid rgba(165,220,134,.2);border-radius:50%;box-sizing:content-box;position:absolute;left:-4px;top:-4px;z-index:2}.sweet-alert .icon.success .fix{width:5px;height:90px;background-color:#fff;position:absolute;left:28px;top:8px;z-index:1;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.sweet-alert .icon.success .line{height:5px;background-color:#a5dc86;display:block;border-radius:2px;position:absolute;z-index:2}.sweet-alert .icon.success .line.tip{width:25px;left:14px;top:46px;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.sweet-alert .icon.success .line.long{width:47px;right:8px;top:38px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.sweet-alert .icon.custom{background-size:contain;border-radius:0;border:0;background-position:center center;background-repeat:no-repeat}

/* ── sweet-alert 收敛（2026-08-18）───────────────────────────────────────
   上面那段内嵌的 sweetalert 样式里，本该只在窄屏生效的
   `.sweet-alert{width:auto;left:15px;right:15px;margin:0}` 漏在了媒体查询外面，
   桌面端弹窗跟着铺满整屏。这里统一收成 420px 居中卡片，并贴合结账页的圆角/阴影。 */
.sweet-alert{
    width:auto !important;
    max-width:420px;
    left:16px !important;
    right:16px !important;
    margin-left:auto !important;
    margin-right:auto !important;
    margin-top:0 !important;
    top:50% !important;
    -webkit-transform:translateY(-50%);
    transform:translateY(-50%);
    padding:28px 28px 26px;
    border-radius:12px;
    box-shadow:0 18px 48px rgba(0,0,0,.18);
    font-family:var(--cq-font, inherit);
}
.sweet-alert h2{font-size:22px;line-height:28px;margin:18px 0 10px;color:#171717;}
.sweet-alert p{font-size:14px;line-height:22px;color:#5f5b56;}
.sweet-alert .icon{width:64px;height:64px;margin:6px auto 0;}
.sweet-alert .icon.error .line{width:38px;top:29px;height:4px;}
.sweet-alert .icon.error .line.left{left:13px;}
.sweet-alert .icon.error .line.right{right:13px;}
.sweet-alert .icon.warning .body{height:38px;top:8px;}
.sweet-alert .icon.success::before,.sweet-alert .icon.success::after{display:none;}
.sweet-alert .icon.success .fix{display:none;}
.sweet-alert .icon.success .placeholder{width:64px;height:64px;}
.sweet-alert button{
    font-size:14px;
    font-weight:600;
    letter-spacing:.2px;
    padding:11px 26px;
    margin:22px 4px 0;
    border-radius:8px;
    /* 底色由 sweetalert 以内联样式写死(#333)，这里不争；只收形状 */
}
.sweet-alert button.cancel{background-color:#eeeae5;color:#171717;}
.sweet-alert button.cancel:hover{background-color:#e2ddd6;}
@media (max-width:480px){
    .sweet-alert{padding:22px 18px 20px;}
    .sweet-alert h2{font-size:19px;line-height:25px;}
}
