diff --git a/scripts/a11y-routes.mjs b/scripts/a11y-routes.mjs new file mode 100644 index 0000000..4c4f790 --- /dev/null +++ b/scripts/a11y-routes.mjs @@ -0,0 +1,23 @@ +import site from '../site.config.json' with { type: 'json' }; + +/** + * Which routes the Lighthouse gate audits. + * + * Derived from site.config.json rather than typed out, because a hand-kept copy + * of the route inventory drifts: /code-signing-policy had to be added in a + * follow-up commit, and /helper shipped with no audit at all. Adding a page to + * the inventory now adds it to the audit, which is the only behaviour that + * cannot fall behind. + */ + +/** In the inventory, but not an HTML page a Lighthouse run means anything for. */ +const NOT_A_PAGE = new Set(['/rss.xml']); + +/** + * Routes built from a template, where auditing every instance would audit the + * same markup over and over. One stands for the family: the accessibility of + * the 104th post is the accessibility of the first. + */ +const TEMPLATE_REPRESENTATIVES = ['/blog/the-tool-goes-to-the-data', '/blog/engine/postgresql']; + +export const a11yRoutes = [...site.routes.filter((route) => !NOT_A_PAGE.has(route)), ...TEMPLATE_REPRESENTATIVES]; diff --git a/scripts/lighthouse-gate.mjs b/scripts/lighthouse-gate.mjs index e2acf6e..d76886a 100644 --- a/scripts/lighthouse-gate.mjs +++ b/scripts/lighthouse-gate.mjs @@ -23,6 +23,7 @@ import { existsSync, statSync } from 'node:fs'; import { extname, join, resolve as resolvePath, sep } from 'node:path'; import { launch } from 'chrome-launcher'; import lighthouse from 'lighthouse'; +import { a11yRoutes } from './a11y-routes.mjs'; const args = process.argv.slice(2); const flag = (name, fallback) => { @@ -32,37 +33,7 @@ const flag = (name, fallback) => { const MIN = Number(flag('min', 95)); const DIST = 'dist'; -const ROUTES = args.includes('--route') - ? args.filter((a, i) => args[i - 1] === '--route') - : [ - '/', - '/blog', - '/blog/the-tool-goes-to-the-data', - // The engine archives are one template over seventeen routes, so one - // stands for all of them the way the post above stands for 104. - '/blog/engine/postgresql', - '/faq', - '/get-started', - // Every standalone content page is audited. /playground earns its slot - // twice over: it is the only route with an interactive surface built by - // script at runtime, so it is the one axe-core findings can appear on - // without anyone touching a template. - '/playground', - '/databases', - '/features', - '/open-source', - '/supporters', - '/deploy', - '/docker-compose', - '/libredb-database', - '/security', - '/code-signing-policy', - '/helper', - '/support', - '/platform', - '/compare', - '/privacy-policy', - ]; +const ROUTES = args.includes('--route') ? args.filter((a, i) => args[i - 1] === '--route') : a11yRoutes; if (!existsSync(join(DIST, 'index.html'))) { console.error(`No ${DIST}/index.html — run \`bun run build\` first.`); diff --git a/src/components/home/FlowBand.astro b/src/components/home/FlowBand.astro index cedfee0..b8328d4 100644 --- a/src/components/home/FlowBand.astro +++ b/src/components/home/FlowBand.astro @@ -164,9 +164,15 @@ const modes = ['out', 'in'] as const; } /* "Tool → data" is the working direction: green wire, Studio lands, specs light */ - .flow__card[data-switch-active='in'] .diag__line { - background-image: repeating-linear-gradient(90deg, var(--success-text) 0 5px, transparent 5px 10px); - animation-name: lbDashXR; + .flow__card[data-switch-active='in'] .diag { + --diag-dash-color: var(--success-text); + } + /* Running the dashes backwards is a horizontal idea. Below 560px the wire is + drawn top-to-bottom, so it keeps the shared vertical animation instead. */ + @media (min-width: 561px) { + .flow__card[data-switch-active='in'] .diag { + --diag-dash-anim: lbDashXR; + } } .flow__card[data-switch-active='in'] .diag__chip { color: var(--success-text); @@ -180,15 +186,6 @@ const modes = ['out', 'in'] as const; color: var(--success-text); } - /* The stacked layout turns the wire vertical, but the rule above is what sets - this state's animation and it outranks the one in diagram.css, so the axis - has to be restated here or the green wire stops moving. */ - @media (max-width: 560px) { - .flow__card[data-switch-active='in'] .diag__line { - background-image: repeating-linear-gradient(180deg, var(--success-text) 0 5px, transparent 5px 10px); - animation-name: lbDashY; - } - } .flow__card[data-switch-active='in'] .flow__spec { color: var(--text-brand); border-color: var(--primary-600); diff --git a/src/components/home/WhySection.astro b/src/components/home/WhySection.astro index 35653a4..678e34f 100644 --- a/src/components/home/WhySection.astro +++ b/src/components/home/WhySection.astro @@ -163,8 +163,8 @@ import { why } from '../../data/home'; } /* step 04 is the one that works: the wire turns green and Studio lands */ - .why__card[data-switch-active='3'] .diag__line { - background-image: repeating-linear-gradient(90deg, var(--success-text) 0 5px, transparent 5px 10px); + .why__card[data-switch-active='3'] .diag { + --diag-dash-color: var(--success-text); } .why__card[data-switch-active='3'] .diag__chip { color: var(--success-text); @@ -178,12 +178,6 @@ import { why } from '../../data/home'; color: var(--success-text); } - @media (max-width: 560px) { - .why__card[data-switch-active='3'] .diag__line { - background-image: repeating-linear-gradient(180deg, var(--success-text) 0 5px, transparent 5px 10px); - } - } - .why__status { font: var(--weight-regular) 11.5px / 1.5 var(--font-mono); color: var(--text-tertiary); diff --git a/src/styles/diagram.css b/src/styles/diagram.css index 25204b7..659d4b6 100644 --- a/src/styles/diagram.css +++ b/src/styles/diagram.css @@ -4,7 +4,14 @@ arrangement, so the base rules live here; each section keeps only its own state overrides in its scoped