CI (SIAX Cloud) / integration (push) Skipped
masterplan-lock / check (push) Successful in 7s
Security Scan (SIAX Cloud) / security (push) Successful in 20s
CI (SIAX Cloud) / security (push) Successful in 47s
masterplan-lock / check (pull_request) Successful in 10s
CI (SIAX Cloud) / quality (push) Successful in 1m11s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 32s
CI (SIAX Cloud) / security (pull_request) Successful in 42s
CI (SIAX Cloud) / integration (pull_request) Successful in 56s
CI (SIAX Cloud) / quality (pull_request) Successful in 59s
axe-core 4.10.2 mot 0pt.app 2026-09-26: en enda regel, color-contrast, impact=serious, 82 noder. Estatets största enskilda a11y-defekt. Alla 82 har samma form: en Tailwind-alfamodifierare på en textfärg. Uppmätt WCAG 2.2-kontrast mot bägge temabakgrunderna i styles/globals.css: text-muted-foreground 4.73:1 ljust 7.63:1 mörkt GODKÄNT text-muted-foreground/70 2.71:1 4.20:1 faller text-muted-foreground/60 2.29:1 3.37:1 faller text-muted-foreground/50 1.96:1 2.67:1 faller text-muted-foreground/40 1.69:1 2.11:1 faller text-foreground/20 1.57:1 1.74:1 faller Den omodifierade token klarar AA i bägge teman, så åtgärden är helt enkelt att aldrig tona den. Elva textställen bytte till text-muted-foreground. Kopieringsknappen i app/portal går från 1.57:1 till 4.73:1 i viloläge och 19.79:1 vid hover — den föll även 1.4.11 för icke-textkomponenter. Toastens stängknapp klarade redan 1.4.11 (3.71:1) men blir 4.73:1. Kvar med alfa är endast den dekorativa masthead-siffran i app/bestall, som redan bär aria-hidden + select-none + pointer-events-none. Den är undantagen både av WCAG och av axe, och guarden nedan tillåter den på just den grunden. scripts/ci/check-text-contrast.mjs är en blockerande källkodsgrind i quality-jobbet. Den är avsiktligt inte en axe-körning: den fullständiga axe-jobb som UI-09 också begär kräver build + serve i CI och spåras separat. Tills det finns stoppar den här grinden regressionen vid den form som orsakade defekten. Refs: UI-09 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
51 lines
3.0 KiB
TypeScript
51 lines
3.0 KiB
TypeScript
"use client";
|
|
|
|
import { useReveal } from "@/hooks/use-reveal";
|
|
import { useT } from "@/components/locale-provider";
|
|
|
|
type Loc = { en: string; sv: string };
|
|
const PRINCIPLES: [string, Loc, Loc][] = [
|
|
["01", { en: "Provenance per field.", sv: "Härkomst per fält." }, { en: "Source, freshness, confidence. The whole chain is visible.", sv: "Källa, färskhet, konfidens. Hela kedjan syns." }],
|
|
["02", { en: "Corroboration first.", sv: "Korroborering först." }, { en: "Sources that disagree become an uncertain field.", sv: "Oeniga källor blir osäkert fält." }],
|
|
["03", { en: "Empty over guessed.", sv: "Hellre tomt än gissat." }, { en: "Unverified data is not delivered. Never invented.", sv: "Obelagt levereras ej. Aldrig uppfunnet." }],
|
|
];
|
|
|
|
export function PhilosophySection() {
|
|
const ref = useReveal<HTMLElement>();
|
|
const t = useT();
|
|
return (
|
|
<section ref={ref} id="filosofi" className="border-b border-border bg-background">
|
|
<div className="mx-auto grid max-w-[80rem] grid-cols-1 gap-12 px-6 py-32 lg:grid-cols-[4fr_8fr] lg:py-40">
|
|
<div className="lg:sticky lg:top-24 lg:self-start">
|
|
<p className="reveal-left font-mono text-[11px] uppercase tracking-[0.14em] text-muted-foreground">{t({ en: "01 — Philosophy", sv: "01 — Filosofi" })}</p>
|
|
<p className="reveal-left delay-1 mt-4 font-mono text-[11px] uppercase tracking-[0.08em] text-foreground">{t({ en: "Honest data. Shown honestly.", sv: "Ärlig data. Visad ärligt." })}</p>
|
|
</div>
|
|
<div>
|
|
<h2 className="reveal max-w-[20ch] text-[clamp(2.4rem,5.5vw,4.5rem)] font-medium leading-[0.98] tracking-[-0.03em]">
|
|
{t({ en: "Others sell certainty they don't have.", sv: "Andra säljer säkerhet de saknar." })}
|
|
<br />
|
|
<span className="text-muted-foreground">{t({ en: "We show the source.", sv: "Vi visar källan." })}</span>
|
|
</h2>
|
|
<div className="mt-20 border-t border-border">
|
|
{PRINCIPLES.map(([n, title, body], i) => (
|
|
<div
|
|
key={n}
|
|
className={`reveal delay-${i + 1} group relative grid grid-cols-[3.5rem_1fr] items-baseline gap-8 border-b border-border py-8 transition-[padding] duration-300 ease-out hover:pl-2`}
|
|
>
|
|
<span className="absolute -left-2 top-0 h-px w-0 bg-foreground transition-all duration-500 ease-out group-hover:w-full group-hover:opacity-100" aria-hidden />
|
|
<span className="font-mono text-[clamp(1.5rem,2vw,2.25rem)] font-medium leading-none tracking-[-0.02em] text-muted-foreground transition-colors duration-300 group-hover:text-foreground">
|
|
{n}
|
|
</span>
|
|
<div>
|
|
<p className="text-[clamp(1.25rem,2vw,1.75rem)] font-medium leading-tight tracking-[-0.02em]">{t(title)}</p>
|
|
<p className="mt-2 max-w-[42ch] leading-relaxed text-muted-foreground">{t(body)}</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|