/* ============================================================
   封面模组皮肤（cover.css）—— 前台作品页与编辑器画布共用
   布局形态（is-layout-* 引擎）统一在 theme.css；本文件负责
   封面的三层视觉与自身 params 的消费：
     --cover-img / --cover-fx / --cover-fy   背景图 url + 焦点点（裁剪基准）
     --cover-overlay-g                       遮罩渐变（渐变模式 = 编辑器序列化串原样输出；
                                              纯色模式 = 服务端把颜色×透明度拼成的同色双锚点串，2026-09-04）
     --cover-minh                            最小高度（值已含单位：480px / 90vh；
                                             0 = 随内容不输出变量，回落 0px）
     aspect-ratio                            宽高比（模板内联在根元素上，期望值；
                                             与 --cover-minh 取大，min-height 硬下限）
     --cp-v / --cp-h                         内容位置九宫格的主轴分量
     （§57 起背景图改为弹窗物理裁剪，原 --cover-crop-* 取景变量已删除）
   层级：媒体层(0) < 遮罩层(1) < 内容层(2) < ::after 选中环(2，DOM 序最后)。
   边框 = 根元素真实 border（2026-09-05 回归 WP 几何，弃 ::before 覆盖层）：
   线在 overflow 裁剪区之外，子元素一律裁在 border 内缘、盖不住线。
   ============================================================ */

.work-module-cover {
    position: relative;
    overflow: hidden;            /* 背景图随容器形状裁剪（配合圆角也成立） */
    /* WP 同款双写（trunk cover/style.scss）：clip 不产生滚动容器、不影响子元素
       position: sticky；hidden 仅为不支持 clip 的旧浏览器兜底 */
    overflow: clip;
    min-height: var(--cover-minh, 0px);
    /* 宽度硬上限（2026-09-05 手机溢出修复）：aspect-ratio + min-height 会按
       css-sizing 的纵横比传导出「最小宽 = min-height × ratio」（480 × 16/9
       ≈ 853px），传导宽不随页宽收窄——手机预览/窄前台溢出画面 374px 的根因
       （桌面上也一直存在：根 853 > 内容列 840，居中后不易察觉）。
       max-width: 100% 把传导宽钳进所在容器：宽裕时 ratio 期望值照常生效，
       页窄于传导宽时宽度跟随容器收窄、高度回落 min-height 硬下限
       （WP cover 无 aspect-ratio，宽度全由布局上限管——本条即向 WP 语义
       靠拢的钳制层；crop 取景在窄页下 ratio 被钳断，背景 cover 填充与
       取景变量仍成立，属可接受的响应式降级） */
    max-width: 100%;
    /* 根元素纵排 flex：内容层因此成为可拉伸的 flex 项，min-height 撑出的
       富余高度才会"进入"内容层——九宫格的 justify-content 才有空间可分配。
       （修复记录：此前根是块级盒，内容层高度=内容自身高度且贴顶，
       top/center/bottom 三档算出来完全一样，九宫格形同虚设） */
    display: flex;
    flex-direction: column;
    border-radius: var(--bd-radius-tl, 0px) var(--bd-radius-tr, 0px) var(--bd-radius-br, 0px) var(--bd-radius-bl, 0px);
    /* 边框（2026-09-05 回归 WP 真实 border，替代 2026-09-03 的 ::before
       覆盖层方案）：WP cover 的线画在根元素上、位于 overflow 裁剪区之外——
       子内容（负 margin/块阴影/播放按钮）一律被裁在 border 内缘，结构上
       不可能盖线；媒体/遮罩层 inset:0 只铺到 padding box，止步于线内缘
       （线外圈露根背景 = WP 原生几何，细线无感）。线宽的内缩布局由 border
       盒模型自带，原 padding 顶线宽的垫层随之删除。无边框时 --bd-width
       不输出 → 0px + transparent = 不可见，几何零变化；写法与群组
       group.css 同构 */
    border-width: var(--bd-width-top, 0px) var(--bd-width-right, 0px) var(--bd-width-bottom, 0px) var(--bd-width-left, 0px);
    border-style: var(--bd-style-top, solid) var(--bd-style-right, solid) var(--bd-style-bottom, solid) var(--bd-style-left, solid);
    border-color: var(--bd-color-top, transparent) var(--bd-color-right, transparent) var(--bd-color-bottom, transparent) var(--bd-color-left, transparent);
}

/* ---- 媒体层：背景图 cover 填充，位置 = 焦点点 ----
   自绘内弧（2026-09-05 第五刀，图片/视频模组同款保险）：根元素的
   overflow:clip 圆角蒙版是低精度光栅，弧线边缘向内收缩数像素，边框
   内缘处会透出细缝——媒体层自己按「根圆角 − 边框宽」画弧（无边框时
   −0 = 原值），与 clip 弧线/边框内缘同心重合，收缩缝不可见；
   overflow:hidden 让层内背景视频/封面叠层跟随同一内弧 */
.work-cover-media {
    position: absolute;
    inset: 0;
    z-index: 0;
    /* 纯视觉层豁免指针（下方 77/91 行子层注释同语义收口到容器，20260920 补）：
       inset:0 + z-0 定位层不豁免指针就会拦住容器内流内容——cover「有背景图·
       无子模组」空态的流内＋钮同病（群组侧同日实锤后，按"同一 bug 的多处
       调用点逐一核对"家法同批补齐）。豁免后点按穿透 root：选中/右键/
       本体拖拽照常（canvas.js:629 注释的既定语义至此才真正成立） */
    pointer-events: none;
    overflow: hidden;
    border-radius: calc(max(var(--bd-radius-tl, 0px) - max(var(--bd-width-top, 0px), var(--bd-width-left, 0px)), 0px)) calc(max(var(--bd-radius-tr, 0px) - max(var(--bd-width-top, 0px), var(--bd-width-right, 0px)), 0px)) calc(max(var(--bd-radius-br, 0px) - max(var(--bd-width-bottom, 0px), var(--bd-width-right, 0px)), 0px)) calc(max(var(--bd-radius-bl, 0px) - max(var(--bd-width-bottom, 0px), var(--bd-width-left, 0px)), 0px));
    background-image: var(--cover-img, none);   /* 未设背景图 = none，纯遮罩形态 */
    background-size: cover;
    background-position: var(--cover-fx, 50%) var(--cover-fy, 50%);
}
/* ---- 背景视频（§31，WP backgroundType='video' 同实现）----
   视频背景 = <video> 元素（视频进不了 background-image）：absolute 容器内
   铺满 + cover 取景；焦点复用图片侧 --cover-fx/fy——WP focalPoint 图/视频
   同源，只是消费属性不同（图片 background-position / 视频 object-position）。
   autoplay/muted/loop/playsinline 属性由模板输出（WP save.jsx 同款）；
   pointer-events:none = 背景是纯视觉层——右键菜单、选中点击、拖拽都不被
   视频拦截（画布与前台同规则，§10.6 右键菜单不受视频元素影响） */
.work-cover-media > video {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: var(--cover-fx, 50%) var(--cover-fy, 50%);
    pointer-events: none;
}
/* ---- 背景视频封面叠层（2026-09-05 用户拍板）----
   封面显示不再依赖浏览器绘制 <video poster>（用户环境 Chromium 出现
   poster HTTP 200 加载成功却不渲染的问题，GPU 合成层，headless 及其他
   环境正常）——改走普通 <img> 绝对叠层：铺满 + cover 取景 + 焦点对齐
   （object-position 与视频同源 --cover-fx/fy），pointer-events:none
   同视频 = 纯视觉层（不拦选中/右键/拖拽，§10.6 同规则）。状态机与
   video 模组封面叠层同款：默认显示，video 首次 play 加 is-video-started
   隐藏（播放中/暂停帧可见），ended 回封面；poster 属性保留垫底 */
.work-cover-media > .work-cover-poster {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: var(--cover-fx, 50%) var(--cover-fy, 50%);
    pointer-events: none;
}
.work-cover-media > video.is-video-started:not(.is-video-ended) + .work-cover-poster {
    display: none;
}
/* 视差：滚动时背景固定在视口（WP Cover 的 "Fixed background" 同实现）；
   移动端 Safari 对 fixed 背景支持差，前台降级为普通滚动背景（媒体查询不处理，
   iOS 会自动回退——已知平台差异，不做 JS 补偿） */
.work-module-cover.is-parallax .work-cover-media {
    background-attachment: fixed;
}
/* ---- 播放/暂停按钮（2026-09-04 §31 收尾，样式在公共组件 playbtn.css）----
   本文件只管 z 序：按钮挂在根元素末尾（内容层之后），absolute 相对根
   定位——z2 与内容层同级，DOM 序在后 = 压住遮罩(z1)与内容层，
   浮在视频右下角（Apple 同位置，坐标由 playbtn.css 的 right/bottom）。
   画布可点（2026-09-04 用户裁决，推翻同日早前的「画布禁点」规则）：
   点按钮切播放/暂停，同时按画布常规选中 cover 块，互不妨碍 */
.work-module-cover > .work-module-video-playbtn {
    z-index: 2;
}
/* （cover 裁切取景段——.is-crop 的 --cover-crop-* 消费、裁切/视差互斥
   降级——已随 §57 退役删除：背景图改为弹窗物理裁剪，取景由焦点参数
   承担；视差降级路径仍由移动端媒体查询承担） */

/* ---- 遮罩层：压暗/染色背景，保证内容对比度（WP Overlay 同语义）---- */
.work-cover-overlay {
    position: absolute;
    inset: 0;
    z-index: 1;
    /* 遮罩 = 单一渐变图层（2026-09-03 四层合一）：纯色/浓度坡度/颜色渐变
       全由渐变色标表达（同色同浓度=纯色、同色异浓度=压暗坡度、异色=彩色
       渐变）；留空回落 none = 无遮罩。旧纯色遮罩体系（--cover-overlay/
       --cover-overlay-a/--cover-overlay-ag）已随本次重构删除 */
    background-image: var(--cover-overlay-g, none);
}

/* ---- 内容层：子模组挂载点（引擎基础形态在 theme.css），置于最上层 ---- */
.work-cover-inner {
    position: relative;
    z-index: 2;
    width: 100%;
    flex: 1 0 auto;   /* 纵向拉伸占满封面富余高度；shrink 0：内容超高时由根自然增高，不被压缩 */
}

/* ---- 内容位置九宫格·完全体（WP contentPosition，优先级同 WP）----
   WP 机制（gutenberg cover/style.scss 实证）：
   - cover 根 flex 双轴对齐内容层；仅显式非默认位置才输出 is-position-* 类
   - 左右六档时内容层放弃满宽（width:auto）→ 水平对齐才真正生效
   映射到本引擎（内容层须保持满宽作 constrained 基准，水平改在交叉轴消费）：
   垂直 = 主轴 justify-content ← --cp-v
   水平 = 交叉轴 align-items ← --cp-h > 布局面板 --lay-justify > 引擎默认
   默认"正中"服务端不输出任何变量/类 → 布局引擎全权（零回归） */
/* §43 类名收敛：is-layout-row/stack → is-layout-flex（竖排加 .is-vert）；
   cover 九宫格消费端的 fallback 键随轴分派同步（竖排交叉轴 = --lay-valign） */
.work-module-cover:not(.is-layout-grid):not(.is-layout-flex) > .work-cover-inner {
    justify-content: var(--cp-v, center);
    align-items: var(--cp-h, stretch);
}
/* 竖排 flex（旧 stack）：引擎自身有水平对齐（--lay-valign），作为 fallback 保留 */
.work-module-cover.is-layout-flex.is-vert > .work-cover-inner {
    justify-content: var(--cp-v, center);
    align-items: var(--cp-h, var(--lay-valign, flex-start));
}
/* 横排 flex（旧 row）：主轴水平 ← --cp-h（fallback 引擎主轴对齐）；交叉轴垂直 ← --cp-v（fallback 引擎默认居中） */
.work-module-cover.is-layout-flex:not(.is-vert) > .work-cover-inner {
    justify-content: var(--cp-h, var(--lay-justify, flex-start));
    align-items: var(--cp-v, center);
}
/* 显式九宫格档（含正中）：解除 constrained 的子项对齐钉死（align-self）、
   居中缩进公式与满宽公式，水平/垂直全部交给九宫格 + 用户自身边距
   （WP 显式档 inner width:auto 同语义；未动过九宫格的封面不命中本规则，
   constrained 排版零回归）。
   width:auto（2026-08-29 补）：constrained 的显式宽度公式仍会命中子项
   （theme.css §16），块宽≈内容列宽——align-self 松绑了也看不出"贴右"，
   这就是"文字模组撑满一整行、九宫格选了位置没反应"的根因。
   块收缩为 fit-content（短文字 = 文字宽）后：左右档真正贴边、
   垂直档（上·居中/正中/下·居中）的水平居中也才可见。
   max-width 双上限（2026-08-29 二补）：纯百分比上限在 flex 容器的
   intrinsic（max-content）测量中失效（循环参照被当无效），cover 嵌在
   row 群组里时标题的单行宽度会无上限传导、把整个封面撑宽——补上
   --lay-content 确定值上限后，fit-content 测量封顶在内容列宽；
   实际布局时百分比分量恢复生效，长文本仍在封面边缘内折行。
   注意 width:auto 对 stack/row/grid 子项同样无害：stack 本就无宽度公式、
   row 子项宽由 flex-basis 管、grid 子项本就 width:auto（stretch 拉满列）。 */
.work-module-cover[class*='is-position-']
    > .work-cover-inner > .block-wrap > .work-module-wrap {
    align-self: auto;
    width: auto;
    max-width: min(
        calc(100% - var(--m-l, 0px) - var(--m-r, 0px)),
        var(--lay-content, var(--content-width, 840px))
    );
    margin-left: var(--m-l, 0px);
    margin-right: var(--m-r, 0px);
}
/* 空白模组例外（2026-08-29 全模组排查补）：spacer 没有宽度参数、语义就是
   "撑满所在列的空白"，而它是空元素——上面 width:auto 的 fit-content 收缩
   会把它算成 0 宽（虚线贴边消失）。恢复满宽：交叉轴 stretch + 解除收缩，
   九宫格只对它生效垂直位置（水平位置对满宽空白无意义，WP Spacer 同语义） */
.work-module-cover[class*='is-position-']
    > .work-cover-inner > .block-wrap > .work-module-wrap:has(> .work-module-spacer) {
    align-self: stretch;
    width: auto;
    max-width: none;
}
