Rest of World Design System
Overview
This design system documents the visual language of a browser security challenge interface—a deliberately stripped-down surface that communicates trust through extreme restraint. The entire composition reduces to three elements: a headline, a reassurance subtext, and a rotating spinner indicator. There are no navigation bars, no footers, no decorative flourishes, no brand marks. The philosophy is one of institutional transparency: the page exists to perform a function, and its visual austerity reinforces that the process is mechanical, neutral, and safe.
The color story is nearly monochromatic. The canvas is pure white ({colors.canvas}), the ink is a warm-leaning near-black ({colors.ink} at #111516), and the only chromatic departure is the indigo spinner ({colors.accent}) that signals active processing. This single accent color does double duty: it draws the eye to the only animated element while subtly evoking the technology/security domain through its cool violet undertone. Typography relies entirely on Helvetica Neue—a choice that reads as default, system-native, and therefore trustworthy. No custom typefaces, no variable font experiments, no letter-spacing theater. The hierarchy is established through size differential (32px headline vs 16px body) and a modest weight bump (500 vs 400).
Shape language defaults to soft corners ({rounded.DEFAULT} at 8px) wherever containers appear, though the spinner itself uses a perfect circular clip ({rounded.full} at 50%) appropriate to its geometry. Spacing is generous and mathematically regular—the challenge card breathes with {spacing.xl} (32px) internal padding, and vertical rhythm between elements follows multiples of 8px. Elevation is virtually absent; the page lives in a single z-plane with no drop shadows, no border treatments, no layer separation. This flatness is intentional—it eliminates any visual hierarchy that might suggest hidden elements or deceptive UI patterns.
Key Characteristics:
- Canvas is pure
{colors.canvas}(#ffffff) with no gradient washes, textures, or tints. - Primary brand voltage lives exclusively in
{colors.accent}(#6366f1) applied to the spinner indicator. - Typography is a single-family system using
{typography.display-lg}(32px/500) for headlines and{typography.body-md}(16px/400) for all supporting text. - Corner rounding defaults to
{rounded.DEFAULT}(8px); only geometric primitives (spinners, avatars) use{rounded.full}(50%). - Spacing follows an 8px base unit with
{spacing.xl}(32px) as the standard container inset. - No elevation model—all surfaces are flat against
{colors.canvas}. - The only animated element is the
{component.spinner}, which rotates continuously via CSS keyframes. - Color contrast ratios exceed WCAG AAA for all text-on-background pairings by wide margins.
Colors
Brand & Accent
- Primary (
{colors.primary}— #111516): Near-black ink used for the main headline and any high-emphasis text. Functions as both text color and darkest brand anchor. - Primary Active (
{colors.primary-active}— #000000): Pure black reserved for pressed/active states on primary buttons. - Accent (
{colors.accent}— #6366f1): Indigo-500 tone used exclusively for the spinner indicator. This is the sole source of brand color on the page. - Accent Dim (
{colors.accent-dim}— #a5b4fc): Lighter indigo used for the spinner track/background arc where applicable.
Surface
- Canvas (
{colors.canvas}— #ffffff): Pure white background of the entire viewport and the challenge card interior. - Surface Soft (
{colors.surface-very-soft}— #f9fafb): Barely perceptible off-white used for hypothetical secondary card backgrounds. - Surface Strong (
{colors.surface-strong}— #f3f4f6): Light gray used for badge backgrounds, input borders in resting state, and subtle area fills.
Text & Ink
- Ink (
{colors.ink}— #111516): Darkest text value, used for the challenge heading and any text requiring maximum weight. - Body (
{colors.body}— #374151): Medium-gray used for the "This will only take a few seconds..." subtext and paragraph content. - Muted (
{colors.muted}— #6b7280): Secondary gray for captions, metadata, placeholder text, and disabled labels. - Muted Soft (
{colors.muted-soft}— #9ca3af): Lightest text-appropriate gray for tertiary information and disabled button text. - On Primary (
{colors.on-primary}— #ffffff): White text guaranteed readable atop{colors.primary}and{colors.accent}surfaces.
Hairlines & Borders
- Hairline (
{colors.hairline}— #e5e7eb): Lightest border/divider gray for subtle separators and input outlines. - Border Strong (
{colors.border-strong}— #d1d5db): Medium border gray for focused inputs and emphasized dividers.
Semantic
No explicit semantic colors (error, success, warning) were present on the challenge page. Hypothetical tokens for alert states are documented in component definitions using standard accessible red/blue backgrounds.
Typography
Font Family
The system uses a single typeface family: Helvetica Neue, with a fallback chain of HelveticaNeue, Helvetica, Arial, and finally sans-serif. This is a system-native stack that renders identically across macOS, Windows, and Linux without web font loading. Helvetica Neue carries associations of Swiss design neutrality, corporate institutionalism, and technical documentation—appropriate for a security verification context where the goal is transparency over personality. Both headline and body text share this family; hierarchy is achieved through size and weight alone, not through contrasting typefaces.
Hierarchy
| Token | Size | Weight | Line Height | Letter Spacing | Use |
|---|---|---|---|---|---|
| {typography.display-xl} | 48px | 500 | 1.15 | -0.02em | Hero-level headlines (hypothetical) |
| {typography.display-lg} | 32px | 500 | 1.25 | -0.01em | Challenge page heading |
| {typography.title-md} | 20px | 500 | 1.4 | 0 | Section titles, card headers |
| {typography.body-md} | 16px | 400 | 1.5 | 0 | Challenge subtext, body paragraphs |
| {typography.body-sm} | 14px | 400 | 1.43 | 0 | Secondary body, metadata |
| {typography.caption} | 13px | 400 | 1.38 | 0 | Footer text, timestamps |
| {typography.button} | 14px | 500 | 1.25 | 0 | Button labels, CTAs |
| {typography.label-md} | 14px | 500 | 1.4 | 0 | Form labels, table headers |
Principles
The typography system operates on modesty. Headlines stop at weight 500—never bold (700)—and the body remains at a comfortable 400. Size carries the bulk of hierarchical responsibility: the {typography.display-lg} heading at 32px is exactly twice the size of the {typography.body-md} body at 16px, creating a clear visual tier without resorting to weight extremes. Letter spacing is effectively neutral (0 or micro-negative values of -0.01em to -0.02em) to preserve Helvetica's native proportions; tracking is never expanded for stylistic effect.
Line heights follow typographic convention: tighter for display sizes (1.15–1.25) to keep multi-line headlines cohesive, and relaxed for body (1.5) to ensure readability at 16px. The system trusts size and color value—not weight, case transformation, or italic—to establish emphasis. If a word needs emphasis within body text, it receives {colors.ink} rather than <strong> treatment. Uppercase is absent entirely from the observed UI.
Note on Font Substitutes
Helvetica Neue is proprietary to Apple and may not render correctly on all Windows configurations or open-source systems. For implementations requiring free alternatives, substitute with Inter (Google Fonts) which shares Helvetica's humanist-grotesque skeleton, identical x-height proportions, and a comprehensive weight range. Define via CSS:
:root {
--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
Inter provides a near-identical optical size at 16px body copy and matches the 500-weight headline appearance of Helvetica Neue without licensing constraints.
Layout
Spacing System
- Base unit: 8px (all spacing values derive from this multiple).
- Tokens:
{spacing.xxs}(2px) for micro-adjustments;{spacing-xs}(4px) for inline gaps;{spacing.sm}(8px) for tight element spacing;{spacing.md}(16px) for standard padding;{spacing.lg}(24px) for card interiors;{spacing.xl}(32px) for the challenge card wrapper;{spacing.section}(80px) for major vertical bands. - Section padding (vertical):
{spacing.section}(80px) — used for hypothetical hero and CTA band sections beyond the challenge view. - Card internal padding:
{spacing.xl}(32px) on{component.challenge-card};{spacing.lg}(24px) on generic{component.card}variants. - Gutters: Not applicable in the single-column challenge layout; horizontal margins are handled by auto-centering with max-width constraint.
Grid & Container
The challenge page uses a single centered column with no grid system. Content is constrained to approximately 480–600px maximum width and positioned at the vertical and horizontal center of the viewport via flexbox centering (display: flex; align-items: center; justify-content: center). There are no multi-column layouts, sidebars, or rail structures on the observed page. For hypothetical expanded layouts (article pages, dashboards), a 12-column grid with 24px gutters and a 1200px max-width container would be consistent with the spacing scale.
Whitespace Philosophy
Whitespace is abundant and asymmetric. The challenge card occupies roughly 40% of the viewport height, leaving 30% whitespace above and below. This distribution signals that the page is a momentary interstitial—a waiting room—rather than a destination. The system refuses density: there are no compact tables, no multi-field forms, no information-dense panels. Every element has room to breathe, reinforcing the message that nothing is being hidden or rushed.
Header Architecture
No header/navigation is present on the challenge page. For reference, a hypothetical header would follow this structure:
+------------------------------------------------------------------+
| [Logo] Nav Items [Utility] |
+------------------------------------------------------------------+
| max-width: 1200px |
+------------------------------------------------------------------+
Hero Section
The challenge page itself functions as a hero-level layout:
+------------------------------------------------------------------+
| |
| |
| +------------------------------------+ |
| | | |
| | Checking your browser | <- h1 |
| | (display-lg, 32px, ink) | |
| | | |
| | This will only take a few | <- p |
| | seconds... | (body-md)|
| | | |
| | ◌ | <- spin |
| | (spinner, 40px) | |
| | | |
| +------------------------------------+ |
| |
| |
+------------------------------------------------------------------+
Vertical rhythm: 32px below heading → body text → 32px below body text → spinner.
Elevation & Depth
| Level | Treatment | Use |
|---|---|---|
| 0 (Flat) | No shadow, no border | Challenge card, page background |
| 1 (Hairline) | 1px solid {colors.hairline} | Dividers, input outlines |
| 2 (Soft) | {extensions.shadows.sm} | Hypothetical elevated cards |
| 3 (Modal) | Overlay {colors.modal-content} + {extensions.shadows.md} | Dialog boxes |
The observed page operates entirely at Level 0. There are no drop shadows, no border treatments on the challenge card, and no layer separation between the card and the canvas background. This flatness is deliberate: the challenge interface must appear inseparable from the browser chrome itself, suggesting it is a native system dialog rather than a web page artifact. Depth, when needed in hypothetical expansions, should remain subtle—cool-toned shadows at low opacity (4–8% black), never colored or dramatically offset.
Decorative Depth
None observed. No gradient washes, no photographic backgrounds, no pattern overlays, no glassmorphism effects. The canvas is {colors.canvas} at 100% opacity throughout.
Shapes
Border Radius Scale
| Token | Value | Use |
|---|---|---|
| {rounded.sm} | 4px | Small badges, tag elements |
| {rounded.DEFAULT} | 8px | Buttons, inputs, cards |
| {rounded.md} | 8px | Alias for DEFAULT |
| {rounded.lg} | 12px | Elevated cards, panels |
| {rounded.xl} | 16px | Modal dialogs, large containers |
| {rounded.full} | 50% | Spinner, avatar circles |
| {rounded.pill} | 9999px | Pills, full-round tags |
The radius vocabulary is conservative. Most interactive elements land at 8px—the sweet spot between friendly (not sharp) and serious (not playful). Only truly circular elements (the spinner) warrant {rounded.full}.
Photography Geometry
Not applicable—no images present on the challenge page. For hypothetical image integration: photographs would use {rounded.lg} (12px) corners, 4:3 or 16:9 aspect ratios, and no border treatments. Full-bleed imagery would be edge-to-edge with zero radius.
Components
No hover states documented. Hover behavior is unreliable to extract from a single screenshot. State variants live as separate entries in the
components:frontmatter (e.g.{component.button-primary-active},{component.text-input-focus}); add hover styling at implementation time per your stack's conventions.
Core Challenge Components
{component.challenge-page} — The root viewport container occupying 100vh × 100vw. Background {colors.canvas}, uses flexbox centering to position {component.challenge-card} at the exact midpoint. No scroll overflow; the page is designed to fit without scrolling on any viewport ≥480px tall.
{component.challenge-card} — The central content wrapper, visually invisible (transparent background matching canvas, no border, no shadow). Contains the headline, subtext, and spinner in vertical flow. Padding {spacing.xl} (32px) on all sides creates the internal breathing room. Max-width approximately 520px.
{component.challenge-heading} — The "Checking your browser" H1 element. Uses {typography.display-lg} (32px/500) in {colors.ink}. Vertical padding of {spacing.md} above and {spacing.sm} below establishes rhythm. No underline, no text transform, no decoration.
{component.challenge-body-text} — The "This will only take a few seconds..." paragraph. Uses {typography.body-md} (16px/400) in the softer {colors.body} gray. Padding {spacing.xl} (32px) below separates it from the spinner. Text-align center.
{component.spinner} — The rotating loading indicator. Rendered as a circular SVG or bordered element at 40×40px ({component.spinner}). Border/color is {colors.accent} (#6366f1). Animated via CSS @keyframes rotate with linear easing over approximately 1000ms per revolution. Uses {rounded.full} (50%) to form a perfect circle.
{component.spinner-track} — The faint background arc behind the spinner (where applicable). Color {colors.accent-dim} (#a5b4fc), same 40×40px dimensions, providing contrast so the active accent arc is visible.
Interactive Elements
{component.button-primary} — Solid dark button with {colors.primary} background and {colors.on-primary} text. Type {typography.button} (14px/500), padding 10px 20px, corners {rounded.DEFAULT}. Appears nowhere on the challenge page but defined for post-verification CTAs. State variant: {component.button-primary-active} darkens to {colors.primary-active} (#000000).
{component.button-secondary} — Outlined or ghost button variant. Transparent or {colors.canvas} background, {colors.primary} text, thin border in {colors.hairline}. Same dimensions and type as primary.
{component.button-accent} — Accent-colored button using {colors.accent} background with {colors.on-primary} text. Reserved for high-emphasis actions in post-challenge flows.
{component.text-input} — Standard text entry field. {colors.canvas} background, 1px {colors.hairline} border, {colors.ink} text, height 44px, padding 10px 14px, corners {rounded.DEFAULT}. Focus state {component.text-input-focus} shifts border to {colors.border-strong} or accent ring.
{component.link} — Inline text link in {colors.body}, underlined on hover. Hover state {component.link-hover} shifts to {colors.primary}.
Container Components
{component.card} — Generic content card with {colors.surface-soft} background, {spacing.lg} padding, {rounded.lg} corners. Used for article previews, setting groups, or informational blocks.
{component.card-elevated} — Variant with {colors.canvas} background plus {extensions.shadows.md} shadow for floating panel effect.
{component.badge} — Small status pill. {colors.surface-strong} background, {colors.muted} text, {typography.caption}, {rounded.pill} shape, tight padding 4px 10px.
{component.divider} — Horizontal rule, 1px height, {colors.hairline} color, full-width within parent container.
{component.footer} — Page footer region. {colors.canvas} background, {colors.muted} text in {typography.caption}, generous {spacing.xl} vertical padding.
Band Components
{component.hero-band} — Full-width hero section. {colors.canvas} background, centered content up to 1200px, {spacing.section} vertical padding. Would host {typography.display-xl} headline.
{component.cta-band} — Call-to-action section with {colors.surface-soft} tinted background to differentiate from adjacent content. Same padding as hero.
Alert Components
{component.alert-info} — Informational alert banner. Light blue background (#eff6ff), dark blue text (#1e40af), {typography.body-sm}, {rounded.DEFAULT} corners.
{component.alert-error} — Error state alert. Light red background (#fef2f2), dark red text (#991b1b).
Overlay Components
{component.modal-overlay} — Semi-transparent backdrop (rgba(0,0,0,0.4)) covering the full viewport behind a modal dialog.
{component.modal-content} — The modal dialog itself. {colors.canvas} background, {rounded.xl} corners, {spacing.xl} padding, {extensions.shadows.md} shadow.
Do's and Don'ts
Do
- Do center the challenge card vertically and horizontally using flexbox—this is the defining spatial gesture of the interface.
- Do use
{typography.display-lg}at exactly 32px/500 for the primary heading; do not inflate it to 40px+ or bold (700). - Do reserve
{colors.accent}(#6366f1) exclusively for the spinner or verified-success indicators; it should never appear as static text or background color on the challenge page. - Do maintain
{spacing.xl}(32px) minimum internal padding on the challenge card—anything tighter feels cramped and suspicious. - Do keep body text at
{colors.body}(#374151) rather than{colors.ink}; the lighter gray signals secondary information appropriately. - Do use
{rounded.full}(50%) for the spinner and any circular icon containers—never square off rotating indicators. - Do ensure the spinner animates with
lineareasing (notease-in-out) so rotation speed appears constant and reassuring. - Do set
min-height: 100vhon the body to prevent scroll on short viewports—the challenge must feel like a modal overlay, not a page. - Do define the font stack as
"Helvetica Neue", HelveticaNeue, Helvetica, Arial, sans-serifin that exact order for cross-platform consistency. - Do leave the canvas at
{colors.canvas}(#ffffff) with no texture, gradient, or tint—even a 1% gray wash would undermine the clinical clarity.
Don't
- Don't add a logo, branding mark, or site name to the challenge page—the anonymity is intentional and builds trust.
- Don't introduce drop shadows or borders to the challenge card—it must appear painted directly onto the browser background.
- Don't use any weight heavier than 500 in the typography system; Helvetica Neue at 600+ looks aggressive and commercial.
- Don't substitute Inter or system-ui for Helvetica Neue in the primary definition unless licensing requires it—the visual weight difference matters at 32px display size.
- Don't add a progress bar, percentage counter, or time estimate alongside the spinner—the indefinite spinner communicates "working" without creating false expectations about duration.
- Don't allow the challenge card to become scrollable on mobile—if content overflows, reduce font size or padding before introducing scroll.
- Don't apply
{colors.primary}as a background fill on any element larger than a button; it's too heavy for cards or bands in this restrained palette. - Don't round the challenge card corners beyond
{rounded.DEFAULT}(8px)—larger radii (16px+, 24px+) read as playful/app-like, inappropriate for a security interface. - Don't add hover effects to the spinner—it should rotate continuously regardless of pointer position.
- Don't introduce additional colors (greens, oranges, brand palettes) into the challenge flow; the monochrome + accent restriction is total.
Motion & Animation
Transition Tokens
--transition-spinner: all 1000ms linear;
--transition-default: all 150ms ease-out;
Only two transition patterns were detected. The spinner uses an unqualified all transition with 1000ms duration and linear easing, mapped to a rotate keyframe that spins the element 360 degrees continuously. Any UI transitions (focus rings, hover lifts) would reasonably use a 150ms ease-out curve consistent with the system's understated motion philosophy, though none were explicitly present on the static challenge page.
Keyframe Animations
rotate— Continuous 360° clockwise rotation applied to the{component.spinner}element. Linear timing function ensures constant angular velocity. Duration approximately 1000ms, infinite iteration count.
Interaction Patterns
- Spinner rotation: The
{component.spinner}rotates indefinitely at constant speed, signaling ongoing background processing (browser verification, CAPTCHA solving). - Focus indication: Hypothetical focus states on inputs would show a 2px outline in
{colors.accent}with{extensions.shadows.sm}offset, transitioning over 150ms. - Page transition: On challenge completion, the page would likely fade or swap content via JS-driven DOM replacement rather than CSS transition—no exit animation was detectable in the static markup.
No parallax, scroll-triggered fades, hover-lift transforms, or spring physics were observed. The motion level is classified as subtle: functional feedback only, zero decorative animation.
Imagery Style
- No photography, illustration, or rendered imagery appears on the challenge page. The visual vocabulary is purely typographic and geometric (text + spinner).
- The spinner is a constructed SVG/CSS primitive—a stroked arc or bordered circle—not a raster graphic or illustration file.
- In hypothetical post-challenge pages (articles, landing pages), imagery would likely follow a documentary/photojournalistic style consistent with Rest of World's editorial mission: environmental portraiture, street photography, documentary shots with natural lighting.
- Image treatment would likely favor full-bleed or wide-format (16:9) presentations with
{rounded.lg}(12px) corner softening, avoiding stock-photo aesthetics, filters, or heavy color grading. - No gradient overlays, duotone treatments, or text-on-image hero compositions were evident—type sits on solid
{colors.canvas}backgrounds exclusively.
Icon System
- Library: Custom SVG. No icon library (Lucide, Heroicons, Material) was detected in the framework analysis. The spinner is a hand-crafted SVG or CSS-border construct.
- Specific icons observed: Only the spinner/loading indicator—a partial circular arc (approximately 270° of a circle) in
{colors.accent}. - Treatment: Stroke-based rendering (the spinner is a stroked path/border, not filled). Color is
{colors.accent}(#6366f1) set tocurrentColorwhere applicable. Size is 40×40px. Alignment is center-relative to the text column above it. - For hypothetical icon needs (navigation arrows, social links, utility icons), recommend Lucide React or Heroicons (outline style, 24px default, stroke-width 2) as they match the stroke-based, lightweight aesthetic of the existing spinner.
Recommended Frontend Stack
- Framework: Next.js (App Router) or vanilla HTML/JS for challenge page specifically
- Styling: Vanilla CSS or CSS Modules (no Tailwind detected; classnames absent)
- Fonts: System font stack only (Helvetica Neue via OS bundling, no web font loading)
- Animation: Vanilla CSS @keyframes for spinner; Framer Motion for post-challenge page transitions
- Icons: Custom SVG for spinner; Lucide (outline) for any added UI icons
- Component lib: None (challenge page is unstyled HTML/CSS directly)
The challenge page appears to be served as raw HTML (possibly from a CDN edge function like Cloudflare's challenge system) with inline styles or a minimal stylesheet. No build tooling, framework markers, or CSS preprocessing was detected. For production implementations of this design system, Tailwind CSS would map naturally to the 8px spacing grid and token architecture, but the reference implementation is deliberately framework-agnostic.
Responsive Behavior
Breakpoints
| Name | Width | Key Changes |
|---|---|---|
| Mobile | < 640px | Challenge card width 100% with {spacing.md} horizontal padding; spinner scales to 32px; heading reduces to 26px (not a defined token, ad-hoc override) |
| Tablet | 640–1024px | Card max-width 480px; full token values apply |
| Desktop | > 1024px | Card max-width 520px; centered in viewport |
Touch Targets
{component.button-primary}: 44px height (via padding10px 20px+ line-height) meets WCAG AAA minimum.{component.text-input}: Explicitly 44px height—passes touch target requirements.{component.spinner}: 40×40px—below 44px recommendation but acceptable for non-interactive indicators. Consider enlarging to 44px on mobile if tap confusion is possible.
Collapsing Strategy
- The challenge card has no multi-column layout to collapse—it is inherently single-column and center-aligned.
- On viewports narrower than 375px,
{spacing.xl}(32px) card padding should reduce to{spacing.lg}(24px) to prevent excessive margin consumption. - The spinner should scale proportionally: 40px desktop → 36px tablet → 32px mobile, maintaining visual balance with the heading.
- Font size of
{typography.display-lg}(32px) could clamp to 26px below 375px viewport width usingclamp(26px, 5vw, 32px).
Image Behavior
Not applicable—no images on challenge page. Future imagery should use width: 100%; height: auto; object-fit: cover; with aspect-ratio constraints and {rounded.lg} border-radius.
Iteration Guide
- Build the challenge page as a single centered flex container (
min-height: 100vh) with a child card element. Pull every color, font size, and spacing value from the YAML frontmatter via{section.token}paths—never hardcode#111516or32pxinline. - Implement the
{component.spinner}as a CSS-only element (border-radius 50%, border-top-color{colors.accent}, other borders{colors.accent-dim}or transparent) withanimation: rotate 1s linear infinite. Test that rotation is smooth and constant at 60fps. - Set typography using the exact font stack:
"Helvetica Neue", HelveticaNeue, Helvetica, Arial, sans-serif. Verify that the heading renders at 500 weight (medium, not bold) and the body at 400 (regular). - Add state variants (
-active,-disabled,-focus) for buttons and inputs per your stack's conventions. The spec documents Default and Active/Pressed only; hover is your decision. - When extending beyond the challenge page (adding nav, articles, footer), decide whether new components belong to the Challenge dialect (minimal, centered, monochrome) or an Editorial dialect (which may introduce surface colors, shadows, richer imagery).
- Variants of existing components always become separate frontmatter entries (
button-primary-active, never nested insidebutton-primary.states.active). - Run
npx @google/design.md lint DESIGN.mdafter edits—broken-ref,contrast-ratio, andorphaned-tokenswarnings flag missing or mismatched tokens automatically. - When in doubt about emphasis: increase size before increasing weight; prefer
{colors.ink}over{colors.primary}for text; keep{colors.accent}reserved for the single animated element.
Font Setup: If Helvetica Neue is unavailable, substitute Inter from Google Fonts via <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap"> and define --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif.
Known Gaps
- Hover state styling: Per the no-hover policy, all interactive elements lack hover documentation. Implement hover as intermediate between Default and Active (e.g., slight darken or opacity shift).
- Loading/error states: The challenge page shows only the "checking" state. Timeout errors ("Verification failed, please retry"), network offline states, and success/completion transitions are not represented.
- Form validation: No error messages, inline validation styling, or input formatting (email, phone) were present to document.
- Post-challenge redirect: What happens after verification completes (fade-out? hard navigation? slide-up confirmation?) is unknowable from the static screenshot.
- Accessibility announcements: Screen reader behavior for the spinner (role="status", aria-label="Verifying") is assumed but not confirmed in the extracted markup.
- Dark mode variant: While
extensions.modeis documented as "dark", the visual evidence shows a light canvas. A true dark mode inversion (canvas →{colors.ink}, text →{colors.canvas}) was not observable. - Brand extension: The Rest of World publication likely has a much richer design language for its editorial content (article pages, category indexes, author bios). This spec captures only the security interstitial—a tiny subset of the full brand system.
- CSS variable naming: No CSS custom properties (e.g.,
--color-primary) were detected in the source. Implementation should introduce these as a layer above hardcoded values for themability. - Internationalization: No RTL (right-to-left) or CJK (Chinese/Japanese/Korean) typographic adjustments were considered. The Helvetica stack handles Latin scripts well but may need Noto Sans fallbacks for global deployment.