
"The deployment of the Proto AICX solution is in line with the Bank of Zambia's 2020–2023 Strategic Plan that has prioritized financial inclusion."
Every value below is painted with the real --p4-* custom property, so this page can't drift from proto-v4-tokens.css. Authority order ↓
One accent hue, no categorical marketing palette. Orange is the SECONDARY action colour — ink is primary.
Colour resolves in three layers, each below the last: the raw palette (orange and neutral ramps), a semantic layer that names a role on the page (--p4-bg-*, --p4-text-*,--p4-hairline-*), and a component layer (--p4-action-*) that names a ButtonV2 variant rather than a page role. Every exhibit below paints with the real token, so none of the three tables can drift from what's actually declared in proto-v4-tokens.css.
500 is the primary orange. 600 is link hover and text below 18px. 50/100 are the only orange surfaces allowed in body sections. 700/900 are text on white / on an orange field.
Never marketing decoration — inbox rows, live queues, simulated product surfaces only.
One layer past "semantic": each row is a token ButtonV2.astro itself reads, not a role reused across the page. Secondary and Ghost aren't rows here on purpose — both render on transparent, hover , straight off the palette with no --p4-action-* token of their own.
Off the same layer, but not a button at all: arrow-link hover reads its own token, .
Sora for display and headings (light only — 400 display, 450 heading, never heavier), Inter for body, Plex Mono for labels and codes.
home-v3.astro ships, per the authority order above. --p4-link-hover was wrongly o-700 in the token file — fixed to o-600 this pass, matching every shipped .arrow-link:hover rule and the rules doc.One workspace from first message to resolved case.
Sovereign by deployment, fluent in the languages support usually skips.
Sora's ceiling is 450 — v3's xbold/bold/semibold (800/700/600) steps have no v4 equivalent, on purpose (rules §2, "never heavier"). Inter's medium (500) was real but untokenised until this pass — 10–14 hardcoded font-weight: 500 literals per page, now --p4-weight-medium.
Production pages (Layout.astro) use the vendored classes on the left; v4-native pages (LayoutV2) use the .v2-* classes further down. Both resolve through the same tokens as of the typography bridge — picking either table's matching row renders identically.
Layout.astro).heading-style-h1 (also <h1>).heading-style-h2 (also <h2>).heading-style-h3 (also <h3>).heading-style-h4 (also <h4>).heading-style-h5.heading-style-h6.heading-style-title.text-size-large.text-size-medium.text-size-regular.text-size-small.text-size-tiny.text-weight-medium.text-weight-semibold.text-weight-normal.text-weight-light.text-weight-bold.text-weight-xboldLayoutV2, src/styles/v4/type.css).v2-eyebrow.v2-eyebrow-sm.v2-eyebrow-xs.is-onfield.v2-h2.v2-ledeContainer 1280 (80rem) is the default of three sizes — small/medium/large (900 / 1080 / 1280), kept from v3's Client-First convention and unified with it 2026-08-28. 12 columns, gutter 32 (2rem), column gap 16/24. 4px scale, off-scale steps flagged.
Section · heading gap · 24 grid gap / card padding
Product modules, proof grids, resources, tables.
Section · heading gap · 32 grid gap / card padding
Statements, single-idea sections, editorial breaks, CTA.
Full-bleed is allowed for hero graphics and the logo strip only.
One border weight. Hairlines do the work, not shadows. Flat is the default — elevation is the exception.
pills, inputs, chips
cards, buttons
panels, media, frames
Black leads, orange supports. Sentence case, never uppercase. Heights 56 hero / 48 default / 40 compact.
redesign-brief.md: that brief's "orange = secondary buttons" line is retired. Target set: primary black fill, secondary/ghost(the same borderless look, revised 2026-08-28 — secondary used to be a grey fill), grey(that old fill, kept as its own explicit option), white (for use on a solid orange/grey section), outline (ghost plus a grey border — the one variant that deliberately keeps a border; no other variant carries a border colour), and accent (added 2026-08-31 — orange fill, white text, the one named exception to "orange is never a button fill"). Reconciled intoButtonV2.astro itself — the swatches below render the real component, not a page-scoped stand-in.variant="primary"Black fill. One per view.
variant="secondary"Ghost, not grey, as of this pass — identical to the ghost variant below.
variant="grey"The old secondary look, kept as its own option.
variant="white"For a solid orange or grey section.
variant="ghost"Borderless. What secondary now means.
variant="outline"Ghost plus a grey border — the one variant that keeps one.
variant="accent"Added 2026-08-31. Orange fill, white text — the one named exception to "orange never fills".
Label first, icon (or dot) second, in its own boxed tile — not the pill's mono/uppercase count badge above. Icon tile , tag fill , radius (card, not pill).
.p4-tagWhite outer pill nests a small accent pill for a live status (.p4-tag__inner, .is-neutral for a non-live one). .is-accent on the outer tag itself — no nesting — is the standalone solid-orange, white-text tag for a single highlighted item.
Rule (design-system-rules-addendum-v10.md §10): once a .p4-tag nests a .p4-tag__inner, its left padding matches the nested pill's own narrow right-hand gap — on both sides, not the wider plain-label the left still carries when there's no nested pill (.is-accent above).
.p4-tag.is-sentenceSame nested shell as the pill tag above, without the uppercase transform and tracking, and with the nested pill's text sized up to match — for a phrase-style label rather than an eyebrow-style word.
.workflow-card_tagSolid fill () for industry, dashed border for usecase — same card, two rows, no third colour to tell them apart. Eyebrow size throughout () — hover or tap +N to reveal the rest of that row.
Module · proof · quote · resource · metric. Each a hairline box on white. The o-50 field card is the one exception, max twice per page, never adjacent.
.card, .card-nohover, 29 definition sites) tinted at, matching the elevation ladder's card tier. That's now wrong as a default: cards revert to white with their existing hairline as the only definition — an outline card, not a filled one. A tinted fill stays for two ad-hoc cases, both real and shipped, neither using the.card class at all: a product card that's mostly a surface for other UI to sit on (the government feature grid's .product-grid_card, .product_feature_row on the platform pages), and a CTA field meant to draw the eye. Fixed at src/styles/v4/bridge.css — see that file for the two dormant.card modifiers (.is-cta_cbg, .is-agen-gen-cta) kept correct against the day either ships again.Six modules, one deployment.
Deployed in the Philippines.
"Every scam report is traced before the money moves again."
Workflow co-pilot, priority chat assignment.
First-contact resolution
G20 TechSprint · 2025
The one exception, ink text throughout — max 2×/page, never adjacent.
Resource card thumbnail: aspect-ratio: 1200 / 630 (the source image's real ratio, not 16:9), hover lift only — no hover shadow.
Outer padding IS the gap — not the card's normal content padding.
(range 4–8px, tune per component)calc(r-lg − gap) — never an independent value.vb-card)calc(outer − gap), same rule as §6b, applied to every sibling on a plain (unfilled) sibling — the ordinary hairline is invisible with no fill to contrast against. A filled sibling (right, matching the shipped promo card) can keep the plain hairline..v2-mega__inner → .v2-mega__col ×3Every section is the same five parts. Separation by padding alone, not a hairline or alternating background — see §09 Avoid. Left-aligned by default — centred is reserved for hero and CTA, two max.
An optional lede, never longer than two lines — if a section needs three, it's two sections.
Surface order: n-25 (page) → n-0 (card) → o-500 once, for a hero or CTA field. Rails always show a partial fourth card.
One workspace from first message to resolved case — sovereign by deployment, fluent in the languages support usually skips.
index.astro, ported verbatim from hero-variants.astro Variant 1a.1.02fr / 1fr, gap — copy column fractionally wider than the graphic, not an even split.100vh, clamped 40rem–56.25rem — the one section on the page sized to the viewport rather than its content./explore/hero-variants for comparison — dragging any globe spins it by hand.Secondary by role, confident where it lands.
Reversed on direction from the earlier ink-only rule — body and heading text is now white on an orange field. Worth having the number on record, not as a blocker: measured contrast for white on o-500 is ≈2.9:1, under WCAG AA's 4.5:1 for body text (ink measured ≈6.4:1 on the same field). A button's own FILL is a separate question, reviewed here: black-filled reads as a dark shape sitting on top of a saturated field, lower contrast against it than the field has against the page; white-filled pops the way a CTA on an orange field should. Resolved: white fill, ink text — the "white" target variant from §05 exists specifically for this, unaffected by the body-text reversal above.
Named, not reproduced — the drawn spec renders each retired pattern live; this table states the rule instead, since coding a deliberately-wrong pattern for a "don't do this" demo isn't worth the upkeep.
One card (TestimonialCard.astro), one section (TestimonialSlider.astro) — every page with a testimonial renders from these two components, so the design can't drift page to page the way nine separate hand-rolled sections used to. The section picks its own layout from how much content it actually has; no page passes a layout prop.
TestimonialCard — layout="card" (default)
"The deployment of the Proto AICX solution is in line with the Bank of Zambia's 2020–2023 Strategic Plan that has prioritized financial inclusion."
Image on top, name-led, body-sized quote — the unit every card inside both static-row and slider section modes below is built from, unchanged since it shipped on the homepage.Whole card is the link when a storyHref resolves — the right card above, hover it — via an empty, absolutely-positioned .tc-card__cover-linklayered over the card (same technique as ResourceCard.astro's.resource-card_current-link, resource-card.css). The round arrow badge on the image's corner (.tc-card__image-link) is the visible affordance for that link — over the photo, not trailing text below the quote, so it's seen the moment the card is rather than missed at the bottom. It brightens on card hover; the badge itself isn't a separate link, the cover above is. The left card has no storyHref — its testimonial has no linked client-story yet — and is correctly inert: no badge, no cover-link, no cursor change, nothing to click. Same optional pattern driveslayout="description"'s href below.
TestimonialCard — layout="spotlight"
“Proto delivered noticeable results immediately after deployment, greatly reducing the number of routine concerns we handle by providing 24/7 responses.”
Figure-led ("Option A", design review): the number is the claim, the quote is the evidence for it. The figure sits at in a column of its own, closed by a vertical hairline, parsed with lib/figure.ts — the same "**value** *caption* (+delta)" parser case-study/[slug].astro already uses — and the quote drops to beside it, capped at 62ch so a line doesn't run the width of the section. Card width is the caller's job, not this component's — full shell width in TestimonialSlider.astro (this exhibit is narrower only because the style guide's own rail+exhibits column is). Logo and figure are spotlight-only; the whole-card link behind "Read the story" is shared with the compact card layout above, same storyHref prop either way. Reworked from two retired single-story patterns rather than designed from nothing —TestimonialCard (the logo + linked-story idea) and QuoteAccordion + QuoteCard (the highlight-stat idea).
TestimonialSlider.astrocounts its resolved slides (testimonials plus any interleaved awards) and picks one of three designs, live below:cardOnly skips the section entirely — no eyebrow/heading/nav, just the card(s) — for a page that already has its own heading nearby and only wants the proof itself; the four/platform/* pages use it inside their own feature column.Section — 1 story → spotlight

“Proto delivered noticeable results immediately after deployment, greatly reducing the number of routine concerns we handle by providing 24/7 responses. It can also be trained quickly with new data, making it a highly adaptable tool for our customer service operations.”
.png)
Section — 2 stories → filled row
In production

"The National Bank of Rwanda is pleased to deploy the Proto customer complaints handling AI system. The Intumwa AI agent will include customers in their local languages and preferred messaging channels."


"Proto delivered noticeable results immediately after deployment, greatly reducing the number of routine concerns we handle by providing 24/7 responses. It can also be trained quickly with new data, making it a highly adaptable tool for our customer service operations."
.png)
Section — 3 stories → slider
Client stories
Three real testimonials, same content proto-vs-wizai and proto-vs-botmd ship on/compare/* — the slider path, not the static row above, per the raised floor.
Section — 4 stories → slider
Regulator & central bank stories
Same real content mixes shipped today — /pricing//enterprise//roi(1), voice.astro (2), /compare/* (3–4) and the homepage (10 + an award) — not staged data invented for this page.