# Art Nouveau Design Language System

*Botanica DLS v1.0 · Tokens and components for CSS, Tailwind CSS and Figma · Web, editorial, brand and mobile*

---

## 0. System Architecture at a Glance

The DLS uses three token layers. Components only ever consume the **semantic** layer, so a brand can re-skin the system (for example, a Mucha-style poster palette versus a Tiffany-style glass palette) by editing primitives alone.

| Layer | Prefix | Example | Consumed by |
|---|---|---|---|
| Primitive | `--an-{hue}-{step}` | `--an-moss-900: #2D3B2D` | Semantic tokens only |
| Semantic | `--an-{role}` | `--an-text`, `--an-surface`, `--an-accent` | Components |
| Component | `--an-btn-*`, `--an-card-*` | `--an-btn-bg` | Individual components |

**Ornament density levels** (set per page region with `data-ornament`):

| Level | Name | Use | Ornament allowed |
|---|---|---|---|
| L0 | Functional | Data tables, checkout, dense dashboards | Hairline borders only |
| L1 | Refined | App UI, forms, settings | Corner flourishes, leaf focus rings |
| L2 | Ornate | Editorial articles, product pages | Cartouches, tendril dividers, drop-caps |
| L3 | Showpiece | Landing heroes, campaign pages, 404s | Full whiplash frames, stained-glass panels |

---

## 1. Design Philosophy & Aesthetic Principles

### 1.1 Emotional Tone

Art Nouveau (c. 1890–1910: Mucha, Gallé, Tiffany, Guimard, Horta) rejected industrial repetition and borrowed its grammar from stems, tendrils, insect wings and water. The digital translation keeps that warmth and rejects kitsch.

| Trait | What the user feels | How it appears in the UI | Guardrail |
|---|---|---|---|
| Organic | Growth, living material | Curved containers, asymmetric balance, no hard 90° boxes at L2/L3 | Never at the cost of readable grid alignment for text |
| Graceful | Ease, unhurried calm | Slow easing, generous whitespace, long line-height | No bounce or elastic overshoot |
| Ornate | Richness, craft | Filigree, frames, cartouches | Ornament budget (see 1.3) |
| Sensual | Warmth, touch | Warm light, soft shadows, rounded press depth | Never glossy or plastic |
| Handcrafted | Human maker | Slightly irregular line weight, tapered strokes | Irregularity is designed once and reused, never random per render |
| Nature-inspired | Botanical, aquatic | Ginkgo, iris, water lily, peacock, dragonfly motifs | Stylised and flattened, never photographic clip-art |

### 1.2 Core Tenets

1. **The line is alive.** Every border, divider and underline is a drawn curve with a pen-pressure feel (taper from 2.5px to 0.75px), not a CSS `1px solid` default. Plain CSS borders are used only at L0.
2. **The S-curve rule (whiplash).** Decorative paths must contain at least one inflection point, where curvature reverses. A path that only bows one way reads as a generic rounded corner, not Nouveau.
3. **Botanical asymmetry.** Balance by weight, not mirror. A flourish on the top-left is answered by a smaller, differently shaped one at the bottom-right. Use roughly a 3:2 visual weight ratio.
4. **Craft integrated with structure.** Ornament is the container, not a sticker on it. The frame is the card border, the tendril is the divider, the leaf is the focus ring. If you can delete an ornament and nothing structural changes, move it into the structure or remove it.
5. **Abstract nature.** Reduce plants and animals to flowing silhouettes with 3–5 shape primitives. No gradients inside motif icons beyond a single flat tint plus a lead outline.
6. **Material honesty.** Surfaces imitate vellum, enamel, stained glass, patinated copper and gilt. Each has a defined token set (Sections 2 and 3), and they are never mixed on a single element.
7. **Modern translation.** Responsive, accessible, performant. Ornament is vector (SVG/CSS), lazy-loaded, and removable at L0 without layout shift.

### 1.3 Ornament Budget (anti-kitsch rules)

- One *hero flourish* per viewport (a large whiplash frame, cartouche or illustration).
- Maximum **two** accent hues plus gold in any single component.
- Gold is **decoration, never text** on light surfaces (see contrast data in Section 2).
- Ornaments never overlap body text. Reserve a 16px safe zone (`--an-safe`) between filigree and copy.
- On screens under 480px, drop the ornament level by one (L3 → L2, L2 → L1).

---

## 2. Color Palette & Organic Surface Tokens

### 2.1 Natural Foundation

| Token | Hex | Role |
|---|---|---|
| `--an-vellum` | `#F5F0EB` | Primary page background (warm parchment/vellum) |
| `--an-ivory` | `#EDE4D3` | Antique ivory: raised surfaces, input fields |
| `--an-parchment` | `#E3D6BF` | Aged parchment: wells, table stripes, pressed state |
| `--an-moss-900` | `#2D3B2D` | Deep moss: primary text, dark surfaces |
| `--an-moss-800` | `#3B4D3B` | Dark surface variant |
| `--an-moss-950` | `#1B251B` | Footer, deepest background, text on gold |
| `--an-lead` | `#3A2E26` | Burnt charcoal: lead lines, stained-glass cames |
| `--an-bronze` | `#6B4E2E` | Secondary linework, wrought-iron nav |

### 2.2 Art Nouveau Accent Palette

Each hue has a **decorative** step (fills, borders, glass tints) and a **text-safe** step (dark enough for AA text on vellum). Always pick the step for the job.

| Hue | Decorative token | Hex | Text/UI-safe token | Hex | Contrast of text-safe step on `#F5F0EB` |
|---|---|---|---|---|---|
| Peacock teal | `--an-teal-500` | `#2A8A94` | `--an-teal-700` | `#17606A` | 6.4 : 1 |
| Dusty rose | `--an-rose-500` | `#C99A98` | `--an-rose-700` | `#8A4B4F` | 5.8 : 1 |
| Burnt ochre | `--an-ochre-500` | `#B5651D` | `--an-ochre-700` | `#8F4A0F` | 5.9 : 1 |
| Sage | `--an-sage-500` | `#9CAF88` | `--an-sage-700` | `#5E7352` | 4.6 : 1 |
| Warm copper | `--an-copper-500` | `#B87333` | `--an-copper-700` | `#8A4F1E` | 5.8 : 1 |
| Gilded gold | `--an-gold-500` | `#D4AF37` | `--an-gold-700` | `#7A5C0F` | 5.5 : 1 |

Extra tints: `--an-gold-300 #E8D48A`, `--an-sage-300 #C5D1B5`, `--an-rose-300 #E6CFCD`, `--an-teal-300 #A9CFD3`, `--an-teal-900 #0F3F46`.

> Ratios are calculated with the WCAG 2.1 relative-luminance formula and rounded. Re-verify in your tooling (Stark, Figma contrast plugins, axe) after any hex edit.

**Key contrast facts**

| Pair | Ratio | Verdict |
|---|---|---|
| `--an-moss-900` on `--an-vellum` | ~10.5 : 1 | AAA body text |
| `--an-gold-500` on `--an-vellum` | ~1.9 : 1 | **Fails.** Decoration only |
| `--an-gold-500` on `--an-moss-900` | ~5.6 : 1 | AA text and icons on dark |
| `--an-copper-500` on `--an-vellum` | ~3.4 : 1 | Passes 3:1 for borders and icons, not text |
| `--an-teal-500` on `--an-vellum` | ~3.6 : 1 | Large text (24px+ or 19px bold) and UI only |
| `--an-vellum` on `--an-teal-700` | ~6.4 : 1 | Button label |

### 2.3 Semantic Tokens

```css
:root {
  /* primitives */
  --an-vellum:#F5F0EB; --an-ivory:#EDE4D3; --an-parchment:#E3D6BF;
  --an-moss-950:#1B251B; --an-moss-900:#2D3B2D; --an-moss-800:#3B4D3B;
  --an-lead:#3A2E26; --an-bronze:#6B4E2E;
  --an-teal-300:#A9CFD3; --an-teal-500:#2A8A94; --an-teal-700:#17606A; --an-teal-900:#0F3F46;
  --an-rose-300:#E6CFCD; --an-rose-500:#C99A98; --an-rose-700:#8A4B4F;
  --an-ochre-500:#B5651D; --an-ochre-700:#8F4A0F;
  --an-sage-300:#C5D1B5; --an-sage-500:#9CAF88; --an-sage-700:#5E7352;
  --an-copper-500:#B87333; --an-copper-700:#8A4F1E;
  --an-gold-300:#E8D48A; --an-gold-500:#D4AF37; --an-gold-700:#7A5C0F;

  /* semantic */
  --an-bg: var(--an-vellum);
  --an-surface: var(--an-ivory);
  --an-surface-sunken: var(--an-parchment);
  --an-text: var(--an-moss-900);
  --an-text-muted: #4F5B4A;            /* ~6.6:1 on vellum */
  --an-text-accent: var(--an-teal-700);
  --an-link: var(--an-teal-700);
  --an-link-hover: var(--an-teal-900);
  --an-line: var(--an-lead);
  --an-line-soft: color-mix(in srgb, var(--an-bronze) 35%, transparent);
  --an-gild: var(--an-gold-500);       /* decoration only on light */
  --an-gild-text: var(--an-gold-700);  /* text-safe gold on light */
  --an-focus: var(--an-teal-700);
  --an-danger: #9B2F2F;                /* ~6.6:1 on vellum */
  --an-success: var(--an-sage-700);
  --an-warning: var(--an-ochre-700);
  --an-safe: 16px;
}

[data-theme='night'] {
  --an-bg: var(--an-moss-950);
  --an-surface: var(--an-moss-900);
  --an-surface-sunken: #121A12;
  --an-text: var(--an-vellum);
  --an-text-muted: #CFC8B8;
  --an-text-accent: var(--an-gold-500);
  --an-link: var(--an-gold-300);
  --an-link-hover: #FFF1B8;
  --an-line: var(--an-gold-500);
  --an-gild-text: var(--an-gold-500);
  --an-focus: var(--an-gold-300);
}
```

### 2.4 Gradients & Atmospheric Surfaces

Gradients are **soft, low-chroma and warm**. Maximum two stops of hue plus a neutral, with at most a 12% lightness change. Never use saturated or neon colors, and never cool-white highlights.

| Token | Definition | Use |
|---|---|---|
| `--an-grad-paper` | `linear-gradient(170deg,#F8F4EE 0%,#F5F0EB 55%,#EFE6D8 100%)` | Page background |
| `--an-grad-dawn` | `radial-gradient(120% 90% at 20% 0%,#F3E3D2 0%,transparent 60%)` | Warm atmospheric tint, hero corner |
| `--an-grad-pond` | `linear-gradient(160deg,#A9CFD3 0%,#C5D1B5 100%)` | Water-lily / pond feature panels |
| `--an-grad-peacock` | `linear-gradient(155deg,#17606A 0%,#0F3F46 100%)` | Dark feature panels, hero buttons |
| `--an-grad-moss` | `linear-gradient(180deg,#3B4D3B 0%,#1B251B 100%)` | Footer, night theme |
| `--an-grad-gilt` | `linear-gradient(110deg,#B8932A 0%,#E8D48A 38%,#D4AF37 55%,#9C7A1C 100%)` | Gilded strokes and borders (never behind text) |
| `--an-glow-gilt` | `0 0 0 1px rgba(212,175,55,.55), 0 0 18px rgba(212,175,55,.35)` | Hover and active glow |

**Surface contrast rules**

1. Text sits on flat or near-flat surfaces. If a gradient lies behind text, the lightest and darkest points must both still meet 4.5:1.
2. Metallic highlights (gilt, copper) are 1–2px lines, small icons or glows, never full-bleed fills behind copy.
3. Elevation is expressed by warm shadows (`rgba(58,46,38,.18)`), never grey or black ones.
4. A subtle paper grain (SVG noise at 3–4% opacity, `mix-blend-mode: multiply`) is optional at L2/L3.

```css
body {
  background: var(--an-grad-paper), var(--an-bg);
  color: var(--an-text);
}
.an-grain::after {
  content:''; position:absolute; inset:0; pointer-events:none; opacity:.04; mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
}
```

---

## 3. Decorative Linework, Motifs & Border Engine

### 3.1 Whiplash Vector Mechanics

The *coup de fouet* (whiplash) is a curve that swells, reverses direction and snaps into a tight terminal curl. Use these rules for every authored SVG path.

| Parameter | Rule |
|---|---|
| Inflections | At least 1 per path; 2 for dividers longer than 240px |
| Curve type | Cubic Béziers (`C` / `S`), with smooth joins (control handles collinear) |
| Handle ratio | Control-point length = 30–45% of segment length (a longer handle gives a lazier, more organic swing) |
| Terminals | End in a spiral curl (r 4–10px) or a leaf-point; never a blunt butt cap on decorative paths |
| Stroke weight | Tapers 2.5px (root) → 0.75px (tip). For true taper, draw as a filled outline path; for simple cases, use `stroke-width: 1.5` with `stroke-linecap: round` |
| Asymmetry | Left/right or top/bottom halves differ in length by about 3:2 |
| Vine branching | Side shoots leave the stem at 25–50°, alternate sides, and shrink 15–25% per generation (max 3 generations) |
| Stroke color | `currentColor`, so ornaments inherit the theme (`--an-line`, `--an-gild`, etc.) |
| Optimisation | Max 12 anchor points per path, 2-decimal precision, inline `<symbol>` sprites |

**Tendril divider (reusable SVG)**

```html
<svg class='an-divider' viewBox='0 0 480 48' fill='none' stroke='currentColor'
     stroke-width='1.5' stroke-linecap='round' aria-hidden='true' focusable='false'>
  <!-- main stem: two inflections -->
  <path d='M4 26 C52 4 88 46 150 26 S214 6 240 26 S306 46 342 26 S424 6 476 24'/>
  <!-- central curl, answered by a smaller counter-curl -->
  <path d='M240 26 c-4-15 10-23 18-13 c6 8-3 15-9 10'/>
  <path d='M150 26 c4 11-5 17-11 12 c-4-4 0-9 4-7'/>
  <!-- leaf -->
  <path d='M342 26 c6-10 17-12 22-10 c-2 9-11 15-22 10 z'/>
</svg>
```

```css
.an-divider { width:100%; max-width:480px; height:auto; color:var(--an-gild); margin-inline:auto; display:block; }
/* On light surfaces pair gold with a bronze under-stroke to keep the line visible */
.an-divider { filter: drop-shadow(0 1px 0 color-mix(in srgb, var(--an-bronze) 40%, transparent)); }
```

> Decorative dividers are `aria-hidden`. Semantic separation uses `<hr>` or heading structure (see Section 6).

### 3.2 Frame & Border Specifications

| Frame | Construction | Use |
|---|---|---|
| **Hairline (L0)** | `1px solid var(--an-line-soft)` | Functional UI |
| **Triple-line (L1)** | Outer 2px lead, 1px gilt gap line, 1px bronze inner (CSS below) | Cards, modals, inputs |
| **Arched frame (L2)** | Triple-line + `border-radius: 999px 999px 12px 12px` top arch | Feature cards, portraits, product images |
| **Cartouche (L2)** | Ellipse/lozenge SVG nine-slice with scroll terminals | Pull-quotes, badges, section titles |
| **Whiplash frame (L3)** | Full SVG `border-image` with corner flourishes | Hero panels, campaign pages |

**Triple-line frame (pure CSS)**

```css
.an-frame {
  position: relative;
  background: var(--an-surface);
  border: 2px solid var(--an-lead);
  border-radius: 14px 28px 14px 28px;           /* asymmetric: 1:2 alternation */
  outline: 1px solid var(--an-gild);
  outline-offset: -7px;                         /* inner gilt hairline */
  box-shadow:
    0 0 0 4px var(--an-bg),                     /* breathing gap */
    0 0 0 5px var(--an-copper-500),             /* outer copper hairline */
    0 10px 28px -12px rgba(58,46,38,.35);       /* warm elevation */
  padding: calc(var(--an-safe) * 1.5);
}
```

**Arched corner flourish (inline SVG, reusable on all four corners via transforms)**

```css
.an-flourish::before,
.an-flourish::after {
  content:''; position:absolute; width:56px; height:56px; pointer-events:none;
  background: no-repeat center / contain
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 56 56' fill='none' stroke='%23B8932A' stroke-width='1.5' stroke-linecap='round'><path d='M2 54 C2 24 24 2 54 2'/><path d='M10 54 C10 32 30 10 54 10' stroke-width='1'/><path d='M2 30 c-3-9 6-14 11-8 c3 4-1 8-5 6'/><path d='M30 2 c9-3 14 6 8 11 c-4 3-8-1-6-5'/></svg>");
}
.an-flourish::before { top:-6px; left:-6px; }
.an-flourish::after  { bottom:-6px; right:-6px; transform: rotate(180deg) scale(.8); } /* smaller answer = asymmetry */
```

**Filigree header (section header lockup)**

```html
<header class='an-filigree'>
  <svg class='an-filigree__wing' aria-hidden='true'><use href='#an-wing'/></svg>
  <h2 class='an-h2'>The Iris Collection</h2>
  <svg class='an-filigree__wing an-filigree__wing--r' aria-hidden='true'><use href='#an-wing'/></svg>
</header>
```

```css
.an-filigree { display:grid; grid-template-columns: 1fr auto 1fr; align-items:center; gap:var(--an-safe); color:var(--an-gild); }
.an-filigree__wing { width:100%; height:24px; }
.an-filigree__wing--r { transform: scaleX(-1) scaleY(.85); } /* mirrored but not identical */
```

### 3.3 Stained Glass & Enamel Surface Math

**Glass anatomy:** a tinted translucent pane, a lead came (dark outline), and light that bleeds from behind.

| Layer | Spec |
|---|---|
| Pane tint | Hue at **22–35% alpha** over `--an-vellum` (light) or **30–45%** over moss (night) |
| Lead came | `1.5px solid var(--an-lead)` for panes, `2px` for the outer frame, `1px` for fine divisions |
| Backlight | Radial gradient of warm gold at 25–40% alpha from the pane centre or the top |
| Edge luminance | Inset glow `inset 0 0 24px rgba(232,212,138,.28)` |
| Blur | `backdrop-filter: blur(6px) saturate(1.1)` (optional; fall back to a solid tint) |
| Text on glass | Always use `--an-moss-900` (light) or `--an-vellum` (night). Verify 4.5:1 against the *worst-case* pane color (lightest tint over lightest background) |

**Pane tint tokens**

| Token | RGBA | Looks like |
|---|---|---|
| `--an-glass-teal` | `rgba(42,138,148,.28)` | Peacock-feather pane |
| `--an-glass-rose` | `rgba(201,154,152,.34)` | Dusty-rose pane |
| `--an-glass-ochre` | `rgba(181,101,29,.26)` | Amber pane |
| `--an-glass-sage` | `rgba(156,175,136,.34)` | Leaf pane |
| `--an-glass-gold` | `rgba(212,175,55,.22)` | Lamplit pane |

```css
.an-glass {
  --pane: var(--an-glass-teal);
  position: relative;
  isolation: isolate;
  background:
    radial-gradient(70% 60% at 50% 0%, rgba(232,212,138,.40), transparent 70%),  /* backlight */
    var(--pane);
  border: 1.5px solid var(--an-lead);                    /* lead came */
  border-radius: 999px 999px 10px 10px;                  /* arched window */
  box-shadow:
    inset 0 0 24px rgba(232,212,138,.28),                /* luminous edge */
    inset 0 0 0 4px color-mix(in srgb, var(--an-bg) 60%, transparent), /* matte mat */
    0 14px 30px -14px rgba(58,46,38,.45);
  backdrop-filter: blur(6px) saturate(1.1);
}
/* Lead divisions: a grid of thin lines drawn with gradients */
.an-glass--leaded {
  background-image:
    linear-gradient(var(--an-lead), var(--an-lead)),
    linear-gradient(90deg, var(--an-lead), var(--an-lead)),
    radial-gradient(70% 60% at 50% 0%, rgba(232,212,138,.40), transparent 70%);
  background-size: 100% 1.5px, 1.5px 100%, 100% 100%;
  background-position: 0 38%, 50% 0, 0 0;
  background-repeat: no-repeat;
  background-color: var(--pane);
}
@supports not (backdrop-filter: blur(1px)) { .an-glass { background-color: var(--an-ivory); } }
```

**Enamel (cloisonné) variant:** opaque pane (`--an-teal-700`, `--an-rose-700` etc.), a 1px gilt cell wall (`outline: 1px solid var(--an-gild)`), and a top-left specular highlight `linear-gradient(135deg, rgba(255,255,255,.18), transparent 40%)`. It works well for badges and tags, with `--an-vellum` text.

---

## 4. Typography & Floral Ornamentation

### 4.1 Type Families

| Role | Premium (licensed) | Open-source production stack | Notes |
|---|---|---|---|
| **Display / H1–H2** | Eckmann, Willow, Parisish, Mulberry Sans, Royal Acid | **Fraunces** (variable; `SOFT` 100, `WONK` 1, opsz 144) | Fraunces gives high contrast with soft, inky terminals that read as organic. Use the premium faces for logos and posters only, since their irregular letterforms lose legibility below 32px |
| **Subhead / H3–H4** | Cormorant Garamond SemiBold | **Cormorant Garamond** 600 | Elegant high-contrast serif. Use at 22px and up |
| **Body (long-form)** | EB Garamond, Lora | **Lora** 400/500 (or EB Garamond at 20px+) | Lora holds up better at 17–19px on screens than thin Garamonds |
| **UI / labels / captions** | Alegreya Sans | **Alegreya Sans** 500/700 | A humanistic sans with calligraphic rhythm, good for buttons and inputs |
| **Numerals / data** | Lora lining figures | `font-variant-numeric: lining-nums tabular-nums` | Keep old-style figures for editorial prose only |

> Keep to a maximum of **three families per page** (display, body, UI). Self-host WOFF2 with `font-display: swap`, subset to Latin plus the ornament glyphs you use, and preload the display and body files only.

### 4.2 Type Scale (fluid, 1.25 major-third with an editorial bump at display sizes)

| Token | Font | Size (clamp) | Line-height | Tracking | Weight |
|---|---|---|---|---|---|
| `--an-fs-display` | Display | `clamp(3rem, 2rem + 5vw, 6rem)` | 1.02 | -0.01em | 600 |
| `--an-fs-h1` | Display | `clamp(2.25rem, 1.6rem + 3vw, 3.75rem)` | 1.08 | -0.005em | 600 |
| `--an-fs-h2` | Display | `clamp(1.75rem, 1.4rem + 1.6vw, 2.5rem)` | 1.15 | 0 | 600 |
| `--an-fs-h3` | Cormorant | `clamp(1.375rem, 1.2rem + .8vw, 1.75rem)` | 1.25 | 0.005em | 600 |
| `--an-fs-body` | Lora | `clamp(1.0625rem, 1rem + .3vw, 1.1875rem)` | 1.7 | 0 | 400 |
| `--an-fs-ui` | Alegreya Sans | `1rem` | 1.4 | 0.02em | 500 |
| `--an-fs-caption` | Alegreya Sans | `.875rem` | 1.45 | 0.03em | 500 |
| `--an-fs-overline` | Alegreya Sans | `.8125rem` | 1.3 | 0.16em, uppercase | 700 |

```css
:root {
  --an-font-display: 'Fraunces', 'Cormorant Garamond', Georgia, serif;
  --an-font-serif:   'Cormorant Garamond', 'EB Garamond', Georgia, serif;
  --an-font-body:    'Lora', 'EB Garamond', Georgia, serif;
  --an-font-ui:      'Alegreya Sans', 'Source Sans 3', system-ui, sans-serif;
  --an-measure: 66ch;                       /* optimal line length: 60-72 characters */
}
body { font-family: var(--an-font-body); font-size: var(--an-fs-body); line-height: 1.7; }
h1, h2, .an-display {
  font-family: var(--an-font-display);
  font-variation-settings: 'SOFT' 100, 'WONK' 1, 'opsz' 144;
  font-weight: 600; text-wrap: balance; color: var(--an-text);
}
p, li { max-width: var(--an-measure); text-wrap: pretty; hanging-punctuation: first; }
.an-overline { font: 700 .8125rem/1.3 var(--an-font-ui); letter-spacing: .16em; text-transform: uppercase; color: var(--an-gild-text); }
```

If you use a licensed face such as Eckmann for display, apply it only to `.an-display--lettering` (logo, hero word, poster headline) at 40px or larger, keep the semantic heading in the DOM, and give it a Fraunces fallback so the page never depends on one font file.

### 4.3 Floral Drop-Caps

The drop-cap occupies 3 lines and sits inside a tendril-wrapped medallion. The letter itself stays live text (screen readers read it normally); the tendril is a background SVG.

```css
.an-dropcap::first-letter {
  font-family: var(--an-font-display);
  font-weight: 700;
  font-size: 4.6em;
  line-height: .82;
  float: left;
  padding: .08em .14em .02em .06em;
  margin: .04em .12em 0 0;
  color: var(--an-teal-700);
  background:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' fill='none' stroke='%23B8932A' stroke-width='1.6' stroke-linecap='round'><path d='M6 70 C2 36 30 6 64 8 C86 10 96 28 92 44'/><path d='M12 94 C34 84 48 90 62 78'/><path d='M92 44 c8-6 4-18-6-16'/><path d='M6 70 c-6 6-2 16 6 14'/></svg>") no-repeat center / 118% 118%;
}
@media (max-width: 480px) { .an-dropcap::first-letter { font-size: 3.4em; } }
```

### 4.4 Ornamental Bullets & Section Marks

Bullets are SVG masks, 1em square, colored with `background-color` through the mask so they inherit the theme.

| Ornament | Token | Use |
|---|---|---|
| Ginkgo leaf | `--an-bullet-ginkgo` | Default list bullet (editorial) |
| Water lily | `--an-bullet-lily` | Feature lists, pricing benefits |
| Peacock feather | `--an-bullet-peacock` | Highlights and "new" markers |
| Iris bud | `--an-bullet-iris` | Nested (level 2) lists |
| Dragonfly | `--an-mark-dragonfly` | Section end-mark (replaces the fleuron) |

```css
.an-list { list-style: none; padding-inline-start: 0; }
.an-list > li { position: relative; padding-inline-start: 1.75em; margin-block: .55em; }
.an-list > li::before {
  content: ''; position: absolute; inset-inline-start: 0; top: .38em; width: 1.05em; height: 1.05em;
  background-color: var(--an-teal-700);
  -webkit-mask: var(--an-bullet-ginkgo) no-repeat center / contain;
          mask: var(--an-bullet-ginkgo) no-repeat center / contain;
}
/* ginkgo leaf: fan-shaped with a central notch */
:root {
  --an-bullet-ginkgo: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 22 V13 M12 13 C6 13 2 8 3 3 C6 5 9 5 12 8 C15 5 18 5 21 3 C22 8 18 13 12 13 Z' fill='black'/></svg>");
}
.an-list--lily > li::before { -webkit-mask-image: var(--an-bullet-lily); mask-image: var(--an-bullet-lily); background-color: var(--an-rose-700); }
```

**Section ornaments:** use a centered tendril divider (3.1) for chapter breaks, a single dragonfly mark for end-of-article, and a small three-leaf cluster as the `<hr>` replacement inside long prose.

---

## 5. Component Specifications & Mechanics

All components inherit: warm shadows, asymmetric radii, lead-line borders, `--an-focus` focus ring, and the motion tokens from Section 6. Minimum touch target is **44×44px**.

### 5.1 Buttons & Interactive Controls

| Variant | Surface | Border | Label | Hover | Active (pressed) |
|---|---|---|---|---|---|
| **Primary** | `--an-grad-peacock` | 1.5px `--an-lead` + 1px inner gilt | `--an-vellum`, Alegreya Sans 700 | Gilt glow `--an-glow-gilt`, lift 1px | Inset shadow, translateY(1px), glow fades |
| **Secondary** | Transparent over `--an-surface` | 1.5px `--an-teal-700` | `--an-teal-700` | Fills with `--an-teal-300` at 35% | Fills with `--an-teal-300` at 55% |
| **Gilded (hero only)** | `--an-moss-950` | 1.5px `--an-gold-500` | `--an-gold-300` (9:1 on moss) | Gilt glow + shimmering border sweep | Inset glow |
| **Ghost / text** | None | Underline as drawn tendril | `--an-link` | Tendril lengthens (`background-size`) | Color `--an-link-hover` |
| **Icon button** | `--an-ivory` | Arched (`999px 999px 10px 10px`) | Icon `--an-moss-900` | Gilt glow | Inset |

**Silhouette:** the base shape is a "pointed arch pill": `border-radius: 28px 28px 28px 10px`, a slightly different corner from the others, which lends hand-cut character without compromising the hit area.

```css
.an-btn {
  --btn-bg: var(--an-grad-peacock);
  --btn-fg: var(--an-vellum);
  position: relative; display: inline-flex; align-items: center; justify-content: center; gap: .6em;
  min-height: 44px; padding: .75em 1.6em;
  font: 700 1rem/1.2 var(--an-font-ui); letter-spacing: .04em;
  color: var(--btn-fg); background: var(--btn-bg);
  border: 1.5px solid var(--an-lead);
  border-radius: 28px 28px 28px 10px;
  box-shadow: inset 0 0 0 3px rgba(232,212,138,.55), 0 6px 14px -8px rgba(58,46,38,.55);
  cursor: pointer;
  transition: box-shadow var(--an-dur-md) var(--an-ease-vine),
              transform var(--an-dur-sm) var(--an-ease-water),
              filter var(--an-dur-md) var(--an-ease-vine);
}
.an-btn:hover  { box-shadow: inset 0 0 0 3px rgba(232,212,138,.9), var(--an-glow-gilt); transform: translateY(-1px); }
.an-btn:active { transform: translateY(1px); box-shadow: inset 0 3px 8px rgba(0,0,0,.35); filter: brightness(.96); }
.an-btn:focus-visible { outline: 3px solid var(--an-focus); outline-offset: 3px; }
.an-btn[aria-disabled='true'] { opacity: .55; cursor: not-allowed; box-shadow: none; }
.an-btn--secondary { --btn-bg: transparent; --btn-fg: var(--an-teal-700); border-color: var(--an-teal-700); box-shadow: none; }
.an-btn--secondary:hover { background: color-mix(in srgb, var(--an-teal-300) 35%, transparent); }
```

**Ghost-link tendril underline**

```css
.an-link {
  color: var(--an-link);
  text-decoration: underline 1px;              /* static underline stays as the baseline */
  text-underline-offset: .22em;
  background: no-repeat left bottom / 0% 6px
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 6' preserveAspectRatio='none' fill='none' stroke='%2317606A' stroke-width='1.4'><path d='M0 4 C20 0 30 6 50 3 S80 0 100 3'/></svg>");
  transition: background-size var(--an-dur-md) var(--an-ease-vine);
}
.an-link:hover, .an-link:focus-visible { background-size: 100% 6px; }
```

### 5.2 Cards & Content Containers

| Card type | Shape | Header | Surface | Shadow / depth |
|---|---|---|---|---|
| **Arch card** (default L2) | Top arch `999px 999px 14px 14px` image window, body below | Cartouche banner overlapping the arch base | `--an-surface` | Triple-line frame + warm lift |
| **Asymmetric card** (L1) | `14px 28px 14px 28px` | Overline + H3, with a short tendril under it | `--an-surface` | Hairline + soft shadow |
| **Glass card** (L3) | Arched window (3.3) | Gilt overline | Pane tint + backlight | Luminous inset |
| **Data card** (L0) | `6px` radius | Plain | `--an-bg` | `1px --an-line-soft` |

**Inner vignette:** to give the vellum a lived-in feel, add `box-shadow: inset 0 0 60px rgba(139,105,60,.14)`, a warm sepia shading at the edges only (never greater than 18% alpha).

```html
<article class='an-card an-card--arch an-flourish'>
  <figure class='an-card__arch'><img src='iris.jpg' alt='Hand-colored iris lithograph' loading='lazy'></figure>
  <div class='an-card__banner'><span class='an-overline'>Collection No. 7</span></div>
  <div class='an-card__body'>
    <h3 class='an-h3'>The Iris Folio</h3>
    <p>Twelve plates of swaying stems, printed on cotton rag.</p>
    <a class='an-btn an-btn--secondary' href='#'>View the folio</a>
  </div>
</article>
```

```css
.an-card { position: relative; background: var(--an-surface); border: 2px solid var(--an-lead);
  border-radius: 14px 28px 14px 28px; box-shadow: inset 0 0 60px rgba(139,105,60,.14), 0 10px 28px -14px rgba(58,46,38,.4); }
.an-card--arch { border-radius: 999px 999px 14px 14px / 40% 40% 14px 14px; }
.an-card__arch { margin: 10px; aspect-ratio: 4/5; overflow: hidden; border-radius: 999px 999px 8px 8px; border: 1.5px solid var(--an-gild); }
.an-card__arch img { width: 100%; height: 100%; object-fit: cover; }
.an-card__banner { display:grid; place-items:center; margin: -22px 24px 0; position:relative; padding:.5em 1.2em;
  background: var(--an-vellum); border: 1.5px solid var(--an-lead); border-radius: 999px 999px 999px 8px; }
.an-card__body { padding: calc(var(--an-safe) * 1.5); display: grid; gap: .75rem; }
```

### 5.3 Form Fields & Inputs

**Anatomy:** a parchment-tinted field framed by a delicate double stroke, with the label above in Alegreya Sans, helper text below, and a leaf or tendril motif that grows on focus. The leaf is *additional* to a standard high-contrast focus outline, never a replacement for it.

| State | Field background | Border | Extra |
|---|---|---|---|
| Default | `--an-ivory` | 1.5px `--an-bronze` (comfortably above 3:1 on vellum) | none |
| Hover | `--an-ivory` | `--an-copper-700` | none |
| Focus | `--an-vellum` | 2px `--an-teal-700` | 3px outer `--an-gold-300` ring; leaf tendril unfurls at the right edge |
| Filled | `--an-ivory` | `--an-bronze` | none |
| Error | `#F6E3E1` | 2px `--an-danger` | Thorn icon and text message (not color alone) |
| Success | `#E8EFE0` | 2px `--an-sage-700` | Leaf-check icon and text message |
| Disabled | `--an-parchment` | 1px dashed `--an-line-soft` | `aria-disabled` and reduced opacity |

```css
.an-field { display: grid; gap: .4rem; position: relative; }
.an-field label { font: 700 .9375rem/1.3 var(--an-font-ui); letter-spacing: .03em; color: var(--an-text); }
.an-input {
  min-height: 48px; padding: .7em 3em .7em 1em;
  font: 400 1rem/1.4 var(--an-font-body); color: var(--an-text);
  background: var(--an-ivory);
  border: 1.5px solid var(--an-bronze);
  border-radius: 10px 20px 10px 20px;
  box-shadow: inset 0 2px 5px rgba(58,46,38,.12), 0 0 0 3px transparent;
  transition: border-color var(--an-dur-md) var(--an-ease-vine), box-shadow var(--an-dur-md) var(--an-ease-vine), background var(--an-dur-md) var(--an-ease-vine);
}
.an-input::placeholder { color: #6A6455; }                 /* verify >= 4.5:1 on ivory in your tooling */
.an-input:hover  { border-color: var(--an-copper-700); }
.an-input:focus-visible {
  outline: 2px solid var(--an-focus); outline-offset: 2px;  /* high-contrast ring, required */
  background: var(--an-vellum);
  box-shadow: inset 0 2px 5px rgba(58,46,38,.08), 0 0 0 5px color-mix(in srgb, var(--an-gold-300) 70%, transparent);
}
/* leaf-tendril unfurl: decorative, sits in the reserved right padding */
.an-field::after {
  content:''; position:absolute; right: 12px; bottom: 12px; width: 26px; height: 26px; opacity: 0; transform: scale(.6) rotate(-25deg); transform-origin: bottom left;
  background: no-repeat center / contain url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 26 26' fill='none' stroke='%2317606A' stroke-width='1.5' stroke-linecap='round'><path d='M3 23 C4 12 12 5 23 3 C23 14 15 22 3 23 Z'/><path d='M3 23 C9 17 14 12 20 6'/></svg>");
  transition: opacity var(--an-dur-md) var(--an-ease-vine), transform var(--an-dur-lg) var(--an-ease-vine);
  pointer-events: none;
}
.an-field:focus-within::after { opacity: 1; transform: scale(1) rotate(0); }
.an-input[aria-invalid='true'] { border-color: var(--an-danger); border-width: 2px; background: #F6E3E1; }
.an-help, .an-error { font: 500 .875rem/1.45 var(--an-font-ui); }
.an-error { color: var(--an-danger); display: flex; gap: .4em; }  /* prefix with an icon and text */
```

### 5.4 Navigation & Header Bars

**Desktop:** a wrought-iron or stained-glass bar with the logo set in a central cartouche, nav items split asymmetrically (3 left, 2 right), and flowing arched dropdowns.

| Part | Spec |
|---|---|
| Bar | 72px high, `--an-moss-950` (wrought-iron variant) or `--an-glass-teal` over a deep backdrop (glass variant), a 2px gilt bottom stroke that dips into a shallow S-curve around the logo |
| Items | Alegreya Sans 700, 1rem, tracking .06em, `--an-vellum` on moss (very high contrast) |
| Active item | Gilt underline plus `aria-current='page'` |
| Dropdown | Arched panel, `border-radius: 0 0 40% 40% / 0 0 14px 14px`, `--an-surface`, triple-line frame, items stagger in at 60ms |
| Mobile | 56px bar, full-screen stained-glass sheet, arched menu items 56px high, close control top-right |

```css
.an-nav { position: sticky; top: 0; z-index: 50; min-height: 72px; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  padding-inline: clamp(1rem, 4vw, 3rem); color: var(--an-vellum); background: var(--an-moss-950);
  border-bottom: 2px solid var(--an-gold-500); }
.an-nav::after { content:''; position:absolute; left:50%; bottom:-14px; width:140px; height:14px; transform:translateX(-50%);
  background: var(--an-moss-950); border: 2px solid var(--an-gold-500); border-top: 0; border-radius: 0 0 70px 70px / 0 0 14px 14px; }
.an-nav a { color: inherit; font: 700 1rem/1 var(--an-font-ui); letter-spacing: .06em; padding: .9em .6em; }
.an-nav a[aria-current='page'] { box-shadow: inset 0 -2px 0 var(--an-gold-500); }
.an-nav a:focus-visible { outline: 3px solid var(--an-gold-300); outline-offset: 2px; }
.an-menu { position: absolute; min-width: 260px; margin-top: 10px; padding: 1rem 1.25rem 1.5rem;
  background: var(--an-surface); color: var(--an-text); border: 2px solid var(--an-lead);
  border-radius: 0 0 40% 40% / 0 0 14px 14px; transform-origin: top center;
  opacity: 0; transform: translateY(-8px) scaleY(.96); visibility: hidden;
  transition: opacity var(--an-dur-md) var(--an-ease-vine), transform var(--an-dur-md) var(--an-ease-vine), visibility 0s linear var(--an-dur-md); }
.an-menu[data-open='true'] { opacity: 1; transform: none; visibility: visible; transition-delay: 0s; }
```

> Dropdowns open on click or Enter/Space (not hover only), close on Esc, and return focus to the trigger. Use `aria-expanded` and `aria-controls`.

---

## 6. Motion, Micro-Interactions & Accessibility

### 6.1 Kinetic Rules

Motion should feel like a vine swaying in a breeze or water finding its level: long ease-in-out curves, soft starts and soft stops, no linear, no spring overshoot.

| Token | Value | Use |
|---|---|---|
| `--an-ease-vine` | `cubic-bezier(.45, .05, .25, 1)` | Default: reveals, hovers, color and shadow changes |
| `--an-ease-water` | `cubic-bezier(.37, 0, .18, 1)` | Press, slide, move across the layout |
| `--an-ease-sway` | `cubic-bezier(.4, 0, .6, 1)` | Looping idle sway (symmetric) |
| `--an-dur-sm` | `300ms` | Hover, press, focus |
| `--an-dur-md` | `450ms` | Dropdowns, tooltips, tendril draw |
| `--an-dur-lg` | `600ms` | Page-section reveals, modals, ornament unfurl |
| `--an-stagger` | `60ms` (max 6 items) | Lists, menu items, card grids |

| Interaction | Choreography |
|---|---|
| **Tendril draw-in** | SVG path `stroke-dasharray` equals path length, `stroke-dashoffset` animates to 0 over 600ms using `--an-ease-vine` |
| **Leaf unfurl** | `scale(.6) rotate(-25deg)` → identity, transform-origin at the stem base, 600ms |
| **Gilt shimmer** (hover) | A 110° highlight sweeps across the border once, 600ms, no loop |
| **Page / section reveal** | Fade plus 12px rise, staggered by 60ms |
| **Idle sway (L3 only)** | ±1.5° rotation, 6–8s loop on hero flourishes, paused when off-screen |
| **Modal** | Arch opens upward from its base: `clip-path: inset(100% 0 0 0 round 999px 999px 0 0)` → `inset(0)` over 600ms |

```css
:root {
  --an-ease-vine: cubic-bezier(.45,.05,.25,1);
  --an-ease-water: cubic-bezier(.37,0,.18,1);
  --an-ease-sway: cubic-bezier(.4,0,.6,1);
  --an-dur-sm: 300ms; --an-dur-md: 450ms; --an-dur-lg: 600ms;
}
.an-draw path { stroke-dasharray: var(--len, 600); stroke-dashoffset: var(--len, 600);
  animation: an-draw var(--an-dur-lg) var(--an-ease-vine) forwards; }
@keyframes an-draw { to { stroke-dashoffset: 0; } }
.an-sway { animation: an-sway 7s var(--an-ease-sway) infinite alternate; transform-origin: 50% 100%; }
@keyframes an-sway { from { transform: rotate(-1.5deg); } to { transform: rotate(1.5deg); } }
.an-shimmer:hover::before { animation: an-shimmer var(--an-dur-lg) var(--an-ease-vine) 1; }
@keyframes an-shimmer { from { background-position: -150% 0; } to { background-position: 250% 0; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important; }
  .an-sway { animation: none; }
  .an-draw path { stroke-dashoffset: 0; }          /* draw the finished state immediately */
}
```

### 6.2 Accessibility (WCAG 2.1 AA)

**Contrast rules for thin and metallic ornament**

| Element | Requirement | Implementation |
|---|---|---|
| Body and UI text | 4.5 : 1 (1.4.3) | `--an-text` and `--an-text-muted` on `--an-bg` / `--an-surface`; `--an-moss-900` on vellum is ~10.5:1 |
| Large text (24px+, or 18.66px bold) | 3 : 1 | Teal-500 allowed here, never for body |
| Meaningful icons, input borders, focus rings | 3 : 1 against adjacent colors (1.4.11) | `--an-bronze`, `--an-copper-500` (~3.4:1), `--an-teal-700` |
| **Antique gold** | Decorative only on light surfaces (~1.9:1). As text or a meaningful icon use `--an-gild-text` `#7A5C0F` (~5.5:1) on light, or `--an-gold-500` on moss (~5.6:1) | Pair gold hairlines with a bronze or lead under-stroke so the shape remains perceivable |
| Thin filigree (<2px) | Never carries meaning on its own | Treated as decoration: `aria-hidden='true'`; any meaning is duplicated in text or a heavier-weight icon |
| Text over ornament or glass | 4.5 : 1 at the worst-case pixel | Keep a 16px `--an-safe` zone, or put a `--an-surface` plate behind the copy |
| Focus indicator (2.4.7) | Visible, 3:1, not clipped | 2–3px solid `--an-focus` with 2–3px offset; leaf and glow effects are additional |
| Target size | 44×44px minimum | Ornamental corners must never extend or shrink hit areas |
| Color independence (1.4.1) | State is never color-only | Error = thorn icon plus message; success = leaf-check plus message; links underlined in prose |
| Reflow and zoom (1.4.10, 1.4.4) | Works at 320px and 200% zoom | Ornaments scale with `em`/`%`, and the ornament level drops on small screens |
| Motion (2.3.3, 2.2.2) | No flashing; idle motion pausable; `prefers-reduced-motion` respected | See 6.1; sway is L3-only and pauses when out of view |
| Forced colors (Windows High Contrast) | Borders survive | See the snippet below |

```css
@media (forced-colors: active) {
  .an-frame, .an-card, .an-input, .an-btn { border: 2px solid CanvasText; outline-color: Highlight; box-shadow: none; }
  .an-glass { background: Canvas; backdrop-filter: none; }
  .an-flourish::before, .an-flourish::after { display: none; }
}
@media (prefers-contrast: more) {
  :root { --an-line-soft: var(--an-lead); --an-text-muted: var(--an-moss-900); --an-gild: var(--an-gold-700); }
}
```

**Semantic and screen-reader guidance:** decorative SVGs are `aria-hidden='true' focusable='false'`; drop-caps remain real text in the DOM; section ornaments never replace `<h2>` or `<hr>`; dropdown menus use the disclosure pattern with `aria-expanded`; stained-glass imagery has no text baked into raster images.

---

## 7. Implementation Exports

### 7.1 Tailwind CSS Configuration (v3 `tailwind.config.js`)

```js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ['./src/**/*.{html,js,jsx,ts,tsx,mdx}'],
  theme: {
    extend: {
      colors: {
        vellum: '#F5F0EB', ivory: '#EDE4D3', parchment: '#E3D6BF',
        moss: { 800: '#3B4D3B', 900: '#2D3B2D', 950: '#1B251B' },
        lead: '#3A2E26', bronze: '#6B4E2E',
        teal:   { 300: '#A9CFD3', 500: '#2A8A94', 700: '#17606A', 900: '#0F3F46' },
        rose:   { 300: '#E6CFCD', 500: '#C99A98', 700: '#8A4B4F' },
        ochre:  { 500: '#B5651D', 700: '#8F4A0F' },
        sage:   { 300: '#C5D1B5', 500: '#9CAF88', 700: '#5E7352' },
        copper: { 500: '#B87333', 700: '#8A4F1E' },
        gold:   { 300: '#E8D48A', 500: '#D4AF37', 700: '#7A5C0F' },
      },
      fontFamily: {
        display: ['Fraunces', 'Cormorant Garamond', 'Georgia', 'serif'],
        serif:   ['Cormorant Garamond', 'EB Garamond', 'Georgia', 'serif'],
        body:    ['Lora', 'EB Garamond', 'Georgia', 'serif'],
        ui:      ['Alegreya Sans', 'Source Sans 3', 'system-ui', 'sans-serif'],
      },
      fontSize: {
        display: ['clamp(3rem,2rem+5vw,6rem)', { lineHeight: '1.02', letterSpacing: '-0.01em' }],
        h1: ['clamp(2.25rem,1.6rem+3vw,3.75rem)', { lineHeight: '1.08' }],
        h2: ['clamp(1.75rem,1.4rem+1.6vw,2.5rem)', { lineHeight: '1.15' }],
        h3: ['clamp(1.375rem,1.2rem+.8vw,1.75rem)', { lineHeight: '1.25' }],
        body: ['clamp(1.0625rem,1rem+.3vw,1.1875rem)', { lineHeight: '1.7' }],
      },
      borderRadius: {
        arch: '999px 999px 14px 14px',
        leaf: '14px 28px 14px 28px',
        petal: '28px 28px 28px 10px',
        field: '10px 20px 10px 20px',
      },
      boxShadow: {
        warm: '0 10px 28px -14px rgba(58,46,38,.4)',
        gilt: '0 0 0 1px rgba(212,175,55,.55), 0 0 18px rgba(212,175,55,.35)',
        vignette: 'inset 0 0 60px rgba(139,105,60,.14)',
        glass: 'inset 0 0 24px rgba(232,212,138,.28), 0 14px 30px -14px rgba(58,46,38,.45)',
      },
      backgroundImage: {
        paper: 'linear-gradient(170deg,#F8F4EE 0%,#F5F0EB 55%,#EFE6D8 100%)',
        peacock: 'linear-gradient(155deg,#17606A 0%,#0F3F46 100%)',
        pond: 'linear-gradient(160deg,#A9CFD3 0%,#C5D1B5 100%)',
        gilt: 'linear-gradient(110deg,#B8932A 0%,#E8D48A 38%,#D4AF37 55%,#9C7A1C 100%)',
      },
      transitionTimingFunction: {
        vine: 'cubic-bezier(.45,.05,.25,1)',
        water: 'cubic-bezier(.37,0,.18,1)',
        sway: 'cubic-bezier(.4,0,.6,1)',
      },
      transitionDuration: { sm: '300ms', md: '450ms', lg: '600ms' },
      keyframes: {
        draw: { to: { strokeDashoffset: '0' } },
        sway: { from: { transform: 'rotate(-1.5deg)' }, to: { transform: 'rotate(1.5deg)' } },
      },
      animation: {
        draw: 'draw 600ms cubic-bezier(.45,.05,.25,1) forwards',
        sway: 'sway 7s cubic-bezier(.4,0,.6,1) infinite alternate',
      },
    },
  },
  plugins: [],
};
```

**Example utility composition**

```html
<button class='min-h-[44px] rounded-petal border-[1.5px] border-lead bg-peacock px-6 py-3 font-ui font-bold tracking-wide text-vellum
               shadow-warm transition duration-md ease-vine hover:-translate-y-px hover:shadow-gilt active:translate-y-px
               focus-visible:outline focus-visible:outline-[3px] focus-visible:outline-offset-[3px] focus-visible:outline-teal-700
               motion-reduce:transition-none'>
  Begin the journey
</button>
```

### 7.2 Figma Variables & Tokens Studio JSON

**Figma variable collections**

| Collection | Modes | Contents |
|---|---|---|
| `Primitives` | none | All `--an-*` hex values, grouped `color/moss/900`, `color/gold/500`, etc. |
| `Semantic` | `Day`, `Night` | `bg`, `surface`, `text`, `text-muted`, `link`, `line`, `gild`, `gild-text`, `focus`, `danger`, `success` (alias to Primitives) |
| `Shape` | none | `radius/arch`, `radius/leaf`, `radius/petal`, `radius/field`, `stroke/lead 1.5`, `stroke/frame 2`, `stroke/hair 1` |
| `Motion` | none | `dur/sm 300`, `dur/md 450`, `dur/lg 600`; easing as text styles for handoff |
| `Density` | `L0`, `L1`, `L2`, `L3` | `ornament/visible` (boolean), `ornament/scale`, `safe-zone` |

**Tokens Studio (JSON, partial)**

```json
{
  "primitives": {
    "color": {
      "vellum":  { "value": "#F5F0EB", "type": "color" },
      "ivory":   { "value": "#EDE4D3", "type": "color" },
      "moss":    { "900": { "value": "#2D3B2D", "type": "color" }, "950": { "value": "#1B251B", "type": "color" } },
      "teal":    { "500": { "value": "#2A8A94", "type": "color" }, "700": { "value": "#17606A", "type": "color" } },
      "rose":    { "700": { "value": "#8A4B4F", "type": "color" } },
      "ochre":   { "700": { "value": "#8F4A0F", "type": "color" } },
      "sage":    { "700": { "value": "#5E7352", "type": "color" } },
      "copper":  { "500": { "value": "#B87333", "type": "color" } },
      "gold":    { "500": { "value": "#D4AF37", "type": "color" }, "700": { "value": "#7A5C0F", "type": "color" } },
      "lead":    { "value": "#3A2E26", "type": "color" }
    }
  },
  "semantic-day": {
    "bg":        { "value": "{primitives.color.vellum}", "type": "color" },
    "surface":   { "value": "{primitives.color.ivory}", "type": "color" },
    "text":      { "value": "{primitives.color.moss.900}", "type": "color" },
    "link":      { "value": "{primitives.color.teal.700}", "type": "color" },
    "gild":      { "value": "{primitives.color.gold.500}", "type": "color" },
    "gild-text": { "value": "{primitives.color.gold.700}", "type": "color" },
    "line":      { "value": "{primitives.color.lead}", "type": "color" }
  },
  "semantic-night": {
    "bg":        { "value": "{primitives.color.moss.950}", "type": "color" },
    "surface":   { "value": "{primitives.color.moss.900}", "type": "color" },
    "text":      { "value": "{primitives.color.vellum}", "type": "color" },
    "link":      { "value": "#E8D48A", "type": "color" },
    "gild-text": { "value": "{primitives.color.gold.500}", "type": "color" },
    "line":      { "value": "{primitives.color.gold.500}", "type": "color" }
  },
  "shape": {
    "radius-arch":  { "value": "999 999 14 14", "type": "borderRadius" },
    "radius-leaf":  { "value": "14 28 14 28", "type": "borderRadius" },
    "radius-petal": { "value": "28 28 28 10", "type": "borderRadius" },
    "stroke-lead":  { "value": "1.5", "type": "borderWidth" }
  },
  "shadow": {
    "warm": { "value": { "x": "0", "y": "10", "blur": "28", "spread": "-14", "color": "#3A2E2666", "type": "dropShadow" }, "type": "boxShadow" },
    "gilt": { "value": { "x": "0", "y": "0", "blur": "18", "spread": "0", "color": "#D4AF3759", "type": "dropShadow" }, "type": "boxShadow" }
  },
  "motion": {
    "dur-sm": { "value": "300", "type": "duration" },
    "dur-md": { "value": "450", "type": "duration" },
    "dur-lg": { "value": "600", "type": "duration" }
  }
}
```

**Figma component construction notes**

- Build ornaments as **vector components** with stroke bound to variables (`Semantic/gild` or `line`), so they re-theme in Night mode.
- Use **Component Properties**: `Ornament level` (L0–L3), `Corner flourish` (on/off), `State` (default, hover, focus, pressed, disabled, error).
- Use **Boolean variants** for `Show filigree`, wired to the `Density` mode so a frame switches L3 → L1 without rebuilding.
- Use **Auto layout** with an explicit `safe-zone` padding variable so ornament never collides with content.
- Record the prototype easing as custom Bézier `(.45, .05, .25, 1)` with durations of 300/450/600ms.

---

## 8. Quality Checklist (Definition of Done)

| Check | Pass condition |
|---|---|
| Whiplash test | Every decorative path has at least one inflection and a curled or leaf terminal |
| Asymmetry test | Opposite corners or sides differ in size or shape (about 3:2) |
| Ornament budget | One hero flourish per viewport; no ornament overlaps text |
| Gold audit | No gold-500 text on light surfaces; `gild-text` used instead |
| Contrast audit | All text 4.5:1 (3:1 for large text), all UI boundaries and focus rings 3:1 |
| Focus audit | Every interactive element has a visible `:focus-visible` ring that is not clipped by ornament |
| Motion audit | Durations 300–600ms, eased with vine or water curves, no linear, no flashing; reduced-motion verified |
| Performance | Ornament SVG sprite < 30KB gzipped; fonts subset; glass `backdrop-filter` limited to 3 per viewport |
| Density behavior | L3 → L2 → L1 degradation verified at 480px and 320px; zero layout shift when ornament is hidden |
| Forced-colors and print | Borders remain visible in forced-colors; print stylesheet removes glass and gradients, keeps lead lines |
