Files
hmbown--codewhale/web/tailwind.config.ts
CodeWhale Bot 74b5192110 fix(web): accessibility, structured data, and metadata defects
Defect fixes ahead of relaunch — no redesign, no new copy, no media.

Accessibility:
- The mobile menu declares `aria-modal`, which promises the dialog owns
  interaction, but focus never entered it and never came back. Focus now
  moves inside on open and returns to the toggle on close. The toggle node
  is captured before cleanup rather than read from the ref inside it, which
  would race React clearing it.
- The terminal player had `role="tablist"` with none of the pattern behind
  it. Adds arrow-key/Home/End movement, a roving tabindex, and
  aria-controls/aria-labelledby wiring between each tab and the panel.
- Context text ran at white/45 on ink — 4.32:1, below the 4.5:1 WCAG AA
  floor for normal text. Now white/55, 5.78:1.

Metadata:
- SoftwareApplication JSON-LD on the home page. Every field traces to a
  repo-sourced fact already rendered on the page; `softwareVersion` is
  omitted rather than guessed when facts carry none.
- `id` was missing from the OpenGraph locale map, so Indonesian pages
  emitted no og:locale.

Drafted by Kimi K3 in Codewhale exec, reviewed here. The claimed contrast
ratio was recomputed independently (5.78:1 vs its stated 5.75:1 — a
rounding difference against the exact ink token, and the before value does
genuinely fail AA). Gates re-run here: 250 tests, eslint clean.

Note for follow-up, not introduced by this change: `npm audit` in web/ now
reports 1 high-severity js-yaml advisory. The release contract requires 0.
2026-08-06 16:11:31 -07:00

44 lines
1.7 KiB
TypeScript

import type { Config } from "tailwindcss";
export default {
content: ["./app/**/*.{ts,tsx}", "./components/**/*.{ts,tsx}"],
theme: {
extend: {
colors: {
// The surface and ink tokens resolve through CSS custom properties so
// docs can still re-theme, while the shared accent palette stays oceanic.
paper: "rgb(var(--c-paper) / <alpha-value>)",
"paper-deep": "rgb(var(--c-paper-deep) / <alpha-value>)",
"paper-edge": "rgb(var(--c-paper-edge) / <alpha-value>)",
"paper-line": "#1B2230",
"paper-line-soft": "#CBD3DF",
ink: "rgb(var(--c-ink) / <alpha-value>)",
"ink-soft": "rgb(var(--c-ink-soft) / <alpha-value>)",
"ink-mute": "rgb(var(--c-ink-mute) / <alpha-value>)",
indigo: "#315FD8",
"indigo-deep": "#2448A6",
"indigo-pale": "#E8EEF8",
ochre: "#7A5500",
jade: "#08766D",
cobalt: "#315FD8",
},
fontFamily: {
// The real display face is Fraunces, loaded by next/font in
// app/[locale]/layout.tsx onto --font-display (globals.css .font-display
// resolves the same stack). Space Grotesk was never loaded — naming it
// here only produced a utility that silently fell back to sans-serif.
display: ["var(--font-display)", '"Fraunces"', '"Noto Serif SC"', "Georgia", "serif"],
body: ['"IBM Plex Sans"', '"Noto Sans SC"', "ui-sans-serif", "system-ui", "sans-serif"],
cjk: ['"Noto Serif SC"', '"Source Han Serif SC"', "serif"],
mono: ['"JetBrains Mono"', "ui-monospace", "Menlo", "monospace"],
},
letterSpacing: {
crisp: "-0.018em",
wider: "0.08em",
widest: "0.18em",
},
},
},
plugins: [],
} satisfies Config;