diff --git a/.agents/PAPERCUTS.md b/.agents/PAPERCUTS.md index 2f9c5d9..a17704f 100644 --- a/.agents/PAPERCUTS.md +++ b/.agents/PAPERCUTS.md @@ -6,10 +6,15 @@ This is not a completed-work log or a bug tracker. Never include secrets, creden ## Open +- [ ] `2026-07-11T21:38:29Z` — `codex` — While visually testing the BadSEO design lab, a stale local process still held the configured port 8787, so Vite silently moved the app to 8788. Make the active preview URL more visible in the normal workflow or provide a reliable task-local server cleanup step. +- [ ] `2026-07-10T21:32:49Z` — `codex` — While starting the BadSEO TanStack/Cloudflare dev server in a sandbox, the Cloudflare Vite plugin failed with `listen EPERM` while probing its inspector port, even though the app port was otherwise valid. Document the need for elevated local port binding or provide an inspector-disabled validation command. +- [ ] `2026-07-10T21:28:46Z` — `codex` — While validating the standalone BadSEO package after merging its TanStack migration, `pnpm --dir badseo run typecheck` appeared to work through the root toolchain but `pnpm --dir badseo run build` could not find Vite because `badseo/node_modules` was absent. Document or enforce the required package-local install before validation. - [ ] `2026-07-10T22:32:40Z` — `codex` — While running the badseo audit from the workspace, sandboxed TSX failed with `listen EPERM` when creating its IPC socket under the temporary directory. Rerunning the same audit with local IPC permission succeeded; provide a sandbox-compatible TSX invocation for validation scripts. - [ ] `2026-07-10T22:23:50Z` — `codex` — While pushing the consent-banner refinement to PR #380, the SSH push hung without output and a separate remote verification hung as well; retrying the same push succeeded immediately. Surface an actionable SSH timeout or connection error instead of waiting indefinitely. - [ ] `2026-07-10T21:36:27Z` — `codex` — While using the repository's `webapp-testing` skill, its required Python Playwright import was unavailable in both system and bundled Python. The bundled Node Playwright runtime completed the check; document or provide that fallback, including Cloudflare Vite's default port 8787 rather than Vite's usual 5173. - [ ] `2026-07-10T21:32:10Z` — `codex` — While formatting the standalone `badseo` workspace, `pnpm exec prettier` failed because Prettier is only available from the repository root. Document the root-only formatter command or expose a workspace-local formatting script. +- [ ] `2026-07-11T15:13:43Z` — `codex` — While inspecting a BadSEO merge with login-shell commands, zsh printed `(eval):5: parse error near \`end'` before otherwise successful Git output. Running the same commands with login-shell initialization disabled avoided the noise; identify and fix the malformed shell startup hook. +- [ ] `2026-07-11T15:15:13Z` — `codex` — While resolving a merge from the sandboxed BadSEO subdirectory, `git add` could not create the parent worktree's `index.lock` despite the merge itself being allowed. Staging required the approved elevated Git path; align the workspace write boundary with the actual Git worktree root. - [ ] `2026-07-10T21:09:27Z` — `codex` — While building the TanStack/Cloudflare badseo app, Wrangler reported an EPERM writing its debug log under the user preferences directory even though the build succeeded. Set `WRANGLER_LOG_PATH` to a writable temporary path in sandboxed build commands or make the logging failure non-fatal and quiet. - [ ] `2026-07-10T17:53:20Z` — `codex` — While validating `.greptile/`, both `pnpm exec prettier --check` and the existing `pnpm format:check` attempted to reconcile `node_modules` and aborted because no TTY was available. Calling `node_modules/.bin/prettier` performed the non-installing check successfully; the agent/CI path needs a stable way to run package scripts without an interactive modules purge. - [ ] `2026-07-10T18:12:35Z` — `codex` — While validating referenced files in zsh, using `path` as a loop variable overwrote zsh's special `path` array and made commands such as `git`, `jq`, and `sed` appear missing later in the same shell. Use a neutral name such as `file_path` in shell loops. diff --git a/badseo/README.md b/badseo/README.md index 70e136a..e9aaff7 100644 --- a/badseo/README.md +++ b/badseo/README.md @@ -32,14 +32,14 @@ Every issue type in the OpenSEO audit engine is exercised by at least one page | **Site structure** | orphan page, deep click-path | | **Kitchen sink** | one page that breaks six ways at once | -Browse them all at `/catalog`. +Browse them all on the homepage at `/#issues`. ## How it's built badseo.dev is a TanStack Start app deployed to a Cloudflare Worker, following the same Vite and Cloudflare setup as the repository's `web/` app. -TanStack React routes render the healthy homepage, catalog, and privacy policy. +TanStack React routes render the healthy homepage and privacy policy. A TanStack catch-all server route keeps the deliberate fixtures as raw responses with byte-level control over status codes, redirects, headers (`X-Robots-Tag`, `Link: …; rel=canonical`), timing, and the malformed `` @@ -76,7 +76,7 @@ npm run dev # serves on http://localhost:8787 The harness drives the **real** OpenSEO crawl + issue-detection functions (imported straight from `../src`) against a running badseo.dev, then asserts every fixture triggers exactly the issues it declares — and that the homepage, -catalog, privacy policy, and support pages come back clean. +privacy policy, and support pages come back clean. ```bash # with `npm run dev` running in another terminal: diff --git a/badseo/public/styles.css b/badseo/public/styles.css index 393b114..3c33de0 100644 --- a/badseo/public/styles.css +++ b/badseo/public/styles.css @@ -1,417 +1,152 @@ :root { - --canvas: #f5f1ec; - --surface: #ffffff; - --surface-2: #ebe7e1; - --ink: #111111; - --ink-muted: #626260; - --ink-subtle: #7b7b78; - --hairline: #d8d1c8; - --hairline-soft: #ebe7e1; - --orange: #ff5600; - --footer-bg: #eee8de; - --critical: #d23b1f; - --warning: #b26a00; - --info: #6b7280; - --mono: - "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; - --sans: - Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, - "Segoe UI", sans-serif; + color-scheme: light; + --navy: #0c1b3a; + --blue: #1745d1; + --paper: #e7ecf4; + --paper-deep: #d9e1ef; + --surface: #f7f9fc; + --line: #93a5c8; + --line-soft: #bdc8da; + --muted: #526584; + --critical: #d94040; + --warning: #cf7d18; + --info: #6f82a5; + --mono: "IBM Plex Mono", monospace; + --sans: "IBM Plex Sans", sans-serif; + --serif: "Newsreader", Georgia, serif; + --condensed: "Archivo Narrow", sans-serif; } -* { - box-sizing: border-box; -} -html { - -webkit-text-size-adjust: 100%; -} +* { box-sizing: border-box; } +html { min-height: 100%; background: var(--paper); scroll-behavior: smooth; -webkit-text-size-adjust: 100%; } +body { min-height: 100%; margin: 0; background: var(--paper); color: var(--navy); font-family: var(--sans); font-size: 16px; line-height: 1.55; -webkit-font-smoothing: antialiased; } +button, input { font: inherit; } +a { color: inherit; text-underline-offset: 4px; } +a:focus-visible, button:focus-visible { outline: 3px solid #ff6a57; outline-offset: 3px; } -body { - margin: 0; - background: var(--canvas); - color: var(--ink); - font-family: var(--sans); - font-size: 16px; - line-height: 1.5; - -webkit-font-smoothing: antialiased; - text-rendering: optimizeLegibility; -} - -a { - color: var(--ink); - text-decoration: none; -} -a:hover { - text-decoration: underline; - text-underline-offset: 3px; -} - -.wrap, -.main, -.panel, -.nav, -.foot-inner { - max-width: 820px; - margin: 0 auto; - padding-left: 24px; - padding-right: 24px; -} - -/* ── nav ── */ -.nav { - display: flex; - align-items: center; - gap: 20px; - padding-top: 20px; - padding-bottom: 20px; -} -.brand { - font-weight: 600; - letter-spacing: -0.01em; - color: var(--ink); - font-size: 17px; -} -.brand:hover { - text-decoration: none; -} -.nav-link { - color: var(--ink-muted); - font-weight: 500; - margin-left: auto; - font-size: 15px; -} -.nav-link:hover { - color: var(--ink); -} - -/* ── content ── */ -.main { - padding-top: 8px; - padding-bottom: 48px; -} -.main h1 { - font-size: clamp(30px, 4.6vw, 46px); - font-weight: 500; - line-height: 1.1; - letter-spacing: -0.025em; - margin: 12px 0 18px; - text-wrap: balance; -} -.main h2 { - font-size: 24px; - font-weight: 500; - letter-spacing: -0.017em; - margin: 40px 0 12px; -} -.main h3 { - font-size: 19px; - font-weight: 500; - margin: 26px 0 8px; -} -.main h4 { - font-size: 16px; - font-weight: 600; - margin: 20px 0 6px; -} -.main p { - color: #2c2c2b; - margin: 0 0 16px; -} -.lede { - font-size: 19px; - line-height: 1.45; - letter-spacing: -0.006em; - color: var(--ink); -} -.main a { - color: var(--ink); - text-decoration: underline; - text-decoration-color: var(--hairline); - text-underline-offset: 3px; -} -.main a:hover { - text-decoration-color: var(--ink); -} -.main img { - max-width: 100%; - border-radius: 10px; - border: 1px solid var(--hairline); - display: block; - margin: 20px 0; - background: var(--surface); -} -.main code { - font-family: var(--mono); - font-size: 13.5px; - background: var(--surface-2); - padding: 2px 6px; - border-radius: 5px; -} -.main ul, -.main ol { - color: #2c2c2b; - padding-left: 20px; -} -.main li { - margin: 4px 0; -} -.next { - margin-top: 8px; -} -.next a { - font-weight: 500; -} - -/* ── test panel ── */ -.panel { - margin-top: 8px; - margin-bottom: 32px; - background: var(--surface); - border: 1px solid var(--hairline); - border-radius: 12px; - padding: 18px 20px; -} -.panel-head { - display: flex; - align-items: baseline; - gap: 10px; - flex-wrap: wrap; -} -.panel-kicker { - text-transform: uppercase; - letter-spacing: 0.08em; - font-size: 11px; - font-weight: 600; - color: var(--ink-subtle); -} -.panel-cat { - margin-left: auto; - font-size: 12px; - color: var(--ink-subtle); - font-family: var(--mono); -} -.panel-summary { - margin: 10px 0 0; - font-size: 15px; - color: var(--ink); -} -.panel-lesson { - margin: 6px 0 0; - font-size: 14px; - color: var(--ink-muted); -} -.panel-chips { - margin-top: 14px; - display: flex; - flex-wrap: wrap; - gap: 8px; - align-items: center; -} -.chips-label { - font-size: 12px; - color: var(--ink-subtle); - font-weight: 500; - margin-right: 2px; -} - -.chip { - display: inline-flex; - align-items: center; - gap: 7px; - font-size: 12.5px; - font-weight: 500; - color: var(--ink); - padding: 3px 11px 3px 9px; - border-radius: 999px; - background: var(--canvas); - border: 1px solid var(--hairline); -} -.chip::before { - content: ""; - width: 7px; - height: 7px; - border-radius: 50%; - flex: none; - background: var(--info); -} -.chip-critical::before { - background: var(--critical); -} -.chip-warning::before { - background: var(--warning); -} -.chip-info::before { - background: var(--info); -} -.chip-clean { - color: var(--ink-muted); -} -.chip-clean::before { - background: #3a9d5d; -} - -/* ── hero + home bits ── */ -.hero { - padding: 20px 0 4px; -} -.stat-row { - display: flex; - gap: 40px; - flex-wrap: wrap; - margin: 26px 0 8px; -} -.stat b { - font-size: 30px; - font-weight: 500; - letter-spacing: -0.02em; - display: block; - line-height: 1.1; -} -.stat span { - color: var(--ink-muted); - font-size: 14px; -} -.callout { - background: var(--surface); - border: 1px solid var(--hairline); - border-radius: 12px; - padding: 16px 18px; - margin: 24px 0; -} -.callout p { - margin: 0; - color: #2c2c2b; -} - -/* ── catalog index (no cards) ── */ -.index-group { - margin: 40px 0; -} -.index-group > h2 { - margin-bottom: 4px; -} -.index-list { - margin-top: 8px; - border-top: 1px solid var(--hairline); -} -.index-list .index-row { - display: grid; - grid-template-columns: minmax(160px, 240px) 1fr auto; - gap: 20px; - align-items: baseline; - padding: 14px 12px; - margin: 0 -12px; - border-radius: 8px; - border-bottom: 1px solid var(--hairline); - color: var(--ink); - text-decoration: none; -} -.index-list .index-row:hover { - background: var(--surface-2); - border-bottom-color: transparent; -} -.index-list .index-row:hover .row-name { - text-decoration: underline; - text-decoration-color: var(--ink); - text-underline-offset: 3px; -} -.row-name { - font-weight: 500; -} -.row-sum { - color: var(--ink-muted); - font-size: 14.5px; -} -.row-sev { - display: inline-flex; - gap: 5px; - align-items: center; - padding-top: 4px; -} -.dot { - width: 8px; - height: 8px; - border-radius: 50%; - display: inline-block; - flex: none; -} -.dot-critical { - background: var(--critical); -} -.dot-warning { - background: var(--warning); -} -.dot-info { - background: var(--info); -} -.legend { - display: inline-flex; - gap: 14px; - flex-wrap: wrap; - align-items: center; - color: var(--ink-muted); - font-size: 14px; -} -.legend span { - display: inline-flex; - gap: 6px; - align-items: center; -} -@media (max-width: 640px) { - .index-row { - grid-template-columns: 1fr auto; - } - .row-sum { - grid-column: 1 / -1; - } -} - -/* ── footer + OpenSEO badge ── */ -/* The band fills to the bottom of the page (no body padding beneath it). Extra - bottom padding keeps the footer text clear of the fixed badge, which floats - in the empty band space below the row. */ -.foot { - background: var(--footer-bg); - border-top: 1px solid var(--hairline); - margin-top: 64px; -} -.foot-inner { - padding: 26px 24px 76px; - color: var(--ink-muted); - font-size: 14px; +/* Shared site chrome. No headings or images are introduced here, keeping the + fixture pages' audit signals entirely under fixture control. */ +.site-header, .nav { display: flex; + min-height: 92px; + align-items: end; justify-content: space-between; - gap: 8px 24px; - flex-wrap: wrap; + gap: 28px; + padding: 31px 3.5vw 19px; + border-bottom: 1px solid var(--line); } -.foot-inner a { - color: var(--ink-muted); +.site-brand, .brand { color: var(--navy); font-family: var(--condensed); font-size: 18px; font-weight: 700; letter-spacing: .03em; text-decoration: none; } +.site-header nav, .nav-links { display: flex; align-items: center; gap: 27px; } +.site-header nav a, .nav-links a { color: var(--navy); font-family: var(--mono); font-size: 8px; } + +/* Homepage */ +.home-main { width: min(980px, calc(100% - 64px)); margin: 0 auto; padding-bottom: 80px; } +.home-hero { padding: clamp(70px, 8vw, 112px) 0 clamp(64px, 8vw, 96px); } +.home-copy h1 { margin: 0; font-family: var(--condensed); font-size: clamp(112px, 10vw, 136px); font-weight: 700; letter-spacing: -.055em; line-height: .72; } +.home-copy > p { max-width: 860px; margin: 42px 0 0; font-family: var(--serif); font-size: clamp(28px, 2.2vw, 32px); line-height: 1.08; } +.home-issues { scroll-margin-top: 24px; border-top: 3px solid var(--navy); } +.home-issue-group { margin: 22px 0 54px; } +.home-issue-group h3 { margin: 0; padding: 18px 0 14px; border-bottom: 1px solid var(--line); font-family: var(--condensed); font-size: 30px; line-height: 1; } +.home-case-head, .home-case-row { display: grid; grid-template-columns: minmax(220px, .72fr) minmax(320px, 1.28fr); gap: clamp(30px, 6vw, 90px); } +.home-case-head { padding: 11px 0; border-bottom: 1px solid var(--line-soft); color: var(--muted); font-family: var(--mono); font-size: 8px; } +.home-case-row { min-height: 72px; align-items: center; padding: 16px 0; border-bottom: 1px solid var(--line-soft); text-decoration: none; } +.home-case-row:hover .home-case-name { color: var(--blue); text-decoration: underline; text-underline-offset: 4px; } +.home-case-name { font-family: var(--serif); font-size: 19px; line-height: 1.15; } +.home-case-summary { color: var(--muted); font-size: 13px; line-height: 1.5; } +.home-case-row:hover .home-case-summary { color: var(--navy); } + +/* Catalog and fixture pages: deliberately restrained versions of the same + system so the content and injected SEO issue stay central. */ +.main { width: min(920px, calc(100% - 48px)); margin: 0 auto; padding: 62px 0 72px; } +.main h1 { margin: 0 0 18px; font-family: var(--condensed); font-size: clamp(52px, 8vw, 82px); font-weight: 700; letter-spacing: -.035em; line-height: .93; text-wrap: balance; } +.main h2 { margin: 48px 0 13px; font-family: var(--condensed); font-size: 34px; line-height: 1; } +.main h3 { margin: 30px 0 9px; font-family: var(--condensed); font-size: 24px; } +.main h4 { margin: 24px 0 7px; font-family: var(--mono); font-size: 13px; text-transform: uppercase; } +.main p { margin: 0 0 17px; color: #263b5e; } +.main .lede { max-width: 800px; margin-bottom: 28px; color: var(--navy); font-family: var(--serif); font-size: 25px; line-height: 1.32; } +.main a { color: var(--blue); } +.main code { padding: 2px 5px; background: #d4deed; font-family: var(--mono); font-size: 13px; } +.main ul, .main ol { padding-left: 22px; color: #263b5e; } +.main li { margin: 5px 0; } +.main img { display: block; max-width: 100%; margin: 26px 0; border: 1px solid var(--line); background: var(--surface); } +.next { margin-top: 12px; } + +.panel { width: min(920px, calc(100% - 48px)); margin: 38px auto 0; padding: 20px 22px; border: 1px solid var(--line); border-top: 3px solid var(--navy); background: rgb(247 249 252 / 70%); } +.panel-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; } +.panel-kicker { color: var(--navy); font-family: var(--mono); font-size: 9px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; } +.panel-cat { margin-left: auto; color: var(--muted); font-family: var(--mono); font-size: 9px; } +.panel-summary { margin: 12px 0 0; color: var(--navy); font-family: var(--serif); font-size: 20px; } +.panel-lesson { margin: 8px 0 0; color: var(--muted); font-size: 14px; } +.panel-chips { display: flex; flex-wrap: wrap; gap: 7px; align-items: center; margin-top: 16px; } +.chips-label { margin-right: 3px; color: var(--muted); font-family: var(--mono); font-size: 9px; text-transform: uppercase; } +.chip { display: inline-flex; align-items: center; gap: 7px; padding: 4px 9px; border: 1px solid var(--line-soft); background: var(--paper); font-family: var(--mono); font-size: 10px; } +.chip::before { width: 7px; height: 7px; border-radius: 50%; background: var(--info); content: ""; } +.chip-critical::before { background: var(--critical); }.chip-warning::before { background: var(--warning); }.chip-info::before { background: var(--info); }.chip-clean::before { background: #24845a; } + +.legend { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; color: var(--muted); font-family: var(--mono); font-size: 10px; } +.legend span { display: inline-flex; gap: 6px; align-items: center; } +.dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--info); } +.dot-critical { background: var(--critical); }.dot-warning { background: var(--warning); }.dot-info { background: var(--info); } +.index-group { margin: 52px 0; } +.index-group > h2 { margin-bottom: 12px; } +.index-list { border-top: 1px solid var(--line); } +.index-row { display: grid; grid-template-columns: minmax(190px, .75fr) 1.4fr auto; gap: 24px; align-items: baseline; min-height: 76px; padding: 18px 12px; margin: 0 -12px; border-bottom: 1px solid var(--line); color: var(--navy) !important; text-decoration: none; transition: background 150ms ease, color 150ms ease; } +.index-row:hover { background: var(--blue); color: #fff !important; } +.row-name { font-family: var(--serif); font-size: 19px; line-height: 1.1; } +.row-sum { color: var(--muted); font-size: 13px; } +.index-row:hover .row-sum { color: rgb(255 255 255 / 75%); } +.row-sev { display: inline-flex; gap: 5px; align-items: center; } + +.foot { margin-top: 36px; border-top: 1px solid var(--line); background: #dce4f0; } +.foot-inner { display: flex; width: min(1700px, 100%); min-height: 110px; align-items: center; justify-content: space-between; gap: 16px 32px; margin: 0 auto; padding: 30px 3.5vw; color: var(--muted); font-family: var(--mono); font-size: 9px; } +.foot-brand { color: var(--navy); font-family: var(--condensed); font-size: 18px; font-weight: 700; letter-spacing: .03em; text-decoration: none; } +.foot-links { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; margin-left: auto; } + +@media (max-width: 1100px) { + .home-case-head, .home-case-row { grid-template-columns: minmax(190px, .75fr) minmax(280px, 1.25fr); gap: 32px; } } -.foot-inner a:hover { - color: var(--ink); + +@media (max-width: 720px) { + .site-header, .nav { min-height: 78px; align-items: center; margin: 0 18px; padding: 18px 0; } + .site-header nav, .nav-links { gap: 14px; } + .home-main { width: calc(100% - 36px); padding-bottom: 48px; } + .home-hero { padding: 64px 0 58px; } + .home-copy h1 { font-size: 100px; } + .home-copy > p { margin-top: 25px; font-size: 22px; line-height: 1.16; } + .home-case-head { display: none; } + .home-case-row { grid-template-columns: 1fr; gap: 7px; padding: 18px 0; } + .home-case-name { font-size: 21px; } + .main { width: calc(100% - 36px); padding-top: 42px; } + .main h1 { font-size: 51px; } + .main .lede { font-size: 22px; } + .panel { width: calc(100% - 36px); margin-top: 28px; } + .panel-cat { width: 100%; margin-left: 0; } + .index-row { grid-template-columns: 1fr auto; gap: 7px 15px; } + .row-sum { grid-row: 2; grid-column: 1 / -1; } + .foot-inner { align-items: flex-start; flex-direction: column; } + .foot-links { margin-left: 0; } } -.foot-links { - display: flex; - gap: 18px; - align-items: center; - flex-wrap: wrap; + +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { scroll-behavior: auto !important; transition-duration: 1ms !important; } } + .footer-button { appearance: none; - border: 0; padding: 0; + border: 0; background: transparent; - color: var(--ink-muted); - font: inherit; + color: var(--muted); cursor: pointer; + font: inherit; } .footer-button:hover { - color: var(--ink); + color: var(--navy); text-decoration: underline; - text-underline-offset: 3px; + text-underline-offset: 4px; } -/* ── analytics consent ── */ +/* Consent-gated analytics controls added by /analytics.js. */ .consent-banner { position: fixed; z-index: 100; @@ -419,12 +154,12 @@ a:hover { left: 24px; width: min(350px, calc(100vw - 48px)); padding: 16px; - background: var(--surface); - border: 1px solid var(--hairline); + border: 1px solid var(--line); border-radius: 14px; + background: var(--surface); box-shadow: - 0 20px 50px rgb(17 17 17 / 14%), - 0 2px 8px rgb(17 17 17 / 7%); + 0 20px 50px rgb(12 27 58 / 14%), + 0 2px 8px rgb(12 27 58 / 7%); animation: consent-in 180ms ease-out; } .consent-banner[hidden] { @@ -439,20 +174,20 @@ a:hover { } .consent-copy p { margin: 0 0 7px; - color: var(--ink-muted); + color: var(--muted); font-size: 13.5px; line-height: 1.45; } .consent-copy a { - color: var(--ink-muted); + color: var(--muted); font-size: 12.5px; text-decoration: underline; - text-decoration-color: var(--hairline); + text-decoration-color: var(--line-soft); text-underline-offset: 3px; } .consent-copy a:hover { - color: var(--ink); - text-decoration-color: var(--ink); + color: var(--navy); + text-decoration-color: var(--navy); } .consent-actions { display: grid; @@ -461,27 +196,26 @@ a:hover { margin-top: 12px; } .consent-actions button { - border: 1px solid var(--hairline); - border-radius: 8px; min-height: 36px; padding: 7px 12px; + border: 1px solid var(--line); + border-radius: 8px; background: var(--surface); - color: var(--ink); - font: inherit; + color: var(--navy); + cursor: pointer; font-size: 14px; font-weight: 500; - cursor: pointer; } .consent-actions button:hover { - background: var(--surface-2); + background: var(--paper-deep); } .consent-actions .consent-accept { - border-color: var(--ink); - background: var(--ink); - color: #ffffff; + border-color: var(--navy); + background: var(--navy); + color: #fff; } .consent-actions .consent-accept:hover { - background: #000000; + background: #000; } @keyframes consent-in { from { @@ -503,43 +237,3 @@ a:hover { padding: 15px; } } - -.openseo-badge { - position: fixed; - right: 20px; - bottom: 20px; - z-index: 50; - display: inline-flex; - align-items: center; - gap: 8px; - background: var(--ink); - color: #ffffff; - border-radius: 999px; - padding: 11px 17px; - font-size: 14px; - font-weight: 500; -} -.openseo-badge:hover { - background: #000000; - text-decoration: none; -} -.openseo-badge strong { - font-weight: 600; -} -.openseo-mark { - width: 22px; - height: 24px; - flex: none; - background: url("/openseo-logo.png") center / contain no-repeat; - /* The source logo is a silver tree on transparent; render it white so it - reads on the dark pill with no backing chip. */ - filter: brightness(0) invert(1); -} -@media (max-width: 640px) { - .openseo-badge .badge-label { - display: none; - } - .openseo-badge { - padding: 10px 12px; - } -} diff --git a/badseo/scripts/run-audit.ts b/badseo/scripts/run-audit.ts index 40f74ba..8e6af8b 100644 --- a/badseo/scripts/run-audit.ts +++ b/badseo/scripts/run-audit.ts @@ -46,7 +46,7 @@ interface CrawlLink { async function warmup(): Promise { // Prime the dev server so healthy pages don't read as slow on a cold start. - const paths = new Set(["/", "/catalog", "/privacy"]); + const paths = new Set(["/", "/privacy"]); for (const f of allFixtures) for (const p of fixturePaths(f)) paths.add(p); await Promise.all( [...paths].map((p) => @@ -247,7 +247,7 @@ async function main() { if (process.env.DEBUG_DEPTH) { for (const p of pages) { - if (p.url.includes("/structure/deep/") || p.url.endsWith("/catalog")) { + if (p.url.includes("/structure/deep/")) { console.log(` depth ${p.crawlDepth} ${p.url}`); } } @@ -334,7 +334,6 @@ async function main() { // Non-fixture content pages must be clean. check("Homepage", "/", [], false); - check("Catalog", "/catalog", [], false); check("Privacy policy", "/privacy", [], false); const byCategory = new Map(); diff --git a/badseo/src/components/site-layout.tsx b/badseo/src/components/site-layout.tsx index e3aa583..5a87308 100644 --- a/badseo/src/components/site-layout.tsx +++ b/badseo/src/components/site-layout.tsx @@ -3,23 +3,23 @@ import type { ReactNode } from "react"; export function SiteLayout({ children }: { children: ReactNode }) { return ( <> -