Files
0pt/components/sections/testimonials-section.tsx
SimonandClaude Opus 5 e3930aa633
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
fix(a11y): ta bort alfa-tonad textfärg — 82 kontrastöverträdelser (UI-09)
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>
2026-09-27 01:27:28 +02:00

63 lines
3.1 KiB
TypeScript

"use client";
import { useReveal } from "@/hooks/use-reveal";
import { useT } from "@/components/locale-provider";
const NUMBERS: [string, { en: string; sv: string }, boolean][] = [
["94%", { en: "Average confidence", sv: "Snittkonfidens" }, true],
["50/50", { en: "Start. Approved.", sv: "Start. Godkänt." }, false],
["<4d", { en: "Delivery", sv: "Leverans" }, false],
];
export function TestimonialsSection() {
const t = useT();
const ref = useReveal<HTMLElement>();
return (
<section ref={ref} className="relative border-b border-border bg-background">
<div className="mx-auto max-w-[80rem] px-6 py-32 lg:py-44">
<div className="flex items-baseline justify-between border-b border-border pb-6">
<p className="reveal font-mono text-[11px] uppercase tracking-[0.18em] text-muted-foreground">{t({ en: "05 — Proof", sv: "05 — Bevis" })}</p>
<p className="reveal delay-1 font-mono text-[11px] uppercase tracking-[0.18em] text-muted-foreground">{t({ en: "Measurable", sv: "Mätbart" })}</p>
</div>
<h2 className="reveal delay-1 mt-10 max-w-3xl text-[clamp(2.4rem,6vw,4.5rem)] font-medium leading-[0.98] tracking-[-0.03em]">
{t({ en: "Numbers.", sv: "Siffror." })}
<br />
{t({ en: "Not promises.", sv: "Inte löften." })}
</h2>
<div className="mt-20 grid grid-cols-1 border-t border-border sm:grid-cols-3">
{NUMBERS.map(([n, l, red], i) => (
<div
key={l.sv}
className={`reveal delay-${i + 2} group relative border-b border-border py-12 sm:border-b-0 sm:border-l sm:py-0 sm:pl-8 sm:pr-4 ${i === 0 ? "sm:border-l-0 sm:pl-0" : ""}`}
>
<p className="font-mono text-[11px] tabular-nums text-muted-foreground">0{i + 1}</p>
<p
className="mt-3 text-[clamp(3.2rem,8vw,6rem)] font-semibold leading-[0.9] tracking-[-0.04em] transition-transform duration-300 group-hover:-translate-y-0.5"
style={{ color: red ? "var(--accent-red)" : "var(--foreground)" }}
>
{n}
</p>
<p className="mt-4 font-mono text-[11px] uppercase tracking-[0.14em] text-muted-foreground">{t(l)}</p>
</div>
))}
</div>
<figure className="reveal-scale delay-5 mt-24 max-w-3xl border-t border-border pt-10">
<blockquote className="text-[clamp(1.5rem,3.2vw,2.25rem)] font-medium leading-[1.15] tracking-[-0.02em]">
{t({
en: "“We trust the list before we dial. The per-contact provenance is what sealed it.”",
sv: "“Vi litar på listan innan vi ringer. Härkomsten per kontakt avgjorde.”",
})}
</blockquote>
<figcaption className="mt-8 flex items-center gap-3 font-mono text-[11px] uppercase tracking-[0.16em] text-muted-foreground">
<span aria-hidden className="inline-block h-1.5 w-1.5" style={{ background: "var(--prov-0)" }} />
RevOps · B2B SaaS
</figcaption>
</figure>
</div>
</section>
);
}