diff --git a/skills/htmlit/client/client.css b/skills/htmlit/client/client.css index d8df0ef..aab4e0e 100644 --- a/skills/htmlit/client/client.css +++ b/skills/htmlit/client/client.css @@ -107,11 +107,11 @@ .log { flex: 1; overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 10px; } /* Minimal scrollbars inside the review chrome, so they don't clash with the browser's default scrollbar on the artifact. */ -.log, .rail .card, .ce, .selmenu { scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--muted) 45%, transparent) transparent; } -.log::-webkit-scrollbar, .rail .card::-webkit-scrollbar, .ce::-webkit-scrollbar { width: 7px; height: 7px; } -.log::-webkit-scrollbar-thumb, .rail .card::-webkit-scrollbar-thumb, .ce::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--muted) 38%, transparent); border-radius: 7px; } +.log, .rail > .card, .ce, .selmenu { scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--muted) 45%, transparent) transparent; } +.log::-webkit-scrollbar, .rail > .card::-webkit-scrollbar, .ce::-webkit-scrollbar { width: 7px; height: 7px; } +.log::-webkit-scrollbar-thumb, .rail > .card::-webkit-scrollbar-thumb, .ce::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--muted) 38%, transparent); border-radius: 7px; } .log::-webkit-scrollbar-thumb:hover, .ce::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--muted) 60%, transparent); } -.log::-webkit-scrollbar-track, .rail .card::-webkit-scrollbar-track, .ce::-webkit-scrollbar-track { background: transparent; } +.log::-webkit-scrollbar-track, .rail > .card::-webkit-scrollbar-track, .ce::-webkit-scrollbar-track { background: transparent; } .bubble { max-width: 86%; padding: 8px 11px; border-radius: 12px; line-height: 1.4; white-space: pre-wrap; word-break: break-word; } .bubble small { display: block; font-size: 10px; text-transform: uppercase; letter-spacing: 0.04em; opacity: 0.6; margin-bottom: 3px; } .bubble.user { align-self: flex-end; background: var(--user); color: var(--user-text); } @@ -165,8 +165,8 @@ /* comment rail (Google-Docs-style): cards docked in the right margin, just left of the review panel, each vertically aligned to its highlighted text/element. */ .rail { position: fixed; inset: 0; z-index: 2147482002; pointer-events: none; } -.rail .card { position: fixed; width: 276px; box-sizing: border-box; pointer-events: auto; background: var(--elev); color: var(--text); border: 1px solid var(--border); border-left: 3px solid var(--accent); border-radius: 8px; box-shadow: var(--shadow); padding: 10px 12px 10px 11px; transition: top 0.12s ease, left 0.12s ease; } -.rail .card.draft { border-left-color: var(--muted); border-left-style: dashed; } +.rail > .card { position: fixed; width: 276px; box-sizing: border-box; pointer-events: auto; background: var(--elev); color: var(--text); border: 1px solid var(--border); border-left: 3px solid var(--accent); border-radius: 8px; box-shadow: var(--shadow); padding: 10px 12px 10px 11px; transition: top 0.12s ease, left 0.12s ease; } +.rail > .card.draft { border-left-color: var(--muted); border-left-style: dashed; } .rail .card-draft { font-size: 11px; color: var(--muted); margin: -2px 0 7px; } .rail .card-q { font-size: 11.5px; line-height: 1.5; color: var(--muted); background: color-mix(in srgb, var(--accent) 10%, transparent); border-radius: 4px; padding: 3px 7px; margin: 0 0 8px; max-height: calc(3em + 6px); overflow: hidden; cursor: pointer; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } .rail .card-q::before { content: "\201C"; } .rail .card-q::after { content: "\201D"; } @@ -174,7 +174,7 @@ .rail .cmt { display: flex; align-items: flex-start; gap: 6px; } .rail .cmt-txt { flex: 1; min-width: 0; font-size: 13px; line-height: 1.4; white-space: pre-wrap; word-break: break-word; } .rail .cmt-edit { flex: none; border: none; background: none; color: var(--muted); cursor: pointer; font-size: 12px; padding: 1px 3px; border-radius: 4px; opacity: 0; } -.rail .card:hover .cmt-edit { opacity: 1; } +.rail > .card:hover .cmt-edit { opacity: 1; } .rail .cmt-edit:hover { color: var(--accent); background: var(--user); } .rail .cmt.editing { display: block; } .rail .cmt-editta { width: 100%; box-sizing: border-box; min-height: 42px; max-height: 260px; overflow-y: auto; padding: 7px 9px; border: 1px solid var(--border); border-radius: 6px; background: var(--bg); color: var(--text); font: inherit; font-size: 13px; line-height: 1.45; white-space: pre-wrap; word-break: break-word; text-align: left; } diff --git a/tests/client/collapsed-anchor.test.mjs b/tests/client/collapsed-anchor.test.mjs index e8ff206..59cf24d 100644 --- a/tests/client/collapsed-anchor.test.mjs +++ b/tests/client/collapsed-anchor.test.mjs @@ -2,7 +2,8 @@ * Browser regression test for comment cards whose anchor sits inside a collapsed * section (a CSS radio "option"): the card must stay in the rail instead of * vanishing, "View in document" must reveal the option and scroll to it, and the - * agent's answer must render its markup (a numbered list keeps its numbers). + * agent's answer must render its markup without promoting an artifact .card into + * a separate fixed rail card. * * Skips rather than fails when no browser or Python is available. */ @@ -34,11 +35,14 @@ function readState() { const sr = document.getElementById("htmlit-chrome").shadowRoot; const card = sr.querySelector('.rail .card[data-id="cm-b"]'); const body = card && card.querySelector(".card-answer-body"); + const answerCard = body && body.querySelector(".card"); const answer = document.querySelector('[data-htmlit-answer-for="cm-b"]'); return { cardExists: Boolean(card), cardVisible: Boolean(card) && getComputedStyle(card).display !== "none", + cardPosition: card ? getComputedStyle(card).position : null, answerRich: Boolean(body) && body.classList.contains("rich"), + answerCardPosition: answerCard ? getComputedStyle(answerCard).position : null, listItems: body ? body.querySelectorAll("ol li").length : 0, answerShown: Boolean(answer) && answer.getClientRects().length > 0, bChecked: document.getElementById("s-b").checked, @@ -80,9 +84,11 @@ test("a comment in a collapsed option stays carded, reveals on jump, and renders const before = await page.evaluate(readState); assert.equal(before.cardExists, true); assert.equal(before.cardVisible, true, "card should stay visible while Option B is collapsed"); + assert.equal(before.cardPosition, "fixed", "the rail comment card should stay fixed"); assert.equal(before.bChecked, false); assert.equal(before.answerShown, false, "the answer/anchor is collapsed to start"); assert.equal(before.answerRich, true); + assert.equal(before.answerCardPosition, "static", "artifact .card content should remain inside the agent answer"); assert.equal(before.listItems, 3, "the answer's numbered list should render, not flatten to text"); await page.evaluate(() => document.getElementById("htmlit-chrome").shadowRoot.querySelector('.rail .card[data-id="cm-b"] .card-answer-jump').click()); diff --git a/tests/client/fixtures/collapsed-option.html b/tests/client/fixtures/collapsed-option.html index 1b385fc..8fa38eb 100644 --- a/tests/client/fixtures/collapsed-option.html +++ b/tests/client/fixtures/collapsed-option.html @@ -24,12 +24,14 @@
Take a maintenance window: freeze writes, dump, restore, repoint, unfreeze.
Concretely, the window looks like this:
-Concretely, the window looks like this:
+Option C detail.