Maison · LV × IBM · Design System
Component Library · Phase 2 — Complete

Maison Design System

Covers both the 18-screen Maison mobile prototype and the IBM × LVMH pitch microsite as one cohesive visual system. Self-initiated work — speculative, never deployed, not commissioned by Louis Vuitton. Tokens, easing, typography, all 18 screens' components, and microsite-specific patterns documented below. Color gaps flagged in the Tokens section are untokenized values hardcoded in the prototype source. (Screen count updated 2026-07-12: two cold-start client screens added — see the Content section.)

Brand Colors

All declared tokens in the app :root. The cream is the single cross-surface token shared by the app, the microsite, and the case study.

Brand accent
Cream — the only token shared across all three surfaces

Cream is the single token shared identically across all three surfaces — app, microsite, and case study — while nearly everything else only lives in one or two of them. It anchors interactive elements, brand marks, and active states throughout the app; --cream-soft is reserved for hover states and italic emphasis. --cream-dim isn't declared as a token in the app source at all — it exists only as a repeated inline rgba() value.

In the app source --cream-dim is not declared as a token — it appears inline as rgba(212,184,150,.55). The case study names it --lv-cream-soft. Declare once and replace both.
--cream
#D4B896
Primary accent · interactive elements · brand marks · active states
--cream-soft
#E8D5B7
Hover state on primary buttons · italic body emphasis
--cream-dim
rgba(212,184,150,.55)
GenAI "why" italic text · passport prose accents Reconcile with cream-soft
Background stack
Five navy layers — deepest to lightest — create depth without color contrast

The four swatches below are the app's actual screen-level background layers, from the darkest (labeled --stage here, sitting behind the phone frame itself) up to --navy-2 (tabbar and gradient stops). Card surfaces --surface and --surface-2, documented in the next block, add a fifth and sixth step above these — together the stack creates depth entirely through tonal shift within one navy family, with no separate accent color doing the work.

Correction: --stage is not a declared token in app/index.html#050818 is real (used as the real body background and the first stop of .stage's gradient) but only ever appears as a literal hardcoded hex value, never tokenized. Shown here under a descriptive label for this reference, not as a claim the app declares a --stage custom property.
--stage
#050818
Stage / outer canvas behind the phone frame
--navy-deep
#001A49
Absolute deepest in-app layer · microsite loader fill
--navy-1
#0E1430
App base background · phone screen fill
--navy-2
#14193F
Gradient second stop · tabbar · thread input background
Surfaces
Card and input elevation above the base

Cards never use a flat fill — every card gradient runs top (--surface) to bottom (--surface-2), a linear-gradient(180deg, …) that reads as a subtle physical lift rather than a color change. This is the pattern behind appointment cards, rec cards, and every other elevated panel in the app.

Cards always use a linear-gradient(180deg, var(--surface) 0%, var(--surface-2) 100%) — never a flat fill. The gradient reads as a subtle lift, not a color change.
--surface
#181D45
Card top · appointment card · rec card
--surface-2
#1F254F
Card gradient bottom · deepens card to give physicality
Lines & borders
Cream-alpha rather than white-alpha — keeps borders warm

Borders throughout the app use cream-alpha rather than white-alpha, keeping every rule and outline warm instead of cool-gray. --line is the default card and input border; --line-2 strengthens it for hover states and featured cards. --line-3 is referenced in the push banner's hover state but was never actually declared in :root — the swatch shown here is an approximation, flagged as a gap rather than papered over.

--line
rgba(212,184,150, .10)
Default card and input borders · tabbar rule
--line-2
rgba(212,184,150, .22)
Hover borders · push banner border · featured cards
--line-3
~rgba(212,184,150, .34)
Gap Used in push hover — never declared. Approximate value shown.
Text hierarchy
Cream-white alpha stack — not pure white, keeps warmth at all opacity levels

All three text tokens draw from the same warm white base (#F5F0E6) at different opacities rather than three independently chosen grays — --text for names and primary labels, --muted for metadata, --dim for inactive tab labels and section headings. On cream backgrounds (button labels, badges), text reverses to --navy-deep instead of white, since white would break the token family's warm cast.

All three text tokens draw from the same warm white base #F5F0E6. On-cream text (e.g., button labels) uses --navy-deep for reversal.
--text
#F5F0E6
Primary body text · names · primary labels
--muted
rgba(245,240,230, .62)
Secondary text · metadata · helper copy
--dim
rgba(245,240,230, .52)
Tertiary text · inactive tab labels · section headings
Semantic Colors

Three status tones — each desaturated enough to feel like they belong in the navy field, not like system alerts pasted in.

Status tones

Three semantic colors carry status meaning site-wide: --ok marks the live infra dot and authentication success, --warn covers general caution states, --alert drives the brand-defense alert strip and counterfeit signals. All three stay desaturated enough to sit inside the navy field rather than reading as a system dialog dropped on top of the UI — fills stay at 6% opacity and borders at 20%, never full saturation.

Semantic fills use rgba(token, 0.06) for tinted backgrounds and rgba(token, 0.20) for borders — never full saturation fills. This keeps alerts readable without reading as consumer UI error styling.
--ok
#9CC8A0
Live status dot · authentication success · provenance score label
--warn
#E8C28A
Caution states · secondary attention signals
--alert
#E89F8A
Brand-defense alert strip · counterfeit signal · error states
Color Gaps 4 issues

Values used throughout the prototype that are hardcoded rather than tokenized. All four appear multiple times and should be declared before the system is extended.

Sepia palette — avatar & product backgrounds
Three sepia browns used in all avatar gradients and object backgrounds. Identical values appear in app/index.html and work/lv.html but are not tokenized in either.

Three sepia browns run every avatar gradient and product-adjacent background in the app, but none of the three is declared as a CSS custom property in app/index.html — they appear only as repeated inline hex values. The same three values, slightly off, are independently redefined in work/lv.html's own --lv-sepia-* tokens, which is the reconciliation problem the block-note documents.

The case study (lv.html) independently defines --lv-sepia-deep: #2c2317, --lv-sepia-mid: #5a4830, --lv-sepia-warm: #6e5a3e. The app and case study values are close but not identical — pick one set and align.
--sepia-deep
#3a2e1f (proposed)
Avatar gradient top · wardrobe card background base
--sepia-mid
#5a4830 (proposed)
Avatar gradient bottom · viewfinder item background
--sepia-warm
#6a5538 (proposed)
Arrival ring background · client hero avatar gradient
Product showcase background
The cream-to-ivory gradient behind every product image. Used in piece hero, passport hero, wardrobe cards, and rec card images.

The cream-to-ivory gradient sits behind every product image in the app — piece hero, passport hero, wardrobe cards, and rec cards all use the identical two-stop gradient plus a radial highlight at 50% 30% to simulate ambient light falling on the piece. Like the sepia palette above, neither stop is a declared token; both are inline hex values repeated at each usage site.

Standard usage: linear-gradient(180deg, #F2EBDF 0%, #DCCFB7 100%) with a radial light bloom at 50% 30% and a hatching overlay for atelier paper texture.
--ivory-top
#F2EBDF (proposed)
Gradient top — lighter ivory to simulate ambient light on piece
--ivory-base
#DCCFB7 (proposed)
Gradient bottom — warmer base, shadows the piece downward
--line-3 — missing border token

The push banner's hover state references var(--line-3) in the app's CSS, but --line-3 is never declared anywhere in :root — the property silently falls through to its initial value, so the hover border currently renders as if no border-color were set at all. This panel documents the exact failure and proposes a value one step brighter than --line-2.

Gap: The push banner hover state references var(--line-3) but this token is never declared in :root. The push hover border currently renders with no value (falls through to initial). Proposed value: rgba(212,184,150,0.34) — one step above --line-2.
--cream-soft / --cream-dim discrepancy

The app and the case study each solved “a slightly lighter cream for emphasis” independently and arrived at two different answers: the app's --cream-soft is a solid, opaque lighter cream (#E8D5B7), while the case study's --lv-cream-soft is a semi-transparent overlay (rgba(212,184,150,.55)). Both get used for emphasis text, but a solid fill and a transparent overlay behave differently depending on what sits behind them.

Recommended: keep --cream-soft as the solid hover value. Add --cream-overlay: rgba(212,184,150,.55) explicitly for transparency use cases.
Gap: The app declares --cream-soft: #E8D5B7 (a solid lighter cream). The case study independently defines --lv-cream-soft: rgba(212,184,150,.55) (a semi-transparent cream). Both are used for emphasis text, but they produce visually different results against dark backgrounds. Pick one semantics: solid lighter cream for hover/emphasis, transparent cream for overlay text.
Cross-Surface Tokens

How the app and microsite token systems relate. The microsite uses a 3rd-party template with its own naming convention; the app uses a custom system. Only cream bridges them natively.

App ↔ microsite convergence

The microsite runs on a third-party marketing template with its own token-naming convention, so of the ten visual roles in this table only cream and the Radikal typeface are genuinely shared between app and microsite — everything else either diverges or exists on only one side. Rows marked “App only” (the ok semantic, the sepia palette) are real product tokens the template has no equivalent for; rows marked “Microsite only” (loader orange, case-study amber) are presentation choices native to the editorial surfaces.

The microsite is built on a marketing template and diverges significantly from the app's token system. The cream color and Radikal typeface are the only native bridges. For a fully cohesive system, the microsite would need a custom token override layer that adopts the app's navy and text values.
Visual roleApp tokenMicrosite tokenStatus
Brand accent --cream (#D4B896) --accent--dark: #D4B896 (override) ✓ Shared
Typeface Radikal (300–700) Radikal (100–900) + italics ✓ Shared
Navy deep --navy-deep (#001A49) loader fill #001a49 ✓ Shared (inline only)
Background --navy-1 #0E1430 --base--dark #161616 (template default) ≠ Diverges
Body text --text #F5F0E6 --t-bright--dark #FFFFFF ≠ Diverges
Secondary text --muted rgba(245,240,230,.62) --t-medium--dark #ACACAC ≠ Diverges
Semantic ok --ok #9CC8A0 None App only
Sepia palette #3a2e1f / #5a4830 (inline) None App only
Orange loader None #ff9933 (loader bg only) Microsite only · intentional
Amber eyebrow None --amber #C4892A (case study) Case study only · not in app
Typography

Radikal is the only typeface in the system — one face carries everything from ultra-thin display to heavy eyebrow labels. Letter-spacing is the primary lever for expressing hierarchy.

Weight range
300–700 in the app · 100–900 with italics in the microsite

Radikal alone carries every register in the system, from a 300-weight 36px welcome headline down to a 600-weight 9px badge label, with letter-spacing doing the work of distinguishing hierarchy rather than switching typefaces. All ten rows trace directly to real screen usage — the Welcome h1, ceremony h2, screen titles, card labels, and body copy sizes are the actual values pulled from app/index.html, not a generic type scale.

Uppercase labels use letter-spacing as the hierarchy signal — not size. An eyebrow at 0.24em reads as more deliberate than one at 0.10em, even at the same size. The app's smallest legible tracking is 0.10em (metadata).
Companion
for the floor.
36px · wt 300
ls −0.025em
Welcome h1
Mme. Élise Laurent
has arrived.
28px · wt 300
ls −0.020em
Ceremony h2
Welcome, Camille
22px · wt 400
ls −0.010em
Section h2 / auth title
Client History
17px · wt 500
ls −0.005em
Screen title
Mme. Élise Laurent
14px · wt 500
ls 0em
Card primary label
One product. Two readers. The bag's story, owned by your client — guided by you.
13px · wt 300
lh 1.55
Body copy
She is at the door with a companion.
12px · wt 300
Secondary body
Louis Vuitton
11px · wt 500
ls 0.14em · caps
Chip label
Recently
10px · wt 500
ls 0.20em · caps
Section heading
Arriving
9px · wt 600
ls 0.24em · caps
Badge / eyebrow
Easing

One primary curve runs the entire system — sine-in-out. Click any row to see the ball travel the track at that curve. All demos use identical duration and distance so only the shape varies.

Named easing curves

Sine in-out (cubic-bezier(0.37, 0, 0.63, 1)) is scoped to a single interaction — the bag-react glow — because it eliminates abrupt starts and stops so that pulse reads as weight rather than a UI snapping into place. The scan sweep and loader fill use plain ease-in-out/ease, not this curve; each curve documented here is scoped to one specific interaction rather than being an interchangeable alternate. Click any row to see the actual curve shape animate at equal duration and distance.

Every curve here is a custom cubic-bezier — nothing from a browser default — which keeps transitions feeling authored rather than stock. Sine-in-out (0.37, 0, 0.63, 1) is real but single-use: it's bag-react's glow pulse only. The scan sweep (scan-sweep/scan-shine) and loader fill use the generic ease-in-out and 0.6s ease respectively — not this curve. Correction: "Spring" and "Veil" are both real, but sourced from the case study (work/lv.html), not app/index.html — the app itself doesn't use either curve. "Spring" is .lv-motion-trigger's hover transform (the case study's own motion-lab play button); "Veil" is the case study's page-transition veil.
Sine in-out
var(--ease-sine) = cubic-bezier(0.37, 0, 0.63, 1)
App: bag-react glow only. Also drives the case study's own motion suite (scan/loader/tile, work/lv.html).
Out Quint
var(--ease-out-quint) = cubic-bezier(0.22, 0.61, 0.36, 1)
Screen slide (translateY) — forward/back navigation
Out Cubic
var(--ease-out-cubic) = cubic-bezier(0.33, 1, 0.68, 1)
Screen opacity fade — slightly snappier than slide
Weighted finish
var(--ease-weighted) = cubic-bezier(0.32, 0.72, 0, 1)
Push banner entry · Face ID progress ring
Spring
cubic-bezier(0.34, 1.56, 0.64, 1)
Case study only — motion-lab play button hover
Veil
cubic-bezier(0.76, 0.00, 0.24, 1.00)
Case study page veil / hover cursor — deliberate pause
Ease
ease
Micro-interactions: hover fills, border colors, opacity
Duration

The app has no explicit duration token set — values are inline. The pattern below documents the de-facto scale from source. Click any row to preview the fill timing.

Duration scale

The app declares no duration tokens — every transition-duration value is written inline at its call site, so this scale is reconstructed from source rather than read off a token list. Durations span two full orders of magnitude, from 120ms hover fills up to 2800ms for the bee-mark ring's ambient pulse; click any row to preview the actual fill timing.

No explicit duration variables are declared. Recommend tokenizing at minimum: --dur-micro: 120ms, --dur-fast: 180ms, --dur-base: 420ms, --dur-nav: 540ms, --dur-ambient: 2400ms.
120ms
Hover fills · border color · logo water-fill step
180ms
Button press transforms · tab icon opacity · most micro-transitions
240ms
Toast show/hide · cursor size changes
350ms
Motion trigger button state changes (lv.html)
420ms
Screen opacity fade · push banner entry
540ms
Screen slide (translateY) · page navigation
700ms
Easing curve ball-track demos (equal duration so curve shape is isolated)
1100ms
Tile animation demo (lv.html)
1200ms
Bag-react authenticity cycle · scan-shine luminance
1600ms
Face ID progress ring fill
2400ms
Scan sweep (continuous bounce) · dot pulse · scan demo (lv.html)
2800ms
Bee-mark ring pulse animation
Spacing

The app uses a de-facto scale from source — no spacing tokens declared. Values below document the recurring patterns.

Layout spacing

Like duration, spacing has no declared scale — every value below is a de-facto pattern pulled directly from the app's inline styles. Screen edge padding is the most consistent rule in the system: 22px on every standard screen, stepping up to 32px only on the four full-bleed ceremony screens where content needs more room to breathe; bottom padding is always 96px so content never sits under the tabbar.

Screen edge padding is consistently 22px (left/right). Ceremony screens (Welcome, Pair, Face ID, Arrival) use 32px to give full-bleed content more breathing room. Bottom padding is always 96px to keep content above the tabbar.
4px
Minimum gap between inline elements · section heading top margin
6px
Icon button gap · badge padding vertical · wardrobe card margin
8px
Chip gap in maison strip · care grid gap · fact grid gap
10px
Wardrobe card gap · NFC ring gap · alerts strip gap
12px
Card item gap · pipeline step gap · fact internal padding
14px
Card body horizontal padding · section heading bottom margin · topbar gap
16px
Card padding comfortable · handoff bridge gap · score card padding
18px
Score card padding · resale summary spacing · passport section spacing
22px
Screen edge padding (left/right throughout) · topbar horizontal padding
28px
Welcome bee-mark bottom margin · passport hero margin
32px
Ceremony screen edge padding (arrival copy, pair, welcome)
96px
Screen bottom padding — clears the tabbar (76px) + buffer
Corner Rounding

No radius tokens declared. Values follow a deliberate logic — rounder for interactive targets, squarer for data displays and luxury product contexts.

Radius scale

Corner rounding follows a deliberate logic rather than one flat default: objects that hold or display the physical product — the viewfinder frame, piece hero, passport hero — stay square or use the standard 16px card radius, while interactive affordances (buttons, chips, badges, the segmented control) are always full pill at 999px. Rounding is reserved for things you tap, never used decoratively on things you're meant to look at.

Luxury context applies a restraint rule: objects that hold or display the product (viewfinder, piece hero, passport hero) stay square or use only the standard 16px card radius. Pills are reserved for interactive affordances — never decorative.
3px
Motion readout strip (lv.html) · minimal data chrome
4px
Price tag overlay · viewfinder reticle corners · toast px offset
6px
Settings row group (stacked, only outermost corners) · back button
8px
Push banner icon · pipeline step icon · rec card product image
10px
Wardrobe card image · data rows · back button
12px
Alert strip · fact tile · care card · brand defense feed item · settings group
14px
Push banner · handoff bridge · auth result · chat bubbles
16px
Appointment card · rec card · resale summary · piece hero · passport hero
18px
Viewfinder frame
999px (pill)
All buttons · chips · badges · infra pill · segmented control · toggles · thread input
50% (circle)
All avatars · icon buttons · bee-mark · NFC rings · dots
Object as Interface Key Pattern

The defining UX convention of the Maison system. Rather than the app mediating between the SA and the client, the physical object — the bag — becomes the interface. The three-stage pattern spans seven screens across two modes (SA view and client view).

The three-stage arc
How a physical Louis Vuitton piece moves from the floor to the client's ownership story

The system's central design logic in three steps: the SA reads context around the piece before the client arrives (Presentation), the camera and scan pipeline confirm the object's identity in real time (Authentication), then an NFC tap transfers that verified story to the client's own phone as a persistent passport (Handoff). Every component in the Object and Passport sections exists to serve one of these three stages.

This pattern is the load-bearing claim of the Maison system — not a feature list, a design logic. Every component in the Object and Passport sections is in service of this arc. When reviewing new components for this system, the test is: does this component advance the SA's knowledge of the object, confirm the object's identity, or transfer that knowledge to the client? If not, it is chrome, not function.
1
Presentation — SA pulls up the client's world
The SA opens the client card before the client arrives. The piece the client owns or is considering is already in context: wardrobe history, Maison affiliations, preferences. The bag is not yet in the frame — the SA is reading context around it.
Screens: Client Card, Recommend
2
Authentication — the physical piece enters the loop
The SA points the camera at the piece. The viewfinder places the object inside a reticle — the product is literally inside the UI. The scan pipeline runs (stitch density, hardware micro-engraving, leather grain, cert ID lookup) while the bag glows under the scan light. The app confirms: this piece is what it says it is.
Screens: Piece Detail, Authenticate
3
Handoff — the object becomes the client's passport
The SA taps Pair. Both phones pulse with NFC rings. The passport transfers. The client's phone receives a view that is not a receipt or a loyalty point — it is the piece's story: where it was made, who handled it, what it's worth today, what to do next. The object has become a persistent narrative the client carries.
Screens: Handoff, Tap to Pair, Passport
Two modes — one object

The same underlying object record renders completely differently depending on who's looking at it: the SA sees the full provenance graph, confidence scores, and client history; the client sees only the plain-language origin story, care instructions, and resale value, with every score and pipeline detail stripped out. The Handoff segmented control is the one UI element that bridges both modes.

The Handoff toggle (segmented control) is the only UI element shared between both modes. The SA side of the toggle is the active default; tapping the client side previews exactly what the client will see on their phone before the NFC transfer fires.
SA Mode
  • Full provenance graph visible
  • Confidence scores + raw pipeline output
  • Handoff controls (consent, NFC pair)
  • Brand defense + alert context
  • Client purchase history + preferences
Client Mode
  • Origin story in plain language
  • 45-year chronology of the piece
  • Care instructions + resale valuation
  • No scores, no pipelines, no SA-side context
  • The piece speaks; the data disappears
Topbar

Persistent chrome at the top of every non-ceremony screen. Carries brand identity, contextual icon buttons, and the SA avatar. Collapses entirely in onboarding and ceremony modes.

Default state
LV monogram + Maison wordmark + notification bell + avatar

Every non-ceremony screen carries the same topbar: the LV bee-mark, the current Maison wordmark, a notification bell, and the SA's avatar. The bell's notification dot only appears when a brand-defense alert is active, so an empty bell is a real signal — nothing to review — not a placeholder state.

The bee glyph is a cream circle with the LV monogram reversed in navy-deep. The notification dot (cream fill + navy-1 ring shadow) appears on the bell only when brand-defense alerts are active. The avatar uses initials on a cream-to-cream-soft gradient. Real .topbar is padding: 60px 22px 10px (the 60px accounts for the real device's status-bar safe area) with no own background (it sits on the app's navy body) — this demo uses padding:14px 22px and an explicit var(--navy-1) background instead, since the real safe-area padding would just be empty space in a contained card rather than a status bar.
LV
Maison · Faubourg
CD
Display rules

The topbar isn't universal — it deliberately disappears on the onboarding and ceremony screens (Welcome, Face ID, Client Arrives, Tap to Pair) where a full-bleed, single-focus layout matters more than persistent navigation chrome. It returns on Floor mode, every child screen reached from a client or piece record, and both utility tabs.

Visible in
  • Floor mode (home tab)
  • Child screens (client card, authenticate, handoff, passport)
  • History + Settings tabs
Hidden in
  • Welcome + Face ID (onboarding mode)
  • Client Arrives (ceremony mode)
  • Tap to Pair (ceremony mode)
Tabbar

Three root destinations — Floor, History, Settings — using the absolute-darkest stage color to float above screen content. Tab changes use a fade-only transition (no slide) to signal lateral movement vs. hierarchy navigation.

Floor active

Floor, History, and Settings are the only three root destinations in the app, and switching between them uses a fade-only transition rather than a slide — a deliberate signal that these are lateral, equal-weight destinations rather than a hierarchy the way pushing into a client card is. The bar sits on --stage, the single darkest value in the system, so it keeps visual mass even against the darkest screen content behind it.

Active tab: cream label + full-opacity icon. Inactive: dim label + 55% icon opacity. Background is --stage (#050818) — darker than the app background so the bar has mass even on the darkest screens. Hidden in onboarding and ceremony modes. Real .tabbar is position:absolute; bottom:0; left:0; right:0; height:76px; padding-bottom:18px (pinned to the viewport bottom, with padding to clear a device's home-indicator area) — this demo keeps only the padding/layout that renders sensibly inside a contained card.
Infra Pill

A live data strip below the topbar. Communicates that IBM's provenance graph is actively connected — not a static label but a real-time indicator. Disappears in onboarding and ceremony modes.

Live connected state

The pill's job is to make an invisible backend connection feel present — the pulsing dot and the live latency readout (14ms in this demo) turn “IBM's provenance graph is connected” from a static claim into something the SA can visually verify at a glance. The latency figure uses tabular-nums specifically so the digits don't shift horizontally as the value updates.

Pill background: rgba(212,184,150, 0.07) — warm but barely visible. The pulsing green dot uses a box-shadow keyframe to breathe. Latency value uses font-variant-numeric: tabular-nums so the number doesn't shift as it updates.
Atelier · Live Provenance graph 14 ms
Screen Header

The back-button + title pair that opens every child screen. Back button uses a 10px square radius — the only square-ish interactive element in the system, consistent with its role as a navigation affordance rather than an action.

With eyebrow sub-label

The eyebrow (10px, uppercase, muted) exists for screens whose identity is ambiguous without it — “Client” above Mme. Laurent's name clarifies this is a client record, not a piece record. Section headings elsewhere reuse the identical type spec, but for grouping list items rather than establishing screen identity.

The eyebrow sub-label (10px, 0.16em tracking, uppercase, muted) provides context for screens that could belong to multiple tabs — e.g., "Client" clarifies this is a client card, not a product record. Section headings use the same type spec but apply to list groups rather than screen identity.
Client

Mme. Élise Laurent

Today
Buttons

Two semantic types. Primary is always a cream fill — reserved for the single most important action on screen. Ghost is for secondary actions that must be visible but not competing. Both are full-pill (999px).

Primary

Cream fill is reserved for exactly one action per screen — the single most important next step, never a secondary or destructive one. Hover lightens to --cream-soft and the active state scales down to 97%, giving the button a slight physical compression on tap rather than a color-only feedback.

Fill: --cream. Label: --navy-deep. Hover: --cream-soft. Active: scale(.97). Font: 13px · weight 500 · 0.04em tracking. Never use primary for destructive actions.
Ghost

Ghost buttons pair with a primary action to offer a dismissal or deferral path — “Greet later” beside a presumed “Begin” primary, for instance — and are always positioned as the secondary button in a pair, never standing alone as the main call to action. The border-only treatment keeps it visible without competing against whatever primary fill sits next to it.

Border: --line-2. Label: --cream. Hover: rgba(212,184,150,0.10) fill. Used alongside primary to give a dismissal or deferral option — always the left or secondary button in a pair.
Block (full-width)

Full-width buttons appear only on ceremony screens — Welcome, Pair, Handoff — where there's exactly one action on screen and it needs the largest possible touch target for a moment meant to feel deliberate, not incidental. Pair is the one exception to true full-bleed: it subtracts 64px to leave breathing room from the screen edges during the NFC pairing moment.

Ceremony screens (Welcome, Pair, Handoff) use block buttons because the single action needs maximum touch target on mobile. Pair screen subtracts 64px from full-width to give breathing room from screen edges.
Chips & Badges

Chips are navigable filter elements (Maison affiliation). Badges are non-interactive status labels. Both use the pill shape, distinguishing them from data tiles which use square-ish radii.

Maison chips
Default + primary (the client's primary Maison)

Chips show every Maison a client has purchased from across the LVMH group, not just Louis Vuitton — Élise Laurent's real spread here is 22 LV pieces, 5 Dior, 3 Tiffany & Co., 2 Loro Piana. The client's primary Maison gets a stronger fill and border than the others; the piece count is styled as muted metadata rather than bolded, so it reads as a count, not part of the Maison's name.

Primary chip: rgba(212,184,150,0.14) fill + rgba(212,184,150,0.36) border. Default: rgba(212,184,150,0.06) fill + --line border. The count uses muted text and normal weight to feel like metadata, not part of the Maison name.
Louis Vuitton22 Dior5 Tiffany & Co.3 Loro Piana2
Status badges

Badges share the same pill shape as chips but are strictly non-interactive labels for card-level state — an arrival status, an alert count, an authentication result — and unlike chips they never carry a count suffix or click behavior. The visual similarity to chips is intentional; the behavioral distinction is what keeps a viewer from expecting a badge to filter something.

Badges are non-interactive chips used for state labeling inside cards (appointment status, alert count, authentication result). They share the pill shape but never have a count suffix or chip-click behavior.
Arriving 3 alerts Verified
Toggle Switch

Used exclusively on the Handoff screen to manage data consent permissions. The client controls which attributes the SA can see during the session.

Consent rows

Toggles appear in exactly one place in the app: the Handoff screen's consent block, where the client controls which of their own data attributes the SA can continue to see mid-session. Purchase history and preference notes default to on; contact details defaults to off, reflecting that the SA needs the first two to do the job well but shouldn't assume access to direct contact info without it being explicitly granted.

Off state: rgba(212,184,150,0.15) track, white thumb. On state: --cream track, --navy-deep thumb. Click any row to toggle the demo. Consent rows use no outer card wrapper — they live inside the Handoff screen's consent block.
Purchase history Pieces across all Maisons
Preference notes SA observations from previous visits
Contact details Email · phone
Segmented Control

The only two-panel segmented control in the system — exclusively on the Handoff screen to toggle between SA view and the client's preview of what they'll receive after NFC pairing.

SA view / Client preview

This is the only two-panel segmented control in the entire system, and it exists for one purpose: letting the SA preview exactly what the client's phone will show once the NFC pair fires, before it actually transfers. The active segment renders as a cream badge sitting inside the pill container rather than as a separate button.

Active segment: --cream fill + --navy-deep text. Container: rgba(212,184,150,0.05) background + --line border + 999px radius + 4px padding. The active segment's fill reads as a badge living inside the pill, not a separate element.
Appointment Card

The primary list item on the Floor screen. Featured variant marks the next arriving client with a radial cream halo and a stronger border — drawing the eye without using color.

Featured + default

The featured variant — reserved for whichever client is arriving next — adds a radial cream halo and a stronger border, so the SA's eye lands on the most time-sensitive card without any color signaling it. Metadata differs by appointment type: an arriving client shows Maison tenure, a repair shows the service type, a first visit flags itself as referred.

Featured variant adds a radial gradient at top-right corner (cream, 16% opacity) and strengthens the border to rgba(212,184,150,0.32). Avatar background: sepia gradient (#3a2e1f → #5a4830) — the untokenized sepia palette. Time value uses --cream to separate it from metadata text.
JM
M. Jean Marais
16:00·Repair · authentication
SH
Ms. Sara Hadid
17:30·First visit · referred
Client Hero

The opening element of the Client Card screen — a large avatar and summary line that immediately establishes who this client is across all Maisons.

Hero + Maison strip

The client hero opens every Client Card screen with a 64px avatar — the largest in the system, and the only one that gets a full 2px cream border rather than a thin ring — followed by the client's cross-Maison chip strip. Mme. Laurent's version shown here is the fully-populated case; the second instance below is the app's real first-visit client, Sara Hadid — her card omits the chip strip, since there's no cross-Maison history to show, but the "Across the group" heading stays and is followed by a real referral note instead, not left empty.

Avatar is 64px (vs. 44px in list items) with a 2px cream border — the only component where the avatar gets a full border rather than just a line-2 ring. The metadata line uses dot separators colored in --cream as a subtle rhythm device.
Real data from the app's genuine cold-start client (clientCardHadid): Sara Hadid, first visit, referred — zero purchase history. Correction 2026-07-17: an earlier version of this block claimed her card "renders with no chip strip at all... the component correctly omits the section rather than rendering an empty row" — true for the chip strip itself, but incomplete: the real screen keeps the "Across the group" heading and substitutes a real referral quote (.quote, same component documented in Quote Block below) in place of the chips, rather than showing nothing. Quote text and source line are the exact real strings from app/index.html.
EL
Élise Laurent
Paris 7e · VIC · 11 yrs · 32 pieces
Across the group
Louis Vuitton22 Dior5 Tiffany & Co.3 Loro Piana2
SH
Sara Hadid
New York · First visit · Referred
Across the group
No purchase history anywhere in the group — first recorded visit. A referral note from Place Vendôme is the only signal on file: interested in structured leather goods.
Referral · Place Vendôme · 27 Apr 2026 · governance: no cross-Maison data exists to redact
Wardrobe Scroll

Horizontal scroll strip showing the client's owned pieces. Cards use the ivory product background — the same palette as piece hero and passport hero. Scroll snaps to card-start. Scrollbar hidden.

Wardrobe cards

The wardrobe strip is the one place in the client card where multiple owned pieces show at once — five cards plus a “26 more” count that keeps Élise Laurent's real 32-piece total honest without cramming every item into the scroll. Two of the six cards (Diane and Iconic Bracelet) open a real Piece Detail using the same PIECES-driven mechanism as the Recommend cards; the other four still show a placeholder toast, a genuine scope boundary rather than a bug.

Card image area uses the unresolved ivory gradient (#F2EBDF → #DCCFB7) with a radial highlight at 50% 30% simulating ambient light on the piece. Overflow is margin: 0 -22px; padding: 0 22px in the app to bleed edge-to-edge while items start at screen padding.
Updated 2026-07-12: of the six cards, Diane and Iconic Bracelet now open a real Piece Detail (reusing the same PIECES-driven mechanism as the Recommend screen's cards) — Diane specifically demonstrates a retired-line piece, whose certificate stays active after the model itself is discontinued. The other four still show a one-line toast; no PIECES entry has been written for them, a known scope boundary rather than a bug.
2019
Speedy 20
2021
Diane
2022
Noé BB
2023
Pochette Liv
2024
Iconic Bracelet
26 more across the Maisons · 11 years
Fact Tile

2-column grid of key metrics on the Client Card. Numeric values use tabular-nums. Cream emphasis on the most significant number in each tile.

2×2 grid

Four key metrics render as a 2×2 grid rather than a list, so an SA can read a client's lifetime spend, visit recency, piece count, and preferred SA in one glance. The two “key” figures — lifetime value and piece count — get cream emphasis, while the other two stay plain, so the eye lands on the numbers that matter most.

Label: 9px uppercase 0.18em tracking dim text. Value: 14px weight 500 text. Key figures use <em> styled to --cream to make the number immediately scannable. Tile background is the same rgba(212,184,150,0.04) as data rows — a very warm near-invisible tint.
Lifetime
€187k
Last visit
3 days ago
Pieces
32
Preferred SA
C. Dumont
No-data state

The same four-cell grid renders completely differently for a client with no history: an em dash instead of a zero or blank cell, deliberately, since a zero would misread as a measured value rather than “nothing recorded yet.” This is Sara Hadid's real cold-start card — referred by Place Vendôme, zero visits, no lifetime figure to show.

Added 2026-07-12 for the cold-start client thread. An em dash, not a zero or a blank cell — "0" would misread as a real measured value (zero of something), while a dash reads unambiguously as "not applicable yet." No cream emphasis on the dashes; emphasis is reserved for real figures.
Referred by
Place Vendôme
Visits
0
Lifetime
Aftercare
Data Row

Horizontal key-value pair used in the Piece Detail screen to show object metadata. Each row is a standalone card at 10px radius.

Object metadata

Data rows present a piece's core metadata as a stacked list of key-value cards rather than a table, each its own 10px-radius card. Reference and material stay in plain text; year and atelier — anything a client could use to trace the piece's provenance — get cream emphasis, the same treatment fact-grid gives its most important numbers.

Key: 11px uppercase 0.10em tracking muted. Value: 13px weight 500. Highlighted values (year, atelier — anything traceable to provenance) use --cream emphasis. 6px gap between rows so they read as a list, not a table.
ReferenceM43501
MaterialMonogram Canvas
Year2019
AtelierAsnières
Quote Block

SA observation captured from a prior visit. The cream left border is the single strongest decorative use of the brand color in the system — a thin vertical stripe that carries the SA's voice without overshadowing the text.

SA observation

The quote block is the strongest use of the cream accent as pure decoration in the system — a 2px left border carrying a captured SA observation without competing with the italic text it frames. It exists to surface institutional memory: what one SA learned about a client on a prior visit, available to whichever SA sees them next.

Border: 2px solid --cream, left side only. Text is italic weight 300 with rgba(212,184,150,0.55) — the unresolved cream-dim token. The source line uses 0.10em tracking and muted color to read as provenance, not byline.
"She gravitates toward the Monogram canvas in small formats. Her third piece was a special-order Speedy — always knows exactly what she wants."
C. Dumont · Faubourg · March 2024
Empty-state variant

The exact same component does double duty for clients with nothing on record — rather than hiding the block or inventing a plausible-sounding note, it states the absence directly, in a non-italic register that reads as fact rather than overheard color. Having nothing to say gets the same visual care as having something to say.

Added 2026-07-12 for the cold-start client thread. Same component doing double duty: where the default use quotes a specific observation, this variant states an absence in the SA's own voice register, non-italic to read as fact rather than overheard color. Deliberately reuses the exact component rather than inventing a separate "empty state" pattern — the point is that having nothing to say is handled with the same visual care as having something to say.
Nothing on record. This is deliberate: the system does not infer a wardrobe from a referral note.
Empty by design
History Item

Used in both the Floor screen's "Recently" strip and as full list items in the History tab. A compressed appointment card — smaller avatar, tighter type, value label right-aligned.

History list

History items are a compressed version of the appointment card — smaller avatar, tighter type, a right-aligned value label (Service, Auth) in place of a time. They appear both as a “Recently” strip on the Floor screen and as full list items in the History tab, so the same compact format has to work as both a glance and a browsable list.

Yesterday
EL
Mme. Laurent · Speedy 20 dropoff
3 days ago · ref FB-21834
Service
JM
M. Marais · Capucines authentication
6 days ago · ref FB-21819
Auth
Recommendation Card

IBM Granite-generated product suggestions on the Recommend screen. The "why" field is the key AI signal — always italic, cream-dimmed, and framed with quotation marks to distinguish machine reasoning from factual data.

Three suggestions

Three real recommendations for Mme. Laurent — Alma BB, Side Trunk MM, LV Bloom Bracelet — each with a “why” line citing something specific from her actual purchase history (structured silhouettes since 2022, the Diane she retired, her 2024 Iconic bracelet) rather than a generic pitch. The product image area renders the ivory gradient in this demo; in production each card carries a real product photograph.

Corrected 2026-07-16: this block previously showed "Nano Noé" and "Capucines BB" at invented prices — neither piece appears anywhere in app/index.html. The real recommend screen shows exactly three cards for Mme. Laurent (Alma BB €1,790, Side Trunk MM €3,500, LV Bloom Bracelet €395), matching this block's "Three suggestions" title for the first time. The "why" italic uses rgba(212,184,150,0.55) — the unresolved cream-dim token. Opening/closing guillemet-style quotes are added via ::before/::after pseudo-elements in --cream.
€1,790
Alma BB · Monogram
Coated canvas · cowhide trim · brass
Echoes the structured silhouette she’s drifted toward since 2022 — the Art Deco shape, gold-tone hardware, the wardrobe palette she’s settled into.
€3,500
Side Trunk MM · Monogram
Architectural · cowhide trim
She’s leaned into architectural silhouettes since 2023. The Side Trunk reads quieter than the Diane she retired last spring — same Monogram language, calmer profile.
€395
LV Bloom Bracelet
Smooth leather · gold-tone
Pairs with the wrist she’s been wearing — leather and gold, no logo at the surface. Sister to her 2024 Iconic bracelet, in a softer leather register.
Governance Tag

A compact disclosure bar that appears below AI-generated recommendation cards. Its presence signals that the AI's output passes IBM's responsible AI governance — the dot turns this from a label into a live indicator.

Active governance signal

The governance tag is the disclosure that follows every AI-generated recommendation — a compact strip naming IBM watsonx and confirming the output passed consent and regional-compliance filtering. It shares the ok-green semantic and the pulsing dot language of the infra pill deliberately: this is a live check being run, not a static legal footer.

Uses the ok semantic palette: rgba(156,200,160,0.06) background + rgba(156,200,160,0.20) border. The green dot matches the infra pill's live-status dot — same visual language: this too is a live check, not a static label.
Recommendations generated by IBM watsonx · filtered for client consent and regional compliance
Restraint variant — no history to ground

The same disclosure component reports an absence instead of a pass for Sara Hadid's cold-start recommendations — no purchase history exists, so none is claimed, rather than fabricating a “quiet preference.” It deliberately keeps neutral tag styling rather than switching to a warning color, since declining to fabricate familiarity is the system working correctly.

Added 2026-07-12 for the cold-start client thread (see Content section). Same component, same "this is a live check" language — but the check it reports is an absence, not a presence. Deliberately not a warning/alert color: declining to fabricate familiarity isn't an error state, it's the system working correctly.
Not personalized. No purchase history exists to ground a recommendation, so none is claimed.
Authentication Pipeline

A step-list showing the authentication checks running in real time while the SA holds the camera over the piece. Three states: pending (default), active (cream ring + cream label), done (ok-green with timestamp).

Mid-scan state + success result

The pipeline is a live step list — material signature, stitching pattern, hardware serial, provenance graph match — that the SA watches complete in real time while holding the camera over the piece. Each step morphs from pending to an active cream ring to a done ok-green checkmark; the result card only renders once all four steps finish, confirmed here for a genuine Alma BB with no anomalies across four checkpoints.

Pipeline lives below the viewfinder. Steps use a numbered circle (22px, border-radius 50%) that morphs from pending → active (cream) → done (ok-green). Auth result block only renders when all steps complete — it uses display:none → display:block via JS class toggle.
Material signature
0.4s
Stitching pattern
0.7s
3
Hardware serial
4
Provenance graph match
Authenticated
Alma BB · Monogram Canvas
Verified across 4 checkpoints · Asnières, 2019 · no anomalies detected
Mismatch state + alert result

Added 2026-07-12 behind a demo-only toggle: before this existed, the scanner in the interactive prototype could only ever resolve positive, so “brand defense” was a claim the prototype never actually demonstrated. The failing step swaps its timestamp for a literal “MISMATCH” label, and the result routes to brand-defense review without touching the client's own passport.

Added 2026-07-12, live in the app behind a demo-only toggle above "Begin scan." Same components as the success state, alert palette instead of ok: border/background swap to rgba(232,159,138,…) (the --alert token), and the failing step's timestamp is replaced with a literal "MISMATCH" label rather than a duration — the point isn't that it was slower, it's that it didn't match. Before this existed, the scanner could only ever resolve positive, so "brand defense" was a claim the interactive prototype never actually demonstrated.
1
Stitch density
MISMATCH
Hardware micro-engraving
0.32s
Flagged · pattern mismatch
Speedy 20 · Unverified
Routed to brand-defense review — does not touch the client's own passport or history.
Piece Hero

The full-width product showcase used in Piece Detail and Authenticate. A 4:5 panel with the ivory gradient background, radial highlight, and hatching texture. In production, a product image is positioned at 44% from top with a drop shadow.

Product showcase panel

The piece hero is the full-width product showcase that opens both Piece Detail and Authenticate — a 4:5 ivory-gradient panel with a radial highlight and a barely-visible hatching texture meant to read as atelier paper. The confidence badge (98.4% match, shown here for a real Alma BB) sits in the same panel rather than as a separate element.

Background: linear-gradient(180deg, #F2EBDF 0%, #DCCFB7 100%) (untokenized gap). Hatching: repeating-linear-gradient(45deg, rgba(0,0,0,0.025) 0 1px, transparent 1px 6px) — barely visible, reads as atelier paper. Confidence badge uses ok-green on a navy-deep semi-transparent background.
Louis Vuitton
Alma BB
98.4% match
Viewfinder

The Authenticate screen's camera frame. The physical bag occupies the center; a scanning line sweeps from 18% to 82% using a sine-in-out bounce animation. Two blend-mode overlays (plus-lighter + soft-light) create a warm glow that appears to emanate from the scan itself passing across the product.

Scanning state (animated)

The viewfinder places the physical piece inside a reticle on the Authenticate screen — the scanline sweeps from 18% to 82% on a 2.4s sine-in-out bounce, with luminance peaking twice per cycle, both times at the center where the bag sits. The blend-mode overlays that create the warm glow crossing the surface are omitted from this static demo but drive the effect in the real prototype.

The scanline uses two synchronized animations: scan-sweep (2.4s, moves top position) and scan-shine (1.2s, pulses opacity + box-shadow). Luminance peaks twice per sweep cycle — both times at the center where the bag sits. The scan-glow and scan-tint blend-mode overlays track the scanline; they're omitted from this demo but critical in the prototype for the "warm light crossing a surface" read.
Provenance Timeline

A vertical timeline on the Passport screen documenting the piece's journey since manufacture — atelier, purchase, ownership transfers, service events. The cream gradient line fades out at the bottom to imply the story continues.

Piece history

The provenance timeline documents a piece's full lifecycle on the Passport screen — crafted at Asnières in 2019, sold at Faubourg the same year, a handle replacement in 2022, transferred to Passport in 2024 — using a single gradient line that fades to transparent at the bottom to imply the story is still being written. This is the real chronology for the Alma BB shown throughout Piece Hero and Score Card.

The vertical line is a pseudo-element: linear-gradient(180deg, var(--cream) 0%, transparent 100%) — 1px wide, runs from the first dot to off the bottom. Dots are 11px circles: background:var(--cream); border:2px solid var(--navy-deep); box-shadow:0 0 0 1px var(--cream). Year labels are uppercase cream at 0.16em tracking.
2019
Crafted at Asnières — hand-stitched by Maison LV
2019
Sold at Faubourg — Speedy 20, special order Monogram
2022
Service — handle replacement · Faubourg workshop
2024
Transferred to Passport · provenance graph updated
Score Card

Provenance confidence score on the Passport screen. Uses the ok-green semantic throughout — label, number accent, and border — to read as a positive verification, not a metric.

Provenance confidence

The score card gives the pipeline's numeric output (98.4%) its own dedicated moment on the Passport screen, styled entirely in the ok-green semantic — label, number, and border all reinforcing “this is verified,” not presenting the figure as a neutral metric.

Provenance confidence
98.4%
Verified across material origin, manufacturing records, and 4 ownership transfers
Care Grid

2-column grid of care instructions on the Passport screen. Uses icon tiles rather than text-only rows so the client can scan the four most important care actions without reading.

Four care tiles

Care instructions render as four icon tiles rather than a text block, so a client can scan the most important actions — avoid rain, condition annually, store upright, where to get repairs done — without reading paragraphs. Each tile pairs a symbol with a one-line title and a slightly longer instruction.

Avoid rain
Canvas absorbs water — use the dust bag in wet weather
Condition annually
Apply leather balm to vachetta trim once per year
Store upright
Stuff with tissue to retain the base shape
Faubourg repair
Hardware and handle replacement available at any Maison
Message Thread

The Aftercare screen's post-purchase channel. Bubbles use two visual lanes: inbound (them) is warm-tinted dark, outbound (me) is solid cream with navy text. The sticky thread input uses the navy-2 background to lift it off the scroll content.

Conversation + composer

The message thread is the Aftercare screen's post-purchase channel between SA and client, using two visual lanes — inbound bubbles in warm-tinted dark, outbound in solid cream with navy text — with a sticky composer pinned as the thread scrolls. Fixed 2026-07-12: the send button previously had no click handler at all; it now appends the typed reply as a new outbound bubble and, after a pause, a canned inbound response.

Inbound bubble: rgba(212,184,150,0.08) background + --line border + bottom-left-radius flattened to 4px. Outbound: --cream background + --navy-deep text + bottom-right flattened. Thread input uses position:sticky; bottom:0 so it stays visible as the thread grows.
Fixed 2026-07-12: the composer's send button previously had no click handler at all — a real defect, not a design choice. Now wired to append the typed text as a new outbound bubble and, after a short pause, a canned inbound reply, so the thread genuinely composes rather than just displaying a fixed transcript.
Bonjour Camille — I wanted to follow up on the Alma BB. How is she settling in?
Élise · 09:14
She is absolutely perfect. I've been using her every day since Tuesday.
09:18
Wonderful to hear. Your Passport is ready when you'd like to explore the full story of your piece.
09:20
Reply…
Resale Summary

Opening card on the Resale Path screen. Shows current estimated value with the same card gradient as appointment cards — provenance data has the same visual weight as client data.

Current valuation

The resale summary opens the Resale Path screen with the same card gradient used for appointment cards — a deliberate signal that provenance-backed valuation data carries the same visual weight as client-facing information. The €1,840 figure is grounded explicitly in current secondary-market data for this exact model and condition, not a flat estimate.

Estimated resale value
€1,840 — 2025
Based on current secondary market data for Monogram Speedy 20 in very good condition
Stat Grid

Three-column metric strip at the top of the Brand Defense screen. Large cream numerals on transparent tiles — data without chrome.

Defense metrics

Three large cream numerals open the Brand Defense screen — total takedowns, the SA's own region, and the resolution rate — rendered on transparent tiles with no card chrome at all, so the numbers carry the weight rather than a bordered container.

142
Takedowns
3
Your region
98%
Resolved
Feed Item

Brand defense alert entries. The geo prefix (2-letter or abbreviated location code) provides immediate spatial context — an SA scanning the list reads the geography before the detail.

Counterfeit alerts

Each feed item leads with a 2-letter geo prefix so an SA scanning the list reads the geography before the detail — a marketplace counterfeit in France, a supply-chain diversion in Italy, a matched serial number in the US. System references (provenance graph, IBM supply intelligence) render inline in cream to credit which underlying platform surfaced each alert.

Geo prefix: 48px wide, 10px uppercase, cream. System reference text (provenance graph, IBM supply intelligence) uses --cream inline to credit the underlying platform. Background: rgba(212,184,150,0.04) — same as fact tiles, establishing these as data items.
FR
Marketplace counterfeit · Speedy 25
Identified via provenance graph · Taken down 08:32
IT
Supply chain diversion · Florence hub
Flagged by IBM supply intelligence · Under review
US
Social marketplace listing · Neverfull MM
Matched serial FB-18472 · Takedown initiated
Alert Strip

Inline notification strip on the Floor screen. Uses the alert semantic palette to draw attention without alarming — a tinted background rather than a bold red.

Brand defense alert

The alert strip is a tappable, inline notification on the Floor screen — clicking it navigates straight to Brand Defense — using a tinted background rather than a bold red to draw attention without alarming an SA about to greet a client. Hover strengthens both the background and border.

Alert palette: rgba(232,159,138,0.06) background + rgba(232,159,138,0.22) border. Icon tile: rgba(232,159,138,0.16). The strip is tappable — clicking navigates to the Brand Defense screen. Hover darkens background to rgba(232,159,138,0.12) and strengthens border to 0.40.
3 brand-defense alerts in your region this morning
Marketplace takedowns · counterfeit detection
Toast

Confirmation feedback for non-navigating taps — appointment info, copied reference numbers, locked appointments. Cream fill reversed with navy text: the same color pairing as the primary button, which reinforces that something the user initiated has confirmed.

Confirmation toast

Toast confirms non-navigating taps — appointment info, a copied reference number, a locked appointment — using the same cream-on-navy pairing as the primary button, reinforcing that whatever the user initiated has completed. It sits above the tabbar so it's never clipped, and auto-dismisses after 2.4 seconds.

Background: rgba(212,184,150,0.96) — near-opaque cream. Text: --navy-deep. Appears at bottom:110px (above tabbar), centered. Enters via translateY(20px) → translateY(0) + opacity 0→1 in 240ms. Auto-dismisses after 2.4s.
Referred from Place Vendôme
Push Banner

In-app arrival notification that appears above the status bar area when a client the SA is expecting has arrived. Slides down from off-screen using the weighted-finish easing. Tappable to open the Client Arrives screen.

Client arrival notification

The push banner slides down from off-screen using the same weighted-finish curve as the Face ID progress ring, appearing whenever a client the SA is expecting arrives at the entrance. It's tappable — opening the Client Arrives ceremony screen directly — and its hover state references the undeclared --line-3 token documented in Color Gaps.

Background: #14193F (navy-2). Border: --line-2. Hover state references undeclared --line-3 — this is the color gap that needs resolution. Entry easing: var(--ease-weighted) (cubic-bezier(0.32, 0.72, 0, 1)) at 420ms (same as Face ID progress ring — the "weighted finish" curve throughout the system for elements landing into view).
LV
Maison
Mme. Laurent has arrived at the main entrance
Handoff Bridge

Contextual panel on the Handoff screen explaining what data transfers during the NFC pairing. The cream-tinted border distinguishes it from standard data rows — this panel is explanatory, not navigable.

Transfer context

The handoff bridge is explanatory, not navigable — a single panel on the Handoff screen spelling out exactly what transfers during NFC pairing (the piece's Passport) and what stays private (the SA's own session notes). Its cream-tinted border visually distinguishes it from a standard data row, signaling “read this” rather than “tap this.”

Tapping Pair sends the piece's Passport to Mme. Laurent's phone. She controls what she shares with future SAs — your session notes remain private.
Settings rows

Settings rows collapse their borders into a single grouped list — only the first and last rows keep their corner radii, and there's no gap between rows, so the group reads as one continuous list. Each row ends in either a chevron (navigable) or a toggle (boolean), and the value cell's cream text signals which kind of row it is before the user taps.

Settings rows use no gap between them — border-top:0 on each subsequent row collapses borders. Only the first and last rows carry their corner radii. Value cells use cream text with a right-pointing chevron for navigable items, or a toggle for boolean settings.
Language
Français ›
NotificationsArrivals · brand defense alerts
Biometric loginFace ID · Touch ID
Surface 2 of 2
Microsite & Case Study

Components unique to ibm-louisvuitton/index.html and work/lv.html. These surfaces share Radikal and the cream color with the app but use different layout systems, additional typefaces, and a distinct brown-black rather than navy-1 as their base background.

Loader — Bee Water-Fill

The microsite's loading screen. An orange field (#ff9933) unique to this surface — not in the app palette. The LV bee SVG fills with navy-deep as a clip-path animation driven by the page's load progress. Hover the demo to see it fill.

Bee fill · orange ground (hover to complete fill)

The microsite's loading screen uses an orange field (#ff9933) that appears nowhere else in the whole system — app, microsite, or case study — making it the loader's own dedicated identity color. The LV bee fills with solid navy-deep via an animated clip-path, driven by the actual page load progress rather than a fixed duration.

Orange ground #ff9933 is used nowhere else in the system — it is loading-screen only. The ghost layer is fill:rgba(0,26,73,0.15) (navy-deep at 15% opacity on orange = warm bronze silhouette). Fill layer is solid #001a49 revealed by animating clip-path:inset() from 100% → 0%. Progress is driven by JS reading the page load counter.
Hero Typography

The microsite hero uses Radikal Black (wt 900) at viewport-scaled size — calc((100vw − gutters) / 6.2) — so the headline always fills the usable width regardless of viewport. Background is warm dark brown #1C1008, distinct from the app's navy stack.

Hero headline system

The microsite hero headline scales its font-size directly off viewport width — calc((100vw − gutters) / 6.2) — so “IBM×LVMH” always fills the usable width regardless of screen size, rather than jumping between fixed breakpoint sizes. The divisor 6.2 is tuned to the character count of “IBM×LV,” the longer of the headline's two lines, so both lines fill equally.

Font size formula: calc((100vw - 6rem) / 6.2) at base, scaling to calc((100vw - 12rem) / 6.2) at ≥768px and calc((100vw - 18rem) / 6.2) at ≥1600px. The divisor 6.2 matches the number of characters in "IBM×LV" — tuned so both lines fill equally. Caption uses Radikal 500 with 0.26em tracking at 9px.
IBM × LVMH · A partnership built for what comes next
IBM×
LVMH
Radikal Black · wt 900 · 0.88 leading · −0.02em tracking · scales to fill viewport width
Service Cards — Color Schemes

Five branded color schemes applied to the microsite's service pitch cards. Each scheme pairs a background with a complementary foreground — card hover reveals a button that swaps foreground/background. These schemes do not appear in the app.

Three primary schemes

Five branded color schemes exist across the microsite's service pitch cards, of which three are shown here — orange/navy for AI, espresso/gold for Data, cobalt/white for Supply. None of the five appears in the app; they're presentation choices specific to the editorial pitch context, each pairing a background with a complementary foreground that swaps on hover.

Five schemes total: orange #ff9933 / navy-deep · espresso #362518 / gold #bda476 · cobalt #0047ab / white · sage #bda476 / espresso · forest #2d4a36 / eucalyptus #d8e4c8. Cards use the drift and float animations (60s rotation + 6s vertical breathe) on product images.
AI
Intelligence at the point of sale
Learn more →
Data
Client data you can trust — and use
Learn more →
Supply
From atelier to passport in one chain
Learn more →
Motion Suite Cards

Three animated demo cards in work/lv.html — each shows a specific motion applied in the prototype (Scan, Loader, Tile entrance). A motion readout strip below each stage shows the easing curve graph and an animated dot that travels the path.

Authentication scan card (representative)

This is one of three animated demo cards in work/lv.html, each pairing a live motion demo with a readout strip that plots the actual easing curve as an SVG path beneath it. The scan card runs the same 2.4s duration as the app's Viewfinder scan line, but on sine-in-out — the case study's own custom curve, replacing the app's generic ease-in-out as a deliberate design decision. The readout strip itself is unique to the case study page and doesn't exist in the app.

The motion readout strip is a unique lv.html component: a 36px-tall SVG plots the easing curve as a path, with an animated dot that travels it via CSS offset-path when the card is active. Three demos: Scan (mirrored U), Loader (sigmoid bottom→top), Tile entrance (overshoot). Primary easing cubic-bezier(0.37, 0, 0.63, 1) used for all three demo dots.
2400ms Sine in-out
Authentication Scan
The scan line bounces continuously on sine-in-out — no abrupt reversal. The bag reacts: a warm glow brightens the surface as the scan passes, then relaxes. Product and motion read as a single event.
Duration 2400ms Curve sine-in-out Screen Authenticate
Motion specs catalog

The specs catalog is a linked grid of all six named motion demos in the case study — Scan sweep, Bee water-fill, Tile entrance, Screen slide, Bag glow, Face ID ring — each cell linking to its corresponding demo further down the page. The grid uses intersecting hairline borders rather than a gap between cells, specific to this catalog.

The specs catalog is a linked grid — each cell links to the corresponding motion demo in the case study page. Grid uses intersecting 1px cream-alpha borders rather than gap: border-top + border-left on the container, box-shadow: 1px 0 0 0 … 0 1px 0 0 … on each cell.
All motion specs
Pull Quote

Large editorial statements in case study text blocks. Uses a hypothetical serif typeface (Hatton in the source, fallback to Radikal Light here) at italic wt 200. The split variant places a shorter opening claim at full size and a longer elaboration at ~60% size.

Split pull quote

Pull quotes carry the case study's largest editorial claims — “The object becomes the interface” — in a dimmed white rather than pure white, a deliberate restraint that keeps them from competing with body text in adjacent columns. The split variant pairs a short primary claim at full size with a longer elaboration at roughly 60% size directly beneath it.

Primary quote: clamp(40px,5.4vw,80px) · wt 200 · italic · rgba(255,255,255,.5). Sub-line: clamp(24px,3.2vw,44px) · same weight and color. The dimmed white (not pure white) reads as editorial restraint — a deliberate choice that keeps pull quotes from competing with body text in adjacent columns.
The object becomes the interface.
Not a receipt. Not a loyalty point. The bag's own story — carried by its owner.