---
version: alpha
name: Bloomindesign
description: Technical-architect, monospace-first portfolio design language for a UI/UX/AI studio. A 24px grid, paper-vs-graphite palette, hand-drawn editorial robots, and precise crop-mark cards that work across three themes (light, dark, matrix).
colors:
  light:
    bg-primary: "#faf9f7"
    bg-secondary: "rgba(245, 244, 242, 0.95)"
    text-primary: "#1a1a1a"
    text-secondary: "#555555"
    text-muted: "#888888"
    border: "#d4d2cf"
    grid-lines: "#d8d6d3"
    accent-gold: "#f5a623"
    accent-gold-hover: "#e09000"
    accent-ai: "#6366f1"
    accent-ai-light: "#a5b4fc"
    destructive: "oklch(0.577 0.245 27.325)"
  dark:
    bg-primary: "#1a1a1a"
    bg-secondary: "rgba(30, 30, 30, 0.95)"
    text-primary: "#faf9f7"
    text-secondary: "#b0b0b0"
    text-muted: "#888888"
    border: "#2a2a2a"
    grid-lines: "#333333"
    accent-gold: "#f5a623"
    accent-gold-hover: "#ffb84d"
    accent-ai: "#818cf8"
    accent-ai-light: "#a5b4fc"
    destructive: "oklch(0.704 0.191 22.216)"
  matrix:
    bg-primary: "#0a0a0a"
    bg-secondary: "rgba(0, 20, 0, 0.95)"
    text-primary: "#00ff00"
    text-secondary: "#00cc00"
    text-muted: "#009900"
    border: "rgba(0, 255, 0, 0.2)"
    grid-lines: "#003300"
    accent-gold: "#00ff00"
    accent-gold-hover: "#33ff33"
    accent-ai: "#00ff00"
    accent-ai-light: "#66ff66"
    destructive: "#ff0000"
typography:
  font-family: "Overpass Mono, 'Courier New', monospace"
  weights: [300, 400, 500, 600, 700]
  scale:
    h1: "clamp(40px, 8vw, 72px)"
    h2: "clamp(28px, 5vw, 40px)"
    h3: "clamp(20px, 3vw, 24px)"
    body: "18px"
    small: "14px"
    micro: "12px"
    nano: "11px"
  letter-spacing-display: "-0.02em"
  letter-spacing-mono-label: "0.1em"
  line-height-headings: "1.2"
  line-height-body: "1.6"
rounded:
  base: "0"          # site components are deliberately square
  shadcn-radius: "0.625rem"
  pill: "9999px"
  phone-frame: "24px"
spacing:
  grid-unit: "24px"
  xs: "6px"
  sm: "12px"
  md: "24px"
  lg: "48px"
  xl: "72px"
  "2xl": "120px"
  container-max: "1152px"
  container-padding: "24px"
components:
  - id: button
    description: Site-level Button using class-variance-authority. Variants live alongside shadcn defaults; the production site uses primary, outline-site, and ghost almost exclusively.
  - id: mono-tag
    description: Monospace pill-less tag with 1px border. Uppercase optional. Compact 12px.
  - id: mono-label
    description: 12px monospace caps label for section eyebrows.
  - id: card
    description: Crop-mark card with 1px border, blurred secondary background, and four 6px corner ticks that extend 1px outside the box.
  - id: glow-card
    description: Card variant with a conic-gradient GlowingEffect that follows the cursor on hover.
  - id: browser-frame
    description: Card-embedded faux browser chrome with three hollow dots and a URL bar.
  - id: phone-frame
    description: Card-embedded faux phone with a notch bar and rounded screen.
  - id: section-header
    description: Centered eyebrow (mono-label) + h2 layout used for every page section.
  - id: timeline
    description: Vertical timeline with 12px square dots, accent-gold for current and accent-ai for highlighted milestones.
  - id: testimonial
    description: Crop-mark card with blockquote and avatar/role footer.
  - id: header
    description: Fixed 72px tall translucent header with backdrop-blur(8px).
  - id: footer
    description: Two-column footer with brand block, link group, and bottom bar including a mono-tag for location.
  - id: theme-toggle
    description: Cycles through light → dark → matrix using lucide Sun, Moon, Monitor icons.
  - id: imagery-toggle
    description: Cycles through robot ↔ flower decorations.
  - id: form-input
    description: Square 1px-bordered text input on bg-secondary with body-on-focus border and box-shadow ring.
---

# Bloomindesign Design System

Site: https://bloomindesign.com
Stack: Next.js 16, React 19, Tailwind CSS v4, shadcn/ui (style: new-york, base: neutral), Radix Slot, class-variance-authority, framer-motion, lucide-react, Overpass Mono (next/font).
Themes: `.light` (default-light), `.dark` (default), `.matrix` (easter-egg / hacker mode). Theme class is set on `<html>`; user toggles with the `ThemeToggle` button (Sun → Moon → Monitor cycle).

## Overview

Bloomindesign is the personal studio of Simon Bloom, a 20+ year UX designer working in UI/UX and AI. The site reads like a draftsman's notebook: warm paper, dark graphite, generous whitespace, and an obsessive 24px grid printed faintly across every section. Every typographic decision uses **Overpass Mono** — there is no proportional typeface anywhere in the system.

The personality is "Technical Architect": precise, restrained, slightly dry, with one warm gold accent and one electric indigo accent. Imagery alternates between hand-drawn ink robots and pale-green pressed flowers; both are user-toggleable so the same layout can read as engineering-heavy or organic.

The most identifiable visual gesture is the **crop-mark card**: a 1px hairline rectangle with four tiny 6px L-shaped corner ticks that hang one pixel outside the box, like printer registration marks. Cards never use rounded corners. Buttons never use rounded corners. The system is square by default; the only rounded shapes are the faux browser dots (50%) and faux phone frames (24px).

A `matrix` theme exists. It's the only place in the system where readability rules bend — green-on-black, scanline overlay, every accent collapses to `#00ff00`. Treat it as a coherent alternate skin, not a dark-mode variant.

### Source priority used to build this doc

1. Codebase: Bloomindesign source app (Next.js app + CSS modules)
2. Live site: https://bloomindesign.com (live computed CSS variables verified)
3. Captured screenshots: home (light/dark/matrix), portfolio (light)

When in doubt, prefer the implemented values in `app/globals.css` over anything in this document.

### Voice & atmosphere keywords

- Technical, draftsman, schematic
- Monospace, terminal-comfortable
- Editorial, ink-drawn, paper-warm
- Confident-but-quiet; one accent at a time
- Anti-startup-glossy

## Colors

The system uses CSS custom properties defined in `app/globals.css` and overridden per `.dark` / `.matrix` class. shadcn token aliases (`--background`, `--foreground`, `--primary`, etc.) live alongside the Bloomindesign-native tokens (`--bg-primary`, `--text-primary`, `--accent-gold`, `--accent-ai`).

Site components prefer the **native** tokens (`--bg-primary`, `--text-primary`, `--accent-gold`). shadcn tokens are present so future shadcn primitives drop in cleanly, but the marketing surface deliberately does not use them.

### Light theme — "Paper"

| Role | Token | Value | Use |
| --- | --- | --- | --- |
| Background primary | `--bg-primary` | `#faf9f7` | Page, footer, card interiors |
| Background secondary | `--bg-secondary` | `rgba(245, 244, 242, 0.95)` | Header (with blur), section bands, mono-tags |
| Grid lines | `--grid-lines` | `#d8d6d3` | 24px radial-dot page background |
| Border | `--border-color` | `#d4d2cf` | Hairline borders on every card and divider |
| Text primary | `--text-primary` | `#1a1a1a` | Headings, dark CTAs, avatars |
| Text secondary | `--text-secondary` | `#555555` | Body, paragraphs, crop-mark corners |
| Text muted | `--text-muted` | `#888888` | mono-label, metadata, browser URL |
| Accent gold | `--accent-gold` | `#f5a623` | Primary hover, links, current-state, dot accents |
| Accent gold hover | `--accent-gold-hover` | `#e09000` | Hover-on-hover for the gold itself |
| Accent AI | `--accent-ai` | `#6366f1` | "[All-In on AI]" callout border, highlight dots |
| Accent AI light | `--accent-ai-light` | `#a5b4fc` | Soft-AI usage if needed |
| Destructive | `--destructive` | `oklch(0.577 0.245 27.325)` | Form errors |
| Form success | (inline) | `#dcfce7 / #166534` | Contact form success message |
| Form error | (inline) | `#fef2f2 / #991b1b` | Contact form error message |

### Dark theme — "Graphite"

| Role | Token | Value | Use |
| --- | --- | --- | --- |
| Background primary | `--bg-primary` | `#1a1a1a` | Page |
| Background secondary | `--bg-secondary` | `rgba(30, 30, 30, 0.95)` | Header / band sections |
| Grid lines | `--grid-lines` | `#333333` | Page dot grid |
| Border | `--border-color` | `#2a2a2a` | Hairline borders |
| Text primary | `--text-primary` | `#faf9f7` | Headings, paragraph foreground |
| Text secondary | `--text-secondary` | `#b0b0b0` | Body |
| Text muted | `--text-muted` | `#888888` | Labels, metadata |
| Accent gold | `--accent-gold` | `#f5a623` | Same gold; readable on dark |
| Accent gold hover | `--accent-gold-hover` | `#ffb84d` | Lifted on hover |
| Accent AI | `--accent-ai` | `#818cf8` | Slightly lighter indigo for dark contrast |
| Destructive | `--destructive` | `oklch(0.704 0.191 22.216)` | Errors |

Imagery filters: in dark mode, `blog-card-image`, `article-image`, and any `.grid-overlay-image` get `filter: invert(1) brightness(1.2) contrast(0.9);` so the ink-on-paper drawings become silver-on-graphite. The logo SVG receives `filter: invert(1) brightness(1.5);`.

### Matrix theme — "Terminal"

| Role | Token | Value |
| --- | --- | --- |
| Background primary | `--bg-primary` | `#0a0a0a` |
| Background secondary | `--bg-secondary` | `rgba(0, 20, 0, 0.95)` |
| Grid lines | `--grid-lines` | `#003300` |
| Border | `--border-color` | `#004400` (`rgba(0, 255, 0, 0.2)` for shadcn `--border`) |
| Text primary | `--text-primary` | `#00ff00` |
| Text secondary | `--text-secondary` | `#00cc00` |
| Text muted | `--text-muted` | `#009900` |
| Accent gold | `--accent-gold` | `#00ff00` (collapses to terminal green) |
| Accent AI | `--accent-ai` | `#00ff00` |
| Card | `--card` | `#0d1a0d` |
| Destructive | `--destructive` | `#ff0000` |

Matrix exclusives:

- A fixed full-screen scanline overlay: `repeating-linear-gradient(0deg, rgba(0,0,0,0.15) 0 1px, transparent 1px 2px)` on `body::after` at `z-index: 9999`, `pointer-events: none`.
- A custom SVG color-matrix filter `<filter id="matrix-video-filter">` is rendered once at the body root (`MatrixFilter.tsx`) and applied to images and overlays, isolating the green channel:
  - `feColorMatrix type="matrix" values="0.33 0.33 0.33 0 0  0.33 0.33 0.33 0 0  0.33 0.33 0.33 0 0  0 0 0 1 0"`
  - `feComponentTransfer feFuncR slope=0.051 / feFuncG slope=1 intercept=0.051 / feFuncB slope=0.051`
- The logo SVG is recolored to match: `filter: brightness(0) saturate(100%) invert(52%) sepia(98%) saturate(2059%) hue-rotate(84deg) brightness(104%) contrast(108%);`
- Flower decorations get `filter: invert(1) brightness(0.85) sepia(100%) hue-rotate(90deg) saturate(3); opacity: 0.7;`
- Primary button overrides via `data-variant="primary"`: `background-color: #00ff00; color: #0a0a0a; hover #00cc00`.

### Semantic color roles (theme-agnostic)

- **Surface base** = `--bg-primary` — the page floor
- **Surface raised** = `--bg-primary` — also the floor; raised feeling comes from border + crop marks, not background shift
- **Surface band** = `--bg-secondary` — wide horizontal sections (Testimonials, Timeline)
- **Surface overlay** = `--bg-secondary` with `backdrop-filter: blur(8px–20px)` — header and cards-over-grid
- **Body content** = `--text-secondary`
- **Brand accent (warm)** = `--accent-gold` — used sparingly, for current state, hovers, and dot accents
- **Brand accent (cool)** = `--accent-ai` — reserved for AI-related callouts only; never decorative

### Contrast & accessibility

- Light: `#1a1a1a` on `#faf9f7` ≈ 16.8:1 (AAA).
- Light body `#555555` on `#faf9f7` ≈ 7.5:1 (AAA for body text).
- Dark: `#faf9f7` on `#1a1a1a` ≈ 16.8:1 (AAA).
- Matrix: `#00ff00` on `#0a0a0a` is high-contrast technically, but the scanline overlay reduces effective legibility — never use matrix for first-impression marketing or critical content.
- Accent gold `#f5a623` on `#faf9f7` is **not** AA for body text; only use gold for ≥18px or non-text icons / dots.
- Accent AI `#6366f1` on `#faf9f7` is also borderline for body — keep at >=18px or non-text.

## Typography

Bloomindesign uses **Overpass Mono** for 100% of text. There is no proportional sans-serif. This is a load-bearing brand decision; do not introduce a second typeface.

```css
--font-family: var(--font-mono), 'Courier New', monospace;
/* loaded via next/font: weights 300, 400, 500, 600, 700 */
```

### Type scale

| Token | Value | Weight | Line-height | Usage |
| --- | --- | --- | --- | --- |
| `h1` | `clamp(40px, 8vw, 72px)` | 600 | 1.2 | Page hero "UI/UX/AI" |
| `h1 sub` | `clamp(20px, 3vw, 28px)` | 400 | 1.2 | Hero strapline ("Design that thinks.") |
| `h2` | `clamp(28px, 5vw, 40px)` | 600 | 1.2 | Section titles ("Services", "I Believe That…") |
| `h3` | `clamp(20px, 3vw, 24px)` | 600 | 1.2 | Card titles |
| `h3 (card)` | `15px–18px` | 600 | 1.3–1.4 | Inside dense cards |
| Body L | `18px` | 400 | 1.6 | Lead paragraphs |
| Body M | `15px–16px` | 400 | 1.6–1.7 | Default body |
| Body S | `13–14px` | 400 | 1.5–1.6 | Card body, navigation |
| Micro | `11–12px` | 400 | 1.4 | Labels, browser URL, avatar initials |

`<p>` defaults: `font-size: 18px`, `color: var(--text-secondary)`, `line-height: 1.6`. On mobile (≤768px) it drops to `16px`.

`<h1>` carries `letter-spacing: -0.02em` for tighter display set; everything else stays at default tracking, except mono-label (see below).

### Specialty type rules

- **Mono Label** (`.mono-label`)
  - `12px / 400 / uppercase / letter-spacing: 0.1em / color: --text-muted`
  - Used as section eyebrow above every `h2`, plus `[01]`-style numbering inside Services / Beliefs cards.

- **Mono Tag** (`.mono-tag`)
  - `12px / 400 / not uppercase by default / 6px 12px padding / 1px solid --border-color / background --bg-secondary / color --text-secondary`
  - Used as inline chips: hero "Design / User / AI", footer location pill, blog post tags.

- **Numbers**
  - Always written `[001]`, `[002]`, `[01]` etc. — square-bracket prefix mimics terminal logging.

- **Links**
  - Inherit color, no underline by default.
  - Hover: `color: var(--accent-gold)` (or `--accent-ai` inside the AI callout).
  - In `Header.module.css` nav links override: 13px / 400 / `--text-secondary`, hover `--text-primary`.

- **Skip link**: visually hidden until focused, then 14px, `border-radius: 4px`, color `--bg-primary` on `--text-primary`.

### Do

- Use the type scale literally; clamp() values are calibrated to 24px grid rhythm.
- Pair `mono-label` (eyebrow) with `h2` for every section.
- Treat any number, version, label, or step as a candidate for `[bracketed]` form.

### Don't

- Don't add a serif or proportional sans-serif. The mono is the brand.
- Don't use uppercase outside of `mono-label` and the contact-form `<label>`s.
- Don't introduce italics in mono — they're available but break the schematic feel.

## Layout

### Grid

Strict 24px base unit. Every spacing token is a multiple of 24:

```
--grid-size: 24px;
--space-xs:  6px;   /*  ¼ */
--space-sm: 12px;   /*  ½ */
--space-md: 24px;   /*  1 */
--space-lg: 48px;   /*  2 */
--space-xl: 72px;   /*  3 */
--space-2xl: 120px; /*  5 */
```

Mobile (<=768px) overrides: `--space-xl: 60px`, `--space-2xl: 80px`, `--container-padding: 16px`. Body text drops from 18→16px.

### Container

```
--container-max: 1152px;       /* 48 grid units */
--container-padding: 24px;
.container { max-width:1152px; margin:0 auto; padding:0 24px; position:relative; z-index:1; }
```

Always center content inside `.container`. Sections (`<section>`) get `padding: var(--space-xl) 0;` (72px) by default; major bands use `padding: var(--space-2xl) 0;` (120px).

### Page background grid

The page wrapper paints a subtle 24px radial-dot grid:

```css
.page-wrapper {
  background-image: radial-gradient(circle, var(--grid-lines) 1px, transparent 1px);
  background-size: 24px 24px;
  background-position: center top;
  background-attachment: local;
}
```

This dotted grid is the system's silent signature. It's strongest on light, fades on dark, and goes faint-green on matrix. Don't remove it.

### Section composition

Standard section layout:

```
section
└── .container
    ├── .header (text-align: center)
    │   ├── span.mono-label  ("Philosophy", "What I Do", "Writing", …)
    │   └── h2               ("I Believe That…", "Services", …)
    └── .grid (1, 2, or 3 columns)
        └── …cards
```

Distinct sections are separated by colour rather than dividers:

- Hero / Latest Articles → `--bg-primary`
- TrustBar / Testimonials / Timeline → `--bg-secondary` (a quieter band)

### Page-level grids by section

| Section | Desktop | Tablet (≤968) | Mobile (≤768) | Mobile (≤600) |
| --- | --- | --- | --- | --- |
| Hero | 2 cols 1fr/1fr | — | 1 col, centered | — |
| TrustBar | 6 logos in flex-wrap | — | Tight gap | — |
| Services | `repeat(3, 1fr)` gap 0 | 1 col, max 480px | — | — |
| Beliefs | `repeat(3, 1fr)` gap 0 | `repeat(2, 1fr)` | — | 1 col |
| Testimonials | `repeat(2, 1fr)` | — | 1 col | — |
| Timeline | single column, max 672px | — | — | tighter dots |
| Latest Articles | `repeat(3, minmax(0, 1fr))` | — | 1 col, max 520px | — |
| Portfolio | 12-col mosaic | 6-col | 4-col | 2-col |
| Footer | flex space-between | — | — | column |
| Contact | 2 cols 1fr/1fr | — | 1 col | — |

The portfolio grid uses these spans (12-col):

| Variant | Cols × Rows | Purpose |
| --- | --- | --- |
| `1x1` | span 3 × 1 | Phone, 4-up |
| `4x1` | span 4 × 1 | Phone, 3-up |
| `2x1` | span 6 × 1 | Browser, 2-up |
| `2x2` | span 6 × 2 | Browser, hero 2×2 |
| `3x1` | span 9 × 1 | Wide browser, ¾ width |

### Breakpoints

```
≥1024px  desktop
 ≤1024   tablet         (portfolio 6-col)
 ≤968    medium tablet  (cards collapse, hero stacks)
 ≤768    tablet/mobile  (typography down, padding down)
 ≤600    mobile compact (timeline tighter, header 48px)
 ≤480    mobile         (CTAs full-width, portfolio 2-col)
```

### Header / scroll behaviour

- Fixed at top, `z-index: 100`, `height: 72px` (3 grid units), `≤600px → 48px`.
- Background `--bg-secondary` + `backdrop-filter: blur(8px)`, hairline border-bottom.
- Mobile: burger button (32px hit area, three 20×2 lines, animates to X via 45°/-45° rotate ± 6px translate).
- Mobile menu is a full-viewport overlay rendered outside the header for stacking; body scroll is locked while open.

## Elevation & Depth

This system does not use traditional shadow-based elevation. Depth comes from:

1. **Hairline borders** (`1px solid var(--border-color)`) — the only structural separator.
2. **Crop-mark corners** — four 6px L-shaped ticks at each corner of every card, sitting 1px outside the box, `border-color: var(--text-secondary)`. These are not borders; they are absolutely-positioned `<span>` elements.
3. **Backdrop blur** — header (`8px`) and floating cards over the grid (`20px`).
4. **Glow on hover** — the `<GlowingEffect />` component renders a conic-gradient ring under the card that follows the cursor, gated by proximity (`spread=80, proximity=80, inactiveZone=0.5, blur=0.5, borderWidth=1.5`). Used on every primary card surface.

Shadcn's `shadow-xs` and `shadow-sm` exist on default Card / outline Button but the marketing site overrides them away. Do not introduce new drop shadows on marketing components.

### When to use what

| Effect | Use case | Don't use for |
| --- | --- | --- |
| Hairline border | Cards, inputs, dividers, footer top, header bottom | Buttons (use solid fill or border accent) |
| Crop-mark corners | Service / Belief / Testimonial / Blog / Portfolio cards | Standalone images, header, hero |
| Backdrop blur | Header, cards floating over the grid | Inputs, body sections |
| Cursor glow | Cards that are the primary clickable surface | Inline tags, body text, decorative blocks |

## Shapes

Default radius for the system: **0**. Square corners are mandatory unless this list says otherwise:

| Element | Radius |
| --- | --- |
| Page sections | 0 |
| Cards (Service, Belief, Testimonial, Blog, Portfolio) | 0 |
| Buttons (primary, outline-site) | 0 |
| Inputs, selects, textareas | 0 |
| Mono-tag chips | 0 |
| Skip link | 4px (only when focused) |
| Browser URL bar (inside browser-frame) | 4px |
| Browser dots | 50% (circle) |
| Phone frame card | 24px |
| Phone screen | 4px |
| Phone notch | 3px |
| Phone home indicator | 2px |
| Code block | 4px |
| Avatar initials block | 0 (square 36×36) |
| Crop-mark ticks | 0 (1px lines) |

Borders are always **1px solid var(--border-color)**, with a single exception: the AI callout in About (`.aiSection`) uses `1px solid var(--accent-ai)` and indigo crop-marks.

## Components

Each component below lists anatomy, sizing on the 24px grid, variants, states, and what an agent should never do.

### Button (`components/ui/button.tsx`)

cva-driven shadcn-style primitive with custom site variants.

#### Anatomy

```
<Button data-slot="button" data-variant data-size>
  [icon?] [label] [icon?]
</Button>
```

Always rendered with `data-variant` / `data-size` attributes — matrix mode targets these for color overrides.

#### Variants (use only the **site** variants on marketing pages)

| Variant | Use | Light | Dark | Matrix |
| --- | --- | --- | --- | --- |
| `primary` | Primary CTA | bg `#1a1a1a`, text `#faf9f7`, hover bg `#f5a623` text `#1a1a1a` | bg `#faf9f7`, text `#1a1a1a`, hover bg `#f5a623` | bg `#00ff00`, text `#0a0a0a`, hover bg `#00cc00` |
| `outline-site` | Secondary CTA | bg transparent, border `#d4d2cf`, text `#1a1a1a`, hover border + text `#f5a623` | border `#555`, text `#faf9f7`, hover `#f5a623` | border `#00ff00`, text `#00ff00`, hover lighter green + bg `rgba(0,255,0,0.1)` |
| `ghost` | Theme/imagery toggles, low-key | hover `accent` background | dark hover | n/a |
| `default` (shadcn) | Avoid on marketing | bg `--primary` | inverted | terminal |
| `destructive` | Errors only | red | red | red |
| `secondary` / `outline` / `link` | shadcn fallbacks; not used on marketing |

#### Sizes

| Size | Height | Padding | Notes |
| --- | --- | --- | --- |
| `default` | 36px (h-9) | px-4 py-2 | rare; site uses primary/outline-site which override |
| `sm` | 32px (h-8) | px-3 | Header CTA "Get in touch" |
| `lg` | 40px (h-10) | px-6 | Larger CTA |
| `xl` | auto | py-3 px-6, text 24px | Hero-scale CTA |
| `icon` | 36×36 (size-9) | — | Theme toggle |
| `icon-sm` | 32×32 | — | |
| `icon-lg` | 40×40 | — | |

site variants `primary` / `outline-site` force `!px-6 !py-3 !text-[13px]`, so on the marketing surface buttons are visually consistent at 13px regardless of `size`.

#### States

- Default: see table above.
- Hover: gold accent everywhere except matrix (terminal green).
- Focus-visible: `ring-2 ring-[var(--accent-gold)]`.
- Disabled: `pointer-events-none opacity-50`.
- Mobile menu CTA uses `fullWidth: true`.

#### Don't

- Don't add radius. Buttons must be square.
- Don't use `default`, `secondary`, or `outline` (shadcn defaults) on marketing pages — they don't match.
- Don't add drop shadows.
- Don't add gradient fills. Solid only.

### Mono-Label (`.mono-label`)

```css
.mono-label {
  font-family: var(--font-family);
  font-size: 12px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
}
```

One per section, immediately before the `<h2>`. Examples: `WHAT I DO`, `PHILOSOPHY`, `TESTIMONIALS`, `JOURNEY`, `WRITING`, `WEBSITES`. Inside cards used as `[01]`, `[001]` etc., where the bracketed number replaces uppercase text.

### Mono-Tag (`.mono-tag`)

```css
.mono-tag {
  font-family: var(--font-family);
  font-size: 12px;
  padding: 6px 12px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  color: var(--text-secondary);
}
```

Square chip. Used inline in the hero ("Design / User / AI"), in blog post tag rows, and as a one-off footer pill ("Peel, Isle of Man"). Don't add icons. Don't add radius. Don't change the typography.

### Crop-Mark Card (universal pattern)

The single most reused composition on the site. Used by Services, Beliefs, Testimonials, BlogCard, PortfolioGrid card, About AI callout, About personal callout.

#### Anatomy

```jsx
<div className="card">
  <GlowingEffect ... />                 {/* optional cursor-tracked glow */}
  <span className="cardCorner cardCornerTL" />
  <span className="cardCorner cardCornerTR" />
  <span className="cardCorner cardCornerBR" />
  <span className="cardCorner cardCornerBL" />
  {/* … card content … */}
</div>
```

#### Sizing & visuals

```css
.card {
  background: var(--bg-secondary);   /* or --bg-primary on Testimonials */
  border: 1px solid var(--border-color);
  padding: 24px;                      /* var(--space-md) */
  position: relative;
  backdrop-filter: blur(20px);        /* on Services/Beliefs over grid */
}

.cardCorner { position: absolute; width: 6px; height: 6px; pointer-events: none; }
.cardCornerTL { top: -1px; left: -1px;  border-top:    1px solid var(--text-secondary); border-left:  1px solid var(--text-secondary); }
.cardCornerTR { top: -1px; right: -1px; border-top:    1px solid var(--text-secondary); border-right: 1px solid var(--text-secondary); }
.cardCornerBR { bottom: -1px; right: -1px; border-bottom: 1px solid var(--text-secondary); border-right: 1px solid var(--text-secondary); }
.cardCornerBL { bottom: -1px; left: -1px;  border-bottom: 1px solid var(--text-secondary); border-left:  1px solid var(--text-secondary); }
```

#### Variants

- **Service card**: `mono-label` (`[01]`) → `h3` 18px → 14px description → flex-wrap feature chips. Has a 4×4 `featureDot` square in `--accent-gold` (or `--accent-ai` for AI-tagged service).
- **Belief card**: `mono-label` `[001]` colored `--accent-gold` → `h3` 15px → 13px description.
- **Testimonial card**: blockquote 14px → top-bordered author row with 36×36 square avatar (initials, mono 11px).
- **Blog card**: clickable `<a>`, contains a Browser-Frame image area + content footer with title, description, tags, date.
- **Portfolio card**: clickable, contains either a Browser-Frame or a Phone-Frame; size variants `1x1, 4x1, 2x1, 2x2, 3x1`.
- **AI callout card** (About `.aiSection`): same shape, but border + crop-marks both `--accent-ai`.

#### States

- Default: hairline + crop-marks.
- Hover (interactive cards): `<GlowingEffect />` activates a conic glow on the border; image inside scales to `1.05` for blog/portfolio cards.
- Focus (when keyboard-tabbed): rely on browser-default ring or add `outline: 2px solid var(--text-primary); outline-offset: 3px;` (used by `.blogLink`).

#### Do

- Always include all four crop-mark spans, even on the side that touches a sibling card.
- Use `--text-secondary` for crop-mark color, except the AI callout (which uses `--accent-ai`).
- Keep `padding: 24px` desktop, drop to `12px` on `≤480px`.

#### Don't

- Don't round the corners.
- Don't drop the crop-marks "to simplify" — they are the system signature.
- Don't combine drop-shadow with crop-marks; pick one form of depth.

### Glowing Effect (`components/ui/glowing-effect.tsx`)

A motion-driven cursor-tracked conic gradient that sits behind a card border.

Default site usage:

```jsx
<GlowingEffect
  spread={80}
  glow={true}
  disabled={false}
  proximity={80}
  inactiveZone={0.5}
  borderWidth={1.5}
  blur={0.5}
  movementDuration={0.5}
  gradient="conic-gradient(from 0deg at 50% 50%, var(--accent-gold) 0%, var(--accent-gold) 100%)"
/>
```

Mounted *inside* a relatively-positioned card. Listens to `pointermove` and `scroll` (passive). The CSS variable `--active` toggles the after-pseudo opacity. Performance: animation frame-throttled and pointer-events-none.

Don't:

- Don't enable on dense list items (Timeline dots, mono-tags).
- Don't change the gradient to a multi-color rainbow on marketing pages — keep it `--accent-gold` mono-conic.

### Header (`components/Header.tsx` + `Header.module.css`)

- Fixed top, z-100, 72px tall (48px ≤600px), `--bg-secondary` + `backdrop-filter: blur(8px)`, hairline `border-bottom`.
- Logo: 48×48 SVG (36×36 ≤600px), `logo-svg` class for theme-specific filters.
- Nav links: 13px / 400 / `--text-secondary`, hover `--text-primary`. Items: Services, Beliefs, About Me, Portfolio, Blog, Volume11.ai (external + ↗), Imagery toggle, Theme toggle, primary "Get in touch" CTA.
- Volume11 link includes a `↗` 11px @ 0.6 opacity icon and `target="_blank"`.
- Mobile: burger toggles a full-viewport overlay; body scroll locked.

### Footer (`components/Footer.tsx`)

```
[Brand block]
  Bloomindesign (mono 18 / 600)
  UI/UX/AI – Design that thinks. (13)
  144×144 logo
                                     [Connect]
                                       Email
                                       LinkedIn
                                       X / Twitter
                                       Contact
                                       Volume11.ai
[Bottom bar]
  © 2025 Bloomindesign. All rights reserved.   [Peel, Isle of Man]
```

- Top: `padding: 48px 0`, hairline top border.
- Brand block max-width 288px.
- Mono-tag in the bottom-right for location.
- Mobile: stacks vertically with `text-align: center`.

### Section Header

```jsx
<div className="header" style={{ textAlign: 'center', marginBottom: 'var(--space-lg)' }}>
  <span className="mono-label">{eyebrow}</span>
  <h2>{title}</h2>            {/* margin-top: var(--space-xs) */}
  {subtitle && <p>{subtitle}</p>} {/* 16px, max-width: 600px, centered */}
</div>
```

Used for Services, Beliefs, Testimonials, Timeline, Latest Articles, Portfolio. Always centered.

### Trust Bar (`components/TrustBar.tsx`)

- 24px vertical padding, hairline borders top + bottom, `--bg-secondary` background.
- Eyebrow mono-label "Trusted by", then a `flex-wrap`, gap 48px, of company names rendered as 13px mono / 500 / `--text-primary`.
- Items have `opacity: 0.5; hover: 1`.
- Mobile: gap drops to 24px, then 12px / 24px.

### Timeline (`components/Timeline.tsx`)

- Vertical, max-width 672px, single 1px line at `left: var(--space-md)`.
- Each item: 48px-wide marker column with a 12×12 square `dot`, then content with mono-label year, `h3` 16px, 14px description.
- Dot colors:
  - default: bg `--bg-primary`, border `--border-color`
  - `.current`: bg + border `--accent-gold`
  - `.highlight`: bg + border `--accent-ai`
- Hover any item: dot border becomes `--text-primary`.
- About-page variant uses identical pattern but lives inside the AI section's parent.

### Testimonial Card

- 24px padding, gap 12px, `flex-direction: column`.
- Body: 14px blockquote in `--text-secondary`, no italic.
- Footer: `border-top: 1px solid var(--border-color)`, padding-top 12px. Avatar is a 36×36 SQUARE with 11px / 600 mono initials, `bg: --text-primary, color: --bg-primary`. Name 13px / 600 / primary; role 11px / muted.
- 2-column desktop, 1-column mobile.

### Blog Card (`components/BlogCard.tsx`)

- Wraps the entire card in `<Link>`.
- Crop-mark card with optional Browser-Frame around the image (default on; opt out via `showBrowserFrame: false` in `BlogPost`).
- Image `aspect-ratio: 1800 / 1000`; `object-fit: contain` inside browser frame, `object-fit: cover` without.
- Hover scales the image to 1.05.
- Content area: `padding: 24px`, gap 12px, `bg: --bg-primary`, top border. h3 18px, description 14px, footer with mono-tags + 12px date.

### Portfolio Card (`components/PortfolioGrid.tsx`)

Two visual modes:

- **Browser-Frame** (`displayFormat: 'desktop'`): full card body is a faux browser. Aspect 16:10. URL bar shows `liveUrl` truncated with ellipsis.
- **Phone-Frame** (`displayFormat: 'mobile'`): the entire card becomes the phone — `border-radius: 24px`, internal notch (60×6 rounded 3px) at top, screen with `border-radius: 4px`, content footer rounded `0 0 23px 23px`.

Card footer: 12px padding, `--bg-primary`, top border. Title 14px / 600 / ellipsis. Category mono-tag 10px.

### Browser Frame (sub-component)

```
[bar]
  ●  ●  ●     [https://example.com               ]   <- mono 11px, ellipsis, hover gold
[content]
  [image, aspect 16:10]
```

- Bar height: `padding: 6px 12px`, `bg: --bg-secondary`, hairline bottom.
- Dots: 10×10, `border-radius: 50%`, hollow (border `--border-color`, transparent fill).
- URL bar: 4px corner radius, `--bg-primary` fill, hairline border.

### Phone Frame (sub-component)

- Notch: 60×6, 3px radius, `--border-color` fill, 10px top / 6px bottom margin, centered.
- Screen: `margin: 0 6px 6px`, 4px radius, hairline border.
- Optional home indicator: 80×4, 2px radius, 6px top / 12px bottom.
- Mobile (≤480px): notch 40×4, indicator 50×3.

### Form (Contact)

- Two-column: 1fr left info / 1fr right form.
- Form panel: `--bg-primary`, hairline border, `padding: 24px`.
- Form header: `[Contact Form]` mono-label inside square brackets, hairline bottom.
- Field group: 24px bottom margin.
- Label: 12px / mono / uppercase / letter-spacing 0.1em / `--text-secondary`.
- Input/select/textarea: 12px padding, `--bg-secondary` fill, hairline border, mono 14px, `:focus` switches border to `--text-primary` and adds `box-shadow: 0 0 0 1px var(--text-primary)`.
- Textarea: `min-height: 120px`, `resize: vertical`.
- Select: custom 12×12 chevron SVG via background-image, `appearance: none`.
- Submit button: full-width, 12px 24px padding, mono 14px / 500, uppercase, letter-spacing 0.05em, fill `--text-primary` text `--bg-primary`. Hover inverts to transparent / `--text-primary`.
- Success: `bg #dcfce7 / color #166534`, hairline `#bbf7d0`.
- Error: `bg #fef2f2 / color #991b1b`, hairline `#fecaca`.

### Theme Toggle (`components/ThemeToggle.tsx`)

Cycles light → dark → matrix → light using a single ghost icon button. Three lucide icons (Sun, Moon, Monitor) overlaid; the inactive ones rotate ±90° and scale to 0. The `aria-label` always announces the next state.

### Imagery Toggle (`components/ImageryToggle.tsx`)

A ghost button labeled `Imagery: Robot` or `Imagery: Flower`. Persists selection in `localStorage('bloomindesign-imagery')`. Default is `robot`. When `flower`, sections render `<FlowerDecoration>` props (opacity 0.15–0.25); when `robot`, they render `<GridOverlay>` with editorial robot images and an animated reveal grid.

### Decorations (Robots & Flowers)

- **Robots**: hand-drawn ink-on-paper illustrations of antique mechanical robots (`/public/images/robot-hero.png`, `/public/images/robots/*.png`). Rendered through `GridImageOverlay` which divides the image into a `rows × cols` grid of cells (default 19×10 portrait) that animate in.
- **Flowers**: pressed-flower webp photographs (`/public/images/flower-1.webp` … `flower-3.webp`). Rendered with size, position, opacity, optional flip and rotate.
- In dark, both inverted via CSS filter.
- In matrix, both passed through the matrix-video-filter and recolored green.

Use one decoration per section maximum at low opacity (0.15–0.25). Don't tile multiple at full opacity.

## Do's and Don'ts

### Do

- Use Overpass Mono for everything.
- Snap every spacing decision to 6 / 12 / 24 / 48 / 72 / 120.
- Wrap any card in the four crop-mark corner spans with 1px borders.
- Use `mono-label` + `h2` for every section header.
- Pair primary CTA + outline-site CTA in hero areas.
- Treat numbers as `[01]`, `[001]`, `[Step 1]` inside square brackets.
- Limit accent-gold to one or two appearances per viewport.
- Reserve accent-ai strictly for AI-related content (callouts, highlight markers).
- Use the page-wrapper dot grid; don't replace it with solid color.
- Default to dark mode on first paint (`defaultTheme="dark"` in layout).
- Persist theme + imagery prefs to `localStorage`.

### Don't

- Don't mix in a proportional sans-serif (Inter, Geist, system-ui). Mono only.
- Don't introduce drop shadows on cards or buttons.
- Don't round corners on cards, buttons, inputs, or chips.
- Don't add gradient fills on buttons or text.
- Don't use multiple bright colors. The brand has *one* warm accent and *one* cool accent.
- Don't replace crop-marks with rounded outlines.
- Don't render the whole site in matrix theme by default — it's an alternate skin, not the brand.
- Don't use icons inside mono-tags or mono-labels.
- Don't forget to provide an `aria-label` on the theme/imagery toggles — they cycle and are not self-describing.

## Motion

- Theme/imagery toggle icon transitions: `transition-all` with rotate ±90° and scale 0↔1 — duration default Tailwind (~200ms).
- Burger to X: 0.3s `ease` rotate ±45° and translate 6px on the outer lines, opacity 0 on middle line.
- Card image zoom on hover: `transition: transform 0.3s ease`, scale to 1.05.
- Mono-tag/Card border-color transitions: `transition: border-color 0.2s ease`.
- Form input focus: `transition: border-color 0.2s ease, box-shadow 0.2s ease`.
- GlowingEffect: cursor-tracked conic; uses `motion/react` `animate(currentAngle, targetAngle, { duration: 0.5, ease: [0.16, 1, 0.3, 1] })`.
- `disableTransitionOnChange={false}` on ThemeProvider — themes do crossfade.

There is no global page-load entrance animation, no parallax, no on-scroll fade. The animation budget is small and intentional.

## Iconography

- Library: **lucide-react** (`iconLibrary: "lucide"` in `components.json`).
- Stroke 2, 16×16 inside buttons (`size-4`).
- Site itself uses very few icons: `Sun`, `Moon`, `Monitor` in the theme toggle; the `↗` glyph (just a unicode character, not an SVG) for external links; the burger lines (custom CSS); copy-to-clipboard SVGs in CodeBlock.
- Avoid decorative icons in cards. The crop-marks and `[01]` numbering are the system's "icons".

## Imagery

Two coexisting illustration styles:

1. **Editorial robot ink drawings** (default). Hand-drawn graphite/ink, antique mechanical robots, warm paper white. Used for: hero, services side-fade, beliefs side-fade, portfolio support robots, blog banners. They are the "studio mascot".
2. **Pressed-flower photography**. Pale-green flat-lay flowers as background atmosphere. Used as low-opacity decoration only.

Banner generation rules (from `AGENTS.md`):

- Use Nano Banana Pro for the final generated image.
- Refined editorial illustration: hand-drawn ink/graphite, warm paper white, restrained pale-green accents.
- Avoid readable text, fake UI words, labels, logos, watermarks, screenshots, browser chrome, clutter, and generic SaaS art.
- Export final banner as **WebP at 1800×1000** for article hero / browser-frame use.
- Inspect output visually and iterate if it has text artifacts or weak composition.

In dark mode, all decorative images inherit `filter: invert(1) brightness(1.2) contrast(0.9)`. In matrix mode, they pass through `<filter id="matrix-video-filter">` (an SVG `feColorMatrix` + `feComponentTransfer` that isolates the green channel).

Don't:

- Don't use full-color stock photography.
- Don't use vector flat-illustration art (the "Corporate Memphis" look). It violates the editorial direction.
- Don't render UI mockups inside hero illustrations — let real browser-frames carry that job.

## Content Voice

- First-person and direct: *"I bring passion, excitement, and pathological attention to detail to every project."*
- Dry technical humor: section labels like `[All-In on AI]`, `[Contact Form]`, `[001] I Believe That…`.
- Pragmatic, anti-jargon. No "synergy", no "leverage". Plain words inside mono type.
- Sentences are short. Paragraphs are 1–3 sentences.
- Acknowledge AI directly: AI is a tool that amplifies, not replaces. Don't be coy about using it.
- Belief / Service taglines are imperative and self-evident: "User experience informs content and design."

## Accessibility

- Skip-link at the top of every page (`.skip-link`), targeting `#main-content`. Hidden until focus, then 14px button with 4px radius.
- All images have `alt` (decorative ones use empty `alt=""` and `aria-hidden="true"`).
- Theme & imagery toggles must announce next state via `aria-label="Switch to {next} mode"`.
- Burger button uses `aria-expanded` and `aria-label="Open menu" / "Close menu"`.
- Color contrast:
  - Body and headings hit AAA in light and dark.
  - Don't ship body text in `--accent-gold` on `--bg-primary` (it falls below AA).
  - Matrix theme adds a scanline overlay; never the primary surface for first-time visitors.
- Focus rings: every interactive element receives a `focus-visible` ring of `2px var(--accent-gold)` (buttons) or `2px var(--text-primary)` (links like `.blogLink`).
- Hit areas: minimum 44px height on key CTAs (`.blogLink` has explicit `min-height: 44px`).

## Responsive Behavior

| Range | Effect |
| --- | --- |
| ≥1024 | Full desktop. Portfolio mosaic 12-col. Cards 3-up. |
| ≤1024 | Portfolio drops to 6-col. |
| ≤968 | Hero stacks (illustration moves above content). Services 1-col. Beliefs 2-col. Latest Articles 1-col (max 520px). |
| ≤768 | Tablet/mobile. `--container-padding` 16px. `--space-xl: 60px`, `--space-2xl: 80px`. Body 16px. Burger menu replaces nav. Portfolio 4-col. Trust-bar gap drops to 24px. |
| ≤600 | Header shrinks to 48px. Logo to 36×36. Timeline tighter. Footer columns stack and center. Beliefs 1-col. |
| ≤480 | Hero CTAs go full-width. Portfolio 2-col. Card padding 12px. Phone-card notch 40×4. |

Use `clamp()` for h1 / h2 / h3 — values are pre-tuned. Don't replace with breakpoint-based jumps.

## Agent Implementation Notes

When generating new screens or components for this design system, follow these rules:

1. **Tokens, not literals.** Pull from `--bg-primary`, `--text-primary`, `--accent-gold`, etc. Never hard-code hex values for colors that have a token. The hex literals visible in `button.tsx` exist *because* shadcn cva strings can't use CSS variables for arbitrary class composition; mirror that pattern only when you must.
2. **Scaffold the section, not the card.** Every page block is a `<section>` → `.container` → `.header` (mono-label + h2) → `.grid` → cards. Generate the wrapper structure first, fill cards last.
3. **Always include all four crop-mark spans.** Even on the corners that touch a sibling card. They are part of the brand recognition.
4. **Use the GlowingEffect import for any clickable card.** Default props: `spread=80, proximity=80, inactiveZone=0.5, borderWidth=1.5, blur=0.5, movementDuration=0.5, gradient='conic-gradient(from 0deg at 50% 50%, var(--accent-gold) 0%, var(--accent-gold) 100%)'`.
5. **Buttons must use `Button` from `@/components/ui/button`** with `variant="primary"` or `"outline-site"`. Don't recreate buttons inline.
6. **Wrap whole card in `<Link>` for clickable cards.** Don't add a "Read more" button inside.
7. **Use `next/image` for content images, raw `<img>` for the inline blog/portfolio frames.** The site mixes these intentionally — `BlogCard` uses `<img loading="lazy">` to keep the frame layout simple while content images use `<Image priority>`.
8. **Persist preferences in `localStorage`** under existing keys (`bloomindesign-theme`, `bloomindesign-imagery`).
9. **Default new themes go in `app/globals.css`** under their own `.themeName` selector and override both the native (`--bg-primary`…) and shadcn (`--background`…) tokens.
10. **Match the AGENTS.md workflow for blog content.** Posts live in `lib/posts.ts`. Newest first, never delete or reword existing entries unless asked.

### Generation prompt template

```
Build a new <section name> for bloomindesign.com using its design system:

- Wrap in <section className={…}> with padding var(--space-2xl) 0
- Use a centered .container with .header containing a mono-label eyebrow and an h2
- Below the header, render a grid of crop-mark cards with GlowingEffect, 1px hairline borders, square corners, no shadows
- Use Overpass Mono for all text; body 14–18px in --text-secondary; titles in --text-primary
- Restrict color to --bg-primary, --bg-secondary, --border-color, --text-primary, --text-secondary, --text-muted, --accent-gold, --accent-ai
- Avoid radius unless the element is a faux browser dot, faux phone frame, or code block
- Verify the screen reads correctly in light, dark, and matrix themes
```

### File map

```
app/globals.css                            ← all tokens, all themes
app/layout.tsx                             ← font + ThemeProvider + ImageryProvider
components/ThemeProvider.tsx               ← light/dark/matrix cycle
components/ImageryProvider.tsx             ← robot/flower toggle
components/ui/button.tsx                   ← cva button variants
components/ui/card.tsx                     ← shadcn card (mostly unused on marketing)
components/ui/glowing-effect.tsx           ← cursor-tracked glow
components/ui/MatrixFilter.tsx             ← SVG filter for matrix mode
components/Header*                         ← fixed header + mobile menu
components/Hero*                           ← page hero with grid overlay
components/Services*                       ← 3-up service cards
components/Beliefs*                        ← 6-up belief cards
components/Testimonials*                   ← 2-up testimonial cards
components/Timeline*                       ← vertical career timeline
components/About*                          ← about page including AI callout
components/PortfolioGrid*                  ← 12-col mosaic
components/BlogCard*                       ← post card with browser frame
components/LatestArticles*                 ← 3-up blog grid
components/Footer*                         ← brand + links + bottom bar
components/Contact*                        ← contact form
components/FlowerDecoration*               ← pressed-flower decoration
components/RobotDecoration.tsx             ← robot grid overlay decoration
components/GridOverlay.tsx / GridImageOverlay.tsx ← cell-by-cell image reveal
lib/posts.ts                               ← blog data
lib/projects.ts                            ← portfolio data
lib/utils.ts                               ← cn() = twMerge(clsx)
```

### Confidence

- Tokens, spacing, type scale, component anatomy: **high** (extracted from source code and verified against live computed CSS).
- Matrix mode behaviour: **high** (extracted directly from globals.css).
- Motion timings: **medium** (pulled from CSS module transitions; framer-motion specifics are inside GlowingEffect).
- Imagery editorial brief: **high** (matches `AGENTS.md` directly).
- Voice & content rules: **medium** (inferred from on-site copy and AGENTS.md).
