# Application 6 — Barber Booking · Design System

> Single source of truth for App 6. Any new screen **must** use only the tokens, components and patterns below. If something is missing, add it here first, then build.
> **AI agents:** read this file, then `AI_GUIDE.md` (how to rebuild or clone the app step by step). Machine-readable values are in `tokens.json`.

- Entry file: `apps/app-6/App 6 - Barber.html`
- Source: `apps/app-6/src/` → `ui.jsx` (data, store, icons, primitives, chrome) · `screens.jsx` (all screens, phone shell, app)
- CSS: all in the HTML `<style>` block, split into commented sections: `TOKENS`, `DEVICE`, `PRIMITIVES`, `TAB BAR`, `ONBOARDING`, `HOME`, `DETAILS`, `TABS`
- Stack: React 18 + Babel in-browser, plain CSS with custom properties. No framework.
- Images: `assets/*.jpg` (public-domain / CC photos): `onboard` · `detail` · `color` · `haircut` · `avatar` · `shave` · `bw`

---

## 1. Principles

1. **White + one orange.** The UI is white with near-black text. **Orange `#FD6F29`** is the single accent: primary CTAs, the selected state of every control, the promo card, the active tab. No other hues except star-yellow and the "Save" coral.
2. **Selected = filled orange.** Any selectable item (category, action, day, time, tab icon colour) is white/grey when idle and **solid orange with white content + orange glow shadow** when selected. This is the app's signature pattern.
3. **Soft, tactile tiles.** Small rounded squares (radius 12) with a 1px hairline plus a very soft shadow. Nothing has a heavy border.
4. **Photo-led.** Real photography sits in rounded frames or fades into white (onboarding) or into orange (promo card).
5. **Friendly bold type.** Plus Jakarta Sans. Titles are 700, body 400–500. Hierarchy comes from size **and** weight.

---

## 2. Canvas & device

| Token | Value |
|---|---|
| Stage | `1024 × 768`, scaled with `Math.min(w/1024, h/768)` |
| Page bg | `--canvas #FDFDFD` (near white, like the reference) |
| Phone | `278 × 652`, radius `46`, **white bezel** (padding 6) + a single thin grey outline `0 0 0 1.2px #A9A9AA` + a faint shadow `0 18px 40px rgba(0,0,0,.05)` |
| Screen | radius `40`, bg `#fff` |
| Dynamic Island | `88 × 24`, radius 14, top 8 |
| Status bar | height `40`, 11.5px/700, static `9:41` |
| Content | `.view` = `inset: 40px 0 0 0` |
| Tab bar | height `64`, white, `1px --line` top border |
| Home indicator | `96 × 3.5`, `#111`, bottom 7 |
| Phone positions | P1 `left:66` · P2 `left:366` · P3 `left:678`, all `top:58` |

Every size is CSS px **at phone scale** (266px inner width). Keep this scale.

---

## 3. Colour tokens (CSS custom properties in `:root`)

| Token | Hex | Use |
|---|---|---|
| `--brand` | `#FD6F29` | Primary buttons, selected tiles/days/times/actions, promo card, active tab, "See All", add (+) buttons, progress dots |
| `--brand-600` | `#EF6320` | Primary hover |
| `--brand-50` | `#FEF1E8` | Soft tint surfaces (booking summary, profile stats, success halo) |
| `--brand-100` | `#FCE3D3` | Reserved (pressed tint) |
| `--ink` | `#0E0E0E` | Primary text, icons |
| `--ink-2` | `#2B2B2B` | Secondary text, idle tab labels |
| `--muted` | `#747575` | Weekday labels, "Welcome Back,", captions |
| `--sub` | `#666666` | Address lines |
| `--muted-2` | `#B5B5B5` | Disabled / struck-through slots, chevrons |
| `--line` | `#F1F1F1` | Hairlines (1px rings, tab bar top, list separators) |
| `--field` | `#F5F5F5` | Search field (placeholder `#444445`), chat bubble (them). Idle day `#F4F4F4`, idle time `#F7F7F7`, rating chip on white `#F8F8F8` |
| `--card` | `#FFFFFF` | Cards, tiles |
| `--canvas` | `#FDFDFD` | Page background |
| `--star` | `#FF9C04` | Star in rating chips |
| `--danger` | `#FE4620` | Notification dot, Cancel, Log out |
| `--save-bg` / `--save` | `#FBEADA` / `#EB6C37` | "30% Save" badge |

**Shadows are almost invisible** (sampled from the reference): `--shadow-card: 0 2px 8px rgba(0,0,0,.035)` (every tile, always with a `0 0 0 1px var(--line)` ring) · `--shadow-brand: 0 3px 8px rgba(253,111,41,.18)` (orange filled elements get only a faint warm glow). Do not make them stronger.

> Colours in this table were sampled pixel-by-pixel from the reference screenshot. Keep them exact.

---

## 4. Typography

Font: **Plus Jakarta Sans** (Google Fonts 400/500/600/700), antialiased.

| Role | Size / weight | Example |
|---|---|---|
| Onboarding headline | 19.5 / 700, lh 1.28, ls −0.2 | "Your Style, Your Barber, **Just One Tap**" (3rd line orange) |
| Success title | 16 / 700 | "Booking Confirmed!" |
| Promo title | 15 / 700, white | "Classic Taper Cut" (2 lines) |
| Screen title (top bar) | 13.5 / 700 | "Details" |
| Detail name / price | 12–12.5 / 700 | "Classic Cutting & Hair Color", "$49.00" |
| Button | 11.5–12 / 600 | "Get Started", "Book Appointment" |
| Section title | 11–11.5 / 700 | "Popular Services", "Available Today" |
| User name | 11.5 / 700 | "Dianne Russell" |
| Day number | 10.5 / 600 | "24" |
| Body / onboarding paragraph | 9.5 / 400, lh 1.65 | |
| Card title / price | 9.5 / 700 · 8.5 / 400 | "Hair Color" / "$49.00" |
| Link | 9 / 600 orange | "See All" |
| Label (action, time, address) | 8 / 500 | "Call", "10:00 AM" |
| Micro (tab, category, weekday, "Welcome Back,") | 6.5–7.5 / 500 | |

Money: always `money(n)` → `$49.00` (2 decimals).

---

## 5. Spacing, radius & components

- Screen gutter: **`--gutter: 14px`** (onboarding uses 16).
- Grid gap 10 · chip gap 6 · action gap 9 · section top margin 16–18 · title-to-content 8–9.
- Radius scale: `--r-xs 8` · `--r-sm 10` (time chips, thumbnails) · `--r-md 12` (buttons, tiles, fields, cards, days) · `--r-lg 16` (promo card, big icon tile) · `--r-xl 20` (detail gallery) · `--r-pill` (chips, rating) · sheet `24 24 0 0`.

### 5.1 Button `.btn`
Height 40 (detail CTA 42), radius 12, 11.5/600, full width.
- `.pri`: orange fill, white text, `--shadow-brand`; hover `--brand-600`; press `scale(.97)`. In onboarding, the label is centred with a trailing arrow at the right edge.
- `.ghost`: white, `1px #E4E4E4` border, ink text ("Skip for Now").
- `.sm`: auto width, 34 tall (empty states).

### 5.2 Icon button `.ibtn`
32 circle. Plain (bell with a 6px red `.dot` ringed white) or `.pri` (orange fill + glow, white `+`). Press `scale(.9)`.

### 5.3 Search field `.search`
36 tall, radius 12, `--field` bg, 16px search icon · placeholder "Search Salon, Specialist..." 10px `--muted` · filter icon button on the right.

### 5.4 Promo card `.hero`
178 tall, radius 16, **solid orange**. Photo on the right 62% width, masked `linear-gradient(90deg, transparent, #000 30%)` so it melts into the orange. Top-left: white rating chip `★ 4.9`. Top-right: 22px white rounded-7 bookmark (orange when saved). Title 15/700 white at top 50, 2 lines. Address 7.5 at top 102. Bottom-left: 28px white circle with a ↗ arrow. Bottom-right: pager dots (5px, active 14px white). Tap the card → Details.

### 5.5 Category tile `.cat` + `.cat-ic`
Column 48 wide: 36×36 tile (radius 12, white, ring + soft shadow), 18px line icon, label 6.5/500 below (wraps to 2 lines). **Selected:** orange fill, white icon, brand shadow. Order: Haircut · Hair Color · Hair Treatment · Beard Trim · More.

### 5.6 Service card `.svc`
2-column grid. White, radius 12, ring + shadow. Photo 68 tall (top corners rounded). Body pad 8/9: name 9.5/700, price 8.5. **20px orange `+` circle** at bottom-right (right 8, bottom 10). Press `scale(.97)`.

### 5.7 Rating chip `.rate`
20 tall pill, pad 0 7, 9/600, yellow star 10px. White on photos or orange; `.dk` = `--field` on white.

### 5.8 Action tile `.act`
4 equal tiles, 46 tall, radius 12, icon 16 above label 8/500. Idle white + ring + shadow; **selected orange** (Call is selected by default).

### 5.9 Tab bar `.tabbar`
5 tabs: **Home · Bookings · Favorites · Messages · Profile**, icon 17 + label 7.5. Active = orange (Home icon becomes filled). Bookings shows an orange count badge (13px, ringed white) when there are bookings.

### 5.10 Day picker `.day` + time chips `.time`
Days: 7 equal tiles, 40 tall, radius 12, `--field`; weekday 7 `--muted` above the number 10.5/600. **Selected** orange with white text + glow.
Times: horizontal scroller of chips, 26 tall, radius 10, `--field`, 8/500. Selected orange. Unavailable = struck-through `--muted-2` and disabled.

### 5.11 Other
- **Gallery `.gal`:** 168 tall, radius 20, swipe or tap dots (4px, active 12px orange), slides with `translateX` .45s.
- **"Save" badge `.save`:** 15 tall, radius 5, coral on peach.
- **Pager (onboarding) `.ob-dots`:** 3 bars, 38×3, active orange.
- **Bottom sheet `.sheet`:** dim `rgba(0,0,0,.35)`, white, radius 24 top, 36×4 grab handle; summary row on `--brand-50`; total 15/700; primary CTA.
- **Toast `.toast`:** 30 tall ink pill that drops from the island, orange check icon.
- **List card (`.bk`, `.fv`):** ring + shadow card, radius 12, thumb radius 10.
- **Chat:** bubbles radius 14 with one 4px corner; them = `--field`, me = orange/white; input pill 38 tall on `--field` + orange send button.

### 5.12 Icons `I` / `ICONS` (ui.jsx)
24 viewBox, **1.7 stroke, round caps and joins, no fill** (except star, homeF, dots). Add new icons in the same style. Names: arrowR, arrowUR, back, heart, bell, plus, search, filter, star, bookmark, pin, scissors, drop, sparkle, beard, more, phone, chat, direction, grid, home, homeF, bag, user, check, clock, cal, x, logout, gear.

---

## 6. Screens

| # | Screen | Component | Reached by | Key content |
|---|---|---|---|---|
| 6.1 | Onboarding (3 slides) | `Onboarding` | start · Profile → Log out | Photo top-right fading into white (left + bottom gradients) · 3-line headline, 3rd line orange · paragraph max-width 150 · **Next / Get Started** (orange, arrow) + **Skip for Now** (ghost), bottom 48 |
| 6.2 | Home | `Home` | Get Started · tab Home | Avatar 32 + "Welcome Back," / name · bell + orange `+` · search · promo card (2 offers, dots) · 5 categories (filter the grid; More → All Services) · "Popular Services" + See All · service grid |
| 6.3 | Details | `Details` | promo card · service card · `+` · favourite | Top bar (back · "Details" · heart toggles favourite) · gallery · name + rating · pin + address · price + Save badge · 4 action tiles · "Available Today" days · time chips · **Book Appointment** (fixed at bottom 30) → bottom sheet → Success |
| 6.4a | All Services | `Services` | See All · More | Top bar + filter chips + grid |
| 6.4b | Bookings | `Bookings` | tab | Booking cards (thumb, name, date, time, price, Cancel) or an empty state |
| 6.4c | Favorites | `Favorites` | tab | Favourited or saved salons |
| 6.4d | Messages | `Messages` | tab | Chat with auto-reply |
| 6.4e | Profile | `Profile` | tab | Avatar 74, stats strip on `--brand-50`, settings list, Log out |
| 6.5 | Success | `Success` | confirm booking | 76 orange check with a 10px peach halo, pop-in, → Bookings |

**State:** one shared store (`StoreCtx`, `useStoreState`) for all three phones, persisted to `localStorage['app6']`: `fav[]`, `saved[]`, `bookings[]`. A booking made on phone 3 shows up in Bookings on phone 2 (badge included).

---

## 7. Motion

| Pattern | Spec |
|---|---|
| Tab / screen change | `fade` .35s `--ease`: opacity 0 → 1, translateY 6px |
| Push to Details | `push` .38s: translateX 36px → 0 |
| Selection | background/colour .2s; tile press `scale(.92–.97)` |
| Gallery | translateX .45s `--ease` |
| Sheet | dim fade .25s + slide up .4s |
| Toast | spring `--spring` .45s from −80px |
| Success check | pop .5s `--spring` |
| Pager dots | width .3s |

`--ease: cubic-bezier(.2,.8,.2,1)` · `--spring: cubic-bezier(.34,1.4,.64,1)`.

---

## 8. Data (ui.jsx)

`CATEGORIES` · `SERVICES` (id, cat, name, price, img, min) · `SALONS` (id, title, name, addr, rating, price, save, img, gallery[]) · `SLIDES` (img, a, b, c, p) · `TIMES` · `TABS` · `weekDays()` (Sun 21 → Sat 27) · `money()`.
To re-skin for another business (spa, nails, dentist…), change these arrays, the images and `--brand`. No component changes are needed.

---

## 9. Adding a new screen: checklist
1. Build the component in `screens.jsx` (or a new `src/*.jsx` that exports to `window`) using only §3–§5 classes and tokens.
2. Add a route in `Phone()` (`route.v` or a new `tab`).
3. Top bar = `TopBar` (back · 13.5/700 title · optional right icon).
4. When the tab bar is visible, scroll areas get 78px bottom padding (`.view.with-tabs .scroll`).
5. Selected state = orange fill + white + `--shadow-brand`. Idle = white tile + ring + soft shadow, or `--field`.
6. Add press states and entry motion from §7. Update §6 of this file and `tokens.json`.
