Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit fdf1bcd119cd26343d4d69f5efa215dbb48ff919
parent 2f573c384410fcb536adc29ef8fb89e7eaea0764
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Mon, 28 Sep 2026 19:09:52 -0400

homepage: the growth chart's separators in the ground's foreground — dark on Light and Sepia, light on Dark

The line along each stratum's upper edge was the page background (1.25 px):
light on Light, dark on Dark. It is now `.growth-sep` (globals.css): the
ground's foreground at full strength, 1 px, and CanvasText in forced colours;
the gridlines are unchanged. Three strengths were built and screenshotted;
full strength is the only one that reaches 3:1 against any band, and at 1 px a
2–3 px stratum keeps its colour between two lines. Against some bands the
foreground stays under 3:1 (the record lists them per ground); the series
colours are unchanged. Homepage-only: the shared charts have no such separator.

growth-chart.spec: the separators are the foreground at full strength and 1 px,
never the background, on Light, Sepia and Dark, and CanvasText in forced
colours. The record, the plan and the homepage changelog.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Diffstat:
Mhomepage/CHANGELOG.md | 1+
Mhomepage/app/components/ArchiveGrowthChart.tsx | 16++++++++++++----
Mhomepage/app/globals.css | 15+++++++++++++++
Ahomepage/e2e/growth-chart.spec.ts | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mplans/export-header-first-search.md | 4++++
Mplans/release-14.md | 31++++++++++++++++++++++++++++++-
6 files changed, 117 insertions(+), 5 deletions(-)

diff --git a/homepage/CHANGELOG.md b/homepage/CHANGELOG.md @@ -6,6 +6,7 @@ - **One Options button in place of the two theme buttons.** The header's theme menu and base toggle are one gear, **Options**, which opens a dialog with **Base** (System, Light, Sepia, Dark) and **Accent** (the seven named accents, Signal tagged *default*) as radio lists. It opens on the ground in force; a choice applies at once and the dialog stays open; Escape, Close or a click outside closes it. - **Changelog is in the footer only.** The header's nav is Docs, Source, Downloads and Stats; the footer's Sections list and the 404 page keep Changelog. - **Each Official Instances card names its site with the site's wordmark.** The first part of the name is set heavy in the site's own accent and the rest light, as the site's own header sets it (Jer·alyzer, Hasan·alyzer, …), at the card title's size; the accent is fitted to the ground in force and reads above 4:1 on the card on Light, Sepia and Dark. A site with no configured lead, or a summary built before this, shows its title plain as before. `homepage-summary.json` gains an optional `wordmarkLead` per site (still version 5). +- **The growth chart's strata are parted by lines in the text colour.** The line along each stratum's upper edge was drawn in the page's background colour, so it was light on Light and dark on Dark; it is now a 1 px line in the ground's foreground (dark on Light and Sepia, light on Dark, the system's text colour in high-contrast mode). The gridlines are unchanged. - **Larger social links, with a focus ring.** Each icon, in the header and the footer, is a 36 px target around its 20 px glyph (44 px on a touch screen), in the muted text colour and the text colour on hover; the footer's were 20 px, in the faint colour, with no ring. Keyboard focus draws a 2 px ring in the accent, and in high-contrast mode the browser's own focus outline. An icon of two or more colours keeps its colours. - **The e2e no longer reads the checkout's `settings.json`.** Its dev server reads `e2e/.e2e-settings.json` (`SETTINGS_FILE`), written by `e2e/fixture-social.ts`: three synthetic icons (a gradient, one colour, and a two-colour disc pasted with only its size), put through the same check a save runs, and `SITES_DIR` points at an empty directory, so no `homepage.json` in the checkout can override them. `e2e/social.spec.ts` covers the header and the footer rows (and that a stored icon that would run script is shown as its label and never runs), `e2e/options.spec.ts` the Options dialog, and `e2e/instance-wordmark.spec.ts` the cards' names; specs change the theme through one helper, `chooseTheme` (`e2e/helpers.ts`). - **The source is on the site, with its history: `/source/`.** A new **Source** page (and nav entry) gives `git clone https://archilyzer.pages.dev/source/archilyzer.git`, a read-only mirror of the main branch regenerated with every deploy, with its head, the private commit it reflects, a link to browse every file raw at `/source/tree/`, and the tarball with its size and sha256. Commit ids differ from the private repository's, because machine paths are scrubbed on the way out, and the page says so. A build without a published source says "No source published in this build." instead of offering a clone. The Downloads tarball is now regenerated by every build (its commit is the mirror's), and the page points at the mirror for history. The docs that said there is no public repository (*Install*, the FAQ, *What is Archilyzer*) now say how to clone. Below `md` the header's nav drops to its own row, as it did below `sm`, because five labels no longer fit beside the wordmark. `_headers` serves the raw tree as plain text. diff --git a/homepage/app/components/ArchiveGrowthChart.tsx b/homepage/app/components/ArchiveGrowthChart.tsx @@ -180,15 +180,23 @@ export function ArchiveGrowthChart({ {layers.map((l) => ( <path key={l.site.siteId} d={l.area} fill={l.color} /> ))} - {/* The surface gap: each layer's upper edge is drawn in the page - colour, so touching strata separate by negative space. */} + {/* The separators: each layer's upper edge is a 1 px hairline in + the ground's FOREGROUND (the page text's colour) at full + strength — dark on Light and Sepia, light on Dark. Colour and + width are `.growth-sep` in globals.css (CanvasText in forced + colours), so they follow the theme with no script. Full + strength because only it reaches 3:1 against any band (60 % + and 35 % reach it against none); 1 px, not the 1.25 px the + old page-coloured gap was, so a 2–3 px stratum keeps its + colour between two lines. Against some bands even the + foreground stays under 3:1 (Light: violet, rust; Sepia: + green, violet, magenta, rust; Dark: green, violet, amber). */} {layers.map((l) => ( <path key={`${l.site.siteId}-edge`} d={l.edge} + className="growth-sep" fill="none" - stroke="var(--background)" - strokeWidth={1.25} strokeLinejoin="round" vectorEffect="non-scaling-stroke" /> diff --git a/homepage/app/globals.css b/homepage/app/globals.css @@ -105,3 +105,18 @@ body { .growth-hit:hover { fill: var(--chart-grid); } + +/* The growth chart's separators: each stratum's upper edge, a 1 px line in + the ground's foreground at full strength — dark on Light and Sepia, light on + Dark (ArchiveGrowthChart.tsx says why this strength). */ +.growth-sep { + stroke: var(--foreground); + stroke-opacity: 1; + stroke-width: 1px; +} +@media (forced-colors: active) { + .growth-sep { + stroke: CanvasText; + stroke-opacity: 1; + } +} diff --git a/homepage/e2e/growth-chart.spec.ts b/homepage/e2e/growth-chart.spec.ts @@ -0,0 +1,55 @@ +import { test, expect, type Page } from "@playwright/test"; + +// The growth chart's separators — each stratum's upper edge — are the ground's +// FOREGROUND at full strength, 1 px: dark on Light and Sepia, light on Dark +// (ArchiveGrowthChart.tsx, globals.css `.growth-sep`), and CanvasText in forced +// colours. The fixture summary (fixture-summary.ts) has six sites with monthly +// data, so the chart and its six separators render. + +const BASE_KEY = "ytdlp-tb:base"; + +const resolveColor = (page: Page, css: string) => + page.evaluate((c) => { + const el = document.createElement("span"); + el.style.color = c; + document.body.append(el); + const out = getComputedStyle(el).color; + el.remove(); + return out; + }, css); + +const separators = (page: Page) => + page.locator("figure svg path.growth-sep").evaluateAll((els) => + els.map((el) => { + const s = getComputedStyle(el); + return { stroke: s.stroke, opacity: s.strokeOpacity, width: s.strokeWidth }; + }), + ); + +test("the separators are the ground's foreground at full strength, never the page background", async ({ + page, +}) => { + await page.goto("/"); + for (const base of ["light", "sepia", "dark"] as const) { + await page.evaluate(([k, v]) => localStorage.setItem(k, v), [BASE_KEY, base]); + await page.reload(); + await expect(page.locator("html")).toHaveAttribute("data-base", base); + const fg = await resolveColor(page, "var(--foreground)"); + const bg = await resolveColor(page, "var(--background)"); + expect(fg).not.toBe(bg); + const seps = await separators(page); + expect(seps.length, base).toBeGreaterThan(0); + for (const s of seps) { + expect(s, base).toEqual({ stroke: fg, opacity: "1", width: "1px" }); + } + } +}); + +test("in forced colours the separators are CanvasText", async ({ page }) => { + await page.emulateMedia({ forcedColors: "active" }); + await page.goto("/"); + const canvasText = await resolveColor(page, "CanvasText"); + const seps = await separators(page); + expect(seps.length).toBeGreaterThan(0); + for (const s of seps) expect(s.stroke).toBe(canvasText); +}); diff --git a/plans/export-header-first-search.md b/plans/export-header-first-search.md @@ -33,6 +33,7 @@ main...<branch>` is empty for the search and header components on all five). social icons' rhythm, and the narrow header carries the icons and the gear in its bar; on Official Instances each site's name uses the bold-lead effect of the sites' own headings, with a slight tint or underline in the site's accent. +- 2026-09-28, on the homepage chart: light mode has dark lines and dark mode has light lines. - Standing: **no copy** beside any social link: icons with accessible names only. ## Decisions and assumptions @@ -197,6 +198,9 @@ shipped". What it built, so H1 does not re-derive it: 7. **The Official Instances cards** set each site's title with the shared `Wordmark` when the summary carries its `wordmarkLead` (new, optional, still v5), the lead tinted in the site's own accent (`siteAccentColor`). The hub's cards are not touched. +8. **The homepage's growth chart** parts its strata with 1 px lines in the ground's foreground + (`.growth-sep`; `CanvasText` in forced colours), no longer the page background. Homepage-only: + the shared charts have no such separator. ## Slice H3 — the homepage's instances anchor (branch `r14/home-anchor`) diff --git a/plans/release-14.md b/plans/release-14.md @@ -42,6 +42,7 @@ branch: with a slight tint or underline in the site's accent colour. 5. (The review, ruled by the parent.) No vendor file in the repository; the icon check hardened on save and at render; the shared dialog wrapper unchanged. +6. On the homepage chart, light mode has dark lines and dark mode has light lines. **The branch's history was rewritten once** (after the review, ruling 5): its first nine commits, one of which added a vendor file as a test fixture, were replaced by the five commits below, @@ -186,6 +187,33 @@ leads (Jer, Hasan, Ani, Bonnell, Rekieta, Jaso) and their named accents; the num - **The swap**, if asked: replace `{ color: accent }` in `ArchiveCards`' `SiteName` with a 2 px accent `text-decoration` on the lead. It is one line. +**The chart's separators** (ruling 6; after the review, a new commit on top). The line along each +stratum's upper edge in `homepage/app/components/ArchiveGrowthChart.tsx` was the page background +(`var(--background)`, 1.25 px): light on Light, dark on Dark. It is now `.growth-sep` in +`homepage/app/globals.css`: `var(--foreground)`, full strength, 1 px, and `CanvasText` in forced +colours. The gridlines are unchanged. +- **Three strengths built and screenshotted** (the foreground at 100 %, 60 % and 35 %, 1 px; the + chart at 1280 and 390 px and a 4× close-up of the thin strata, on the three grounds; the + published summary): `~/reports/release-14/shots/chart/sep-{100,60,35}-…`. +- **Shipped: 100 %.** Only full strength reaches 3:1 against any band; 60 % reaches it against + none (at best 2.69:1) and 35 % against none (1.81:1). At 1 px, a 2–3 px stratum keeps a coloured + stripe between its two lines in the close-ups; the old gap was 1.25 px. +- **Against the six bands, measured on the page** (the separator against each band's rendered + colour): + - Light: blue 4.25, amber 4.24, green 4.00, magenta 3.80, violet 2.17, rust 2.13 — minimum + **2.13**; + - Sepia: amber 3.55, blue 3.17, magenta 2.95, green 2.84, violet 1.81, rust 1.78 — minimum + **1.78**; + - Dark: rust 4.77, blue 4.63, magenta 3.64, violet 2.63, amber 2.54, green 2.49 — minimum + **2.49**. + With the ground's foreground, 3:1 is out of reach against those bands: Light violet and rust; + Sepia green, magenta, violet and rust; Dark green, violet and amber. The series colours are + unchanged, as ruled for this commit. +- **Homepage-only.** The separator is in the homepage's own chart. The shared charts + (`common/components/charts/`, the homepage's `/stats`, the export sites and the hub) draw each + series' edge in its own colour and have no page-coloured separator. Whether they take a + foreground separator is left for the operator to rule on. + **Beyond the prompt.** - **Icon ids are scoped per copy (`scopeSvgIds`).** An id resolves to the first element carrying it, and a gradient defined inside a `display: none` copy does not paint. The first build rendered @@ -232,7 +260,8 @@ operator's pasted icons do): | `4d93dc84` | `common:` `SocialLinks`, `OptionsDialog` (its own border and Close, focus on the checked radio), `ThemeRadios`; `export:` `MobileMenu` renders `ThemeRadios`, the footer inlines only through `safeSocialSvg` | | `6c500818` | `homepage:` the social row and the gear in the header at every width, the width × pointer rule; Changelog in the footer only; the e2e's own settings and sites; `social`, `options`, nav and theme specs | | `88d61908` | `homepage:` the cards' names as the site's wordmark, the lead tinted; `wordmarkLead` in the summary and its check on read; `siteAccentColor`; `Wordmark` `leadStyle`; `instance-wordmark.spec.ts` | -| _this_ | `plans:` this record; the plan's slice HP, H1 and H2; STATE; the changelogs | +| `afc642fd` | `plans:` this record; the plan's slice HP, H1 and H2; STATE; the changelogs | +| _this_ | `homepage:` the growth chart's separators in the ground's foreground, 1 px, full strength (ruling 6); `growth-chart.spec.ts`; the record, the plan, the changelog | **Gates** (at `88d61908`; logs `$T/hp5-*.log`): - **tsc** was clean at each of the five commits (the rewrite ran it on each commit's own tree: