/* =========================================================================
   PwIv · AI 图生视频 · 可嵌套公共组件样式（原生 CSS）
   -------------------------------------------------------------------------
   本文件是 VideoEhancer_Web 的**直接移植**，不是重新设计：
     · 结构 / 类名 ← src/pages/video/ai-image-to-video/index.vue（模板原样）
     · 样式        ← src/assets/styles/image_text_to_video.less
                      （nested LESS 展开为平铺 CSS，选择器前缀 .pw-iv 做隔离，
                        数值与声明一律照搬，不做“优化”）
     · 变量        ← src/assets/styles/theme.less，取值完全一致，且**沿用参考站
                      命名**（--pw-bg-color-N / --pw-text-color-N / --pw-border-*
                      / --pw-upload-drop-* / --pw-panel-enhance-*），
                      方便日后与产品端同步、也便于按参考站文档互查。
   只有“参考站里没有、我们为了嵌进 WordPress 才需要”的部分是本组件自有实现：
   卡片外壳（等高双卡 / sticky）、右侧 Sample 区、弹层容器、Toast。
   ========================================================================= */

/* ---------- 0. icomoon 图标字体（与参考站 assets/icons-font 同一份字体） ----------
   字体原件放在 assets/icons/（icomoon.ttf/svg/woff/eot + 参考站原样的 index.css）。
   组件**不直接引**那个 index.css：它的基类
       [class^="icon-"], [class*=" icon-"] { font-family:'icomoon' !important; ... }
   是裸选择器，嵌进 WordPress 会把宿主主题自己的图标元素（如 <i class="mytheme-icon icon-home">
   的 class 里含 " icon-"）也强行换成 icomoon 字形；何况那 767 个图标组件只用到 8 个。
   所以这里只内联 @font-face + 组件真正用到的那几个码位，且全部收进 .pw-iv 作用域。
   升级图标：整包替换 assets/icons/，再跑
       node assets/icons/extract-used-icons.js
   把输出贴回下面「生成段」。 */
@font-face {
  font-family: 'icomoon';
  src: url('../icons/icomoon.ttf?9r1na8') format('truetype'),
       url('../icons/icomoon.svg?9r1na8#icomoon') format('svg'),
       url('../icons/icomoon.woff?9r1na8') format('woff'),
       url('../icons/icomoon.eot?9r1na8#iefix') format('embedded-opentype');
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}
/* 基类收进 .pw-iv：只作用于组件内部，不与宿主主题抢 [class^="icon-"] */
.pw-iv [class^="icon-"],
.pw-iv [class*=" icon-"] {
  /* 用 !important 防止宿主主题的字体规则改写图标字形（与参考站同样的处理） */
  font-family: 'icomoon' !important;
  speak: never;
  font-style: normal;
  font-weight: normal;
  font-variant: normal;
  text-transform: none;
  line-height: 1;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ↓↓↓ 生成段：由 assets/icons/extract-used-icons.js 从 assets/icons/index.css 生成，勿手改 ↓↓↓
   要加 / 减图标改那个脚本的 USED 数组，再把它的输出整段贴回这里（脚本会回报命中条数）。
   ⚠️ 这里**不写死条数** —— 早先写的是「以下 21 条」，图标加到二十几个之后没人回头改，
   那句就成了一条长期挂着的错话。条数由脚本的输出说话。 */
/* 下拉箭头 .model-trigger-simple / .config-trigger（AiModelConfigSelector.vue:38,196） */
.pw-iv .icon-16_open:before { content: "\e98e"; }
/* .tool-item 替换（index.vue:172） */
.pw-iv .icon-16_change_sp:before { content: "\eb23"; }
/* .tool-item 裁剪（index.vue:184） */
.pw-iv .icon-16_hl_tailor:before { content: "\eb39"; }
/* .tool-item 删除（index.vue:196） */
.pw-iv .icon-16_delet_sp:before { content: "\eb24"; }
/* 生成按钮 .generate-button（index.vue:636） */
.pw-iv .icon-20_generate_sp:before { content: "\eb88"; }
/* 生成按钮上的积分 .credit-tip-box（参考站 cost-tip，video-enhancer/index.vue:370） */
.pw-iv .icon-20_coins:before { content: "\e9b2"; }
/* 配置弹层比例图标 RATIO_ICON_MAP["16:9"]（AiModelConfigSelector.vue:485） */
.pw-iv .icon-20_16_9_sp:before { content: "\ebf6"; }
/* 配置弹层比例图标 RATIO_ICON_MAP["9:16"] */
.pw-iv .icon-20_9_16_sp:before { content: "\ebf5"; }
/* 配置弹层比例图标 RATIO_ICON_MAP["4:3"] */
.pw-iv .icon-20_4_3_sp:before { content: "\ebf4"; }
/* 配置弹层比例图标 RATIO_ICON_MAP["3:4"] */
.pw-iv .icon-20_3_4_sp:before { content: "\ebf3"; }
/* 配置弹层比例图标 RATIO_ICON_MAP["21:9"] */
.pw-iv .icon-20_21_9_sp:before { content: "\ebfe"; }
/* 配置弹层比例图标 RATIO_ICON_MAP["1:1"]，也是 map 的兜底值（未知比例用它；
   Auto 档按产品要求改用了 16:9 图标，见 pw-iv.js 的 ratioOption） */
.pw-iv .icon-20_1_1_sp:before { content: "\ebf2"; }
/* 模型列表的限免提示条 .model-free-trial-tip（index.vue:137） */
.pw-iv .icon-20_gift:before { content: "\e934"; }
/* 历史卡片完成态的静态播放按钮 .pw-iv-hist-play（参考站 PwVideoControls.vue 同款播放图标） */
.pw-iv .icon-24_player_sp:before { content: "\eb92"; }
/* 视频控制条的「播放」图标 .pw-iv-hist-ctrl-btn（参考站 PwVideoControls.vue:12 同款） */
.pw-iv .icon-20_bf_sp:before { content: "\eb0e"; }
/* 视频控制条的「暂停」图标 —— 由 _histPaintCtrl 在运行期换成它（参考站 PwVideoControls.vue:12 同款） */
.pw-iv .icon-20_bf2_sp:before { content: "\eb1c"; }
/* 历史底部条的「复制链接」图标按钮（HistoryShareMenu.vue 同款） */
.pw-iv .icon-16_link_sp:before { content: "\eb79"; }
/* 历史底部条的「分享」图标按钮（HistoryShareMenu.vue 同款） */
.pw-iv .icon-16_shareone_sp:before { content: "\eb72"; }
/* 历史底部条的「下载」图标按钮（HistoryShareMenu.vue 同款） */
.pw-iv .icon-16_toolbar_download2:before { content: "\e995"; }
/* 历史卡片的删除图标 —— 完成态与失败态**共用**（参考站 HistoryShareMenu.vue:248 那条 delete 同款字形；失败态那边照 ImageToVideoHistoryItem.vue 的 .more-icon，不带 icon-img） */
.pw-iv .icon-16_hl_delete:before { content: "\eb37"; }
/* 「复制链接」进行中的转圈；也是桌面分享 / 下载弹出层每行右侧的转圈（参考站 HistoryShareMenu.vue / AigcDownloadDrawer.vue） */
.pw-iv .icon-16_loading_sp:before { content: "\eb8c"; }
/* 移动端底部抽屉里分享 / 下载每行右侧的转圈（参考站 ShareDrawer.vue / AigcDownloadDrawer.vue 的抽屉形态） */
.pw-iv .icon-32_log_loading1:before { content: "\ea38"; }
/* 下载弹出层「带水印」那一行的图标（AigcDownloadDrawer.vue） */
.pw-iv .icon-16_watermark_sp:before { content: "\eb9c"; }
/* 下载弹出层「无水印」那一行的图标，右侧另挂金色 VIP 徽章（AigcDownloadDrawer.vue） */
.pw-iv .icon-16_nowatermark_sp:before { content: "\eb9b"; }
/* 提示词弹窗两套外壳的 ✕：PC 那套在卡片右上角（PwDialog 自带的 .close-icon）、≤768 那套在 .drawer-title-bar 右端 */
.pw-iv .icon-24_close:before { content: "\e984"; }
/* AI 改写成功后那颗「撤销」的回退图标（两个组件模板里的 .undo-button） */
.pw-iv .icon-16_toolbar_recovery:before { content: "\e999"; }
/* ↑↑↑ 生成段结束 ↑↑↑ */

/* ---------- 1. 主题变量（照抄 theme.less） ---------- */
.pw-iv {
  /* 组件内所有弹出层的包含块 —— 裁剪弹层、.pw-iv-hpop、.pw-iv-hdrawer-wrap 全是它的
     absolute 后代，坐标都以它的 padding box 为原点。（⚠️ 是**这个**元素，不是宿主传给
     `mount(el)` 的那个挂载元素 —— 见 js 里 `_root` / `_appEl` 那段与 § 桌面弹出层。） */
  position: relative;
  /* 字体与参考站 base.less:63 的 `*{font-family:Poppins,Arial,Helvetica,sans-serif}` 对齐。
     参考站只打包了 Poppins-ExtraBold（800），常规 Poppins 并不存在 → 实际落到 Arial。
     这里若换成 -apple-system/Segoe UI 之类的系统栈，Latin 字宽会与参考不同，
     直接影响 trigger 与比例按钮的实测宽度。中文由 sans-serif 回落到系统 CJK 字体。 */
  --pw-f: "Poppins", Arial, Helvetica, sans-serif;

  /* 背景层 */
  --pw-bg-color-1: #09090b;
  --pw-bg-color-2: #31333c;
  --pw-bg-color-3: #26272f;
  --pw-bg-color-4: #2f313e;
  --pw-bg-color-5: #a984ff;
  /* 历史底部条图标按钮的 hover 底色（参考站 HistoryShareMenu.vue 的 .menu-item:hover）。
     ⚠️ 曾经这里没有它，底部条那一段的注释还断言「参考站也没有、是靠 fallback 兜的」——
     那是错的：参考站 theme.less:15 明确定义了它。 */
  --pw-bg-color-9: rgba(0, 0, 0, 0.8);
  --pw-bg-color-15: #ffffff;
  --pw-bg-color-16: rgba(0, 0, 0, 0.4);

  /* 文字 */
  --pw-text-color-1: #ffffff;
  --pw-text-color-2: #a984ff;
  --pw-text-color-3: #ff3a3e;
  --pw-text-color-4: rgba(255, 255, 255, 0.8);
  --pw-text-color-5: rgba(255, 255, 255, 0.6);

  /* 上传区 */
  --pw-upload-drop-content-border: #a984ff;
  --pw-upload-drop-content-bg-hover: rgba(169, 132, 255, 0.15);

  /* 面板控件 */
  --pw-panel-control-bg: #1c1d24;
  --pw-panel-control-color: #ffffff;

  /* 弹窗 / 按钮（theme.less） */
  --pw-dialog-mask-color: rgba(0, 0, 0, 0.8);
  --pw-dialog-content-bg: #2f313e;
  /* 弹窗右上角那颗 ✕ 的颜色（theme.less:102）。§11 的 PC 外壳用它 —— 参考站是靠
     PwDialog 的 .close-icon 拿到的，那个变量只在那一条规则里出现。 */
  --pw-dialog-close-color: #ffffff;
  --pw-button-text-color-1: #ffffff;
  --pw--button-primary-bg: linear-gradient(129deg, #4d5aff 0%, #8a53ff 48%, #f84eb4 97%);
  /* 「制作同款」按钮按下时的底色（参考站 --pw--button-primary-bg-a）。
     ⚠️ 注意它跟上面那条**不是**同一串渐变：中停点从 48% 挪到了 52%，两端也多写了 3% / 100%。
     别顺手写成 var(--pw-grad)，那会悄悄换掉渐变的走向。 */
  --pw--button-primary-bg-a: linear-gradient(129deg, #f84eb4 3%, #8a53ff 52%, #4d5aff);
  /* ⚠️ 本文件里 hover 那条叫 `--pw-btn-primary-bg-h`（**单**横线），不是参考站的
     `--pw--button-primary-bg-h`。值一样，名字不一样 —— 照抄参考站的 var() 会解析成
     undefined，整个 background 声明在计算值阶段失效，hover 时渐变**直接消失**。 */
  --pw-btn-primary-bg-h: linear-gradient(90deg, #757bff 0%, #f972c3 100%);
  --pw--button-white-border: #ffffff;
  --pw--button-white-border-bg: transparent;
  /* 失败插画的「颜色」（参考站 --pw-svg-img-to-video-error-color / --pw-svg-dialog-img-color，
     分别是基准档与窄屏档）。
     ⚠️ 对本组件现在这张插画**是死的**：那个 SVG 的五条路径各自带着写死的 fill/stroke
     （#26272F / #BCB7FF / #FF4F78 / white / #DBD8FF），呈现属性虽然特异性最低，却**胜过继承**，
     所以父级那两条 color/fill:currentColor 一个字节都到不了里面。留着是为了照抄参考站、
     以及万一将来换成单色字形时它正好接上 —— **别**以为改这两个变量能把插画换成别的颜色。 */
  --pw-svg-img-to-video-error-color: #2F313E;
  --pw-svg-dialog-img-color: #26272f;

  /* 面板 / 配置项 */
  --pw-panel-enhance-config-border: transparent;
  --pw-panel-enhance-config-border-active: #a984ff;
  --pw-panel-enhance-config-content-border: #414450;
  --pw-panel-enhance-video-tool-bg: rgba(0, 0, 0, 0.8);
  --pw-panel-enhance-video-tool-border-color: rgba(255, 255, 255, 0.2);

  /* 描边 */
  --pw-border-color-1: #a984ff;

  /* 品牌渐变 / 尺寸（参考站散落各处的常量，这里收敛成变量） */
  /* 主渐变：与参考站 base.less:500 / image_text_to_video.less:648 完全一致（中停点是 48%） */
  --pw-grad: linear-gradient(129deg, #4d5aff 0%, #8a53ff 48%, #f84eb4 97%);
  --pw-grad-h: linear-gradient(90deg, #757bff 0%, #f972c3 100%);
  --pw-panel-w: 360px;
  --pw-r-lg: 12px;
  --pw-pop-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);

  container-type: inline-size;
  background: var(--pw-bg-color-1);
  color: var(--pw-text-color-1);
  font-family: var(--pw-f);
  font-size: 14px;
  line-height: 1.5;
  /* 与上面几行同因：不继承宿主页面的排版。WP 主题 / 文章正文常有 text-align:center
     （居中标题、图文环绕），漏进来会把面板里的标题、按钮文案、点数一并居中。
     组件内的对齐都是各自声明的，这里只把根节点的起点钉回 left。 */
  text-align: left;
  min-width: 0;
}

/* 隔离重置（仅组件内） */
.pw-iv *, .pw-iv *::before, .pw-iv *::after { box-sizing: border-box; margin: 0; padding: 0; }
.pw-iv img, .pw-iv video { display: block; max-width: 100%; }
.pw-iv button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
.pw-iv button:disabled { cursor: not-allowed; }
.pw-iv input, .pw-iv textarea, .pw-iv select { font: inherit; color: inherit; }
.pw-iv textarea { resize: none; }
/* 选图用的 <input type=file>（见 js 的 pickFile）。**必须显式藏**：它是个可见控件，
   不藏就是宿主页面上多一个「选择文件」按钮。`display:none` 不影响 `.click()` 拉起
   文件框 —— 这是隐藏 file input 的标准做法。 */
.pw-iv .pw-iv-fileinput { display: none; }
.pw-iv ::-webkit-scrollbar { width: 8px; height: 8px; }
.pw-iv ::-webkit-scrollbar-thumb { background-color: #31333c; border-radius: 8px; }
.pw-iv svg { display: block; width: 1em; height: 1em; }
.pw-iv :focus { outline: none; }
.pw-iv [hidden] { display: none !important; }


/* 图标：类名与 ai-image-to-video/index.vue 一致，例如 <i class="icomoon icon-16_change_sp"></i>。
   注意 index.css 里每个图标类**只给 content（码位），不给 font-size**——
   `icon-16_` / `icon-20_` / `icon-24_` 只是命名约定，真实字号一律由使用处的 CSS 决定，
   所以下面每条使用场景都按参考页原样补 font-size。 */
.pw-iv :where(.icomoon) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
/* 展开态旋转（复刻参考站 .icon-rotate，arco_dropdown.less:237） */
.pw-iv .icon-rotate { transform: rotate(180deg); }

/* ---------- 2. 外层两栏骨架（组件自有：等比等高双卡 + sticky） ---------- */
.pw-iv-shell { position: relative; display: flex; align-items: flex-start; gap: 16px; }

/* 左卡 = 参考 .ai-image-to-video-panel-page 的容器位；sticky 视口高由本组件提供。
   宽度就是卡片本身的 360：参考页的收起把手 .show-control 未移植（面板常驻展开），
   所以不再为那 15px 留位。 */
.pw-iv-panel-slot {
  position: sticky; top: 16px;
  flex: 0 0 var(--pw-panel-w); width: var(--pw-panel-w);
  height: calc(100vh - 32px); min-height: 540px;
  display: flex; flex-direction: column;
}

/* 右侧 Sample 卡（组件自有，对齐 .ai-history-page 整卡） */
.pw-iv-stage {
  position: sticky; top: 16px;
  flex: 1 1 0%; min-width: 0;
  height: calc(100vh - 32px); min-height: 540px;
  background: var(--pw-bg-color-2);
  border-radius: var(--pw-r-lg);
  overflow: hidden;
}
.pw-iv-stage-body { height: 100%; }

/* =========================================================================
   3. 面板 —— 逐条移植 image_text_to_video.less
   ========================================================================= */
.pw-iv .ai-image-to-video-panel-page {
  height: 100%;
  display: flex;
  align-items: center;
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
}

/* .panel-content：360 宽 / radius12 / --pw-bg-color-3 / overflow hidden */
.pw-iv .panel-content {
  transition: all 300ms;
  overflow: hidden;
  width: 360px;
  height: 100%;
  border-radius: 12px;
  position: relative;
  background-color: var(--pw-bg-color-3);
}
.pw-iv .panel-content.blur { filter: blur(8px); }

/* 注：参考页的收起把手 .show-control 未移植 —— 本组件面板常驻展开（见 README「有意差异」）。
   滚动内容区：padding-bottom 180px 是给吸底 .button-box 让位的，别删 */
.pw-iv .ai-image-to-video-panel-content {
  width: 360px;
  height: 100%;
  /* 左右内缩下沉到子元素（见下），容器本身只留吸底条的让位空间 ——
     这样 .ai-image-to-video-panel-tab 的 border-bottom 才能通栏，其余内容照旧内缩。 */
  --pw-content-pad-x: 14px;
  padding: 0 0 180px;
  overflow: auto;
}

/* 左右内缩：容器 padding 归零后，由每个直接子元素自己承担。
   分两类，因为两者的正确工具不同：
     ① 无自身背景/描边的（tab 条、字段标题、提示词标签、提示文案）→ padding，
        元素盒子铺满整行，视觉上文字仍是内缩的；
     ② 自带背景/描边的盒子（.add-video / .exist-img-box / .prompt-textarea-content）
        → 必须用 margin：padding 是画在边框**内侧**的，
        给它们加 padding 会把自己的虚线框/圆角边框推到通栏，同时压掉它们自身的
        内边距（.add-video 的 21px、.prompt-textarea 的 14px）。
        宽度同时改 auto：它们的 width:100% 是含 padding 的 border-box 100%，
        再加左右 margin 会横向溢出 28px。 */
.pw-iv .ai-image-to-video-panel-content > .ai-image-to-video-panel-tab,
.pw-iv .ai-image-to-video-panel-content > .video-config-title,
.pw-iv .ai-image-to-video-panel-content > .prompt-text,
.pw-iv .ai-image-to-video-panel-content > .video-effect-panel-image-tip,
.pw-iv .ai-image-to-video-panel-content > .prompt-limit-error {
  padding-left: var(--pw-content-pad-x);
  padding-right: var(--pw-content-pad-x);
}
.pw-iv .ai-image-to-video-panel-content > .add-video,
.pw-iv .ai-image-to-video-panel-content > .exist-img-box,
.pw-iv .ai-image-to-video-panel-content > .prompt-textarea-content {
  width: auto;
  margin-left: var(--pw-content-pad-x);
  margin-right: var(--pw-content-pad-x);
}

/* 注：参考页的 .panel-title（面板大标题）已去除，标题交给宿主页面自己出。
   首个子元素随之变成下面的 .ai-image-to-video-panel-tab。 */

/* 模型 Tab */
.pw-iv .ai-image-to-video-panel-content .ai-image-to-video-panel-tab {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 0 30px;
  gap: 36px;
  /* 通栏下划线（子元素的内缩在上面统一给，边框铺满整行） */
  border-bottom: 1px solid #333336;
  margin: 4px auto 14px;
}
.pw-iv .ai-image-to-video-panel-content .ai-image-to-video-panel-tab .panel-tab-item {
  transition: all 300ms;
  width: 100%;
  padding: 10px 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid transparent;
  font-size: 16px;
  color: var(--pw-text-color-1);
  line-height: 24px;
}
/* 选中态只改**下边框**：另外三边沿用上面那条 border 的 transparent，
   所以切换时不会因为少了 2px 而整体跳动。 */
.pw-iv .ai-image-to-video-panel-content .ai-image-to-video-panel-tab .panel-tab-item-active {
  border-bottom: 2px solid var(--pw-border-color-1);
  color: var(--pw-text-color-2);
}
@media (hover: hover) and (pointer: fine) {
  .pw-iv .ai-image-to-video-panel-content .ai-image-to-video-panel-tab .panel-tab-item:hover {
    border-bottom: 2px solid var(--pw-border-color-1);
    color: var(--pw-text-color-2);
  }
}

/* 字段标题 *图片 */
.pw-iv .ai-image-to-video-panel-content .video-config-title {
  font-size: 14px;
  color: var(--pw-text-color-1);
  line-height: 22px;
  padding-bottom: 12px;
}

/* 空态上传框 */
.pw-iv .ai-image-to-video-panel-content .add-video {
  padding: 21px;
  background: var(--pw-bg-color-3);
  border-radius: 16px;
  border: 2px dashed var(--pw-upload-drop-content-border);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  height: 170px;
}
.pw-iv .ai-image-to-video-panel-content .add-video.error { border-color: var(--pw-text-color-3); }
.pw-iv .ai-image-to-video-panel-content .add-video .add-video-img { width: 48px; height: 48px; }
.pw-iv .ai-image-to-video-panel-content .add-video .add-text-mobile {
  display: none;
  font-weight: 400; font-size: 14px;
  color: var(--pw-text-color-4); line-height: 22px; text-align: center;
}
.pw-iv .ai-image-to-video-panel-content .add-video .add-text {
  font-weight: 400; font-size: 14px;
  color: var(--pw-text-color-4); line-height: 22px; text-align: center;
}
@media (hover: hover) and (pointer: fine) {
  /* :not() 把「上传中 / 上传失败」两态摘出去 —— 它们也是 .add-video，但都不可点
     （cursor 已经是 default），跟着高亮会让人以为点了有用。
     ⚠️ :not() 按它**参数的特异度**计贡献（各 +1 个类），这条因此从 3 类变 5 类；
     全文件只有这一条在给 .add-video 上悬停底色，所以不担心压到别的规则。 */
  .pw-iv .ai-image-to-video-panel-content .add-video:not(.uploading-file-box):not(.error-box):hover {
    background: var(--pw-upload-drop-content-bg-hover);
  }
}

/* 上传中（= 参考站 .add-video.uploading-file-box + 那张 AiUploadingCard）。
   「裁剪确定即上传」的产物：图还在路上，框里换成一件逐帧精灵图 + 一句文案 + 一根进度条，
   顺序与参考站 AiUploadingCard.vue 那张卡一致（精灵图 → .card-describe → a-progress）。
   与参考站一致 —— 此态**不显示本地预览**（那边 <img> 源是 VIDEO_BASE_URL + s3key，
   key 没回来时无从渲染；本地 objectURL 其实画得出来，但刻意不画，好让「还在传」一目了然，
   这也正是「创建按钮不置灰却点了没反应」能被用户理解的前提）。
   改这段前先读 pw-iv.js 的 _startImageUpload 与 _paintImgProgress ——
   后者只在 [data-img-progress] 及其 .uploading-bar-fill / .uploading-info 上做局部更新，
   精灵图一个钩子都没有、整段只在面板重绘时重建，别给它加 data-* 再往上报里塞。
   ⚠️ 两个新态的元素（上传中 / 失败框）**都带着 .add-video 类**，所以窄屏那两处断点（@container / @media
   max-width:900px）里的 `height: 160px` 自动管到它们 —— 别再去那边补一遍，那是冗余规则。
   高度账（`box-sizing: border-box`，见 :203）：默认 170px 去掉 4px 边框是 166 的内容高，
   三件 63 + 24 + 7 = 94、加两条 6px 的 gap 共 106 —— 上下各余 30；窄屏 160px 那份剩 25。
   换图 / 改帧高时先算这一笔，别让精灵图把进度条挤出去。 */
.pw-iv .ai-image-to-video-panel-content .add-video.uploading-file-box {
  padding: unset;
  overflow: hidden;
  cursor: default;          /* 不接点击：它既不是「可放置」也不是「可替换」 */
  gap: 6px;
  text-align: center;
}
/* 逐帧精灵图 —— 参考站 AiUploadingCard.vue 的 .upload-loading-mobile，由
   loading.less:149-157 那段 mixin 展开（@mobile-frame-width/height = 60/63、
   @upload-total = 24、1s）。
   资源 upload_loading_m.png 是 **120×3024 的 2 倍图**：24 帧竖排、每帧 60×63 CSS px
   （3024÷2 = 1512 = 63×24）。`background-size` **只写宽度 60px**、高度 auto，
   缩完正好 60×1512，第 i 帧的偏移量就是精确的 -(i*63)px —— 与下面那条
   .common-dark-loading（生成中遮罩那张品牌精灵图）同一套写法，那份注释把尺寸账算得更细，
   换图时对照着读。
   参考站这张图带 "-mobile"、另有一张 120px 的 PC 版（upload-loading-pc，loading.less:139），
   但那张只在别的卡片上用；AiUploadingCard 在**所有宽度**下都用 mobile 版，
   所以这里不写断点 —— 面板本身也就 360px 上下，60px 的图正合适。 */
.pw-iv .ai-image-to-video-panel-content .add-video.uploading-file-box .uploading-loading {
  width: 60px;
  height: 63px;
  background-image: url('../images/loading/upload_loading_m.png');
  background-repeat: no-repeat;
  background-size: 60px;
  animation: pw-iv-upload-loading 1s steps(1) infinite;
}
.pw-iv .ai-image-to-video-panel-content .add-video.uploading-file-box .uploading-info {
  font-weight: 400; font-size: 12px; line-height: 24px;
  color: var(--pw-text-color-1);
}
/* 进度条：260×7、紫填充 / 灰底，照参考站 a-progress 的参数（:stroke-width="7"、
   填充 --pw-bg-color-5、底 --pw-bg-color-2），**条内不嵌数字** —— 百分比只在上面那句文案里。
   max-width:100% 是给窄栏兜底的：面板宽度小于 260 时不让它撑破框。 */
.pw-iv .ai-image-to-video-panel-content .add-video.uploading-file-box .uploading-bar {
  width: 260px; max-width: 100%; height: 7px;
  border-radius: 4px;
  background: var(--pw-bg-color-2);
  overflow: hidden;
}
.pw-iv .ai-image-to-video-panel-content .add-video.uploading-file-box .uploading-bar-fill {
  height: 100%;
  border-radius: 4px;
  background: var(--pw-bg-color-5);
  transition: width .2s linear;
}
/* 25 个停靠点（i = 0..24），间距 i*100/24 —— 照 loading.less 那段 mixin 的展开结果
   （`@i: 0` 起、条件 `@i <= @total-frames` 即 24，所以是 total+1 = 25 个）逐条写死。
   ⚠️ 最后那条（100% ↔ -1512px）已经越过缩放后整图的下边界（60×1512），那一瞬间没有像素可画。
   这是 mixin 的 `<=` 多展开了一帧，**参考站自己也是这样**，不是这里写错。
   steps(1) 下它只在 100% 这一个时间点上生效、随即回绕到第 0 帧，所以肉眼看不见；
   留着它是为了将来跟参考站的展开结果**逐条对齐**时不会差一帧。
   真正会渲染的是第 0..23 帧，偏移量就是 -(i*63)。首帧写 `0 0px` 而不是 `0 0`，
   与 .common-dark-loading 那一列保持同一形态。 */
@keyframes pw-iv-upload-loading {
  0%       { background-position: 0 0px; }
  4.1667%  { background-position: 0 -63px; }
  8.3333%  { background-position: 0 -126px; }
  12.5%    { background-position: 0 -189px; }
  16.6667% { background-position: 0 -252px; }
  20.8333% { background-position: 0 -315px; }
  25%      { background-position: 0 -378px; }
  29.1667% { background-position: 0 -441px; }
  33.3333% { background-position: 0 -504px; }
  37.5%    { background-position: 0 -567px; }
  41.6667% { background-position: 0 -630px; }
  45.8333% { background-position: 0 -693px; }
  50%      { background-position: 0 -756px; }
  54.1667% { background-position: 0 -819px; }
  58.3333% { background-position: 0 -882px; }
  62.5%    { background-position: 0 -945px; }
  66.6667% { background-position: 0 -1008px; }
  70.8333% { background-position: 0 -1071px; }
  75%      { background-position: 0 -1134px; }
  79.1667% { background-position: 0 -1197px; }
  83.3333% { background-position: 0 -1260px; }
  87.5%    { background-position: 0 -1323px; }
  91.6667% { background-position: 0 -1386px; }
  95.8333% { background-position: 0 -1449px; }
  100%     { background-position: 0 -1512px; }
}

/* 上传失败（= 参考站 .add-video.error-box 里内联了 AiErrorDialog）。
   参考站在 :793-832 把那个弹窗「折进盒子」：去掉标题与关闭钮、插画缩到 60px、
   文案 12px、按钮 124×24 —— 这里做的是同一件事，只是改用本组件历史卡片失败态
   现成的那两个类名（.error-img / .error-info），图标资源也是同一个
   task_processing_failed.svg。
   ⚠️ 边框**不覆盖**：参考站这个盒子只挂 .add-video + .error-box 两个类，
   没挂 .error，所以虚线边框与颜色保持 .add-video 的默认值 —— 这是有意的，别顺手改成实线。 */
.pw-iv .ai-image-to-video-panel-content .add-video.error-box {
  padding: 12px;
  cursor: default;
  gap: 8px;
  text-align: center;
}
.pw-iv .ai-image-to-video-panel-content .add-video.error-box .error-img {
  width: 60px;
  color: var(--pw-svg-img-to-video-error-color);
}
.pw-iv .ai-image-to-video-panel-content .add-video.error-box .error-info {
  font-weight: 400; font-size: 12px; line-height: 22px;
  color: var(--pw-text-color-3);
}
.pw-iv .ai-image-to-video-panel-content .add-video.error-box .card-button-box {
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap;
  gap: 8px;
}
/* 按钮：照参考站 .error-box 那条覆盖（弹窗默认 32 高 / 16px，盒子里压到 24 高 / 12px）。
   ⚠️ 这一段**必须整套重来**、不能指望 §7 那条通用 .pw-button —— 它的选择器只覆盖
   .crop-button-box 与 .pw-iv-hist-card 两处，图片区这里的按钮**不在其中**。
   少写哪条，按钮就是一个没底色、没圆角、没内边距的裸 <button>。 */
.pw-iv .ai-image-to-video-panel-content .add-video.error-box .card-button-box .pw-button {
  display: flex; align-items: center; justify-content: center;
  width: 124px; height: 24px; padding: 0 8px;
  border-radius: 50px;
  font-size: 12px; line-height: 18px;
  color: var(--pw-button-text-color-1);
  cursor: pointer;
  box-sizing: border-box;
}
.pw-iv .ai-image-to-video-panel-content .add-video.error-box .card-button-box .pw-button.primary {
  background: var(--pw--button-primary-bg);
}
.pw-iv .ai-image-to-video-panel-content .add-video.error-box .card-button-box .pw-button.white-border {
  border: 1px solid var(--pw--button-white-border);
  background: var(--pw--button-white-border-bg);
}
@media (hover: hover) and (pointer: fine) {
  .pw-iv .ai-image-to-video-panel-content .add-video.error-box .card-button-box .pw-button.primary:hover {
    background: var(--pw-btn-primary-bg-h);
  }
}

/* 已选图片框（单图） */
.pw-iv .ai-image-to-video-panel-content .exist-img-box {
  border-radius: 16px;
  height: 170px;
  overflow: hidden;
  border: 2px dashed var(--pw-upload-drop-content-border);
  background-color: black;
  position: relative;
}
.pw-iv .ai-image-to-video-panel-content .exist-img-box img {
  position: absolute;
  object-fit: contain;
  object-position: center;
  width: 100%;
  height: 100%;
}

/* ⚠️ 这里**没有**「检测未通过」的失败蒙层：内容检测不过（违规 / 检测异常）时图是**整个撤掉**的，
   槽位回到空态（见 pw-iv.js 的 _startImageUpload），所以 .exist-img-box 里出现的图一定是验过的。 */

/* 悬浮工具（替换 / 裁剪 / 删除） */
.pw-iv .ai-image-to-video-panel-content .tool-box {
  position: absolute;
  display: flex;
  align-items: center;
  right: 8px;
  top: 8px;
  gap: 4px;
  z-index: 2;
}
.pw-iv .ai-image-to-video-panel-content .tool-box .tool-item {
  display: flex;
  align-items: center;
  width: 24px;
  justify-content: center;
  height: 24px;
  background: var(--pw-panel-enhance-video-tool-bg);
  border-radius: 4px;
  border: 1px solid var(--pw-panel-enhance-video-tool-border-color);
  color: white;
  font-size: 16px;
  cursor: pointer;
}
/* .tool-item 自带 font-size:16px（参考 less:884），图标直接继承 */

/* 提示词字段标题 + 翻译开关 */
.pw-iv .ai-image-to-video-panel-content .prompt-text {
  font-size: 14px;
  color: var(--pw-text-color-1);
  line-height: 22px;
  margin: 20px 0 12px;
}
/* 文生档没有图片区，.prompt-text 直接跟在 tab 条后面：它自带的 20px 上边距会叠上
   tab 条的 14px 下边距变成 34px，比图生档 tab→*图片 的 14px 松一大截。
   只在**紧邻 tab 条**时把上边距收掉；图生档里它跟在图片区之后，仍是原来的 20px。 */
.pw-iv .ai-image-to-video-panel-content > .ai-image-to-video-panel-tab + .prompt-text {
  margin-top: 6px;
}
.pw-iv .ai-image-to-video-panel-content .negative-box {
  display: flex;
  align-items: center;
  width: 100%;
  margin-bottom: 8px;
  justify-content: space-between;
}
.pw-iv .ai-image-to-video-panel-content .negative-box .translate-box {
  display: flex;
  align-items: center;
  gap: 4px;
  font-weight: 400;
  font-size: 12px;
  color: var(--pw-text-color-4);
  line-height: 16px;
}

/* switch（参考站为 Arco .arco-switch，尺寸/配色照搬） */
.pw-iv .pw-iv-switch {
  width: 30px;
  height: 16px;
  background: rgba(126, 128, 143, 0.4);
  border-radius: 15px;
  min-width: unset;
  position: relative;
  cursor: pointer;
  transition: background-color .2s;
}
.pw-iv .pw-iv-switch::after {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--pw-bg-color-15);
  transition: left .2s;
}
.pw-iv .pw-iv-switch.is-checked { background-color: var(--pw-bg-color-5); }
.pw-iv .pw-iv-switch.is-checked::after { left: calc(100% - 16px); }

/* 文本域容器 */
.pw-iv .ai-image-to-video-panel-content .prompt-textarea-content {
  position: relative;
  margin-top: 8px;
  height: 200px;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid var(--pw-border-color-1);
  margin-bottom: 10px;
}
.pw-iv .ai-image-to-video-panel-content .prompt-textarea-content.error {
  border-color: var(--pw-text-color-3);
}
.pw-iv .ai-image-to-video-panel-content .prompt-textarea-content .prompt-limit-text {
  position: absolute;
  font-size: 12px;
  color: var(--pw-text-color-5);
  line-height: 20px;
  right: 14px;
  bottom: 12px;
}
.pw-iv .ai-image-to-video-panel-content .prompt-textarea-content .prompt-limit-text-error {
  color: var(--pw-text-color-3);
}
.pw-iv .ai-image-to-video-panel-content .prompt-textarea {
  width: calc(100% - 4px);
  height: 150px;
  background-color: transparent;
  padding: 0 14px 14px;
  border-radius: 12px;
  font-size: 12px;
  color: var(--pw-text-color-1);
  line-height: 20px;
  margin-top: 14px;
  border: 0;
}
.pw-iv .ai-image-to-video-panel-content .prompt-textarea::placeholder {
  color: var(--pw-text-color-5);
}
.pw-iv .ai-image-to-video-panel-content .prompt-limit-error {
  font-size: 12px;
  line-height: 20px;
  padding-top: 10px;
  right: 14px;
  bottom: 12px;
  color: var(--pw-text-color-3);
}

/* 模型提示文案 */
.pw-iv .video-effect-panel-image-tip {
  color: var(--pw-text-color-1);
  font-size: 12px;
  font-weight: 400;
  line-height: 20px;
  margin-top: 12px;
  opacity: .6;
}

/* =========================================================================
   4. 吸底按钮区（.button-box：sticky bottom 覆盖在滚动内容之上）
   ========================================================================= */
.pw-iv .button-box {
  display: flex;
  width: 100%;
  align-items: center;
  gap: 6px;
  padding: 14px 0;
  flex-direction: column;
  justify-content: space-between;
  position: sticky;
  z-index: 10;
  bottom: 0;
  background-color: var(--pw-bg-color-3);
  border-top: 1px solid var(--pw-panel-enhance-config-content-border);
}

/* 生成按钮（参考 .generate-button / PwButton） */
.pw-iv .generate-button {
  overflow: visible;
  position: relative;
  width: calc(100% - 16px);
  height: 44px;
  border-radius: 50px;
  background: var(--pw-grad);
  color: var(--pw-text-color-1);
  font-size: 16px;
  font-weight: 500;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: background .2s;
}
.pw-iv .generate-button:hover:not(:disabled) { background: var(--pw-grad-h); }
.pw-iv .generate-button:disabled { opacity: .6; cursor: not-allowed; }
.pw-iv .generate-button > .icomoon { font-size: 20px; }
.pw-iv .generate-button .credit-tip-box { display: flex; align-items: center; gap: 2px; font-size: 14px; }
.pw-iv .generate-button .credit-tip-box .icomoon { font-size: 20px; }
/* 实付价（font-weight 照抄参考的 .clone-btn-cost-value，video-cloner/index.vue:2141 附近）。
   font-size:16px 是产品指定的：参考站那个类不写字号、直接继承按钮的，我们这里写死 16px ——
   注意父级 .credit-tip-box 是 14px（照抄 .promotion-cost-value 的 font-size:14px），
   所以这一条是**覆盖**父级而不是继承，删掉就退回 14px 了。 */
.pw-iv .generate-button .credit-tip-box .credit-tip-value { font-weight: 500; font-size: 16px; }
/* 生成按钮上的 VIP 小标（照抄 image_text_to_video.less:1064 的 .vip-btn-tag）。
   我们自己加的 .generate-button 是 flex + gap:6px，margin-left:4px 是在这个 gap 之上再顶开一点，
   跟参考站里的观感一致（参考站那个按钮的间距由 PwButton 内部决定）。 */
.pw-iv .vip-btn-tag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 1px 5px;
  border-radius: 4px;
  background: linear-gradient(135deg, #FFD581, #FFBC42);
  color: #000;
  font-size: 10px;
  font-weight: 400;
  line-height: 14px;
  margin-left: 4px;
}

/* =========================================================================
   5. AiModelConfigSelector 吸底条（逐条移植 components/ai-model-config/AiModelConfigSelector.vue）
   ========================================================================= */
.pw-iv .ai-model-config-selector {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 0 0 17px;
  width: 100%;
  padding: 0 8px;
}
.pw-iv .ai-model-config-selector .selector-left { flex: 1; min-width: 0; }
.pw-iv .ai-model-config-selector .selector-right { flex-shrink: 0; }
/* 锁定态（只有一个模型，模型 trigger 整块不渲染，见 JS 的 locked 分支）：这一条只剩配置
   一项，**配置 trigger 拉满整行** —— 三个参数照旧靠左，下拉箭头用 margin-left:auto 顶到
   最右。若不做这件事，selector-left 那个 flex:1 的空容器会把右边的 trigger 顶到最右、
   左边留一大截空白，看着像「少了一个控件」。
   类由 renderPanelFoot 在 modelTrig 为空时挂上。这几条写在基础规则**之后**是有意的：
   与上面两条同特异度（0,3,0），靠源码顺序赢；`.config-chevron` 那条多一层是 0,4,0，
   稳过 `margin-left:12px`。`.pw-iv *` 是 border-box，所以 width:100% 含左右 padding。 */
.pw-iv .ai-model-config-selector--cfg-only .selector-left { display: none; }
.pw-iv .ai-model-config-selector--cfg-only .selector-right { flex: 1; min-width: 0; }
.pw-iv .ai-model-config-selector--cfg-only .config-trigger { width: 100%; }
.pw-iv .ai-model-config-selector--cfg-only .config-trigger .config-chevron { margin-left: auto; }

/* —— 模型 trigger：.model-option-item.model-trigger-simple（同时受 arco_dropdown.less 的
      `.model-type-box .model-option-item` 规则影响，这里把两边合并成一条） ——
   注意在参考站里它**不是** .config-trigger 那套：底色/描边都取自 .model-option-item。
   padding 用 !important 是照抄参考：`.model-trigger-simple{padding:0 8px!important}` 与
   `.model-type-box .model-option-item{padding:8px 10px}` 特异度相同，靠 !important 定胜负，
   否则 trigger 会被撑到 38px（内容 22px + 上下各 8px），比参考的 36px 高一截。
   描边同理：`.model-trigger-simple{border:1px solid var(--pw-bg-color-2)}` 在参考里
   因为排在 arco_dropdown.less 之后而赢过 `.model-option-item` 的 transparent。
   **底色与描边因此不写在这条规则里** —— 本文件把 trigger 放在第 5 节、档位 `.model-option-item`
   放在第 6 节，两节顺序与参考相反，同特异度（0,2,0）下后写的赢，写在这里会被档位那条的
   `transparent` 盖掉（实测过：桌面 trigger 曾经完全没有底色）。这两条挪到档位规则之后，
   见 `.model-option-item` 下方那段注释。 */
.pw-iv .model-trigger-simple {
  overflow: hidden;
  width: 100%;
  min-height: 36px;
  padding: 0 8px !important;
  border-radius: 6px;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  transition: all .3s;
  color: var(--pw-text-color-1);
  cursor: pointer;
  user-select: none;
}
.pw-iv .model-trigger-simple:hover { background: var(--pw-bg-color-2); }
/* 空档（这一档的 ml 没请求到 / 该分类下没有模型）：文案是「没有可用模型」，
   但**必须能点**（点开弹层里是 .empty-model-tip），所以只弱化配色，不动交互。
   （另有一种「只有一个模型」的形态 —— 页面 URL 指定了单个模型，JS 的 lockModel ——
    那种**整块不渲染**，所以这里没有、也不需要对应的类。） */
.pw-iv .model-trigger-simple.pw-iv-model-empty { cursor: pointer; }
.pw-iv .model-trigger-simple.pw-iv-model-empty .model-trigger-name { color: var(--pw-text-color-5); }
.pw-iv .model-trigger-simple > .icomoon {
  flex: 0 0 auto;
  font-size: 16px;
  color: var(--pw-text-color-1);
  transition: transform .2s ease;
}
/* 展开态：背景 + 高亮描边（.model-option-item-active） */
.pw-iv .model-trigger-simple.model-option-item-active {
  background: var(--pw-bg-color-2);
  border: 1px solid var(--pw-text-color-2);
}
.pw-iv .model-trigger-name {
  font-size: 14px;
  font-weight: 400;
  line-height: 22px;
  color: var(--pw-text-color-1);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

/* —— 配置 trigger —— */
.pw-iv .config-trigger {
  display: flex;
  align-items: center;
  gap: 4px;
  height: 36px;
  padding: 0 12px;
  border-radius: 6px;
  border: 1px solid var(--pw-bg-color-2);
  background: var(--pw-bg-color-2);
  cursor: pointer;
  font-size: 14px;
  font-weight: 400;
  color: var(--pw-text-color-1);
  white-space: nowrap;
  user-select: none;
  transition: border-color .2s ease;
}
.pw-iv .config-trigger .config-separator { color: rgba(255, 255, 255, .2); font-weight: 400; margin: 0 2px; }
/* 参考给 .ratio-value 加了 uppercase，但那样 Auto 档会被渲染成 "AUTO"；
   产品侧要的是「Auto」（只 A 大写），所以这里显式 none（比例档位值都是数字，如 16:9，本就不受影响）。
   写 none 而不是删规则，是为了挡住宿主主题可能泄漏进来的 text-transform。
   **别推广到 .config-value**：时长会被写成 "5S"、
   分辨率 "720P" 虽无变化，但时长的大小写是肉眼可见的差异。 */
.pw-iv .config-trigger .ratio-value { text-transform: none; }
.pw-iv .config-trigger .config-chevron {
  font-size: 16px;
  color: var(--pw-text-color-1);
  margin-left: 12px;
  transition: transform .2s ease;
}
.pw-iv .config-trigger.config-trigger-active { border-color: var(--pw-panel-enhance-config-border-active) !important; }

/* —— 配置加载骨架（mount({loading:true}) → inst.setTabs() 之前）——
   形态照参考站 ai-image-to-video/index.vue 的 <a-skeleton :animation="true">：
   一个 30×30 的 shape + 一条 line（参考站那一条是 76px 的模型卡片，本组件的
   吸底条是 36px，高度按本组件走）。配色与扫光照抄 image_text_to_video.less /
   base.less 的 :deep(.arco-skeleton-*)：渐变 --pw-bg-color-4 → --pw-bg-color-3、
   background-size 400% 100%；关键帧与 Arco 的 arco-skeleton-circle 完全一致
   （1.5s cubic-bezier(0,0,1,1)，background-position 100% → 0）。
   骨架块自己带 trigger 同款底色与描边，加载完成时吸底条高度不变，不会跳一下。 */
.pw-iv .pw-iv-skeleton-bar { align-items: stretch; }
.pw-iv .pw-iv-skeleton-model,
.pw-iv .pw-iv-skeleton-config {
  display: flex;
  align-items: center;
  height: 36px;
  border-radius: 6px;
  border: 1px solid var(--pw-bg-color-2);
  background: var(--pw-bg-color-2);
}
.pw-iv .pw-iv-skeleton-model { width: 100%; padding: 0 8px; }
.pw-iv .pw-iv-skeleton-config { padding: 0 12px; gap: 8px; }
.pw-iv .pw-iv-skeleton-shape,
.pw-iv .pw-iv-skeleton-line {
  display: block;
  flex: 0 0 auto;
  border-radius: 4px;
  background: linear-gradient(90deg, var(--pw-bg-color-4) 25%, var(--pw-bg-color-3) 37%, var(--pw-bg-color-3) 63%);
  background-size: 400% 100%;
  animation: pw-iv-skeleton-circle 1.5s cubic-bezier(0, 0, 1, 1) infinite;
}
.pw-iv .pw-iv-skeleton-shape { width: 30px; height: 30px; }
.pw-iv .pw-iv-skeleton-line { height: 14px; }
.pw-iv .pw-iv-skeleton-line--model { flex: 1; min-width: 0; margin-left: 12px; }
.pw-iv .pw-iv-skeleton-line--cfg { width: 34px; }
.pw-iv .pw-iv-skeleton-line--cfg-sm { width: 26px; }
@keyframes pw-iv-skeleton-circle {
  0% { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}

/* 模型标签（arco_dropdown.less .model-tag）：默认底色是**两层**渐变（第二层是兜底），
   hot/new/vip 各自覆盖。照抄自编译产物 entry-Ci19NTV2.css。 */
.pw-iv .model-tags { display: flex; gap: 8px; flex-wrap: wrap; }
.pw-iv .model-tag {
  flex: 0 0 auto;
  padding: 0 4px;
  border-radius: 4px;
  min-width: 30px;
  font-size: 10px;
  height: 14px;
  line-height: 14px;
  text-align: center;
  background: linear-gradient(107.69deg, #41ccff 9.98%, #5961ff 115.37%),
              linear-gradient(92.19deg, #4d5aff 0%, #8a53ff 64.38%, #f84eb4 131.17%);
  color: #fff;
  white-space: nowrap;
}
.pw-iv .model-tag.hot {
  background: linear-gradient(101.31deg, #ffa835 4.1%, #ff3535 100.14%),
              linear-gradient(92.19deg, #4d5aff 0%, #8a53ff 64.38%, #f84eb4 131.17%);
}
.pw-iv .model-tag.new {
  background: linear-gradient(107.69deg, #41ccff 9.98%, #5961ff 115.37%),
              linear-gradient(92.19deg, #4d5aff 0%, #8a53ff 64.38%, #f84eb4 131.17%);
}
.pw-iv .model-tag.vip {
  background: radial-gradient(56.77% 136.36% at 50% -18.18%, #ffb525 0%, rgba(255, 210, 81, 0) 100%),
              radial-gradient(61.19% 55.13% at 49.79% 97.14%, #ffffff 0%, rgba(255, 255, 255, 0) 100%),
              radial-gradient(34.01% 43.94% at 49.79% 100%, #ffffff 0%, rgba(255, 255, 255, 0) 100%),
              radial-gradient(55.18% 26.3% at 50.41% 96.43%, #ffffff 0%, rgba(255, 255, 255, 0) 100%),
              #ffd581;
  color: #26272f;
}

/* =========================================================================
   6. 弹层（dropdown：挂在 .panel-content 内、贴吸底条向上展开）
   -------------------------------------------------------------------------
   面板 overflow:hidden 且 sticky，弹层挂到面板外会随页面滚走，故挂面板内，
   由 JS 按可用高度设 max-height（见 _placePop）。
   参考站这两个 dropdown 的**弹层外壳**（宽 344 / padding 6 / radius 8 / 描边+m底色）
   由 arco 的 .arco-trigger-popup-wrapper 提供，这里落到 .model-select-pop 上。
   ========================================================================= */
.pw-iv .model-select-pop {
  position: absolute;
  z-index: 1000;
  left: 10px;
  bottom: calc(100% - 4px);   /* 兜底，JS 会按吸底条顶边精确定位 */
  overflow: hidden auto;
  /* 参考里这两个弹层的**外壳宽度都是 344**（arco 的 .arco-trigger-popup-wrapper）：
     模型是 `.model-type-dropdown .arco-trigger-popup-wrapper{width:344px;padding:6px}`
     配置是 `.config-dropdown .arco-trigger-popup-wrapper{width:344px;border-radius:12px}`。
     注意配置面板**不是** 360 宽 —— scoped 里的 `.config-panel{width:360px}` 被
     `.config-dropdown .arco-trigger-popup-wrapper .config-panel{width:100%}` 盖掉了，
     实际渲染宽 = 344 - 上下各 1px 边框 = 342。所以两边都用 344 才对得上。 */
  width: 344px;
  max-width: 100%;
  border: 1px solid var(--pw-bg-color-2);
  box-shadow: 0 1px 0 0 #333336;
  border-radius: 8px;
  padding: 6px;
  background: var(--pw-bg-color-1);
  animation: pw-iv-pop-in .12s ease;
}

/* —— 模型分类面板（.model-category-panel） —— */
.pw-iv .model-category-panel { display: flex; width: 100%; flex-direction: column; }
.pw-iv .model-panel-title {
  border-bottom: 1px solid rgba(255, 255, 255, .2);
  padding: 4px 10px;
  font-size: 16px;
  line-height: 24px;
  font-weight: bold;
  color: var(--pw-text-color-1);
}
/* 右侧模型列表：可滚动、gap 4、自带细滚动条 */
.pw-iv .model-list-content {
  flex: 1;
  overflow-y: auto;
  padding: 8px 3px 0 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.pw-iv .model-list-content::-webkit-scrollbar { width: 4px; }
.pw-iv .model-list-content::-webkit-scrollbar-thumb { background: var(--pw-bg-color-2); border-radius: 2px; }

/* .model-option-item：**弹层里的档位**——透明底 + 透明描边，hover 才浮出 bg-color-2，
   选中态 bg-color-2 + 高亮描边（与参考站一致；产品也确认档位默认无底色）。
   模型 trigger 也带这个类，但它的底色/描边写在本条**之后**（见下方第二段），别在这里动。 */
.pw-iv .model-option-item {
  overflow: hidden;
  width: 100%;
  border-radius: 6px;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border: 1px solid transparent;
  transition: all .3s;
  padding: 8px 10px;
  background: transparent;
  color: var(--pw-text-color-1);
  cursor: pointer;
  font-size: 11px;
  font-weight: 400;
  line-height: 16px;
}
.pw-iv .model-option-item:hover { background: var(--pw-bg-color-2); border: 1px solid transparent; }
.pw-iv .model-option-item.model-option-item-active {
  background: var(--pw-bg-color-2);
  border: 1px solid var(--pw-text-color-2);
}

/* 模型 trigger 的底色与描边**只能写在这里**：参考站里
   `.model-trigger-simple{background:var(--pw-bg-color-2);border:1px solid var(--pw-bg-color-2)}`
   排在 arco 的 `.model-option-item` 之后，靠源码顺序赢下同特异度的两条；本文件把 trigger 放在
   第 5 节、档位放在第 6 节，顺序天然相反 —— 写在 trigger 那条里会被上面这两条盖掉
   （实测过：桌面 trigger 曾经完全没有底色、也没有描边）。挪到这里即与参考胜负一致。
   这里**不提特异度**是有意的：下面窄屏块的 `.model-trigger-simple{background:bg-color-3}`
   同样是 0,2,0 且更靠后，按源码顺序压过本条，窄屏才保得住「压深一档」；
   而展开态 `.model-trigger-simple.model-option-item-active` 是 0,3,0，不受影响照旧赢。 */
.pw-iv .model-trigger-simple {
  background: var(--pw-bg-color-2);
  border: 1px solid var(--pw-bg-color-2);
}
.pw-iv .model-option-item .model-info-box {
  width: 100%;
  padding-right: 8px;
  display: flex;
  gap: 2px;
  flex-direction: column;
  font-weight: 400;
  font-size: 11px;
  line-height: 16px;
  color: var(--pw-text-color-1);
  white-space: break-spaces;      /* 参考放在 box 上，两行文字都继承 */
  margin-left: 12px;              /* 参考有；trigger 里没有 .model-info-box，故写在通用规则里不外溢 */
}
.pw-iv .model-type-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pw-iv .model-option-item .model-type { font-size: 14px; line-height: 22px; color: var(--pw-text-color-1); }
.pw-iv .model-option-item .model-info {
  font-size: 12px;
  line-height: 16px;
  opacity: .8;
  margin-top: 4px;
}

/* —— 模型列表项的完整内容（参考 arco_dropdown.less 的
      `.model-type-dropdown, .model-type-box` 一节 + PwDiscountBadge.vue 的 scoped 块）——
   参考站的模型弹层 min-width:652、减去 200 的分类侧栏后列表列约 440px；
   本组件弹层固定 344、没有侧栏，列表项可用宽约 300px。所以这里是**内容对齐**：
   参考那套尺寸（57px 折扣角标、76px 最小高）在窄列里会换行，min-height 只是下限。 */

/* 档位本体：加高到 76 / 圆角 12 / padding 10（参考 `.model-type-box .model-option-item`）。
   **必须限定在 .model-list-content 里**：吸底条的模型 trigger 也带 .model-option-item，
   而 trigger 那条规则（第 5 节）与本文件第 6 节的档位规则同为 0,2,0、靠源码顺序决胜
   （见上面 trigger 一节与下方 `.model-trigger-simple` 那段的注释）。写成
   `.pw-iv .model-option-item` 会把 trigger 一并撑到 76px、圆角变 12 —— 它的 padding 有
   !important 躲得过，min-height 和 border-radius 躲不过（实测：trigger 由 36 变 76）。
   这里**只写这三个属性**：带上 background / border 会与下方 :hover、.model-option-item-active
   同分且位置更靠后，把 hover 与选中高亮一起盖掉，而三个 .mjs 检查全都测不出来。 */
.pw-iv .model-list-content .model-option-item {
  min-height: 76px;
  border-radius: 12px;
  padding: 10px;
}

/* 模型封面图（参考只给 width 与圆角）。cover_url 是接口给的绝对地址，不经 asset() 拼路径；
   徽标 PNG 才是走 asset() 的本地资源。 */
.pw-iv .model-img { flex: 0 0 auto; width: 24px; border-radius: 4px; }

/* 档位附赠信息：积分价 / Audio Support / 4K */
.pw-iv .model-extra-info { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
.pw-iv .model-extra-info .model-extra-item {
  display: flex;
  align-items: center;
  gap: 2px;
  font-size: 12px;
  line-height: 16px;
  padding: 0 6px;
  height: 18px;
  border-radius: 3px;
  color: var(--pw-text-color-1);
  background: #ffffff1a;          /* 参考硬编码，无对应的 --pw-* 变量 */
  white-space: nowrap;            /* 参考没有：我们这列更窄，不加会在固定 18px 高的 pill 里换行溢出 */
}
.pw-iv .model-extra-info .model-extra-item .icomoon { font-size: 16px; }

/* 限免提示条 */
.pw-iv .model-free-trial-tip {
  display: flex;
  align-items: center;
  width: 100%;
  height: 36px;
  padding: 0 10px;
  margin-top: 8px;
  border: 1px solid rgba(255, 213, 129, .5);
  background: rgba(255, 213, 129, .2);
  border-radius: 6px;
}
.pw-iv .model-free-trial-tip .icomoon { font-size: 20px; margin-right: 8px; color: #FFD581; flex-shrink: 0; }
.pw-iv .model-free-trial-tip .trial-text { font-size: 12px; font-weight: 400; color: #FFD581; }
.pw-iv .model-free-trial-tip .trial-count {
  font-size: 12px;
  font-weight: 400;
  color: #FFD581;
  margin-left: auto;
  white-space: nowrap;
}

/* 折扣角标（PwDiscountBadge.vue 的 scoped 块）。
   注意 PNG 本体是 228×56，宽高**都要给** —— 只给宽度会被 `.pw-iv img{max-width:100%}`
   放过，撑高整个档位。 */
.pw-iv .pw-discount-badge { display: inline-flex; align-items: center; z-index: 3; }
.pw-iv .pw-discount-badge .pw-discount-badge-icon { width: 57px; height: 14px; display: block; }
.pw-iv .pw-discount-badge .pw-discount-badge-text {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 67px;
  height: 20px;
  font-size: 12px;
  color: #fff;
  font-weight: bold;
  background: linear-gradient(129deg, #f84eb4 3%, #8a53ff 52%, #4d5aff 100%);
  border-radius: 3px;
}

/* VIP 蒙层（参考 `.model-option-item.has-vip-tag`）。
   蒙层常驻 DOM，靠 hover 才 opacity:1；父层 pointer-events:none、按钮自己 auto，
   所以非 hover 设备上它是个隐形但可点的区域 —— 两种路径都走同一个 _shouldShowVipOverlay
   判据、都调 onUpgrade，结果一致。 */
.pw-iv .model-option-item.has-vip-tag { position: relative; }
.pw-iv .model-option-item.has-vip-tag .vip-hover-overlay {
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, .01);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  border: 1px solid rgba(255, 255, 255, .2);
  border-radius: 12px;            /* 跟上面档位的新圆角对齐 */
  opacity: 0;
  transition: opacity 300ms;
  pointer-events: none;
}
.pw-iv .model-option-item.has-vip-tag .vip-purchase-btn {
  height: 36px;
  width: 160px;
  padding: 0 26px;
  border: none;
  border-radius: 50px;
  font-size: 14px;
  font-weight: 600;
  color: #26272f;
  cursor: pointer;
  background: radial-gradient(56.77% 136.36% at 50% -18.18%, #ffb525 0%, rgba(255, 210, 81, 0) 100%),
              radial-gradient(61.19% 55.13% at 49.79% 97.14%, #ffffff 0%, rgba(255, 255, 255, 0) 100%),
              radial-gradient(34.01% 43.94% at 49.79% 100%, #ffffff 0%, rgba(255, 255, 255, 0) 100%),
              radial-gradient(55.18% 26.3% at 50.41% 96.43%, #ffffff 0%, rgba(255, 255, 255, 0) 100%),
              #ffd581;
  box-shadow: inset 0 0 5px 1px rgba(248, 202, 110, .9);
  transition: opacity 200ms;
  pointer-events: auto;
}
.pw-iv .model-option-item.has-vip-tag .vip-purchase-btn:hover { opacity: .85; }
.pw-iv .model-option-item.has-vip-tag .vip-purchase-btn:active { opacity: .7; }
@media (hover: hover) and (pointer: fine) {
  .pw-iv .model-option-item.has-vip-tag:hover .vip-hover-overlay { opacity: 1; pointer-events: auto; }
}

.pw-iv .empty-model-tip {
  display: flex; align-items: center; justify-content: center;
  padding: 30px 12px;
  color: var(--pw-text-color-5);
  font-size: 13px;
}

/* 配置弹层 = arco 外壳（344 / 描边 #31333c / 圆角 12 / 硬阴影 0 1px #333336）
   + 内层 .config-panel（padding 17 / min-height 260 / 软阴影 0 4px 20px）。这里合成一个盒子。 */
.pw-iv .config-panel {
  position: absolute;
  z-index: 1001;
  right: 10px;
  bottom: calc(100% - 4px);   /* 兜底，JS 按吸底条顶边精确定位 */
  width: 344px;
  max-width: 100%;
  padding: 17px;
  min-height: 260px;
  background: var(--pw-bg-color-1);
  border: 1px solid #31333c;
  border-radius: 12px;
  box-shadow: 0 1px 0 0 #333336, 0 4px 20px rgba(0, 0, 0, .12);
  overflow-y: auto;
  animation: pw-iv-pop-in .12s ease;
}
@keyframes pw-iv-pop-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; } }

/* 配置弹层内部分节 */
.pw-iv .config-section { margin-top: 16px; }
.pw-iv .config-section:first-child { margin-top: 0; }
.pw-iv .config-section-title {
  font-size: 16px; font-weight: bold; line-height: 24px;
  color: var(--pw-text-color-1); padding-bottom: 8px;
}
.pw-iv .config-ratio-scroll-container {
  width: 100%;
  background: var(--pw-bg-color-3);
  border-radius: 8px;
  padding: 4px;
}
.pw-iv .config-ratio-list {
  display: flex; flex-wrap: nowrap; gap: 4px; align-items: flex-start;
  padding: 0;
  will-change: transform; transition: transform .3s ease;
}
/* 比例按钮：flex:1 等分（6 档时每档约 52px），尺寸由档数决定 —— 与参考完全一致。
   不要加 min-width / white-space:nowrap：参考没加，加了会让档数多时挤破容器。 */
.pw-iv .config-ratio-item {
  flex: 1;
  height: 50px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; padding: 0 8px;
  border-radius: 6px;
  border: 1px solid transparent;
  font-size: 14px; line-height: 22px;
  color: var(--pw-text-color-1);
  cursor: pointer;
  transition: all .15s ease;
}
/* 同上：弹层里的 Auto 档要显示 "Auto"，不做 uppercase（其余档位是数字，无差别） */
.pw-iv .config-ratio-item > span { text-transform: none; }
/* 比例图标是 icomoon 字体（icon-20_16_9_sp …），字号 20 与参考一致 */
.pw-iv .config-ratio-item .icomoon { font-size: 20px; }
.pw-iv .config-ratio-item:not(.config-ratio-item-active):hover {
  background-color: var(--pw-bg-color-2);
  color: var(--pw-text-color-1);
}
.pw-iv .config-ratio-item.config-ratio-item-active {
  background-color: var(--pw-bg-color-2);
  border: 1px solid var(--pw-text-color-2);
  color: var(--pw-text-color-2);
}
.pw-iv .config-option-list { display: flex; flex-wrap: wrap; gap: 16px; }
/* 基础态照抄参考：bg-color-2 + 2px 透明描边；分辨率列表再把它改成透明底 + 1px 描边。
   两层都要留着，否则单用 base 的其他列表会没底色。 */
.pw-iv .config-option-item {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  height: 36px;
  border-radius: 6px;
  border: 2px solid transparent;
  background: var(--pw-bg-color-2);
  font-size: 16px;
  color: var(--pw-text-color-1);
  white-space: nowrap;
  cursor: pointer;
  transition: all .15s ease;
}
.pw-iv .config-option-item > span { text-transform: uppercase; }
.pw-iv .config-option-list--resolution {
  background: var(--pw-bg-color-3);
  padding: 4px; border-radius: 6px;
  gap: 4px;
}
.pw-iv .config-option-list--resolution .config-option-item {
  flex: 1;
  min-width: calc(50% - 2px);
  background: transparent;
  gap: 4px;
  font-size: 14px;
  border: 1px solid var(--pw-bg-color-2);
}
/* 分辨率档位的换行排布：1 个占满整行、2 个左右平分、4 个 2×2 —— 这三档默认（flex:1 +
   min-width:calc(50% - 2px)）就是想要的效果，不动。
   **只有 3 个**时默认会把独占第二行的第 3 个用 flex:1 拉满整行（参考站也是这个表现），
   按产品要求改成半行宽、靠左，与第一行的两格左右对齐。
   选择器读作「列表恰好 3 个时取最后一个」：首个子项同时又是倒数第 3 个 ⟺ 总共 3 个。
   （不用 :has() 是为了不额外依赖它的支持度。）
   宽度 calc(50% - 2px)：百分比按容器的**内容盒**算，减去半个 4px 的 gap 才和第一行那两格等宽。 */
.pw-iv .config-option-list--resolution > .config-option-item:first-child:nth-last-child(3) ~ .config-option-item:last-child {
  flex: none;
  width: calc(50% - 2px);
}
.pw-iv .config-option-list--resolution .config-option-item:hover {
  background: var(--pw-bg-color-2);
  color: var(--pw-text-color-1);
}
.pw-iv .config-option-list--resolution .config-option-item.config-option-item-active {
  background: var(--pw-bg-color-2);
  border: 1px solid var(--pw-text-color-2);
}
/* 选中态的文字高亮：参考里这条是**独立规则**（不带 .config-option-list--resolution 前缀），
   所以分辨率列表里的选中项也是靠它拿到颜色。 */
.pw-iv .config-option-item.config-option-item-active { color: var(--pw-text-color-2); }

/* 时长档位（当前分辨率下只有 ≤3 个时长时用它替代滑条，见 pw-iv.js 的 _cfgPanelHtml）。
   几何与配色整份照抄分辨率那一节，好让同一个弹层里两节手感一致；唯独**不套用**
   「恰好 3 个时末位收半宽」那条排布规则 —— 时长最多 3 档，等分三格才是想要的。 */
.pw-iv .config-option-list--duration {
  background: var(--pw-bg-color-3);
  padding: 4px; border-radius: 6px;
  gap: 4px;
}
.pw-iv .config-option-list--duration .config-option-item {
  flex: 1;
  min-width: 0;
  background: transparent;
  font-size: 14px;
  border: 1px solid var(--pw-bg-color-2);
}
/* 基类的 `text-transform:uppercase` 会把 "5s" 变成 "5S"（分辨率的 "720P" 本来就没有小写，
   所以在那边看不出来）。与 .config-ratio-item > span 的 Auto 档同一个处理。 */
.pw-iv .config-option-list--duration .config-option-item > span { text-transform: none; }
.pw-iv .config-option-list--duration .config-option-item:hover {
  background: var(--pw-bg-color-2);
  color: var(--pw-text-color-1);
}
.pw-iv .config-option-list--duration .config-option-item.config-option-item-active {
  background: var(--pw-bg-color-2);
  border: 1px solid var(--pw-text-color-2);
}

/* 时长滑条 */
.pw-iv .duration-slider-wrapper { display: flex; align-items: center; gap: 12px; padding: 0; }
/* flex:1（= 1 1 0%）而不是 1 1 auto：滑条没有固有宽度，basis 0 才能稳稳占满剩余空间 */
.pw-iv .duration-slider {
  position: relative; flex: 1; height: 20px;
  cursor: pointer; user-select: none;
}
.pw-iv .duration-slider-rail,
.pw-iv .duration-slider-track {
  position: absolute; top: 50%; left: 0; height: 3px;
  transform: translateY(-50%); border-radius: 2px;
}
.pw-iv .duration-slider-rail { right: 0; background: #585a67; }
.pw-iv .duration-slider-track {
  width: 0;
  background: var(--pw-grad);
  transition: width .15s ease;
  pointer-events: none;
}
.pw-iv .duration-slider-thumb {
  position: absolute; top: 50%; left: 0;
  width: 18px; height: 18px; border-radius: 50%;
  transform: translate(-50%, -50%);
  background: #fff;
  box-shadow: 0 2px 6px rgba(138, 83, 255, .3);
  cursor: grab;
  z-index: 2;
  transition: left .15s ease, box-shadow .15s ease;
}
.pw-iv .duration-slider-thumb:hover { box-shadow: 0 2px 10px rgba(138, 83, 255, .5); }
.pw-iv .duration-slider-thumb:active { cursor: grabbing; box-shadow: 0 2px 12px rgba(138, 83, 255, .6); }
.pw-iv .duration-slider-label { font-size: 14px; white-space: nowrap; }

/* 运动幅度 Motion Range（配置弹层第四节，排在时长下方）——容器底色/圆角与档位的描边配色由产品指定：
   容器的 padding 4 + bg-color-3 + radius 8；档位默认描边用**容器同色**（不可见），
   选中时描边 + 文字亮成 text-color-2、底色换 bg-color-2（比容器底色亮一档，把选中档托出来）。
   产品未指定的几何量（36 行高、等分、4px 间隙）照抄分辨率那一节，
   免得同一个弹层里两节的档位手感不一致。 */
.pw-iv .config-motion-list {
  display: flex; align-items: center;
  gap: 4px;
  padding: 4px;
  border-radius: 8px;
  background: var(--pw-bg-color-3);
}
.pw-iv .config-motion-item {
  flex: 1;
  min-width: 0;
  display: flex; align-items: center; justify-content: center;
  height: 36px;
  padding: 0 8px;
  font-size: 14px;
  font-weight: 400;
  color: var(--pw-text-color-5);
  border: 1px solid var(--pw-bg-color-3);
  border-radius: 6px;
  white-space: nowrap;
  overflow: hidden;
  cursor: pointer;
  transition: all .15s ease;
}
/* hover / active 的先后照抄分辨率那一节：base → hover → active，
   优先级相同时靠源码顺序让选中态压住 hover。 */
.pw-iv .config-motion-item:hover {
  background: var(--pw-bg-color-2);
}
.pw-iv .config-motion-item.config-motion-item-active {
  color: var(--pw-text-color-2);
  border-color: var(--pw-text-color-2);
  background: var(--pw-bg-color-2);
}

/* 生成中菊花 */
.pw-iv .pw-iv-spin {
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, .3);
  border-top-color: #fff;
  animation: pw-iv-spin .8s linear infinite;
}
@keyframes pw-iv-spin { to { transform: rotate(360deg); } }

/* =========================================================================
   7. 右侧 Sample 区（组件自有）
   ========================================================================= */
.pw-iv .pw-iv-sample-page { height: 100%; padding: 20px; display: flex; flex-direction: column; }
.pw-iv .pw-iv-sample-title {
  display: flex; align-items: center; gap: 8px;
  font-size: 28px; line-height: 42px; font-weight: 700;
  color: var(--pw-text-color-1); margin-bottom: 8px;
}
.pw-iv .pw-iv-sample-box {
  flex: 1 1 auto; min-height: 0;
  position: relative;
  background: var(--pw-bg-color-1);
  border-radius: var(--pw-r-lg);
  overflow: hidden;
}
.pw-iv .pw-iv-sample-img,
.pw-iv .pw-iv-sample-video {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain;
}
.pw-iv .pw-iv-ov {
  position: absolute; inset: 0; z-index: 3;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  background: rgba(0, 0, 0, .55);
  color: var(--pw-text-color-1);
}
.pw-iv .pw-iv-ov b { font-size: 14px; font-weight: 500; }
.pw-iv .pw-iv-pbar { width: 62%; height: 6px; border-radius: 3px; background: rgba(0, 0, 0, .25); overflow: hidden; }
.pw-iv .pw-iv-pfill { height: 100%; border-radius: 3px; background: var(--pw-grad); width: 0; transition: width .3s; }
.pw-iv .pw-iv-pbar-txt { font-size: 13px; color: rgba(255, 255, 255, .9); }

/* ---------------------------------------------------------------------------
   历史卡片「生成中」那一态的遮罩 + 底部进度条
   （结构见 pw-iv.js 的 _histCard，整段照 AiImageTextToVideoProcessingCard.vue）
   --------------------------------------------------------------------------- */

/* `.content-layer` 的等价物（参考站 :158-165，那边还挂了工具类 flex-col-center）。
   ⚠️ 是**修饰类**不是改 .pw-iv-ov 本体：那个基类同时被右栏生成区（renderStage）用着，
   改基类会把那边的观感一起动掉（底色 .55 → .6）。
   `gap: 0` 也是**特意**的：参考站这一层没有 gap，.common-dark-loading 与 .brand-text
   之间的 5px 间距来自 .brand-text 自己的 margin-top；继承基类的 gap:10px 会让它变成 15px。
   z-index 留在基类的 3 上（不是参考站的 20）：见下面 .pw-iv-hist-blob 那段对层级的说明。
   user-select: none 照抄 —— 没有它，在遮罩上拖一下就把这段文案选蓝了。 */
.pw-iv .pw-iv-ov--proc {
  gap: 0;
  background: rgba(0, 0, 0, .6);
  user-select: none;
}

/* 品牌逐帧加载动画（参考站 loading.less:162-171 的 common-dark-loading）。
   精灵图 loading_dark.png 是 **466×2640** 的 2 倍图 —— 22 帧竖排，每帧 233×60 CSS px
   （60×22 = 1320 = 2640/2）。`background-size: 233px` 只写宽度、高度 auto，
   于是缩放后的整图正好 233×1320，第 i 帧的偏移量就是精确的 -(i*60)px，
   不会攒出半像素的模糊。声明 `background-size: 233px 1320px` 反而更脆 ——
   哪天换一张帧数不同的图，这里就得跟着改两个数。
   `steps(1)`：每帧之间**硬切**，不插值 —— 少了它背景位置会连续滑，
   看起来像图在滚动而不是逐帧动画。 */
.pw-iv .pw-iv-ov--proc .common-dark-loading {
  width: 233px;
  height: 60px;
  background-image: url('../images/loading/loading_dark.png');
  background-repeat: no-repeat;
  background-size: 233px;
  animation: pw-iv-common-dark-loading 1s steps(1) infinite;
}
/* 23 个停靠点（i = 0..22），百分比 = i*100/22 —— 照参考站 loading.less 里
   `@{i*100/22}% { background-position: 0 -(@i*60px) }` 那条 mixin 展开的结果，逐个写死。
   ⚠️ 最后一帧（100% ↔ -1320px）落在**第 0 帧上**（缩放后整图正好 1320 高，再往下没有像素），
   整段因此能无缝循环；改成 -1380px 会在每轮末尾闪一下空白。
   首帧写成 `0 0px` 而不是 `0 0`：mixin 里 i=0 展开出来是 `0 -0px`，两处**等价**，
   统一带单位是为了这一列 23 个值形态一致（测试也逐个比对 -i*60）。 */
@keyframes pw-iv-common-dark-loading {
  0%      { background-position: 0 0px; }
  4.5455% { background-position: 0 -60px; }
  9.0909% { background-position: 0 -120px; }
  13.6364% { background-position: 0 -180px; }
  18.1818% { background-position: 0 -240px; }
  22.7273% { background-position: 0 -300px; }
  27.2727% { background-position: 0 -360px; }
  31.8182% { background-position: 0 -420px; }
  36.3636% { background-position: 0 -480px; }
  40.9091% { background-position: 0 -540px; }
  45.4545% { background-position: 0 -600px; }
  50%     { background-position: 0 -660px; }
  54.5455% { background-position: 0 -720px; }
  59.0909% { background-position: 0 -780px; }
  63.6364% { background-position: 0 -840px; }
  68.1818% { background-position: 0 -900px; }
  72.7273% { background-position: 0 -960px; }
  77.2727% { background-position: 0 -1020px; }
  81.8182% { background-position: 0 -1080px; }
  86.3636% { background-position: 0 -1140px; }
  90.9091% { background-position: 0 -1200px; }
  95.4545% { background-position: 0 -1260px; }
  100%    { background-position: 0 -1320px; }
}

/* 说明文字（参考站 .brand-text:122-129）。宽度**写死 400px** 是照抄 ——
   这段文案本来就长，窄卡片里让它自己撑会顶出遮罩。窄屏档在下面收窄。 */
.pw-iv .pw-iv-ov--proc .brand-text {
  font-weight: 400;
  font-size: 14px;
  color: var(--pw-text-color-1);
  line-height: 22px;
  text-align: center;
  width: 400px;
  margin-top: 5px;
}
/* 文案里那个链到「我的创作」的 <a>（参考站 `#dy_myCre` 那条裸 ID 选择器，:390-393）。
   ⚠️ 这里**按结构选**（`.brand-text a`）而不是照搬 `#dy_myCre`：那个 id 是 i18n 串
   `aigc_creatTask_tip` 里带出来的，译者顺手改一下 id 或者哪天换一版文案，
   样式就**静默**掉了，而这颗链接是这段文案里唯一可点的东西。
   颜色 / 下划线照抄；cursor 不写 —— <a> 带 href，浏览器本来就给 pointer。 */
.pw-iv .pw-iv-ov--proc .brand-text a {
  color: var(--pw-text-color-2);
  text-decoration: underline;
}

/* 进度条整条**钉在卡片底边**（参考站 .bar-container:131-137）。
   ⚠️ 它是 .pw-iv-ov--proc 的**兄弟**，不能塞进遮罩里 —— 遮罩那层是居中 flex，
   塞进去会被拉回垂直居中，而参考站这条是在底边上的。z-index 30 压在遮罩（3）之上。 */
.pw-iv .pw-iv-hist-card .bar-container {
  position: absolute;
  bottom: 26px;
  left: 20px;
  width: calc(100% - 40px);
  z-index: 30;
  /* 参考站的 .bar-container / .progress-bar-container 都挂着工具类 flex-row-left
     （base.less:536：row + align-items:center + justify-content:flex-start）。
     组件里没有那套工具类，就地展开。宽度那一行也照抄，别改成 flex:1 ——
     右边那 40px 是留给 .progress-text 的，改成 flex:1 百分比会被挤到卡片外面。 */
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
}
.pw-iv .pw-iv-hist-card .progress-bar-container {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
  width: calc(100% - 40px);
  height: 10px;
  background: rgba(0, 0, 0, .25);
  z-index: 15;
  overflow: hidden;
  border-radius: 25px;
}
.pw-iv .pw-iv-hist-card .progress-bar {
  height: 100%;
  background: var(--pw-bg-color-5);
  /* 0.8s 的缓出：进度是**每秒**一格的估算值（frontendProgress），
     没有补间的话每一跳都是硬切。曲线照抄参考站。 */
  transition: width .8s cubic-bezier(0.4, 0, 0.2, 1);
  width: 0;
  border-radius: 25px;
}
.pw-iv .pw-iv-hist-card .progress-text {
  font-size: 14px;
  color: var(--pw-text-color-1);
  margin-left: 12px;
  /* 等宽数字：百分比每秒都在变，不定宽的话整条进度条会跟着左右抖。 */
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
  white-space: nowrap;
}
/* 窄屏档（参考站 `@media screen and (max-width:899px)`:355-371）。
   ⚠️ 写在 900px 而不是照抄 899：本文件其余各处（含 @container 那份）一律用 900，
   898/899/900 这三档差 1px 谁也看不出来，而同一个文件里并存两个只差 1px 的断点
   只会让人以为是笔误。留这条注释是为了下次比对参考站时不用再查一遍。 */
@media (max-width: 900px) {
  .pw-iv .pw-iv-ov--proc .brand-text { font-size: 12px; line-height: 16px; width: calc(100% - 28px); }
  .pw-iv .pw-iv-hist-card .progress-bar-container { width: calc(100% - 20px); height: 6px; }
  .pw-iv .pw-iv-hist-card .bar-container { bottom: 16px; left: 12px; width: calc(100% - 24px); }
  .pw-iv .pw-iv-hist-card .progress-text { font-size: 12px; }
}

/* 真实模式的失败态：沿用遮罩容器，错误色用全局的 --pw-text-color-3
   （与 :322 / :448 / :459 / :482 / Toast 一致）。
   这里刻意没有进度条 —— 空条或满条都会被读成「在跑 / 跑完了」。 */
.pw-iv .pw-iv-ov--err { background: rgba(0, 0, 0, .68); }
.pw-iv .pw-iv-err-msg {
  max-width: 82%; text-align: center; line-height: 1.5;
  color: var(--pw-text-color-3); word-break: break-word;
}
/* 重试按钮：生成区这条失败遮罩用的**不是** `.pw-button`（那个是 `size-32` 的胶囊，
   见下面 §7 末尾那段；历史卡片那边失败态用的就是它），而 `.generate-button` 是满宽 ——
   这里给生成区那条遮罩一个自己的小胶囊按钮。 */
.pw-iv .pw-iv-ov-btn {
  padding: 6px 18px; border: 1px solid var(--pw-text-color-2); border-radius: 50px;
  background: transparent; color: var(--pw-text-color-1); font-size: 13px;
  font-family: inherit; cursor: pointer; transition: background .2s, color .2s;
}
.pw-iv .pw-iv-ov-btn:hover { background: var(--pw-text-color-2); color: var(--pw-bg-color-1); }

/* `.pw-button` = 参考站 PwButton 的 `size-32`（见那个组件的 CSS）：这里把它拍平进一条规则。
   三处用它：裁剪弹窗的按钮组（§9）、历史卡片失败态里的「重试 / 立即购买 / 反馈」（§8）、
   提示词违规弹窗的底部两颗（§11）。
   ⚠️ 这条必须留在 **§7**、不能跟着裁剪那段放去 §9：历史卡片那边窄屏档（§8）要覆盖
   `height` / `font-size`，两条特异性相同（都是 4 个类），**媒体查询不加特异性** ——
   谁在后面谁赢。挪到 §9 就等于把 900px 那档的 124×24 / 12px 全部作废（界面上是
   窄屏时按钮还是 32px 高、文字还是 16px），而且没有任何报错。
   ⚠️ §11 的弹窗按钮同理：它要在这里拿到基础外观，尺寸（PC 240×44 / 窄屏 100%）由 §11 覆盖。 */
.pw-iv .crop-button-box .pw-button,
.pw-iv .prompt-process-footer .pw-button,
.pw-iv .pw-iv-hist-card .card-button-box .pw-button {
  display: flex; align-items: center; justify-content: center;
  min-width: 118px; height: 32px; padding: 0 25px;
  border-radius: 50px;
  font-size: 16px; line-height: 24px;
  color: var(--pw-button-text-color-1);
  cursor: pointer;
  box-sizing: border-box;
}
.pw-iv .crop-button-box .pw-button.primary,
.pw-iv .prompt-process-footer .pw-button.primary,
.pw-iv .pw-iv-hist-card .card-button-box .pw-button.primary { background: var(--pw--button-primary-bg); }
.pw-iv .crop-button-box .pw-button.white-border,
.pw-iv .prompt-process-footer .pw-button.white-border,
.pw-iv .pw-iv-hist-card .card-button-box .pw-button.white-border {
  border: 1px solid var(--pw--button-white-border);
  background: var(--pw--button-white-border-bg);
}
.pw-iv .crop-button-box .pw-button.primary:hover,
.pw-iv .prompt-process-footer .pw-button.primary:hover,
.pw-iv .pw-iv-hist-card .card-button-box .pw-button.primary:hover { background: var(--pw-btn-primary-bg-h); }

/* Toast —— **照参考站那条消息组件逐值搬过来**。
   参考站的消息链是 composables/useMessage.ts 的 showErrorMessage / showSuccessMessage
   → arco 的 `Message.info`，站点又用 assets/styles/arco-design/arco_message.less 盖了一层
   （底色/描边取自 assets/styles/theme.less:158-159 的 --message-error-*）。对照表：

     参考站                                         本组件（下面）
     .arco-message-list-top { top: 105px }          top: 105px（≤900px 55px）
     .arco-message-info { padding: 20px 40px }      padding: 20px 40px（≤900px 15px）
                          rgba(47,49,62,.8)         同值
                          1px 描边 rgba(219,217,227,.4)  同值
     .arco-message-content { font-size: 16px }      16px（≤900px 13px）
     .message-icon { font-size: 26px }              .pw-iv-t-icon 26px（≤900px 23px）
     .my-message-*-box .message-icon { color }      字色 #ff3a3e / #a984ff
   两处**故意不一样**：
     · 参考站一条消息是 `.arco-message-list` 下的 item（list 居中、item 靠 flex 排），
       本组件只有一条，所以直接 `left:50% + translateX(-50%)` 居中、并给
       `max-width: calc(100% - 20px)`（= 那个 list 的左右各 10px 内边距）。
     · 行高：参考站 `.arco-message { line-height: 1 }`，单行英文够用，但本组件那几句
       （71001 / 71003）比参考站长，窄屏折行后会挤在一起，所以给 1.4。
   ⚠️ 这几条**不能**写成 `.pw-iv .pw-iv-toast`：toast 是挂在 `document.body` 上的
   （见 js 的 toast() —— 它要相对**视口**定位，而 `.pw-iv` 是组件根元素、页面一滚就跟着走），
   根本不在 `.pw-iv` 里面。写成后代选择器等于一条都不生效，界面上是一个没有定位、
   没有底色、没有边框的裸 div，落在页面最底下 —— 表现成「点了删除什么都没有」。
   ⚠️ 同理它也拿不到 `.pw-iv` 上那套 `--pw-*`，下面每个值都是**字面量**（参考站那边也是
   字面量：底色/描边来自 theme.less 的 --message-error-*，在这里各带一份兜底没有意义）。
   **不**把整个变量块套到 toast 上是因为那块里还带着 `container-type: inline-size`：
   它会让 auto 宽度按「没有内容」算，布局宽度直接塌成 0，toast 会整个消失。 */
.pw-iv-toast {
  /* ⚠️ z-index **有意不照抄**：参考站那条消息列表是 1003，它上面只有 arco 自己的弹层；
     本组件自己的分享/下载弹层与移动端抽屉是 **1900**（参考站那一层本组件没有），照抄 1003
     会让「抽屉/弹层开着时弹的消息」被那层半透明蒙层盖住 —— 那样用户根本看不见提示。
     所以留在 2000（本组件原有的值），其余每一条都照参考站。 */
  position: fixed; z-index: 2000; left: 50%; transform: translateX(-50%); top: 105px;
  box-sizing: border-box; max-width: calc(100% - 20px);
  display: flex; align-items: center; text-align: center;
  padding: 20px 40px; border: 1px solid rgba(219, 217, 227, 0.4); border-radius: 4px;
  background: rgba(47, 49, 62, 0.8);
  font-size: 16px; line-height: 1.4;
  font-family: var(--pw-f, "Poppins", Arial, Helvetica, sans-serif);
  /* 一条消息里没有可点的东西（参考站那半颗「联系我们」按钮，检测这两句走的是
     showContact: false）—— 所以整条不吃指针，免得挡住底下的按钮。 */
  pointer-events: none;
}
/* 图标是**字形**不是字符（参考站那两档各带一颗 26px 的图标，不是 ! / ✓）。
   ⚠️ 码位只能**写死在这里**：上面「0. 图标」生成段是 `.pw-iv .icon-*` 作用域的，
   而 toast 在 `.pw-iv` 外面，一条都套不上。两个码位抄自 assets/icons/index.css
   （与参考站同一份字体）：icon-26_tips_information1 = \ea6d、icon-26_tips_success = \e972，
   docs/pw-iv-upload.check.mjs 里有一条把这里和字体原件对起来（改字体时漏改这里 = 一片空白方块）。 */
.pw-iv-toast .pw-iv-t-icon {
  font-family: 'icomoon' !important;
  font-style: normal; font-weight: normal; font-variant: normal;
  speak: never; text-transform: none; line-height: 1;
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
  font-size: 26px; margin-right: 12px;   /* 参考站 .arco-message-icon 的 margin-right: 12px */
}
.pw-iv-toast .pw-iv-t-icon:before { content: "\ea6d"; }        /* icon-26_tips_information1 */
.pw-iv-toast.is-ok .pw-iv-t-icon:before { content: "\e972"; }  /* icon-26_tips_success */
.pw-iv-toast .pw-iv-t-txt { flex: 1; }                         /* 参考站 .arco-message-content { flex: 1 } */
.pw-iv-toast.is-err .pw-iv-t-icon,
.pw-iv-toast.is-err .pw-iv-t-txt { color: #ff3a3e; }   /* 参考站 useMessage.ts 里写死的两档字色 */
.pw-iv-toast.is-ok .pw-iv-t-icon,
.pw-iv-toast.is-ok .pw-iv-t-txt { color: #a984ff; }
@media screen and (max-width: 900px) {
  .pw-iv-toast { top: 55px; padding: 15px; font-size: 13px; }
  .pw-iv-toast .pw-iv-t-icon { font-size: 23px; }
}

/* =========================================================================
   8. 右侧历史列表（登录成功后占据右侧那一列）
   -------------------------------------------------------------------------
   结构照参考站 layouts/content/ai-image-to-video/ImageToVideoHistoryContent.vue
   与 assets/styles/history_list.less:1-46：

     .ai-history-page > .ai-history-box > .scroll-box > (卡片… + .request-tip)

   但有几处**必须**和参考站写得不一样，改回去就会坏：

   1) 参考站的 `.ai-history-page` 是那层带头像/菜单的**整卡**（它自己的
      background: var(--pw-bg-color-2) + border-radius: 12px）。本组件里那个位置
      已经是 .pw-iv-stage（见 :190 的注释），所以那一条**整条不移植** ——
      移过来就是双层圆角背景。这里只留类名做结构对齐，样式由 .pw-iv-history 给。
   2) `.scroll-box` / `.request-tip` / `.end-list-box` 这几个名字太通用，宿主页面
      很可能有同名类，一律加 .pw-iv 前缀。
   3) 参考站 flag=2 的 `.end-list-box` 里除了「没有更多了」还挂着一颗
      `.all-creations-item`（「查看全部创作」，点击 `historyStore.goHistoryPage` 去
      `/video/history/`）。**这颗按钮本组件不移植** —— 本组件没有那个页面，
      出个点了不知道去哪里的按钮不如不出。所以 `.end-list-box` 里只有那句文案，
      `.all-creations-item` 的样式也**整条不存在**（别从参考站 history_list.less:48-64 抄回来）。
      底部四态（data-hist-flag 0/1/2/3）**照搬**参考站 ImageToVideoHistoryContent.vue:57-74：
      0 与 1 同一句「加载中…」、2 才是「没有更多了」、3 是「请求失败」。
   4) **高度链层层都要 min-height: 0**：
        .pw-iv-stage-body{height:100%} → .pw-iv-history{height:100%;flex column}
        → .ai-history-box{flex:1;min-height:0} → .scroll-box{flex:1;min-height:0;overflow-y:auto}
      flex 子项默认 min-height:auto，不肯收缩到内容以下 —— 漏掉任何一层，
      overflow-y:auto 都**永远不生效**（真实浏览器表现为整卡一直往下长、滚动条不出现
      → 滚到底永远不触发 → 分页彻底失效）。happy-dom 没有布局引擎，这条在无头测试里
      是测不出来的，只能读源文件断言（见 docs/pw-iv-history.check.mjs 的 [21]）。
   5) 处理中那一态的遮罩/进度条搬的是参考站**另一个**组件的结构
      （ImageToVideoHistoryItem.vue:32 在处理中渲染的 AiImageTextToVideoProcessingCard.vue，
      不是 Item 自己写的），三处名字/取值**必须**不一样，见各条自己的注释：
        · `.content-layer` → `.pw-iv-ov--proc`（修饰类，因为 .pw-iv-ov 基类右栏也在用）
        · `#dy_myCre`      → `.brand-text a`（那个 id 出自 i18n 串，按结构选更稳）
        · 899px 断点       → 900px（与本文件其余断点对齐）
      另有 z-index 全面下调（12/20/30 → 1/3/30，参考站那些层本组件没有），
      同样写在各自的注释里。
   ========================================================================= */
.pw-iv .pw-iv-history { height: 100%; display: flex; flex-direction: column; }
.pw-iv .pw-iv-history .ai-history-box {
  flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column; align-items: stretch;
}
.pw-iv .pw-iv-history .scroll-box {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 12px;
  padding: 20px;
}
/* 四态提示条（data-hist-flag = 0/1/2/3，口径见 js 的 _renderHistory）：
   0 / 1 「加载中…」、2 `.end-list-box`「没有更多了」、3 「请求失败」。
   属性与参考站 assets/styles/history_list.less:20-25 的 `.request-tip` 对齐 ——
   `display: flex` + `justify-content: center` + `text-align: center`，
   **颜色取 --pw-text-color-1**。⚠️ 这里原先写的是 --pw-text-color-5（60% 白），
   比参考站暗一档，本次对齐一并改回；字号 / 行高按参考站**不声明**（那条里没有），
   由 .pw-iv 根节点的 14px / 1.5 继承下来 —— 别再补 `font-size: 13px` 之类，
   那就又比参考站小一号了。`flex: none` 是本组件自己的（它是 .scroll-box 这个
   列向 flex 的子项，不能被压缩）。 */
.pw-iv .pw-iv-history .request-tip {
  flex: none;
  display: flex; align-items: center; justify-content: center;
  text-align: center; padding: 4px 0;
  color: var(--pw-text-color-1);
}
.pw-iv .pw-iv-history .end-list-box {
  flex: none;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 20px;
}

/* 卡片 = 参考站 ImageToVideoHistoryItem 的 .enhance-video-content：圆角 12 +
   --pw-bg-color-3 底 + 下间距 20。
   ⚠️ 参考站那张卡是**左右两栏**（左媒体盒 flex:3、右信息列 flex:1 min-width:420），
   本组件**右栏整块不渲染**，所以卡片是「媒体盒 → 底部动作条」的上下两条 ——
   别再照着参考站把 .video-result-content 改回 flex-direction:row。
   类名一律保留参考站原名，只靠 .pw-iv 作用域隔离 —— 对着参考站读代码能一眼对上。 */
.pw-iv .pw-iv-hist-card {
  flex: none;
  display: flex; flex-direction: column;
  margin-bottom: 20px;
  border-radius: var(--pw-r-lg);
  overflow: hidden;
  background: var(--pw-bg-color-3);
}
/* --processing / --failed 这两个修饰类**刻意没有默认样式**：参考站也不按状态给卡片染色，
   三态全靠媒体盒里的内容区分。留着是给宿主当钩子用的。 */

/* 卡片正文：**上下两条**（媒体盒 → 底部动作条）。
   参考站这里是左右两栏（媒体 + .enhance-result-video-box 信息列），本组件右栏整块
   不渲染（口径见 README 有意差异表），所以只剩媒体盒，方向也跟着从 row 改成 column。 */
.pw-iv .pw-iv-hist-card .video-result-content {
  display: flex; flex-direction: column;
  width: 100%; flex: 1; position: relative;
}
/* 媒体盒按**视频的原生比例**走：776 / 437，并且**不超过 776px 宽**。
   参考站在模板里还给了个 `height: enhanceVideo.height || 350px` 的行内样式，但那个值
   会被样式表里更靠后的 min/max-height 直接盖掉（同优先级、后者靠后）—— 实际生效的一直
   是固定值。所以本组件干脆**不接** width/height 两个字段。
   ⚠️ 也**不是**照搬参考站的高度。参考站给的是 `height:100%; min/max-height:440px`
   （外加 `flex:3`），那是因为它是**左右两栏**、媒体盒横向很宽，440px 固定高配 16:9 的
   片子基本填得满。本组件右栏整块不渲染、变成**上下两条**的单栏窄盒子，同样的 440px 会
   让盒子比画面高出一大截 —— 上下各留一条黑边，控制条也跟着浮在画面下方的空白里，
   而不是贴着画面底边（它是按盒子定位的，不是按画面）。
   所以改成 aspect-ratio：盒子高度由宽度推出来，画面永远正好填满，控制条永远贴边。

   `max-width: 776px` 是**上限**，窄了等比例缩：列宽够宽时盒子就停在 776×437，多出来的
   横向空间靠 `margin: 20px auto` 两边分掉（居中）。没有这个上限的话，超宽屏下列宽
   1200px 会把盒子撑到约 630px 高，卡片大得离谱。
   ⚠️ 宽度写成 `calc(100% - 40px)` 而不是省掉让 `align-items: stretch` 去拉：一旦横向
   margin 用了 `auto`，规范就不再做 stretch 对齐，此时 `width: auto` 会退化成
   hypothetic size（这个盒子的孩子全是绝对定位，算出来接近 0）—— 盒子会当场塌掉。
   显式给宽度 + auto 外边距，行为才是确定的。
   （`calc` 里的 40px = 左右各 20px 外边距；窄屏段跟着把外边距改成 8px，那里也要一起改。） */
.pw-iv .pw-iv-hist-card .origin-video-box {
  margin: 10px; border-radius: 12px; position: relative;
  width: calc(100% - 20px);
  max-height: 437px;
  aspect-ratio: 776 / 437;
  background: var(--pw-bg-color-4);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}

/* 媒体：视频与封面都 contain（别裁掉正在播的画面，也别让封面与视频的边对不上）。
   首帧图（处理中 / 失败铺底、完成态但没有视频地址时）仍然 cover —— 它填满更好认。 */
.pw-iv .pw-iv-hist-card .pw-iv-hist-video,
.pw-iv .pw-iv-hist-card .pw-iv-hist-poster,
.pw-iv .pw-iv-hist-card .pw-iv-hist-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
}
/* 完成态是「封面 <img> + 播放按钮」，点了才换成 <video>（见 _histPlay）。
   background 一律 **transparent**：内容按 contain 缩放，四周留白处露的是媒体盒自己的底色，
   video/img 自带的黑底或白底会在画面四周描出一圈突兀的框。 */
.pw-iv .pw-iv-hist-card .pw-iv-hist-video { object-fit: contain; background: transparent; border-radius: 0; }
/* 画面本身也是暂停/继续的点击面（`data-hist-act="toggle"`，见 _histCard 那段注释），
   不给个手型的话没人知道那里能点。 */
.pw-iv .pw-iv-hist-card .pw-iv-hist-video { cursor: pointer; }
/* 完成态的封面取的是 result.thumbnail，也就是结果视频自己的某一帧 —— 这里必须**跟着
   视频一起 contain**：用 cover 的话，点播放的那一下画面会因为裁切方式换了而**跳一下**。
   下面那条 .pw-iv-hist-img 是另一回事（处理中 / 失败的铺底首帧，没有「切换前后」要对齐）。 */
.pw-iv .pw-iv-hist-card .pw-iv-hist-poster { object-fit: contain; background: transparent; }
.pw-iv .pw-iv-hist-card .pw-iv-hist-img { object-fit: cover; }

/* 静态播放按钮：完成态默认形态里唯一可点的东西。
   z-index 2 —— 压过封面(0)与光斑(1)，但低于 .pw-iv-ov(3)：完成态本来就没有遮罩，
   这个值只是保证将来多一层东西时按钮不会跑到遮罩上面去。
   76×76 的圆形 + 38px 字形（保持 1:2，字形占圆的一半）—— 字号的单位是 px 不是 em，
   改上面的 width/height 时**字号要跟着改**，否则圆变大、字形不变，看着像一个空圈。 */
.pw-iv .pw-iv-hist-card .pw-iv-hist-play {
  position: absolute; z-index: 2;
  display: flex; align-items: center; justify-content: center;
  width: 76px; height: 76px; padding: 0; border: 0; border-radius: 50%;
  background: rgba(0, 0, 0, .55); color: #fff;
  font-size: 38px; line-height: 1; cursor: pointer;
  transition: background .2s;
}
/* hover **只让背景变深**，不做缩放：这张封面是整张卡片上最大的色块，
   在它正中间放大一个小圆，视觉上像是整块图在动 —— 而这里要表达的信息只有
   「可以点」这一条，变个底色就够了。
   ⚠️ 别把 scale 加回来：真机上「点播放的瞬间画面跳一下」和这里的放大是同一类
   没人会当成 bug 报上来的问题，而 transition 里留着 transform 又不写 scale
   就是一条死规则（本项目的检查专门盯这种）。 */
@media (hover: hover) {
  .pw-iv .pw-iv-hist-card .pw-iv-hist-play:hover {
    background: rgba(0, 0, 0, .75);
  }
}
/* 图标字形是居中排的，右下角自带一点视觉留白 —— 往右推 2px 才是光学居中。 */
.pw-iv .pw-iv-hist-card .pw-iv-hist-play > i { transform: translateX(2px); }

/* ---------------- 视频形态的控制条（`_histCtrl`） ----------------
   为什么不用 `<video controls>`：进度条要上品牌渐变，而原生控件是浏览器画的 UA
   shadow DOM，外面改不了 —— `::-webkit-media-controls-timeline` 只认 WebKit/Blink、
   还只能改整条轨道改不了「已播放段」的填充色；`::part(timeline)` 因为原生控件不
   export 任何 part 也拿不到。所以只能自己画一层。
   代价（有意取舍）：画中画 / 右键另存 / 原生全屏都没了。 */
.pw-iv .pw-iv-hist-card .pw-iv-hist-ctrl {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  display: flex; align-items: center; gap: 12px;
  padding: 24px 16px 12px;
  /* 上缘那道渐变是**底衬**，不是装饰：控制条直接压在视频画面上，白字碰到亮画面
     就读不出来了。用 transparent → 黑 遮一层，画面暗处看不出来、亮处压得住。 */
  background: linear-gradient(to top, rgba(0, 0, 0, .65), rgba(0, 0, 0, 0));
  color: #fff;
}
.pw-iv .pw-iv-hist-card .pw-iv-hist-ctrl-btn {
  flex: none;
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0; border: 0; border-radius: 50%;
  background: transparent; color: #fff;
  font-size: 22px; line-height: 1; cursor: pointer;
  transition: background .2s;
}
@media (hover: hover) {
  .pw-iv .pw-iv-hist-card .pw-iv-hist-ctrl-btn:hover { background: rgba(255, 255, 255, .2); }
}
.pw-iv .pw-iv-hist-card .pw-iv-hist-ctrl-btn:focus-visible,
.pw-iv .pw-iv-hist-card .pw-iv-hist-bar:focus-visible {
  outline: 2px solid #8A53FF; outline-offset: 2px;
}
/* 播放图标（icon-20_bf_sp）的留白偏左，暂停（icon-20_bf2_sp）是居中的 —— 只推播放那个。 */
.pw-iv .pw-iv-hist-card .pw-iv-hist-ctrl-btn > i {
  transform: translateX(1px);
}
.pw-iv .pw-iv-hist-card .pw-iv-hist-ctrl-btn > i.icon-20_bf2_sp { transform: none; }

/* 进度条。⚠️ 高度 20px 是**命中区**，不是视觉高度 —— 轨道本体只有 4px（::before 画的）。
   做成 4px 的话鼠标要精确到像素才点得中，触屏上更是没法用。 */
.pw-iv .pw-iv-hist-card .pw-iv-hist-bar {
  position: relative; flex: 1 1 auto; min-width: 0;
  height: 20px; cursor: pointer;
  /* 触屏上拖进度条别顺手把页面滚走 */
  touch-action: none;
}
.pw-iv .pw-iv-hist-card .pw-iv-hist-bar::before {
  content: ''; position: absolute; top: 50%; left: 5px; right: 5px;
  height: 4px; margin-top: -2px; border-radius: 999px;
  background: rgba(255, 255, 255, .3);
}
/* 填充层是**满宽**的，靠 clip-path 从左往右揭开 —— 不是给元素设 width。
   渐变要按整条轨道铺满：跟着元素宽度走的话，进度 5% 时那 5% 宽的条上会显示
   完整的蓝→紫→粉（渐变被压缩了），看着像已经播完。
   右边 5px 是给滑块留的行程，和 ::before 的左右内缩对齐。 */
.pw-iv .pw-iv-hist-card .pw-iv-hist-bar-fill {
  position: absolute; top: 50%; left: 5px; right: 5px;
  height: 4px; margin-top: -2px; border-radius: 999px;
  background: linear-gradient(129deg, #4D5AFF 0%, #8A53FF 47.8%, #F84EB4 97.4%);
  /* --pw-iv-progress 是 0~1 的无单位数（_histPaintCtrl 写的）。
     1 - 它 = 要从右边裁掉的占比；`round 999px` 让右端也是圆的。 */
  clip-path: inset(0 calc(100% * (1 - var(--pw-iv-progress, 0))) 0 0 round 999px);
}
.pw-iv .pw-iv-hist-card .pw-iv-hist-bar-thumb {
  position: absolute; top: 50%;
  /* ⚠️ 行程只能用 `left` 算，**不能用 translateX**：translateX 里的百分比是按
     元素**自身宽度**解析的（这里只有 10px），拿它算位移会算出个几乎不动的值。
     `left` 的百分比才是相对包含块（轨道）。两端各留 5px（滑块半径），
     这样 0% / 100% 时整个圆都在轨道范围内，不会探出去半个。 */
  left: calc(5px + (100% - 10px) * var(--pw-iv-progress, 0));
  width: 10px; height: 10px;
  margin: -5px 0 0 -5px;
  border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, .45);
  pointer-events: none;
}
.pw-iv .pw-iv-hist-card .pw-iv-hist-ctrl-time {
  flex: none; font-size: 12px; line-height: 1;
  /* 等宽数字。不写的话每秒字宽都变，整条控制条会跟着左右抖一下。 */
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
  white-space: nowrap;
}
/* 窄屏：控制条挤不下时把时间收起来，进度条优先 —— 它是这条控制条上唯一
   没法用别的方式替代的东西。 */
@media (max-width: 560px) {
  .pw-iv .pw-iv-hist-card .pw-iv-hist-ctrl { gap: 8px; padding: 20px 10px 8px; }
  .pw-iv .pw-iv-hist-card .pw-iv-hist-ctrl-time { display: none; }
}

/* 处理中态的两个流动光斑（照抄参考站 ProcessingCard 的 .blob / .blob-bl / .blob-tr）。
   ⚠️ 它**不是** .common-dark-loading 的替代品 —— 参考站这两样是**同时**出的
   （ProcessingCard.vue:13-14 是光斑，:19 才是精灵图动画），都铺在同一张卡片上。
   本组件先前只有光斑，是因为那张精灵图当时没搬进来（见 .common-dark-loading 那条，
   现在搬了，两个都在）。
   ⚠️ z-index **改成 1**（参考站是 12）。参考站那一层能站到 12，是因为它的进度条容器是
   15、文字层是 20、底部条是 30 —— 都压在光斑**之上**（封面 img 是 3，在光斑之下）。
   本组件没有这么多层：进度与失败共用**同一个** .pw-iv-ov（z-index 3），照抄 12 的话
   光斑会盖在进度条和百分比上面，正好把这一块唯一的信息糊掉。
   层次应当是 封面(0) < 光斑(1) < 控制条(2) < 遮罩(3) < 底部进度条(30) ——
   只就这张卡片的媒体盒而言（全站另有多处 z-index，不在此列的别去套）。 */
.pw-iv .pw-iv-hist-blob {
  position: absolute; width: 80%; height: 50%;
  filter: blur(100px); z-index: 1; pointer-events: none;
  background: linear-gradient(129deg, #4d5aff 0%, #f84eb4 97%);
  animation: pw-iv-intense-morph 3s infinite ease-in-out;
}
.pw-iv .pw-iv-hist-blob--bl { bottom: -35%; left: -20%; animation-delay: 0s; }
.pw-iv .pw-iv-hist-blob--tr {
  top: -35%; right: -20%; animation-delay: -5s;
  background: linear-gradient(129deg, #f84eb4 0%, #4d5aff 97%);
}
@keyframes pw-iv-intense-morph {
  0%   { border-radius: 50% 50% 40% 60% / 70% 60% 40% 30%; transform: scale(1);   opacity: .5; }
  50%  { border-radius: 45% 55% 50% 50% / 65% 55% 45% 35%; transform: scale(1.2); opacity: 1; }
  100% { border-radius: 50% 50% 40% 60% / 70% 60% 40% 30%; transform: scale(1);   opacity: .5; }
}

/* 失败态：结构照参考站 AiImageTextToVideoErrorCard.vue:10-29（由
   ImageToVideoHistoryItem.vue:36 在失败那一态渲染）。
   逐项对应见 pw-iv.js 的 _histCard —— 这里只说样式上的三件事：

   ① `.img-mask-box`（:10，`background: var(--pw-bg-color-9)` = rgba(0,0,0,.8)）
      **折进** `.pw-iv-ov--err` 的底色，不再单独出一个节点。
      ⚠️ 上面 §7 那条共用的 `.pw-iv-ov--err` 保持 rgba(0,0,0,.68) **不能动** ——
      生成区那条失败遮罩用的是同一个类，这一轮只改历史卡片（见 `.pw-iv-hist-card` 这条覆盖）。
   ② `.error-info-box`（:11）的 `padding: 0 16px` 搬到 `.pw-iv-ov--err` 上；
      参考站那个盒子是 `absolute + 50%/translate(-50%,-50%)` 自居中的，
      本组件的 `.pw-iv-ov` 基类已经是 `inset: 0` + 居中 flex，不必再套一层。
   ③ 参考站**没有**给这个盒子设 gap —— 图标与文案之间就是贴着的，间距全靠
      `.error-info` 的 `margin-bottom: 24px` 与按钮组自己的 gap 撑。所以这里 gap 归零
      （与处理中那张卡的 `.pw-iv-ov--proc` 同一个道理）。 */
.pw-iv .pw-iv-hist-card .pw-iv-ov--err {
  gap: 0;
  padding: 0 16px;
  background: var(--pw-bg-color-9);
}
/* 插画 120×126。⚠️ 这个 width 是**唯一**生效的样式：那条 color 是照抄参考站的，
   对多色 SVG 是死的（见变量块里的注释），照抄是为了两边读起来能对上。 */
.pw-iv .pw-iv-hist-card .pw-iv-ov--err .error-img {
  width: 120px;
  color: var(--pw-svg-img-to-video-error-color);
}
.pw-iv .pw-iv-hist-card .pw-iv-ov--err .error-info {
  font-weight: 400; font-size: 16px; line-height: 24px;
  color: var(--pw-text-color-3);
  margin-bottom: 24px;
}
/* NSFW 那一档换成白色（参考站 .nsfw-error-info）。
   ⚠️ 只对「插画 + 白字」的那批码成立，**错误码 7 不在内** —— 它文案是 NSFW 的，
   颜色却走普通那档。名单在 pw-iv.js 的 _histNsfw，别按文案归纳。 */
.pw-iv .pw-iv-hist-card .pw-iv-ov--err .error-info.nsfw-error-info {
  color: var(--pw-text-color-1);
}
/* 按钮组：竖排、居中。参考站写了两条 gap（先 32px 再 8px 32px），后一条生效 ——
   纵向 8px、横向 32px。本组件是竖排，所以实际起作用的是那个 8px。 */
.pw-iv .pw-iv-hist-card .card-button-box {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; flex-wrap: wrap;
  gap: 8px 32px;
}
.pw-iv .pw-iv-hist-card .card-button-box .card-button { width: 160px; }

/* 窄屏档（参考站 `@media screen and (max-width: 1280px)`:377-403）。
   ⚠️ 参考站那张卡用的是 **1280px**，而同一个文件里处理中那张卡用的是 899px ——
   它自己两张兄弟卡就不统一。本文件统一走 900px 这条阶梯（处理中态那轮就是这么办的），
   代价是 900~1280 之间插画按参考站本该已经缩到 60px 了，这里仍是 120px：
   那个区间在本组件里卡片本来就不宽，大图标反而更合适。 */
@media (max-width: 900px) {
  .pw-iv .pw-iv-hist-card .pw-iv-ov--err .error-img {
    width: 60px; height: 63px; margin-bottom: 0;
    color: var(--pw-svg-dialog-img-color);
  }
  .pw-iv .pw-iv-hist-card .pw-iv-ov--err .error-info {
    font-size: 14px; line-height: 22px; margin-bottom: 8px; padding: 0 8px;
  }
  .pw-iv .pw-iv-hist-card .card-button-box { gap: 12px; }
  .pw-iv .pw-iv-hist-card .card-button-box .card-button {
    width: 124px; height: 24px; font-size: 12px;
  }
}

/* 底部动作条。参考站把它放在**右栏**里；本组件右栏不渲染，它就跟到媒体盒下面。
   结构照参考站 HistoryShareMenu.vue：
     完成态 .history-share-menu-container（flex + space-between）
              ├ 左 .bottom-left-box：复制链接 / 分享 / 下载 / 删除，四个 30×30 **图标**按钮
              └ 右 .create-btn：「制作同款」
     失败态 只有左边一个孤零零的删除图标（**不包** .history-share-menu-container）
   处理中整条不出。钩子一个都没接时组件**整条不渲染**（见 pw-iv.js 的 _histCard），
   所以这里不必考虑「空条」的样子。

   ⚠️ 高度 52px，**不是**参考站的 64 → 54。参考站那条 54px 是**窄屏**的收缩值
   （媒体查询里的第二段），64 才是不缩的时候；本组件把基准定在 52 之后，54 > 52
   会让窄屏反而比宽屏更高 —— 那个收缩值随之失去意义，一并删掉了。
   高度只够装内容即可：.menu-item 自己就是 30px 高，.create-btn 是 36px，两个都能在
   52px 里居中（36 上下各留 8px），再加那条 1px 的内阴影分隔线正好。
   ⚠️ 别再补一个窄屏覆盖 —— 真要改高度就改这里一个数，别弄成两套。 */
.pw-iv .pw-iv-hist-card .video-result-bottom-box {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%; height: 52px; flex-shrink: 0; padding: 0 16px;
  margin-top: auto;
  box-shadow: inset 0 1px 0 0 rgba(255, 255, 255, .2);
}
/* 左块与「制作同款」之间的分组：width:100% 是为了把 space-between 撑满整条，
   否则容器只有内容宽，右端那颗按钮会贴到左块后面而不是贴到条的右边缘。
   ⚠️ 这里**没有** gap —— 参考站也没有。四个图标的间距是 .menu-item 各自 30px 宽排出来的，
   容器这条 gap 只管「左块」与「create-btn」之间那 12px。 */
.pw-iv .pw-iv-hist-card .history-share-menu-container {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; width: 100%;
}
.pw-iv .pw-iv-hist-card .bottom-left-box { display: flex; align-items: center; }
/* 30×30 的纯图标按钮（照参考站 .bottom-left-box .menu-item）。
   ⚠️ background / cursor / font 三条不能省：参考站那里是 <div>，本组件是 <button>，
   少了 background:transparent 每个图标背后会多出一块系统按钮灰底，
   少了 cursor:pointer 悬停时是箭头而不是手。 */
.pw-iv .pw-iv-hist-card .menu-item {
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 4px;
  border: 1px solid transparent; border-radius: 4px;
  background: transparent; color: var(--pw-text-color-1);
  font: inherit; line-height: 1; cursor: pointer;
}
/* 图标字号。⚠️ 选择器写 `.icomoon` 而不是 `.icon-img`：
   失败态那个删除图标照参考站**不带** icon-img（那边写作 `icomoon icon-16_hl_delete more-icon`），
   按 .icon-img 写会让它停在继承来的 14px，比完成态那四个小一圈，肉眼就能看出来。
   （完成态与失败态现在**画的是同一个字形** icon-16_hl_delete，差的只是这一串类名。） */
.pw-iv .pw-iv-hist-card .menu-item .icomoon { font-size: 20px; }
@media (hover: hover) and (pointer: fine) {
  .pw-iv .pw-iv-hist-card .menu-item:hover {
    border-color: rgba(255, 255, 255, .2); background: var(--pw-bg-color-9);
  }
}
/* 「制作同款」。数值全部照参考站的 .create-btn：36 高 / 圆角 27 / 内容最小 180 宽 /
   上下内阴影两道（那道「内发光」不是渐变的一部分，别漏）。
   ⚠️ margin-left:auto 不是多余的：它让这颗按钮**不管左边有几个图标都贴着右端**。
   光靠容器的 space-between 只在「左右两边都非空」时才成立，一旦哪天左边意外空了
   （比如完成态判定改坏），按钮会无声地滑到左端 —— auto 是那道防呆。 */
.pw-iv .pw-iv-hist-card .create-btn {
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; margin-left: auto;
  height: 36px; min-width: 180px; padding: 0 38px;
  border: none; border-radius: 27px; outline: none;
  background: var(--pw--button-primary-bg); color: var(--pw-text-color-1);
  font: inherit; font-size: 16px; font-weight: 700; cursor: pointer;
  box-shadow: inset 2px 2px 10px rgba(255, 255, 255, .25), inset -2px -2px 10px rgba(255, 255, 255, .25);
}
@media (hover: hover) and (pointer: fine) {
  .pw-iv .pw-iv-hist-card .create-btn:hover { background: var(--pw-btn-primary-bg-h); }
}
.pw-iv .pw-iv-hist-card .create-btn:active { background: var(--pw--button-primary-bg-a); }

/* ---------- 历史卡片的分享 / 下载浮层（组件自带，钩子不接时才出现） ----------
   参考站这两块是 arco 的 a-popover（teleport 到 body）+ PwDrawer（移动端）。
   本组件的做法见 pw-iv.js 的 _histPop / _histDrawer：
     · 桌面：.pw-iv-hpop —— `position: absolute`，挂在组件根元素 `.pw-iv` 内（不是 body）。
     · 移动端：.pw-iv-hdrawer-wrap —— 外壳显式铺满视口，面板在里面 `bottom: 0`，
       所以面板高度是**内容自适应**的（不用猜内容多高）。

   ⚠️ **挂 `.pw-iv` 内**（`this._appEl`）这件事，样式与坐标两头都指着它：
     · 样式：`--pw-*`、那套 reset、下面 `.pw-iv .pw-iv-hmenu*` 全是后代选择器，
       挂到外面一条都不生效（没底色、没行距、图标塌成 0×0）。
     · 坐标：`.pw-iv` 是 `position: relative`（本文件开头那条 `.pw-iv` 规则），absolute 后代
       以它的 padding box 为原点 —— JS 里那一份 `- rr.left / - rr.top` 就是这条的直接后果。
   ⚠️ 别把它跟宿主传给 `mount(el)` 的那个**挂载元素**混为一谈（js 里叫 `_root`）：
   `.pw-iv` 只是它的子节点。挂错一层，上面两条同时失效，而**无头检查脚本全绿** ——
   没有布局引擎，两个矩形都是全 0，减不减、正着减还是反着减，算出来都是 0。

   ⚠️ **弹层不能挂进卡片里。但卡住它的不是卡片那条 `overflow: hidden` —— 是列表那条
   `overflow-y: auto`（见上面 6 节前的 .scroll-box）。** 这条区别很要紧，写错了会让后来人
   往错误的方向改：CSS 的裁剪**只对有包含块关系的后代生效**，而 `.pw-iv-hist-card` 是
   `position: static` —— 它既不是弹层的包含块、也不在「弹层 → 它的包含块」这条链上，
   所以它那条 `overflow: hidden` **根本裁不到**一个挂在（定位过的）menu-item 里的绝对定位
   弹层。真正会裁的是**滚动容器**：把弹层挂进卡片，它的包含块就落到 `.scroll-box` 内部，
   于是它成了被滚动的内容 —— 既跟着滚动区一起被裁在可视边之外（卡片在列表底部时菜单被
   切掉半截），又会把滚动区撑高（悬停一下滚动条就变短）。
   挂在组件根元素 `.pw-iv` 下则两者都避开：根元素在滚动区**外面**，弹层不属于被滚动的内容。
   代价是列表自己滚动时它不自动跟手，得由 JS 重摆 —— 见 js 里的 _histPopFollow。 */
.pw-iv-hpop {
  position: absolute; z-index: 1900;
  min-width: 200px; padding: 8px 6px;
  background: var(--pw-bg-color-1);
  border: 1px solid rgba(47, 49, 62, .8);
  border-radius: 4px;
  box-shadow: var(--pw-pop-shadow);
  visibility: hidden;
  /* ⚠️ 上面这条 hidden 与 JS 里那句 `pop.style.visibility = 'visible'` 是**一对**，缺一不可。
     为什么 CSS 要先藏：弹层是先 append 进 DOM、再量尺寸、最后才摆位置（见 _histPop）。
     没有这条的话，从 append 到摆好之间会有一帧停在左上角 —— 屏幕上闪一下。
     为什么 JS 那边必须是**显式的 'visible'**：写成 `= ''` 不是「恢复可见」，而是把这条
     内联声明**删掉**，级联随即回落到本规则，弹层永远不显示。这个 bug 真发生过：
     DOM 里节点在、坐标也对，就是屏幕上什么都没有，表现成「点分享没有任何反应」。 */
  animation: pw-iv-drop-in .15s ease-out;
}
/* 下拉式展开：从按钮下面**掉**出来（-4px → 0）。
   ⚠️ 不复用 pw-iv-pop-in —— 那个是给吸底条上那两个**向上弹**的浮层用的（+4px → 0），
   方向正好相反；拿过来会让菜单从下面往上顶，与「挂在按钮下面」的锚点打架。 */
@keyframes pw-iv-drop-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; } }
/* 下面放不下、翻到按钮**上方**时（_histPop 里的 flip），方向跟着反过来。 */
.pw-iv-hpop.pw-iv-hpop-up { animation-name: pw-iv-pop-in; }
/* 弹层 / 抽屉里的一行。参考站是 `.share-menu`（分享）与 `.more-operation-item`（下载）
   两套几乎一样的规则，这里合成一套。
   ⚠️ 类名**没有**沿用参考站的 `.flex-row-left` / `.flex-row-right` —— 那是全局工具类，
   宿主题里极可能已经有同名规则，会倒灌进来把行布局改掉。`pw-iv-` 前缀在 WP 里不会撞。 */
.pw-iv .pw-iv-hmenu {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; padding: 5px 20px; border-radius: 4px; cursor: pointer;
}
@media (hover: hover) and (pointer: fine) {
  .pw-iv .pw-iv-hmenu:hover { background: var(--pw-bg-color-4); }
}
.pw-iv .pw-iv-hmenu-l { display: flex; align-items: center; min-width: 0; }
.pw-iv .pw-iv-hmenu-txt {
  font-size: 14px; font-weight: 400; line-height: 30px;
  color: var(--pw-text-color-1); white-space: nowrap;
}
/* 30×30 的品牌圆标（照参考站 .share-menu-icon），margin-right 也是那边的 12px */
.pw-iv .pw-iv-hmenu-img { width: 30px; height: 30px; margin-right: 12px; flex-shrink: 0; }
/* 下载那两行的图标是 icomoon 字形（不是图片），字号照参考站 .more-operation-item i 的 16px */
.pw-iv .pw-iv-hmenu-ico { font-size: 16px; margin-right: 8px; flex-shrink: 0; }
/* 行右侧的转圈。参考站是 .share-menu-loading（16×16，`rotate 1.5s infinite linear`） */
.pw-iv .pw-iv-rot { display: inline-block; animation: pw-iv-rotate 1.5s infinite linear; }
@keyframes pw-iv-rotate { to { transform: rotate(360deg); } }
.pw-iv .pw-iv-hide { display: none; }
/* 金色 VIP 徽章。数值照参考站 share.less 的 .vip-tag。
   ⚠️ 参考站那条写的是 `color: var(--pw-text-color-12)` —— 本组件**没有** --pw-text-color-12
   （主题变量只到 5），照抄会得到一条无效声明、文字颜色继承下去。这里用参考站同一个十六进制值。 */
.pw-iv .pw-iv-viptag {
  flex-shrink: 0; margin-left: 4px; height: 12px; min-width: 22px; padding: 0 4px;
  border-radius: 3px; background: #FFD581; color: #26272F;
  font-size: 10px; line-height: 14px; text-align: center;
}

/* 移动端抽屉的外壳：铺满**视口**。它是 .pw-iv 的 absolute 后代，原点是**组件根元素**
   `.pw-iv` 的 padding box —— 所以铺满视口这件事由 JS 把 `- rr.left / - rr.top` 减出来
   （`- rr` 是**负**的：根元素不在视口原点时，只有负偏移才能把原点挪回视口；
   见 _placeHistDrawer），`inset: 0` 只会铺满根元素本身。
   ⚠️ 外壳挂 `_appEl`（`.pw-iv`）而不是 `_root`（宿主的挂载元素）—— 与 .pw-iv-hpop 同一条纪律，
   见上面 § 桌面弹出层那段 ⚠️。
   遮罩在里面铺满外壳，面板贴外壳底边 —— 所以面板高度由内容决定。 */
.pw-iv-hdrawer-wrap { position: absolute; z-index: 1900; }
.pw-iv-hdrawer-mask { position: absolute; left: 0; top: 0; right: 0; bottom: 0; background: var(--pw-dialog-mask-color); }
.pw-iv-hdrawer {
  position: absolute; left: 0; right: 0; bottom: 0;
  max-height: 70%; overflow-y: auto;
  background: var(--pw-bg-color-1);
  border-radius: 16px 16px 0 0;    /* 照参考站 PwDrawer 的 position="bottom" */
  padding-bottom: 8px;
  animation: pw-iv-drawer-up .2s ease-out;
}
@keyframes pw-iv-drawer-up { from { transform: translateY(100%); } to { transform: translateY(0); } }
.pw-iv-hdrawer-hd {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 20px 8px;
}
.pw-iv-hdrawer-title { font-size: 16px; font-weight: 700; color: var(--pw-text-color-1); }
.pw-iv-hdrawer-x {
  border: none; background: none; padding: 0 4px; cursor: pointer;
  color: var(--pw-text-color-3); font-size: 16px; line-height: 1;
}
.pw-iv-hdrawer-bd { padding: 4px 0 8px; }

/* 这里**没有**「无图占位」的规则，是刻意的：媒体层拿不到图时（生成中/失败且没有参考图、
   NSFW 被 hideThumb 挡掉、示例数据连视频都没有）pw-iv.js 一律**什么都不渲染**，
   只剩媒体盒自己的底色。参考站那两态在没图时同样一个节点都不出。
   曾经补过一条 `.pw-iv-ph` + 🎞️ emoji 的占位，后来去掉了 —— 遮罩里的精灵图 / 进度 /
   错误文案已经把信息说全，一个 emoji 反而让人以为那是内容。 */

/* 窄屏：卡片收边距与圆角。参考站这里还有一整套「右栏堆到媒体下面、原图/提示词/参数
   按 1560px 折叠」的规则 —— 本组件右栏整块不渲染，那套规则随之没有对象，
   所以这里只留媒体盒、卡片圆角、底部条那三条。 */
@media screen and (max-width: 1560px) {
  /* 窄屏只缩圆角，**卡片不给内边距**（基础规则里本来也没有 —— 这条是原来多出来的）。
     卡片的内边距会把媒体盒与底部动作条一起往里推，等于在卡片和内容之间又垫一层；
     媒体盒自己已经有 8px 外边距了，窄屏下再叠 10px 只剩拥挤。
     去掉之后底部动作条是**通栏**的（它自带 `padding: 0 16px`，文字不会贴边）——
     本组件的右栏本来就不渲染，这条跟参考站那个「嵌在右栏里」的条不是一回事。
     ⚠️ 副作用：内容盒因此宽了 20px，下面那条媒体盒也跟着宽 20px。 */
  .pw-iv .pw-iv-hist-card { border-radius: 6px; }
  /* 只缩外边距与圆角。参考站这里还压了高度（`height:auto; max-height:360px;
     min-height:320px`）—— 本组件**不能跟**：盒子的高度现在由 `aspect-ratio: 776/437`
     从宽度推出来，再插一个 min/max-height 就会在窄屏下把比例掰弯，画面重新出现黑边
     （正是这次要消掉的东西）。要调就调宽度，高度别碰。
     ⚠️ 宽度必须跟着外边距一起改：`calc(100% - 16px)` 里的 16 = 这里的 8px × 2。
     曾经这里是 `width: 100%`，配上 8px 外边距会**横向溢出 16px** —— 卡片有
     `overflow: hidden`，右边被裁掉，盒子看着就偏了。（`max-width: 776px` 拦不住：
     100% 在窄屏下本来就小于 776。） */
  .pw-iv .pw-iv-hist-card .origin-video-box {
    margin: 8px; border-radius: 6px; width: calc(100% - 16px);
  }
  /* 「制作同款」在窄卡里收一收，别把左边四个图标挤出去。
     参考站自己也收了（`font-size: 14px; padding: 0`），但只收这两条不够 ——
     它那个 `min-width: 180px` 是宽屏值，窄卡里 180 + 四个 30px 图标 + gap 一起会顶满，
     所以这里额外把 min-width 放开，让按钮按内容宽走。
     ⚠️ 写在这段里，**不新开断点**：同一个值写成两套，将来没人说得清哪套生效。 */
  .pw-iv .pw-iv-hist-card .create-btn {
    font-size: 14px; padding: 0 16px; min-width: 0;
  }
}
/* 无限循环的装饰动画要在 prefers-reduced-motion 下停掉。
   光斑是 100px 模糊 + 3s 无限循环；两张精灵图都是 1s 无限循环 —— 三条都是纯装饰，
   且都是**无限**的，正是这条媒体查询要管的东西。
   ⚠️ 精灵图停掉之后**停在第一帧**而不是变空：background-size 只写了宽度，
   没动的 background-position 是 `0 0`，露出来的正是精灵图最上面那一帧
   （品牌标 / 上传图标）。两条都是这个道理。
   进度条那条 0.8s 的 width 过渡**不关** —— 它是一次性的，且是那一格里唯一的信息，
   关掉只会让百分比跳变；闪烁风险在无限循环那边，不在它这里。
   这一块是就地写的、没提成公共节：本文件其余动画（pw-iv-spin / pw-iv-rotate 等）
   都在**交互控件**上，停了反而会让人以为界面卡住，所以只圈住这几条装饰性的。 */
@media (prefers-reduced-motion: reduce) {
  .pw-iv .pw-iv-hist-blob { animation: none; opacity: .8; }
  .pw-iv .pw-iv-ov--proc .common-dark-loading { animation: none; }
  .pw-iv .ai-image-to-video-panel-content .add-video.uploading-file-box .uploading-loading { animation: none; }
  /* 骨架的扫光是无限循环的装饰动画：停掉后停在 background-position 的初始值上，
     渐变底色还在（仍能看出是占位块），只是不闪。 */
  .pw-iv .pw-iv-skeleton-shape,
  .pw-iv .pw-iv-skeleton-line { animation: none; }
}

/* =========================================================================
   9. 裁剪弹层（port src/components/dialog/CropDialog.vue + drawer/CropDrawer.vue）
   -------------------------------------------------------------------------
   零依赖替代 cropperjs：.crop-box 就是参考里的 cropper 容器（拖拽/缩放），
   遮罩与裁剪框都用 CSS 画，比例按钮尺寸表照抄参考的 .ratio-box。
   ========================================================================= */
.pw-iv .crop-mask {
  position: absolute; inset: 0; z-index: 998;
  background: var(--pw-dialog-mask-color);
  display: flex; align-items: center; justify-content: center;
}
.pw-iv .crop-dialog-container {
  width: calc(100% - 24px);
  /* 1240 = 图片区上限 1200 + 左右各 20 的 padding（box-sizing: border-box）——
     这样里面 .cropper-content / .crop-box 才真正能到 1200。参考站这里是 1200，
     等于把图片区卡在 1160；本组件按需求放宽到 1200。 */
  max-width: 1240px;
  max-height: calc(100% - 24px);
  overflow-y: auto;
  background: var(--pw-dialog-content-bg);
  border-radius: 12px;
  padding: 20px;
  color: var(--pw-text-color-1);
  box-sizing: border-box;
}
.pw-iv .crop-dialog-title { font-size: 16px; line-height: 28px; padding-bottom: 6px; }

.pw-iv .cropper-content {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 460px;
  background: var(--pw-bg-color-3);
  margin-bottom: 12px;
  overflow: hidden;
}
.pw-iv .crop-box {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  width: 100%; max-width: 1200px; height: 100%;
  overflow: hidden;
  user-select: none;
  touch-action: none;
}
.pw-iv .crop-box > img {
  width: 100%; height: 100%; max-width: 100%; max-height: 460px;
  object-fit: contain;
  -webkit-user-drag: none;
  pointer-events: none;
}
/* 绘制层：遮罩与裁剪框都绝对定位，原点即 .crop-box。
   这层自己脱离 flex 流向 —— 否则它会作为 .crop-box（flex 居中）里的一个空 flex item
   参与排布，img 的 offsetLeft 就不再恒为 0，_layoutCrop 的坐标基准会跟着漂。 */
.pw-iv .crop-box .crop-overlay { position: absolute; inset: 0; }
/* 裁剪框：外圈 4 条遮罩 + 描边（复刻 cropperjs modal/highlight/guides:false）。
   四角把手**保留在 DOM 里**：缩放靠它们的命中区（见 _wireCrop），只是用 opacity 视觉隐藏。
   注意别改成 display:none / visibility:hidden —— 那会连命中区一起丢掉，四角就再也拖不动了。
   要恢复可见，把下面的 opacity 改回 1 即可。 */
.pw-iv .crop-cropbox { position: absolute; box-sizing: border-box; border: 1px solid var(--pw-text-color-2); cursor: move; }
.pw-iv .crop-shade { position: absolute; background: rgba(0, 0, 0, .5); pointer-events: none; }
.pw-iv .crop-handle {
  position: absolute; width: 10px; height: 10px;
  background: #fff; border-radius: 1px;
  opacity: 0;
}
.pw-iv .crop-handle--nw { left: -5px; top: -5px; cursor: nwse-resize; }
.pw-iv .crop-handle--ne { right: -5px; top: -5px; cursor: nesw-resize; }
.pw-iv .crop-handle--sw { left: -5px; bottom: -5px; cursor: nesw-resize; }
.pw-iv .crop-handle--se { right: -5px; bottom: -5px; cursor: nwse-resize; }

.pw-iv .crop-ratio-title { font-weight: 400; font-size: 16px; line-height: 28px; margin: 20px 0 12px; }
.pw-iv .crop-ratio-box {
  display: flex; gap: 8px; align-items: center; justify-content: flex-start;
  width: 100%; margin-bottom: 24px;
  overflow-x: auto;
}
.pw-iv .crop-ratio-box .ratio-box-item {
  cursor: pointer;
  min-width: 50px; height: 70px;
  background: var(--pw-bg-color-3);
  border-radius: 6px;
  display: flex; align-items: center; justify-content: end;
  flex-direction: column;
  padding: 5px;
  border: 2px solid transparent;
  transition: all 300ms;
  font-weight: 400; font-size: 14px; line-height: 24px;
  text-transform: none;
  flex: 0 0 auto;
  box-sizing: border-box;
}
.pw-iv .crop-ratio-box .ratio-box-item .ratio-display-item {
  width: 51px; height: 51px;
  display: flex; align-items: center; justify-content: center;
}
.pw-iv .crop-ratio-box .ratio-box-item .ratio-display-item > div { background-color: var(--pw-bg-color-2); }
/* 比例示意小方框：**短边恒为 18px**，长边按比例算（对齐参考站 CropDialog.vue 的 .dialog-content .ratio-box）。
   注意不是「长边恒为 32px」—— 那只在 16:9 / 9:16 上碰巧一致，4:3 应是 24×18 而非 24×32。
   这些 .item-* class 此前没有任何尺寸规则，方框是 0×0 看不见，这里是补上第一份定义。 */
.pw-iv .crop-ratio-box .ratio-box-item .ratio-display-item > .item-1-1  { width: 18px; height: 18px; }
.pw-iv .crop-ratio-box .ratio-box-item .ratio-display-item > .item-16-9 { width: 32px; height: 18px; }
.pw-iv .crop-ratio-box .ratio-box-item .ratio-display-item > .item-9-16 { width: 18px; height: 32px; }
.pw-iv .crop-ratio-box .ratio-box-item .ratio-display-item > .item-4-3  { width: 24px; height: 18px; }
.pw-iv .crop-ratio-box .ratio-box-item .ratio-display-item > .item-3-4  { width: 18px; height: 24px; }
.pw-iv .crop-ratio-box .ratio-box-item .ratio-display-item > .item-21-9 { width: 42px; height: 18px; }
.pw-iv .crop-ratio-box .ratio-box-item.ratio-box-item-active {
  border: 2px solid var(--pw-border-color-1);
  color: var(--pw-text-color-2);
}
@media (hover: hover) and (pointer: fine) {
  .pw-iv .crop-ratio-box .ratio-box-item:hover {
    border: 2px solid var(--pw-border-color-1);
    color: var(--pw-text-color-2);
  }
}
/* 原参考站这里还有 .auto-item（只出文字、隐藏示意方框）—— 组件已去掉 Auto 档，规则一并删除 */

.pw-iv .crop-button-box {
  width: 100%;
  display: flex; align-items: center; justify-content: space-between;
}
.pw-iv .crop-button-box .right-button-box { display: flex; align-items: center; gap: 16px; }
/* 裁剪弹窗那两个按钮的样式在 §7 —— `.pw-button` 是两处共用的那条规则，
   留在这里会盖掉 §8 历史卡片的窄屏档（见那边的注释）。 */

/* =========================================================================
   10. 窄容器
   ========================================================================= */

/* 参考站 @media screen and (max-width: 900px) 的等价容器查询 + 视口兜底 */
@container (max-width: 900px) {
  .pw-iv-shell { display: flex; flex-direction: column; align-items: stretch; gap: 0; }
  .pw-iv-panel-slot { position: relative; flex: none; width: 100%; height: auto; min-height: 0; }
  .pw-iv .ai-image-to-video-panel-page { width: 100%; height: auto; }
  .pw-iv .panel-content {
    transition: unset;
    overflow: unset;
    width: 100% !important;
    height: 100%;
    padding: 0;
    border-radius: unset;
    background-color: var(--pw-bg-color-2);
  }
  /* 窄屏内缩 20px：容器 padding 仍是 0，只改这个变量，子元素规则自动跟随 */
  .pw-iv .ai-image-to-video-panel-content { width: 100%; --pw-content-pad-x: 20px; padding: 0 0 180px; overflow: unset; }
  .pw-iv .ai-image-to-video-panel-content .add-video { height: 160px; }
  .pw-iv .ai-image-to-video-panel-content .add-video .add-text-mobile { display: block; }
  .pw-iv .ai-image-to-video-panel-content .add-video .add-text { display: none; }
  /* 参考页窄屏这里靠被去掉的 .panel-title 的 margin-top:16px 撑顶，标题没了就得 tab 自己顶上来 */
  /* gap 沿用基类的 36px（下划线式 tab 的固定间距，不随窄屏缩） */
  .pw-iv .ai-image-to-video-panel-content .ai-image-to-video-panel-tab { margin: 16px auto 12px; }
  .pw-iv .ai-image-to-video-panel-content .prompt-text { margin: 12px 0 8px; }
  .pw-iv .ai-image-to-video-panel-content .prompt-textarea { height: 216px; }
  .pw-iv .pw-iv-stage {
    position: static; flex: none; height: auto; min-height: 0;
    background: transparent; border-radius: 0;
  }
  .pw-iv .pw-iv-stage-body { height: auto; }
  /* 窄屏把 .pw-iv-stage / -body 都改成了 auto 高（上面两行），历史滚动容器的
     height:100% 就没了参照物 → .scroll-box 的 overflow-y:auto 不再生效、
     滚到底不触发 → **窄屏下分页彻底失效**。这里给滚动区一个视口兜底高度捞回来。
     同因：这一条在两个窄屏块里必须逐字一致（见本节开头第 3 条）。 */
  .pw-iv .pw-iv-history .scroll-box { max-height: 70vh; }
  .pw-iv .pw-iv-sample-page { padding: 0 20px 20px; }
  .pw-iv .pw-iv-sample-title { font-size: 12px; line-height: 22px; font-weight: 400; }
  .pw-iv .pw-iv-sample-box { min-height: 210px; }
  /* 参考在窄屏把两个 trigger 各压深一档（`@media screen and (max-width:899px){background:var(--pw-bg-color-3)}`）。
     窄栏嵌入正是本组件的主场景，一并对齐；展开态（.model-option-item-active / .config-trigger-active）
     特异度更高，照旧覆盖这里。 */
  .pw-iv .model-trigger-simple,
  .pw-iv .config-trigger { background: var(--pw-bg-color-3); }
}

@media (max-width: 900px) {
  .pw-iv-shell { display: flex; flex-direction: column; align-items: stretch; gap: 0; }
  .pw-iv-panel-slot { position: relative; flex: none; width: 100%; height: auto; min-height: 0; }
  .pw-iv .ai-image-to-video-panel-page { width: 100%; height: auto; }
  .pw-iv .panel-content {
    transition: unset;
    overflow: unset;
    width: 100% !important;
    height: 100%;
    padding: 0;
    border-radius: unset;
    background-color: var(--pw-bg-color-2);
  }
  /* 窄屏内缩 20px：容器 padding 仍是 0，只改这个变量，子元素规则自动跟随 */
  .pw-iv .ai-image-to-video-panel-content { width: 100%; --pw-content-pad-x: 20px; padding: 0 0 180px; overflow: unset; }
  .pw-iv .ai-image-to-video-panel-content .add-video { height: 160px; }
  .pw-iv .ai-image-to-video-panel-content .add-video .add-text-mobile { display: block; }
  .pw-iv .ai-image-to-video-panel-content .add-video .add-text { display: none; }
  /* 参考页窄屏这里靠被去掉的 .panel-title 的 margin-top:16px 撑顶，标题没了就得 tab 自己顶上来 */
  /* gap 沿用基类的 36px（下划线式 tab 的固定间距，不随窄屏缩） */
  .pw-iv .ai-image-to-video-panel-content .ai-image-to-video-panel-tab { margin: 16px auto 12px; }
  .pw-iv .ai-image-to-video-panel-content .prompt-text { margin: 12px 0 8px; }
  .pw-iv .ai-image-to-video-panel-content .prompt-textarea { height: 216px; }
  .pw-iv .pw-iv-stage {
    position: static; flex: none; height: auto; min-height: 0;
    background: transparent; border-radius: 0;
  }
  .pw-iv .pw-iv-stage-body { height: auto; }
  /* 窄屏把 .pw-iv-stage / -body 都改成了 auto 高（上面两行），历史滚动容器的
     height:100% 就没了参照物 → .scroll-box 的 overflow-y:auto 不再生效、
     滚到底不触发 → **窄屏下分页彻底失效**。这里给滚动区一个视口兜底高度捞回来。
     同因：这一条在两个窄屏块里必须逐字一致（见本节开头第 3 条）。 */
  .pw-iv .pw-iv-history .scroll-box { max-height: 70vh; }
  .pw-iv .pw-iv-sample-page { padding: 0 20px 20px; }
  .pw-iv .pw-iv-sample-title { font-size: 12px; line-height: 22px; font-weight: 400; }
  .pw-iv .pw-iv-sample-box { min-height: 210px; }
  /* 同上：窄屏 trigger 压深一档（视口兜底那一份，与 @container 块保持逐行一致） */
  .pw-iv .model-trigger-simple,
  .pw-iv .config-trigger { background: var(--pw-bg-color-3); }
}

/* =========================================================================
   11. 提示词违规弹窗（port src/components/dialog/PromptProcessDialog.vue
       + src/components/drawer/PromptProcessDrawer.vue）
   -------------------------------------------------------------------------
   同一份内层内容、两套外壳：>768 是 PwDialog 居中卡（.prompt-process-mask），
   ≤768 是 PwDrawer 全屏底部抽屉（照 PwDrawer 的 position=bottom + is-full-screen）。
   内层值逐条照抄参考站那两个 <style>，两套外壳的差异（插图 112/80、标题 20/16……）
   由后面那组窄屏规则覆盖 —— 基类**只写一份**，否则两边会各自漂。

   ⚠️ 标题的红是**写死的 #ff4d4f**，不是本组件的 --pw-text-color-3（#ff3a3e）。
   别归一 —— 归一就与参考站那个弹窗不是一个红（与 .error-icon 的 #ef4444 同类）。

   ⚠️ textarea **没有边框**，这是照着参考站算出来的结果、不是漏写：参考站那条是
   `border: 1px solid var(--pw-border-color-3)`，而 `--pw-border-color-3` **全参考站
   只出现这一次、从来没有被定义过**（theme.less 只定义了 -1 / -2）。CSS 变量替换失败
   会让整条声明在**计算值阶段**失效 → border 回到初始值（border-style: none）→ 无边框。
   连它那条 `:focus { border-color: … }` 也一起是死的（style 还是 none，只改颜色画不出来），
   所以本组件干脆写 `border: none`，并把那条 focus 规则一并省掉。 */
.pw-iv .prompt-process-mask {
  position: absolute; inset: 0; z-index: 998;
  background: var(--pw-dialog-mask-color);
  overflow-y: auto;
  display: flex; align-items: center; justify-content: center;
}
.pw-iv .prompt-process-container {
  position: relative;
  background: var(--pw-dialog-content-bg);
  border-radius: 12px;
  /* 照参考站的 :deep(.pw-dialog-container) 覆盖：那份基类本身是 64/64/78 + max-width 726 */
  padding: 48px 40px 88px;
  width: calc(100% - 40px);
  max-width: 1000px;
  display: flex; align-items: center; flex-direction: column; justify-content: center;
  box-sizing: border-box;
}
/* 参考站那颗 ✕ 是 PwDialog 自带的（.close-icon，绝对定位在卡片右上角） */
.pw-iv .prompt-process-container .close-icon {
  position: absolute; right: 10px; top: 10px;
  font-size: 24px; cursor: pointer;
  color: var(--pw-dialog-close-color);
}

.pw-iv .prompt-process-content { width: 100%; color: var(--pw-text-color-1); }
.pw-iv .prompt-process-content .prompt-process-header {
  display: flex; flex-direction: column; align-items: center;
  margin-bottom: 20px;
}
.pw-iv .prompt-process-content .prompt-process-header .tishici-img { width: 112px; height: 112px; }
.pw-iv .prompt-process-content .prompt-process-header .prompt-process-title {
  font-size: 20px; font-weight: bold; color: #ff4d4f;   /* ← 写死，见本节开头那条 ⚠️ */
  line-height: 28px; margin-bottom: 8px; text-align: center;
}
.pw-iv .prompt-process-content .prompt-process-header .prompt-process-subtitle {
  font-size: 18px; color: var(--pw-text-color-1); line-height: 22px; text-align: center;
}

.pw-iv .prompt-process-content .prompt-process-body {
  margin-bottom: 78px;
  background: var(--pw-bg-color-3);
  border: 1px solid var(--pw-text-color-2);
  border-radius: 12px;
  height: 300px;
  position: relative;
}
.pw-iv .prompt-process-content .prompt-process-body .prompt-process-textarea {
  width: 100%;
  height: calc(100% - 56px);       /* 让出下面那行 .textarea-footer */
  padding: 12px;
  border: none;                    /* ← 参考站那条是死声明，见本节开头那条 ⚠️ */
  border-top-left-radius: 12px;
  border-top-right-radius: 12px;
  background: var(--pw-bg-color-3);
  color: var(--pw-text-color-1);
  font-size: 14px; line-height: 22px;
  resize: none;
  outline: none;
  box-sizing: border-box;
}
.pw-iv .prompt-process-content .prompt-process-body .textarea-footer {
  display: flex; justify-content: space-between; align-items: center;
  padding: 14px;
}
.pw-iv .prompt-process-content .ai-action-box .ai-action-button {
  display: flex; align-items: center; gap: 4px;
  cursor: pointer;
  font-size: 13px;
  transition: opacity .2s;
  padding: 0 24px;
  height: 28px; line-height: 28px;
  background: linear-gradient(129deg, #4D5AFF 0%, #8A53FF 47.8%, #F84EB4 97.4%);
  box-shadow: inset 4px 4px 20px 0px rgba(255, 255, 255, .25),
              inset -4px -4px 20px 0px rgba(255, 255, 255, .25);
  border-radius: 50px;
  color: var(--pw-text-color-1);
}
@media (hover: hover) and (pointer: fine) {
  .pw-iv .prompt-process-content .ai-action-box .ai-action-button:hover {
    background: linear-gradient(90deg, #757bff 0%, #f972c3 100%);
    box-shadow: 0 4px 12px rgba(123, 140, 255, .4);
  }
}
.pw-iv .prompt-process-content .ai-action-box .icomoon { font-size: 16px; }
/* 转圈复用组件已有的 pw-iv-spin（同为 rotate 360°）—— 参考站那份叫 spin，值一样 */
.pw-iv .prompt-process-content .ai-action-loading { cursor: not-allowed; opacity: .7; }
.pw-iv .prompt-process-content .ai-action-loading .loading-spin { animation: pw-iv-spin 1s linear infinite; }
/* 成功态：文案 + 一颗撤销。参考站的 a-tooltip 换成 title 属性 —— 本组件不引 arco */
.pw-iv .prompt-process-content .ai-action-success {
  display: flex; align-items: center;
  color: var(--pw-text-color-1);
}
.pw-iv .prompt-process-content .ai-action-success .undo-button {
  margin-left: 4px; color: var(--pw-text-color-1); cursor: pointer;
}
.pw-iv .prompt-process-content .textarea-footer .char-count {
  font-size: 12px; color: var(--pw-text-color-5);
}
/* 错误行绝对定位在 body 下沿外侧 —— 不占位，所以 body 的 300px 不会因为出错而变高
   （参考站同款）。⚠️ 它落在 body 与 footer 之间那 78px 的间距里，
   所以 .prompt-process-body 的 margin-bottom 不能改小。 */
.pw-iv .prompt-process-content .prompt-process-body .error-message {
  position: absolute; bottom: -42px; left: 0;
  font-size: 16px; color: var(--pw-text-color-3); line-height: 20px;
}
.pw-iv .prompt-process-content .prompt-process-footer {
  display: flex; justify-content: center; gap: 16px;
}
/* PC 两颗按钮：照参考站 .output-type-button（宽度固定 240，不随卡片伸缩） */
.pw-iv .prompt-process-footer .pw-button.output-type-button {
  min-width: 240px; height: 44px; line-height: 44px;
}

/* ---------- ≤768：PwDrawer 形态 ---------- */
/* ⚠️ 移动端那套外壳也是「铺满视口」的，同样得靠 _placePromptOverlay 把原点挪回视口
   （同 .pw-iv-hdrawer-wrap，见 §8 那段 ⚠️）。z-index 与历史抽屉同档：两个抽屉在本组件里
   不会同时开，同档就是「谁后挂谁在上面」。 */
.pw-iv .pw-iv-pdrawer-wrap { position: absolute; z-index: 1900; }
.pw-iv .pw-iv-pdrawer-mask {
  position: absolute; left: 0; top: 0; right: 0; bottom: 0;
  background: var(--pw-dialog-mask-color);
}
/* is-full-screen：整屏铺满（参考站 PwDrawer 的 is-full-screen + position=bottom） */
.pw-iv .pw-iv-pdrawer {
  position: absolute; left: 0; right: 0; top: 0; bottom: 0;
  display: flex; flex-direction: column;
  background: var(--pw-dialog-content-bg);
  overflow-y: auto;
}
.pw-iv .pw-iv-pdrawer .drawer-title-bar {
  display: flex; align-items: center; justify-content: flex-end;
  padding: 12px 16px 0;
  flex-shrink: 0;
}
.pw-iv .pw-iv-pdrawer .drawer-title-bar .icomoon {
  font-size: 24px; color: var(--pw-text-color-1); cursor: pointer;
}
/* 内层在窄屏的整体差异：内缩 16px + 底 24px。参考站 PC 那份 .prompt-process-content
   自己没有 padding（那是 PwDialog 卡片给的），所以这一组只在窄屏出现，别提到基类上去。 */
@media (max-width: 768px) {
  .pw-iv .pw-iv-pdrawer .prompt-process-content {
    display: flex; flex-direction: column;
    padding: 0 16px 24px;
    box-sizing: border-box;
  }
  .pw-iv .pw-iv-pdrawer .prompt-process-header { padding: 16px 0 20px; margin-bottom: 0; }
  .pw-iv .pw-iv-pdrawer .prompt-process-header .tishici-img { width: 80px; height: 80px; }
  .pw-iv .pw-iv-pdrawer .prompt-process-header .prompt-process-title {
    font-size: 16px; line-height: 24px; margin-top: 8px; margin-bottom: 0;
  }
  .pw-iv .pw-iv-pdrawer .prompt-process-header .prompt-process-subtitle {
    font-size: 14px; line-height: 20px; margin-top: 6px;
  }
  /* body 窄屏不设固定高：textarea 自己 200px + 一行 footer，容器跟着内容走 */
  .pw-iv .pw-iv-pdrawer .prompt-process-body { height: auto; margin-bottom: 48px; }
  .pw-iv .pw-iv-pdrawer .prompt-process-body .prompt-process-textarea {
    height: 200px; background: transparent;
  }
  .pw-iv .pw-iv-pdrawer .textarea-footer { padding: 10px 14px; }
  .pw-iv .pw-iv-pdrawer .ai-action-box .ai-action-button { padding: 0 16px; }
  .pw-iv .pw-iv-pdrawer .prompt-process-body .error-message { font-size: 14px; }
  .pw-iv .pw-iv-pdrawer .prompt-process-footer { flex-direction: column; gap: 12px; }
  .pw-iv .pw-iv-pdrawer .prompt-process-footer .pw-button.footer-button {
    width: 100%; height: 44px; line-height: 44px;
  }
}
