Trusted AI·Local languages
Internal reference · noindex

Style guide

Every value below is painted with the real --p4-* custom property, so this page can't drift from proto-v4-tokens.css. Authority order ↓

Authority order: home-v3.astro (current, shipped) → design-system-rules.md+ the drawn spec (foundation/reference) → redesign-brief.md (superseded where it conflicts — its orange-secondary-button line is the one that matters; see §05).

01

Color

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.

Brand orange
50
100
200
300
400
500
600
700
900

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.

Warm neutrals
n-0
n-25
n-50
n-100
n-200
n-300
n-500
n-600
n-700
n-800
ink
Semantic assignment
Page
Surface / card
Recessed
Field (orange, max 2×/page)
Hairline
Hairline (strong)
Hairline (on a field)
Text — heading
Text — body
Text — strong
Text — meta
Text — faint
Text — eyebrow (on a field)
Status — product UI only

Never marketing decoration — inbox rows, live queues, simulated product surfaces only.

live
pending
escalated
idle
Component colour — ButtonV2 variants

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.

Variant
Fill / border
Text
Hover
Primary
Grey
White
Outline
Accent

Off the same layer, but not a button at all: arrow-link hover reads its own token, .

02

Typography

Sora for display and headings (light only — 400 display, 450 heading, never heavier), Inter for body, Plex Mono for labels and codes.

Resolved against the drawn spec: display-xl 70px (spec 64px), h2 40px (spec 32px), h3/card-title kept as two tokens (spec has one 22px value), metric 34px (spec 44px) — all four follow what 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.

Deploying AI that includes everyone

display-xl
Sora 400
hero only — clamp(), 36px → 70px
Trusted where it is hardest
display-l
Sora 400
stat / price figure — 44px

One platform, every channel

h2
Sora 450
section heading — clamp(), 32px → 40px

Grievance redress, end to end

h3
Sora 450
tab / subsection title — 26px
Sovereign by deployment
card-title
Sora 450
card heading — 22px

One workspace from first message to resolved case.

lede
Inter 400
section lede, max 54ch — 19px

Sovereign by deployment, fluent in the languages support usually skips.

body
Inter 400
default paragraph — 16px
Talk to local team
nav (added this pass)
Inter 500
nav / footer links, mega-menu items — 14px
REGULATOR & CENTRAL BANK STORIES
eyebrow
Plex Mono 500
section label, uppercase, +.1em — 12px
Weights
Aa
Inter body (normal)
default paragraph text
Aa
Inter medium
nav, buttons, labels, eyebrows, pills
Aa
Sora display
display sizes only
Aa
Sora heading (max)
headings, card titles — the heaviest Sora ever gets

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.

Size scale, small → large — every size token, independent of the specimen rows above
Aa
Aa
Aa
Aa
Aa
Aa
Aa
Aa
Aa
Aa
Aa
Aa
Aa
Aa
Aa
Aa
Typography control classes — what to type to change text

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.

Production — headings (Layout.astro)
Class
Renders at
Note
.heading-style-h1 (also <h1>)
clamp 36→70px
.heading-style-h2 (also <h2>)
clamp 32→40px
.heading-style-h3 (also <h3>)
.heading-style-h4 (also <h4>)
same target as h5
.heading-style-h5
same target as h4
.heading-style-h6
bare <h6> resolves to --p4-size-body instead, not --p4-size-lede — the class and the bare element differ on this one
.heading-style-title
retired — 0 live usages, not bridged. Use .heading-style-h1 instead.
Production — body text
Class
Renders at
Note
.text-size-large
.text-size-medium
the most common — 143 live usages
.text-size-regular
same target as medium
.text-size-small
default paragraph size — 369 live usages
.text-size-tiny
meta text, captions
Production — weight
Class
Renders at
Note
.text-weight-medium
.text-weight-semibold
v3 had a real 600 step; v4 has none, collapses onto medium (500) — D3
.text-weight-normal
0 live usages, kept for completeness
.text-weight-light
own fixed weight
no v4 equivalent — renders at its own 300, unbridged
.text-weight-bold
own fixed weight
no v4 equivalent — renders at its own 700, unbridged
.text-weight-xbold
own fixed weight
no v4 equivalent, 0 live usages — renders at its own 800, unbridged
v4-native (LayoutV2, src/styles/v4/type.css)
Class
Renders at
Note
.v2-eyebrow
mono, uppercase, +.1em tracking
.v2-eyebrow-sm
mono, uppercase, +.1em tracking
.v2-eyebrow-xs
mono, uppercase, +.1em tracking
.is-onfield
modifier
modifier, stack onto any eyebrow — recolours for text sitting on a tinted/dark field
.v2-h2
Sora, clamp 32→40px, -.02em tracking
.v2-lede
Inter, max 54ch
03

Space & grid

Container 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.

Spacing scale
Container sizes — kept from v3's container-small/medium/large
smallnot yet used in a v4 page — narrow content columns (long-form text, forms)
mediumcompare/[slug].astro narrows its `.v2-shell` and TestimonialSlider’s `.va-viewport` (via `--tsl-container`) to this — see §10
largethe default — every v4 page uses this one today
Dense rhythm

Section · heading gap · 24 grid gap / card padding

Product modules, proof grids, resources, tables.

Calm rhythm

Section · heading gap · 32 grid gap / card padding

Statements, single-idea sections, editorial breaks, CTA.

Container — 12 columns

Full-bleed is allowed for hero graphics and the logo strip only.

04

Shape & borders

One border weight. Hairlines do the work, not shadows. Flat is the default — elevation is the exception.

r-sm

pills, inputs, chips

r-md

cards, buttons

r-lg

panels, media, frames

Flat
Raised
Floating
Grid frame — resolved to 80px / 12px (the caption's value, not the drawn spec's own 48px / 10px demo)
Reserved for the CTA and at most one other anchor per page.
05

Controls

Black leads, orange supports. Sentence case, never uppercase. Heights 56 hero / 48 default / 40 compact.

Superseding 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.
Primary variant="primary"

Black fill. One per view.

Secondary variant="secondary"

Ghost, not grey, as of this pass — identical to the ghost variant below.

Grey variant="grey"

The old secondary look, kept as its own option.

White variant="white"

For a solid orange or grey section.

Ghost variant="ghost"

Borderless. What secondary now means.

Outline variant="outline"

Ghost plus a grey border — the one variant that keeps one.

Accent variant="accent"

Added 2026-08-31. Orange fill, white text — the one named exception to "orange never fills".

Arrow link
All modules

Not a ButtonV2 variant — a plain text link with a trailing arrow.

Tags & status
OutlineOn-fieldSOC 2 · ISO 27001
Tabs — active marker is the ONE orange state
OverviewInteractionsPricing
Compliance / status tag — CertTag.astro, footer status link
ISO 27001SOC 2 Type IIStatus

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).

Pill tag — controls.css .p4-tag
PhilippinesDeployedPakistanIn development2026 · Current

White 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).

Pill tag, sentence case — .p4-tag.is-sentence
Latest releaseNew

Same 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.

Category tag — workflow-card.css .workflow-card_tag
PaymentsCustomer SupportGovernmentHealthcareInsight Advisor

Solid 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.

Auto-tabs — menu + progress bar + auto-advance (ported from the interactions section)
Overview panel content
06

Cards — five types, no more

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.

Colour is ad hoc, not the default — direction settled after the merge bridge shipped every production card (.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.
Module

Six modules, one deployment.

Proof

Deployed in the Philippines.

"Every scam report is traced before the money moves again."

Director, Consumer Protection
Resource

Workflow co-pilot, priority chat assignment.

8 min read
92%

First-contact resolution

Award2025

G20 TechSprint · 2025

Proto and FNA win the G20 TechSprint cybercrime award

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.

Nested-card construction — §6b
Card title

Outer padding IS the gap — not the card's normal content padding.

Gap
(range 4–8px, tune per component)
Inner radius
calc(r-lg − gap) — never an independent value
What nests
one block — an image or media frame, not text content
Body padding
flush, not additive (§6d) — the text body carries zero horizontal padding of its own; the shell's own padding is the only left/right inset, same as the nested image. Vertical padding is unrestricted.
Shipped instances
ResourceCard.astro · TestimonialCard.astro · index.astro's usecase slider (.vb-card)
Sibling outline — §6b, several nested blocks
Outer gap
One value on every edge — the wrapper's own padding AND the gap between siblings (shown: 6px)
Inner radius
calc(outer − gap), same rule as §6b, applied to every sibling
Border colour
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.
Shipped instance
Header.astro's mega-menu — .v2-mega__inner.v2-mega__col ×3
07

Section anatomy

Every 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.

Section eyebrow
Heading — the second part

An optional lede, never longer than two lines — if a section needs three, it's two sections.

Optional footer link

Surface order: n-25 (page) → n-0 (card) → o-500 once, for a hero or CTA field. Rails always show a partial fourth card.

Hero — one composition, shipped; two more explored
Agentic workflows, in-country models
Deploying AI that includes everyone

One workspace from first message to resolved case — sovereign by deployment, fluent in the languages support usually skips.

Graphic column
(ASCII globe, live)
Shipped
Split — copy left, graphic right, offset to overflow the section edge so it reads larger than its own frame. No card, no field. index.astro, ported verbatim from hero-variants.astro Variant 1a.
Anatomy
badge (dot + label) → h1 title → lede → two hero-size buttons (primary + secondary) — same five-part shape as §07's general anatomy, just centred in its own column rather than the page.
Graphic
the design system's own mono accent, built out as the hero device — not a stock illustration or photo.
Layout ratio
1.02fr / 1fr, gap — copy column fractionally wider than the graphic, not an even split.
Height
100vh, clamped 40rem56.25rem — the one section on the page sized to the viewport rather than its content.
Also explored, not shipped
a centred variant with the same globe dimmed behind the copy as an ambient field (quieter, copy sits on texture); an inset-card family (recessed or gradient-washed) with a smaller, cropped graphic; a wireframe globe on a flat o-500 field, the one hero treatment allowed a full orange background. All 8 live side by side at /explore/hero-variants for comparison — dragging any globe spins it by hand.
08

Orange rules

Secondary by role, confident where it lands.

Allowed
Secondary buttons
Tags, badges, eyebrows
Active-tab underline (the only orange state marker)
Large flat fields in hero graphics
o-50 / o-100 product-card backgrounds
Chart / data marks
White text on an orange field
Not allowed
Orange as the primary CTA
A coloured word inside a heading
Gradients anywhere outside the hero graphic or the orb/glow device
Orange body text, or orange under 18px, on white
Two orange sections adjacent
Orange dividers
Orange on orange

White type on orange

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.

reads flat here
resolved — use this
09

Avoid — retired from v3

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.

Retired
Use instead
Vertical background lines
Flat surfaces, separated by spacing
Hairline border between sections (`.v2-section`)
Padding-block alone; `.is-surface` background tint for emphasis, no border either side of it
Gradient section backgrounds
Flat surfaces; the orb/glow device is the one exception, graphic elements only
Italic type, coloured words in headings
Weight and position carry emphasis
All-caps glowing pill buttons
Sentence case, flat fill, 1px hairline
36px radius, heavy drop shadow
r-lg (16px) max, flat shadow tiers
Auto-scrolling marquees, unbounded
One runner max per page, pauses on reduced motion
10

Testimonials — card & section

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.

TestimonialCardlayout="card" (default)
Zambia
Bank of Zambia
"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."
Dr. Francis Chipimo
Deputy Governor – Operations, Bank of Zambia
Philippines
Bangko Sentral ng Pilipinas
"The multilingual Proto AI agent empowers consumers by providing an accessible channel for complaints, supporting the central bank's commitment to financial service innovation."
Benjamin E. Diokno
Governor, Central Bank of the Philippines

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.

TestimonialCardlayout="spotlight"
Philippines · PhilCare
“Proto delivered noticeable results immediately after deployment, greatly reducing the number of routine concerns we handle by providing 24/7 responses.”
5K
members engaged monthly
Alex Aquino
CTO, PhilCare
Read the story

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).

The section chooses its own layoutTestimonialSlider.astrocounts its resolved slides (testimonials plus any interleaved awards) and picks one of three designs, live below:
1 slide
Spotlight — the wide single-story card above, no nav/dots
2 slides
A static, evenly filled row — cards widen to use the space rather than a slider with nothing to scroll
3+ slides
The horizontal slider — peek bleed, prev/next, dots. Lowered from a 4+ floor: three cards in a static row read cramped once the shell itself is narrower than the sitewide default, as on /compare/* pages
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

Philippines · PhilCare
“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.”
5K
members engaged monthly
Alex Aquino
CTO, PhilCare
Read the story

Section — 2 stories → filled row

In production

Already carrying real volume

Rwanda
National Bank of Rwanda
"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."
Gérard Nsabimana
Director of Market Conduct Supervision, BNR
Philippines
PhilCare
"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."
Alex Aquino
CTO, PhilCare

Section — 3 stories → slider

Client stories

What the clients say

Philippines
Bangko Sentral ng Pilipinas
"The multilingual Proto AI agent empowers consumers by providing an accessible channel for complaints, supporting the central bank’s commitment to financial service innovation."
Benjamin E. Diokno
Governor, Central Bank of the Philippines
Rwanda
National Bank of Rwanda
"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."
Gérard Nsabimana
Director of Market Conduct Supervision, BNR
Philippines
Philippines Department of Trade & Industry
"The DTI's assistant TIA is built to speak the languages of our Filipino customers, understand their needs, and provide them with an immediate response."
Mary Jean Pacheco
Undersecretary of the Department of Trade and Industry

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

Trusted by the institutions that supervise us

Liberia
Central Bank of Liberia
"Access to financial consumer protection in Liberia is limited due to traditional channels such as email and in-person complaint filing. Proto's automated consumer protection solution helped us solve this issue."
J. Aloysius Tarlue, Jr.
Executive Governor, Central Bank of Liberia
Zambia
Bank of Zambia
"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, and implementation of SupTech to digitize reporting and regulatory processes."
Dr. Francis Chipimo
Deputy Governor – Operations, Bank of Zambia
Rwanda
National Bank of Rwanda
"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."
Gérard Nsabimana
Director of Market Conduct Supervision, BNR
Philippines
Dept. of Trade & Industry
"The DTI's assistant TIA is built to speak the languages of our Filipino customers, understand their needs, and provide them with an immediate response."
Mary Jean Pacheco
Undersecretary of the Department of Trade and Industry

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.