---
version: alpha
name: Letterboxd
description: A cool blue-black canvas where serif headlines and a singular electric green turn film-watching into a social ritual.

colors:
  # Primary canvas + surfaces
  background: "#14181c"
  surface: "#2c3440"
  surface-elevated: "#12161a"

  # Brand accent — the singular Letterboxd green
  primary: "#00e054"
  primary-cta: "#00ac1c"
  primary-cta-active: "#009926"
  on-primary: "#ffffff"
  on-primary-active: "#cbead3"
  badge-brand: "#00c030"

  # Text scale — cool-blue gray ramp on dark
  ink: "#99aabb"
  ink-display: "#aabbcc"
  ink-high-emphasis: "#ddeeff"
  ink-bold-link: "#d8e0e8"
  ink-on-dark: "#ffffff"
  ink-muted: "#778899"
  ink-subtle: "#667788"
  ink-disabled: "#556677"
  ink-tertiary: "#8899aa"

  # Interactive accents
  link: "#209ce4"
  link-hover: "#40bcf4"
  accent-warm: "#ff9933"
  accent-warm-strong: "#ff8000"
  accent-warm-surface: "#ee7000"

  # Status
  destructive: "#ec1200"
  destructive-active: "#c40f00"
  rating-active: "#15953b"

  # Borders + dividers (flattened from inset/alpha shadows for Google format)
  border-rule: "#99aabb"   # 1px section underlines
  border-muted: "#556677"  # secondary input borders
  border-strong: "#445566" # was rgb(68, 85, 102) — table/list separators
  border-edge-highlight: "#3a4554"  # was rgba(221, 238, 255, 0.25) inset — poster edge ring approximation
  border-tag: "#00e054"             # outlined-green tag border

  # Shadow tints (flattened from rgba blends to opaque approximations)
  shadow-black: "#000000"     # poster drop, dropdown card
  shadow-ink: "#1a1e22"       # was rgba(20,24,28,0.2-0.35) modal halo approximation
  on-primary-cta: "#ffffff"

typography:
  display-editorial:
    fontFamily: "TiemposHeadlineWeb, Georgia, serif"
    fontSize: 36px
    fontWeight: 700
    lineHeight: 1.33
    letterSpacing: 0px
  display-h1:
    fontFamily: "GraphikWeb, -apple-system, system-ui, sans-serif"
    fontSize: 26px
    fontWeight: 300
    lineHeight: 1.23
    letterSpacing: 0px
  heading-section:
    fontFamily: "GraphikWeb, -apple-system, system-ui, sans-serif"
    fontSize: 24px
    fontWeight: 400
    lineHeight: 1.0
    letterSpacing: 0px
  heading-serif-sub:
    fontFamily: "TiemposTextWeb, Georgia, serif"
    fontSize: 22px
    fontWeight: 700
    lineHeight: 1.2
    letterSpacing: 0px
  heading-card:
    fontFamily: "GraphikWeb, -apple-system, system-ui, sans-serif"
    fontSize: 18px
    fontWeight: 700
    lineHeight: 1.2
    letterSpacing: 0px
  body-large:
    fontFamily: "GraphikWeb, -apple-system, system-ui, sans-serif"
    fontSize: 17px
    fontWeight: 400
    lineHeight: 1.5
    letterSpacing: 0px
  body-serif:
    fontFamily: "TiemposTextWeb, Georgia, serif"
    fontSize: 15px
    fontWeight: 400
    lineHeight: 1.67
    letterSpacing: 0px
  body:
    fontFamily: "GraphikWeb, -apple-system, system-ui, sans-serif"
    fontSize: 15px
    fontWeight: 400
    lineHeight: 1.5
    letterSpacing: 0px
  button-primary:
    fontFamily: "GraphikWeb, -apple-system, system-ui, sans-serif"
    fontSize: 18px
    fontWeight: 700
    lineHeight: 1.0
    letterSpacing: 0px
  button-small:
    fontFamily: "GraphikWeb, -apple-system, system-ui, sans-serif"
    fontSize: 13px
    fontWeight: 700
    lineHeight: 1.31
    letterSpacing: 1px
  caption-eyebrow:
    fontFamily: "GraphikWeb, -apple-system, system-ui, sans-serif"
    fontSize: 13px
    fontWeight: 700
    lineHeight: 1.31
    letterSpacing: 1px
  nav-uppercase:
    fontFamily: "GraphikWeb, -apple-system, system-ui, sans-serif"
    fontSize: 13px
    fontWeight: 400
    lineHeight: 1.54
    letterSpacing: 0.975px
  micro-eyebrow:
    fontFamily: "GraphikWeb, -apple-system, system-ui, sans-serif"
    fontSize: 11px
    fontWeight: 400
    lineHeight: 1.25
    letterSpacing: 0.825px
  badge-label:
    fontFamily: "GraphikWeb, -apple-system, system-ui, sans-serif"
    fontSize: 10px
    fontWeight: 700
    lineHeight: 1.0
    letterSpacing: 0.75px

spacing:
  micro: 2px
  xs: 5px
  sm: 10px
  md: 15px
  lg: 20px
  xl: 24px
  2xl: 32px
  3xl: 40px

rounded:
  none: 0px
  micro: 2px
  sm: 3px
  md: 4px
  lg: 8px
  pill: 12px
  search: 15px
  circle: 9999px

components:
  # Top navigation
  nav-bar:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.ink}"
    typography: "{typography.nav-uppercase}"
    padding: 16px 24px
  nav-link:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.ink}"
    typography: "{typography.nav-uppercase}"
    padding: 8px 12px
  nav-link-hover:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.ink-on-dark}"
    typography: "{typography.nav-uppercase}"
    padding: 8px 12px

  # Primary green CTA — the "Get started" button with signature 1px inset highlight
  button-primary:
    backgroundColor: "{colors.primary-cta}"
    textColor: "{colors.on-primary}"
    typography: "{typography.button-primary}"
    rounded: "{rounded.md}"
    padding: 12px 24px
  button-primary-hover:
    backgroundColor: "{colors.badge-brand}"
    textColor: "{colors.on-primary}"
    typography: "{typography.button-primary}"
    rounded: "{rounded.md}"
    padding: 12px 24px
  button-primary-active:
    backgroundColor: "{colors.primary-cta-active}"
    textColor: "{colors.on-primary-active}"
    typography: "{typography.button-primary}"
    rounded: "{rounded.md}"
    padding: 12px 24px

  # Secondary slate pill — UPPERCASE chip button
  button-secondary:
    backgroundColor: "{colors.ink-disabled}"
    textColor: "{colors.ink-bold-link}"
    typography: "{typography.button-small}"
    rounded: "{rounded.pill}"
    padding: 6px 12px
  button-secondary-hover:
    backgroundColor: "{colors.ink-disabled}"
    textColor: "{colors.ink-on-dark}"
    typography: "{typography.button-small}"
    rounded: "{rounded.pill}"
    padding: 6px 12px

  # Destructive button
  button-destructive:
    backgroundColor: "{colors.destructive}"
    textColor: "{colors.on-primary}"
    typography: "{typography.button-primary}"
    rounded: "{rounded.md}"
    padding: 12px 24px
  button-destructive-active:
    backgroundColor: "{colors.destructive-active}"
    textColor: "{colors.on-primary}"
    typography: "{typography.button-primary}"
    rounded: "{rounded.md}"
    padding: 12px 24px

  # Search input — glassy in header chrome
  input-search:
    backgroundColor: "{colors.surface-elevated}"
    textColor: "{colors.ink-disabled}"
    typography: "{typography.body}"
    rounded: "{rounded.search}"
    padding: 6px 10px
  input-search-focus:
    backgroundColor: "{colors.on-primary-cta}"
    textColor: "{colors.shadow-ink}"
    typography: "{typography.body}"
    rounded: "{rounded.search}"
    padding: 6px 10px

  # Text input — form body
  input:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.ink-on-dark}"
    typography: "{typography.body}"
    rounded: "{rounded.sm}"
    padding: 8px 12px
  input-focus:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.ink-on-dark}"
    typography: "{typography.body}"
    rounded: "{rounded.sm}"
    padding: 8px 12px

  # Cards & surfaces
  card:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.ink}"
    typography: "{typography.body}"
    rounded: "{rounded.none}"
    padding: 20px
  poster:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.ink-display}"
    rounded: "{rounded.md}"
    padding: 0px
  modal:
    backgroundColor: "{colors.surface-elevated}"
    textColor: "{colors.ink-on-dark}"
    typography: "{typography.body-large}"
    rounded: "{rounded.md}"
    padding: 24px

  # Badges
  badge-neutral:
    backgroundColor: "{colors.ink-tertiary}"
    textColor: "{colors.shadow-ink}"
    typography: "{typography.badge-label}"
    rounded: "{rounded.micro}"
    padding: 2px 5px
  badge-brand:
    backgroundColor: "{colors.badge-brand}"
    textColor: "{colors.on-primary}"
    typography: "{typography.badge-label}"
    rounded: "{rounded.micro}"
    padding: 3px 4px
  badge-outlined:
    backgroundColor: "{colors.background}"
    textColor: "{colors.primary}"
    typography: "{typography.badge-label}"
    rounded: "{rounded.micro}"
    padding: 2px 5px

  # Links inside prose
  link-prose:
    backgroundColor: "{colors.background}"
    textColor: "{colors.link}"
    typography: "{typography.body-serif}"
    padding: 0px
  link-prose-hover:
    backgroundColor: "{colors.background}"
    textColor: "{colors.link-hover}"
    typography: "{typography.body-serif}"
    padding: 0px

  # Editorial heading with section underline
  heading-editorial:
    backgroundColor: "{colors.background}"
    textColor: "{colors.ink-display}"
    typography: "{typography.display-editorial}"
    padding: 0px 0px 8px 0px
---

# Letterboxd Design System

## Overview

Letterboxd does not look like a 2025 web app. It looks like a film-magazine layout port of a 2012 social network that someone has been quietly polishing for thirteen years — and that consistency *is* the brand. The canvas is a deep, cool, blue-shifted near-black (`{colors.background}`) — not the warm `#1a1a1a` of a coffee-shop blog, not the pure black of a Netflix splash, but a desaturated dark navy that lets film posters carry every saturated color the page contains. Above the fold sits a stepped gradient — the body's background runs flat for 250 pixels then snaps a single pixel later to `{colors.surface}`, a denser graphite stripe that quietly delineates the header zone without using a border. Posters and stills float on top of this graphite-and-ink backdrop in a 2:3 grid, edges rounded by a fluid `clamp(2px, 2.66667%, 8px)` so a thumbnail and a hero poster share the same proportional softness.

The brand asserts itself through exactly one color — a fluorescent radioactive green (`{colors.primary}`) that descends from a slightly more demure `{colors.badge-brand}` on filled badges and a steadier `{colors.primary-cta}` on primary CTAs. This is the green of a Letterboxd "Pro" stripe, of "NEW" badges, of rating-fill dots, of the upgrade button. It is never used decoratively. It earns its way onto the screen by signaling status, action, or progress, and because everything else on the page is a cool gray, it reads as a single, unambiguous nervous-system signal. A second tier of accent — orange-amber (`{colors.accent-warm-strong}`, `{colors.accent-warm}`) for "like" hearts and the warm-orange Pro chevron — exists, but quietly; it is the warmth that prevents the green from looking institutional.

Typography is the design system's most underrated decision. Letterboxd pairs two original web fonts — **Graphik** for UI, body, micro-caps, and labels, and **Tiempos** (both Headline and Text cuts) for editorial titles and quoted prose. Graphik handles every all-caps `13px`-and-down navigation label with a `1px` tracking step that gives the chrome a quiet, broadcast-graphics rhythm. Tiempos carries the serif heading load — a `36px` review title at line-height `1.33` reads like the lede of a film essay, not a product H1. The pairing communicates the brand's core proposition: this is a database, but written by people who care about prose. There are no animations to speak of, no motion-blurred reveals, no parallax. The cinema is in the content. The chrome stays out of the way.

**Key Characteristics:**
- Cool blue-black body canvas (`{colors.background}`) — a hair toward navy, never neutral
- Two-tone vertical zoning: body flat for 250px, then `{colors.surface}` header stripe (a 1px gradient step, not a border)
- One signature accent: Letterboxd green (`{colors.primary}`) — used exclusively for status, ratings, CTAs, Pro indicators
- Graphik (sans) + Tiempos (serif) — original commercial typefaces, no Google fallbacks
- All-caps `13px` and `10px` Graphik with `0.75–1px` tracking for nav, badges, captions
- Serif body copy (Tiempos `15px` weight 400 line-height 1.67) for review excerpts and editorial text
- Cool-gray text scale across seven steps (`{colors.ink-high-emphasis}` → `{colors.ink-display}` → `{colors.ink}` → `{colors.ink-muted}` → `{colors.ink-disabled}`)
- Fluid poster radius `clamp(2px, 2.66667%, 8px)` — radius scales with the image
- Tactile shadow philosophy: dark drop + 1px white inset highlight — early-2010s "buttons feel pressable" inheritance, kept tasteful
- Tight border-radius scale (2px → 3px → 4px → 12px) — sharp by modern standards
- Posters as the content unit — every list, every grid, every page revolves around the 2:3 movie thumbnail
- Heavy reliance on 1-pixel `none none solid` underlines (`{colors.border-rule}`) for sectioning instead of cards-on-cards

## Colors

### Primary Brand
- **Letterboxd Green** (`{colors.primary}`): The signature green. Filled "NEW" badge variant, rating fills, Pro accents, link-active states. Cap usage at one element per viewport — its job is to be the only saturated thing on screen.
- **Brand Green Solid** (`{colors.badge-brand}`): Muted filled-badge variant.
- **CTA Green** (`{colors.primary-cta}`): Primary button surface — "Get started — it's free!"
- **CTA Green Active** (`{colors.primary-cta-active}`): Pressed state.
- **Rating Active** (`{colors.rating-active}`): Selected star fill, more saturated than green-on-dark needs.

### Surface (Canvas + Container)
- **Body Ink** (`{colors.background}`): page background. Cool-blue near-black — never substitute pure `#000000` or warm `#1a1a1a`.
- **Header Graphite** (`{colors.surface}`): top-bar zone color, also the figure play-button background and section-card surface.
- **Modal Slate** (`{colors.surface-elevated}`): denser-than-body dark used in modal scrims and overflow layers.

### Text Scale (cool-blue gray ramp, dark → light, on dark canvas)
- **Heading Ink-Hover** (`{colors.ink-on-dark}`): link hover state across all weights. The universal "alive" color.
- **Text High-Emphasis** (`{colors.ink-high-emphasis}`): brightest text on dark, just barely cool. Used sparingly for emphasis.
- **Text Default-Display** (`{colors.ink-display}`): hero titles, section headers.
- **Text Body-Light** (`{colors.ink}`): primary body text on dark, default link color. The most-used color on the entire site.
- **Text Bold-Link** (`{colors.ink-bold-link}`): weight-700 link color at rest.
- **Text Tertiary** (`{colors.ink-tertiary}`): metadata and tertiary text.
- **Text Muted** (`{colors.ink-muted}`): captions, timestamps.
- **Text Subtle** (`{colors.ink-subtle}`): faded link, poster-list link.
- **Text Disabled** (`{colors.ink-disabled}`): truly de-emphasized; also the secondary button surface.

### Interactive / Link Accent
- **Link Default** (`{colors.link}`): Primary blue link inside prose.
- **Link Hover** (`{colors.link-hover}`): The lighter sky-blue on hover.
- **Like Heart** (`{colors.accent-warm}`): The warm orange used for "Liked" state. Not red.
- **Pro Orange Surface** (`{colors.accent-warm-surface}`): The Pro chevron / paid-tier surface.
- **Pro Orange Content** (`{colors.accent-warm-strong}`): Pro icon/text on dark.

### Status / Semantic
- **Destructive Hover** (`{colors.destructive}`): Hover state for destructive buttons.
- **Destructive Active** (`{colors.destructive-active}`): Pressed state.

### Borders & Dividers
- **Section Underline** (`{colors.border-rule}`) — the canonical sectioning device — h2/section headers get a bottom rule, not a card.
- **Divider Mid** (`{colors.border-strong}`): list-item separators.
- **Tag Border** (`{colors.border-tag}`): the radioactive-green outline on the rare outlined badge.
- **Poster Edge Ring** (`{colors.border-edge-highlight}`): approximates the `rgba(221, 238, 255, 0.25) 0px 0px 0px 1px inset` highlight on every poster.

## Typography

### Font Family
- **Primary Sans**: `GraphikWeb`, with fallbacks: `-apple-system, system-ui, "Segoe UI", "Hiragino Sans", "Meiryo", sans-serif`
- **Primary Serif (Headline)**: `TiemposHeadlineWeb`, with fallbacks: `Georgia, serif`
- **Primary Serif (Text)**: `TiemposTextWeb`, with fallbacks: `Georgia, serif`
- **OpenType Features**: none declared in CSS. The brand voice comes from the typeface choice itself, not feature flags.
- **Font Sources**: self-hosted from `s.ltrbxd.com` — no Google Fonts, no Adobe Fonts, no variable axes. Both Graphik and Tiempos are commercially licensed from Commercial Type.

### Hierarchy

The complete type scale lives in the `typography:` token block above. Use those tokens directly via reference (`{typography.display-editorial}`, `{typography.body}`, etc.) rather than hardcoding values.

| Token | Use |
|---|---|
| `display-editorial` | Editorial title — review hero (Tiempos 36px / 700) — the "this is editorial" signal |
| `display-h1` | Light-weight Graphik for non-editorial display (26px / 300) |
| `heading-section` | Used on h1 / display contexts (24px / 400) |
| `heading-serif-sub` | h2/h3 in serif — review subheadings (Tiempos 22px / 700) |
| `heading-card` | Card titles, sectioned list headers (18px / 700) |
| `body-large` | Default UI body size on dark (17px / 400) |
| `body-serif` | The "people wrote this" prose — long-form member reviews (Tiempos 15px / 400 / line-height 1.67) |
| `body` | List rows, meta info (15px / 400) |
| `button-primary` | "Get started" CTA (18px / 700) |
| `button-small` | All-caps secondary button (13px / 700 / tracking 1px) |
| `caption-eyebrow` | UPPERCASE — section eyebrow, badge label (13px / 700 / tracking 1px) |
| `nav-uppercase` | UPPERCASE — header nav, tab labels (13px / 400 / tracking 0.975px) |
| `micro-eyebrow` | UPPERCASE — finest tracking (11px / 400 / tracking 0.825px) |
| `badge-label` | UPPERCASE — "NEW", "PRO", rating badges (10px / 700 / tracking 0.75px) |

### Principles
- **Two-typeface binary.** Graphik handles everything functional (UI, nav, buttons, captions). Tiempos handles everything editorial (review titles, long-form prose). Never mix the roles. Never use Tiempos for a button. Never use Graphik for review prose at 15px.
- **Weight inversion at scale.** Large display text drops to weight 300 (26px Graphik); large editorial titles climb to weight 700 (36px Tiempos). The further from body size, the more weight diverges from 400.
- **All-caps owns small.** Every text smaller than `14px` is a candidate for uppercase + tracking `0.75–1px`. Nav, tabs, badges, eyebrows, micro-labels — all uppercased.
- **Letter-spacing is binary.** Either `0px` (sentence-case) or `0.75–1px` (UPPERCASE). There is no `0.5px` middle ground.
- **Line-height widens with weight reduction.** Light (300) body climbs to `1.50` for legibility; bold (700) headings tighten to `1.20–1.33`.

## Layout

### Spacing System
The complete spacing scale lives in the `spacing:` token block above. Base unit is **5px** (dembrandt classifies the page as 8px-anchored, but actual high-frequency anchors are at 5/10/15/20 — the system is a 5px grid).

Most-used values: `2px` (badges), `5px` (chip padding), `10px` (gap between posters), `15px` (form padding), `20px` (section spacing), `24px`/`32px`/`40px` (zone breaks).

### Grid & Container
- Max content width: approximately `1140px`
- Poster grids: 2:3 aspect, gap typically `10px` between tiles
- Sidebar pattern: ~`220px` left rail + main content + ~`220px` right rail on profile pages
- Section spacing: typically `20px` between bands, `40px` between major zones

### Whitespace Philosophy
- **Dense, not airy.** Letterboxd is a database — every screen prioritizes "how many films can I see at once" over "how much room can each film breathe." Poster grids run 6-wide on desktop.
- **Vertical rhythm is led by underlines, not margins.** A section ends with a `1px solid {colors.border-rule}` bottom rule, and the next section begins `{spacing.lg}` later. Cards-on-cards do not exist.
- **Padding lives in the page, not inside content.** Posters reach their rounded edge — no inner margin.

## Elevation & Depth

| Level | Treatment | Use |
|---|---|---|
| Flat (Level 0) | No shadow | Header strip, section bands, body backdrop |
| Inset Highlight (Level 0.5) | `1px solid {colors.border-edge-highlight}` (flattened from `rgba(221,238,255,0.25) inset`) | Poster edge ring, input edge, framed thumb |
| Subtle (Level 1) | `1px solid {colors.on-primary-cta}` 10% inset (button top edge highlight) | Signature 1px white inset highlight at the top of every primary button |
| Pressed (Level 1.5) | Inset highlight + 2px black drop | Secondary pill button |
| Poster (Level 2) | Two-layer `{colors.shadow-black}` drop (5px + 10px) | Freestanding posters in carousels |
| Hover Lift (Level 2.5) | `{colors.shadow-black}` 7px lateral drop | Hovered poster — lateral pure-black shadow |
| Dropdown (Level 3) | `{colors.shadow-black}` 8px/16px soft drop at ~15% | Floating menus, autocomplete dropdowns — the only "modern flat" shadow on the site |
| Dialog Edge (Level 4) | Three-layer `{colors.shadow-ink}` halo | Modal dialog body-ink halo |

**Shadow Philosophy**: Letterboxd's shadow language is openly inherited from the early-2010s tactile UI era — every button has a 1px white inset highlight at the top, exactly as iOS 6 and Twitter's "Bootstrap 2" era taught the web. Drop shadows are unapologetically pure black (`{colors.shadow-black}`), never tinted to the body color. The combination — inset highlight at top, dark drop below — gives posters and buttons a subtle "pressable" pop without crossing into skeuomorphic territory. The discipline is that the brand never overlays shadows on top of other shadows: a poster has its drop, a button has its highlight, a modal has its halo — and that is the entire vocabulary. There is no "shadow-md → shadow-lg → shadow-xl" Tailwind ladder.

## Shapes

| Token | Value | Use |
|---|---|---|
| `none` | 0px | Page bands, section dividers, full-bleed surfaces |
| `micro` | 2px | Badges ("NEW", "PRO"), small chips, inline tags |
| `sm` | 3px | Inputs, default cells, small buttons — most common value |
| `md` | 4px | Primary CTAs, "Watch video", action links |
| `lg` | 8px | Modal cards, dialog edges |
| `pill` | 12px | Secondary slate buttons, filter chips |
| `search` | 15px | Search input — only the search bar gets this generous radius |
| `circle` | 9999px | Close button, user avatars |

Posters use a fluid radius: `clamp(2px, 2.66667%, 8px)`. A 32px thumb gets ~2px radius; a 240px hero poster gets ~8px. The signature radius scales with the element.

## Components

The complete component spec lives in the `components:` token block above. Reference component tokens directly rather than reconstructing them.

### Buttons
- **`button-primary`** — Primary green CTA (`{colors.primary-cta}` background, `{colors.on-primary}` text, `{rounded.md}` radius). Always paired with a 1px white inset highlight at the top — the signature "pressable" cue.
- **`button-primary-hover`** — Brightens to `{colors.badge-brand}`.
- **`button-primary-active`** — Surface darkens to `{colors.primary-cta-active}`, text shifts to `{colors.on-primary-active}` (green-tinted off-white).
- **`button-secondary`** — Slate pill (`{colors.ink-disabled}` background, `{rounded.pill}` radius). Text is UPPERCASE `{typography.button-small}`.
- **`button-destructive`** — Red variant for destructive confirms.

### Cards & Containers
- **`card`** — Header zone surface (`{colors.surface}` background, no border-radius — the gradient transition replaces it).
- **`poster`** — The core content unit: 2:3 aspect, `{rounded.md}` radius (fluid clamp() in production), `{colors.border-edge-highlight}` edge ring.
- **`modal`** — Dialog panel (`{colors.surface-elevated}` background, `{rounded.md}` radius).

### Inputs & Forms
- **`input-search`** — Glassy translucent input in the header. Background flips from `{colors.surface-elevated}` to `{colors.on-primary-cta}` on focus; text from `{colors.ink-disabled}` to `{colors.shadow-ink}`.
- **`input`** — Form-body input on dark surfaces, `{rounded.sm}` radius.

### Badges / Tags / Pills
- **`badge-neutral`** — Gray pill for "DISCLOSURE" or inline meta (`{colors.ink-tertiary}` background, dark `{colors.shadow-ink}` text, UPPERCASE `{typography.badge-label}`).
- **`badge-brand`** — Green "NEW" / Pro pill (`{colors.badge-brand}` background, white text). Use only on truly new/active items — never decorative.
- **`badge-outlined`** — Rare green outline (`{colors.border-tag}` border, green text, transparent fill).

### Navigation
- Top nav: full-width strip at `{colors.surface}`, sitting on a body of `{colors.background}` — gradient-stepped, no border.
- **`nav-link`** — UPPERCASE `{typography.nav-uppercase}` at `{colors.ink}`. Hover transitions to `{colors.ink-on-dark}` (`text-decoration: none` at all times — Letterboxd never uses underlines on chrome).
- Logo: white SVG wordmark on the left.
- Search: glassy `input-search` pill, centered or right-aligned.
- CTA: green `button-primary` on far right.
- Mobile: collapses below `1024px`, hamburger at `<800px`.

### Image Treatment
- Posters (2:3): fluid `clamp(2px, 2.66667%, 8px)` radius — scales with image dimensions.
- Inset highlight ring: every poster gets `{colors.border-edge-highlight}` 1px border to define the edge against the dark canvas.
- Cinema stills: paired with an 8-stop gradient mask fading to `{colors.background}` so body content reads cleanly atop the image.

## Do's and Don'ts

### Do
- Use `{colors.background}` (cool blue-black) for the body — never `#000000`, never `#1a1a1a` warm
- Use `{colors.primary}` (or `{colors.badge-brand}` filled, `{colors.primary-cta}` for buttons) as the *only* saturated brand color per viewport
- Pair Graphik (sans, UI) with Tiempos (serif, editorial) — never substitute Inter or Georgia
- Set nav, badge, and caption text below `14px` to UPPERCASE with `0.75–1px` letter-spacing
- Use the fluid `clamp(2px, 2.66667%, 8px)` radius on every poster image, regardless of size
- Apply the `{colors.border-edge-highlight}` 1px edge ring to every poster, framed image, or input
- Wrap primary CTAs in a 1px white inset highlight — the signature tactile cue
- Step the cool-gray text scale through `{colors.ink-display}` → `{colors.ink}` → `{colors.ink-muted}` → `{colors.ink-subtle}` → `{colors.ink-disabled}` for descending emphasis
- Use `1px solid {colors.border-rule}` bottom-rules for section dividers — never card-on-card containers
- Set serif body (review prose) to `{typography.body-serif}` (Tiempos `15px` line-height `1.67`) — the wide leading is what makes prose feel literary

### Don't
- Don't use pure black `#000` for the canvas — it kills the cool-blue cast that defines the brand
- Don't introduce a second saturated accent color — orange already does double duty as Like + Pro
- Don't put Tiempos on a button or a navigation link — it's editorial-only
- Don't use weight 600 on Graphik headings — Letterboxd's weight axis is binary: 300 (light display) or 400 (body) or 700 (bold)
- Don't add underlines to chrome links — hover changes color to `{colors.ink-on-dark}`, never `text-decoration`
- Don't make poster radius a fixed pixel value — use the `clamp()` so thumbnails and heroes share the same proportional curve
- Don't stack shadow tiers (Tailwind-style `shadow-md` ladder) — each component owns exactly one shadow treatment
- Don't drop the signature green into decorative roles (background panels, gradients) — it must always signal status or action
- Don't tighten serif headlines below line-height `1.20` — the relaxed `1.33` on `36px` Tiempos is the editorial voice
- Don't introduce rounded-pill buttons larger than `{rounded.pill}` — only the search input gets `{rounded.search}`; everything else is `{rounded.micro}`–`{rounded.md}`

## Responsive Behavior

### Breakpoints

Letterboxd uses an extraordinarily granular breakpoint set (46 distinct values from 98px to 1280px) — the engineering pattern is to declare every "off-by-one" twice (`449px` / `450px`) for clean inclusive/exclusive ranges. Conceptually:

| Name | Width | Key Changes |
|------|-------|-------------|
| Mobile XS | <`375px` | Single-column poster grid (3-wide), nav collapses to hamburger, hero text drops to `18–20px` |
| Mobile | `375–667px` | 3-wide poster grid, sidebar rails hidden, single content column |
| Tablet | `668–1023px` | 4-wide poster grid, sidebar rails return as collapsible drawers, inline nav at `>800px` |
| Desktop | `1024–1193px` | 5-wide poster grid, full sidebars (~`220px` each), inline nav |
| Wide Desktop | `1194–1279px` | 6-wide poster grid, comfortable rail spacing |
| Max | >`1280px` | Layout caps at ~`1140px` content width — page does not expand further |

### Touch Targets
- Primary buttons stay at `~40px` effective height
- Secondary pills at `~24px` tall — slightly under WCAG's 44px target, compensated by `12px` horizontal padding
- Poster tiles get a full-tile tap area; the entire image is clickable to the film page

### Collapsing Strategy
- **Posters**: grids reduce columns (6 → 5 → 4 → 3 → 2) rather than shrinking individual posters below `~70px` wide
- **Sidebars**: above `1024px`, both rails visible; below, right rail drops first, then left collapses into a drawer at `<800px`
- **Nav**: inline `13px` UPPERCASE links at `≥800px`; below, collapse to hamburger; search persists at all sizes
- **Footer**: stacks from 4-column (desktop) to 2-column (tablet) to single-column (mobile)

### Image Behavior
- Posters served at multiple resolutions (`@1x`, `@2x`, `@3x`) via `srcset`
- Assets content-hashed and served from `s.ltrbxd.com` CDN
- The fluid `clamp()` radius means a `48px` thumbnail and a `300px` hero poster share the same proportional curve — no separate `--radius-sm` / `--radius-md` token tier

## Agent Prompt Guide

### Quick Color Reference
- Background: Body Ink (`{colors.background}`)
- Header strip: Header Graphite (`{colors.surface}`)
- Text default: Text Body-Light (`{colors.ink}`)
- Text high-emphasis: Text Display (`{colors.ink-display}`)
- Text muted: Text Subtle (`{colors.ink-subtle}`)
- Brand accent: Letterboxd Green (`{colors.primary}`) / Filled Badge (`{colors.badge-brand}`) / CTA (`{colors.primary-cta}`)
- Link blue (in prose): `{colors.link}`
- Like / Pro orange: `{colors.accent-warm}` / `{colors.accent-warm-strong}`
- Edge ring: `{colors.border-edge-highlight}`

### Example Component Prompts

- "Build a film-detail hero. Background `{colors.background}`. Overlay a 16:9 cinema still and fade an 8-stop linear gradient down to `{colors.background}` so body content fades up from the image. Title in `{typography.display-editorial}`, color `{colors.ink-display}`. Subtitle in `{typography.caption-eyebrow}` UPPERCASE, color `{colors.ink}`. To the left: a 2:3 poster at 230px wide, `{components.poster}` token. Border-radius `clamp(2px, 2.66667%, 8px)`."

- "Build a poster grid card. Image at 2:3 aspect, `{components.poster}`. Below: film title in `{typography.nav-uppercase}` UPPERCASE, color `{colors.ink-display}`. Year metadata directly below in `{typography.micro-eyebrow}` UPPERCASE, color `{colors.ink-subtle}`. Gap between tiles: `{spacing.sm}`. On hover, title color shifts to `{colors.ink-on-dark}`."

- "Create a primary call-to-action button using `{components.button-primary}`. Always include a 1px white inset highlight at the top (`box-shadow: rgba(255, 255, 255, 0.1) 0px 1px 0px 0px inset`) — the signature 'pressable' cue. Hover uses `{components.button-primary-hover}`; active uses `{components.button-primary-active}`."

- "Create a secondary action pill using `{components.button-secondary}`. Text in `{typography.button-small}` UPPERCASE."

- "Build a top navigation. Background `{colors.surface}` sitting on a body of `{colors.background}`. The transition is a 1-pixel gradient step from `{colors.background}` to `{colors.surface}` at the 250px mark — not a border. Nav links use `{components.nav-link}`; hover uses `{components.nav-link-hover}`. Search uses `{components.input-search}` — on focus, it morphs into `{components.input-search-focus}`. Far right: `{components.button-primary}` 'Sign In'."

- "Create a status badge using `{components.badge-brand}` for 'NEW' or 'PRO' indicators. Use only on truly new/active items — never decorative."

- "Build a section heading using `{components.heading-editorial}`. Below the heading text, add a `1px solid {colors.border-rule}` bottom border spanning the section width. Vertical spacing: `{spacing.lg}` above the next content block. Never wrap the heading in a card — the bottom rule is the only delimiter."

- "Build a long-form review prose block. Use `{typography.body-serif}`, color `{colors.ink}`. Inline links use `{components.link-prose}`; hover uses `{components.link-prose-hover}`. Above the review: 5-star rating row using `{colors.primary}` filled stars."

### Iteration Guide
1. **Start with the canvas.** Set body background to `{colors.background}` and text to `{colors.ink}` with the Graphik sans stack. Step the header band to `{colors.surface}` via a gradient transition at the 250px mark — not a border.
2. **One green only.** `{colors.primary}` (or `{colors.primary-cta}` for buttons) is the *only* saturated color allowed on screen at a time. Use it for action, status, ratings — never decoration.
3. **Two typefaces, two roles.** Graphik = UI (nav, buttons, captions, body chrome). Tiempos = editorial (review titles, long-form prose). Never cross the streams. Below `14px`, Graphik goes UPPERCASE with `0.75–1px` tracking.
4. **Weight axis is binary.** 300 (light display) → 400 (body) → 700 (bold). No 500. No 600. Weight 300 climbs as text gets larger; weight 700 dominates at small uppercase sizes.
5. **Text scale is monochromatic cool-gray.** `{colors.ink-on-dark}` only on hover. Display: `{colors.ink-display}`. Body: `{colors.ink}`. Muted: `{colors.ink-muted}` → `{colors.ink-subtle}` → `{colors.ink-disabled}`. Never warm grays.
6. **Shadows are vocabulary, not ladder.** Each component picks one of: inset highlight ring, button highlight, poster drop, or dropdown card. No stacking.
7. **Radius scale is conservative.** `{rounded.micro}` (badges) → `{rounded.sm}` (inputs) → `{rounded.md}` (buttons). Posters use the fluid clamp(). Only the search input gets `{rounded.search}`. Never use 16px "Material" rounded everywhere.
8. **Posters are the content unit.** 2:3 aspect, inset edge ring, fluid radius. Grids run as wide as possible — Letterboxd is a database, density is the value.
9. **Underlines, not cards.** Section delimiters are `1px solid {colors.border-rule}` bottom-rules, not surface elevations. Cards-on-cards are forbidden.
10. **Stay 2012 in spirit.** This is not a 2025 SaaS dashboard. It's a film magazine with a database underneath. When in doubt, choose the more restrained option — Letterboxd's design has barely changed in a decade, and that's the point.

---

## Attribution

Independent design analysis from [Design Swatches](https://designmd.santiagoalonso.com) by [Santiago Alonso](https://santiagoalonso.com). Based on publicly observable interface patterns. Not affiliated with or endorsed by Letterboxd. Brand names and trademarks belong to their respective owners.
