/* 右键菜单 + Edge 材质公共件 — 统一设计语言 §4.1 落地(2026-08-30 · A-28 趟 2)
 *
 * 真相源:docs/DESIGN_LANGUAGE_2026_08_29.md §3 令牌 / §4.1 右键菜单;
 * 演示页对照:docs/design_demo/01-context-menu.html + demo.css §1–5。
 *
 * 本文件除右键菜单本体外,还提供三块**公共件**——词义弹窗与句译弹窗直接复用,
 * 三块浮层因此天然同材质、同行高、同分隔线:
 *   .dl-float   浮层出入场(瞬时,无位移无缩放)
 *   .dl-mat-edge Edge 材质(不透明面 + --dl-sh-menu;深色由阴影第一层的白 ring 描边)
 *   .dl-sep / .dl-menu__item / .dl-ico / .dl-iconbtn / .dl-dots
 *
 * 令牌:一律裸 var(--dl-x),不带回退值——design-tokens.css 已由 base.html 与
 * viewer.html 在 style.css 之前引入(A-28 趟 1)。
 */

/* === 浮层出入场(§3.7:瞬时出现、瞬时消失,无 transition / 无位移 / 无缩放)===
 *
 * position: fixed 且挂在 <body> 下(不在 #pdf-viewer 的缩放子树里)——
 * §8-4「浮层不随页面缩放」:弹窗与菜单是浏览器级工具,不是试卷内容。
 */
.dl-float {
    position: fixed;
    top: 0;
    left: 0;
    opacity: 0;
    pointer-events: none;
    font-family: var(--dl-font);
    /* 工具层不留任何过渡:高频重开时淡入淡出会两团交叠发糊 */
    transition: none;
    box-sizing: border-box;
}

.dl-float * {
    box-sizing: border-box;
}

/* 浮层自身可能带 display:flex/grid,会盖掉 UA 的 [hidden]{display:none};补一条 */
.dl-float[hidden] {
    display: none !important;
}

/* .visible 是阅读器既有浮层的开态类名(overlayManager / 各 tooltip 都在用),
   与本组件的 .is-open 等价,两个都认,免得各处再各写一遍开态 */
.dl-float.is-open,
.dl-float.visible {
    opacity: 1;
    pointer-events: auto;
}

/* === Edge 材质:不透明面 + 阴影当描边,不用 border、不用 backdrop-filter === */
.dl-mat-edge {
    background: var(--dl-surface);
    border-radius: var(--dl-r-pop);
    box-shadow: var(--dl-sh-menu);   /* 第一层 0 0 0 1px 即发丝描边(深浅两套) */
}

/* === 指向锚点的小箭头(P-06,2026-09-03)===
 *
 * 只有「贴着锚点出现」的两种弹窗要它:词义弹窗(锚=词框)、句译弹窗(锚=句子首/末行)。
 * 用法:定位算完后由 JS 写两个值 —— data-caret=朝向、--dl-caret-pos=沿边中心坐标(px,
 * 弹窗自身坐标系,即缩放前的 CSS px)。data-caret 的值说的是**箭头长在哪条边**:
 *   left   弹窗在锚点右侧 → 箭头在左边,向左指
 *   right  弹窗在锚点左侧 → 箭头在右边,向右指
 *   top    弹窗在锚点下方 → 箭头在上边,向上指
 *   bottom 弹窗在锚点上方 → 箭头在下边,向下指
 *
 * 形制:10×10 正方形旋转 45°,底色与面板同 --dl-surface,只给**朝外的两条边**上 1px 描边,
 * 与本体的 ring 接成一条线;另两条边不画,靠白底把本体那段 ring 盖掉,base 处无横线。
 * 旋转后原边与外观的对应(顺时针 45°):top→右上、right→右下、bottom→左下、left→左上。
 * 偏移 -6 = 半边长 5 + ring 1:让方块两个侧角正好落在 ring 线上,接缝无 1px 断茬;
 * 尖端因此外伸 5√2+1 ≈ 8px,弹窗与锚点的 12px 间距(ANCHOR_GAP)不变。
 */
.dl-mat-edge[data-caret] {
    overflow: visible;
}

.dl-mat-edge[data-caret]::before {
    content: '';
    position: absolute;
    width: 10px;
    height: 10px;
    box-sizing: border-box;
    background: var(--dl-surface);
    transform: rotate(45deg);
    pointer-events: none;
}

.dl-mat-edge[data-caret="left"]::before {
    left: -6px;
    top: calc(var(--dl-caret-pos, 50%) - 5px);
    border-left: 1px solid var(--dl-line-pop);
    border-bottom: 1px solid var(--dl-line-pop);
}

.dl-mat-edge[data-caret="right"]::before {
    right: -6px;
    top: calc(var(--dl-caret-pos, 50%) - 5px);
    border-top: 1px solid var(--dl-line-pop);
    border-right: 1px solid var(--dl-line-pop);
}

.dl-mat-edge[data-caret="top"]::before {
    top: -6px;
    left: calc(var(--dl-caret-pos, 50%) - 5px);
    border-top: 1px solid var(--dl-line-pop);
    border-left: 1px solid var(--dl-line-pop);
}

.dl-mat-edge[data-caret="bottom"]::before {
    bottom: -6px;
    left: calc(var(--dl-caret-pos, 50%) - 5px);
    border-bottom: 1px solid var(--dl-line-pop);
    border-right: 1px solid var(--dl-line-pop);
}

/* === 图标(§4.1:16 槽内 16×16 线性图标,1.5 描边)===
 *
 * 刻意**不加** vector-effect: non-scaling-stroke。浮层虽然自身不随页面缩放,
 * 但同一套类会被缩放子树里的控件(答案选择器)复用,描边必须跟着一起缩放,
 * 否则放大后图标线条相对变细、与同屏文字脱节。
 */
.dl-ico {
    flex: none;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.dl-ico--fill {
    fill: currentColor;
    stroke: none;
}

/* === 分隔线(§3.6:上 7 / 线 1 / 下 8,左右内缩 1)=== */
.dl-sep {
    height: var(--dl-sep-h);
    margin: var(--dl-sep-margin);
    background: var(--dl-line);
}

/* === 紧凑行(§4.1 行规格;词义 / 句译弹窗的动作行同款)=== */
.dl-menu__item {
    display: grid;
    /* [16 图标槽][10 间隙][文字 1fr][快捷键 auto] —— 无图标行文字仍从 38 起 */
    grid-template-columns: var(--dl-icon) var(--dl-icon-gap) 1fr auto;
    align-items: center;
    height: var(--dl-row);
    padding: var(--dl-item-pad);
    border-radius: var(--dl-r-item);
    color: var(--dl-ink);
    background: transparent;
    border: 0;
    width: 100%;
    text-align: left;
    font-family: inherit;
    font-size: var(--dl-fs-body);
    line-height: var(--dl-lh-body);
    cursor: default;
    transition: none;
}

.dl-menu__label {
    grid-column: 3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: clip;
}

.dl-menu__icon {
    grid-column: 1;
    display: grid;
    place-items: center;
    color: var(--dl-ink);
}

.dl-menu__sc {
    grid-column: 4;
    margin-left: var(--dl-sp-24);
    color: var(--dl-ink-2);
    white-space: nowrap;
}

.dl-menu__item:hover:not([aria-disabled="true"]),
.dl-menu__item.is-active:not([aria-disabled="true"]) {
    background: var(--dl-hover-strong);
}

.dl-menu__item[aria-disabled="true"] {
    color: var(--dl-ink-disabled);
}

.dl-menu__item[aria-disabled="true"] .dl-menu__icon {
    color: var(--dl-ink-disabled);
}

/* 键盘焦点与悬停同一块高亮:菜单里高亮就是「当前项」,不再叠一圈焦点环 */
.dl-menu__item:focus,
.dl-menu__item:focus-visible {
    outline: none;
    box-shadow: none;
    background: var(--dl-hover-strong);
}

/* === 带 ▾ 的行(§3.30-3:「加入单词本」行右端展开选本子菜单)===
 *
 * 主区与 ▾ 是两个按钮(button 不能嵌 button),外层 flex 行把它们并排。
 * ▾ 热区固定 24px,前面一条细分隔线 —— 让「点文字 = 加默认本」与「点 ▾ = 选本」
 * 在按下之前就分得开。 */
.dl-menu__row {
    display: flex;
    align-items: center;
}

.dl-menu__row > .dl-menu__item {
    flex: 1 1 auto;
    min-width: 0;
}

.dl-menu__caret {
    position: relative;
    flex: none;
    width: 24px;
    height: var(--dl-row);
    display: grid;
    place-items: center;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--dl-ink-2);
    border-radius: var(--dl-r-item);
    cursor: default;
    transition: none;
}

/* 细分隔线:上下各内缩 6px,不顶满行高 */
.dl-menu__caret::before {
    content: '';
    position: absolute;
    left: 0;
    top: 6px;
    bottom: 6px;
    width: 1px;
    background: var(--dl-line);
}

.dl-menu__caret:hover,
.dl-menu__caret[aria-expanded="true"] {
    background: var(--dl-hover-strong);
    color: var(--dl-ink);
}

.dl-menu__caret:focus-visible {
    outline: none;
    box-shadow: var(--dl-focus-ring);
}

/* 子菜单:比主菜单窄,内容是单词本名字 */
.dl-menu--sub {
    min-width: 160px;
}

/* 子菜单行没有图标,16 槽 + 10 间隙就成了一段读不出意思的左空白 —— 收掉图标槽,
   让本名从行内边距起笔(= 主菜单行图标的起笔处),与 .dl-menu__hint 同一条竖线。
   行高、字号、内边距、悬停底色都不动。 */
.dl-menu--sub .dl-menu__item {
    grid-template-columns: 0 0 1fr auto;
}

.dl-menu--sub .dl-menu__icon {
    display: none;
}

/* 子菜单的载入 / 空 / 失败一行 —— 不是可选项,故不是 .dl-menu__item */
.dl-menu__hint {
    display: flex;
    align-items: center;
    height: var(--dl-row);
    padding: var(--dl-item-pad);
    color: var(--dl-ink-2);
    white-space: nowrap;
}

/* === 图标钮(弹窗内 28 圆钮,§3.6 --dl-ctl-sm)=== */
.dl-iconbtn {
    width: var(--dl-ctl-sm);
    height: var(--dl-ctl-sm);
    display: grid;
    place-items: center;
    border: 0;
    padding: 0;
    background: transparent;
    border-radius: var(--dl-r-item-lg);
    color: var(--dl-ink-2);
    cursor: default;
    transition: none;
}

.dl-iconbtn:hover {
    background: var(--dl-hover);
}

.dl-iconbtn:active {
    background: var(--dl-pressed);
}

.dl-iconbtn.is-on {
    color: var(--dl-ink);
}

.dl-iconbtn:focus-visible {
    outline: none;
    box-shadow: var(--dl-focus-ring);
}

/* === 思考三点(S:watson-think 同款 4px 三点)=== */
.dl-dots {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: var(--dl-lh-body);
}

.dl-dots i {
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: var(--dl-ink-3);
    animation: dl-dot 1.2s infinite ease-in-out;
}

.dl-dots i:nth-child(2) { animation-delay: .15s; }
.dl-dots i:nth-child(3) { animation-delay: .3s; }

@keyframes dl-dot {
    0%, 60%, 100% { opacity: .28; }
    30% { opacity: 1; }
}

/* === §4.1 右键菜单本体 === */
.dl-menu {
    width: fit-content;
    min-width: 200px;
    max-width: 320px;
    padding: var(--dl-pad-panel);
    z-index: var(--dl-z-context-menu);
    font-size: var(--dl-fs-body);
    line-height: var(--dl-lh-body);
    color: var(--dl-ink);
}

.dl-menu:focus {
    outline: none;
}

/* === 阅读器主题适配(规范 §3.2 判例,2026-08-30)===
 *
 * 深色 --dl-surface 在宿主主题内取**宿主面色**:阅读器浮层取 #18181B
 * (= --theme-surface rgba(24,24,27,.95) 去 alpha),不取令牌表的石板蓝 #1E293B。
 * 理由:阅读器深色下周边一切(页底、工具钮、题号圈)都是近中性灰黑,浮层独自带蓝
 * 会让同屏出现两种「黑」。描边 / 悬停 / 按下 / ring 这些**角色**令牌照用令牌表深色值。
 *
 * 墨色同理跟随宿主(与答案选择器 --ias-ink 的取法一致),否则同屏两种字色。
 * 护眼态按 §3.2 走浅色令牌 + 自身面色 #FFFCF7。
 */
html.theme-dark .dl-float,
html.theme-eye-care .dl-float {
    --dl-ink: var(--theme-text);
    --dl-ink-2: var(--theme-text-secondary);
}

html.theme-dark .dl-float {
    --dl-surface: #18181B;
    /* 次级块(句译弹窗原文块)沿令牌表方向取「比面板更深」,用宿主页底色 */
    --dl-surface-2: #0F0F11;
    /* 焦点环内圈的隔离色跟随浮层底色 */
    --dl-focus-ring: 0 0 0 2px #18181B, 0 0 0 4px rgba(49, 130, 206, .55);
}

html.theme-eye-care .dl-float {
    --dl-surface: #FFFCF7;
    /* 浅色下 surface-2 比面板暗约 5%(#F3F3F4 之于 #FFFFFF);在暖底上按同一比例取 */
    --dl-surface-2: color-mix(in srgb, var(--theme-bg-secondary) 60%, #FFFCF7);
    /* 护眼是亮底,焦点环跟主令牌一起去蓝(A4);深色那一支保持原值,中性环在暗底上看不见 */
    --dl-focus-ring: 0 0 0 2px #FFFCF7, 0 0 0 4px rgba(13, 13, 13, .40);
}
