---
version: alpha
name: "Porto Rocha"
description: "Stark monochrome identity for a New York branding studio — SF Pro at every scale, full-bleed imagery, and choreographed inversion as the sole expressive device"

colors:
  background: "#ffffff"
  surface: "#f5f5f5"
  surface-dark: "#000000"
  ink: "#000000"
  ink-muted: "#4a4a4a"
  on-background: "#000000"
  on-surface: "#000000"
  primary: "#000000"
  on-primary: "#ffffff"
  primary-container: "#f0f0f0"  # was rgba(0,0,0,0.04) — Google format requires hex
  text-hover: "#1a1a1a"         # was rgba(0,0,0,0.816) — Google format requires hex
  focus-ring: "#000000"
  focus-tint: "#e5e5e5"         # was rgba(0,0,0,0.075) — Google format requires hex
  accent: "#007aff"
  on-accent: "#ffffff"
  border: "#e0e0e0"
  shadow-soft: "#d9d9d9"
  gradient-start: "#d9d6d5"     # from radial gradient stop 0
  gradient-end: "#efefef"       # from radial gradient stop 100

typography:
  display-hero:
    fontFamily: "SF Pro Display, -apple-system, BlinkMacSystemFont, Helvetica Neue, sans-serif"
    fontSize: 80px
    fontWeight: 400
    lineHeight: 1.0
    letterSpacing: -1px
  display:
    fontFamily: "SF Pro Display, -apple-system, BlinkMacSystemFont, Helvetica Neue, sans-serif"
    fontSize: 48px
    fontWeight: 400
    lineHeight: 1.05
    letterSpacing: -0.5px
  heading-section:
    fontFamily: "SF Pro Display, -apple-system, BlinkMacSystemFont, Helvetica Neue, sans-serif"
    fontSize: 32px
    fontWeight: 400
    lineHeight: 1.1
    letterSpacing: -0.25px
  heading-sub:
    fontFamily: "SF Pro Display, -apple-system, BlinkMacSystemFont, Helvetica Neue, sans-serif"
    fontSize: 23px
    fontWeight: 400
    lineHeight: 1.17
    letterSpacing: 0.45px
  body-large:
    fontFamily: "SF Pro Text, -apple-system, BlinkMacSystemFont, Helvetica Neue, sans-serif"
    fontSize: 18px
    fontWeight: 400
    lineHeight: 1.5
    letterSpacing: 0px
  body:
    fontFamily: "SF Pro Text, -apple-system, BlinkMacSystemFont, Helvetica Neue, sans-serif"
    fontSize: 14px
    fontWeight: 400
    lineHeight: 1.25
    letterSpacing: 0px
  nav-link:
    fontFamily: "SF Pro Text, -apple-system, BlinkMacSystemFont, Helvetica Neue, sans-serif"
    fontSize: 14px
    fontWeight: 400
    lineHeight: 1.25
    letterSpacing: 0px
  button-ui:
    fontFamily: "SF Pro Text, -apple-system, BlinkMacSystemFont, Helvetica Neue, sans-serif"
    fontSize: 14px
    fontWeight: 400
    lineHeight: 1.25
    letterSpacing: 0px
  caption:
    fontFamily: "SF Pro Text, -apple-system, BlinkMacSystemFont, Helvetica Neue, sans-serif"
    fontSize: 12px
    fontWeight: 400
    lineHeight: 1.4
    letterSpacing: 0px

spacing:
  xs: 4px
  sm: 8px
  md: 16px
  lg: 20px
  xl: 32px
  2xl: 48px
  3xl: 64px
  4xl: 96px

rounded:
  none: 0px
  sm: 8px
  pill: 9999px

components:
  button-primary:
    backgroundColor: "{colors.primary}"
    textColor: "{colors.on-primary}"
    typography: "{typography.button-ui}"
    rounded: "{rounded.pill}"
    padding: 8px 16px
  button-primary-hover:
    backgroundColor: "{colors.text-hover}"
    textColor: "{colors.on-primary}"
    typography: "{typography.button-ui}"
    rounded: "{rounded.pill}"
    padding: 8px 16px
  button-ghost:
    backgroundColor: "{colors.primary-container}"
    textColor: "{colors.ink}"
    typography: "{typography.button-ui}"
    rounded: "{rounded.pill}"
    padding: 8px 16px
  button-ghost-hover:
    backgroundColor: "{colors.focus-tint}"
    textColor: "{colors.ink}"
    typography: "{typography.button-ui}"
    rounded: "{rounded.pill}"
    padding: 8px 16px
  card:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.ink}"
    rounded: "{rounded.none}"
    padding: 16px
  card-dark:
    backgroundColor: "{colors.surface-dark}"
    textColor: "{colors.on-primary}"
    rounded: "{rounded.none}"
    padding: 16px
  card-hover:
    backgroundColor: "{colors.primary-container}"
    textColor: "{colors.ink}"
    rounded: "{rounded.none}"
    padding: 16px
  nav:
    backgroundColor: "{colors.background}"
    textColor: "{colors.ink}"
    typography: "{typography.nav-link}"
    rounded: "{rounded.none}"
    padding: 8px 16px
  nav-inverted:
    backgroundColor: "{colors.surface-dark}"
    textColor: "{colors.on-primary}"
    typography: "{typography.nav-link}"
    rounded: "{rounded.none}"
    padding: 8px 16px
  project-tile:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.ink}"
    rounded: "{rounded.none}"
    padding: 0px
  badge:
    backgroundColor: "{colors.primary-container}"
    textColor: "{colors.ink}"
    typography: "{typography.caption}"
    rounded: "{rounded.pill}"
    padding: 4px 10px
---

# Porto Rocha Design System

## Overview

Porto Rocha operates at an extreme register of restraint. The studio's site is built almost entirely from two colors — {colors.background} and {colors.ink} — deployed in near-equal measure, never decorating but always asserting. The background shifts between stark white and absolute black depending on which surface is in play, and the transition between those two states is the studio's primary expressive gesture. This is not minimalism by default; it is minimalism as ideology, maintained with the same deliberateness the studio brings to the brands it builds.

Typography is set in SF Pro Display and SF Pro Text — Apple's system typefaces, self-hosted rather than simply inherited. The choice is knowing: these fonts carry neutrality without blandness, optical precision without coldness. At display sizes the letterforms push close together (tight tracking, low line-height) to form monolithic headline blocks. At body scale they relax into utility. The effect is a studio that communicates through scale and contrast rather than through ornament. Project titles land large; captions recede. Nothing fights for attention that has not earned it.

The sole accent in the palette is {colors.accent}, an iOS-blue that functions as a system color rather than a brand color — it appears in interactive focus states, signaling utility rather than personality. Every piece of visual warmth comes instead from photography: editorial spreads, campaign imagery, and identity mockups that supply all the hue and texture the typographic shell withholds. The result is a portfolio site that recedes into its own work.

**Key Characteristics:**
- Binary canvas: pages switch between {colors.background} (white) and {colors.surface-dark} (black) as the primary design gesture, with no mid-tones in structural surfaces
- SF Pro Display + SF Pro Text self-hosted — system-familiar but intentional, not inherited-default
- Display type at 80px and above set at 1.0 line-height for dense headline mass; `{typography.display-hero}` is the primary brand voice
- Single button variant: a near-invisible ghost pill with `{colors.primary-container}` background (~4% black on white), 40px radius
- `{colors.accent}` (#007aff) reserved strictly for interactive/focus states — the only non-mono hue in the system
- No border-radius on content cards or project tiles (`{rounded.none}`) — sharp edges throughout structural elements
- 0.5s ease transitions on all interactive elements (color, background, opacity) — slow and deliberate, not snappy
- 8px base spacing unit with 20px as the dominant layout gap
- Full-bleed photography as the sole source of color, texture, and warmth
- Navigation inverts on dark-canvas pages: same type, opposite colors
- Project hover states use color shift rather than scale or shadow
- No decorative elements: no gradients in UI, no shadows on cards, no iconography system

## Colors

### Primary Canvas
- **White** (`{colors.background}`): The primary canvas. Body pages, project listings, and editorial sections all open on white — it reads as light, neutral, and gallery-like.
- **Black** (`{colors.surface-dark}`): The inversion state. Used for dark-canvas sections, inverted navigation, and hero moments where work needs to float against darkness.
- **Light Gray** (`{colors.surface}`): A near-white tint (`#f5f5f5`) used for secondary surfaces, image backgrounds, and subtle lift without introducing a new tonal tier.

### Text / Ink
- **Black** (`{colors.ink}`): All body copy, headings, navigation, and labels on light canvases.
- **Muted** (`{colors.ink-muted}`): Secondary captions and metadata on light backgrounds where full black would overpower.

### Brand Accent
- **iOS Blue** (`{colors.accent}`): A direct reference to Apple's system focus color. Applied to interactive focus rings and accessibility states. Carries no brand meaning — its role is purely functional.

### Interaction States
- **Ghost Fill** (`{colors.primary-container}`): Near-transparent black (~4%), used as the resting state for the "Show all projects" pill button. Barely visible, intentionally so.
- **Hover Text** (`{colors.text-hover}`): Darkened ink for link hover states — `#1a1a1a` rather than pure black, creating a subtle dimming effect on hover. Original value was `rgba(0,0,0,0.816)`.
- **Focus Tint** (`{colors.focus-tint}`): Light gray used as an elevated button hover fill. Original value was `rgba(0,0,0,0.075)`.

### Borders & Shadow
- **Border** (`{colors.border}`): A light rule at `#e0e0e0` for structural dividers and image frames.
- **Shadow Soft** (`{colors.shadow-soft}`): Reserved for the radial gradient backdrop used on thumbnail card surfaces — warm off-white (`#d9d6d5`) to `#efefef`.

## Typography

### Font Family
- **Display**: `SF Pro Display`, with full Apple system fallback stack: `-apple-system, BlinkMacSystemFont, Helvetica Neue, sans-serif`
- **Text**: `SF Pro Text`, same fallback stack — the optical companion to Display, optimized for smaller sizes
- Both faces are self-hosted as `.woff2`, not relying on OS installation

### Hierarchy

The complete type scale is declared in the `typography:` token block above. Reference tokens directly rather than restating values.

| Token | Use |
|---|---|
| `display-hero` | Campaign headlines, project titles at max scale, homepage statement text |
| `display` | Section openers, project case-study titles, large editorial headers |
| `heading-section` | Secondary headers, case-study chapter titles |
| `heading-sub` | Tertiary labels, client names in project listings (23px, 0.45px tracking) |
| `body-large` | Introduction paragraphs, editorial lead text |
| `body` | All standard prose, project descriptions, news snippets |
| `nav-link` | Navigation items, filter labels, footer links |
| `button-ui` | Button labels, interactive element text |
| `caption` | Timestamps, image credits, metadata |

### Principles
- A single-family system: SF Pro Display handles everything above 20px; SF Pro Text handles everything below
- Weight stays at 400 throughout — no bold or black weights. Hierarchy comes from size alone
- Negative tracking at display sizes (`-1px` for `{typography.display-hero}`) creates monolithic headline blocks
- Positive tracking at `heading-sub` level (`0.45px`) creates open, airy labels
- No italic variants in the system — all emphasis comes from scale, weight, or inversion

## Layout

### Spacing System
The complete spacing scale is in the `spacing:` token block above. Base unit: 8px.

Spacing is tight at the component level and generous at the layout level. The `{spacing.lg}` value (20px) carries much of the load — it appears in over 220 instances across the computed CSS, acting as the primary layout gap between cards, sections, and navigation items. White space is structural, not decorative.

### Grid & Container
- Max content width: approximately 1280px (widest breakpoint)
- Project grid: responsive masonry/flex with 8px gutters at mobile, expanding to 20px at desktop
- Navigation: full-width horizontal bar, pinned at top, 16px horizontal padding
- Hero sections: full-viewport-width, edge-to-edge imagery with text overlaid or adjacent

### Whitespace Philosophy
- At component level: compact — buttons have 8px vertical padding, captions have no exterior breathing room
- At section level: generous — project grids use significant inter-card spacing to let photography breathe
- The tension between tight type and open layout is deliberate: it mirrors the studio's own design ethos of constraint enabling expression

## Elevation & Depth

| Level | Treatment | Use |
|---|---|---|
| Flat (Level 0) | No shadow | All project cards, navigation, standard content |
| Surface (Level 1) | `{colors.surface}` (#f5f5f5) background | Image card backing, thumbnail frames |
| Gradient (Level 2) | Radial from `{colors.gradient-start}` to `{colors.gradient-end}` | Thumbnail card surface — the only depth cue in the system |
| Focus Ring | `{colors.focus-ring}` (black) | Keyboard navigation, form focus states |

**Shadow Philosophy**: Porto Rocha uses no box-shadows. Depth is created through color contrast alone — white card on white page gets a light gray surface; dark section on white page creates its own plane through inversion. The single gradient (radial, warm gray) exists only as a thumbnail card backdrop, simulating the light-table quality of a physical portfolio. The absence of shadow is not an oversight; it is the same flat confidence the studio brings to its identity work.

## Shapes

The complete radius scale is in the `rounded:` token block above. The system uses:

| Token | Value | Use |
|---|---|---|
| `none` | 0px | All project cards, image tiles, layout containers, navigation |
| `sm` | 8px | Minor UI elements where slight softening is appropriate |
| `pill` | 9999px | The "Show all projects" button and any interactive pill-shaped labels |

The system is effectively binary: everything is either perfectly sharp (`{rounded.none}`) or fully rounded (`{rounded.pill}`). There are no mid-range radii. This creates a visual language of hard-edged editorial frames punctuated by soft pill-shaped affordances — a tension that is characteristic of contemporary branding studio sites.

## Components

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

### Button Variants

- **`button-primary`** — Full black pill on white. Used for high-emphasis actions like primary CTAs on dark surfaces where inversion is needed. `{colors.primary}` background, `{colors.on-primary}` text.
- **`button-ghost`** — The workhorse button. A near-invisible `{colors.primary-container}` pill (barely-there gray tint, ~4% black) for "Show all projects" and other soft affordances. No border, light fill, full pill radius of 40px.
- **`button-ghost-hover`** — Hover state deepens to `{colors.focus-tint}` (~7.5% black). Transition at 0.5s ease across background-color and color.

### Cards
Project tiles are sharp-edged (`{rounded.none}`), zero padding, image-first. The card surface uses either `{colors.surface}` for thumbnail backgrounds or `{colors.surface-dark}` for dark-mode moments. Hover shifts the color state smoothly at 0.5s ease — no scale transform, no shadow lift.

### Navigation
Full-width bar, available in two states: `nav` (black on white) and `nav-inverted` (white on black). Transitions at 0.5s ease when the page context changes. No sticky blur or glass effects — the nav simply inverts color.

### Badges / Tags
Minimal pill badges using `{colors.primary-container}` fill and `{typography.caption}` type. Used for metadata labels, category tags, and date annotations in news sections.

## Do's and Don'ts

### Do
- Use `{colors.background}` and `{colors.surface-dark}` as primary canvas alternates — inversion is the signature gesture
- Set display type to `{typography.display-hero}` with tight tracking (`-1px`) for campaign-scale headlines
- Keep button fills below 10% opacity (`{colors.primary-container}`) for ghost variants — the barely-there quality is intentional
- Use 0.5s ease transitions on all color and background changes — the deliberate slowness is part of the character
- Let photography carry all color; the typographic system should remain resolutely `{colors.ink}` on `{colors.background}`
- Apply `{rounded.none}` to all image frames and project tiles — sharp edges throughout structural content
- Reserve `{colors.accent}` strictly for keyboard focus rings and accessibility states — never as a brand decoration
- Match typography weight (400) across the entire scale — size difference alone creates hierarchy

### Don't
- Don't introduce mid-range border radii between `{rounded.sm}` and `{rounded.pill}` — the system is deliberately binary
- Don't add box-shadows to cards or containers — depth comes from color inversion, not elevation
- Don't use `{colors.accent}` as a brand color in layouts, buttons, or headlines — it is a system UI signal only
- Don't set type above 400 weight at display sizes — bold headlines would contradict the studio's restrained voice
- Don't introduce new surface colors between `{colors.background}` and `{colors.surface-dark}` — mid-tones dilute the binary contrast system
- Don't animate with transform-scale on project hover — Porto Rocha hovers through color shift, not scale
- Don't add decorative gradients to UI elements; the only gradient is the subtle radial card backdrop
- Don't fragment the single-family system by introducing a secondary typeface — the SF Pro duality (Display + Text) is the full range

---

## Responsive Behavior

### Breakpoints
| Name | Width | Key Changes |
|---|---|---|
| Mobile Small | <656px | Single-column project grid; navigation collapses; large type scales down ~40% |
| Mobile | 657px–768px | Single column; touch-optimized spacing; 8px gutters |
| Tablet | 769px–1024px | Two-column project grid; navigation expands; spacing increases to 16px gutters |
| Desktop | 1025px–1280px | Three or four-column grid; hero type at full `{typography.display-hero}` scale |
| Large Desktop | >1280px | Capped at 1280px container; outer margins absorb additional width |

### Touch Targets
- Pill buttons use 40px height minimum, comfortably above 44px tap targets at their padding of 8px vertical
- Project tile links span the full card surface for maximum tap area
- Navigation items have 16px horizontal padding ensuring adequate spacing between targets

### Collapsing Strategy
- Navigation: horizontal bar collapses to a minimal mobile state; menu items may stack or abbreviate below 656px
- Project grid: 4-column → 2-column → 1-column as viewport narrows
- Hero typography: display-hero scales from 80px at desktop to approximately 48px at mobile using viewport-relative sizing
- Dark/light canvas sections maintain their inversion at all breakpoints

### Image Behavior
- Project thumbnails are fluid, filling their grid column at all widths
- Full-bleed hero images expand edge-to-edge with no max-width constraint
- Thumbnails use a subtle radial gradient backdrop (`{colors.gradient-start}` to `{colors.gradient-end}`) that remains at all sizes

---

## Agent Prompt Guide

### Quick Color Reference
- Background: `{colors.background}`
- Text: `{colors.ink}`
- Brand accent / focus: `{colors.accent}`
- Secondary text: `{colors.ink-muted}`
- Border: `{colors.border}`
- Dark canvas: `{colors.surface-dark}`
- Ghost button fill: `{colors.primary-container}`

### Example Component Prompts

- "Build a full-width project listing hero using `{colors.background}` canvas. Display the project title in `{typography.display-hero}` (SF Pro Display, 80px, weight 400, tracking -1px, line-height 1.0) in `{colors.ink}`. Below the title, show client name in `{typography.heading-sub}` (23px, tracking +0.45px). No border-radius on the image frame (`{rounded.none}`). Transition all color properties at 0.5s ease on hover."

- "Create a project grid card with `{rounded.none}` sharp edges, no box-shadow, and a `{colors.surface}` (#f5f5f5) image background. On hover, shift the card background from `{colors.surface}` to `{colors.primary-container}` over 0.5s ease. Set the project title below the image in `{typography.body}` (SF Pro Text, 14px, weight 400) in `{colors.ink}`."

- "Design a pill ghost button using `{components.button-ghost}`: background `{colors.primary-container}` (~4% black, rendered as #f0f0f0), text `{colors.ink}`, border-radius `{rounded.pill}` (9999px), padding 8px 16px, font `{typography.button-ui}`. Hover state: background `{colors.focus-tint}` (#e5e5e5), transition 0.5s ease."

- "Build a full-width inverted navigation bar on `{colors.surface-dark}` (#000000) canvas. Nav links in `{typography.nav-link}` (SF Pro Text, 14px, weight 400) in `{colors.on-primary}` (#ffffff). No border, no shadow. On scroll or page section change, transition between `{components.nav}` and `{components.nav-inverted}` at 0.5s ease."

- "Generate a case-study header with alternating black and white sections. White section: `{colors.background}` canvas, headline in `{typography.display}` (SF Pro Display, 48px, tracking -0.5px, weight 400) in `{colors.ink}`. Black section immediately below: `{colors.surface-dark}` canvas, same headline scale in `{colors.on-primary}`. The visual boundary between sections should be hard-cut — no gradient, no bleed."

- "Create a metadata badge for a news or project listing: `{components.badge}` — background `{colors.primary-container}`, text `{colors.ink}`, border-radius `{rounded.pill}`, font `{typography.caption}` (12px, weight 400), padding 4px 10px. No border, no icon."

### Iteration Guide

1. Start with `{colors.background}` (#ffffff) canvas and set all structural type in `{colors.ink}` (#000000) — the system has no neutral grays in its base layer
2. Introduce `{colors.surface-dark}` (#000000) as a second canvas for contrast sections; the inversion is the brand's signature move
3. Lock typography weight to 400 throughout; use font-size alone to create hierarchy from `{typography.display-hero}` down to `{typography.caption}`
4. Apply `{rounded.none}` to all image frames and cards; use `{rounded.pill}` only for interactive buttons and tags
5. Set all color transitions to 0.5s ease — never instant, never springy
6. Reserve `{colors.accent}` strictly for focus rings and accessibility UI
7. Let photography supply all hue — the typographic and structural system stays resolutely monochrome

---

## 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 Porto Rocha. Brand names and trademarks belong to their respective owners.
