@variance-authority/tribunal 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +100 -0
- package/LICENSE +21 -0
- package/README.md +506 -0
- package/dist/__fixtures__/review.d.ts +47 -0
- package/dist/__fixtures__/review.js +145 -0
- package/dist/__fixtures__/review.js.map +1 -0
- package/dist/bindings.d.ts +134 -0
- package/dist/bindings.js +88 -0
- package/dist/bindings.js.map +1 -0
- package/dist/changelog.d.ts +132 -0
- package/dist/changelog.js +129 -0
- package/dist/changelog.js.map +1 -0
- package/dist/history-queries.d.ts +82 -0
- package/dist/history-queries.js +200 -0
- package/dist/history-queries.js.map +1 -0
- package/dist/history-rows.d.ts +42 -0
- package/dist/history-rows.js +148 -0
- package/dist/history-rows.js.map +1 -0
- package/dist/history.d.ts +40 -0
- package/dist/history.js +186 -0
- package/dist/history.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/migration-steps.d.ts +32 -0
- package/dist/migration-steps.js +303 -0
- package/dist/migration-steps.js.map +1 -0
- package/dist/migrations.d.ts +58 -0
- package/dist/migrations.js +283 -0
- package/dist/migrations.js.map +1 -0
- package/dist/next.d.ts +94 -0
- package/dist/next.js +44 -0
- package/dist/next.js.map +1 -0
- package/dist/node/bin.d.ts +120 -0
- package/dist/node/bin.js +337 -0
- package/dist/node/bin.js.map +1 -0
- package/dist/node/bucket.d.ts +58 -0
- package/dist/node/bucket.js +142 -0
- package/dist/node/bucket.js.map +1 -0
- package/dist/node/database.d.ts +33 -0
- package/dist/node/database.js +157 -0
- package/dist/node/database.js.map +1 -0
- package/dist/node/index.d.ts +43 -0
- package/dist/node/index.js +43 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/serve.d.ts +81 -0
- package/dist/node/serve.js +193 -0
- package/dist/node/serve.js.map +1 -0
- package/dist/node/ui-assets.d.ts +47 -0
- package/dist/node/ui-assets.js +60 -0
- package/dist/node/ui-assets.js.map +1 -0
- package/dist/review-ingest.d.ts +24 -0
- package/dist/review-ingest.js +184 -0
- package/dist/review-ingest.js.map +1 -0
- package/dist/review-read.d.ts +87 -0
- package/dist/review-read.js +361 -0
- package/dist/review-read.js.map +1 -0
- package/dist/review-rows.d.ts +30 -0
- package/dist/review-rows.js +67 -0
- package/dist/review-rows.js.map +1 -0
- package/dist/review-types.d.ts +414 -0
- package/dist/review-types.js +2 -0
- package/dist/review-types.js.map +1 -0
- package/dist/review-write.d.ts +35 -0
- package/dist/review-write.js +86 -0
- package/dist/review-write.js.map +1 -0
- package/dist/review.d.ts +53 -0
- package/dist/review.fixtures.d.ts +47 -0
- package/dist/review.fixtures.js +145 -0
- package/dist/review.fixtures.js.map +1 -0
- package/dist/review.js +245 -0
- package/dist/review.js.map +1 -0
- package/dist/schema.d.ts +36 -0
- package/dist/schema.js +39 -0
- package/dist/schema.js.map +1 -0
- package/dist/store.d.ts +58 -0
- package/dist/store.js +278 -0
- package/dist/store.js.map +1 -0
- package/dist/testing.d.ts +38 -0
- package/dist/testing.js +92 -0
- package/dist/testing.js.map +1 -0
- package/dist/ui/__probe.d.ts +3 -0
- package/dist/ui/__probe.js +5 -0
- package/dist/ui/__probe.js.map +1 -0
- package/dist/ui/attribution.d.ts +46 -0
- package/dist/ui/attribution.js +79 -0
- package/dist/ui/attribution.js.map +1 -0
- package/dist/ui/because.d.ts +51 -0
- package/dist/ui/because.js +52 -0
- package/dist/ui/because.js.map +1 -0
- package/dist/ui/browser-entry.d.ts +2 -0
- package/dist/ui/browser-entry.js +34 -0
- package/dist/ui/browser-entry.js.map +1 -0
- package/dist/ui/builds.d.ts +43 -0
- package/dist/ui/builds.js +79 -0
- package/dist/ui/builds.js.map +1 -0
- package/dist/ui/carried.d.ts +73 -0
- package/dist/ui/carried.js +63 -0
- package/dist/ui/carried.js.map +1 -0
- package/dist/ui/cause.d.ts +73 -0
- package/dist/ui/cause.js +133 -0
- package/dist/ui/cause.js.map +1 -0
- package/dist/ui/change-story.d.ts +153 -0
- package/dist/ui/change-story.js +253 -0
- package/dist/ui/change-story.js.map +1 -0
- package/dist/ui/change.d.ts +51 -0
- package/dist/ui/change.js +125 -0
- package/dist/ui/change.js.map +1 -0
- package/dist/ui/client.d.ts +74 -0
- package/dist/ui/client.js +88 -0
- package/dist/ui/client.js.map +1 -0
- package/dist/ui/consumers.d.ts +80 -0
- package/dist/ui/consumers.js +125 -0
- package/dist/ui/consumers.js.map +1 -0
- package/dist/ui/control.d.ts +63 -0
- package/dist/ui/control.js +39 -0
- package/dist/ui/control.js.map +1 -0
- package/dist/ui/crossing.d.ts +55 -0
- package/dist/ui/crossing.js +74 -0
- package/dist/ui/crossing.js.map +1 -0
- package/dist/ui/declarations.d.ts +36 -0
- package/dist/ui/declarations.js +73 -0
- package/dist/ui/declarations.js.map +1 -0
- package/dist/ui/distance.d.ts +154 -0
- package/dist/ui/distance.js +180 -0
- package/dist/ui/distance.js.map +1 -0
- package/dist/ui/divergence.d.ts +40 -0
- package/dist/ui/divergence.js +176 -0
- package/dist/ui/divergence.js.map +1 -0
- package/dist/ui/docket.d.ts +39 -0
- package/dist/ui/docket.js +172 -0
- package/dist/ui/docket.js.map +1 -0
- package/dist/ui/findings.d.ts +42 -0
- package/dist/ui/findings.js +110 -0
- package/dist/ui/findings.js.map +1 -0
- package/dist/ui/foreseen.d.ts +55 -0
- package/dist/ui/foreseen.js +91 -0
- package/dist/ui/foreseen.js.map +1 -0
- package/dist/ui/glance.d.ts +101 -0
- package/dist/ui/glance.js +101 -0
- package/dist/ui/glance.js.map +1 -0
- package/dist/ui/grouping.d.ts +158 -0
- package/dist/ui/grouping.js +187 -0
- package/dist/ui/grouping.js.map +1 -0
- package/dist/ui/handed.d.ts +60 -0
- package/dist/ui/handed.js +122 -0
- package/dist/ui/handed.js.map +1 -0
- package/dist/ui/history.d.ts +88 -0
- package/dist/ui/history.js +170 -0
- package/dist/ui/history.js.map +1 -0
- package/dist/ui/holding.d.ts +84 -0
- package/dist/ui/holding.js +90 -0
- package/dist/ui/holding.js.map +1 -0
- package/dist/ui/impact.d.ts +31 -0
- package/dist/ui/impact.js +132 -0
- package/dist/ui/impact.js.map +1 -0
- package/dist/ui/index.d.ts +21 -0
- package/dist/ui/index.js +21 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/lead.d.ts +35 -0
- package/dist/ui/lead.js +34 -0
- package/dist/ui/lead.js.map +1 -0
- package/dist/ui/look.d.ts +109 -0
- package/dist/ui/look.js +248 -0
- package/dist/ui/look.js.map +1 -0
- package/dist/ui/mark.d.ts +11 -0
- package/dist/ui/mark.js +13 -0
- package/dist/ui/mark.js.map +1 -0
- package/dist/ui/moved.d.ts +121 -0
- package/dist/ui/moved.js +143 -0
- package/dist/ui/moved.js.map +1 -0
- package/dist/ui/navigation.d.ts +26 -0
- package/dist/ui/navigation.js +53 -0
- package/dist/ui/navigation.js.map +1 -0
- package/dist/ui/order.d.ts +113 -0
- package/dist/ui/order.js +226 -0
- package/dist/ui/order.js.map +1 -0
- package/dist/ui/origins.d.ts +42 -0
- package/dist/ui/origins.js +149 -0
- package/dist/ui/origins.js.map +1 -0
- package/dist/ui/outcome.d.ts +93 -0
- package/dist/ui/outcome.js +162 -0
- package/dist/ui/outcome.js.map +1 -0
- package/dist/ui/parted.d.ts +68 -0
- package/dist/ui/parted.js +101 -0
- package/dist/ui/parted.js.map +1 -0
- package/dist/ui/rail.d.ts +31 -0
- package/dist/ui/rail.js +21 -0
- package/dist/ui/rail.js.map +1 -0
- package/dist/ui/reach.d.ts +66 -0
- package/dist/ui/reach.js +185 -0
- package/dist/ui/reach.js.map +1 -0
- package/dist/ui/regions.d.ts +82 -0
- package/dist/ui/regions.js +67 -0
- package/dist/ui/regions.js.map +1 -0
- package/dist/ui/review.bundle.js +69 -0
- package/dist/ui/review.d.ts +97 -0
- package/dist/ui/review.js +39 -0
- package/dist/ui/review.js.map +1 -0
- package/dist/ui/root.d.ts +72 -0
- package/dist/ui/root.js +102 -0
- package/dist/ui/root.js.map +1 -0
- package/dist/ui/route.d.ts +95 -0
- package/dist/ui/route.js +114 -0
- package/dist/ui/route.js.map +1 -0
- package/dist/ui/run.d.ts +26 -0
- package/dist/ui/run.js +12 -0
- package/dist/ui/run.js.map +1 -0
- package/dist/ui/sense.d.ts +187 -0
- package/dist/ui/sense.js +222 -0
- package/dist/ui/sense.js.map +1 -0
- package/dist/ui/settled.d.ts +43 -0
- package/dist/ui/settled.js +59 -0
- package/dist/ui/settled.js.map +1 -0
- package/dist/ui/shell.d.ts +76 -0
- package/dist/ui/shell.js +65 -0
- package/dist/ui/shell.js.map +1 -0
- package/dist/ui/shift.d.ts +52 -0
- package/dist/ui/shift.js +98 -0
- package/dist/ui/shift.js.map +1 -0
- package/dist/ui/styles-docket.d.ts +18 -0
- package/dist/ui/styles-docket.js +281 -0
- package/dist/ui/styles-docket.js.map +1 -0
- package/dist/ui/styles-stage.d.ts +18 -0
- package/dist/ui/styles-stage.js +92 -0
- package/dist/ui/styles-stage.js.map +1 -0
- package/dist/ui/styles.d.ts +12 -0
- package/dist/ui/styles.js +482 -0
- package/dist/ui/styles.js.map +1 -0
- package/dist/ui/subject.d.ts +36 -0
- package/dist/ui/subject.js +138 -0
- package/dist/ui/subject.js.map +1 -0
- package/dist/ui/text.d.ts +129 -0
- package/dist/ui/text.js +164 -0
- package/dist/ui/text.js.map +1 -0
- package/dist/ui/variations.d.ts +37 -0
- package/dist/ui/variations.js +60 -0
- package/dist/ui/variations.js.map +1 -0
- package/dist/ui/viewer.d.ts +67 -0
- package/dist/ui/viewer.js +246 -0
- package/dist/ui/viewer.js.map +1 -0
- package/dist/worker-auth.d.ts +48 -0
- package/dist/worker-auth.js +74 -0
- package/dist/worker-auth.js.map +1 -0
- package/dist/worker-entry.d.ts +58 -0
- package/dist/worker-entry.js +36 -0
- package/dist/worker-entry.js.map +1 -0
- package/dist/worker-http.d.ts +39 -0
- package/dist/worker-http.js +111 -0
- package/dist/worker-http.js.map +1 -0
- package/dist/worker-input.d.ts +81 -0
- package/dist/worker-input.js +296 -0
- package/dist/worker-input.js.map +1 -0
- package/dist/worker.d.ts +91 -0
- package/dist/worker.js +287 -0
- package/dist/worker.js.map +1 -0
- package/mark.svg +30 -0
- package/migrations/0001_initial.sql +193 -0
- package/migrations/0002_changelog.sql +30 -0
- package/migrations/0003_accessibility.sql +8 -0
- package/migrations/0004_variations.sql +19 -0
- package/migrations/0005_reach.sql +26 -0
- package/migrations/0006_baseline-size.sql +7 -0
- package/migrations/0007_declarations.sql +7 -0
- package/migrations/0008_green-because.sql +7 -0
- package/migrations/0009_moved-bands.sql +6 -0
- package/migrations/0010_composition.sql +15 -0
- package/migrations/0011_movements.sql +21 -0
- package/migrations/0012_control-size.sql +6 -0
- package/package.json +110 -0
- package/wrangler.jsonc +45 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The whole sheet, in one string, with the stage spliced into the middle of it.
|
|
3
|
+
*
|
|
4
|
+
* One value rather than two exports a consumer composes, because the two halves
|
|
5
|
+
* are not optional with respect to each other: a page that injected this and not
|
|
6
|
+
* [`STAGE_STYLES`](./styles-stage.ts) would have every caption styled and the
|
|
7
|
+
* evidence unstyled, which is the one failure mode worth making unreachable. The
|
|
8
|
+
* split is a limit on how much of this a person has to hold at once, not an
|
|
9
|
+
* offer.
|
|
10
|
+
*/
|
|
11
|
+
export declare const REVIEW_STYLES = "\n:root, .va-app { --va-bg: #181b1d; --va-surface: #1e2224; --va-sunken: #181b1d; --va-line: #2f3437; --va-line-firm: #434a4d; --va-ink: #f3f4f6; --va-ink-2: #a8a09b; --va-ink-3: #8f8580; --va-accent: #ff4a19; --va-accent-ink: #181b1d; --va-warn: #e0a458; --va-warn-bg: #2a2118; --va-warn-ink: #f0c48a; --va-bad: #e5695c; --va-bad-bg: #2c1b18; --va-bad-ink: #f3a99e; --va-good: #7fa28c; --va-good-bg: #1a2420; --va-good-ink: #a8c9b5; --va-info-bg: #24282a; --va-info-ink: #d6d0cb; --va-cause: #ff4a19; --va-collateral: #8f8580; --va-accent-soft: rgba(255, 74, 25, 0.14); --va-veil: rgba(24, 27, 29, 0.52); --va-sans: \"Inter\", ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif; --va-mono: \"JetBrains Mono\", ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace; }\n\n.va-app { background: var(--va-bg); color: var(--va-ink); color-scheme: dark light; display: flex; flex-direction: column; font-family: var(--va-sans); font-size: 14px; height: 100dvh; line-height: 1.5; overflow: hidden; }\n/* The element reset, every rule of it wrapped in :where() so the whole block\n weighs nothing. Written plainly, a rule like .va-app h2 scores higher than any\n single-class rule below it, and the component that says what its own heading\n looks like loses to a reset it never knew it was arguing with. That failure is\n invisible on the page and invisible in review: the sheet reads correctly and\n the render simply is not it. A reset is the sentence \"unless somebody says\n otherwise\", and :where() is how that clause is spelled. */\n:where(.va-app *, .va-app *::before, .va-app *::after) { box-sizing: border-box; }\n:where(.va-app h1, .va-app h2, .va-app h3) { line-height: 1.25; margin: 0; }\n:where(.va-app h1) { font-size: 1.35rem; letter-spacing: -0.01em; }\n:where(.va-app h2) { font-size: 0.95rem; letter-spacing: -0.005em; }\n:where(.va-app h3) { font-size: 1.05rem; letter-spacing: -0.005em; }\n:where(.va-app p) { margin: 0; }\n:where(.va-app code, .va-commit) { font-family: var(--va-mono); font-size: 0.85em; }\n.va-num { font-variant-numeric: tabular-nums; }\n\n/* Same reasoning, and this is where it was actually caught: the rail item, the\n mode pill and the build opener each declared no border and were given one\n anyway. */\n:where(.va-app button) { background: var(--va-surface); border: 1px solid var(--va-line-firm); border-radius: 7px; color: var(--va-ink); cursor: pointer; font: inherit; padding: 0.35rem 0.75rem; }\n:where(.va-app button:hover) { border-color: var(--va-ink-3); }\n:where(.va-app button:disabled) { cursor: not-allowed; opacity: 0.55; }\n:where(.va-app button.va-current:disabled) { cursor: default; opacity: 1; }\n:where(.va-app input) { background: var(--va-surface); border: 1px solid var(--va-line-firm); border-radius: 7px; color: var(--va-ink); font: inherit; padding: 0.35rem 0.6rem; }\n:where(.va-app ul, .va-app ol) { list-style: none; margin: 0; padding: 0; }\n\n/* The two things the reset above would otherwise have taken away. A surface that\n reports `nested-interactive` and unreachable controls cannot itself leave a\n keyboard reviewer guessing where they are \u2014 and the seam is the case that\n forces it, being an appearance-stripped range with no border of its own. */\n:where(.va-app a, .va-app button, .va-app summary, .va-app input, .va-app [tabindex]):focus-visible { outline: 2px solid var(--va-accent); outline-offset: 3px; }\n.va-app ::selection { background: var(--va-accent); color: var(--va-accent-ink); }\n\n/* The three panes. `min-height: 0` on each, because a flex child defaults to a\n floor of its content and a rail of two hundred subjects would push the shell\n past the viewport rather than scrolling inside it. */\n.va-body { display: flex; flex: 1; min-height: 0; }\n.va-scroll { min-height: 0; overflow: auto; overscroll-behavior: contain; }\n.va-page { flex: 1; margin: 0 auto; max-width: 72rem; min-width: 0; padding: 1.5rem 1.75rem 4rem; }\n\n.va-topbar { align-items: center; background: var(--va-surface); border-bottom: 1px solid var(--va-line); display: flex; flex: none; gap: 0.75rem; padding: 0.7rem 1rem; }\n.va-brand { color: var(--va-ink); flex: none; }\n.va-topbar-title { display: flex; flex-direction: column; line-height: 1.2; }\n.va-topbar-title strong { font-size: 0.95rem; }\n.va-topbar-sub { color: var(--va-ink-3); font-size: 0.78rem; }\n.va-topbar-meta { align-items: center; color: var(--va-ink-3); display: flex; flex-wrap: wrap; font-size: 0.8rem; gap: 0.5rem; justify-content: flex-end; margin-left: auto; }\n.va-topbar-meta .va-commit { background: var(--va-sunken); border-radius: 5px; color: var(--va-ink-2); padding: 0.1rem 0.35rem; }\n.va-back { flex: none; }\n\n.va-nav { display: flex; gap: 0.35rem; }\n.va-nav button.va-current { background: var(--va-accent-soft); border-color: var(--va-accent); color: var(--va-accent); cursor: default; }\n\n.va-pill { border-radius: 999px; flex: none; font-size: 0.75rem; font-weight: 600; padding: 0.15rem 0.6rem; white-space: nowrap; }\n.va-pill.va-warn { background: var(--va-warn-bg); color: var(--va-warn-ink); }\n.va-pill.va-good { background: var(--va-good-bg); color: var(--va-good-ink); }\n.va-pill.va-bad { background: var(--va-bad-bg); color: var(--va-bad-ink); }\n\n.va-note { color: var(--va-ink-3); font-size: 0.88rem; }\n.va-failure { background: var(--va-bad-bg); border-radius: 8px; color: var(--va-bad-ink); font-size: 0.88rem; margin: 0.5rem 0; padding: 0.6rem 0.75rem; }\n.va-card { background: var(--va-surface); border: 1px solid var(--va-line); border-radius: 12px; margin-bottom: 1rem; padding: 1rem 1.1rem; }\n.va-card > h2 { color: var(--va-ink-3); font-size: 0.72rem; font-weight: 700; letter-spacing: 0.09em; margin-bottom: 0.6rem; text-transform: uppercase; }\n\n.va-builds { display: grid; gap: 0.85rem; }\n.va-build { background: var(--va-surface); border: 1px solid var(--va-line); border-radius: 12px; padding: 0.9rem 1.1rem; }\n.va-build-head { align-items: center; display: flex; flex-wrap: wrap; gap: 0.6rem; margin-bottom: 0.45rem; }\n.va-build-open { align-items: baseline; background: none; border: 0; border-radius: 0; display: flex; gap: 0.5rem; padding: 0; }\n.va-build-id { font-size: 1.05rem; font-weight: 650; letter-spacing: -0.01em; }\n.va-build-go { color: var(--va-accent); font-size: 0.82rem; font-weight: 600; }\n.va-commit { background: var(--va-sunken); border-radius: 5px; color: var(--va-ink-2); padding: 0.1rem 0.35rem; }\n.va-branch { color: var(--va-ink-2); font-size: 0.82rem; }\n.va-when { color: var(--va-ink-3); font-size: 0.78rem; margin-left: auto; }\n\n.va-verdicts { align-items: center; display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 0.3rem; }\n.va-pending { color: var(--va-warn); font-weight: 650; }\n.va-settled { color: var(--va-good); font-weight: 650; }\n.va-counts { color: var(--va-ink-3); font-size: 0.84rem; }\n.va-coverage { color: var(--va-ink-2); font-size: 0.84rem; }\n.va-coverage.va-unknown { color: var(--va-warn); }\n.va-coverage.va-incomplete { color: var(--va-bad); font-weight: 600; }\n\n/* The rail: every reviewable subject at a glance, so the reviewer chooses which\n render to open instead of scrolling through all of them. */\n.va-rail { background: var(--va-surface); border-right: 1px solid var(--va-line); display: flex; flex-direction: column; flex: none; min-height: 0; padding: 0.6rem; width: 21rem; }\n.va-rail-group { align-items: center; color: var(--va-ink-3); display: flex; font-size: 0.7rem; font-weight: 700; gap: 0.4rem; letter-spacing: 0.09em; padding: 0.9rem 0.55rem 0.35rem; text-transform: uppercase; }\n.va-rail-count { background: var(--va-sunken); border-radius: 999px; color: var(--va-ink-2); font-size: 0.7rem; letter-spacing: 0; padding: 0 0.4rem; }\n.va-rail-item { align-items: center; background: none; border: 1px solid transparent; border-radius: 8px; display: flex; gap: 0.55rem; margin-bottom: 0.1rem; padding: 0.45rem 0.55rem; text-align: left; width: 100%; }\n.va-rail-item:hover { background: var(--va-sunken); }\n.va-rail-item.va-current { background: var(--va-accent-soft); border-color: var(--va-accent); }\n.va-rail-body { min-width: 0; }\n.va-rail-name { display: block; font-size: 0.86rem; font-weight: 550; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.va-rail-note { color: var(--va-ink-3); display: block; font-size: 0.75rem; overflow-wrap: anywhere; }\n.va-rail-item.va-current .va-rail-note { color: var(--va-ink-2); }\n.va-dot { border-radius: 50%; flex: none; height: 8px; width: 8px; }\n.va-dot.va-changed { background: var(--va-warn); }\n.va-dot.va-new { background: var(--va-accent); }\n.va-dot.va-incomparable { background: var(--va-bad); }\n.va-dot.va-unstable { background: var(--va-bad); }\n.va-dot.va-failed { background: var(--va-bad); }\n.va-dot.va-ignored { background: var(--va-ink-3); }\n.va-dot.va-unchanged { background: var(--va-good); }\n.va-mark { flex: none; font-size: 0.8rem; margin-left: auto; }\n.va-mark.va-approved { color: var(--va-good); }\n.va-mark.va-rejected { color: var(--va-bad); }\n\n.va-stage { background: var(--va-bg); flex: 1; min-width: 0; }\n.va-subject { display: flex; flex: 1; min-height: 0; min-width: 0; }\n.va-subject-head { align-items: center; display: flex; flex-wrap: wrap; gap: 0.6rem; margin-bottom: 0.35rem; }\n.va-verdict { border-radius: 999px; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.06em; padding: 0.15rem 0.55rem; text-transform: uppercase; }\n.va-verdict.va-changed { background: var(--va-warn-bg); color: var(--va-warn-ink); }\n.va-verdict.va-new { background: var(--va-info-bg); color: var(--va-info-ink); }\n.va-verdict.va-incomparable { background: var(--va-bad-bg); color: var(--va-bad-ink); }\n.va-verdict.va-unstable { background: var(--va-bad-bg); color: var(--va-bad-ink); }\n.va-because { color: var(--va-ink-2); font-size: 0.88rem; }\n\n/* The three measurements a reviewer takes in before reading anything: who moved,\n how much the canvas grew, and how much of it differs. The sentence underneath\n said all three in one clause each and was skipped by the second subject, so the\n numbers are set large and the units small and the prose stands down. Accent on\n the component name only, because that is the one answer the picture cannot give\n \u2014 a region is named from where its box landed, not from what moved it. */\n.va-glance { align-items: flex-start; display: flex; flex-wrap: wrap; gap: 1.6rem; margin: 0.55rem 0 0.35rem; }\n.va-glance-cell { display: flex; flex-direction: column; gap: 0.12rem; margin: 0; }\n.va-glance-cell b { color: var(--va-ink); font-family: var(--va-mono); font-size: 1.4rem; font-weight: 650; letter-spacing: -0.02em; line-height: 1.15; }\n.va-glance-cell span { color: var(--va-ink-3); font-family: var(--va-mono); font-size: 0.66rem; letter-spacing: 0.1em; text-transform: uppercase; }\n.va-glance-cell small { color: var(--va-ink-2); font-family: var(--va-mono); font-size: 0.72rem; }\n.va-glance-cause b { color: var(--va-cause); font-family: var(--va-sans); font-size: 1.45rem; letter-spacing: -0.01em; }\n.va-glance-none b { color: var(--va-ink-2); font-size: 1.05rem; }\n.va-glance-off { background: var(--va-warn-bg); border-radius: 4px; color: var(--va-warn-ink); margin-top: 0.15rem; padding: 0.05rem 0.35rem; width: fit-content; }\n.va-said { color: var(--va-ink-3); font-size: 0.78rem; margin: 0.1rem 0 0; max-width: 74ch; }\n.va-intent { color: var(--va-ink-2); font-size: 0.88rem; }\n.va-subtitle { color: var(--va-ink-3); font-size: 0.88rem; margin-top: 0.2rem; }\n\n/* The right-hand column: everything that is not the picture. A reviewer decides\n from the record and the defect list, and neither should cost a scroll past a\n nine-thousand-pixel render to reach. */\n.va-aside { background: var(--va-surface); border-left: 1px solid var(--va-line); flex: none; padding: 1rem; width: 22rem; }\n.va-aside .va-card { background: var(--va-sunken); border-color: transparent; }\n.va-aside h2 { color: var(--va-ink-3); font-size: 0.72rem; font-weight: 700; letter-spacing: 0.09em; margin-bottom: 0.5rem; text-transform: uppercase; }\n\n/* The review unit, which is a change and not a picture. Each card is one edit\n and every place it landed, so the card is given the weight a row in a table\n never had: a reviewer approves at this level and reads the subjects inside it\n as evidence. The left edge is the cause colour, the same one the region boxes\n use, because that is what the card is. */\n.va-origins { display: grid; gap: 0.75rem; margin-top: 0.75rem; }\n.va-origin { background: var(--va-sunken); border-left: 3px solid var(--va-cause); border-radius: 10px; padding: 0.85rem 1rem; }\n.va-origin.va-orphan { border-left-color: var(--va-warn); }\n.va-origin-head { align-items: baseline; display: flex; flex-wrap: wrap; gap: 0.5rem; }\n.va-origin-head h3 { font-size: 1rem; margin: 0; }\n.va-origin-pixels { color: var(--va-ink-3); font-size: 0.84rem; margin-left: auto; }\n.va-file { color: var(--va-ink-2); }\n.va-origin p { font-size: 0.86rem; margin: 0.35rem 0 0; }\n.va-origin .va-churn, .va-origin .va-stability { margin: 0.35rem 0 0; }\n.va-origin-arrival.va-alarm { background: var(--va-bad-bg); border-radius: 6px; color: var(--va-bad-ink); padding: 0.35rem 0.55rem; }\n/* Two shapes under one component name is two edits, and the sentence saying so\n is the one thing on the card that withdraws the batch approval. */\n.va-note.va-warned { color: var(--va-warn-ink); }\n.va-origin-where { display: grid; font-size: 0.86rem; gap: 0.35rem; margin-top: 0.7rem; }\n.va-origin-where li { align-items: baseline; display: flex; flex-wrap: wrap; gap: 0.5rem; }\n.va-origin-subject { font-weight: 600; }\n.va-origin-act { align-items: center; display: flex; flex-wrap: wrap; gap: 0.55rem; margin-top: 0.8rem; }\n.va-origin-act button { font-weight: 600; }\n.va-origin-act .va-approve { background: var(--va-good); border-color: var(--va-good); color: #ffffff; }\n.va-origin-act .va-approve:disabled { background: var(--va-sunken); border-color: var(--va-line-firm); color: var(--va-ink-3); }\n.va-collateral { border-top: 1px solid var(--va-line); color: var(--va-ink-3); font-size: 0.84rem; margin-top: 0.75rem; padding-top: 0.65rem; }\n\n/* Looking at the change from the card that decides it. The window is fixed and\n the same for every crop: sizing each one to its own region would turn the strip\n into a bar chart of areas, which is the ranking by area this whole surface\n exists to refuse, drawn in the place a reviewer reads as how big is this. */\n.va-origin-look { align-items: center; display: flex; flex-wrap: wrap; gap: 0.5rem; }\n.va-look { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: 0.6rem; }\n.va-sight { background: none; border: 0; color: inherit; cursor: pointer; display: flex; flex-direction: column; font: inherit; gap: 0.3rem; padding: 0; text-align: left; }\n.va-crop { background: var(--va-bg); border: 1px solid var(--va-line); border-radius: 8px; display: block; overflow: hidden; position: relative; }\n.va-sight:hover .va-crop, .va-sight:focus-visible .va-crop { border-color: var(--va-accent); }\n.va-crop-plate { position: absolute; }\n.va-crop-plate img { display: block; height: auto; image-rendering: pixelated; left: 0; position: absolute; top: 0; width: 100%; }\n/* The veil rather than a ring alone: at 3x on a hundred-pixel region the ring is\n most of the window, and a reviewer looking for the difference is looking for\n which part of the window is not dimmed. The spread only has to exceed the crop,\n which is 264px wide and clips it. */\n.va-crop-box { border: 1px solid var(--va-cause); box-shadow: 0 0 0 900px var(--va-veil); position: absolute; }\n.va-crop-part { background: var(--va-bg); border-radius: 5px; bottom: 0.3rem; color: var(--va-ink-3); font-family: var(--va-mono); font-size: 0.65rem; padding: 0.1rem 0.35rem; position: absolute; right: 0.3rem; }\n.va-crop-unplaced { align-items: center; display: flex; justify-content: center; padding: 0.75rem; text-align: center; }\n.va-sight-note { color: var(--va-ink-2); font-family: var(--va-mono); font-size: 0.7rem; max-width: 264px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n/* A subject name that goes somewhere. Underlined rather than coloured, because\n the accent on this page means cause and a second meaning for it would make the\n colour say nothing. */\n.va-open { background: none; border: 0; color: inherit; cursor: pointer; font: inherit; padding: 0; text-align: left; text-decoration: underline; text-decoration-color: var(--va-line-firm); text-underline-offset: 3px; }\n.va-open:hover { text-decoration-color: var(--va-accent); }\n/* The commit does not reach this name, and reaches every render it moved in.\n Ordinary, and therefore not wearing the alarm's colour: a page that shouts at\n every component out of node_modules has spent the shout before the one render\n nothing accounts for arrives. */\n.va-origin-arrival.va-unnamed { background: var(--va-info-bg); border-radius: 6px; color: var(--va-info-ink); padding: 0.35rem 0.55rem; }\n\n/* The third axis: what the commit reaches, crossed with what the run saw. Drawn\n as a grid rather than four counts, because the four cells are one crossing and\n a reader who takes them in as a shape sees at once which half of it is the\n anomaly. */\n.va-reach .va-quad { display: grid; gap: 0.5rem; grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: 0.9rem; }\n.va-cell { background: var(--va-sunken); border-left: 3px solid var(--va-line-firm); border-radius: 9px; display: grid; gap: 0.1rem; padding: 0.7rem 0.85rem; }\n.va-cell-n { font-size: 1.6rem; font-weight: 650; letter-spacing: -0.02em; line-height: 1.15; }\n.va-cell-title { font-size: 0.82rem; font-weight: 650; }\n.va-cell-note { color: var(--va-ink-3); font-size: 0.78rem; }\n.va-cell.va-expected { border-left-color: var(--va-accent); }\n.va-cell.va-alarm { background: var(--va-bad-bg); border-left-color: var(--va-bad); }\n.va-cell.va-alarm .va-cell-n, .va-cell.va-alarm .va-cell-title { color: var(--va-bad-ink); }\n.va-cell.va-inert { background: var(--va-warn-bg); border-left-color: var(--va-warn); }\n.va-cell.va-inert .va-cell-n, .va-cell.va-inert .va-cell-title { color: var(--va-warn-ink); }\n/* A quadrant holding nothing keeps its place and loses its voice. Dropped, it\n reads as a question nobody asked; coloured as a finding, as one nobody\n answered. */\n.va-cell.va-zero { background: transparent; border-left-color: var(--va-line); }\n.va-cell.va-zero .va-cell-n, .va-cell.va-zero .va-cell-title { color: var(--va-ink-3); font-weight: 550; }\n\n.va-reach .va-band { border-left: 2px solid var(--va-line-firm); margin-top: 1.1rem; padding-left: 0.85rem; }\n.va-reach .va-band.va-alarm { border-left-color: var(--va-bad); }\n.va-reach .va-band.va-inert { border-left-color: var(--va-warn); }\n.va-reach .va-band h3 { font-size: 0.95rem; margin-bottom: 0.25rem; }\n.va-reach .va-stability, .va-reach .va-churn { margin: 0.2rem 0 0; }\n.va-reach-list { display: grid; font-size: 0.86rem; gap: 0.5rem; margin-top: 0.55rem; }\n.va-reach-list.va-columns { columns: 2 18rem; display: block; }\n.va-reach-list.va-columns li { break-inside: avoid; margin-bottom: 0.35rem; }\n\n/* The chain, which is the half a reviewer can disprove. A component named\n without it is an assertion; tokens.css to button.tsx to Button is a claim\n somebody can open three files and refute. */\n.va-trails { display: grid; font-size: 0.84rem; gap: 0.35rem; margin-top: 0.55rem; }\n.va-trails code { background: var(--va-sunken); border-radius: 5px; color: var(--va-ink-2); padding: 0.1rem 0.35rem; }\n.va-arrow { color: var(--va-ink-3); padding: 0 0.3rem; }\n.va-axis.va-unread { background: var(--va-warn-bg); color: var(--va-warn-ink); margin-left: 0.5rem; }\n\n/* Drawn where the crossing would have been, never beside it: an empty grid over\n a diff nothing could attribute reads as this commit reaches none of your\n subjects, which is a sentence somebody merges on. */\n.va-refusal { background: var(--va-warn-bg); border-radius: 9px; color: var(--va-warn-ink); font-size: 0.86rem; margin-top: 0.9rem; padding: 0.6rem 0.75rem; }\n.va-reach-note { border-top: 1px solid var(--va-line); margin-top: 0.9rem; padding-top: 0.6rem; }\n.va-reach-note code { color: var(--va-ink-2); }\n.va-lost { color: var(--va-bad); }\n\n/* The map. Three registers on one row \u2014 what was edited, what it arrived at, and\n what became of the renders drawing that \u2014 so the eye reads left to right and\n lands on the track. The indent under a file carries a hairline because the\n relation is containment rather than sequence: at this density an indent alone\n reads as a second list. */\n.va-map { display: grid; gap: 0.55rem; margin-top: 0.9rem; }\n.va-edits { display: grid; gap: 0.5rem; }\n.va-edit { background: var(--va-sunken); border-radius: 9px; padding: 0.6rem 0.8rem; }\n.va-edit-head { align-items: baseline; display: flex; flex-wrap: wrap; gap: 0.5rem; }\n.va-edit-file { min-width: 0; overflow-wrap: anywhere; }\n/* The verdict on an edit is the one label on this page that is read by scanning a\n column rather than by reading a sentence, which is what the mono face is for. */\n.va-effect { flex: none; font-family: var(--va-mono); font-size: 0.7rem; letter-spacing: 0.02em; margin-left: auto; text-transform: uppercase; }\n.va-effect-cause { color: var(--va-accent); }\n.va-effect-ask { color: var(--va-warn-ink); }\n.va-effect-quiet { color: var(--va-ink-3); }\n.va-arrivals { border-left: 1px solid var(--va-line-firm); display: grid; gap: 0.35rem; margin: 0.5rem 0 0 0.25rem; padding-left: 0.8rem; }\n.va-arrival { align-items: center; display: flex; flex-wrap: wrap; gap: 0.5rem; min-width: 0; }\n.va-arrival-name { font-size: 0.86rem; font-weight: 600; }\n.va-arrival-through { color: var(--va-ink-3); font-size: 0.76rem; }\n.va-arrival-tally { color: var(--va-ink-2); flex: none; font-size: 0.76rem; margin-left: auto; }\n/* Cause, collateral, still and not-compared are the same four readings the region\n overlay spends colour on, spent the same way here. A track that invented its own\n palette would be a second vocabulary for one set of facts. */\n.va-bar { background: var(--va-line); border-radius: 3px; display: flex; flex: 1; gap: 1px; height: 5px; max-width: 11rem; min-width: 3rem; overflow: hidden; }\n.va-bar-part { display: block; }\n.va-bar-caused { background: var(--va-cause); }\n.va-bar-moved { background: var(--va-collateral); }\n.va-bar-still { background: var(--va-good); }\n.va-bar-uncompared { background: var(--va-line-firm); }\n.va-map-aside { border-top: 1px solid var(--va-line); display: grid; gap: 0.5rem; padding-top: 0.6rem; }\n.va-map-note { color: var(--va-ink-3); font-size: 0.8rem; }\n.va-map-alarm { color: var(--va-bad-ink); }\n\n/* Since the last run. Each state carries its own left rule, because the section is\n read by jumping to the one that matters and a uniform stack would have to be\n read in order to find it. */\n.va-shift { border-left: 3px solid var(--va-line-firm); display: grid; gap: 0.25rem; margin-top: 0.85rem; padding-left: 0.8rem; }\n.va-shift-head { align-items: baseline; display: flex; gap: 0.5rem; }\n.va-shift-title { font-size: 0.9rem; font-weight: 650; }\n.va-shift-count { font-size: 1.2rem; font-weight: 650; letter-spacing: -0.02em; margin-left: auto; }\n.va-shift-alarm { border-left-color: var(--va-bad); }\n.va-shift-alarm .va-shift-title, .va-shift-alarm .va-shift-count { color: var(--va-bad-ink); }\n.va-shift-ask { border-left-color: var(--va-warn); }\n.va-shift-ask .va-shift-title, .va-shift-ask .va-shift-count { color: var(--va-warn-ink); }\n.va-shift-known { border-left-color: var(--va-accent); }\n.va-shift-known .va-shift-count { color: var(--va-accent); }\n.va-shift-good { border-left-color: var(--va-good); }\n.va-shift-good .va-shift-count { color: var(--va-good-ink); }\n.va-shift-quiet { border-left-color: var(--va-line); }\n.va-shift-list { display: grid; font-size: 0.84rem; gap: 0.3rem; margin-top: 0.25rem; }\n.va-shift-row { align-items: baseline; display: flex; flex-wrap: wrap; gap: 0.5rem; min-width: 0; }\n.va-shift-subject { font-weight: 600; min-width: 0; overflow-wrap: anywhere; }\n.va-shift-held { border-top: 1px solid var(--va-line); margin-top: 0.95rem; padding-top: 0.6rem; }\n\n.va-variation-list { display: grid; gap: 0.5rem; }\n.va-variation { background: var(--va-sunken); border-radius: 9px; padding: 0.6rem 0.75rem; }\n.va-variation-head { align-items: baseline; display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 0.15rem; }\n/* Every chip carries its own text colour rather than inheriting the page's: the\n backgrounds are light in both schemes, and a chip that inherited a dark\n scheme's foreground would be pale text on a pale block. */\n.va-axis { background: var(--va-info-bg); border-radius: 999px; color: var(--va-info-ink); font-size: 0.72rem; font-weight: 650; padding: 0.1rem 0.5rem; }\n/* The two states a reviewer can act on, and they are not the same finding: an\n arm that changes nothing was measured, a pair with no parent never was. */\n.va-variation.va-inert .va-axis { background: var(--va-warn-bg); color: var(--va-warn-ink); }\n.va-variation.va-unlinked .va-axis { background: var(--va-bad-bg); color: var(--va-bad-ink); }\n.va-how { color: var(--va-ink-3); font-size: 0.75rem; }\n\n\n/* The bar over the stage: what is being compared, how large it is drawn, and\n which finding is being looked at. Three groups rather than one row of\n everything, because they are asked in that order and answered independently. */\n.va-viewer-bar { display: grid; gap: 0.45rem; margin: 0.85rem 0 0.6rem; }\n.va-viewer-controls, .va-viewer-readout { align-items: center; display: flex; flex-wrap: wrap; gap: 0.5rem; min-width: 0; }\n.va-modes, .va-zooms { background: var(--va-sunken); border-radius: 9px; display: inline-flex; flex-wrap: wrap; gap: 0.15rem; padding: 0.2rem; }\n.va-mode { background: none; border: 1px solid transparent; border-radius: 7px; font-family: var(--va-mono); font-size: 0.72rem; letter-spacing: 0.08em; padding: 0.25rem 0.6rem; text-transform: uppercase; white-space: nowrap; }\n.va-mode.va-current { background: var(--va-accent-soft); border-color: var(--va-accent); color: var(--va-accent); font-weight: 650; }\n.va-steps { align-items: center; display: inline-flex; gap: 0.4rem; margin-left: auto; }\n.va-steps button { font-size: 0.9rem; line-height: 1; padding: 0.25rem 0.55rem; }\n.va-steps span { color: var(--va-ink-3); font-family: var(--va-mono); font-size: 0.75rem; }\n\n/* The stage is the pane; the plate is the capture inside it, at whatever\n magnification was asked for. Two boxes rather than one, because a zoom that\n grew the pane would push the decision buttons off the screen \u2014 the thing a\n reviewer came here to press. */\n.va-loupe { background: var(--va-sunken); border: 1px solid var(--va-line); border-radius: 10px; max-height: 70vh; max-width: 100%; overflow: auto; overscroll-behavior: contain; position: relative; }\n.va-plate { background: var(--va-surface); margin: 0 auto; position: relative; width: 100%; }\n/* Every layer fills the plate, so the baseline and the candidate are always at\n one magnification. A wipe between two scales is not a comparison \u2014 it reads as\n a change everywhere the seam happens to fall. height: auto, because a deferred\n raster carries its own dimensions as attributes and a width alone would keep\n the declared height, squashing every candidate to the aspect ratio of nothing. */\n.va-plate img { display: block; height: auto; image-rendering: pixelated; width: 100%; }\n/* The baseline sits under the candidate at the corner rather than inset: 0 \u2014\n stretched between top and bottom it would be drawn at the candidate's height\n whenever the two differ, which is often the change itself. */\n.va-plate .va-under { left: 0; position: absolute; top: 0; }\n/* Both layers leave the flow the moment the two captures are different shapes:\n the plate's height then comes from the union it declares, not from whichever\n image happens to be in flow \u2014 which would crop the taller one. */\n.va-plate.va-boxed img { left: 0; position: absolute; top: 0; }\n.va-measure { color: var(--va-ink-3); font-family: var(--va-mono); font-size: 0.72rem; margin: 0; }\n.va-measure .va-resized { color: var(--va-accent); }\n.va-showing { color: var(--va-ink-2); font-family: var(--va-mono); font-size: 0.72rem; margin: 0; }\n\n/* The seam is the control, not a slider parked somewhere else on the page: it\n spans the plate, so the thumb sits over the boundary it moves, and it is a\n real range input, so it answers to the arrow keys as well as to a drag. */\n.va-seam { -webkit-appearance: none; appearance: none; background: none; border: 0; border-radius: 0; display: block; height: 22px; margin-bottom: -22px; padding: 0; position: sticky; top: 0; width: 100%; z-index: 3; }\n.va-seam::-webkit-slider-thumb { -webkit-appearance: none; background: var(--va-accent); border-radius: 2px; height: 22px; width: 4px; }\n.va-seam::-moz-range-thumb { background: var(--va-accent); border: 0; border-radius: 2px; height: 22px; width: 4px; }\n.va-seam-line { background: var(--va-accent); bottom: 0; pointer-events: none; position: absolute; top: 0; width: 1px; }\n.va-blend { accent-color: var(--va-accent); display: block; margin-top: 0.6rem; width: 100%; }\n\n.va-side-by-side { display: flex; gap: 1rem; }\n.va-side-by-side figure { margin: 0; min-width: 0; }\n.va-side-by-side figcaption { color: var(--va-ink-3); font-family: var(--va-mono); font-size: 0.68rem; letter-spacing: 0.09em; margin-bottom: 0.3rem; text-transform: uppercase; }\n.va-side-by-side img { border: 1px solid var(--va-line); border-radius: 10px; height: auto; image-rendering: pixelated; max-width: 100%; }\n.va-pixels { color: var(--va-ink-3); font-size: 0.82rem; margin-top: 0.5rem; }\n\n.va-regions { inset: 0; pointer-events: none; position: absolute; }\n.va-region { pointer-events: auto; position: absolute; }\n.va-region.va-cause { outline: 2px solid var(--va-cause); }\n.va-region.va-collateral { outline: 1px dashed var(--va-collateral); }\n/* Lit from either side: the rectangle and its row are the same finding, and a\n reviewer joining them by counting down a table is doing the work twice. */\n.va-region.va-lit { background: var(--va-accent-soft); outline-width: 3px; }\n.va-region-label { background: var(--va-cause); border-radius: 3px; color: var(--va-accent-ink); font-family: var(--va-mono); font-size: 0.65rem; font-weight: 600; left: 0; padding: 0 0.25rem; position: absolute; top: -1.15rem; white-space: nowrap; }\n.va-region.va-collateral .va-region-label { background: var(--va-collateral); color: var(--va-bg); }\n\n/* The column a rectangle cannot draw. A box says *here*; only the table says\n which file to open, which is what lets a reviewer hand the change on rather\n than decide it themselves. */\n.va-region-table { border-collapse: collapse; font-size: 0.82rem; margin-top: 0.75rem; width: 100%; }\n.va-region-table th { border-bottom: 1px solid var(--va-line-firm); color: var(--va-ink-3); font-family: var(--va-mono); font-size: 0.65rem; font-weight: 600; letter-spacing: 0.09em; padding: 0.3rem 0.5rem; text-align: left; text-transform: uppercase; }\n.va-region-table td { border-bottom: 1px solid var(--va-line); padding: 0.3rem 0.5rem; vertical-align: top; }\n.va-region-table tr.va-lit td { background: var(--va-accent-soft); }\n.va-region-table .va-num-col { text-align: right; }\n.va-region-jump { align-items: baseline; background: none; border: 0; border-radius: 0; display: flex; gap: 0.4rem; padding: 0; text-align: left; }\n.va-region-where { color: var(--va-ink-3); font-size: 0.75rem; }\n.va-dot.va-cause { background: var(--va-cause); }\n.va-dot.va-collateral { background: var(--va-collateral); }\n\n\n/* The trail, which is the whole navigation. Five of the seven pages are *about*\n the page above them, and a trail says that where a menu would assert they are\n peers. */\n.va-crumbs { align-items: center; display: flex; gap: 0.3rem; min-width: 0; }\n.va-crumb { color: var(--va-ink-3); font-size: 0.8rem; text-decoration: none; white-space: nowrap; }\n.va-crumb:hover { color: var(--va-accent); }\n.va-crumb-sep { color: var(--va-line-firm); font-size: 0.8rem; }\n\n/* Changes or subjects: the two ways to work a build, as two addresses rather\n than as a piece of component state. */\n.va-switch { background: var(--va-sunken); border-radius: 9px; display: flex; flex: none; gap: 0.15rem; margin-bottom: 0.5rem; padding: 0.2rem; }\n.va-switch .va-mode { flex: 1; text-align: center; text-decoration: none; }\n.va-switch .va-mode.va-on { background: var(--va-accent-soft); color: var(--va-accent); font-weight: 650; }\n.va-switch .va-mode.va-off { color: var(--va-ink-3); cursor: not-allowed; }\n\n.va-rail-head { align-items: center; display: flex; flex: none; flex-wrap: wrap; gap: 0.4rem; padding: 0 0.15rem 0.5rem; }\n.va-rail-tally { color: var(--va-ink-3); font-size: 0.76rem; margin-right: auto; }\n.va-rail-empty { padding: 0.6rem 0.15rem; }\n/* The scrolling half. `min-height: 0` is what keeps it scrolling rather than\n pushing the rail past the bottom of the window \u2014 a flex child's default\n minimum is its content, and a build of forty changes would take the viewport\n with it. */\n.va-rail-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; }\n\n/* The orders. Small, and deliberately not a select: four addresses a reader can\n middle-click, which a select cannot be. */\n.va-sorting { display: inline-flex; gap: 0.1rem; }\n.va-sort { border-radius: 6px; color: var(--va-ink-3); font-family: var(--va-mono); font-size: 0.66rem; letter-spacing: 0.06em; padding: 0.15rem 0.4rem; text-decoration: none; text-transform: uppercase; }\n.va-sort:hover { background: var(--va-sunken); color: var(--va-ink); }\n.va-sort.va-on { background: var(--va-accent-soft); color: var(--va-accent); }\n\n/* A band, and the sentence that says why its rows are together. The left edge\n carries the band's meaning: an alarm is red, a decision is green, and the\n ordinary work you asked for is the accent. */\n.va-band { border-left: 2px solid var(--va-line-firm); margin: 0 0 0.9rem 0.15rem; padding-left: 0.7rem; }\n.va-band h3 { align-items: center; display: flex; font-size: 0.76rem; font-weight: 700; gap: 0.4rem; letter-spacing: 0.05em; margin-bottom: 0.15rem; text-transform: uppercase; }\n.va-band h3 .va-num { background: var(--va-sunken); border-radius: 999px; color: var(--va-ink-2); font-size: 0.7rem; letter-spacing: 0; padding: 0 0.4rem; }\n.va-band > .va-note { font-size: 0.74rem; margin-bottom: 0.35rem; }\n.va-band-stranded { border-left-color: var(--va-bad); }\n.va-band-stranded h3 { color: var(--va-bad-ink); }\n.va-band-reached { border-left-color: var(--va-accent); }\n.va-band-contradicted { border-left-color: var(--va-warn); }\n.va-band-contradicted h3 { color: var(--va-warn-ink); }\n.va-band-unexplained { border-left-color: var(--va-warn); }\n.va-band-unexplained h3 { color: var(--va-warn-ink); }\n.va-band-upstream { border-left-color: var(--va-collateral); }\n.va-band-token { border-left-color: var(--va-collateral); }\n.va-band-unnamed { border-left-color: var(--va-line-firm); }\n.va-band-unread { border-left-color: var(--va-warn); }\n.va-band-decided { border-left-color: var(--va-good); }\n.va-band-orphan { border-left-color: var(--va-warn); }\n\n/* A heading that is a path or a property, not a claim, so it overrides the\n band's uppercase: a name a reviewer uppercases is a name they cannot grep. */\n.va-band h3.va-root, .va-root { flex-wrap: wrap; font-family: var(--va-mono); font-size: 0.78rem; font-weight: 600; gap: 0.15rem; letter-spacing: 0; text-transform: none; }\n.va-root .va-root-in { color: var(--va-ink-3); font-weight: 400; }\n.va-root .va-root-name { color: var(--va-ink); }\n.va-root-component .va-root-name { font-family: var(--va-sans); font-weight: 700; }\n\n/* The same cause on the change page: one line under the name, and the other\n changes it made. */\n.va-from { align-items: baseline; display: flex; flex-wrap: wrap; font-size: 0.8rem; gap: 0.3rem; margin-top: 0.2rem; }\n.va-from-mark { color: var(--va-ink-3); font-size: 0.72rem; letter-spacing: 0.05em; text-transform: uppercase; }\n.va-from .va-root { font-size: 0.8rem; }\n.va-from-go { color: var(--va-accent); text-decoration: none; }\n.va-from-go:hover { text-decoration: underline; }\n\n/* The prediction under a root, and the same claim about the whole build. It sits\n between a heading and the rows it explains, so it is quieter than both. */\n.va-foreseen { color: var(--va-ink-3); font-size: 0.72rem; line-height: 1.5; margin: 0.1rem 0 0.4rem; }\n.va-foreseen .va-num { color: var(--va-ink-2); font-family: var(--va-mono); }\n.va-foreseen .va-from-go { color: var(--va-ink-2); font-family: var(--va-mono); text-decoration: none; }\n.va-foreseen .va-from-go:hover { color: var(--va-accent); text-decoration: underline; }\n.va-foreseen-off { color: var(--va-warn-ink); }\n.va-rail-head + .va-foreseen { margin: -0.2rem 0 0.5rem; }\n\n/* One change, in a row a reviewer scans a column of. The name is the only thing\n at full contrast; everything else on the row is there to be skipped. */\n.va-row { margin-bottom: 0.1rem; }\n.va-row-link { align-items: baseline; border: 1px solid transparent; border-radius: 8px; column-gap: 0.5rem; display: grid; grid-template-columns: minmax(0, 1fr) auto; padding: 0.35rem 0.5rem; row-gap: 0.05rem; text-decoration: none; }\n.va-row-link:hover { background: var(--va-sunken); }\n.va-row.va-here .va-row-link { background: var(--va-accent-soft); border-color: var(--va-accent); }\n.va-row-name { font-size: 0.88rem; font-weight: 550; grid-area: 1 / 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.va-row-spread { font-size: 0.74rem; grid-area: 2 / 1; }\n.va-row-size { color: var(--va-ink-3); font-size: 0.74rem; grid-area: 2 / 2; text-align: right; }\n.va-row .va-mark { font-size: 0.68rem; grid-area: 1 / 2; justify-self: end; }\n.va-row-from { color: var(--va-ink-3); font-family: var(--va-mono); font-size: 0.7rem; grid-area: 3 / 1 / 4 / 3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n/* The page with nothing open: four sentences and two links, and no encyclopedia.\n Everything a reader could want past this has an address of its own. */\n.va-opening { max-width: 44rem; }\n.va-opening h1 { margin-bottom: 0.3rem; }\n.va-opening-links { align-items: baseline; display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: 1.4rem; }\n\n/* The change itself. The two buttons are in the head, level with the component\n name: every line below them is a reason to press one or to refuse, and a\n reviewer who has read them should not scroll back past the reasons to act. */\n.va-decide { max-width: 62rem; }\n.va-decide-head { align-items: flex-start; border-bottom: 1px solid var(--va-line); display: flex; flex-wrap: wrap; gap: 0.8rem; justify-content: space-between; padding-bottom: 0.8rem; }\n.va-decide-head h1 { margin: 0; }\n.va-decide-lead { font-size: 1rem; margin-top: 0.8rem; }\n.va-decide-act { align-items: center; display: flex; flex-wrap: wrap; gap: 0.55rem; }\n.va-decide-act button { font-weight: 600; }\n.va-decide-act .va-approve { background: var(--va-good); border-color: var(--va-good); color: #ffffff; }\n.va-decide-act .va-approve:disabled { background: var(--va-sunken); border-color: var(--va-line-firm); color: var(--va-ink-3); }\n.va-decide h2 { font-size: 0.78rem; letter-spacing: 0.08em; margin-top: 1.6rem; text-transform: uppercase; }\n\n/* Whether the commit arrives, in the three colours the three answers deserve.\n The alarm is spent on one of them and must stay that way: a page that shouted\n over every component out of a dependency trained the alarm out of its readers\n inside a build. */\n.va-reaches { border-radius: 7px; font-size: 0.9rem; margin-top: 0.9rem; padding: 0.5rem 0.7rem; }\n.va-reaches.va-reached { background: var(--va-info-bg); color: var(--va-info-ink); }\n.va-reaches.va-alarm { background: var(--va-bad-bg); color: var(--va-bad-ink); }\n.va-reaches.va-unnamed { background: var(--va-info-bg); color: var(--va-info-ink); }\n\n/* The run's own conclusion, above the file graph's. Left-marked rather than\n filled: it sits directly over the reach block, and two filled panels in a row\n read as one panel with a seam in it. The colour is the rung \u2014 the two that\n say *the run found nothing* borrow the alarm, and the three that explain\n something do not, because an explanation is not a finding. */\n.va-attributed { border-left: 3px solid var(--va-line-firm); font-size: 0.92rem; margin-top: 0.9rem; padding-left: 0.7rem; }\n.va-attributed code { font-size: 0.86em; }\n.va-attributed-edited { border-left-color: var(--va-accent); }\n.va-attributed-upstream { border-left-color: var(--va-collateral); }\n.va-attributed-token { border-left-color: var(--va-collateral); }\n.va-attributed-contradicted { border-left-color: var(--va-bad); }\n.va-attributed-unexplained { border-left-color: var(--va-bad); }\n.va-attributed-go { color: var(--va-accent); font-weight: 600; white-space: nowrap; }\n\n/* A band this change did not move on its own. Directly under the lead and\n marked in the collateral colour, which is what it is: the sense moved here,\n the decision is one file up, and the two belong on one screen without the\n second looking like a second change. */\n.va-handed { color: var(--va-ink-2); font-size: 0.95rem; margin-top: 0.35rem; }\n.va-handed em { color: var(--va-ink); font-style: normal; font-weight: 600; }\n.va-handed-go { color: var(--va-accent); font-weight: 600; white-space: nowrap; }\n\n/* The three counts, side by side rather than in a sentence. A sentence has to\n pick an order and an emphasis; these are three answers of equal standing to\n three questions a reviewer asks in the same breath. */\n.va-tally { align-items: baseline; color: var(--va-ink-2); display: flex; flex-wrap: wrap; font-size: 0.9rem; gap: 0.15rem 1.1rem; margin: 0.2rem 0 0.9rem; }\n.va-tally strong { color: var(--va-ink); font-size: 1rem; }\n.va-tally > .va-note { margin-left: auto; }\n\n/* What happened to the things that draw this one \u2014 the question an author of a\n leaf actually has. The list is ordered worst first, so the row that needs a\n look is the one under the summary. */\n.va-consumers { margin: 1.1rem 0; }\n.va-consumers-tally { color: var(--va-ink-2); font-size: 0.92rem; margin: 0 0 0.5rem; }\n.va-consumers-own { color: var(--va-bad-ink); font-weight: 600; }\n.va-consumers-list { display: grid; gap: 0.3rem; list-style: none; margin: 0; padding: 0; }\n.va-consumers-list li { align-items: baseline; border-left: 3px solid var(--va-collateral); display: flex; flex-wrap: wrap; gap: 0.5rem; padding: 0.15rem 0 0.15rem 0.6rem; }\n.va-consumer-name { color: var(--va-ink); font-weight: 600; }\n.va-consumer-moved { border-left-color: var(--va-bad); }\n.va-consumers-rest { color: var(--va-ink-3); font-size: 0.85rem; margin: 0.5rem 0 0; }\n.va-consumers-rest span[title] { color: var(--va-ink-2); }\n.va-alarm-text { color: var(--va-bad-ink); }\n\n/* What a press of Approve settles that is not the change it is under. Directly\n under the counts, because it is a correction to one of them: the seven renders\n to accept are seven whole pictures, and four of them hold somebody else's\n undecided difference. */\n.va-carries { background: var(--va-bad-bg); border-radius: 6px; color: var(--va-ink-2); font-size: 0.88rem; margin: 0 0 0.9rem; padding: 0.4rem 0.6rem; }\n.va-carries-go { color: var(--va-accent); font-weight: 600; white-space: nowrap; }\n.va-carries-mark { background: var(--va-bad-bg); border-radius: 999px; color: var(--va-bad-ink); font-size: 0.68rem; padding: 0.05rem 0.4rem; }\n\n/* What a band claim is made of. At the foot, because it is the same sentence for\n all of them and a reviewer needs it once \u2014 and not behind a disclosure,\n because the complaint that produced it was a page hiding its sources. */\n.va-held { border-left: 2px solid var(--va-good); color: var(--va-ink-2); font-size: 0.86rem; margin: 0.6rem 0 0; padding-left: 0.7rem; }\n.va-held-mark { color: var(--va-good); font-weight: 600; }\n.va-held-none { border-left-color: var(--va-ink-3); }\n.va-held-none .va-held-mark { color: var(--va-ink-2); }\n.va-held-go { color: inherit; text-decoration: underline; text-decoration-style: dotted; }\n.va-evidence { border-top: 1px solid var(--va-line); color: var(--va-ink-3); font-size: 0.8rem; margin-top: 1.6rem; padding-top: 0.6rem; }\n.va-evidence em { color: var(--va-ink-2); font-style: normal; }\n\n/* What the last run said, beside the change rather than nine thousand pixels\n below it. Warm rather than red: *you have seen this* is not an alarm, it is\n the sentence a reviewer skips work on. */\n.va-since { border-radius: 7px; font-size: 0.9rem; margin-top: 0.7rem; padding: 0.5rem 0.7rem; }\n.va-since.va-known { background: var(--va-warn-bg); color: var(--va-warn-ink); }\n.va-collateral-note { margin-top: 1.6rem; }\n\n/* Where the renders stopped agreeing. Directly above the list they divide, so a\n reviewer reads the groups and then finds them in order \u2014 and the sizes are the\n left column in both, which is what makes the two readable as one list. */\n.va-parted { margin: 1.4rem 0 0.6rem; }\n.va-parted h2 { margin-bottom: 0.4rem; }\n.va-parted ul { display: grid; gap: 0.5rem; list-style: none; margin: 0; padding: 0; }\n.va-parted li { border-left: 3px solid var(--va-line); padding: 0.1rem 0 0.1rem 0.7rem; }\n.va-parted li:first-child { border-left-color: var(--va-collateral); }\n.va-parted-head { align-items: baseline; display: flex; flex-wrap: wrap; gap: 0.6rem; margin: 0; }\n.va-parted-head .va-num { color: var(--va-ink); font-family: var(--va-mono); font-size: 0.95rem; }\n.va-parted-only { color: var(--va-ink-2); font-size: 0.85rem; font-weight: 600; }\n.va-parted-take { background: var(--va-sunken); border-radius: 5px; color: var(--va-ink-3); font-size: 0.74rem; margin-left: auto; padding: 0.1rem 0.4rem; }\n.va-parted-in { font-size: 0.8rem; margin: 0.15rem 0 0; overflow-wrap: anywhere; }\n\n/* Where it showed up: one row per render, each decidable on its own, because a\n batch that could only be taken whole would be a batch nobody could refuse\n part of. */\n.va-where { display: grid; gap: 0.15rem; margin-top: 0.5rem; }\n.va-where-row { align-items: baseline; border-radius: 8px; column-gap: 0.6rem; display: grid; grid-template-columns: minmax(6rem, 15rem) auto auto minmax(0, 1fr) auto; padding: 0.35rem 0.5rem; }\n.va-where-row:hover { background: var(--va-sunken); }\n.va-where-subject { font-size: 0.88rem; font-weight: 550; grid-column: 1; overflow: hidden; text-overflow: ellipsis; text-decoration: none; white-space: nowrap; }\n.va-where-size { grid-column: 2; text-align: right; }\n.va-where-row .va-mark { grid-column: 3; }\n.va-where-with { grid-column: 4; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.va-where-row .va-note { font-size: 0.76rem; }\n.va-where-act { display: flex; gap: 0.25rem; grid-column: 5; justify-self: end; }\n.va-where-row > .va-mark:last-child { grid-column: 5; justify-self: end; }\n.va-where-act button { border-radius: 6px; font-size: 0.8rem; line-height: 1; padding: 0.2rem 0.5rem; }\n.va-where-act .va-approve:not(:disabled) { border-color: var(--va-good); color: var(--va-good-ink); }\n.va-mark.va-known { background: var(--va-warn-bg); border-radius: 999px; color: var(--va-warn-ink); font-size: 0.68rem; padding: 0.05rem 0.4rem; }\n.va-mark.va-alarm { background: var(--va-bad-bg); border-radius: 999px; color: var(--va-bad-ink); font-size: 0.68rem; padding: 0.05rem 0.4rem; }\n\n/* What moved, in the sense the hashes recorded. The lead sentence is emphasis\n inside the existing lead paragraph and gets no box of its own \u2014 it is the\n subject of the page, not a note beside it. What follows is detail, and the\n only part that raises its voice is a component the picture lost: the hashes\n name it and no region does, which is the one state a reviewer cannot see. */\n.va-decide-lead em { font-style: normal; font-weight: 600; }\n.va-moved-lost { background: var(--va-bad-bg); border-radius: 7px; color: var(--va-bad-ink); font-size: 0.9rem; margin-top: 0.7rem; padding: 0.5rem 0.7rem; }\n.va-moved h3 { font-size: 0.72rem; letter-spacing: 0.06em; margin-top: 1rem; text-transform: uppercase; }\n.va-moved-with { display: grid; gap: 0.15rem; margin-top: 0.35rem; }\n.va-moved-with li { align-items: baseline; column-gap: 0.5rem; display: flex; flex-wrap: wrap; font-size: 0.88rem; }\n.va-moved-list { display: grid; gap: 0.3rem; }\n.va-moved-row { align-items: baseline; column-gap: 0.5rem; display: flex; flex-wrap: wrap; font-size: 0.85rem; }\n/* Pushed rather than edited, and dimmed to say so. The list is ordered by name\n and not by consequence, so without this a passenger reads level with a cause. */\n.va-moved-passenger .va-moved-name { color: var(--va-ink-3); font-weight: 400; }\n.va-moved-name { font-weight: 600; }\n/* How far a passenger is from the change, in the import graph. A chip and not a\n sentence, and only on the rows the records place: a column that says the same\n thing on every row is read once and skipped after. */\n.va-moved-far { background: var(--va-sunken); border-radius: 5px; color: var(--va-ink-3); font-size: 0.74rem; padding: 0.05rem 0.35rem; }\n\n/* The commit, its files, and how far out it landed \u2014 the build page's own\n section, above the docket rather than beside it, because it is true of every\n change on the page and nothing on it is decided. */\n.va-impact { border-top: 1px solid var(--va-line); display: grid; gap: 1rem; margin-top: 1.4rem; padding-top: 1.1rem; }\n.va-impact-commit { align-items: baseline; display: flex; flex-wrap: wrap; font-size: 0.9rem; }\n.va-impact-files ul { display: grid; gap: 0.1rem; margin-top: 0.35rem; }\n.va-impact-files li { font-size: 0.82rem; }\n.va-impact-depth h2 { font-size: 0.72rem; letter-spacing: 0.06em; text-transform: uppercase; }\n.va-rungs { display: grid; gap: 0.3rem; margin-top: 0.5rem; max-width: 34rem; }\n.va-rung { align-items: center; display: grid; gap: 0.6rem; grid-template-columns: 7.5rem 1fr auto; }\n.va-rung-at { font-size: 0.8rem; text-align: right; }\n/* The bar is the reached count and the fill is the moved count inside it, so the\n two are read as a share rather than as two lengths a reader has to divide. */\n.va-rung-bar { background: var(--va-collateral); border-radius: 3px; display: block; height: 0.6rem; min-width: 2px; }\n.va-rung-moved { background: var(--va-cause); border-radius: 3px; display: block; height: 100%; }\n.va-rung-num { font-size: 0.78rem; }\n/* The movement the bars cannot hold, which is the one part of the spread they\n are silent about. A list and not a sentence, because each row carries its own\n reason and a paragraph of them is a paragraph nobody finishes. */\n.va-unheld { background: var(--va-bad-bg); border-radius: 7px; color: var(--va-bad-ink); font-size: 0.85rem; margin-top: 0.7rem; max-width: 34rem; padding: 0.5rem 0.7rem; }\n.va-unheld ul { display: grid; gap: 0.25rem; margin-top: 0.4rem; }\n.va-unheld li { align-items: baseline; column-gap: 0.45rem; display: flex; flex-wrap: wrap; }\n.va-unheld-name { font-weight: 600; }\n.va-unheld-why { opacity: 0.78; }\n\n\n.va-filter { align-items: center; display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 1rem 0; }\n\n.va-changes { display: grid; gap: 0.85rem; }\n.va-change { background: var(--va-surface); border: 1px solid var(--va-line); border-radius: 12px; padding: 0.9rem 1.1rem; }\n.va-change h3 { font-size: 1rem; margin-bottom: 0.25rem; }\n.va-change-meta, .va-fingerprint { color: var(--va-ink-3); font-size: 0.82rem; }\n.va-fingerprint { border-top: 1px solid var(--va-line); margin-top: 0.65rem; padding-top: 0.55rem; }\n.va-change-subjects { color: var(--va-ink-2); columns: 3 14rem; font-size: 0.84rem; margin-top: 0.4rem; }\n.va-ungrouped { border-top: 1px solid var(--va-line-firm); margin-top: 1.75rem; padding-top: 1.25rem; }\n\n/* The three stability states are drawn as three, deliberately: unknown is not\n clean, and a rate nobody swept for is not a rate of zero. */\n.va-history { font-size: 0.86rem; }\n.va-ask { font-size: 0.86rem; width: 100%; }\n.va-stability, .va-churn { color: var(--va-ink-2); font-size: 0.86rem; margin-bottom: 0.5rem; }\n.va-stability.va-unknown, .va-churn.va-unknown { color: var(--va-warn); }\n.va-stability.va-flaky { color: var(--va-bad); }\n\n/* One finding, in three registers: what it is, where it is, and the sentence\n that explains it. The rule id is last because it is the least of the three to\n a person and the whole of it to an ignore list.\n\n The lead is the only loud thing in the panel and it is one sentence about this\n change. The method line that used to open the panel is now the last line in it,\n at note size: it says why nothing here moved the verdict, which is worth\n knowing and is worth nobody's first glance. */\n.va-findings-lead { font-size: 0.9rem; font-weight: 650; margin-bottom: 0.7rem; }\n.va-findings-lead.va-findings-mine { color: var(--va-warn-ink); }\n.va-findings-why { border-top: 1px solid var(--va-line); margin-top: 0.9rem; padding-top: 0.5rem; }\n/* Shut by default, and the summary is the whole argument for the fold: a count a\n reviewer can decide to open, rather than twenty-two rows they have to scroll. */\n.va-findings-rest { margin-top: 1rem; }\n.va-findings-rest > summary { color: var(--va-ink-2); cursor: pointer; font-size: 0.8rem; padding: 0.35rem 0; }\n.va-findings-rest[open] > summary { color: var(--va-ink); }\n.va-findings-rest > .va-note { margin-bottom: 0.7rem; }\n.va-findings-band + .va-findings-band { margin-top: 0.9rem; }\n.va-band-head { color: var(--va-ink-2); font-size: 0.72rem; font-weight: 700; letter-spacing: 0.09em; margin-bottom: 0.5rem; text-transform: uppercase; }\n.va-findings { display: grid; gap: 0.7rem; }\n.va-finding { border-left: 2px solid var(--va-line-firm); padding-left: 0.7rem; }\n.va-finding-new { border-left-color: var(--va-warn); }\n/* The headline is an item and the marks may wrap under it. Left as a bare text\n node beside two flex-none badges it became an anonymous item with nothing\n holding its width, and \"a control inside another control\" read down the rail\n one word to a line. */\n.va-finding-title { align-items: baseline; display: flex; flex-wrap: wrap; font-size: 0.88rem; font-weight: 650; gap: 0.5rem; justify-content: space-between; }\n.va-finding-said { flex: 1 1 9rem; }\n.va-finding-marks { align-items: baseline; display: flex; flex: none; gap: 0.45rem; }\n.va-times { color: var(--va-accent); flex: none; font-family: var(--va-mono); font-size: 0.72rem; font-weight: 500; }\n.va-age { border-radius: 5px; color: var(--va-ink-3); flex: none; font-size: 0.7rem; font-weight: 500; padding: 0.1rem 0.4rem; white-space: nowrap; }\n.va-age-new { background: var(--va-warn-bg); color: var(--va-warn-ink); }\n.va-age-standing, .va-age-undated { background: var(--va-info-bg); }\n.va-finding-where { color: var(--va-ink-2); font-size: 0.8rem; }\n.va-finding-what { color: var(--va-ink-2); font-size: 0.8rem; margin-top: 0.2rem; }\n.va-finding-owner { align-items: center; display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.35rem; }\n.va-tag { background: var(--va-surface); border: 1px solid var(--va-line); border-radius: 5px; color: var(--va-ink-2); font-size: 0.72rem; padding: 0.1rem 0.4rem; }\n.va-tag.va-rule { color: var(--va-ink-3); }\n\n/* The declaration ledgers. Every rule is a row, including the ones that absorbed\n nothing \u2014 those are the finding, and a table that hid them would be a table of\n rules that are working. The rule name is the widest column because it is the\n thing a reader copies into their config; the reason is the widest prose. */\n.va-ledger { margin-top: 0.5rem; }\n.va-ledger code { font-size: 0.78rem; }\n.va-ledger em { color: var(--va-ink-3); font-size: 0.72rem; font-style: normal; }\n.va-ledger .va-none { color: var(--va-ink-3); }\n.va-ledger .va-ledger-why { color: var(--va-ink-2); width: 38%; }\n.va-ledger .va-tag { margin-right: 0.25rem; }\n/* Marked on the row rather than only on the badge: a reviewer scanning for the\n one rule that is wrong reads the left edge, not the third column. */\n.va-ledger tr.va-spent td:first-child { border-left: 2px solid var(--va-warn); padding-left: 0.4rem; }\n.va-tag.va-warn { background: var(--va-warn-bg); border-color: transparent; color: var(--va-warn-ink); }\n.va-ledger-head { color: var(--va-ink-2); font-size: 0.8rem; font-weight: 650; margin-top: 0.9rem; }\n.va-ledger-head .va-note { font-weight: 400; margin-left: 0.5rem; }\n\n/* Folded, because on a run of three hundred stories this is three hundred lines\n of nothing \u2014 and present, because a green subject that is green by declaration\n is the one a mask hides behind. */\n.va-settled > summary { color: var(--va-ink-2); cursor: pointer; font-size: 0.86rem; }\n.va-settled-list { display: grid; gap: 0.3rem; margin-top: 0.6rem; }\n.va-settled-list li { align-items: baseline; display: flex; font-size: 0.84rem; gap: 0.45rem; }\n.va-settled-list strong { font-family: var(--va-mono); font-size: 0.78rem; font-weight: 500; }\n\n.va-not-observed { color: var(--va-ink-2); display: grid; font-size: 0.86rem; gap: 0.35rem; }\n.va-not-observed .va-failed { color: var(--va-bad); font-weight: 600; }\n\n.va-decision { color: var(--va-good); font-size: 0.86rem; margin-bottom: 0.5rem; }\n.va-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; }\n.va-actions button { flex: 1; font-weight: 600; }\n.va-actions .va-approve { background: var(--va-good); border-color: var(--va-good); color: #ffffff; }\n.va-actions .va-approve:disabled { background: var(--va-sunken); border-color: var(--va-line-firm); color: var(--va-ink-3); }\n\n@media (max-width: 60rem) {\n .va-body { flex-wrap: wrap; }\n .va-rail { border-right: 0; width: 100%; }\n .va-subject { flex-wrap: wrap; }\n .va-aside { border-left: 0; width: 100%; }\n .va-reach .va-quad { grid-template-columns: minmax(0, 1fr); }\n}\n\n/* Motion is never how anything here is said, so there is nothing to preserve when\n a reader has asked for less of it. The blink and the scroll to a region are\n turned off in the component that starts them, because neither is a CSS\n animation this could reach; this catches the transitions. */\n@media (prefers-reduced-motion: reduce) {\n .va-app *, .va-app *::before, .va-app *::after { animation-duration: 1ms; animation-iteration-count: 1; scroll-behavior: auto; transition-duration: 1ms; }\n}\n\n@media (prefers-color-scheme: light) {\n :root, .va-app { --va-bg: #f3f4f6; --va-surface: #ffffff; --va-sunken: #e9eaec; --va-line: #d8d6d3; --va-line-firm: #b8b3ae; --va-ink: #181b1d; --va-ink-2: #4c4844; --va-ink-3: #756d67; --va-accent: #d83a13; --va-accent-ink: #ffffff; --va-warn: #8a5a12; --va-warn-bg: #f7ecd9; --va-warn-ink: #5c3c08; --va-bad: #b03a2b; --va-bad-bg: #f8e3df; --va-bad-ink: #7a2418; --va-good: #46705a; --va-good-bg: #dfece4; --va-good-ink: #2b4a38; --va-info-bg: #ecebe9; --va-info-ink: #3d3935; --va-cause: #d83a13; --va-collateral: #756d67; --va-accent-soft: rgba(216, 58, 19, 0.10); --va-veil: rgba(243, 244, 246, 0.55); }\n}\n";
|
|
12
|
+
//# sourceMappingURL=styles.d.ts.map
|
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The stylesheet, as a string the operator injects.
|
|
3
|
+
*
|
|
4
|
+
* Not imported, not bundled, not a CSS module and not a dependency on anybody's
|
|
5
|
+
* build. A component library that ships a `.css` import decides the consumer's
|
|
6
|
+
* toolchain for them; this one hands over text and lets them put it in a
|
|
7
|
+
* `<style>` tag, a `layout.tsx`, or nowhere at all — the markup carries plain
|
|
8
|
+
* class names and degrades to unstyled rather than to broken.
|
|
9
|
+
*
|
|
10
|
+
* Three decisions here are load-bearing rather than decorative:
|
|
11
|
+
*
|
|
12
|
+
* **Cause and collateral are drawn differently.** A single highlight colour would
|
|
13
|
+
* make the box that was edited and the box that merely reflowed look like the
|
|
14
|
+
* same finding, which is precisely the mistake ranking by area makes.
|
|
15
|
+
*
|
|
16
|
+
* **Images render at their own pixel grid.** `image-rendering: pixelated` and no
|
|
17
|
+
* smoothing, because a reviewer zooming into a 2px shift must see 2px and not an
|
|
18
|
+
* interpolation of it.
|
|
19
|
+
*
|
|
20
|
+
* **The page does not grow with the build.** Every pane scrolls inside its own
|
|
21
|
+
* box and the document does not scroll at all. Twenty full-page routes stacked
|
|
22
|
+
* down one document is twenty-seven thousand pixels of page, and a reviewer who
|
|
23
|
+
* has to scroll past a whole render to reach the next subject stops reading them
|
|
24
|
+
* — which is the review blindness this surface exists to refuse, arriving as a
|
|
25
|
+
* layout instead of as a ranking.
|
|
26
|
+
*
|
|
27
|
+
* Colour is spent through tokens on `:root`, so a second scheme re-decides values
|
|
28
|
+
* and never rules. A scheme that could move a box is a second chance to disagree
|
|
29
|
+
* with the region coordinates the run measured.
|
|
30
|
+
*
|
|
31
|
+
* The ground is dark, and that is a decision rather than a default. A capture is
|
|
32
|
+
* the only thing on this page whose colour is evidence; every pixel of chrome
|
|
33
|
+
* around it is the room the evidence is read in, and a room that is brighter than
|
|
34
|
+
* the exhibit shifts what the exhibit looks like. `prefers-color-scheme: light`
|
|
35
|
+
* re-decides the same values for a reader who asks for it.
|
|
36
|
+
*
|
|
37
|
+
* The palette is `docs/visual-guidelines.md` — deep, panel, ivory, quiet, warm,
|
|
38
|
+
* variance orange, signal green — spent here on a surface that also has to say
|
|
39
|
+
* *unknown* and *refused*, which brand assets never do. The font tokens name
|
|
40
|
+
* Inter and JetBrains Mono first and fall back to the system stacks: this sheet is
|
|
41
|
+
* handed over as text, so it can ask for a face and must not require one.
|
|
42
|
+
*/
|
|
43
|
+
import { DOCKET_STYLES } from './styles-docket.js';
|
|
44
|
+
import { STAGE_STYLES } from './styles-stage.js';
|
|
45
|
+
/**
|
|
46
|
+
* The whole sheet, in one string, with the stage spliced into the middle of it.
|
|
47
|
+
*
|
|
48
|
+
* One value rather than two exports a consumer composes, because the two halves
|
|
49
|
+
* are not optional with respect to each other: a page that injected this and not
|
|
50
|
+
* [`STAGE_STYLES`](./styles-stage.ts) would have every caption styled and the
|
|
51
|
+
* evidence unstyled, which is the one failure mode worth making unreachable. The
|
|
52
|
+
* split is a limit on how much of this a person has to hold at once, not an
|
|
53
|
+
* offer.
|
|
54
|
+
*/
|
|
55
|
+
export const REVIEW_STYLES = `
|
|
56
|
+
:root, .va-app { --va-bg: #181b1d; --va-surface: #1e2224; --va-sunken: #181b1d; --va-line: #2f3437; --va-line-firm: #434a4d; --va-ink: #f3f4f6; --va-ink-2: #a8a09b; --va-ink-3: #8f8580; --va-accent: #ff4a19; --va-accent-ink: #181b1d; --va-warn: #e0a458; --va-warn-bg: #2a2118; --va-warn-ink: #f0c48a; --va-bad: #e5695c; --va-bad-bg: #2c1b18; --va-bad-ink: #f3a99e; --va-good: #7fa28c; --va-good-bg: #1a2420; --va-good-ink: #a8c9b5; --va-info-bg: #24282a; --va-info-ink: #d6d0cb; --va-cause: #ff4a19; --va-collateral: #8f8580; --va-accent-soft: rgba(255, 74, 25, 0.14); --va-veil: rgba(24, 27, 29, 0.52); --va-sans: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; --va-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; }
|
|
57
|
+
|
|
58
|
+
.va-app { background: var(--va-bg); color: var(--va-ink); color-scheme: dark light; display: flex; flex-direction: column; font-family: var(--va-sans); font-size: 14px; height: 100dvh; line-height: 1.5; overflow: hidden; }
|
|
59
|
+
/* The element reset, every rule of it wrapped in :where() so the whole block
|
|
60
|
+
weighs nothing. Written plainly, a rule like .va-app h2 scores higher than any
|
|
61
|
+
single-class rule below it, and the component that says what its own heading
|
|
62
|
+
looks like loses to a reset it never knew it was arguing with. That failure is
|
|
63
|
+
invisible on the page and invisible in review: the sheet reads correctly and
|
|
64
|
+
the render simply is not it. A reset is the sentence "unless somebody says
|
|
65
|
+
otherwise", and :where() is how that clause is spelled. */
|
|
66
|
+
:where(.va-app *, .va-app *::before, .va-app *::after) { box-sizing: border-box; }
|
|
67
|
+
:where(.va-app h1, .va-app h2, .va-app h3) { line-height: 1.25; margin: 0; }
|
|
68
|
+
:where(.va-app h1) { font-size: 1.35rem; letter-spacing: -0.01em; }
|
|
69
|
+
:where(.va-app h2) { font-size: 0.95rem; letter-spacing: -0.005em; }
|
|
70
|
+
:where(.va-app h3) { font-size: 1.05rem; letter-spacing: -0.005em; }
|
|
71
|
+
:where(.va-app p) { margin: 0; }
|
|
72
|
+
:where(.va-app code, .va-commit) { font-family: var(--va-mono); font-size: 0.85em; }
|
|
73
|
+
.va-num { font-variant-numeric: tabular-nums; }
|
|
74
|
+
|
|
75
|
+
/* Same reasoning, and this is where it was actually caught: the rail item, the
|
|
76
|
+
mode pill and the build opener each declared no border and were given one
|
|
77
|
+
anyway. */
|
|
78
|
+
:where(.va-app button) { background: var(--va-surface); border: 1px solid var(--va-line-firm); border-radius: 7px; color: var(--va-ink); cursor: pointer; font: inherit; padding: 0.35rem 0.75rem; }
|
|
79
|
+
:where(.va-app button:hover) { border-color: var(--va-ink-3); }
|
|
80
|
+
:where(.va-app button:disabled) { cursor: not-allowed; opacity: 0.55; }
|
|
81
|
+
:where(.va-app button.va-current:disabled) { cursor: default; opacity: 1; }
|
|
82
|
+
:where(.va-app input) { background: var(--va-surface); border: 1px solid var(--va-line-firm); border-radius: 7px; color: var(--va-ink); font: inherit; padding: 0.35rem 0.6rem; }
|
|
83
|
+
:where(.va-app ul, .va-app ol) { list-style: none; margin: 0; padding: 0; }
|
|
84
|
+
|
|
85
|
+
/* The two things the reset above would otherwise have taken away. A surface that
|
|
86
|
+
reports \`nested-interactive\` and unreachable controls cannot itself leave a
|
|
87
|
+
keyboard reviewer guessing where they are — and the seam is the case that
|
|
88
|
+
forces it, being an appearance-stripped range with no border of its own. */
|
|
89
|
+
:where(.va-app a, .va-app button, .va-app summary, .va-app input, .va-app [tabindex]):focus-visible { outline: 2px solid var(--va-accent); outline-offset: 3px; }
|
|
90
|
+
.va-app ::selection { background: var(--va-accent); color: var(--va-accent-ink); }
|
|
91
|
+
|
|
92
|
+
/* The three panes. \`min-height: 0\` on each, because a flex child defaults to a
|
|
93
|
+
floor of its content and a rail of two hundred subjects would push the shell
|
|
94
|
+
past the viewport rather than scrolling inside it. */
|
|
95
|
+
.va-body { display: flex; flex: 1; min-height: 0; }
|
|
96
|
+
.va-scroll { min-height: 0; overflow: auto; overscroll-behavior: contain; }
|
|
97
|
+
.va-page { flex: 1; margin: 0 auto; max-width: 72rem; min-width: 0; padding: 1.5rem 1.75rem 4rem; }
|
|
98
|
+
|
|
99
|
+
.va-topbar { align-items: center; background: var(--va-surface); border-bottom: 1px solid var(--va-line); display: flex; flex: none; gap: 0.75rem; padding: 0.7rem 1rem; }
|
|
100
|
+
.va-brand { color: var(--va-ink); flex: none; }
|
|
101
|
+
.va-topbar-title { display: flex; flex-direction: column; line-height: 1.2; }
|
|
102
|
+
.va-topbar-title strong { font-size: 0.95rem; }
|
|
103
|
+
.va-topbar-sub { color: var(--va-ink-3); font-size: 0.78rem; }
|
|
104
|
+
.va-topbar-meta { align-items: center; color: var(--va-ink-3); display: flex; flex-wrap: wrap; font-size: 0.8rem; gap: 0.5rem; justify-content: flex-end; margin-left: auto; }
|
|
105
|
+
.va-topbar-meta .va-commit { background: var(--va-sunken); border-radius: 5px; color: var(--va-ink-2); padding: 0.1rem 0.35rem; }
|
|
106
|
+
.va-back { flex: none; }
|
|
107
|
+
|
|
108
|
+
.va-nav { display: flex; gap: 0.35rem; }
|
|
109
|
+
.va-nav button.va-current { background: var(--va-accent-soft); border-color: var(--va-accent); color: var(--va-accent); cursor: default; }
|
|
110
|
+
|
|
111
|
+
.va-pill { border-radius: 999px; flex: none; font-size: 0.75rem; font-weight: 600; padding: 0.15rem 0.6rem; white-space: nowrap; }
|
|
112
|
+
.va-pill.va-warn { background: var(--va-warn-bg); color: var(--va-warn-ink); }
|
|
113
|
+
.va-pill.va-good { background: var(--va-good-bg); color: var(--va-good-ink); }
|
|
114
|
+
.va-pill.va-bad { background: var(--va-bad-bg); color: var(--va-bad-ink); }
|
|
115
|
+
|
|
116
|
+
.va-note { color: var(--va-ink-3); font-size: 0.88rem; }
|
|
117
|
+
.va-failure { background: var(--va-bad-bg); border-radius: 8px; color: var(--va-bad-ink); font-size: 0.88rem; margin: 0.5rem 0; padding: 0.6rem 0.75rem; }
|
|
118
|
+
.va-card { background: var(--va-surface); border: 1px solid var(--va-line); border-radius: 12px; margin-bottom: 1rem; padding: 1rem 1.1rem; }
|
|
119
|
+
.va-card > h2 { color: var(--va-ink-3); font-size: 0.72rem; font-weight: 700; letter-spacing: 0.09em; margin-bottom: 0.6rem; text-transform: uppercase; }
|
|
120
|
+
|
|
121
|
+
.va-builds { display: grid; gap: 0.85rem; }
|
|
122
|
+
.va-build { background: var(--va-surface); border: 1px solid var(--va-line); border-radius: 12px; padding: 0.9rem 1.1rem; }
|
|
123
|
+
.va-build-head { align-items: center; display: flex; flex-wrap: wrap; gap: 0.6rem; margin-bottom: 0.45rem; }
|
|
124
|
+
.va-build-open { align-items: baseline; background: none; border: 0; border-radius: 0; display: flex; gap: 0.5rem; padding: 0; }
|
|
125
|
+
.va-build-id { font-size: 1.05rem; font-weight: 650; letter-spacing: -0.01em; }
|
|
126
|
+
.va-build-go { color: var(--va-accent); font-size: 0.82rem; font-weight: 600; }
|
|
127
|
+
.va-commit { background: var(--va-sunken); border-radius: 5px; color: var(--va-ink-2); padding: 0.1rem 0.35rem; }
|
|
128
|
+
.va-branch { color: var(--va-ink-2); font-size: 0.82rem; }
|
|
129
|
+
.va-when { color: var(--va-ink-3); font-size: 0.78rem; margin-left: auto; }
|
|
130
|
+
|
|
131
|
+
.va-verdicts { align-items: center; display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 0.3rem; }
|
|
132
|
+
.va-pending { color: var(--va-warn); font-weight: 650; }
|
|
133
|
+
.va-settled { color: var(--va-good); font-weight: 650; }
|
|
134
|
+
.va-counts { color: var(--va-ink-3); font-size: 0.84rem; }
|
|
135
|
+
.va-coverage { color: var(--va-ink-2); font-size: 0.84rem; }
|
|
136
|
+
.va-coverage.va-unknown { color: var(--va-warn); }
|
|
137
|
+
.va-coverage.va-incomplete { color: var(--va-bad); font-weight: 600; }
|
|
138
|
+
|
|
139
|
+
/* The rail: every reviewable subject at a glance, so the reviewer chooses which
|
|
140
|
+
render to open instead of scrolling through all of them. */
|
|
141
|
+
.va-rail { background: var(--va-surface); border-right: 1px solid var(--va-line); display: flex; flex-direction: column; flex: none; min-height: 0; padding: 0.6rem; width: 21rem; }
|
|
142
|
+
.va-rail-group { align-items: center; color: var(--va-ink-3); display: flex; font-size: 0.7rem; font-weight: 700; gap: 0.4rem; letter-spacing: 0.09em; padding: 0.9rem 0.55rem 0.35rem; text-transform: uppercase; }
|
|
143
|
+
.va-rail-count { background: var(--va-sunken); border-radius: 999px; color: var(--va-ink-2); font-size: 0.7rem; letter-spacing: 0; padding: 0 0.4rem; }
|
|
144
|
+
.va-rail-item { align-items: center; background: none; border: 1px solid transparent; border-radius: 8px; display: flex; gap: 0.55rem; margin-bottom: 0.1rem; padding: 0.45rem 0.55rem; text-align: left; width: 100%; }
|
|
145
|
+
.va-rail-item:hover { background: var(--va-sunken); }
|
|
146
|
+
.va-rail-item.va-current { background: var(--va-accent-soft); border-color: var(--va-accent); }
|
|
147
|
+
.va-rail-body { min-width: 0; }
|
|
148
|
+
.va-rail-name { display: block; font-size: 0.86rem; font-weight: 550; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
149
|
+
.va-rail-note { color: var(--va-ink-3); display: block; font-size: 0.75rem; overflow-wrap: anywhere; }
|
|
150
|
+
.va-rail-item.va-current .va-rail-note { color: var(--va-ink-2); }
|
|
151
|
+
.va-dot { border-radius: 50%; flex: none; height: 8px; width: 8px; }
|
|
152
|
+
.va-dot.va-changed { background: var(--va-warn); }
|
|
153
|
+
.va-dot.va-new { background: var(--va-accent); }
|
|
154
|
+
.va-dot.va-incomparable { background: var(--va-bad); }
|
|
155
|
+
.va-dot.va-unstable { background: var(--va-bad); }
|
|
156
|
+
.va-dot.va-failed { background: var(--va-bad); }
|
|
157
|
+
.va-dot.va-ignored { background: var(--va-ink-3); }
|
|
158
|
+
.va-dot.va-unchanged { background: var(--va-good); }
|
|
159
|
+
.va-mark { flex: none; font-size: 0.8rem; margin-left: auto; }
|
|
160
|
+
.va-mark.va-approved { color: var(--va-good); }
|
|
161
|
+
.va-mark.va-rejected { color: var(--va-bad); }
|
|
162
|
+
|
|
163
|
+
.va-stage { background: var(--va-bg); flex: 1; min-width: 0; }
|
|
164
|
+
.va-subject { display: flex; flex: 1; min-height: 0; min-width: 0; }
|
|
165
|
+
.va-subject-head { align-items: center; display: flex; flex-wrap: wrap; gap: 0.6rem; margin-bottom: 0.35rem; }
|
|
166
|
+
.va-verdict { border-radius: 999px; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.06em; padding: 0.15rem 0.55rem; text-transform: uppercase; }
|
|
167
|
+
.va-verdict.va-changed { background: var(--va-warn-bg); color: var(--va-warn-ink); }
|
|
168
|
+
.va-verdict.va-new { background: var(--va-info-bg); color: var(--va-info-ink); }
|
|
169
|
+
.va-verdict.va-incomparable { background: var(--va-bad-bg); color: var(--va-bad-ink); }
|
|
170
|
+
.va-verdict.va-unstable { background: var(--va-bad-bg); color: var(--va-bad-ink); }
|
|
171
|
+
.va-because { color: var(--va-ink-2); font-size: 0.88rem; }
|
|
172
|
+
|
|
173
|
+
/* The three measurements a reviewer takes in before reading anything: who moved,
|
|
174
|
+
how much the canvas grew, and how much of it differs. The sentence underneath
|
|
175
|
+
said all three in one clause each and was skipped by the second subject, so the
|
|
176
|
+
numbers are set large and the units small and the prose stands down. Accent on
|
|
177
|
+
the component name only, because that is the one answer the picture cannot give
|
|
178
|
+
— a region is named from where its box landed, not from what moved it. */
|
|
179
|
+
.va-glance { align-items: flex-start; display: flex; flex-wrap: wrap; gap: 1.6rem; margin: 0.55rem 0 0.35rem; }
|
|
180
|
+
.va-glance-cell { display: flex; flex-direction: column; gap: 0.12rem; margin: 0; }
|
|
181
|
+
.va-glance-cell b { color: var(--va-ink); font-family: var(--va-mono); font-size: 1.4rem; font-weight: 650; letter-spacing: -0.02em; line-height: 1.15; }
|
|
182
|
+
.va-glance-cell span { color: var(--va-ink-3); font-family: var(--va-mono); font-size: 0.66rem; letter-spacing: 0.1em; text-transform: uppercase; }
|
|
183
|
+
.va-glance-cell small { color: var(--va-ink-2); font-family: var(--va-mono); font-size: 0.72rem; }
|
|
184
|
+
.va-glance-cause b { color: var(--va-cause); font-family: var(--va-sans); font-size: 1.45rem; letter-spacing: -0.01em; }
|
|
185
|
+
.va-glance-none b { color: var(--va-ink-2); font-size: 1.05rem; }
|
|
186
|
+
.va-glance-off { background: var(--va-warn-bg); border-radius: 4px; color: var(--va-warn-ink); margin-top: 0.15rem; padding: 0.05rem 0.35rem; width: fit-content; }
|
|
187
|
+
.va-said { color: var(--va-ink-3); font-size: 0.78rem; margin: 0.1rem 0 0; max-width: 74ch; }
|
|
188
|
+
.va-intent { color: var(--va-ink-2); font-size: 0.88rem; }
|
|
189
|
+
.va-subtitle { color: var(--va-ink-3); font-size: 0.88rem; margin-top: 0.2rem; }
|
|
190
|
+
|
|
191
|
+
/* The right-hand column: everything that is not the picture. A reviewer decides
|
|
192
|
+
from the record and the defect list, and neither should cost a scroll past a
|
|
193
|
+
nine-thousand-pixel render to reach. */
|
|
194
|
+
.va-aside { background: var(--va-surface); border-left: 1px solid var(--va-line); flex: none; padding: 1rem; width: 22rem; }
|
|
195
|
+
.va-aside .va-card { background: var(--va-sunken); border-color: transparent; }
|
|
196
|
+
.va-aside h2 { color: var(--va-ink-3); font-size: 0.72rem; font-weight: 700; letter-spacing: 0.09em; margin-bottom: 0.5rem; text-transform: uppercase; }
|
|
197
|
+
|
|
198
|
+
/* The review unit, which is a change and not a picture. Each card is one edit
|
|
199
|
+
and every place it landed, so the card is given the weight a row in a table
|
|
200
|
+
never had: a reviewer approves at this level and reads the subjects inside it
|
|
201
|
+
as evidence. The left edge is the cause colour, the same one the region boxes
|
|
202
|
+
use, because that is what the card is. */
|
|
203
|
+
.va-origins { display: grid; gap: 0.75rem; margin-top: 0.75rem; }
|
|
204
|
+
.va-origin { background: var(--va-sunken); border-left: 3px solid var(--va-cause); border-radius: 10px; padding: 0.85rem 1rem; }
|
|
205
|
+
.va-origin.va-orphan { border-left-color: var(--va-warn); }
|
|
206
|
+
.va-origin-head { align-items: baseline; display: flex; flex-wrap: wrap; gap: 0.5rem; }
|
|
207
|
+
.va-origin-head h3 { font-size: 1rem; margin: 0; }
|
|
208
|
+
.va-origin-pixels { color: var(--va-ink-3); font-size: 0.84rem; margin-left: auto; }
|
|
209
|
+
.va-file { color: var(--va-ink-2); }
|
|
210
|
+
.va-origin p { font-size: 0.86rem; margin: 0.35rem 0 0; }
|
|
211
|
+
.va-origin .va-churn, .va-origin .va-stability { margin: 0.35rem 0 0; }
|
|
212
|
+
.va-origin-arrival.va-alarm { background: var(--va-bad-bg); border-radius: 6px; color: var(--va-bad-ink); padding: 0.35rem 0.55rem; }
|
|
213
|
+
/* Two shapes under one component name is two edits, and the sentence saying so
|
|
214
|
+
is the one thing on the card that withdraws the batch approval. */
|
|
215
|
+
.va-note.va-warned { color: var(--va-warn-ink); }
|
|
216
|
+
.va-origin-where { display: grid; font-size: 0.86rem; gap: 0.35rem; margin-top: 0.7rem; }
|
|
217
|
+
.va-origin-where li { align-items: baseline; display: flex; flex-wrap: wrap; gap: 0.5rem; }
|
|
218
|
+
.va-origin-subject { font-weight: 600; }
|
|
219
|
+
.va-origin-act { align-items: center; display: flex; flex-wrap: wrap; gap: 0.55rem; margin-top: 0.8rem; }
|
|
220
|
+
.va-origin-act button { font-weight: 600; }
|
|
221
|
+
.va-origin-act .va-approve { background: var(--va-good); border-color: var(--va-good); color: #ffffff; }
|
|
222
|
+
.va-origin-act .va-approve:disabled { background: var(--va-sunken); border-color: var(--va-line-firm); color: var(--va-ink-3); }
|
|
223
|
+
.va-collateral { border-top: 1px solid var(--va-line); color: var(--va-ink-3); font-size: 0.84rem; margin-top: 0.75rem; padding-top: 0.65rem; }
|
|
224
|
+
|
|
225
|
+
/* Looking at the change from the card that decides it. The window is fixed and
|
|
226
|
+
the same for every crop: sizing each one to its own region would turn the strip
|
|
227
|
+
into a bar chart of areas, which is the ranking by area this whole surface
|
|
228
|
+
exists to refuse, drawn in the place a reviewer reads as how big is this. */
|
|
229
|
+
.va-origin-look { align-items: center; display: flex; flex-wrap: wrap; gap: 0.5rem; }
|
|
230
|
+
.va-look { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: 0.6rem; }
|
|
231
|
+
.va-sight { background: none; border: 0; color: inherit; cursor: pointer; display: flex; flex-direction: column; font: inherit; gap: 0.3rem; padding: 0; text-align: left; }
|
|
232
|
+
.va-crop { background: var(--va-bg); border: 1px solid var(--va-line); border-radius: 8px; display: block; overflow: hidden; position: relative; }
|
|
233
|
+
.va-sight:hover .va-crop, .va-sight:focus-visible .va-crop { border-color: var(--va-accent); }
|
|
234
|
+
.va-crop-plate { position: absolute; }
|
|
235
|
+
.va-crop-plate img { display: block; height: auto; image-rendering: pixelated; left: 0; position: absolute; top: 0; width: 100%; }
|
|
236
|
+
/* The veil rather than a ring alone: at 3x on a hundred-pixel region the ring is
|
|
237
|
+
most of the window, and a reviewer looking for the difference is looking for
|
|
238
|
+
which part of the window is not dimmed. The spread only has to exceed the crop,
|
|
239
|
+
which is 264px wide and clips it. */
|
|
240
|
+
.va-crop-box { border: 1px solid var(--va-cause); box-shadow: 0 0 0 900px var(--va-veil); position: absolute; }
|
|
241
|
+
.va-crop-part { background: var(--va-bg); border-radius: 5px; bottom: 0.3rem; color: var(--va-ink-3); font-family: var(--va-mono); font-size: 0.65rem; padding: 0.1rem 0.35rem; position: absolute; right: 0.3rem; }
|
|
242
|
+
.va-crop-unplaced { align-items: center; display: flex; justify-content: center; padding: 0.75rem; text-align: center; }
|
|
243
|
+
.va-sight-note { color: var(--va-ink-2); font-family: var(--va-mono); font-size: 0.7rem; max-width: 264px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
244
|
+
/* A subject name that goes somewhere. Underlined rather than coloured, because
|
|
245
|
+
the accent on this page means cause and a second meaning for it would make the
|
|
246
|
+
colour say nothing. */
|
|
247
|
+
.va-open { background: none; border: 0; color: inherit; cursor: pointer; font: inherit; padding: 0; text-align: left; text-decoration: underline; text-decoration-color: var(--va-line-firm); text-underline-offset: 3px; }
|
|
248
|
+
.va-open:hover { text-decoration-color: var(--va-accent); }
|
|
249
|
+
/* The commit does not reach this name, and reaches every render it moved in.
|
|
250
|
+
Ordinary, and therefore not wearing the alarm's colour: a page that shouts at
|
|
251
|
+
every component out of node_modules has spent the shout before the one render
|
|
252
|
+
nothing accounts for arrives. */
|
|
253
|
+
.va-origin-arrival.va-unnamed { background: var(--va-info-bg); border-radius: 6px; color: var(--va-info-ink); padding: 0.35rem 0.55rem; }
|
|
254
|
+
|
|
255
|
+
/* The third axis: what the commit reaches, crossed with what the run saw. Drawn
|
|
256
|
+
as a grid rather than four counts, because the four cells are one crossing and
|
|
257
|
+
a reader who takes them in as a shape sees at once which half of it is the
|
|
258
|
+
anomaly. */
|
|
259
|
+
.va-reach .va-quad { display: grid; gap: 0.5rem; grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: 0.9rem; }
|
|
260
|
+
.va-cell { background: var(--va-sunken); border-left: 3px solid var(--va-line-firm); border-radius: 9px; display: grid; gap: 0.1rem; padding: 0.7rem 0.85rem; }
|
|
261
|
+
.va-cell-n { font-size: 1.6rem; font-weight: 650; letter-spacing: -0.02em; line-height: 1.15; }
|
|
262
|
+
.va-cell-title { font-size: 0.82rem; font-weight: 650; }
|
|
263
|
+
.va-cell-note { color: var(--va-ink-3); font-size: 0.78rem; }
|
|
264
|
+
.va-cell.va-expected { border-left-color: var(--va-accent); }
|
|
265
|
+
.va-cell.va-alarm { background: var(--va-bad-bg); border-left-color: var(--va-bad); }
|
|
266
|
+
.va-cell.va-alarm .va-cell-n, .va-cell.va-alarm .va-cell-title { color: var(--va-bad-ink); }
|
|
267
|
+
.va-cell.va-inert { background: var(--va-warn-bg); border-left-color: var(--va-warn); }
|
|
268
|
+
.va-cell.va-inert .va-cell-n, .va-cell.va-inert .va-cell-title { color: var(--va-warn-ink); }
|
|
269
|
+
/* A quadrant holding nothing keeps its place and loses its voice. Dropped, it
|
|
270
|
+
reads as a question nobody asked; coloured as a finding, as one nobody
|
|
271
|
+
answered. */
|
|
272
|
+
.va-cell.va-zero { background: transparent; border-left-color: var(--va-line); }
|
|
273
|
+
.va-cell.va-zero .va-cell-n, .va-cell.va-zero .va-cell-title { color: var(--va-ink-3); font-weight: 550; }
|
|
274
|
+
|
|
275
|
+
.va-reach .va-band { border-left: 2px solid var(--va-line-firm); margin-top: 1.1rem; padding-left: 0.85rem; }
|
|
276
|
+
.va-reach .va-band.va-alarm { border-left-color: var(--va-bad); }
|
|
277
|
+
.va-reach .va-band.va-inert { border-left-color: var(--va-warn); }
|
|
278
|
+
.va-reach .va-band h3 { font-size: 0.95rem; margin-bottom: 0.25rem; }
|
|
279
|
+
.va-reach .va-stability, .va-reach .va-churn { margin: 0.2rem 0 0; }
|
|
280
|
+
.va-reach-list { display: grid; font-size: 0.86rem; gap: 0.5rem; margin-top: 0.55rem; }
|
|
281
|
+
.va-reach-list.va-columns { columns: 2 18rem; display: block; }
|
|
282
|
+
.va-reach-list.va-columns li { break-inside: avoid; margin-bottom: 0.35rem; }
|
|
283
|
+
|
|
284
|
+
/* The chain, which is the half a reviewer can disprove. A component named
|
|
285
|
+
without it is an assertion; tokens.css to button.tsx to Button is a claim
|
|
286
|
+
somebody can open three files and refute. */
|
|
287
|
+
.va-trails { display: grid; font-size: 0.84rem; gap: 0.35rem; margin-top: 0.55rem; }
|
|
288
|
+
.va-trails code { background: var(--va-sunken); border-radius: 5px; color: var(--va-ink-2); padding: 0.1rem 0.35rem; }
|
|
289
|
+
.va-arrow { color: var(--va-ink-3); padding: 0 0.3rem; }
|
|
290
|
+
.va-axis.va-unread { background: var(--va-warn-bg); color: var(--va-warn-ink); margin-left: 0.5rem; }
|
|
291
|
+
|
|
292
|
+
/* Drawn where the crossing would have been, never beside it: an empty grid over
|
|
293
|
+
a diff nothing could attribute reads as this commit reaches none of your
|
|
294
|
+
subjects, which is a sentence somebody merges on. */
|
|
295
|
+
.va-refusal { background: var(--va-warn-bg); border-radius: 9px; color: var(--va-warn-ink); font-size: 0.86rem; margin-top: 0.9rem; padding: 0.6rem 0.75rem; }
|
|
296
|
+
.va-reach-note { border-top: 1px solid var(--va-line); margin-top: 0.9rem; padding-top: 0.6rem; }
|
|
297
|
+
.va-reach-note code { color: var(--va-ink-2); }
|
|
298
|
+
.va-lost { color: var(--va-bad); }
|
|
299
|
+
|
|
300
|
+
/* The map. Three registers on one row — what was edited, what it arrived at, and
|
|
301
|
+
what became of the renders drawing that — so the eye reads left to right and
|
|
302
|
+
lands on the track. The indent under a file carries a hairline because the
|
|
303
|
+
relation is containment rather than sequence: at this density an indent alone
|
|
304
|
+
reads as a second list. */
|
|
305
|
+
.va-map { display: grid; gap: 0.55rem; margin-top: 0.9rem; }
|
|
306
|
+
.va-edits { display: grid; gap: 0.5rem; }
|
|
307
|
+
.va-edit { background: var(--va-sunken); border-radius: 9px; padding: 0.6rem 0.8rem; }
|
|
308
|
+
.va-edit-head { align-items: baseline; display: flex; flex-wrap: wrap; gap: 0.5rem; }
|
|
309
|
+
.va-edit-file { min-width: 0; overflow-wrap: anywhere; }
|
|
310
|
+
/* The verdict on an edit is the one label on this page that is read by scanning a
|
|
311
|
+
column rather than by reading a sentence, which is what the mono face is for. */
|
|
312
|
+
.va-effect { flex: none; font-family: var(--va-mono); font-size: 0.7rem; letter-spacing: 0.02em; margin-left: auto; text-transform: uppercase; }
|
|
313
|
+
.va-effect-cause { color: var(--va-accent); }
|
|
314
|
+
.va-effect-ask { color: var(--va-warn-ink); }
|
|
315
|
+
.va-effect-quiet { color: var(--va-ink-3); }
|
|
316
|
+
.va-arrivals { border-left: 1px solid var(--va-line-firm); display: grid; gap: 0.35rem; margin: 0.5rem 0 0 0.25rem; padding-left: 0.8rem; }
|
|
317
|
+
.va-arrival { align-items: center; display: flex; flex-wrap: wrap; gap: 0.5rem; min-width: 0; }
|
|
318
|
+
.va-arrival-name { font-size: 0.86rem; font-weight: 600; }
|
|
319
|
+
.va-arrival-through { color: var(--va-ink-3); font-size: 0.76rem; }
|
|
320
|
+
.va-arrival-tally { color: var(--va-ink-2); flex: none; font-size: 0.76rem; margin-left: auto; }
|
|
321
|
+
/* Cause, collateral, still and not-compared are the same four readings the region
|
|
322
|
+
overlay spends colour on, spent the same way here. A track that invented its own
|
|
323
|
+
palette would be a second vocabulary for one set of facts. */
|
|
324
|
+
.va-bar { background: var(--va-line); border-radius: 3px; display: flex; flex: 1; gap: 1px; height: 5px; max-width: 11rem; min-width: 3rem; overflow: hidden; }
|
|
325
|
+
.va-bar-part { display: block; }
|
|
326
|
+
.va-bar-caused { background: var(--va-cause); }
|
|
327
|
+
.va-bar-moved { background: var(--va-collateral); }
|
|
328
|
+
.va-bar-still { background: var(--va-good); }
|
|
329
|
+
.va-bar-uncompared { background: var(--va-line-firm); }
|
|
330
|
+
.va-map-aside { border-top: 1px solid var(--va-line); display: grid; gap: 0.5rem; padding-top: 0.6rem; }
|
|
331
|
+
.va-map-note { color: var(--va-ink-3); font-size: 0.8rem; }
|
|
332
|
+
.va-map-alarm { color: var(--va-bad-ink); }
|
|
333
|
+
|
|
334
|
+
/* Since the last run. Each state carries its own left rule, because the section is
|
|
335
|
+
read by jumping to the one that matters and a uniform stack would have to be
|
|
336
|
+
read in order to find it. */
|
|
337
|
+
.va-shift { border-left: 3px solid var(--va-line-firm); display: grid; gap: 0.25rem; margin-top: 0.85rem; padding-left: 0.8rem; }
|
|
338
|
+
.va-shift-head { align-items: baseline; display: flex; gap: 0.5rem; }
|
|
339
|
+
.va-shift-title { font-size: 0.9rem; font-weight: 650; }
|
|
340
|
+
.va-shift-count { font-size: 1.2rem; font-weight: 650; letter-spacing: -0.02em; margin-left: auto; }
|
|
341
|
+
.va-shift-alarm { border-left-color: var(--va-bad); }
|
|
342
|
+
.va-shift-alarm .va-shift-title, .va-shift-alarm .va-shift-count { color: var(--va-bad-ink); }
|
|
343
|
+
.va-shift-ask { border-left-color: var(--va-warn); }
|
|
344
|
+
.va-shift-ask .va-shift-title, .va-shift-ask .va-shift-count { color: var(--va-warn-ink); }
|
|
345
|
+
.va-shift-known { border-left-color: var(--va-accent); }
|
|
346
|
+
.va-shift-known .va-shift-count { color: var(--va-accent); }
|
|
347
|
+
.va-shift-good { border-left-color: var(--va-good); }
|
|
348
|
+
.va-shift-good .va-shift-count { color: var(--va-good-ink); }
|
|
349
|
+
.va-shift-quiet { border-left-color: var(--va-line); }
|
|
350
|
+
.va-shift-list { display: grid; font-size: 0.84rem; gap: 0.3rem; margin-top: 0.25rem; }
|
|
351
|
+
.va-shift-row { align-items: baseline; display: flex; flex-wrap: wrap; gap: 0.5rem; min-width: 0; }
|
|
352
|
+
.va-shift-subject { font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
|
|
353
|
+
.va-shift-held { border-top: 1px solid var(--va-line); margin-top: 0.95rem; padding-top: 0.6rem; }
|
|
354
|
+
|
|
355
|
+
.va-variation-list { display: grid; gap: 0.5rem; }
|
|
356
|
+
.va-variation { background: var(--va-sunken); border-radius: 9px; padding: 0.6rem 0.75rem; }
|
|
357
|
+
.va-variation-head { align-items: baseline; display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 0.15rem; }
|
|
358
|
+
/* Every chip carries its own text colour rather than inheriting the page's: the
|
|
359
|
+
backgrounds are light in both schemes, and a chip that inherited a dark
|
|
360
|
+
scheme's foreground would be pale text on a pale block. */
|
|
361
|
+
.va-axis { background: var(--va-info-bg); border-radius: 999px; color: var(--va-info-ink); font-size: 0.72rem; font-weight: 650; padding: 0.1rem 0.5rem; }
|
|
362
|
+
/* The two states a reviewer can act on, and they are not the same finding: an
|
|
363
|
+
arm that changes nothing was measured, a pair with no parent never was. */
|
|
364
|
+
.va-variation.va-inert .va-axis { background: var(--va-warn-bg); color: var(--va-warn-ink); }
|
|
365
|
+
.va-variation.va-unlinked .va-axis { background: var(--va-bad-bg); color: var(--va-bad-ink); }
|
|
366
|
+
.va-how { color: var(--va-ink-3); font-size: 0.75rem; }
|
|
367
|
+
|
|
368
|
+
${STAGE_STYLES}
|
|
369
|
+
${DOCKET_STYLES}
|
|
370
|
+
|
|
371
|
+
.va-filter { align-items: center; display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 1rem 0; }
|
|
372
|
+
|
|
373
|
+
.va-changes { display: grid; gap: 0.85rem; }
|
|
374
|
+
.va-change { background: var(--va-surface); border: 1px solid var(--va-line); border-radius: 12px; padding: 0.9rem 1.1rem; }
|
|
375
|
+
.va-change h3 { font-size: 1rem; margin-bottom: 0.25rem; }
|
|
376
|
+
.va-change-meta, .va-fingerprint { color: var(--va-ink-3); font-size: 0.82rem; }
|
|
377
|
+
.va-fingerprint { border-top: 1px solid var(--va-line); margin-top: 0.65rem; padding-top: 0.55rem; }
|
|
378
|
+
.va-change-subjects { color: var(--va-ink-2); columns: 3 14rem; font-size: 0.84rem; margin-top: 0.4rem; }
|
|
379
|
+
.va-ungrouped { border-top: 1px solid var(--va-line-firm); margin-top: 1.75rem; padding-top: 1.25rem; }
|
|
380
|
+
|
|
381
|
+
/* The three stability states are drawn as three, deliberately: unknown is not
|
|
382
|
+
clean, and a rate nobody swept for is not a rate of zero. */
|
|
383
|
+
.va-history { font-size: 0.86rem; }
|
|
384
|
+
.va-ask { font-size: 0.86rem; width: 100%; }
|
|
385
|
+
.va-stability, .va-churn { color: var(--va-ink-2); font-size: 0.86rem; margin-bottom: 0.5rem; }
|
|
386
|
+
.va-stability.va-unknown, .va-churn.va-unknown { color: var(--va-warn); }
|
|
387
|
+
.va-stability.va-flaky { color: var(--va-bad); }
|
|
388
|
+
|
|
389
|
+
/* One finding, in three registers: what it is, where it is, and the sentence
|
|
390
|
+
that explains it. The rule id is last because it is the least of the three to
|
|
391
|
+
a person and the whole of it to an ignore list.
|
|
392
|
+
|
|
393
|
+
The lead is the only loud thing in the panel and it is one sentence about this
|
|
394
|
+
change. The method line that used to open the panel is now the last line in it,
|
|
395
|
+
at note size: it says why nothing here moved the verdict, which is worth
|
|
396
|
+
knowing and is worth nobody's first glance. */
|
|
397
|
+
.va-findings-lead { font-size: 0.9rem; font-weight: 650; margin-bottom: 0.7rem; }
|
|
398
|
+
.va-findings-lead.va-findings-mine { color: var(--va-warn-ink); }
|
|
399
|
+
.va-findings-why { border-top: 1px solid var(--va-line); margin-top: 0.9rem; padding-top: 0.5rem; }
|
|
400
|
+
/* Shut by default, and the summary is the whole argument for the fold: a count a
|
|
401
|
+
reviewer can decide to open, rather than twenty-two rows they have to scroll. */
|
|
402
|
+
.va-findings-rest { margin-top: 1rem; }
|
|
403
|
+
.va-findings-rest > summary { color: var(--va-ink-2); cursor: pointer; font-size: 0.8rem; padding: 0.35rem 0; }
|
|
404
|
+
.va-findings-rest[open] > summary { color: var(--va-ink); }
|
|
405
|
+
.va-findings-rest > .va-note { margin-bottom: 0.7rem; }
|
|
406
|
+
.va-findings-band + .va-findings-band { margin-top: 0.9rem; }
|
|
407
|
+
.va-band-head { color: var(--va-ink-2); font-size: 0.72rem; font-weight: 700; letter-spacing: 0.09em; margin-bottom: 0.5rem; text-transform: uppercase; }
|
|
408
|
+
.va-findings { display: grid; gap: 0.7rem; }
|
|
409
|
+
.va-finding { border-left: 2px solid var(--va-line-firm); padding-left: 0.7rem; }
|
|
410
|
+
.va-finding-new { border-left-color: var(--va-warn); }
|
|
411
|
+
/* The headline is an item and the marks may wrap under it. Left as a bare text
|
|
412
|
+
node beside two flex-none badges it became an anonymous item with nothing
|
|
413
|
+
holding its width, and "a control inside another control" read down the rail
|
|
414
|
+
one word to a line. */
|
|
415
|
+
.va-finding-title { align-items: baseline; display: flex; flex-wrap: wrap; font-size: 0.88rem; font-weight: 650; gap: 0.5rem; justify-content: space-between; }
|
|
416
|
+
.va-finding-said { flex: 1 1 9rem; }
|
|
417
|
+
.va-finding-marks { align-items: baseline; display: flex; flex: none; gap: 0.45rem; }
|
|
418
|
+
.va-times { color: var(--va-accent); flex: none; font-family: var(--va-mono); font-size: 0.72rem; font-weight: 500; }
|
|
419
|
+
.va-age { border-radius: 5px; color: var(--va-ink-3); flex: none; font-size: 0.7rem; font-weight: 500; padding: 0.1rem 0.4rem; white-space: nowrap; }
|
|
420
|
+
.va-age-new { background: var(--va-warn-bg); color: var(--va-warn-ink); }
|
|
421
|
+
.va-age-standing, .va-age-undated { background: var(--va-info-bg); }
|
|
422
|
+
.va-finding-where { color: var(--va-ink-2); font-size: 0.8rem; }
|
|
423
|
+
.va-finding-what { color: var(--va-ink-2); font-size: 0.8rem; margin-top: 0.2rem; }
|
|
424
|
+
.va-finding-owner { align-items: center; display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.35rem; }
|
|
425
|
+
.va-tag { background: var(--va-surface); border: 1px solid var(--va-line); border-radius: 5px; color: var(--va-ink-2); font-size: 0.72rem; padding: 0.1rem 0.4rem; }
|
|
426
|
+
.va-tag.va-rule { color: var(--va-ink-3); }
|
|
427
|
+
|
|
428
|
+
/* The declaration ledgers. Every rule is a row, including the ones that absorbed
|
|
429
|
+
nothing — those are the finding, and a table that hid them would be a table of
|
|
430
|
+
rules that are working. The rule name is the widest column because it is the
|
|
431
|
+
thing a reader copies into their config; the reason is the widest prose. */
|
|
432
|
+
.va-ledger { margin-top: 0.5rem; }
|
|
433
|
+
.va-ledger code { font-size: 0.78rem; }
|
|
434
|
+
.va-ledger em { color: var(--va-ink-3); font-size: 0.72rem; font-style: normal; }
|
|
435
|
+
.va-ledger .va-none { color: var(--va-ink-3); }
|
|
436
|
+
.va-ledger .va-ledger-why { color: var(--va-ink-2); width: 38%; }
|
|
437
|
+
.va-ledger .va-tag { margin-right: 0.25rem; }
|
|
438
|
+
/* Marked on the row rather than only on the badge: a reviewer scanning for the
|
|
439
|
+
one rule that is wrong reads the left edge, not the third column. */
|
|
440
|
+
.va-ledger tr.va-spent td:first-child { border-left: 2px solid var(--va-warn); padding-left: 0.4rem; }
|
|
441
|
+
.va-tag.va-warn { background: var(--va-warn-bg); border-color: transparent; color: var(--va-warn-ink); }
|
|
442
|
+
.va-ledger-head { color: var(--va-ink-2); font-size: 0.8rem; font-weight: 650; margin-top: 0.9rem; }
|
|
443
|
+
.va-ledger-head .va-note { font-weight: 400; margin-left: 0.5rem; }
|
|
444
|
+
|
|
445
|
+
/* Folded, because on a run of three hundred stories this is three hundred lines
|
|
446
|
+
of nothing — and present, because a green subject that is green by declaration
|
|
447
|
+
is the one a mask hides behind. */
|
|
448
|
+
.va-settled > summary { color: var(--va-ink-2); cursor: pointer; font-size: 0.86rem; }
|
|
449
|
+
.va-settled-list { display: grid; gap: 0.3rem; margin-top: 0.6rem; }
|
|
450
|
+
.va-settled-list li { align-items: baseline; display: flex; font-size: 0.84rem; gap: 0.45rem; }
|
|
451
|
+
.va-settled-list strong { font-family: var(--va-mono); font-size: 0.78rem; font-weight: 500; }
|
|
452
|
+
|
|
453
|
+
.va-not-observed { color: var(--va-ink-2); display: grid; font-size: 0.86rem; gap: 0.35rem; }
|
|
454
|
+
.va-not-observed .va-failed { color: var(--va-bad); font-weight: 600; }
|
|
455
|
+
|
|
456
|
+
.va-decision { color: var(--va-good); font-size: 0.86rem; margin-bottom: 0.5rem; }
|
|
457
|
+
.va-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; }
|
|
458
|
+
.va-actions button { flex: 1; font-weight: 600; }
|
|
459
|
+
.va-actions .va-approve { background: var(--va-good); border-color: var(--va-good); color: #ffffff; }
|
|
460
|
+
.va-actions .va-approve:disabled { background: var(--va-sunken); border-color: var(--va-line-firm); color: var(--va-ink-3); }
|
|
461
|
+
|
|
462
|
+
@media (max-width: 60rem) {
|
|
463
|
+
.va-body { flex-wrap: wrap; }
|
|
464
|
+
.va-rail { border-right: 0; width: 100%; }
|
|
465
|
+
.va-subject { flex-wrap: wrap; }
|
|
466
|
+
.va-aside { border-left: 0; width: 100%; }
|
|
467
|
+
.va-reach .va-quad { grid-template-columns: minmax(0, 1fr); }
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/* Motion is never how anything here is said, so there is nothing to preserve when
|
|
471
|
+
a reader has asked for less of it. The blink and the scroll to a region are
|
|
472
|
+
turned off in the component that starts them, because neither is a CSS
|
|
473
|
+
animation this could reach; this catches the transitions. */
|
|
474
|
+
@media (prefers-reduced-motion: reduce) {
|
|
475
|
+
.va-app *, .va-app *::before, .va-app *::after { animation-duration: 1ms; animation-iteration-count: 1; scroll-behavior: auto; transition-duration: 1ms; }
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
@media (prefers-color-scheme: light) {
|
|
479
|
+
:root, .va-app { --va-bg: #f3f4f6; --va-surface: #ffffff; --va-sunken: #e9eaec; --va-line: #d8d6d3; --va-line-firm: #b8b3ae; --va-ink: #181b1d; --va-ink-2: #4c4844; --va-ink-3: #756d67; --va-accent: #d83a13; --va-accent-ink: #ffffff; --va-warn: #8a5a12; --va-warn-bg: #f7ecd9; --va-warn-ink: #5c3c08; --va-bad: #b03a2b; --va-bad-bg: #f8e3df; --va-bad-ink: #7a2418; --va-good: #46705a; --va-good-bg: #dfece4; --va-good-ink: #2b4a38; --va-info-bg: #ecebe9; --va-info-ink: #3d3935; --va-cause: #d83a13; --va-collateral: #756d67; --va-accent-soft: rgba(216, 58, 19, 0.10); --va-veil: rgba(243, 244, 246, 0.55); }
|
|
480
|
+
}
|
|
481
|
+
`;
|
|
482
|
+
//# sourceMappingURL=styles.js.map
|