From 54f3531833fa7bfdf8279591a0d581e2966a6755 Mon Sep 17 00:00:00 2001 From: Vuong Hoang Date: Mon, 28 Sep 2026 10:23:01 -0700 Subject: [PATCH] =?UTF-8?q?fix(as-S2):=20legibility=20=E2=80=94=20nothing?= =?UTF-8?q?=20fades,=20labels=2011px,=20sentences=2012px?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From the anti-slop run (design-dev, 2026-09-28). Faded is not legible: opacity divides whatever contrast a line had. - Review arrows: the chip under the thin chevron is 82% dense, not 60%; the glyph now clears 7:1 over a white stage by colour (was 3.84:1), and reads at pixel level where the detector sampled a 2.9:1 median. - Filmstrip numbers, the marks' state stamp and the inline ask's state tag are labels at 11px (were 9.5 / 10.5 / 10.5px). - The Desk's section rules, the board note and the bench note are sentences at 12px. - Retired benches: no opacity; the link and URL take --text-muted. - Embed chrome: answered-ask details and the "recorded:" line inherit the host's text colour at full strength (the embed cannot know the host's palette); the notes placeholder inherits it at 75%, not the UA grey. Folded from the heid bug-hunt: the embed's ask title no longer fades either (Q9), and the legibility claims are also held on the browser's COMPUTED style (tests/test_antislop_s2_browser.py): a stylesheet grep cannot see a later rule in the cascade (font-size:1px, color:transparent, filter:grayscale, a placeholder at opacity:0); the browser can. Folded after the first gate run: the flagged tray's number, the tile's "flagged" stamp and compare's A/B badge were still under the 11px label floor; they take --size-micro too. Two film-number rows are re-anchored on the .film-ord selector: the tray's line is now identical to it, and the runner mutates the first match. Contract: as_antislop S2. Falsifiers: antislop.toml 34/34 proved (S1+S2); all 12 tables 314/314 proved on this tree. --- booth/static/embed.js | 14 ++- booth/templates/base.html | 19 ++-- booth/templates/view.html | 2 +- docs/contracts/as_antislop.contract.md | 35 +++++- tests/mutations/antislop.toml | 144 +++++++++++++++++++++++++ tests/test_antislop.py | 109 +++++++++++++++++++ tests/test_antislop_s2_browser.py | 96 +++++++++++++++++ 7 files changed, 401 insertions(+), 18 deletions(-) create mode 100644 tests/test_antislop_s2_browser.py diff --git a/booth/static/embed.js b/booth/static/embed.js index 2d24f96..31e3e66 100644 --- a/booth/static/embed.js +++ b/booth/static/embed.js @@ -73,12 +73,12 @@ ".bk-ask.bk-done{border-top-color:var(--bk-done)}", ".bk-ask.bk-skip{border-top-color:var(--bk-skip)}", ".bk-ask-tag{display:inline-block;margin-bottom:.6rem;padding:2px 7px;border:1.5px solid currentColor;border-radius:3px;", - "font:600 10.5px/1.3 'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;", + "font:600 11px/1.3 'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;", "letter-spacing:.12em;text-transform:uppercase;color:var(--bk-open-text)}", ".bk-ask.bk-done .bk-ask-tag{color:var(--bk-done-text)}", ".bk-ask.bk-skip .bk-ask-tag{color:var(--bk-skip)}", ".bk-ask-title{margin:0 0 .15rem;font:500 11px/1.4 'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;", - "letter-spacing:.12em;text-transform:uppercase;opacity:.62}", + "letter-spacing:.12em;text-transform:uppercase}", ".bk-ask-prompt{margin:0 0 .6rem;font-weight:600}", ".bk-ask-opts{display:flex;flex-direction:column;gap:.35rem}", ".bk-ask-opt{display:flex;align-items:flex-start;gap:.6rem;padding:.55rem .7rem;cursor:pointer;", @@ -87,18 +87,22 @@ ".bk-ask-opt:has(input:checked){border-color:var(--bk-accent-line);background:var(--bk-accent-soft)}", ".bk-ask-opt input{margin:.25rem 0 0;flex:0 0 auto;accent-color:var(--bk-accent)}", ".bk-ask-lab{display:flex;flex-direction:column;gap:.1rem;min-width:0}", - ".bk-ask-det{font-size:.82rem;opacity:.68}", + /* as S2: nothing here fades. Details inherit the HOST's text colour at full + strength, so they carry the host's contrast whatever the host is; the + smaller size is the de-emphasis. */ + ".bk-ask-det{font-size:.82rem}", ".bk-ask-notes{display:block;width:100%;box-sizing:border-box;margin:.6rem 0 0;padding:.5rem .65rem;", "font:inherit;font-size:.9rem;color:inherit;background:rgba(128,140,160,.09);", "border:1px solid rgba(128,140,160,.34);border-radius:8px;resize:vertical}", ".bk-ask-notes:focus{outline:2px solid var(--bk-accent);outline-offset:1px}", + /* the host's colour at 75%, not the browser's grey (3.5-4.3:1 on a dark host) */ + ".bk-ask-notes::placeholder{color:inherit;opacity:.75}", /* the primary — green, because submitting is what arms the answer */ ".bk-ask-go{margin-top:.75rem;cursor:pointer;font:600 13px/1 'IBM Plex Sans',ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;", "padding:.7rem 1.1rem;border-radius:8px;border:1px solid var(--bk-accent);", "background:var(--bk-accent);color:var(--bk-on-accent)}", ".bk-ask-go:hover{filter:brightness(1.06)}", - ".bk-ask-was{margin:.15rem 0 .55rem;font-size:.86rem;opacity:.8}", - ".bk-ask-was b{opacity:1}", + ".bk-ask-was{margin:.15rem 0 .55rem;font-size:.86rem}", ".bk-ask-err{color:var(--bk-err);font-size:.86rem}", /* [hidden] restated at class specificity: a host rule as plain as `p{display:block}` outranks the UA's own [hidden] and would show it. */ diff --git a/booth/templates/base.html b/booth/templates/base.html index 154efd6..856960a 100644 --- a/booth/templates/base.html +++ b/booth/templates/base.html @@ -213,7 +213,7 @@ .desk-head::after{content:"";flex:1;height:1px;background:var(--border-subtle)} .desk-head-needs{color:var(--warning-text)} .desk-head-new{color:var(--intel-text)} - .desk-rule{font-weight:400;letter-spacing:0;text-transform:none;color:var(--text-muted)} + .desk-rule{font-size:var(--size-caption);font-weight:400;letter-spacing:0;text-transform:none;color:var(--text-muted)} .desk-row{display:flex;gap:var(--space-4);align-items:center; padding:12px;margin-bottom:8px;border:1px solid var(--border-default);border-radius:var(--radius-xl); background:var(--surface-card);box-shadow:var(--shadow-sm); @@ -390,7 +390,7 @@ border-bottom:1px solid var(--border-subtle);background:var(--surface-raised); font-family:var(--font-mono);font-size:var(--size-caption);color:var(--text-muted)} .mark-head code{font-size:1em} - .mark-state{font-family:var(--font-mono);font-size:10.5px;font-weight:600;letter-spacing:var(--tracking-caps); + .mark-state{font-family:var(--font-mono);font-size:var(--size-micro);font-weight:600;letter-spacing:var(--tracking-caps); text-transform:uppercase;line-height:1.3;padding:2px 7px;border:1.5px solid currentColor; border-radius:var(--radius-sm);color:var(--warning-text)} .mark.is-answered .mark-state{color:var(--success-text);transform:rotate(-2deg)} @@ -508,7 +508,7 @@ .tray-kind{display:flex;align-items:center;justify-content:center;height:100%;font-family:var(--font-mono); font-size:var(--size-micro);text-transform:uppercase;color:var(--text-muted)} .tray-ord{position:absolute;left:3px;bottom:3px;padding:1px 4px;border-radius:var(--radius-sm); - font:600 10px/1.2 var(--font-mono);background:oklch(0.17 0.01 250 / .85);color:oklch(0.91 0.008 216)} + font:600 var(--size-micro)/1.2 var(--font-mono);background:oklch(0.17 0.01 250 / .85);color:oklch(0.91 0.008 216)} .orphan-flags{margin:0;padding:8px 14px 12px;list-style:none;display:flex;flex-direction:column;gap:4px; font-family:var(--font-mono);font-size:var(--size-caption);color:var(--text-muted)} .orphan-flags li{display:flex;align-items:center;justify-content:space-between;gap:8px} @@ -610,7 +610,7 @@ stamp is drawn by the tile itself, so no markup is added. */ .item.is-flagged{border-color:var(--success);box-shadow:0 0 0 1px var(--success),var(--shadow-sm)} .item.is-flagged::before{content:"flagged";position:absolute;top:10px;right:10px;z-index:2;pointer-events:none; - font:600 10.5px/1.3 var(--font-mono);letter-spacing:var(--tracking-caps);text-transform:uppercase; + font:600 var(--size-micro)/1.3 var(--font-mono);letter-spacing:var(--tracking-caps);text-transform:uppercase; padding:3px 8px;border:1.5px solid currentColor;border-radius:var(--radius-sm);color:var(--success-text); background:color-mix(in oklab,var(--surface-base) 88%,transparent);transform:rotate(-2deg)} @@ -841,7 +841,7 @@ .film-f.is-current{opacity:1;border-color:color-mix(in oklab,var(--accent) 60%,transparent)} .film-kind{display:flex;align-items:center;justify-content:center;height:100%;font-size:20px;color:var(--text-muted)} .film-ord{position:absolute;left:3px;top:3px;padding:1px 4px;border-radius:var(--radius-sm); - font:600 9.5px/1.2 var(--font-mono);background:oklch(0.17 0.01 250 / .85);color:oklch(0.91 0.008 216)} + font:600 var(--size-micro)/1.2 var(--font-mono);background:oklch(0.17 0.01 250 / .85);color:oklch(0.91 0.008 216)} @media (max-width:900px){ .viewer.review{position:static;display:block;min-height:100vh} .review-body{grid-template-columns:1fr} @@ -909,7 +909,7 @@ wears the reticle (with the active stage, via the list above). */ .film-f.is-a,.film-f.is-b{opacity:1;border-color:var(--border-strong)} .film-ab{position:absolute;right:3px;bottom:3px;padding:1px 5px;border-radius:var(--radius-sm); - font:700 9.5px/1.2 var(--font-mono);background:var(--accent);color:var(--accent-contrast)} + font:700 var(--size-micro)/1.2 var(--font-mono);background:var(--accent);color:var(--accent-contrast)} @media (max-width:900px){ .viewer.review.compare{display:block} .cmp-body{grid-template-columns:minmax(0,1fr);grid-template-rows:none} @@ -930,7 +930,7 @@ border-bottom:1px solid var(--border-subtle);background:var(--surface-raised)} .board-selall{display:inline-flex;align-items:center;cursor:pointer;flex:0 0 auto} .board-title{font-weight:600;font-size:var(--size-sm);color:var(--text-heading)} - .board-note{font-family:var(--font-mono);font-size:var(--size-micro);color:var(--text-muted)} + .board-note{font-family:var(--font-mono);font-size:var(--size-caption);color:var(--text-muted)} /* Bulk delete: quiet until something is selected. Once rows are ticked it is ARMED with the hazard stripe — device 2, earned by the selection. */ .board-del-sel{flex:0 0 auto;cursor:pointer;font-family:var(--font-mono);font-size:var(--size-micro); @@ -980,13 +980,14 @@ .bench-head{display:flex;gap:10px;align-items:baseline;padding:10px 14px; background:var(--surface-raised);border-bottom:1px solid var(--border-subtle)} .bench-title{font-weight:600;font-size:var(--size-sm);color:var(--text-heading)} - .bench-note{font-family:var(--font-mono);font-size:var(--size-micro);color:var(--text-muted)} + .bench-note{font-family:var(--font-mono);font-size:var(--size-caption);color:var(--text-muted)} .bench-empty{padding:12px 14px;color:var(--text-muted);font-size:var(--size-sm)} /* DAMAGED AND ABSENT MUST NOT RENDER THE SAME. */ .bench-err{padding:12px 14px;color:var(--danger-text);background:var(--danger-soft);font-size:var(--size-sm)} .bench-row{display:flex;gap:10px;align-items:center;padding:9px 14px;border-top:1px solid var(--border-subtle)} .bench-head+.bench-row{border-top:0} - .bench-row.is-retired{opacity:.5} + /* retired is QUIETER, not fainter: a muted colour keeps the row legible (as S2) */ + .bench-row.is-retired .bench-link,.bench-row.is-retired .bench-url{color:var(--text-muted)} .bench-state{display:inline-flex;align-items:center;gap:6px;flex:0 0 5.6rem;justify-content:flex-start; font-family:var(--font-mono);font-size:var(--size-micro);letter-spacing:.08em;text-transform:uppercase; color:var(--text-muted)} diff --git a/booth/templates/view.html b/booth/templates/view.html index b4d94d5..e6833b5 100644 --- a/booth/templates/view.html +++ b/booth/templates/view.html @@ -148,7 +148,7 @@