01

Color tokens

Base
–wp–preset–color–base
#faf9f7 · page bg
Contrast
–wp–preset–color–contrast
#1a1a1a · body text
Subtle
–wp–preset–color–subtle
#f0ede8 · dividers, code bg
Muted
–wp–preset–color–muted
#6b6560 · captions, meta
Accent
–wp–preset–color–accent
#2c5f6e · –studio-teal · links, em on paper, buttons
Hero stake
–studio-hero-stake
#a8dce8 · italic H1 on dark mesh heroes
Teal light
–studio-teal-light
#3d7a8c · hover / secondary accent
Cream
–studio-cream
#f3efe8 · gr-story–cream bg
Ink
–studio-ink
#0e1a1f · dark section bg
02

Type scale

Display
–studio-display
clamp(2.75rem, 5.5vw, 4.5rem)
Fraunces · weight 300
Claim-driven design
H1 · x-large
fluid 1.75→2.5rem
Fraunces serif
margin-bottom: spacing–40

A trustworthy mirror

H2 · large
fluid 1.25→1.75rem
Fraunces serif
margin-top: spacing–55

Ground truth lives on a sheet

H3 · medium
fluid 1→1.125rem
Fraunces serif
margin-top: spacing–45

Human review is architecture

Body · medium
fluid 1→1.125rem
Source Sans 3 · lh 1.55
default prose
No reservation API. The Forest Service runs a first-come signup clipboard at HQ. Overclaiming availability would erode trust faster than no app at all.
Small
0.875rem
Source Sans 3
nav · captions · tags
Caption · nav · metadata · byline · badge · tag
Section kicker
.gr-section-kicker
0.72rem · uppercase · ls 0.16em
Source Sans 3 · weight 600

01 — Problem

light variant (on dark)

Studio section label
.studio-section-label
Same metrics as kicker
used outside Greenridge scope
03

Spacing scale

–wp–preset–spacing–20 · 0.5rem
–wp–preset–spacing–30 · 1rem
–wp–preset–spacing–40 · 1.5rem
–wp–preset–spacing–45 · 2rem
–wp–preset–spacing–50 · 2.5rem
–wp–preset–spacing–55 · 3rem
–wp–preset–spacing–60 · 4rem
–wp–preset–spacing–70 · 6rem
05

Section patterns

Kicker + H2 + lead + CTA · light bg

01 — Problem

Ground truth lives on a physical sheet

No reservation API. The Forest Service runs a first-come signup clipboard at HQ. Overclaiming availability would erode trust faster than no app at all.

Problem discovery

Kicker + H2 + lead + CTA · dark bg

What it taught

You can’t automate authority

The model reads the sheet. The sheet is still authoritative.

Five lessons
06

Pull quote

Uncertainty is not an edge case in the product. Uncertainty is the product condition.

07

Gate teaser + password page

theme/assets/css/studio-gate.css · .studio-gate__shell · .studio-gate__tier · scripts/gate_teaser.py

A — Bridge teaser (after outline / outcome)

Intent: Continue exploring (longform + live product). Not a lock — tier chip reads Open.

Outcome headline sits above the gate on real pages.

Simulated end-of-page context

Open

Full case study

Problem discovery, process, clipboard pipeline, ML loop, design kit, four surfaces, and five lessons from a solo build — longform on the studio site.

B — Bridge overview layout · visual + gate in sticky side column

Pattern: .bridge-overview__side wraps the visual and gate as a flex column. Left column scrolls; right pins. Locked state: inline password input + request-access panel. Correct password → WP cookie → page reload → PHP renders unlocked. Toggle below switches the demo between states.

ROLEProduct Direction + MVP
SCOPE0 → Pilot
CONTEXTAerospace & defense logistics
YEARS2024
Password

Full case study

Architecture, workflow research, and positioning — password protected.

Most supply chain systems track and report. In aerospace and defense, operators need options, tradeoffs, and consequences filtered by real constraints — not another status feed.

I worked with the founding team to translate deep operational expertise into product direction: decision intelligence built around constraints, viable scenarios, and pilots validated against decisions operators had actually faced.

C — Homepage gate · below-hero first-visit CTA

Intent: Single unlock entry point on the homepage — enter the password once and all bridge gates stay open (localStorage). Dismiss (×) hides it for the session only (sessionStorage). Hidden entirely once unlocked via localStorage or when password was entered on any bridge page. Rendered server-side (PHP hidden); homepage-gate.js shows it when neither unlocked nor dismissed. Uses .studio-bridge-gate-rail for content-column alignment (same as hoisted bridge gates) with white background.

theme/inc/homepage-gate.php · theme/assets/js/homepage-gate.js · theme/assets/css/work-bridge.css · [data-hp-gate]

Portfolio

Full case studies

Enter the portfolio password once to unlock all gated case studies.

D — Password entry (/full/) · task-first .studio-gate__shell–entry

Locked: hero + excerpt visible; body shows gate form. Unlocked: same hero; post_password cookie set — full post-content renders (no .cs-gate).

← Amtrak

Password

Full case study

The complete narrative — research, decisions, and outcomes — is available with password or on request.

09

Device frame

gr-device-frame — phone chrome applied via ::before/::after

160px (thumbnail)

Map screen

200px (story section)

Sites list

260px (showcase tile)

Clipboard capture
10

Glance grid + stack table

gr-glance__grid — dt/dd at-a-glance

Role
Product design · UX writing · design system · full-stack · ops
Stack
React · Vite PWA · Node · Cognito · Claude · Lightsail
Status
Live PWA · iterative field hardening

gr-stack__table — approach table

ClientVite + React PWA
APINode/Express · Cognito
VisionClaude multimodal + admin review
DeployLightsail · Capacitor shell
10

Home hero

hero-interactive · / · min-height capped in kit (production: min(88vh, 920px)) · doors/explore need home-hero.js

Full-process product design for consequential systems.

Shaping products — where getting it wrong matters.

Domain doors + explore panels: interactive on homepage only.

11

About hero

studio-hero · alignfull · 58/42 split · page-about.html

Complex products for expert users. Users in the iteration loop.

Product design · honest user feedback · prototypes that ship · Bristow, VA / remote

Christopher Mullins
12

Work bridge hero

/work/{engagement}/ · hero in page content · .wp-site-blocks > .studio-hero–video · cluster-hero__content rail · engagement backdrop template part

Don’t pick a direction. Build the loop.

Red Cell · Trase / MyAlaska · Governed agents · 2024–2026

13

Full case study hero

/work/{engagement}/full/ · template hero sibling of <main class="studio-case"> · same backdrop + cluster-hero__content · title + excerpt (public lede) · compact min-height when password gate active

Trase — Designing the search for product-market fit

Trase had real AI capability without a defined wedge. The work was a validation loop across verticals — with MyAlaska as the flagship pilot.

15

Podcast landing hero

theme/templates/archive-podcast.html · theme/inc/podcast-landing.php · theme/assets/css/podcast.css · .studio-podcast-landing__hero · podcast.css only enqueued on is_post_type_archive(‘podcast’) and is_singular(‘podcast’) — not on other pages · artwork (140/180px sq) + blurred backdrop (blur 40px, scale 1.15) + series label / title (Fraunces 300) / tagline (Fraunces italic, #a8dce8) / description

Feedback Loupe cover art

Podcast

Feedback Loupe

The insights are mine. The hosts are not.

An occasional podcast on the frontier where AI, product design, and human creativity collide. Each episode surfaces one idea worth your attention. The hosts are fully AI-generated. The curation is not.

16

Podcast episode hero

theme/templates/single-podcast.html · theme/inc/podcast-episode.php · theme/assets/css/podcast.css + cluster-hero.css · .studio-podcast-hero · PHP render_block filter injects: backdrop div + cover art wrapper + studio-podcast-episode__hero-text wrapper into cluster-hero__content · crumb / h1 (Fraunces, clamp 2–3.25rem) / date + duration meta strip

Episode cover art

← All episodes

Designing trust in high-stakes AI systems

May 12, 2026 42 min

17

Podcast episode body components

theme/assets/css/podcast.css · .studio-podcast-episode__body · show-notes list · transcript <details> · CTA strip · episode nav · latest episode card · episode archive grid · podcast.css not loaded on design kit page — all demos use dk-pod-* classes

Show notes list — .wp-block-list inside .studio-podcast-episode__body · no-bullet · tabular-nums timestamps in teal · flex rows · bottom borders

  • 0:00 Introduction — what trust means in consequential systems
  • 4:32 Why defaults are policy decisions
  • 12:18 Field research vs. desk research — when to leave the building
  • 21:45 The co-pilot that creates cargo
  • 33:10 Wrap-up — uncertainty as the product condition

Transcript disclosure — .studio-podcast-transcript · <details> · teal uppercase summary + ▸ chevron rotates on open · scrollable body (max-height 60vh, custom scrollbar) · populated from _ssp_transcript_text post meta by render_block filter

Read transcript
Welcome to Feedback Loupe. Today we’re exploring how trust is designed — not earned through marketing, but built into the grain of an interface. When a clinician sees an AI recommendation, they don’t ask “is this correct?” first. They ask “can I explain this to my patient?” That’s the design constraint most teams miss. The question isn’t whether the model is accurate. The question is whether the person using it can maintain their own professional judgment while incorporating what the system surfaces.

Contact CTA strip — .studio-podcast-cta · injected by render_block filter via {{studio_podcast_cta}} · Fraunces left / teal link right · flex space-between · border-top divider

Interested in this kind of work?

Get in touch →

Episode nav — .studio-podcast-nav · injected via {{studio_podcast_nav}} · 3-col grid: prev / all episodes / next · empty slot for first/last episode uses span.studio-podcast-nav__link–empty · collapses to 2-col on <600px with “All episodes” on its own row

Latest episode card — .studio-podcast-landing__latest · rendered by podcast-landing.php {{studio_podcast_landing}} · section > latest-inner > latest-row · cover art (120px / 160px @641px+) + Fraunces title (margin-top: 0, flush with cover) + meta + excerpt + <audio controls preload=”metadata”> · cover from episode cover_image meta, falling back to series artwork

Designing for Uncertainty

May 4, 2026 · 19:03

Ship real code and let reality grade the idea. For one solo builder, production code is the prototype — feedback comes from the field, not a conference room.

18

Work engagement cards

theme/assets/css/work-engagement-cards.css · .work-engagement-card · video cap (16:9) + paper body · domain-colored top accent bar · used on /work/, clusters, projects hub, podcast related

19

Work domain doors

theme/assets/css/work-domain-doors.css · .work-domain-doors · 3-col paper cards with index, label, claim, meta, CTA · domain-colored top bar · /work/ hub navigation

20

Bridge lightbox

theme/assets/css/bridge-lightbox.css · theme/assets/js/bridge-lightbox.js · .studio-bridge-lightbox · full-screen overlay · teal gradient backdrop + blur + noise · panel chrome (eyebrow + close) · stage (image/video/iframe) · caption bar · trigger: .bridge-visual–zoomable

Trigger thumbnail — .bridge-visual–zoomable · zoom-in cursor · rounded · prototype variant adds play badge

Lightbox panel (static preview) — .studio-bridge-lightbox__panel · chrome bar + stage + caption

Greenridge — map view

Lightbox stage demo
Map interface showing campsite availability across the Monongahela National Forest
21

Contact form

theme/assets/css/contact-page.css · theme/assets/js/contact-form.js · theme/inc/contact-handler.php · .studio-contact-form · flat inputs · uppercase labels · teal focus ring · submit button · status messages

22

Essay page

theme/assets/css/studio-essay.css · theme/templates/single.html · .studio-essay · light header band (crumb + title + date/tags + lede) · narrow prose rail (45rem) · editorial body typography

← Essays

A co-pilot that creates cargo.

May 20, 2026 AI design

AI tools designed to assist often add work rather than remove it. The pattern is predictable — and avoidable.

The assist that isn’t one.

A community health worker visits a patient. The AI generates a care plan draft. Now someone has to review it, edit it, reconcile it with the patient’s actual situation. The draft is cargo — work that didn’t exist before the tool arrived.

The pattern repeats across domains. Every AI “assistant” that outputs text is implicitly asking someone to become an editor. That’s a role change, not a time saving.

23

Cluster navigation chips

theme/assets/css/cluster-engagements.css · .cluster-nav · teal outline chips for domain filtering · .cluster-nav__chip–all (filled dark) · .is-current state

24

Cluster switcher tiles

theme/assets/css/cluster-switcher.css · .cluster-switcher · sibling domain navigation on cluster pages · 3-col tiles · index number + name + tag · current state (dark filled) · mobile → segmented control

25

Work hub toolbar

theme/assets/css/work-hub.css · .work-hub__domain-nav · .work-hub__toolbar · domain nav pills + practice filter chips + sort control · /work/ hub

Domain nav — .work-hub__domain-nav · pill strip with “Domains” label pseudo-element

Section label + toolbar — .work-hub__section-label · .work-hub__toolbar (practice chips + sort)

Product direction Design system Research
Sort: Recent
26

Prototype overlay

theme/assets/css/prototype-overlay.css · theme/assets/js/prototype-overlay.js · .studio-prototype-overlay · full-screen modal for prototype iframes · dark chrome bar (label + close) · viewport iframe · trigger: .cs-prototype-launch button

Launch button — .cs-prototype-launch · teal fill · inside case study body

Overlay panel (static preview) — .studio-prototype-overlay__panel · dark chrome bar + viewport area

Greenridge — interactive prototype

iframe viewport — prototype loads here

27

Approach page deck

theme/assets/css/approach-page.css · theme/assets/js/approach-deck.js · .approach-deck-band · horizontal scroll deck (cream band) · .approach-slide (label + figure) · .approach-phase (border-left prose blocks) · .studio-approach-stakes (dark band) · .studio-approach-cta

Approach claim — .approach-claim · Fraunces italic · max-width 28ch

Design is a strategic function, not a service layer.

Deck slides (horizontal scroll) — .approach-deck · cream band · snap-scroll · .approach-slide (label + bordered figure)

01 — Problem framing

[slide image]

02 — Research & validation

[slide image]

03 — Design & prototype

[slide image]

Phase block — .approach-phase · border-left accent bar (desktop) · section label + prose

Start with what the business believes vs. what users actually do. Most AI products fail because the capability exists without a validated use case.

Artifacts: stakeholder map · assumption log · research brief

28

Work exemplar + artifact grid

theme/assets/css/work-exemplar.css · .work-exemplar · proof-of-craft section (Greenridge) · eyebrow + title + lead + actions · .studio-artifacts__grid · .studio-artifacts__card (kind badge + title + detail + link)

Proof of craft

Greenridge — national forest campsite tracker

Solo build. React PWA + vision pipeline + design system. Demonstrates end-to-end shipping, AI/ML integration, and design under uncertainty.

Artifact grid — .studio-artifacts__grid · cards with kind badge (public/gated) + title + detail + link

Design system Public

Component library

Buttons, cards, device frames, type scale — live on the studio site.

Interactive prototype Gated

Map & booking flow

Full prototype with live data — map, site detail, clipboard capture.

Source code Public

GitHub repository

React client, Node API, vision pipeline, deploy scripts — MIT.

29

Work console

theme/assets/css/work-console.css · theme/assets/css/hero-interactive.css · theme/parts/work-console.html · .work-console-float > .hero-interactive__console > .hero-interactive__doors · floats over hero/paper boundary on /work/ · cluster variant: theme/parts/cluster-console-*.html

Console shell — doors (inactive) — .hero-interactive__console · glass morphism dark container (rgba 10,14,16 + backdrop-filter blur 16px) · .hero-interactive__doors 3-col grid · each door: button[role=”radio”] with data-domain + data-index · index / label / meta flex column

Active door — .is-active + aria-checked=”true” · white bg (–color–base) · dark text · elevated shadow · translateY(-6px) scale(1.02) · door-index inherits contrast at 35% opacity

Cluster console variant — <a> elements (not buttons) · .is-active + aria-current=”page” on current domain · used in theme/parts/cluster-console-healthcare.html etc.

Work explore panel — .work-explore__panel (in work-console.css) · light-mode · reveals on door activate · lead italic text (.work-explore__lead) · tag chips (.work-explore__tag, teal) · cluster narrative block (border-left teal, Fraunces italic) · action link (.work-explore__cta)

Care-team AI where trust is clinical, not cosmetic.

AI Healthcare Validation Voice UI 0→1

Voice AI for community health workers — field research in week one changed the entire product direction.

Sparrow / Lorena · Savoy Life

Explore Healthcare AI →
30

PAI chat shell

PAI at /chat/ · React/Vite SPA · /var/www/html/chat/assets/ · separate from WP theme · CSS ported from index-R0xE_Wqk.css · color tokens identical to studio palette

Surface: .pc-layout wraps the full app; .pc-root centres the conversation column (max-width 720px desktop, 440px in panel mode). Color palette is the studio token set. Input row send button reuses studio teal exactly. Font: system-ui, not the studio serif/sans.

Conversation state — user + assistant bubbles · pc-msg–user / pc-msg–assistant

Ask me anything Beta

What kind of work does Chris focus on?

He focuses on AI products in high-stakes domains — healthcare, defense, civic infrastructure. Mostly 0→1 or early validation, where the product question is still open.

Is there a case study I can read?

Sparrow / Lorena is the most detailed — voice AI for community health workers. The full write-up is gated; I can help you get access.

Empty state with prompts — pc-empty · pc-prompts · shown before first message

Ask me anything Beta

Ask about Chris’s work, process, or background.

31

PAI voice input + states

voice-btn states · voice-processing-chip · pc-bubble–speaking · STT: Deepgram WebSocket · TTS: Deepgram Aura (aura-asteria-en, default) · fallback: OpenAI alloy

Voice button lives inline in .pc-input-row — not a mode switch, just an additional affordance. Six states. The speaking bubble state (pc-bubble--speaking) is separate: it activates on the assistant bubble while TTS is reading the response aloud.

Input row states

Idle

Connecting — voice-btn–connecting

Listening — voice-btn–active

Processing — voice-processing-chip

Transcribing…

Muted — voice-btn–muted

Error — voice-btn–error

Speaking bubble — pc-bubble–speaking · assistant bubble border shifts to #a8c5cc while TTS is reading the response aloud. Only the currently-speaking bubble is highlighted; prior turns remain #ddd8d1.

Tell me about the Sparrow project.

That’s a voice AI for community health workers in the field — the core challenge was documentation burden.

What made it hard?

The workers were doing home visits without reliable connectivity, so the design couldn’t depend on real-time sync…

32

PAI prompt pills + access flow

pc-prompt-pill · pc-prompt-pill–unlock · pre-conversation affordance · unlock pill triggers portfolio gate flow → localStorage.studio_gate_unlocked → BroadcastChannel(‘pai-portfolio-unlock’)

Prompt pills are shown before a visitor types anything — starter questions that scaffold the first turn. The unlock variant (pc-prompt-pill--unlock) appears when the assistant surfaces portfolio access. Tapping it routes into the gate flow: the assistant prompts for the password or offers request-access.

Standard pills — pc-prompt-pill

With unlock pill — pc-prompt-pill–unlock · muted border (#b5afa8) + muted text (#5a5550) · appears contextually when visitor has shown interest in full case studies

What the unlock pill triggers: assistant initiates the gate flow — prompts for the portfolio password or offers request-access. On successful unlock: writes localStorage.studio_gate_unlocked = "1", broadcasts { type: 'pai-portfolio-unlocked' } on BroadcastChannel('pai-portfolio-unlock'), and auto-submits the WP password form in an iframe (setting the wp-postpass cookie). Gate components on all open bridge pages transform to unlocked state without reload. See docs/GATE_SYSTEM.md — PAI integration.
33

PAI panel navigation

pc-panel-col · pc-panel-sidebar · triggered when assistant surfaces structured project/cluster content · desktop: right column slides in · mobile: bottom sheet (78dvh) animates up

Panel mode activates when the assistant answers a question about a specific project or cluster — adds a structured content column alongside the conversation. Conversation narrows (440px fixed); panel takes remaining width. Layout is a full shift, not an overlay.

Ask me anythingBeta

Tell me about the Sparrow project.

Sparrow was a voice AI for community health workers — here’s the full overview.

Sparrow / Lorena

Project

Voice AI for community health workers — field research in week one changed the product direction from documentation to burden removal.

Full case study →

Cluster

Healthcare AI — 2 engagements building care-team tools where trust is clinical, not cosmetic.

Healthcare AI →

Role

Product direction + design. 0→1 through pilot launch.

.pc-panel-col · flex right column · border-left: 1px solid #ddd8d1 · slides in with animation: panel-slide-in .28s ease · conversation root fixed at 440px.

34

PAI conversation voice + tone

Written register for PAI’s conversational output · source: backend communication-style-guide.service.js · condensed rules injected after first turn · error copy approach · TTS/STT infrastructure reference

Context: PAI represents Chris directly in real-time conversation. Register is conversational but not casual — engaged and knowledgeable without performing warmth or slipping into chatbot patterns. TTS output puts a premium on sentence economy: everything the assistant writes will be read aloud.

Core rules with examples

1–2 sentences per turn. Voice-friendly.

TTS reads everything aloud. No paragraphs, no bullet lists — they become unbearable to hear.

Do

Sparrow was a voice AI for community health workers — the core challenge was documentation burden in the field.

Don’t

Great question! Sparrow / Lorena was a voice AI product designed to help community health workers with their documentation workflow. Here are some key aspects of the project:
• Research-driven approach
• Field validation
• Iterative design process

Specific, not generic. Anchor to what they just said.

If the response could apply to any question from any visitor, rewrite it. “I’d be happy to help,” “great question,” “that’s interesting” are all signals to revise.

Do

The healthcare work is all high-stakes environments — the AI can’t just be useful, it has to be trustworthy to the clinicians using it.

Don’t

Great question! I’d be happy to tell you about Chris’s healthcare work. He has done a lot of interesting work in this space that you might find very valuable to learn about.

Dialogue, not interrogation. One ask per turn — or none.

Not every reply needs a question. Observations and invitations work. Never stack two questions in one turn.

Do

The Amtrak work was design system and booking flow — quite different from the AI products. Worth exploring if information architecture is what you’re looking at.

Don’t

Would you like to know more about the Amtrak project? What aspects are you most interested in? Are you looking at the design system work or more the UX research side?

No scripted acknowledgments.

Avoid: “Got it,” “Perfect,” “Thanks for sharing,” “No problem,” “No worries.” If you need to acknowledge, make it specific to what they said — not a filler phrase.

Do

Security-focused work is a different mode — classified context means most of what makes it interesting can’t be public. The cluster page has what can be said.

Don’t

Got it! That makes sense. No problem — I completely understand that you’re interested in the security work. Thanks so much for sharing that with me.

Error + edge case copy — same register as the rest of the conversation. Brief, matter-of-fact, no apology loops. Voice output makes over-apologetic errors especially grating.

Voice unavailable

Voice input isn’t available right now — type your question and it’ll work the same way.

Out of scope

That’s outside what I know — I’m focused on Chris’s work and background. Anything else I can help with?

Connection error

Couldn’t reach the server — worth a retry in a moment.

Gated content

The full case study is password-protected — I can help you get access if you’d like.

Voice identity + infrastructure

LayerChoiceNotes
STT (input)Deepgram — real-time WebSocketAPI key server-side; availability exposed via GET /api/speech/availability
TTS (output)Deepgram Aura — aura-asteria-enDefault. “Friendly and warm.” Fallback: OpenAI alloy. Per-session configurable in admin.
Available voicesDeepgram: Asteria, Luna, Stella, Athena, Hera, Orion, Arcas, Perseus, ZeusAdmin-selectable. Sesame CSM optional if SESAME_TTS_URL set in PAI .env.
LLMClaude Sonnet 4.6 — claude-sonnet-4-6Set via ANTHROPIC_MODEL in PAI backend .env
Knowledge base~4,017 JSON chunksRAG retrieval. Re-ingest via admin “sync site” after publishing new WP content.