/* ============================================================
   HXX-UI 轻量组件库 · 虹小轩UI（HongXiaoXuanUI）（css/hxx-ui.css + js/hxx-ui.js）
   源自 hongxiaoxuan.com 项目，现为独立组件库项目（本目录即全部）：
   设计令牌 / 弹窗 HXXDialog / 轻提示 HXXToast / 通知卡 HXXNotification / 抽屉 HXXDrawer
   / 日期选择器 HXXDatePicker / 全局水印 HXXWatermark / 标签页 .hxx-tabs
   / 富内容气泡 HXXPopover / 折叠面板 .hxx-collapse / 回到顶部 .hxx-backtop
   / 滑动输入条 .hxx-slider（单滑块 + .hxx-slider-dual 双滑块区间）/ 滑动验证框 HXXVerify
   / 按钮 .hxx-btn
   / 表单控件（输入 .hxx-input·多行 .hxx-textarea·自绘下拉 HXXSelect·开关 .hxx-switch·复选 .hxx-checkbox·单选 .hxx-radio·布局 .hxx-form-item）
   / 展示组件（卡片 .hxx-card·横幅 .hxx-notice·步骤 .hxx-steps·进度 .hxx-progress·分页 .hxx-pagination·空态 .hxx-empty·骨架 .hxx-skeleton·头像 .hxx-avatar·气泡 [data-hxx-tip]）
   / 加载指示 .hxx-loading / 标签徽标 .hxx-tag·.hxx-badge / 超细滚动条
   / 动效引擎 HXXEffect（粒子层 .hxx-fx-layer + .hxx-fx-shake / -pulse / -ripple / -heart / -check，令牌 --hxx-fx-*）
   零依赖：不依赖 HWUI / axios / 任何框架，两个文件复制即可复用。
   使用文档见本目录 README.md；设计规格与实现原理见 CODE_WIKI.md；
   在线演示打开 demo.html（同样只依赖本库两个文件）。
   ============================================================ */

/* ---------- 设计令牌 ---------- */
:root {
    /* 品牌色 - 保留蓝色主调 */
    --hxx-primary: #158aff;
    --hxx-primary-deep: #0d7ae8;
    --hxx-primary-light: #4da6ff;
    --hxx-primary-soft: #e3f2fd;
    --hxx-primary-hover: #0d7ae8;

    /* 中性色 - 干净灰阶 */
    --hxx-bg: #fafafa;
    --hxx-surface: #ffffff;
    --hxx-muted: #f5f6f8;
    --hxx-hover: #f3f6fb;
    --hxx-tile: #f5f6f8;

    /* 文字 */
    --hxx-text: #1a1a2e;
    --hxx-text-2: #525266;
    --hxx-text-3: #8c8c9e;
    --hxx-text-placeholder: #b0b0bc;

    /* 边框 */
    --hxx-border: #eceef2;
    --hxx-border-strong: #dcdfe6;

    /* 功能色 */
    --hxx-success: #16a34a;
    --hxx-success-soft: #f0fdf4;
    --hxx-warning: #ea8c00;
    --hxx-warning-soft: #fffbeb;
    --hxx-danger: #e5484d;
    --hxx-danger-soft: #fef2f2;
    --hxx-neutral: #8c8c9e;
    --hxx-neutral-soft: #f4f4f6;

    /* 圆角 */
    --hxx-radius-xs: 6px;
    --hxx-radius-sm: 8px;
    --hxx-radius: 12px;
    --hxx-radius-lg: 16px;
    --hxx-radius-full: 999px;

    /* 阴影 - 极淡 */
    --hxx-shadow-xs: 0 1px 2px rgba(0,0,0,0.03);
    --hxx-shadow: 0 1px 3px rgba(0,0,0,0.04), 0 1px 2px rgba(0,0,0,0.02);
    --hxx-shadow-md: 0 4px 12px rgba(0,0,0,0.06);
    --hxx-shadow-lg: 0 8px 28px rgba(0,0,0,0.08);
    --hxx-shadow-primary: 0 4px 14px rgba(21,138,255,0.25);

    /* 间距 */
    --hxx-gap-xs: 6px;
    --hxx-gap-sm: 10px;
    --hxx-gap-md: 16px;
    --hxx-gap-lg: 24px;
    --hxx-gap-xl: 32px;

    /* 布局 */
    --hxx-content-width: 720px;
    --hxx-nav-height: 56px;

    /* 过渡 */
    --hxx-t-fast: 0.15s;
    --hxx-t: 0.2s;
    --hxx-t-slow: 0.3s;

    /* 动效引擎 HXXEffect（礼花 / 星芒 / 飘心 / 打勾 / 数字滚动 / shake / pulse / ripple）
       粒子配色不走令牌而由 js/hxx-ui.js 运行时读取 --hxx-primary 等色值令牌，宿主换肤自动跟随 */
    --hxx-fx-z: 10008;              /* 层级：高于日期面板 10005，低于水印 10010（水印须覆盖全站） */
    --hxx-fx-ease-back: cubic-bezier(0.34, 1.56, 0.64, 1); /* 弹性曲线，与 HXXDialog 形变 EASE_OUT_BACK 同源 */
    --hxx-fx-shake-dist: 6px;       /* 抖动位移幅度 */
    --hxx-fx-shake-dur: 0.4s;
    --hxx-fx-shake-dur-reduced: 0.15s; /* reduced-motion 下的极短弱版：shake 承载「失败」语义，不整段丢弃 */
    --hxx-fx-pulse-scale: 1.06;     /* 弹一下的放大峰值（克制，不夸张） */
    --hxx-fx-pulse-dur: 0.32s;
    --hxx-fx-ripple-dur: 0.55s;
    --hxx-fx-heart-dur: 1.4s;
    --hxx-fx-check-dur: 0.5s;
    --hxx-fx-countup-dur: 0.9s;     /* JS 读取，控制数字滚动时长 */
}

/* ---------- 局部盒模型重置（不污染宿主项目全局） ----------
   组件壳内一律 border-box，与原项目全局 reset 行为一致 */
.hxx-dialog-mask, .hxx-dialog-mask *,
.hxx-btn, .hxx-btn *, .hxx-loading, .hxx-loading *,
.hxx-toast, .hxx-toast *,
.hxx-notify, .hxx-notify *,
.hxx-form-item, .hxx-form-item *,
.hxx-input, .hxx-textarea, .hxx-select, .hxx-switch, .hxx-checkbox, .hxx-radio,
.hxx-tag, .hxx-badge,
.hxx-drawer-mask, .hxx-drawer-mask *,
.hxx-date-panel, .hxx-date-panel *,
.hxx-popover, .hxx-popover *,
.hxx-collapse, .hxx-collapse *,
.hxx-backtop,
.hxx-slider-single, .hxx-slider-dual, .hxx-slider-bubble,
.hxx-verify, .hxx-verify *,
.hxx-card, .hxx-notice, .hxx-tabs-bar, .hxx-tab, .hxx-tab-pane,
.hxx-steps, .hxx-step, .hxx-step-num, .hxx-step-label,
.hxx-progress, .hxx-progress-bar, .hxx-pagination, .hxx-page,
.hxx-empty, .hxx-skeleton, .hxx-avatar, .hxx-watermark,
.hxx-fx-heart, .hxx-fx-check, .hxx-fx-check-ring, .hxx-fx-ripple {
    box-sizing: border-box;
}
/* 波纹 / 进度环的伪元素走 inset+border 定位，必须显式 border-box
   （伪元素不能并进上面的选择器组，混写会整条规则失效） */
.hxx-step-num::after, .hxx-pagination .hxx-page::after,
.hxx-progress-circle::before, .hxx-progress-circle::after,
.hxx-progress.is-gradient .hxx-progress-bar::before, .hxx-progress.is-gradient .hxx-progress-bar::after,
.hxx-collapse-header::after {
    box-sizing: border-box;
}

/* ---------- 超细滚动条：空闲隐藏、滚动或悬停显示 ----------
   thumb 默认透明但轨道保留 4px 占位，显隐不会引起内容横向抖动；
   .hxx-scrolling 由 js/hxx-ui.js 在元素滚动时挂上、停止 1 秒后摘掉（触发淡出）；
   .hxx-scrollable 由 js/hxx-ui.js 标记「确认可滚动」的容器，鼠标悬停即提前显示；
   html/body 必须排除在悬停规则外（html:hover 恒真，否则页面滚动条永不出隐藏）。
   Firefox 走标准 scrollbar-*，必须用 @supports 隔离：Chromium 121+ 一旦识别到
   scrollbar-color 就会整体忽略 ::-webkit-scrollbar 伪元素规则。 */
::-webkit-scrollbar { width: 4px; height: 4px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
    background: transparent;
    border-radius: 2px;
    transition: background-color .25s ease;
}
::-webkit-scrollbar-thumb:hover { background: rgba(153, 153, 153, .7); }
.hxx-scrolling::-webkit-scrollbar-thumb,
.hxx-scrollable:not(html):not(body):hover::-webkit-scrollbar-thumb {
    background: rgba(153, 153, 153, .5);
}
@supports (-moz-appearance: none) {
    * { scrollbar-width: thin; scrollbar-color: transparent transparent; }
    .hxx-scrolling,
    .hxx-scrollable:not(html):not(body):hover {
        scrollbar-color: rgba(153, 153, 153, .5) transparent;
    }
}

/* ---------- 按钮 .hxx-btn（原生 button，零依赖） ----------
   视觉对齐《设计契约.md》10.2 的 hw-button 规格（胶囊 999px、min-height 38px、
   14px/600、padding 0 20px、1px 边框、白底、无阴影）；本项目内 hw-button 的
   user.css 覆盖样式与此一致，弹窗 actions 按钮由 js/hxx-ui.js 用本类自绘。
   主按钮：<button class="hxx-btn" color="blue">（与 hw-button 的 color 属性语义一致）；
   变体：.hxx-btn-sm / .hxx-btn-danger / .hxx-btn-ghost / .hxx-btn-block */
.hxx-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 38px;
    padding: 0 20px;
    border: 1px solid var(--hxx-border-strong);
    border-radius: var(--hxx-radius-full);
    background: var(--hxx-surface);
    color: var(--hxx-text-2);
    font-size: 14px;
    font-weight: 600;
    font-family: inherit;
    line-height: 1;
    cursor: pointer;
    user-select: none;
    transition: all var(--hxx-t);
}
.hxx-btn:hover {
    border-color: var(--hxx-text-3);
    background: var(--hxx-muted);
}
.hxx-btn:active { transform: scale(0.95); }
.hxx-btn[color="blue"] {
    background: var(--hxx-primary);
    color: #fff;
    border-color: var(--hxx-primary);
}
.hxx-btn[color="blue"]:hover {
    background: var(--hxx-primary-hover);
    border-color: var(--hxx-primary-hover);
}
.hxx-btn[color="red"],
.hxx-btn.hxx-btn-danger {
    background: var(--hxx-danger);
    color: #fff;
    border-color: var(--hxx-danger);
}
.hxx-btn.hxx-btn-sm {
    min-height: 32px;
    font-size: 13px;
    padding: 0 14px;
}
.hxx-btn.hxx-btn-ghost {
    background: transparent;
    border-color: transparent;
    color: var(--hxx-primary);
    padding: 0 12px;
}
.hxx-btn.hxx-btn-ghost:hover { background: var(--hxx-primary-soft); }
.hxx-btn.hxx-btn-block { width: 100%; }
.hxx-btn[disabled] {
    opacity: 0.6;
    pointer-events: none;
}

/* ---------- 输入框 .hxx-input / 多行文本 .hxx-textarea / 下拉选择 .hxx-select（原生控件自绘） ----------
   高度与 .hxx-btn 对齐（38px；-sm 32px），focus 主色描边 + 3px 软光圈；
   .is-error 错误态（红边 + 红光圈，配合 .hxx-form-error 文案使用）；
   select 用 appearance:none + 内联 SVG 箭头（零依赖，不引外部图标文件）；
   禁用态背景一律写 background-color 而非 background 简写——简写会连箭头背景图一起清掉 */
.hxx-input, .hxx-textarea, .hxx-select {
    font-family: inherit;
    font-size: 14px;
    line-height: 1.4;
    color: var(--hxx-text);
    background-color: var(--hxx-surface);
    border: 1px solid var(--hxx-border-strong);
    border-radius: var(--hxx-radius-sm);
    outline: none;
    transition: border-color var(--hxx-t-fast), box-shadow var(--hxx-t-fast);
}
.hxx-input, .hxx-select { height: 38px; padding: 0 12px; }
.hxx-textarea {
    min-height: 76px;
    padding: 9px 12px;
    line-height: 1.6;
    resize: vertical;
}
.hxx-input::placeholder, .hxx-textarea::placeholder { color: var(--hxx-text-placeholder); }
.hxx-input:hover, .hxx-textarea:hover, .hxx-select:hover { border-color: var(--hxx-text-3); }
.hxx-input:focus, .hxx-textarea:focus, .hxx-select:focus {
    border-color: var(--hxx-primary);
    box-shadow: 0 0 0 3px rgba(21, 138, 255, 0.1);
}
.hxx-input:disabled, .hxx-textarea:disabled, .hxx-select:disabled {
    background-color: var(--hxx-muted);
    color: var(--hxx-text-3);
    cursor: not-allowed;
}
.hxx-input.is-error, .hxx-textarea.is-error, .hxx-select.is-error { border-color: var(--hxx-danger); }
.hxx-input.is-error:focus, .hxx-textarea.is-error:focus, .hxx-select.is-error:focus {
    box-shadow: 0 0 0 3px rgba(229, 72, 77, 0.1);
}
.hxx-input.hxx-input-sm, .hxx-select.hxx-select-sm { height: 32px; font-size: 13px; padding: 0 10px; }
.hxx-select {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 34px;
    cursor: pointer;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%238c8c9e' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
}

/* ---------- 开关 .hxx-switch / 复选框 .hxx-checkbox / 单选框 .hxx-radio（原生控件自绘，零 JS） ----------
   全部基于原生 input（appearance:none 自绘轨道/滑块/勾形/圆点）：
   可直接参与表单提交与 JS 取值，无障碍、键盘、label 联动全部随原生行为走，库无需任何脚本配合 */
/* 开关 .hxx-switch：布局取自 ui.hisuperwan.com 的 hw-switch（简化版）——
   70×28px 圆角矩形轨道（10px 圆角、2px #c8c8c8 边常驻不变色），
   关闭态半透明黑底、:checked 转主色；手柄 ::before 为 32×35px 实色浅灰滑块，
   比轨道更高、上下各溢出 3.5px，滑至轨道外缘；
   不做毛玻璃、不做强发光——投影仅 0 2px 5px 柔和落影 + 顶部一线内高光，
   选中态只补一圈轻蓝光晕；悬停微放大、选中微缩；
   ::after 为手柄中央 5×18px 竖条指示灯（灰 → 主色），left 按手柄中心精确对齐
   （11.5px ↔ calc(100% - 16.5px)）。
   绝对定位的百分比与 calc(100%) 均相对 padding box（28 − 2×2 边框 = 高 24px / 宽 66px）；
   :focus-visible 显示 3px 主色软光圈（键盘可达，与 .hxx-input focus 同规格）。 */
.hxx-switch {
    appearance: none;
    -webkit-appearance: none;
    position: relative;
    width: 70px;
    height: 28px;
    margin: 0;
    border: 2px solid #c8c8c8;
    border-radius: 10px;
    background-color: rgba(0, 0, 0, 0.17); /* HWUI #0000002b */
    cursor: pointer;
    vertical-align: middle;
    outline: none;
    transition: background-color var(--hxx-t-slow), box-shadow var(--hxx-t-slow);
}
.hxx-switch::before { /* 实色滑块（oversized：35px 高于 28px 轨道，上下溢出 3.5px） */
    content: "";
    position: absolute;
    top: 50%;
    left: -2px;
    width: 32px;
    height: 35px;
    margin-top: -17.5px;
    border-radius: 10px;
    background-color: #f1f1f1;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.9);
    transition: left var(--hxx-t-slow), scale var(--hxx-t-slow), box-shadow var(--hxx-t-slow);
}
.hxx-switch:hover::before { scale: 1.05; }
.hxx-switch:checked { background-color: var(--hxx-primary); }
.hxx-switch:checked { animation: hxx-switch-pop var(--hxx-t) cubic-bezier(0.34, 1.56, 0.64, 1); } /* 拨动瞬间轨道轻弹一下 */
.hxx-switch:checked::before {
    left: calc(100% - 30px); /* 贴轨道右外缘（与关闭态 -2px 左右对称） */
    scale: 0.98;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.08), 0 0 8px 2px rgba(132, 194, 255, 0.4),
        inset 0 1px 0 rgba(255, 255, 255, 0.9); /* 轻蓝光晕（弱化自 HWUI 17px 3px 强发光） */
}
.hxx-switch:focus-visible { box-shadow: 0 0 0 3px rgba(21, 138, 255, 0.15); }
.hxx-switch:disabled {
    opacity: 0.5;
    pointer-events: none; /* 抑制悬停缩放等动画，与 .hxx-btn[disabled] 一致 */
}
.hxx-switch::after { /* 指示灯：手柄中央竖条小灯，随手柄左右同移（灰 → 主色） */
    content: "";
    position: absolute;
    top: calc(50% - 9px);
    left: 11.5px; /* 手柄中心（-2 + 16）− 灯宽半（2.5），与手柄精确同心 */
    width: 5px;
    height: 18px;
    border-radius: 5px;
    background-color: #8e8e8e;
    transition: left var(--hxx-t-slow), background-color var(--hxx-t-slow);
}
.hxx-switch:checked::after {
    left: calc(100% - 16.5px); /* 手柄右位中心（66 − 30 + 16）− 2.5 */
    background-color: var(--hxx-primary);
}

.hxx-checkbox, .hxx-radio {
    appearance: none;
    -webkit-appearance: none;
    position: relative;
    width: 18px;
    height: 18px;
    margin: 0;
    border: 1.5px solid var(--hxx-border-strong);
    background-color: var(--hxx-surface);
    cursor: pointer;
    vertical-align: -3px; /* 与行内文字基线视觉对齐 */
    transition: background-color var(--hxx-t-fast), border-color var(--hxx-t-fast), transform var(--hxx-t-fast);
}
.hxx-checkbox:hover, .hxx-radio:hover { border-color: var(--hxx-primary); }
.hxx-checkbox:active, .hxx-radio:active { transform: scale(0.88); } /* 按压反馈 */
.hxx-checkbox:focus-visible, .hxx-radio:focus-visible { box-shadow: 0 0 0 3px rgba(21, 138, 255, 0.15); }
.hxx-checkbox:disabled, .hxx-radio:disabled { opacity: 0.5; cursor: not-allowed; }
.hxx-checkbox { border-radius: 4px; }
.hxx-checkbox:checked { background-color: var(--hxx-primary); border-color: var(--hxx-primary); }
.hxx-checkbox:checked { animation: hxx-check-pop var(--hxx-t) cubic-bezier(0.34, 1.56, 0.64, 1); }
.hxx-checkbox:checked::after { /* 白色对勾（两段边框旋转 45° 画出）。
    定位按「旋转后视觉外框中心」对齐控件中心反推：勾形相对自身盒（7×11）在竖直方向
    视觉中心偏低约 1.77px，取盒几何中心会导致勾整体偏右下——left/top 已含该补偿 */
    content: "";
    position: absolute;
    left: 4px;
    top: 0.25px;
    width: 5px;
    height: 9px;
    border: solid #fff;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
    animation: hxx-check-draw var(--hxx-t) cubic-bezier(0.34, 1.56, 0.64, 1); /* 勾形缩放画入 */
}
.hxx-radio { border-radius: 50%; }
.hxx-radio:checked { border-color: var(--hxx-primary); }
.hxx-radio:checked::after { /* 主色实心圆点：绝对定位偏移相对 padding box（18 − 2×1.5 边 = 15px），(15 − 7)/2 = 4px 居中 */
    content: "";
    position: absolute;
    left: 4px;
    top: 4px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--hxx-primary);
    animation: hxx-radio-pop var(--hxx-t) cubic-bezier(0.34, 1.56, 0.64, 1); /* 圆点缩放弹入 */
}
/* 激活动画的公共层：::before 涟漪——选中瞬间从控件边缘荡开一圈主色光环后消散（克制版）；
   inset −1.5px 把涟漪盒扩到含边框的全盒（定位默认相对 padding box），光环与控件外缘吻合 */
.hxx-checkbox::before, .hxx-radio::before {
    content: "";
    position: absolute;
    inset: -1.5px;
    border-radius: inherit;
    pointer-events: none;
}
.hxx-checkbox:checked::before, .hxx-radio:checked::before {
    animation: hxx-check-ripple var(--hxx-t-slow) ease-out;
}
/* 激活动画关键帧（契约 §12 时长令牌；reduce 降级见文件末尾统一块） */
@keyframes hxx-check-pop { /* 复选框体：缩一下再弹过一点回正 */
    0% { transform: scale(0.72); }
    55% { transform: scale(1.15); }
    100% { transform: scale(1); }
}
@keyframes hxx-check-draw { /* 勾形：从小到大画出（终点与静态 rotate(45deg) 一致，无跳变） */
    0% { opacity: 0; transform: rotate(45deg) scale(0.3); }
    100% { opacity: 1; transform: rotate(45deg) scale(1); }
}
@keyframes hxx-radio-pop { /* 圆点：从 0 弹到 1.35 倍再回正 */
    0% { transform: scale(0); }
    55% { transform: scale(1.35); }
    100% { transform: scale(1); }
}
@keyframes hxx-switch-pop { /* 开关轨道：拨通瞬间轻弹 */
    0% { transform: scale(0.96); }
    55% { transform: scale(1.03); }
    100% { transform: scale(1); }
}
@keyframes hxx-check-ripple { /* 涟漪：主色光环 0 透明度扩散到 8px 消散 */
    0% { box-shadow: 0 0 0 0 rgba(21, 138, 255, 0.3); }
    100% { box-shadow: 0 0 0 8px rgba(21, 138, 255, 0); }
}

/* ---------- 表单布局 .hxx-form-item（label + 控件 + 错误/辅助文案） ----------
   横排紧凑布局：label 定宽右对齐、控件占满余宽（.hxx-form-control 内输入类自动 100% 宽）；
   .hxx-form-item-vertical 变体为纵排（label 在上，适合移动端窄屏）；
   is-required 在 label 前加红色星号；错误文案 .hxx-form-error / 辅助说明 .hxx-form-hint */
.hxx-form-item {
    display: flex;
    align-items: flex-start;
    gap: 12px;
}
.hxx-form-item + .hxx-form-item { margin-top: 16px; }
.hxx-form-label {
    flex: none;
    width: 72px;
    padding-top: 9px; /* (38px 控件高 − 20px 行高) / 2，与单行控件视觉居中；textarea 多行时对齐首行 */
    font-size: 14px;
    line-height: 20px;
    color: var(--hxx-text-2);
    text-align: right;
}
.hxx-form-control { flex: 1 1 auto; min-width: 0; }
.hxx-form-control .hxx-input,
.hxx-form-control .hxx-textarea,
.hxx-form-control .hxx-select { width: 100%; }
.hxx-form-error, .hxx-form-hint {
    margin: 6px 0 0;
    font-size: 12px;
    line-height: 1.5;
}
.hxx-form-error { color: var(--hxx-danger); }
.hxx-form-hint { color: var(--hxx-text-3); }
.hxx-form-item.is-required .hxx-form-label::before {
    content: "*";
    margin-right: 2px;
    color: var(--hxx-danger);
}
.hxx-form-item.hxx-form-item-vertical {
    flex-direction: column;
    gap: 6px;
}
.hxx-form-item.hxx-form-item-vertical .hxx-form-label {
    width: auto;
    padding-top: 0;
    text-align: left;
}

/* ---------- 自绘下拉 HXXSelect（js/hxx-ui.js 自动增强 select.hxx-select） ----------
   渐进增强：原生 select 移入 .hxx-select-wrap 隐藏（display:none），仍是表单取值/提交的
   事实来源；视觉与交互换成「触发器按钮 + fixed 浮层面板」。原生 select.hxx-select 样式
   （上方输入类区）仅作 JS 失效兜底与 multiple 多选使用。
   触发器规格与 .hxx-input 对齐（38px / -sm 32px、focus 主色边 + 3px 光圈、is-error 红边）；
   面板：surface 底 + 1px 边 + --hxx-shadow-md + 8px 圆角（契约：浮层菜单用 md 阴影、
   次级卡片角 8px），选项行 hover --hxx-hover、选中主色 soft 底 + 深主色字（契约药丸配色）；
   开场 0.15s 淡入 + 4px 位移微缩放，place-above（上方弹出）时 origin 与位移方向翻转。 */
.hxx-select-wrap {
    position: relative;
    display: inline-block;
    max-width: 100%;
}
.hxx-form-control .hxx-select-wrap { display: block; width: 100%; }
.hxx-select-wrap > select.hxx-select { display: none; } /* 原生控件保留占名占值，仅隐藏 */
.hxx-select-trigger {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    width: 100%;
    height: 38px;
    padding: 0 12px;
    border: 1px solid var(--hxx-border-strong);
    border-radius: var(--hxx-radius-sm);
    background-color: var(--hxx-surface);
    color: var(--hxx-text);
    font-family: inherit;
    font-size: 14px;
    line-height: 1.4;
    text-align: left;
    white-space: nowrap;
    cursor: pointer;
    outline: none;
    user-select: none;
    transition: border-color var(--hxx-t-fast), box-shadow var(--hxx-t-fast), background-color var(--hxx-t-fast);
}
.hxx-select-wrap.hxx-select-sm .hxx-select-trigger {
    height: 32px;
    font-size: 13px;
    padding: 0 10px;
}
.hxx-select-trigger:hover { border-color: var(--hxx-text-3); }
.hxx-select-wrap.is-open .hxx-select-trigger {
    border-color: var(--hxx-primary);
    box-shadow: 0 0 0 3px rgba(21, 138, 255, 0.1);
}
.hxx-select-trigger:disabled {
    background-color: var(--hxx-muted);
    color: var(--hxx-text-3);
    cursor: not-allowed;
}
.hxx-select-wrap.is-error .hxx-select-trigger { border-color: var(--hxx-danger); }
.hxx-select-wrap.is-error.is-open .hxx-select-trigger { box-shadow: 0 0 0 3px rgba(229, 72, 77, 0.1); }
.hxx-select-value {
    min-width: 0;
    flex: 0 1 auto;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.hxx-select-trigger.is-placeholder .hxx-select-value { color: var(--hxx-text-placeholder); }
.hxx-select-arrow {
    display: flex;
    flex: none;
    color: var(--hxx-text-3);
    transition: transform var(--hxx-t);
}
.hxx-select-arrow svg { width: 12px; height: 12px; display: block; }
.hxx-select-wrap.is-open .hxx-select-arrow { transform: rotate(180deg); }
/* 面板 fixed 挂 body：不受弹窗正文 overflow 裁切；z-index 高于弹窗（10002）与 toast（10003）。
   上下弹出方向与 max-height 由 JS 按视口空间现场计算 */
.hxx-select-panel {
    position: fixed;
    z-index: 10004;
    max-width: calc(100vw - 16px);
    max-height: 264px;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 4px;
    background: var(--hxx-surface);
    border: 1px solid var(--hxx-border);
    border-radius: var(--hxx-radius-sm);
    box-shadow: var(--hxx-shadow-md);
    opacity: 0;
    transform: translateY(-4px) scale(0.98);
    transform-origin: top center;
    pointer-events: none;
    transition: opacity var(--hxx-t-fast) ease, transform var(--hxx-t-fast) ease;
}
.hxx-select-panel.place-above {
    transform-origin: bottom center;
    transform: translateY(4px) scale(0.98);
}
.hxx-select-panel.is-open {
    opacity: 1;
    transform: none;
    pointer-events: auto;
}
.hxx-select-group {
    padding: 8px 10px 4px;
    font-size: 12px;
    color: var(--hxx-text-3);
    user-select: none;
}
.hxx-select-option {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 10px 10px;
    border-radius: var(--hxx-radius-xs);
    font-size: 14px;
    color: var(--hxx-text);
    cursor: pointer;
    outline: none;
    user-select: none;
}
.hxx-select-option-text {
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.hxx-select-option:hover,
.hxx-select-option:focus { background: var(--hxx-hover); }
.hxx-select-option.is-selected {
    background: var(--hxx-primary-soft);
    color: var(--hxx-primary-deep);
    font-weight: 600;
}
.hxx-select-option.is-selected:hover,
.hxx-select-option.is-selected:focus { background: var(--hxx-primary-soft); }
.hxx-select-option.is-disabled { opacity: 0.45; cursor: not-allowed; }
.hxx-select-option.is-disabled:hover,
.hxx-select-option.is-disabled:focus { background: transparent; }
.hxx-select-check { display: none; flex: none; color: var(--hxx-primary); }
.hxx-select-check svg { width: 14px; height: 14px; display: block; }
.hxx-select-option.is-selected .hxx-select-check { display: flex; }

/* ---------- 加载指示 ---------- */
@keyframes hxx-spin {
    to { transform: rotate(360deg); }
}
.hxx-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 40px 0;
    gap: 14px;
}
.hxx-spinner {
    width: 36px; height: 36px;
    border: 3px solid var(--hxx-border);
    border-top-color: var(--hxx-primary);
    border-radius: 50%;
    animation: hxx-spin 0.7s linear infinite;
}
.hxx-loading p {
    font-size: 14px;
    color: var(--hxx-text-3);
    margin: 0;
}

/* ---------- 弹窗 HXXDialog（js/hxx-ui.js 注入，调用方式见 README「HXXDialog」） ---------- */
/* 遮罩只做背景色插值、不动画 opacity：opacity 会连带子面板一起淡入，
   破坏「按钮变成弹窗」的形变（面板必须从第一帧起就完全不透明） */
.hxx-dialog-mask {
    position: fixed;
    inset: 0;
    z-index: 10002; /* 高于导航栏（10001） */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    --hxx-morph: calc(var(--hxx-t-slow) * 1.4); /* 形变动效总时长（≈0.42s）：大面积宽/高形变用比 --hxx-t-slow 更从容的节奏 */
    background: rgba(26, 26, 46, 0); /* 与 is-open 的同色透明态，保证颜色插值不偏色 */
    transition: background-color var(--hxx-t-slow);
}
.hxx-dialog-mask.is-open { background-color: rgba(26, 26, 46, 0.45); }
.hxx-dialog-mask.is-origin { transition: background-color var(--hxx-morph); } /* 形变时遮罩压暗节奏与窗口一致 */
/* 三段纵向 flex：标题与页脚固定，正文单独滚动。
   限高必须留够（视口 - 上下遮罩 20px - 余量），并覆盖各页遗留的 .dialog-scroll 等内层限高壳；
   dvh 跟随移动端地址栏收展，后写生效、前一行作为不支持 dvh 时的回退 */
.hxx-dialog {
    display: flex;
    flex-direction: column;
    width: 400px;
    max-width: 100%;
    max-height: calc(100vh - 64px);
    max-height: calc(100dvh - 64px);
    overflow: hidden;
    background: var(--hxx-surface);
    color: var(--hxx-text);
    font-family: inherit;
    border: 1px solid var(--hxx-border);
    border-radius: var(--hxx-radius-lg);
    box-shadow: var(--hxx-shadow-lg);
    padding: 20px;
    opacity: 0;
    transform: translateY(12px);
    /* 注意：此处勿加 height 过渡——内容变化导致的高度变化由 js/hxx-ui.js 的
       watchDialogHeight（ResizeObserver 钉 px 过渡）接管；CSS 直加 height 会与
       其「transition:none 钉住旧高度」的起点提交冲突（打断过渡、出现双向跳变） */
    transition: opacity var(--hxx-t-slow), transform var(--hxx-t-slow);
}
.hxx-dialog-mask.is-open .hxx-dialog {
    opacity: 1;
    transform: translateY(0);
}
.hxx-dialog-title {
    position: relative;
    flex: none;
    margin: 0 0 16px;
    padding-left: 10px;
    font-size: 17px;
    font-weight: 700;
    color: var(--hxx-text);
}
.hxx-dialog-title::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    width: 3px;
    height: 16px;
    margin-top: -8px;
    border-radius: 2px;
    background: var(--hxx-primary);
}
/* 正文是唯一滚动区：min-height:0 让 flex 子项允许收缩到内容高度以下，
   overscroll-behavior:contain 防止滚到底把整页一起带着滚 */
.hxx-dialog-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
}
.hxx-dialog-body > :last-child { margin-bottom: 0; }
/* 页脚：组件把模板尾部的操作行自动提升进这里，与标题一样固定不滚动 */
.hxx-dialog-footer {
    flex: none;
    display: flex;
    flex-direction: column;
}
.hxx-dialog-footer > :last-child { margin-bottom: 0; }
.hxx-dialog-message {
    margin: 0;
    font-size: 14px;
    line-height: 1.6;
    color: var(--hxx-text-2);
    white-space: pre-line;
    word-break: break-word;
}
.hxx-dialog-actions {
    display: flex;
    flex: none;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    margin: 20px 0 0;
}
.hxx-dialog-actions.is-single { justify-content: center; }
.hxx-dialog-hint {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    font-size: 12px;
    color: var(--hxx-text-3);
    margin: 10px 0 0;
}
.hxx-dialog-hint svg {
    width: 14px;
    height: 14px;
    color: var(--hxx-text-3);
    flex-shrink: 0;
}
/* origin 形变动效（is-origin 由 js/hxx-ui.js 识别到触发按钮时添加，总时长 --hxx-morph ≈0.42s）：
   面板创建即与按钮同宽/同高/同圆角/同背景色、不透明并刚好覆盖按钮（无任何淡入），
   形变期间触发按钮加 .hxx-origin-hidden 瞬时隐藏（保留占位），营造「按钮变成弹窗」的共享元素感；
   开启：前 10% 宽高/圆角完全不动、只位移与背景色，位移用弹性曲线飞过中心一点再弹回中央，
   宽/高其后以 90% 时长长大（小幅度弹性），圆角 10%~50% 到位；
   关闭为镜像反向：宽/高前 90% 收完（小幅度弹性），圆角 50%~90% 回到按钮形状，
   位移蓄力弹性飞回按钮原位，收缩到位瞬间卡片移除、按钮同帧恢复——
   卡片本体全程不淡出，靠「换脸」完成变回按钮的闭环。
   宽/高/圆角/背景色/位移过渡由 JS 内联控制（字面秒数 + 开/关不同缓动曲线）。 */
/* 内容元素（标题/正文/按钮）单独渐变，卡片本体不变：
   开启延迟 15%（宽刚开始长大）即随窗口展开淡入；关闭快速淡出（先清空窗口再缩回按钮，观感更干净） */
.hxx-dialog-mask.is-origin .hxx-dialog > * {
    opacity: 0;
    transition: opacity var(--hxx-t-fast) ease;
}
.hxx-dialog-mask.is-origin.is-open .hxx-dialog > * {
    opacity: 1;
    transition: opacity calc(var(--hxx-morph) * 0.7) calc(var(--hxx-morph) * 0.15) ease;
}
/* 瞬时隐藏触发按钮：必须 !important 压过 hw-button 的 transition:all !important，
   否则 visibility 会被过渡延迟 0.2s 才生效（按钮残留）；类选择器特异性高于 hw-button 标签选择器 */
.hxx-origin-hidden {
    visibility: hidden !important;
    transition: none !important;
}
/* 加载中弹窗：小面板、无标题无按钮、不可点遮罩关闭 */
.hxx-dialog-mask.hxx-dialog-loading .hxx-dialog {
    width: auto;
    padding: 28px 40px;
    border-radius: var(--hxx-radius);
}
.hxx-dialog-mask.hxx-dialog-loading .hxx-loading { padding: 0; gap: 12px; }
@media (max-width: 768px) {
    .hxx-dialog { border-radius: var(--hxx-radius); }
}

/* ---------- 轻提示 HXXToast（js/hxx-ui.js 注入，调用方式见 README「HXXToast」） ----------
   顶部居中纵向堆叠：深色胶囊（--hxx-text 同色系底）+ 白字 + 彩色状态图标；
   入场「下滑 + 微放大」淡入、出场镜像淡出；点击条目可提前关闭；
   loading 图标复用 hxx-spin 旋转。容器 pointer-events:none 不挡页面点击，
   由条目自身恢复接收（pointer-events:auto），与弹窗互不干扰、层级在弹窗之上 */
.hxx-toast {
    position: fixed;
    top: 24px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 10003; /* 高于弹窗（10002）：loading 弹窗期间也能弹 toast */
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    max-width: calc(100vw - 32px);
    pointer-events: none;
}
.hxx-toast-item {
    display: flex;
    align-items: center;
    gap: 8px;
    max-width: 100%;
    padding: 10px 16px;
    border-radius: var(--hxx-radius-full);
    background-color: rgba(26, 26, 46, 0.88); /* --hxx-text 同色系深底 */
    color: #fff;
    font-size: 14px;
    line-height: 1.4;
    font-weight: 500;
    box-shadow: var(--hxx-shadow-md);
    cursor: pointer;
    pointer-events: auto;
    opacity: 0;
    transform: translateY(-12px) scale(0.96);
    transition: opacity var(--hxx-t-slow) ease, transform var(--hxx-t-slow) ease;
}
.hxx-toast-item.is-open {
    opacity: 1;
    transform: translateY(0) scale(1);
}
.hxx-toast-icon {
    display: flex;
    flex-shrink: 0;
    color: #6cb6ff; /* info / loading 图标色（深底上的亮蓝） */
}
.hxx-toast-icon svg { width: 16px; height: 16px; display: block; }
.hxx-toast-text { word-break: break-word; }
.hxx-toast-item.is-success .hxx-toast-icon { color: #4ade80; }
.hxx-toast-item.is-error .hxx-toast-icon { color: #ff7a7d; }
.hxx-toast-item.is-warning .hxx-toast-icon { color: #ffb84d; }
.hxx-toast-item.is-loading .hxx-toast-icon svg { animation: hxx-spin 0.7s linear infinite; }
@media (max-width: 768px) {
    .hxx-toast { top: 16px; }
    .hxx-toast-item { font-size: 13px; }
}

/* ---------- 标签 .hxx-tag / 徽标 .hxx-badge（纯 CSS） ----------
   tag：软底彩字胶囊（12px/500/22px 高），color 属性语义与 .hxx-btn 一致（缺省 neutral）；
   badge：红底白字圆形计数徽标（.hxx-badge-dot 纯圆点、.hxx-badge-primary 主色底），
   自身为 inline-flex，绝对定位到角标由宿主自行包裹定位容器 */
.hxx-tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 22px;
    padding: 0 10px;
    border-radius: var(--hxx-radius-full);
    background-color: var(--hxx-neutral-soft);
    color: var(--hxx-neutral);
    font-size: 12px;
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
}
.hxx-tag[color="blue"] { background-color: var(--hxx-primary-soft); color: var(--hxx-primary-deep); }
.hxx-tag[color="success"] { background-color: var(--hxx-success-soft); color: var(--hxx-success); }
.hxx-tag[color="warning"] { background-color: var(--hxx-warning-soft); color: var(--hxx-warning); }
.hxx-tag[color="danger"] { background-color: var(--hxx-danger-soft); color: var(--hxx-danger); }

.hxx-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: var(--hxx-radius-full);
    background-color: var(--hxx-danger);
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
}
.hxx-badge.hxx-badge-primary { background-color: var(--hxx-primary); }
.hxx-badge.hxx-badge-dot {
    width: 8px;
    height: 8px;
    min-width: 0;
    padding: 0;
}

/* ---------- 卡片 .hxx-card（契约 §10.1） ----------
   白底 1px 边 12px 圆角、内边距 20px、极淡阴影；h2 17px/700 左侧 3×16px 主色竖条；
   .hxx-card-clickable hover 加深阴影与边框；hxx-divider 负 margin 贯穿卡片内宽 */
.hxx-card {
    background: var(--hxx-surface);
    border: 1px solid var(--hxx-border);
    border-radius: var(--hxx-radius);
    padding: 20px;
    box-shadow: var(--hxx-shadow-xs);
    transition: box-shadow var(--hxx-t), border-color var(--hxx-t);
}
.hxx-card h2 {
    position: relative;
    margin: 0 0 14px;
    padding-left: 10px;
    font-size: 17px;
    font-weight: 700;
    color: var(--hxx-text);
    line-height: 1.4;
}
.hxx-card h2::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    width: 3px;
    height: 16px;
    margin-top: -8px;
    border-radius: 2px;
    background: var(--hxx-primary);
}
.hxx-card-clickable { cursor: pointer; }
.hxx-card-clickable:hover {
    box-shadow: var(--hxx-shadow-md);
    border-color: var(--hxx-border-strong);
}
.hxx-divider { height: 1px; border: none; background: var(--hxx-border); margin: 16px -20px; }
.hxx-divider-sm { height: 1px; border: none; background: var(--hxx-border); margin: 16px 0; }

/* ---------- 提示横幅 .hxx-notice（契约 §10.15：软底 + 深色字 + 1px 同系边） ---------- */
.hxx-notice {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 16px;
    border-radius: var(--hxx-radius);
    font-size: 14px;
    line-height: 1.6;
}
.hxx-notice svg { flex: none; width: 16px; height: 16px; margin-top: 3px; }
.hxx-notice-info { background: var(--hxx-primary-soft); color: #0d6edb; border: 1px solid #c5defc; }
.hxx-notice-warning { background: var(--hxx-warning-soft); color: #b06f00; border: 1px solid #ffe2a8; }
.hxx-notice-danger { background: var(--hxx-danger-soft); color: #c0392b; border: 1px solid #fcc4c4; }

/* ---------- 标签页 .hxx-tabs（契约 §10.6 分段器；接线见 js/hxx-ui.js HXXTabs） ----------
   bar：--hxx-tile 底 12px 圆角 padding 4px；tab：8px 16px / 8px 圆角 / 14px/500；
   active：白底主文字 600 + 极淡阴影（浮起感）；面板切换 hxx-fade 0.25s 淡入 */
.hxx-tabs-bar {
    display: flex;
    gap: 4px;
    padding: 4px;
    background: var(--hxx-tile);
    border-radius: var(--hxx-radius);
    overflow-x: auto;
    margin-bottom: 14px;
}
.hxx-tab {
    padding: 8px 16px;
    border: none;
    border-radius: var(--hxx-radius-sm);
    background: transparent;
    color: var(--hxx-text-2);
    font-family: inherit;
    font-size: 14px;
    font-weight: 500;
    line-height: 1.4;
    white-space: nowrap;
    cursor: pointer;
    transition: color var(--hxx-t-fast), background-color var(--hxx-t-fast), box-shadow var(--hxx-t-fast);
}
.hxx-tab:hover { color: var(--hxx-text); }
.hxx-tab.is-active {
    background: var(--hxx-surface);
    color: var(--hxx-text);
    font-weight: 600;
    box-shadow: var(--hxx-shadow-xs);
}
.hxx-tab-pane { display: none; }
.hxx-tab-pane.is-active { display: block; animation: hxx-fade 0.25s ease; }

/* ---------- 步骤条 .hxx-steps ----------
   24px 圆形序号；done 主色实心 + 连接线主色；active 主色描边 + 3px 软光圈 + 循环波纹 */
.hxx-steps { display: flex; align-items: center; }
.hxx-step { display: flex; align-items: center; gap: 8px; min-width: 0; flex: 1; }
.hxx-step:last-child { flex: none; }
.hxx-step:last-child::after { display: none; }
.hxx-step::after { /* 连接线：占据剩余宽度，随步骤完成转主色 */
    content: "";
    flex: 1;
    height: 1px;
    background: var(--hxx-border);
    margin: 0 8px;
}
.hxx-step-num {
    position: relative;
    flex: none;
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--hxx-border-strong);
    border-radius: 50%;
    background: var(--hxx-surface);
    color: var(--hxx-text-3);
    font-size: 12px;
    font-weight: 600;
    transition: all var(--hxx-t-fast);
}
.hxx-step-label {
    font-size: 13px;
    color: var(--hxx-text-3);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.hxx-step.is-done .hxx-step-num { background: var(--hxx-primary); border-color: var(--hxx-primary); color: #fff; }
.hxx-step.is-done::after { background: var(--hxx-primary); }
.hxx-step.is-done .hxx-step-label { color: var(--hxx-text-2); }
.hxx-step.is-active .hxx-step-num {
    border-color: var(--hxx-primary);
    color: var(--hxx-primary);
    box-shadow: 0 0 0 3px rgba(21, 138, 255, 0.12);
}
.hxx-step.is-active .hxx-step-num::after { /* 当前步骤循环波纹：自序号圆环向外扩散消散 */
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    border: 2px solid var(--hxx-primary);
    pointer-events: none;
    animation: hxx-ripple-out 1.8s ease-out infinite;
}
.hxx-step.is-active .hxx-step-label { color: var(--hxx-text); font-weight: 600; }

/* ---------- 进度条 .hxx-progress（契约 §10.11） ----------
   6px 高（-lg 8px / muted 底）；柱体主色、width 过渡 0.6s 标准曲线；
   is-gradient 渐变柱体，前端带主色光点 + 循环圆形波纹（随柱体增长移动——
   波纹需溢出轨道，track 默认不裁切，仅 is-indeterminate 滑动柱需裁切防跑出轨道）；
   is-indeterminate 循环滑动（柱体宽固定 36%，translateX 扫全程） */
.hxx-progress { height: 6px; background: var(--hxx-border); border-radius: 3px; overflow: visible; }
.hxx-progress.hxx-progress-lg { height: 8px; background: var(--hxx-muted); }
.hxx-progress-bar {
    position: relative;
    height: 100%;
    background: var(--hxx-primary);
    border-radius: 3px;
    transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}
.hxx-progress.is-gradient .hxx-progress-bar {
    background: linear-gradient(90deg, var(--hxx-primary), var(--hxx-primary-light));
}
/* 渐变柱体前端：::after 主色光点、::before 循环波纹圆环（圆心对齐柱体前端，
   transform+opacity 合成器动画，波纹随 width 过渡同步移动） */
.hxx-progress.is-gradient .hxx-progress-bar::before,
.hxx-progress.is-gradient .hxx-progress-bar::after {
    content: "";
    position: absolute;
    right: -3px;
    top: 50%;
    width: 6px;
    height: 6px;
    margin-top: -3px;
    border-radius: 50%;
}
.hxx-progress.is-gradient .hxx-progress-bar::after { background: var(--hxx-primary-light); }
.hxx-progress.is-gradient .hxx-progress-bar::before {
    border: 2px solid var(--hxx-primary-light);
    --hxx-ripple-to: 3; /* 光点小，波纹扩散倍率放大到 3（6px → 18px） */
    animation: hxx-ripple-out 1.6s ease-out infinite;
}
.hxx-progress.is-indeterminate { overflow: hidden; } /* 滑动柱会越出轨道两端，需要裁切 */
.hxx-progress.is-indeterminate .hxx-progress-bar {
    width: 36% !important;
    animation: hxx-progress-slide 1.2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}

/* ---------- 进度环 .hxx-progress-circle（契约 §10.11 环形变体） ----------
   conic-gradient 画环（径向 mask 挖空中心）+ 中心百分比文字（宿主放 <span>60%</span>）；
   --hxx-circle-val 为 0~100 数值（@property 注册后数值变化可过渡动画，旧浏览器无动画但不影响显示）；
   ::after 为循环波纹——圆环从进度环外缘向外扩散消散；
   尺寸：默认 64px（-sm 48 / -lg 88），环厚 --hxx-circle-thickness 默认 6px（-lg 8px）；
   is-gradient 渐变环（primary-light → primary 扫到进度处） */
@property --hxx-circle-val {
    syntax: "<number>";
    inherits: true;
    initial-value: 0;
}
.hxx-progress-circle {
    --hxx-circle-val: 0;
    --hxx-circle-thickness: 6px;
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 64px;
    height: 64px;
    font-size: 13px;
    font-weight: 600;
    color: var(--hxx-text-2);
    font-variant-numeric: tabular-nums;
    transition: --hxx-circle-val 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}
.hxx-progress-circle::before { /* 环体：conic 进度 + 径向 mask 挖空中心成环 */
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: conic-gradient(var(--hxx-primary) calc(var(--hxx-circle-val) * 1%), var(--hxx-border) 0);
    -webkit-mask: radial-gradient(closest-side, transparent calc(100% - var(--hxx-circle-thickness)), #000 calc(100% - var(--hxx-circle-thickness) + 1px));
    mask: radial-gradient(closest-side, transparent calc(100% - var(--hxx-circle-thickness)), #000 calc(100% - var(--hxx-circle-thickness) + 1px));
}
.hxx-progress-circle.is-gradient::before {
    background: conic-gradient(var(--hxx-primary-light), var(--hxx-primary) calc(var(--hxx-circle-val) * 1%), var(--hxx-border) 0);
}
.hxx-progress-circle::after { /* 循环波纹：自主环外缘向外扩散的圆环 */
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 2px solid var(--hxx-primary);
    pointer-events: none;
    --hxx-ripple-to: 1.45;
    animation: hxx-ripple-out 1.8s ease-out infinite;
}
.hxx-progress-circle.hxx-progress-circle-sm { width: 48px; height: 48px; font-size: 12px; }
.hxx-progress-circle.hxx-progress-circle-lg { width: 88px; height: 88px; font-size: 15px; --hxx-circle-thickness: 8px; }

/* ---------- 分页 .hxx-pagination（契约 §10.12：居中 / gap 12 / tabular-nums） ----------
   激活页带循环波纹（胶囊形圆环向外扩散，transform+opacity 合成器动画） */
.hxx-pagination { display: flex; align-items: center; justify-content: center; gap: 12px; margin-top: 16px; }
/* 注意：.hxx-page 与业务页面的「页面容器」同名（user.css 的 .hxx-page = 内容区包裹层），
   因此分页按钮样式必须限定在 .hxx-pagination 内，否则会把整页容器变成 32px 高的胶囊按钮，
   页面内容全部横向挤在一起。 */
.hxx-pagination .hxx-page {
    position: relative;
    min-width: 32px;
    height: 32px;
    padding: 0 8px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--hxx-border-strong);
    border-radius: var(--hxx-radius-full);
    background: var(--hxx-surface);
    color: var(--hxx-text-2);
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: all var(--hxx-t-fast);
}
.hxx-pagination .hxx-page:hover { border-color: var(--hxx-text-3); background: var(--hxx-muted); }
.hxx-pagination .hxx-page.is-active { background: var(--hxx-primary); border-color: var(--hxx-primary); color: #fff; }
.hxx-pagination .hxx-page.is-active::after { /* 激活页循环波纹：自主色胶囊边缘向外扩散消散 */
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    border: 2px solid var(--hxx-primary);
    pointer-events: none;
    animation: hxx-ripple-out 1.8s ease-out infinite;
}
.hxx-pagination .hxx-page[disabled] { opacity: 0.45; pointer-events: none; }
.hxx-page-info { font-size: 14px; color: var(--hxx-text-3); font-variant-numeric: tabular-nums; }

/* ---------- 空状态 .hxx-empty / 骨架屏 .hxx-skeleton（契约 §10.13 加载三态） ----------
   empty：居中弱色 + 48px 半透明图标；skeleton：muted 底 + 1.4s 高光扫过 */
.hxx-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 40px 20px;
    color: var(--hxx-text-3);
    font-size: 14px;
    text-align: center;
}
.hxx-empty svg, .hxx-empty img { width: 48px; height: 48px; opacity: 0.4; }
.hxx-skeleton {
    position: relative;
    overflow: hidden;
    background: var(--hxx-muted);
    border-radius: var(--hxx-radius-xs);
}
.hxx-skeleton::after {
    content: "";
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.6), transparent);
    animation: hxx-skeleton-slide 1.4s ease infinite;
}
.hxx-skeleton-text { height: 14px; border-radius: 4px; }
.hxx-skeleton-title { height: 20px; width: 40%; border-radius: 4px; }
.hxx-skeleton-avatar { width: 40px; height: 40px; border-radius: 50%; }
.hxx-skeleton-btn { width: 84px; height: 32px; border-radius: var(--hxx-radius-full); }

/* ---------- 头像 .hxx-avatar（契约 §10.17：圆形、文字回退、软底色系） ---------- */
.hxx-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: var(--hxx-primary-soft);
    color: var(--hxx-primary-deep);
    font-size: 15px;
    font-weight: 600;
    overflow: hidden;
    user-select: none;
}
.hxx-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hxx-avatar.hxx-avatar-sm { width: 32px; height: 32px; font-size: 13px; }
.hxx-avatar.hxx-avatar-lg { width: 56px; height: 56px; font-size: 19px; }
.hxx-avatar[color="success"] { background: var(--hxx-success-soft); color: var(--hxx-success); }
.hxx-avatar[color="warning"] { background: var(--hxx-warning-soft); color: var(--hxx-warning); }
.hxx-avatar[color="danger"] { background: var(--hxx-danger-soft); color: var(--hxx-danger); }
.hxx-avatar[color="neutral"] { background: var(--hxx-neutral-soft); color: var(--hxx-text-2); }

/* ---------- 气泡提示 [data-hxx-tip]（纯 CSS，hover / 键盘 focus 显示） ----------
   属性选择器按需启用、零类名冲突；缺省上方，data-hxx-tip-pos="bottom" 下方；
   深色胶囊（与 toast 同色系）、12px 白字、超长省略；z-index 高于弹窗/面板，弹窗内可用 */
[data-hxx-tip] { position: relative; }
[data-hxx-tip]::after {
    content: attr(data-hxx-tip);
    position: absolute;
    left: 50%;
    bottom: calc(100% + 8px);
    transform: translateX(-50%) translateY(2px);
    z-index: 10005;
    padding: 5px 10px;
    border-radius: var(--hxx-radius-xs);
    background: rgba(26, 26, 46, 0.92);
    color: #fff;
    font-size: 12px;
    line-height: 1.5;
    white-space: nowrap;
    max-width: 240px;
    overflow: hidden;
    text-overflow: ellipsis;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--hxx-t-fast) ease, transform var(--hxx-t-fast) ease;
}
[data-hxx-tip]:hover::after,
[data-hxx-tip]:focus-visible::after { opacity: 1; transform: translateX(-50%) translateY(0); }
[data-hxx-tip-pos="bottom"]::after {
    bottom: auto;
    top: calc(100% + 8px);
    transform: translateX(-50%) translateY(-2px);
}
[data-hxx-tip-pos="bottom"]:hover::after,
[data-hxx-tip-pos="bottom"]:focus-visible::after { transform: translateX(-50%) translateY(0); }

/* ---------- 抽屉 HXXDrawer（js/hxx-ui.js 注入，右侧 / 底部滑出） ----------
   遮罩同弹窗只做背景色插值；面板滑入 0.3s 减速曲线；
   右侧 400px 默认宽 / 底部 70vh 圆角上沿（移动端操作面板）；
   标题同弹窗竖条样式；正文唯一滚动区（flex 三段语义与弹窗一致） */
.hxx-drawer-mask {
    position: fixed;
    inset: 0;
    z-index: 10002;
    display: flex;
    background-color: rgba(26, 26, 46, 0);
    transition: background-color var(--hxx-t-slow);
}
.hxx-drawer-mask.is-open { background-color: rgba(26, 26, 46, 0.45); }
.hxx-drawer-mask.is-right { justify-content: flex-end; }
.hxx-drawer-mask.is-bottom { align-items: flex-end; }
.hxx-drawer {
    position: relative;
    display: flex;
    flex-direction: column;
    background: var(--hxx-surface);
    color: var(--hxx-text);
    font-family: inherit;
    box-shadow: var(--hxx-shadow-lg);
    overflow: hidden;
    transition: transform var(--hxx-t-slow) cubic-bezier(0.22, 1, 0.36, 1);
}
.hxx-drawer.is-right { width: 400px; max-width: 100%; height: 100%; transform: translateX(100%); }
.hxx-drawer.is-bottom {
    width: 100%;
    height: 70vh;
    max-height: calc(100dvh - 24px);
    transform: translateY(100%);
    border-radius: var(--hxx-radius-lg) var(--hxx-radius-lg) 0 0;
}
.hxx-drawer-mask.is-open .hxx-drawer { transform: none; }
.hxx-drawer-title {
    position: relative;
    flex: none;
    margin: 16px 52px 12px 20px;
    padding-left: 10px;
    font-size: 17px;
    font-weight: 700;
    color: var(--hxx-text);
}
.hxx-drawer-title::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    width: 3px;
    height: 16px;
    margin-top: -8px;
    border-radius: 2px;
    background: var(--hxx-primary);
}
.hxx-drawer-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 20px;
}
.hxx-drawer-close {
    position: absolute;
    top: 14px;
    right: 14px;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: var(--hxx-text-3);
    cursor: pointer;
    transition: background-color var(--hxx-t-fast), color var(--hxx-t-fast);
}
.hxx-drawer-close:hover { background: var(--hxx-muted); color: var(--hxx-text); }
.hxx-drawer-close svg { width: 16px; height: 16px; }
/* 桌面端底部抽屉：不再全宽贴底，收敛为居中悬浮卡片（宽 ≤480、四角圆角、离底 5vh），
   兼得「底部唤起」的交互心智与桌面排版；移动端（≤768px）维持全宽操作面板不动 */
@media (min-width: 769px) {
    .hxx-drawer-mask.is-bottom { justify-content: center; padding: 0 24px 5vh; }
    .hxx-drawer.is-bottom {
        width: min(480px, calc(100vw - 48px));
        height: auto;              /* 随内容自适应（opts.height 内联值仍优先生效） */
        max-height: min(70vh, 600px);
        border-radius: var(--hxx-radius-lg);
    }
}

/* ---------- 日期选择器 HXXDatePicker（input.hxx-date / .hxx-datetime / .hxx-time 渐进增强，面板 js 注入） ----------
   面板 fixed 挂 body（同 HXXSelect：不受弹窗 overflow 裁切，代价是滚动/resize 收起）；
   头部：‹ 标题 › + 今天（或此刻）/清空/确定 迷你钮；星期行周一为首；42 格固定 6 行（高度稳定不跳）；
   非本月弱化、今天主色加粗、选中主色 soft 底（选中+今天 = 主色实心白字）；
   时间区（datetime / time 型）：时 / 分两列滚动列表，选中项居中、主色 soft 底 */
.hxx-date-panel {
    position: fixed;
    z-index: 10004;
    width: 264px;
    padding: 12px;
    background: var(--hxx-surface);
    border: 1px solid var(--hxx-border);
    border-radius: var(--hxx-radius-sm);
    box-shadow: var(--hxx-shadow-md);
    opacity: 0;
    transform: translateY(-4px) scale(0.98);
    transform-origin: top center;
    pointer-events: none;
    transition: opacity var(--hxx-t-fast) ease, transform var(--hxx-t-fast) ease;
}
.hxx-date-panel.place-above { transform-origin: bottom center; transform: translateY(4px) scale(0.98); }
.hxx-date-panel.is-open { opacity: 1; transform: none; pointer-events: auto; }
.hxx-date-head { display: flex; align-items: center; gap: 4px; margin-bottom: 10px; }
.hxx-date-title { flex: 1; text-align: center; font-size: 14px; font-weight: 600; color: var(--hxx-text); }
.hxx-date-nav {
    flex: none;
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--hxx-border-strong);
    border-radius: var(--hxx-radius-xs);
    background: var(--hxx-surface);
    color: var(--hxx-text-2);
    cursor: pointer;
    transition: background-color var(--hxx-t-fast), border-color var(--hxx-t-fast);
}
.hxx-date-nav:hover { background: var(--hxx-muted); border-color: var(--hxx-text-3); }
.hxx-date-nav svg { width: 14px; height: 14px; }
.hxx-date-mini {
    flex: none;
    padding: 2px 8px;
    border: none;
    border-radius: var(--hxx-radius-xs);
    background: transparent;
    color: var(--hxx-text-3);
    font-family: inherit;
    font-size: 12px;
    cursor: pointer;
    transition: background-color var(--hxx-t-fast), color var(--hxx-t-fast);
}
.hxx-date-mini:hover { background: var(--hxx-primary-soft); color: var(--hxx-primary-deep); }
.hxx-date-mini.is-ok { color: var(--hxx-primary); font-weight: 600; }
.hxx-date-week {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    margin-bottom: 2px;
    font-size: 12px;
    color: var(--hxx-text-3);
    text-align: center;
}
.hxx-date-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.hxx-date-day {
    height: 32px;
    border: none;
    border-radius: var(--hxx-radius-xs);
    background: transparent;
    color: var(--hxx-text);
    font-family: inherit;
    font-size: 13px;
    cursor: pointer;
    transition: background-color var(--hxx-t-fast), color var(--hxx-t-fast);
}
.hxx-date-day:hover, .hxx-date-day:focus { background: var(--hxx-hover); outline: none; }
.hxx-date-day.is-out { color: var(--hxx-text-placeholder); }
.hxx-date-day.is-today { color: var(--hxx-primary); font-weight: 600; }
.hxx-date-day.is-selected { background: var(--hxx-primary-soft); color: var(--hxx-primary-deep); font-weight: 600; }
.hxx-date-day.is-selected.is-today { background: var(--hxx-primary); color: #fff; }

/* 时间区（hxx-datetime / hxx-time 型面板）：时 / 分两列滚动列表 + 居中冒号分隔；
   列 position:relative 供 js 用 offsetTop 把选中项滚到列中央；
   仅时间型面板（.is-time）收窄为 240px 且时间区不带上分割线 */
.hxx-date-time {
    display: flex;
    gap: 8px;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--hxx-border);
}
.hxx-date-panel.is-time { width: 240px; }
.hxx-date-panel.is-time .hxx-date-time { margin-top: 2px; padding-top: 0; border-top: none; }
.hxx-date-time-col {
    position: relative;
    flex: 1;
    min-width: 0;
    max-height: 168px;
    overflow-y: auto;
    overscroll-behavior: contain;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 2px;
}
.hxx-date-time-sep {
    flex: none;
    align-self: center;
    color: var(--hxx-text-3);
    font-weight: 600;
}
.hxx-date-time-item {
    flex: none;
    height: 28px;
    border: none;
    border-radius: var(--hxx-radius-xs);
    background: transparent;
    color: var(--hxx-text);
    font-family: inherit;
    font-size: 13px;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    transition: background-color var(--hxx-t-fast), color var(--hxx-t-fast);
}
.hxx-date-time-item:hover, .hxx-date-time-item:focus { background: var(--hxx-hover); outline: none; }
.hxx-date-time-item.is-selected { background: var(--hxx-primary-soft); color: var(--hxx-primary-deep); font-weight: 600; }

/* ---------- 全局水印 HXXWatermark（js/hxx-ui.js 注入） ----------
   类名仅作标识；视觉全部走 JS 生成的内联样式（canvas 平铺图 + !important 防篡改） */

/* ---------- 通知卡 HXXNotification（js/hxx-ui.js 注入，右上角堆叠） ----------
   与 toast 分工：toast 顶部居中深色胶囊自动消失；notify 右上角白卡常驻（duration:0）
   或延时消失，悬停暂停计时，可带操作按钮（复用 .hxx-btn-sm）。
   容器 pointer-events:none 不挡页面点击，条目自身恢复接收；层级与 toast 相邻
   （10003），一个居中一个靠右互不遮盖；入场「右滑淡入」、出场镜像淡出 */
.hxx-notify {
    position: fixed;
    top: 24px;
    right: 24px;
    z-index: 10003;
    display: flex;
    flex-direction: column;
    gap: 10px;
    width: 320px;
    max-width: calc(100vw - 32px);
    pointer-events: none;
}
.hxx-notify-item {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 14px 34px 14px 14px; /* 右侧给关闭按钮留位 */
    border-radius: var(--hxx-radius);
    background: var(--hxx-surface);
    border: 1px solid var(--hxx-border);
    box-shadow: var(--hxx-shadow-md);
    pointer-events: auto;
    opacity: 0;
    transform: translateX(24px);
    transition: opacity var(--hxx-t-slow) ease, transform var(--hxx-t-slow) ease;
}
.hxx-notify-item.is-open { opacity: 1; transform: none; }
.hxx-notify-icon {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: var(--hxx-radius-full);
    background: var(--hxx-primary-soft);
    color: var(--hxx-primary);
}
.hxx-notify-icon svg { width: 16px; height: 16px; display: block; }
.hxx-notify-item.is-success .hxx-notify-icon { background: var(--hxx-success-soft); color: var(--hxx-success); }
.hxx-notify-item.is-warning .hxx-notify-icon { background: var(--hxx-warning-soft); color: var(--hxx-warning); }
.hxx-notify-item.is-error .hxx-notify-icon { background: var(--hxx-danger-soft); color: var(--hxx-danger); }
.hxx-notify-main { flex: 1; min-width: 0; }
.hxx-notify-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--hxx-text);
    line-height: 1.4;
    word-break: break-word;
}
.hxx-notify-msg {
    margin-top: 2px;
    font-size: 13px;
    color: var(--hxx-text-2);
    line-height: 1.5;
    word-break: break-word;
}
.hxx-notify-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.hxx-notify-close {
    position: absolute;
    top: 10px;
    right: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    padding: 0;
    border: 0;
    border-radius: var(--hxx-radius-xs);
    background: none;
    color: var(--hxx-text-3);
    cursor: pointer;
    transition: color var(--hxx-t-fast), background-color var(--hxx-t-fast);
}
.hxx-notify-close:hover { color: var(--hxx-text); background: var(--hxx-muted); }
.hxx-notify-close svg { width: 12px; height: 12px; display: block; }
@media (max-width: 768px) {
    .hxx-notify { top: 16px; right: 16px; }
}

/* ---------- 富内容气泡 HXXPopover（js/hxx-ui.js 注入，hover / click 触发） ----------
   [data-hxx-tip] 纯文字版的富内容版：白卡 + 阴影 + 箭头，fixed 挂 body（10004，
   与 HXXSelect / HXXDatePicker 同层）；方向类 is-top/bottom/left/right 由 JS 按视口
   空间自动翻转；箭头沿面板边滑动对准触发元素中心（--hxx-arrow / --hxx-arrow-y，
   由 JS 钳制在面板边内）；缩放入场按方向从箭头侧长出（transform-origin 随方向类） */
.hxx-popover {
    position: fixed;
    z-index: 10004;
    max-width: min(300px, calc(100vw - 16px));
    border-radius: var(--hxx-radius-sm);
    background: var(--hxx-surface);
    color: var(--hxx-text);
    box-shadow: var(--hxx-shadow-lg);
    opacity: 0;
    transform: scale(0.96);
    pointer-events: none;
    transition: opacity var(--hxx-t-fast) ease, transform var(--hxx-t-fast) ease;
}
.hxx-popover.is-open { opacity: 1; transform: scale(1); pointer-events: auto; }
.hxx-popover.is-top { transform-origin: bottom center; }
.hxx-popover.is-bottom { transform-origin: top center; }
.hxx-popover.is-left { transform-origin: center right; }
.hxx-popover.is-right { transform-origin: center left; }
.hxx-popover::before { /* 箭头：8px 方块转 45°，一半探出面板边 */
    content: "";
    position: absolute;
    width: 8px;
    height: 8px;
    border-radius: 2px;
    background: var(--hxx-surface);
    transform: rotate(45deg);
}
.hxx-popover.is-top::before { bottom: -4px; left: var(--hxx-arrow, 50%); margin-left: -4px; }
.hxx-popover.is-bottom::before { top: -4px; left: var(--hxx-arrow, 50%); margin-left: -4px; }
.hxx-popover.is-left::before { right: -4px; top: var(--hxx-arrow-y, 50%); margin-top: -4px; }
.hxx-popover.is-right::before { left: -4px; top: var(--hxx-arrow-y, 50%); margin-top: -4px; }
.hxx-popover-body {
    max-height: 60vh;
    overflow-y: auto;
    padding: 10px 12px;
    font-size: 13px;
    line-height: 1.6;
    color: var(--hxx-text);
    word-break: break-word;
}

/* ---------- 折叠面板 .hxx-collapse（js/hxx-ui.js 自动接线） ----------
   结构：<div class="hxx-collapse">（data-accordion 进手风琴模式）> .hxx-collapse-item >
   .hxx-collapse-header（原生 button，箭头 CSS ::after 自绘，aria-expanded 由 JS 同步）
   + .hxx-collapse-content（max-height 0 钳制，展开值由 JS 钉 scrollHeight）。
   卡片式分组线：容器 1px 边框圆角 + item 间分割线；content 的 padding 随 max-height:0
   （border-box）一并收起，动画全程无跳动 */
.hxx-collapse {
    border: 1px solid var(--hxx-border);
    border-radius: var(--hxx-radius);
    background: var(--hxx-surface);
    overflow: hidden;
}
.hxx-collapse-item + .hxx-collapse-item { border-top: 1px solid var(--hxx-border); }
.hxx-collapse-header {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 12px 14px;
    border: 0;
    background: none;
    font: inherit;
    font-size: 14px;
    font-weight: 600;
    color: var(--hxx-text);
    text-align: left;
    cursor: pointer;
    transition: background-color var(--hxx-t-fast);
}
.hxx-collapse-header:hover { background: var(--hxx-hover); }
.hxx-collapse-header:focus-visible {
    outline: 2px solid var(--hxx-primary);
    outline-offset: -2px;
}
.hxx-collapse-header::after { /* 折叠箭头：收起指向右、展开转向下 */
    content: "";
    flex: none;
    margin-left: auto;
    width: 7px;
    height: 7px;
    border-right: 2px solid var(--hxx-text-3);
    border-bottom: 2px solid var(--hxx-text-3);
    transform: rotate(-45deg);
    transition: transform var(--hxx-t) ease;
}
.hxx-collapse-item.is-active .hxx-collapse-header::after { transform: rotate(45deg); }
.hxx-collapse-content {
    max-height: 0;
    padding: 0 14px 14px;
    overflow: hidden;
    font-size: 13px;
    line-height: 1.7;
    color: var(--hxx-text-2);
    transition: max-height var(--hxx-t-slow) ease;
}
.hxx-collapse-content > :first-child { margin-top: 0; }
.hxx-collapse-content > :last-child { margin-bottom: 0; }

/* ---------- 回到顶部 .hxx-backtop（js/hxx-ui.js 自动接管） ----------
   滚动超阈值（默认 300px）由 JS 挂 is-visible 淡入；fixed 右下角圆形按钮，
   声明式 <button class="hxx-backtop"> 与 HXXBackTop.init() 注入共用同一样式；
   点击平滑回顶；默认箭头 SVG 由 JS 补齐 */
.hxx-backtop {
    position: fixed;
    right: 24px;
    bottom: 32px;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: 1px solid var(--hxx-border);
    border-radius: var(--hxx-radius-full);
    background: var(--hxx-surface);
    color: var(--hxx-text-2);
    box-shadow: var(--hxx-shadow-md);
    font: inherit;
    cursor: pointer;
    opacity: 0;
    transform: translateY(8px);
    pointer-events: none;
    transition: opacity var(--hxx-t) ease, transform var(--hxx-t) ease,
        background-color var(--hxx-t-fast), color var(--hxx-t-fast);
}
.hxx-backtop.is-visible { opacity: 1; transform: none; pointer-events: auto; }
.hxx-backtop:hover { background: var(--hxx-primary-soft); color: var(--hxx-primary-deep); }
.hxx-backtop:focus-visible { outline: 2px solid var(--hxx-primary); outline-offset: 2px; }
.hxx-backtop svg { width: 18px; height: 18px; display: block; }
@media (max-width: 768px) {
    .hxx-backtop { right: 16px; bottom: 16px; }
}

/* ---------- 滑动输入条 .hxx-slider（原生 input[type=range] 自绘，js/hxx-ui.js 增强） ----------
   单滑块：input.hxx-slider——轨道 6px 灰、填充主色（WebKit 走 --hxx-fill 渐变、Firefox 原生
   ::-moz-range-progress）、16px 白底主色描边圆滑块（active 放大、focus-visible 光圈）；
   命中区 22px 大于视觉轨道（好点）。数值气泡 .hxx-slider-bubble 深色胶囊（同 data-hxx-tip
   色系），--hxx-p 由 JS 钉在滑块中心，悬停 / 聚焦 / 拖动（is-drag）出现。
   双滑块：.hxx-slider-dual > input.hxx-slider-in × 2——轨道 / 区间填充由容器伪元素渲染
   （--hxx-a / --hxx-b 为两端百分比），input 透明绝对叠放、pointer-events 只开在滑块上；
   滑块钉位计算按「滑块中心 16px」口径，与气泡 left 公式一致 */
.hxx-slider-single {
    position: relative;
    display: inline-block;
    vertical-align: middle;
}
.hxx-slider, .hxx-slider-in {
    -webkit-appearance: none;
    appearance: none;
    display: block;
    margin: 0;
    height: 22px; /* 命中区大于视觉轨道（6px） */
    background: none;
    font: inherit;
    cursor: pointer;
}
.hxx-slider:focus-visible, .hxx-slider-in:focus-visible { outline: none; }
/* WebKit */
.hxx-slider::-webkit-slider-runnable-track,
.hxx-slider-in::-webkit-slider-runnable-track {
    height: 6px;
    border-radius: var(--hxx-radius-full);
    background: var(--hxx-muted);
}
.hxx-slider::-webkit-slider-runnable-track {
    background: linear-gradient(to right,
        var(--hxx-primary) 0, var(--hxx-primary) var(--hxx-fill, 0%),
        var(--hxx-muted) var(--hxx-fill, 0%), var(--hxx-muted) 100%);
}
.hxx-slider::-webkit-slider-thumb,
.hxx-slider-in::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 16px;
    height: 16px;
    margin-top: -5px; /* (轨道 6 - 滑块 16) / 2 */
    border-radius: var(--hxx-radius-full);
    background: var(--hxx-surface);
    border: 2px solid var(--hxx-primary);
    box-shadow: var(--hxx-shadow);
    transition: transform var(--hxx-t-fast) ease, border-color var(--hxx-t-fast) ease;
}
.hxx-slider:active::-webkit-slider-thumb,
.hxx-slider-in:active::-webkit-slider-thumb { transform: scale(1.15); }
.hxx-slider:focus-visible::-webkit-slider-thumb,
.hxx-slider-in:focus-visible::-webkit-slider-thumb {
    border-color: var(--hxx-primary-deep);
    box-shadow: 0 0 0 3px var(--hxx-primary-soft);
}
/* Firefox */
.hxx-slider::-moz-range-track,
.hxx-slider-in::-moz-range-track {
    height: 6px;
    border-radius: var(--hxx-radius-full);
    background: var(--hxx-muted);
}
.hxx-slider::-moz-range-progress {
    height: 6px;
    border-radius: var(--hxx-radius-full);
    background: var(--hxx-primary);
}
.hxx-slider::-moz-range-thumb,
.hxx-slider-in::-moz-range-thumb {
    width: 16px;
    height: 16px;
    border-radius: var(--hxx-radius-full);
    background: var(--hxx-surface);
    border: 2px solid var(--hxx-primary);
    box-shadow: var(--hxx-shadow);
    transition: transform var(--hxx-t-fast) ease;
}
.hxx-slider:active::-moz-range-thumb,
.hxx-slider-in:active::-moz-range-thumb { transform: scale(1.15); }
.hxx-slider:disabled, .hxx-slider-in:disabled { cursor: not-allowed; opacity: 0.55; }
/* 数值气泡：left 按滑块中心钉位（(100% - 16px) * p + 8px），深色胶囊同 data-hxx-tip 色系 */
.hxx-slider-bubble {
    position: absolute;
    bottom: calc(100% + 8px);
    left: calc((100% - 16px) * var(--hxx-p, 0) + 8px);
    transform: translateX(-50%) translateY(2px);
    z-index: 10;
    padding: 4px 8px;
    border-radius: var(--hxx-radius-xs);
    background: rgba(26, 26, 46, 0.92);
    color: #fff;
    font-size: 12px;
    line-height: 1.4;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity var(--hxx-t-fast) ease, transform var(--hxx-t-fast) ease;
}
.hxx-slider-single:hover .hxx-slider-bubble,
.hxx-slider-single:focus-within .hxx-slider-bubble,
.hxx-slider-single.is-drag .hxx-slider-bubble,
.hxx-slider-dual:hover .hxx-slider-bubble,
.hxx-slider-dual:focus-within .hxx-slider-bubble,
.hxx-slider-dual.is-drag .hxx-slider-bubble {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}
/* 双滑块：容器渲染轨道（::before 灰底）与区间填充（::after 主色，两端 --hxx-a/--hxx-b） */
.hxx-slider-dual { position: relative; height: 22px; }
.hxx-slider-dual::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    margin-top: -3px;
    height: 6px;
    border-radius: var(--hxx-radius-full);
    background: var(--hxx-muted);
}
.hxx-slider-dual::after {
    content: "";
    position: absolute;
    top: 50%;
    margin-top: -3px;
    height: 6px;
    border-radius: var(--hxx-radius-full);
    background: var(--hxx-primary);
    left: calc((100% - 16px) * var(--hxx-a, 0) + 8px);
    right: calc(100% - (100% - 16px) * var(--hxx-b, 1) - 8px);
}
.hxx-slider-in {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none; /* 拖动只落在滑块上（两条 input 互相叠放不抢事件） */
}
.hxx-slider-in::-webkit-slider-runnable-track { height: 100%; background: none; }
.hxx-slider-in::-webkit-slider-thumb { margin-top: 3px; /* (22 - 16) / 2 */ }
.hxx-slider-in::-moz-range-track { height: 100%; background: none; }

/* ---------- 滑动验证框 HXXVerify（js/hxx-ui.js 注入 / 接线） ----------
   40px 胶囊轨道（muted 底 + 1px 边）+ 36px 圆滑块；填充随滑块推进（primary-soft，
   通过后 success-soft + 滑块变实心绿 + 对勾）；拖动中（is-drag）禁用过渡跟手，
   松手未达标弹回；文案随进度淡出。touch-action:none 防触摸滚动劫持 */
.hxx-verify {
    position: relative;
    width: 100%;
    height: 40px;
    border-radius: var(--hxx-radius-full);
    background: var(--hxx-muted);
    border: 1px solid var(--hxx-border);
    overflow: hidden;
    user-select: none;
    -webkit-user-select: none;
    touch-action: none;
}
.hxx-verify-fill {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 0;
    background: var(--hxx-primary-soft);
    transition: width var(--hxx-t-slow) ease;
}
.hxx-verify-text {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    color: var(--hxx-text-3);
    pointer-events: none;
    transition: opacity var(--hxx-t-fast) ease;
}
.hxx-verify-thumb {
    position: absolute;
    left: 0;
    top: 50%;
    width: 36px;
    height: 36px;
    margin-top: -18px;
    padding: 0;
    border-radius: var(--hxx-radius-full);
    border: 1px solid var(--hxx-border-strong);
    background: var(--hxx-surface);
    color: var(--hxx-text-2);
    box-shadow: var(--hxx-shadow);
    font: inherit;
    cursor: grab;
    display: flex;
    align-items: center;
    justify-content: center;
    transform: translateX(0);
    transition: transform var(--hxx-t-slow) ease, background-color var(--hxx-t-fast) ease,
        color var(--hxx-t-fast) ease, border-color var(--hxx-t-fast) ease;
}
.hxx-verify-thumb:active { cursor: grabbing; }
.hxx-verify-thumb svg { width: 18px; height: 18px; display: block; }
.hxx-verify-thumb:focus-visible {
    outline: none;
    border-color: var(--hxx-primary);
    box-shadow: 0 0 0 3px var(--hxx-primary-soft);
}
.hxx-verify.is-drag .hxx-verify-fill,
.hxx-verify.is-drag .hxx-verify-thumb { transition: none; }
.hxx-verify.is-success { border-color: var(--hxx-success); }
.hxx-verify.is-success .hxx-verify-fill { background: var(--hxx-success-soft); }
.hxx-verify.is-success .hxx-verify-thumb {
    background: var(--hxx-success);
    border-color: var(--hxx-success);
    color: #fff;
    cursor: default;
}
.hxx-verify.is-success .hxx-verify-text { color: var(--hxx-success); font-weight: 600; }

/* ---------- 动效引擎 HXXEffect（令牌见 :root --hxx-fx-*；驱动逻辑在 js/hxx-ui.js） ----------
   暴露方式为纯 JS 函数（HXXEffect.shake(el) 等），不做声明式接线：JS 内部挂下列类名、
   animationend 后自动摘除，宿主无需手工管理 class。
   层级 --hxx-fx-z = 10008：盖住弹窗 / toast / 日期面板，仍低于水印 10010（水印契约要求覆盖全站）。 */

/* 粒子层：JS 懒创建的 canvas。全屏模式 position:fixed 挂 body；
   局部模式（opts.container）position:absolute 挂到指定容器，宿主需 overflow:hidden 才不外溢。
   pointer-events:none 保证不挡任何交互；粒子全部消亡后 JS 停 rAF 并于空闲 3s 后摘除节点，不常驻合成层。 */
.hxx-fx-layer {
    position: fixed;
    inset: 0;
    /* canvas 是替换元素：绝对/固定定位下 width:auto 会解析为「固有宽度」（= canvas.width 属性 = 视口×DPR），
       而不是被 inset:0 拉伸——那样画布会以物理像素尺寸渲染、溢出视口且 DPR 缩放全废。必须显式 100%。 */
    width: 100%;
    height: 100%;
    z-index: var(--hxx-fx-z);
    pointer-events: none;
    display: block;
}
.hxx-fx-layer.is-local { position: absolute; }

/* shake：水平抖动，承载「操作失败」语义（表单校验不通过 / 拒绝操作） */
.hxx-fx-shake {
    animation: hxx-fx-shake var(--hxx-fx-shake-dur) cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
}

/* pulse：弹一下（把注意力引到某元素），弹性曲线复用 --hxx-fx-ease-back 与弹窗形变同源 */
.hxx-fx-pulse { animation: hxx-fx-pulse var(--hxx-fx-pulse-dur) var(--hxx-fx-ease-back) both; }

/* ripple：点击涟漪。宿主元素由 JS 补 .hxx-fx-ripple-host（relative + overflow:hidden），
   波纹直径取「点击点到四角最远距离 ×2」，保证任意点击位置都能铺满整个元素 */
.hxx-fx-ripple-host { position: relative; overflow: hidden; }
.hxx-fx-ripple {
    position: absolute;
    border-radius: var(--hxx-radius-full);
    background: currentColor; /* 跟随文字色：实心按钮内为白波纹、浅底按钮内为深色波纹 */
    opacity: 0.22;
    transform: scale(0);
    pointer-events: none;
    animation: hxx-fx-ripple var(--hxx-fx-ripple-dur) ease-out forwards;
}

/* hearts：点赞飘心。走 DOM + SVG 而非 canvas——心形曲线 canvas 手绘偏糙，
   且契约 §1 严禁 emoji 当图标；漂移方向由 JS 逐颗写入 --hxx-fx-heart-x / --hxx-fx-heart-y */
.hxx-fx-heart {
    position: fixed;
    z-index: var(--hxx-fx-z);
    width: var(--hxx-fx-heart-size, 20px);
    height: var(--hxx-fx-heart-size, 20px);
    pointer-events: none;
    color: var(--hxx-danger);
    animation: hxx-fx-heart var(--hxx-fx-heart-dur) cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
.hxx-fx-heart svg { display: block; width: 100%; height: 100%; }

/* checkmark：成功打勾描线（stroke-dashoffset 由满偏移收到 0）+ 外圈光环扩散 */
.hxx-fx-check {
    position: fixed;
    z-index: var(--hxx-fx-z);
    width: var(--hxx-fx-check-size, 64px);
    height: var(--hxx-fx-check-size, 64px);
    pointer-events: none;
    color: var(--hxx-success);
    /* 淡出必须并列声明为第二条动画，不能用类名改 opacity：
       hxx-fx-check-pop 带 both 填充，动画层的 100% 关键帧会压过普通声明（含 !important 以外的类规则）。
       同一属性上列表中靠后的动画生效，故 out 在延迟到点后接管；延迟 --hxx-fx-out-at 由 js 按 hold 时长写入。 */
    animation: hxx-fx-check-pop var(--hxx-fx-check-dur) var(--hxx-fx-ease-back) both,
        hxx-fx-check-out var(--hxx-t-slow) ease-out var(--hxx-fx-out-at, 0.76s) forwards;
}
.hxx-fx-check svg { position: relative; z-index: 1; display: block; width: 100%; height: 100%; }
.hxx-fx-check-path {
    fill: none;
    stroke: currentColor;
    stroke-width: 3;
    stroke-linecap: round;
    stroke-linejoin: round;
    stroke-dasharray: 23;   /* ≥ 路径实长（≈22.8）即可完全隐藏；过大则描线提前画完、尾段空转 */
    stroke-dashoffset: 23;
    animation: hxx-fx-check-draw calc(var(--hxx-fx-check-dur) * 0.75) ease-out forwards;
}
.hxx-fx-check-ring {
    position: absolute;
    inset: 0;
    border: 2px solid currentColor;
    border-radius: var(--hxx-radius-full);
    animation: hxx-fx-check-ring var(--hxx-fx-check-dur) ease-out forwards;
}

/* ---------- 新增组件动效关键帧（契约 §12；reduce 降级见文件末尾统一块） ---------- */
@keyframes hxx-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes hxx-skeleton-slide { to { transform: translateX(100%); } }
@keyframes hxx-progress-slide { from { transform: translateX(-100%); } to { transform: translateX(280%); } }
@keyframes hxx-ripple-out { /* 循环波纹：圆环自元素边缘向外扩散消散（transform+opacity 合成器动画；--hxx-ripple-to 控制扩散倍率，随元素自定义覆盖） */
    0% { transform: scale(1); opacity: 0.45; }
    70%, 100% { transform: scale(var(--hxx-ripple-to, 1.8)); opacity: 0; }
}
@keyframes hxx-fx-shake { /* 位移幅度递减的左右抖动：两端小、中段大，收尾归零不残留偏移 */
    10%, 90% { transform: translate3d(calc(var(--hxx-fx-shake-dist) * -0.35), 0, 0); }
    20%, 80% { transform: translate3d(calc(var(--hxx-fx-shake-dist) * 0.6), 0, 0); }
    30%, 50%, 70% { transform: translate3d(calc(var(--hxx-fx-shake-dist) * -1), 0, 0); }
    40%, 60% { transform: translate3d(var(--hxx-fx-shake-dist), 0, 0); }
}
@keyframes hxx-fx-pulse {
    0% { transform: scale(1); }
    45% { transform: scale(var(--hxx-fx-pulse-scale)); }
    100% { transform: scale(1); }
}
@keyframes hxx-fx-ripple { to { transform: scale(1); opacity: 0; } }
@keyframes hxx-fx-heart { /* 上浮 + 横向漂移 + 先放大后淡出；位移量由 JS 逐颗随机写入自定义属性 */
    0% { transform: translate3d(0, 0, 0) scale(0.4); opacity: 0; }
    18% { opacity: 1; }
    100% { transform: translate3d(var(--hxx-fx-heart-x, 0px), var(--hxx-fx-heart-y, -92px), 0) scale(1.1); opacity: 0; }
}
@keyframes hxx-fx-check-pop {
    0% { transform: scale(0.55); opacity: 0; }
    55% { opacity: 1; }
    100% { transform: scale(1); opacity: 1; }
}
@keyframes hxx-fx-check-draw { to { stroke-dashoffset: 0; } }
@keyframes hxx-fx-check-ring {
    0% { transform: scale(0.75); opacity: 0.55; }
    100% { transform: scale(1.75); opacity: 0; }
}
@keyframes hxx-fx-check-out { to { opacity: 0; } }

/* ---------- 动效降级（设计契约 §12：prefers-reduced-motion 下禁用动画/过渡） ----------
   !important 压过 :checked 等更高特异性的动画规则 */
@media (prefers-reduced-motion: reduce) {
    .hxx-checkbox, .hxx-checkbox::before, .hxx-checkbox::after,
    .hxx-checkbox:checked, .hxx-checkbox:checked::before, .hxx-checkbox:checked::after,
    .hxx-radio, .hxx-radio::before, .hxx-radio::after,
    .hxx-radio:checked, .hxx-radio:checked::before, .hxx-radio:checked::after,
    .hxx-switch, .hxx-switch::before, .hxx-switch::after, .hxx-switch:checked,
    .hxx-select-arrow, .hxx-select-trigger, .hxx-select-panel,
    .hxx-drawer, .hxx-drawer-mask, .hxx-drawer-close,
    .hxx-date-panel, .hxx-date-day, .hxx-date-time-item,
    .hxx-tab, .hxx-tab-pane,
    .hxx-progress-bar, .hxx-progress-circle,
    .hxx-progress-circle::before, .hxx-progress-circle::after,
    .hxx-progress.is-gradient .hxx-progress-bar::before, .hxx-progress.is-gradient .hxx-progress-bar::after,
    .hxx-step-num::after, .hxx-pagination .hxx-page::after,
    .hxx-skeleton::after,
    .hxx-notify-item, .hxx-popover,
    .hxx-collapse-content, .hxx-collapse-header::after,
    .hxx-backtop,
    .hxx-slider-bubble, .hxx-verify-fill, .hxx-verify-thumb,
    .hxx-card, .hxx-step-num, .hxx-pagination .hxx-page, .hxx-avatar {
        animation: none !important;
        transition: none !important;
    }
    /* HXXEffect：粒子 / 飘心 / 打勾 / pulse / ripple 的降级由 js/hxx-ui.js 侧 matchMedia 统一拦截
       （整段不创建节点），此处不重复声明，避免与 opts.force = true 强制播放冲突。
       shake 是例外——它承载「操作失败」语义，整段丢弃会丢信息，故降级为极短弱版
       （时长 --hxx-fx-shake-dur-reduced、位移减半），带 .hxx-fx-force 时仍走完整版。 */
    .hxx-fx-shake:not(.hxx-fx-force) {
        --hxx-fx-shake-dist: 3px;
        animation-duration: var(--hxx-fx-shake-dur-reduced) !important;
        animation-timing-function: linear !important;
    }
}
