/**
 * Qin_A11yFixes — 共用 CSS 修复层
 *
 * 每一条都由 <html> 上的 data-a11y-* 属性守卫，属性由 apply-flags.js
 * 按后台开关写入。这样一个 CSS 文件就能逐项开关，不必拆成多个静态资源。
 *
 * 只针对 Luma 从 2.3 到 2.4 都没变过的稳定 class。
 * 加新规则前先确认选择器在两个版本上都存在。
 *
 * 尽量避免 !important；只有在压过 Luma 自身的 outline:none 等
 * 高特异性声明时才使用，并在该行注明原因。
 */

/* ── 焦点指示 · WCAG SC 2.4.7 / 2.4.11 ──────────────────────── */

/*
 * Luma 在多处用 outline:none 抹掉了焦点样式，键盘用户会完全看不到
 * 自己在哪。这里统一补回。用 :focus-visible 而非 :focus，
 * 避免鼠标点击时也出现焦点环。
 */
/*
 * 双色焦点环：内侧 2px 白 + 外侧 2px 蓝。
 *
 * 不要按「这块背景是深色/浅色」去分别指定颜色——六个站的主题背景各不相同，
 * 猜错就等于没有焦点指示。之前这里给 .navigation 和 .page-footer 硬写了
 * 白色描边（按 Luma 默认的深色导航栏），结果在浅灰底导航上完全看不见。
 *
 * 双环任何底色都成立：白环在深底上可见，蓝环在浅底上可见。
 * 这也是 WCAG 2.2 SC 2.4.13 推荐的做法。
 */
html[data-a11y-focus-visible] a:focus-visible,
html[data-a11y-focus-visible] button:focus-visible,
html[data-a11y-focus-visible] input:focus-visible,
html[data-a11y-focus-visible] select:focus-visible,
html[data-a11y-focus-visible] textarea:focus-visible,
html[data-a11y-focus-visible] summary:focus-visible,
html[data-a11y-focus-visible] [tabindex]:focus-visible {
    /* !important：需要压过 Luma 的 outline:none */
    outline: 2px solid #1b44e8 !important;
    outline-offset: 2px !important;
    box-shadow: 0 0 0 2px #fff !important;
}

/*
 * 主导航是特例，纯 CSS 解决不了。
 *
 * Luma 的主导航是 jQuery UI Menu，用 aria-activedescendant 虚拟焦点：
 * DOM 焦点自始至终留在外层 <ul> 上，方向键只是把 aria-activedescendant
 * 指向另一个元素 id。分类链接从来没拿到过 DOM 焦点，
 * 所以 :focus / :focus-visible 永远不会命中它们。
 *
 * 解决办法是 js/nav-focus.js 跟着那个属性给当前项加 .qin-a11y-navfocus，
 * 这里只负责画环。该补丁需要在后台开启（qin_a11yfixes/js/nav_focus）。
 *
 * 环画在内侧（负 offset + inset 阴影）：导航项彼此紧挨，
 * 外扩的环会被裁掉或压到相邻项上。
 */
html[data-a11y-focus-visible] .navigation .qin-a11y-navfocus {
    outline: 2px solid #1b44e8 !important;
    outline-offset: -2px !important;
    box-shadow: inset 0 0 0 2px #fff !important;
    background-color: #eef2ff !important;
}

/*
 * 兜底：某些主题里 DOM 焦点确实会落到链接上，或者 jQuery UI 版本会打
 * ui-state-* 状态类。这几条覆盖那些情况，多写无害。
 * :focus-within 是关键——它保证只有键盘真的停在导航里时才画环，
 * 鼠标悬停同样会触发 jQuery UI 的 focus()，不加这个判断会满屏乱闪。
 */
html[data-a11y-focus-visible] .navigation a:focus,
html[data-a11y-focus-visible] .navigation:focus-within a.ui-state-focus,
html[data-a11y-focus-visible] .navigation:focus-within a.ui-state-active,
html[data-a11y-focus-visible] .navigation:focus-within .ui-state-focus > a,
html[data-a11y-focus-visible] .navigation:focus-within .ui-state-active > a {
    outline: 2px solid #1b44e8 !important;
    outline-offset: -2px !important;
    box-shadow: inset 0 0 0 2px #fff !important;
}

/* ── 触控目标尺寸 · WCAG 2.2 SC 2.5.8 ───────────────────────── */

/*
 * 最小 24×24px。Luma 的若干图标按钮（关闭、数量增减、分页）低于这个尺寸。
 * 用 min-width/min-height 而非固定值，避免撑破已有布局。
 */
html[data-a11y-target-size] .action.close,
html[data-a11y-target-size] .action.delete,
html[data-a11y-target-size] .action.edit,
html[data-a11y-target-size] .action-close,
html[data-a11y-target-size] .pages .item .page,
html[data-a11y-target-size] .pages .action,
html[data-a11y-target-size] .control .qty,
html[data-a11y-target-size] .swatch-option {
    min-width: 24px;
    min-height: 24px;
}

/* 分页链接需要能点到，给足内边距 */
html[data-a11y-target-size] .pages .item .page,
html[data-a11y-target-size] .pages .action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 4px 8px;
}

/*
 * ── 第三方扩展与站点定制的小目标 ────────────────────────────
 *
 * 下面这些不是 Luma 原生，但在多个站上出现。CSS 规则在没有这些元素的站上
 * 完全惰性，所以放共用层零成本。
 *
 * 每条都标注了实测尺寸和来源，方便以后核对是不是还需要。
 */

/* Mageplaza Banner Slider 的轮播圆点。实测 24×20px，只差 4px 高。 */
/*
 * 可定制商品的选项链接（Itoris DynamicProductOptions）。
 *
 * 实测（2026-08-31）：
 *   W4L 首页   118 个不达标   60×18px    "4ft x 12ft" 这类尺寸选项
 *   PP  搜索页   2 个不达标   13×14px    "4ft" / "6ft"
 *   EK / SSD    没有这类元素，规则完全惰性（实测页面高度变化 0px）
 *
 * 两种失败方式都要覆盖：W4L 的宽度够、高度不足；PP 的宽高都不足。
 * 所以 min-width 和 min-height 缺一不可——只加 min-height 时 PP 那 2 个
 * 修不掉（实测验证过）。
 *
 * 用 line-height 而不是 padding 把高度撑到 24px：padding 会在原有尺寸上
 * 累加，把本来就合格的元素一起撑大；line-height 只影响行盒高度，
 * 对已经 ≥24px 的元素是空操作。同理 min-* 对够大的元素也不生效——
 * 这是这条规则能安全全站铺开的关键性质。
 *
 * 原元素是 display:inline，min-width/min-height 对行内盒无效，
 * 所以必须改成 inline-block。text-align:center 让短文本在撑开后居中。
 *
 * 代价：页面高度 W4L +3.0%、PP +0.3~0.5%。选项行之间略微拉开，
 * 字号、颜色、边框一律不变。
 */
html[data-a11y-target-size] .option-item-container > li > a,
html[data-a11y-target-size] .option-item-container > .option-item > a {
    display: inline-block;
    box-sizing: border-box;
    min-width: 24px;
    min-height: 24px;
    line-height: 24px;
    text-align: center;
}

html[data-a11y-target-size] button.owl-dot {
    min-height: 24px;
}

/*
 * 分层导航的筛选项。实测链接 131~172 × 19px，里面的复选框 13×13px。
 *
 * ⚠ 不要按具体的筛选器名字写选择器。上一版写的是 [data-bind*="brandFilter"]，
 *   结果只盖住了品牌筛选——实际还有 make_typeFilter 等等，每加一个筛选属性
 *   就会漏一个。改成按容器 #narrow-by-list 兜底（Magento 分层导航的标准 id）。
 *
 * 结构本身也有问题：<a> 里面套了 <input type="checkbox">，两个可交互元素
 * 嵌套。CSS 只能把尺寸撑够，结构要改模板。
 * 复选框从 13px 撑到 24px 视觉变化明显，上线后先看一眼是否可接受。
 */
html[data-a11y-target-size] #narrow-by-list a,
html[data-a11y-target-size] .filter-options-content a {
    display: flex;
    align-items: center;
    min-height: 24px;
}

html[data-a11y-target-size] #narrow-by-list input[type="checkbox"],
html[data-a11y-target-size] .filter-options-content input[type="checkbox"] {
    width: 24px;
    height: 24px;
}

/*
 * SSD 的商品卡片选项链接（.ssd-config-links > a[data-option-item]）。
 *
 * 两个维度都不够，而且是不同的子集：
 *   · 文字型（"Width: 16-48ft"）实测 87 × 18.9px  → 高度不够
 *   · 数字型（"1" "2" "3"）  实测 7.8 × 18.9px    → 宽高都不够
 *
 * 父容器是 display:flex + flex-wrap:wrap，单字符的项自然只有一个字宽。
 *
 * 用 min-* 而不是 padding：padding 会把每一项都撑大，min-* 只影响不达标的。
 * 已实测容器 overflow:visible、max-height:none，加宽只会自然换行变高，
 * 不会出现「看不见却能 Tab 到」的陷阱（那比原问题更严重）。
 *
 * text-align 只对被撑宽的那些生效——flex 项的宽度由内容决定，
 * 本来就够宽的项加了也看不出变化。
 */
html[data-a11y-target-size] .ssd-config-links a[data-option-item] {
    min-height: 24px;
    min-width: 24px;
    text-align: center;
}

/*
 * 页脚链接。实测 PP 页脚：142.5 × 19px，每页 19 条。
 *
 * 容器 class 各站不同（PP 是 .footer_info_list / .footer_info_box），
 * 所以按 <footer> / .page-footer 这个语义容器兜底，不列举定制 class。
 *
 * 用 min-height + inline-flex 让文字垂直居中，不用 padding——
 * padding 会把所有链接都撑大，min-height 只影响不达标的。
 */
html[data-a11y-target-size] .page-footer a,
html[data-a11y-target-size] footer a {
    display: inline-flex;
    align-items: center;
    min-height: 24px;
}

/* ── 链接下划线 · WCAG SC 1.4.1 ─────────────────────────────── */

/*
 * 只作用于「正文里的链接」——即被普通文字包围、单靠颜色无法与周围文字
 * 区分开的那种。这是 SC 1.4.1 真正要解决的情况。
 *
 * 商品卡片标题、导航、面包屑、按钮不在此列：它们靠位置和形状已经能辨认，
 * 周围也没有需要与之区分的正文，加下划线只会让页面变乱。
 * 用户如果就是想给所有链接加下划线，那是 Qin_EasyAccess 面板里的
 * "Underline all links"——那是用户主动选择，两回事。
 *
 * 不要写 `.column.main li a`。Magento 的商品列表是
 * <ol class="products list items"><li class="product-item"><a class="product-item-link">，
 * 那条选择器会把每个商品标题都划上线。
 */
/*
 * ⚠ 不要靠列举容器。之前写的是 .column.main p / .cms-content /
 *   [data-content-type=text] / .product.attribute.description 四个容器，
 *   结果漏掉了 cookie 提示（div[role="document"] > p > a）——PP 上 10 处，
 *   每个页面都有。这是我第四次栽在「按容器 class 划范围」上。
 *
 * 改成按结构：<p> 里的链接**就是**正文里的链接。这正是 axe 的
 * link-in-text-block 所判定的情形，用 p 作锚点比列举容器稳得多。
 *
 * 导航和商品列表不受影响——那些链接的父级是 <li>/<div>，不是 <p>。
 * 排除按钮类：正文里偶尔会放 CTA 按钮，那种靠形状已能辨认。
 */
html[data-a11y-link-underline] p a:not(.action):not([class*="btn"]):not([class*="button"]),
html[data-a11y-link-underline] .cms-content a:not(.action),
html[data-a11y-link-underline] [data-content-type="text"] a:not(.action),
html[data-a11y-link-underline] .product.attribute.description a:not(.action),
html[data-a11y-link-underline] .product.attribute.description li a:not(.action) {
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* ── 文字对比度 · WCAG SC 1.4.3 ─────────────────────────────── */

/*
 * 「当前页」的文字。Magento 把导航里指向当前页的那一项渲染成 <strong>
 * 而不是链接，并用一个更浅的灰色。实测 #a6a6a6 在 #f4f4f4 上只有 2.21:1。
 *
 * 这个颜色来自 Magento 框架级变量，不是品牌色：
 *   lib/web/css/source/lib/variables/_colors.less:113
 *   @primary__color__light: lighten(@primary__color, 45%);  // #a6a6a6
 * 所以主题和品牌色完全不同的两个站会出现一模一样的失败值——共用层该管。
 *
 * #666666 在 #f4f4f4 上 5.22:1，在纯白上 5.74:1，两种底色都够。
 * 仍是「灰色的次要文字」，观感几乎无变化。
 *
 * ⚠ 实测这个元素在**页脚导航**里，不在面包屑：
 *      strong  ←  li.nav.item.current  ←  ul.footer.links
 *   只写 .breadcrumbs 的选择器会完全打不中（上一版就是这么漏掉的）。
 *   下面同时覆盖页脚、面包屑和账户侧栏三处「当前项」。
 *
 * 只改已知失败的选择器，不动 @primary__color__light 的其他用途——
 * 那个变量在别处未必用于文字，全局改会波及不该动的地方。
 */
html[data-a11y-text-contrast] .footer .links .current > strong,
html[data-a11y-text-contrast] li.nav.item.current > strong,
html[data-a11y-text-contrast] .breadcrumbs strong,
html[data-a11y-text-contrast] .breadcrumbs .current > strong,
html[data-a11y-text-contrast] .account-nav .current > strong {
    color: #666666;
}

/*
 * 社交登录按钮（Mageplaza SocialLogin，配色来自 Bootstrap Social）。
 *
 * 实测三站一致：
 *   .btn-google  白字 on #dd4b39 = 4.09:1  ✗（需 4.5）
 *   .btn-amazon  白字 on #ff9900 = 2.14:1  ✗
 *   .btn-facebook 白字 on #3b5998 = 6.84:1 ✓ 不动
 *
 * 配色在扩展的 vendor/ 代码里，改了升级会被覆盖——所以在共用层压过它。
 *
 * Google：压暗到 #bf4030 = 5.26:1，色相不变。
 * Amazon：金色配白字物理上到不了 4.5（要压暗到 #a35f00 才行，那就不是
 *         Amazon 的金色了）。改成深色文字：#1a1a1a on #ff9900 = 8.13:1，
 *         底色一点不动。
 *
 * 顺带一提，这两个改动其实更贴近两家**现在**的品牌规范：
 * #dd4b39 是 Bootstrap Social 的老配色，Google 官方登录按钮早就改成
 * 白底深字或 #4285F4 蓝底白字；Amazon 官方的 Login with Amazon
 * 本来就是金底**深字**。
 *
 * hover/focus 一并处理，否则悬停时会跳回不达标的颜色。
 */
html[data-a11y-text-contrast] .btn-google,
html[data-a11y-text-contrast] .btn-google:hover,
html[data-a11y-text-contrast] .btn-google:focus {
    background-color: #bf4030;
    border-color: #bf4030;
    color: #ffffff;
}

html[data-a11y-text-contrast] .btn-amazon,
html[data-a11y-text-contrast] .btn-amazon:hover,
html[data-a11y-text-contrast] .btn-amazon:focus {
    color: #1a1a1a;
}

/* 图标继承 color，但有的主题给它单独设了色，这里一并对齐 */
html[data-a11y-text-contrast] .btn-amazon .fa,
html[data-a11y-text-contrast] .btn-amazon span {
    color: inherit;
}

/*
 * 后台内容里粘进来的内联橙色 #eb5202。
 *
 * PP 实测：商品描述和结账运费备注里都有人手写了
 *   <ul style="...;color:#eb5202">  →  白底 3.66:1，不达标（需 4.5）
 *
 * 这些是数据库里的内容，不是代码。挨个改商品描述不现实，而且下次再粘
 * 一段又会回来。改用属性选择器命中「内联把文字设成这个色」的元素，
 * 一次覆盖现有的和将来的。压暗到 #b33e00 = 5.82:1，同色相，观感几乎一样。
 *
 * 只匹配 color:，不匹配 background:——同一个色值当底色用时白字是达标的，
 * 那种情况不能动。加 i 标志是因为后台可能写成大写 #EB5202。
 *
 * 内联样式优先级高于任何外部规则，所以这里必须用 !important。
 */
html[data-a11y-text-contrast] [style*="color:#eb5202" i],
html[data-a11y-text-contrast] [style*="color: #eb5202" i] {
    color: #b33e00 !important;
}

/*
 * 上面那条改完之后的连带问题（PP 结账页实测）。
 *
 *   <ul style="color:#eb5202">
 *     <li>*Express shipping please call us <a href="tel:...">(626)715-4869</a> …</li>
 *
 * 正文变成合规色之后，里面的电话链接仍是主题的蓝色，于是链接和周围文字
 * 之间**只剩颜色差异**——违反 SC 1.4.1 Use of Color（axe: link-in-text-block）。
 * 补下划线，不依赖颜色也能认出是链接。
 *
 * ⚠ 不能只盯 #eb5202。这条违规恰恰是在颜色**改对之后**才冒出来的——
 *   底色合规了，链接却还靠颜色区分。所以判据是「内联设了 color 的内容块」，
 *   而不是某个具体色值。
 *
 * ⚠ 不能写 [style*="color:"]——background-color: 里也含 "color:" 这个子串，
 *   那会把只设了底色的版式容器一并命中，波及里面所有链接。
 *   只匹配位于开头或紧跟 ; 的 color:，前面带连字符的就排除掉了。
 */
/*
 * 同一个不达标橙 #eb5202，这次写在主题编译出的 styles-m.css 里，
 * 不是内联样式，所以上面那条属性选择器够不着。
 *
 * W4L 商品页实测 3 处，全是 #eb5202 白底 = 3.65:1（需 4.5）：
 *   .product-options-wrapper .fieldset .custom-unavailable-hints
 *   .product_extra_notes ul li.highlight-item
 *
 * ⚠ 这里确实是在列举选择器——我一向避免这么做，因为按容器命名划范围
 *   换个容器就失效。但 CSS 无法按「计算出的颜色值」选择元素，而为这
 *   3 个节点引入一个扫描样式表的 JS 层不划算。
 *
 *   durable 的修法是在 W4L 主题的 LESS 里把这个色值改掉（那是他们
 *   自己的主题，不是 vendor，改了不会被升级覆盖）。这条规则是过渡，
 *   源头改完可以删。
 *
 * 压暗到 #b33e00 = 5.82:1，同色相，与 PP 上用的是同一个替代色。
 *
 * ⚠ 选择器必须写全主题那条的完整链路，否则特异性不够、压不过去：
 *     主题  .product-options-wrapper .fieldset .custom-unavailable-hints  (0,3,0)
 *     只写  html[data-a11y-text-contrast] .custom-unavailable-hints       (0,2,1)  ← 输
 *   属性选择器只算一个 class 的权重，抵不过主题多出来的那一层。
 *   第一版就栽在这里，3 处只修掉 2 处。
 */
html[data-a11y-text-contrast] .product-options-wrapper .fieldset .custom-unavailable-hints,
html[data-a11y-text-contrast] .product_extra_notes ul li.highlight-item {
    color: #b33e00;
}

html[data-a11y-text-contrast] [style^="color:" i] a,
html[data-a11y-text-contrast] [style*=";color:" i] a,
html[data-a11y-text-contrast] [style*="; color:" i] a {
    text-decoration: underline;
}

/*
 * 宽度写死的嵌入内容（iframe）· WCAG SC 1.4.10 Reflow
 *
 * W4L 分类页实测：CMS 内容里嵌了 <iframe width="500px"> 的 YouTube 播放器。
 * 320px 视口下 scrollWidth 撑到 515，整页出现横向滚动——1.4.10 明确要求
 * 内容在 320 CSS 像素宽度下无需横向滚动即可使用。
 *
 * 这一条和播放器**内部**的标记问题不同：内部标记是 YouTube 的，我们改不了
 * （审计里按 origin 排除）；但 iframe 自身的尺寸是我们的 HTML，能改。
 *
 * 按结构判断——任何 iframe 都不该突破容器宽度，与它嵌的是视频、地图
 * 还是支付框无关。不写 max-height：高度溢出会自然产生纵向滚动，
 * 那是可接受的；1.4.10 管的是横向。
 *
 * 对本来就不超宽的 iframe 完全惰性（max-width 只在超出时生效）。
 */
html[data-a11y-overlap] iframe {
    max-width: 100%;
}

/* ── 极窄视口下的重叠 · WCAG SC 1.4.10 Reflow ───────────────── */

/*
 * 分类页工具栏：「Shop By」按钮把「Sort By」标签盖住了。
 *
 * 实测机制（enksunrise.com 分类页）：
 *   strong "Shop By" : position:absolute, left:0,       宽 75px, z-index:2
 *   .toolbar-sorter  : position:absolute, left:35.15px, 宽 205px, z-index:1
 *
 * 两个都绝对定位在同一行，Luma 给排序器算的左偏移（35px）小于按钮实际
 * 宽度（75px），而按钮 z-index 更高，于是把 "Sort By" 压在下面。
 *
 * 触发宽度：≤280px 才重叠，290px 以上正常。
 *
 * ⚠ 这一档**低于 WCAG 1.4.10 要求的 320px**——标准那一档实测是通过的。
 *   修它是因为「刚好卡在线上、再窄 10px 就塌」不是个稳的状态：
 *   用户会用更小的窗口、更高的缩放倍数。
 *
 * 修法是在极窄处取消绝对定位，让两者自然堆叠成两行。
 * 不去调左偏移——排序器本身宽 205px，再往右推就会溢出视口。
 *
 * 只在 ≤320px 生效，之上完全惰性，不影响正常布局。
 */
@media (max-width: 320px) {
    html[data-a11y-overlap] .toolbar-products .toolbar-sorter,
    html[data-a11y-overlap] .block.filter .filter-title strong,
    html[data-a11y-overlap] .filter-title > strong {
        position: static;
    }
}

/* ── 通用 ────────────────────────────────────────────────────── */

/*
 * 屏幕阅读器专用文本。Luma 自带的 .visually-hidden 在部分定制主题里
 * 被改过，这里提供一个不会被覆盖的版本，供 JS 补丁插入 live region 时使用。
 */
.qin-a11y-sr {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    margin: -1px !important;
    padding: 0 !important;
    overflow: hidden !important;
    clip: rect(0 0 0 0) !important;
    clip-path: inset(50%) !important;
    white-space: nowrap !important;
    border: 0 !important;
}
