Sentry
MIT
Dark, minimal design system for developer tools with a sophisticated purple palette and refined typography, tailored for error monitoring and performance platforms
Layout StudioImport this kit into a Studio project and start editing.
CLI installRun it in any project. No account needed.
npx @layoutdesign/context install sentry# layout.md — Sentry.io Design System
---
## 0. Quick Reference
> Inject this block into `CLAUDE.md` or `.cursorrules` for instant design-system awareness.
> **How to apply:** Use as `var(--sentry-token-name)` in CSS, `style={{ prop: 'var(--sentry-token-name)' }}` in JSX, or `bg-[var(--sentry-token-name)]` in Tailwind.
> **Full design system → see `layout.md`**
```css
:root {
/* Backgrounds */
--sentry-bg-app: #1F1633; /* Primary dark app background */
--sentry-bg-surface: #181225; /* Card / panel surface */
--sentry-bg-code: rgb(21, 15, 35); /* Code block background */
/* Text */
--sentry-text-primary: #ffffff; /* Headings, primary body */
--sentry-text-secondary: #ececf1; /* Secondary copy, captions */
--sentry-text-code: rgb(249, 117, 131); /* Inline code / syntax highlight */
/* Brand */
--sentry-accent: rgb(121, 98, 140); /* Secondary CTA, hover tint */
--sentry-purple: rgb(106, 95, 193); /* Interactive focus / active */
--sentry-gradient: linear-gradient(120deg, rgb(200,56,82), rgb(180,64,146), rgb(106,95,193) 50%, rgb(69,38,80) 55%, rgb(69,38,80) 100%);
/* Border */
--sentry-border: #362d59;
/* Spacing */
--sentry-space-xs: 4px; --sentry-space-sm: 8px;
--sentry-space-md: 16px; --sentry-space-lg: 20px;
--sentry-space-xl: 44px;
/* Radius */
--sentry-radius-sm: 6px; --sentry-radius-md: 8px;
--sentry-radius-lg: 12px; --sentry-radius-tab: 18px;
/* Motion */
--sentry-duration-fast: 0.2s; --sentry-duration-base: 0.3s;
--sentry-ease: ease;
/* Fonts */
--sentry-font-display: "Dammit Sans", sans-serif;
--sentry-font-body: "Rubik", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
--sentry-font-mono: "Monaco", "Menlo", "Ubuntu Mono", monospace;
}
```
```tsx
// Primary CTA Button — production-ready
const PrimaryButton = ({ children, disabled }: { children: React.ReactNode; disabled?: boolean }) => (
<button
disabled={disabled}
className="btn-new primary"
style={{
fontFamily: 'var(--sentry-font-body)',
fontSize: '14px', fontWeight: 500, lineHeight: '18px', letterSpacing: '0.2px',
color: 'var(--sentry-text-primary)',
backgroundColor: 'rgb(106, 95, 193)',
borderRadius: 'var(--sentry-radius-md)',
padding: '12px 16px',
border: '2px solid transparent',
textTransform: 'uppercase',
transition: `background-color var(--sentry-duration-fast) var(--sentry-ease)`,
cursor: disabled ? 'default' : 'pointer',
opacity: disabled ? 0.5 : 1,
}}
>
{children}
</button>
);
// hover → background-color: rgb(90,79,177)
// focus → outline: 2px solid rgb(106,95,193); outline-offset: 2px
```
**NEVER** use any font other than `Dammit Sans` (display), `Rubik` (body/UI), or `Monaco` (code).
**NEVER** use `border-radius` values outside `6px | 8px | 12px | 18px`.
**NEVER** hardcode hex colours — always reference `var(--sentry-*)` tokens.
<!-- Quick Reference truncated to fit the 75-line cap. See later sections for the full design system. -->
## 1. Design Direction & Philosophy
### Character & Mood
Sentry.io's marketing site is a **deep-space dark UI** — dramatic, developer-native, and unapologetically technical. The aesthetic merges a rave-poster gradient palette (hot-pink → violet → deep purple) with the brutalist clarity of a developer tool. It feels like staring into a terminal at midnight with neon backlighting.
### Personality Attributes
- **Irreverent confidence** — headline copy like *"Wake up babe"* and *"Code breaks, fix it"* is blunt, punchy, slightly provocative
- **Developer-first authenticity** — monospace code chips, inset shadow inputs, dark surfaces; never enterprise-glossy
- **Energetic restraint** — the gradient is bold, but it lives in the background; UI chrome stays minimal and quiet
### What This Design Explicitly Rejects
- **No light mode** — backgrounds are `#1F1633` and `#181225`; white backgrounds are error states
- **No rounded pill buttons** — standard `.btn-new` uses `border-radius: 8px`, not `border-radius: 9999px`
- **No neutral/flat greys** — all surfaces carry a purple tint; pure `#888` or `#ccc` greys are wrong
- **No Inter or Roboto** — the body font is **Rubik**, the display font is **Dammit Sans** (a custom brand typeface)
- **No heavy drop shadows** — elevation is whisper-light (`rgba(0,0,0,0.08) 0px 2px 8px`)
- **No warm tones in UI chrome** — warm colours (pink, coral) appear only in the gradient hero and CTAs
---
## 2. Colour System
### Tier 1 — Primitives
```css
:root {
/* Purple family */
--primitive-purple-950: #150F23; /* Deepest background / code block */
--primitive-purple-900: #181225; /* App surface (--bg-secondary) */
--primitive-purple-800: #1F1633; /* Primary background (--bg-primary) */
--primitive-purple-700: #362d59; /* Border / divider (--border-color) */
--primitive-purple-600: rgb(69, 38, 80); /* Gradient end deep-purple */
--primitive-purple-500: rgb(106, 95, 193); /* Sentry purple — interactive */
--primitive-purple-400: rgb(121, 98, 140); /* Muted accent / secondary CTA */
/* Pink / Red family */
--primitive-pink-600: rgb(200, 56, 82); /* Gradient start red-pink */
--primitive-pink-500: rgb(180, 64, 146); /* Gradient mid magenta */
--primitive-pink-400: rgb(194, 24, 91); /* Vimeo play button hover */
--primitive-pink-300: rgb(225, 86, 124); /* Logo focus fill */
--primitive-pink-200: rgb(249, 117, 131); /* Code chip / inline code text */
/* Neutral (purple-tinted white) */
--primitive-white: #ffffff;
--primitive-off-white: #ececf1;
--primitive-input-bg: #ffffff;
--primitive-input-text: rgb(31, 22, 51); /* Input text on white bg */
--primitive-input-border: rgb(207, 207, 219);
/* Gold / warm accent (button variants) */
--primitive-gold-light: rgb(255, 178, 135); /* primary-dark/secondary-dark focus bg */
--primitive-orange: rgb(252, 139, 97); /* melon-sunset focus */
/* Gradient */
--primitive-gradient-brand: linear-gradient(
120deg,
rgb(200, 56, 82),
rgb(180, 64, 146),
rgb(106, 95, 193) 50%,
rgb(69, 38, 80) 55%,
rgb(69, 38, 80) 100%
);
}
```
### Tier 2 — Semantic Aliases
```css
:root {
/* Backgrounds */
--sentry-bg-app: var(--primitive-purple-800); /* Page root background — #1F1633 */
--sentry-bg-surface: var(--primitive-purple-900); /* Cards, panels — #181225 */
--sentry-bg-code: var(--primitive-purple-950); /* Code blocks — #150F23 */
--sentry-bg-gradient: var(--primitive-gradient-brand); /* Hero / badge background */
/* Text */
--sentry-text-primary: var(--primitive-white); /* #ffffff — headings, body */
--sentry-text-secondary: var(--primitive-off-white); /* #ececf1 — captions, meta */
--sentry-text-code: var(--primitive-pink-200); /* rgb(249,117,131) — code chips */
--sentry-text-input: var(--primitive-input-text); /* rgb(31,22,51) — input on white */
--sentry-text-muted: var(--primitive-purple-400); /* rgb(121,98,140) — de-emphasised */
/* Interactive / Brand */
--sentry-color-interactive: var(--primitive-purple-500); /* rgb(106,95,193) — focus rings, active */
--sentry-color-accent: var(--primitive-purple-400); /* rgb(121,98,140) — silent btn hover */
--sentry-color-danger: var(--primitive-pink-600); /* rgb(200,56,82) — error states */
--sentry-color-focus-ring: var(--primitive-purple-500); /* rgb(106,95,193) */
/* Borders */
--sentry-border: var(--primitive-purple-700); /* #362d59 */
--sentry-border-input: var(--primitive-input-border);/* rgb(207,207,219) */
/* Originals preserved */
--bg-primary: #1F1633; /* ← original CSS var, preserved */
--bg-secondary: #181225; /* ← original CSS var, preserved */
--text-primary: #ffffff; /* ← original CSS var, preserved */
--text-secondary: #ececf1; /* ← original CSS var, preserved */
--border-color: #362d59; /* ← original CSS var, preserved */
}
```
### Tier 3 — Component Tokens
```css
:root {
/* Button */
--btn-primary-bg: rgb(106, 95, 193);
--btn-primary-bg-hover: rgb(90, 79, 177);
--btn-primary-focus-ring: rgb(106, 95, 193);
--btn-silent-hover-bg: rgba(121, 98, 140, 0.075);
--btn-silent-dark-hover-bg: rgb(106, 95, 193);
--btn-secondary-hover-bg: rgb(106, 95, 193);
--btn-default-hover-bg: rgb(236, 236, 241); /* light mode default btn */
--btn-snackbar-bg: rgb(85, 76, 154);
/* Badge */
--badge-bg: var(--sentry-bg-gradient);
--badge-text: var(--sentry-text-primary);
--badge-radius: var(--sentry-radius-lg); /* 12px */
/* Input */
--input-bg: var(--primitive-input-bg);
--input-text: var(--sentry-text-input);
--input-border: var(--sentry-border-input);
--input-shadow: rgba(0, 0, 0, 0.15) 0px 2px 10px 0px inset;
--input-radius: var(--sentry-radius-sm); /* 6px */
/* Code */
--code-bg: var(--sentry-bg-code); /* rgb(21,15,35) */
--code-text: var(--sentry-text-primary);
--code-chip-text: var(--sentry-text-code); /* rgb(249,117,131) */
--code-radius: 10px;
}
```
### Colour Mode Note
The extracted CSS variables define the **same values for both light and dark keys** (`--bg-primary`, `--bg-secondary`). Sentry.io's marketing site appears to be **dark-only**. No light-mode palette override is implemented. If light mode is ever added, gate overrides under `[data-theme="light"]`.
---
## 3. Typography System
> **NEVER list typography properties in isolation.** Always apply as composite groups.
> **Primary body font: Rubik.** Primary display font: Dammit Sans. Monospace: Monaco stack.
### Font Stacks
```css
:root {
--sentry-font-display: "Dammit Sans", sans-serif;
--sentry-font-body: "Rubik", -apple-system, BlinkMacSystemFont, "Segoe UI",
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
--sentry-font-mono: "Monaco", "Menlo", "Ubuntu Mono", monospace;
}
```
### Composite Type Groups
```css
:root {
/* ── Display / Hero ── */
/* h1: Used for page-level hero headline */
--type-h1-family: var(--sentry-font-display);
--type-h1-size: 88px;
--type-h1-weight: 700;
--type-h1-line-height: 105.6px; /* 1.2× */
--type-h1-letter-spacing: normal;
--type-h1-transform: none;
--type-h1-color: var(--sentry-text-primary);
--type-h1-margin-bottom: 24px;
/* h2: Section titles */
--type-h2-family: var(--sentry-font-display);
--type-h2-size: 60px; /* = --sentry-font-size-3xl */
--type-h2-weight: 500;
--type-h2-line-height: 66px; /* = --sentry-line-height-loose */
--type-h2-letter-spacing: normal;
--type-h2-align: center;
--type-h2-color: var(--sentry-text-primary);
/* h3: Sub-section titles, card headings (Rubik, NOT Dammit Sans) */
--type-h3-family: var(--sentry-font-body);
--type-h3-size: 16px; /* = --sentry-font-size-md */
--type-h3-weight: 600;
--type-h3-line-height: 24px;
--type-h3-letter-spacing: normal;
--type-h3-color: var(--sentry-text-primary);
--type-h3-margin-bottom: 16px;
/* body: Default paragraph text */
--type-body-family: var(--sentry-font-body);
--type-body-size: 14px; /* = --sentry-font-size-xs */
--type-body-weight: 400;
--type-body-line-height: 20px;
--type-body-letter-spacing: normal;
--type-body-color: var(--sentry-text-primary);
/* body-lg: Large body / pull quotes */
--type-body-lg-family: var(--sentry-font-body);
--type-body-lg-size: 16px;
--type-body-lg-weight: 400;
--type-body-lg-line-height: 32px; /* = --sentry-line-height-normal */
--type-body-lg-letter-spacing: normal;
/* quote: Testimonials / callout text (27px scale) */
--type-quote-family: var(--sentry-font-body);
--type-quote-size: 27px; /* = --sentry-font-size-2xl */
--type-quote-weight: 400;
--type-quote-line-height: 38px; /* estimated; no extracted value */
--type-quote-letter-spacing: normal;
/* label: Form labels — ALL CAPS */
--type-label-family: var(--sentry-font-body);
--type-label-size: 15px; /* = --sentry-font-size-sm */
--type-label-weight: 500;
--type-label-line-height: 21px;
--type-label-letter-spacing: normal;
--type-label-transform: uppercase;
--type-label-color: var(--sentry-text-primary);
--type-label-margin-bottom: 6px;
/* btn: Button text */
--type-btn-family: var(--sentry-font-body);
--type-btn-size: 14px;
--type-btn-weight: 500;
--type-btn-line-height: 18px;
--type-btn-letter-spacing: 0.2px;
--type-btn-transform: uppercase;
/* badge: Badge / pill labels */
--type-badge-family: var(--sentry-font-body);
--type-badge-size: 10px;
--type-badge-weight: 600;
--type-badge-line-height: 18px;
--type-badge-letter-spacing: 0.25px;
--type-badge-transform: uppercase;
/* code-chip: Inline code / syntax chips */
--type-code-family: var(--sentry-font-mono);
--type-code-size: 16px;
--type-code-weight: 400;
--type-code-line-height: 24px;
--type-code-letter-spacing: normal;
--type-code-color: var(--sentry-text-code); /* rgb(249,117,131) */
/* feature-title: 24px section feature headings */
--type-feature-family: var(--sentry-font-body);
--type-feature-size: 24px; /* = --sentry-font-size-xl */
--type-feature-weight: 600;
--type-feature-line-height: 32px;
--type-feature-letter-spacing: normal;
}
```
### Weight Scale
| Token | Value | Usage |
|---|---|---|
| `--sentry-font-weight-regular` | `400` | Body copy, nav links, code |
| `--sentry-font-weight-medium` | `500` | h2, labels, buttons |
| `--sentry-font-weight-semibold` | `600` | h3, badges, feature titles |
| `--sentry-font-weight-bold` | `700` | h1 only |
### Font Loading
All Rubik variants use `font-display: swap`. Dammit Sans (`.otf`) is a custom brand font — ensure the CDN path `/astro-assets/fonts/dammitsansv0.2-bold.otf` is available in all environments.
---
## 4. Spacing & Layout
### Base Unit & Scale
> The site uses a roughly 4px-base system. Note: `20.3px` (code block padding) and `6px` (label margin) are **off-grid legacy values** — do not replicate them. Use nearest grid token.
```css
:root {
/* Spacing scale — 4px base grid */
--sentry-space-1: 4px; /* = former --space-sm */
--sentry-space-2: 8px; /* = former --space-lg (mapped down) */
--sentry-space-3: 12px; /* inferred from input padding */
--sentry-space-4: 16px; /* = --space-lg: card padding, margin-bottom */
--sentry-space-5: 20px; /* = --space-xl: section padding increments */
--sentry-space-6: 24px; /* h1 margin-bottom */
--sentry-space-8: 32px; /* section rhythm */
--sentry-space-11: 44px; /* = --space-3xl: code block padding, large gaps */
--sentry-space-12: 48px; /* nav breathing room */
--sentry-space-14: 56px; /* [TBD - extract manually] */
/* Named semantic aliases */
--sentry-space-xs: var(--sentry-space-1); /* 4px — icon gap, badge margin */
--sentry-space-sm: var(--sentry-space-2); /* 8px — button padding, tight gaps */
--sentry-space-md: var(--sentry-space-4); /* 16px — card padding, label margin */
--sentry-space-lg: var(--sentry-space-5); /* 20px — section sub-spacing */
--sentry-space-xl: var(--sentry-space-11); /* 44px — section padding, code blocks */
/* Border Radius */
--sentry-radius-sm: 6px; /* inputs */
--sentry-radius-md: 8px; /* buttons (.btn-new), cards */
--sentry-radius-lg: 12px; /* badges (.new-pill), toggle */
--sentry-radius-tab: 18px; /* tab elements */
--sentry-radius-code: 10px; /* code blocks */
--sentry-radius-asymmetric: 12px 0px 0px 12px; /* toggle container — not for general use */
}
```
### Grid & Breakpoints
```css
:root {
/* Breakpoints — preserved from extracted CSS vars */
--breakpoint-xs: 0px;
--breakpoint-sm: 576px; /* Mobile landscape */
--breakpoint-md: 768px; /* Tablet */
--breakpoint-lg: 992px; /* Desktop */
--breakpoint-xl: 1152px; /* Wide desktop (max content width) */
/* Additional detected breakpoints (from media queries) */
--breakpoint-640: 640px; /* Tailwind sm breakpoint */
--breakpoint-767: 767px; /* Max-width mobile query */
--breakpoint-991: 991px; /* Max-width tablet query */
--breakpoint-1151: 1151px; /* Max-width wide query */
--breakpoint-1440: 1440px; /* Max layout width / clamp ceiling */
/* Container */
--sentry-container-max: 1152px; /* --breakpoint-xl */
--sentry-container-padding: 16px; /* horizontal gutter, mobile */
--sentry-container-padding-md: 32px; /* horizontal gutter, desktop */
}
```
### Layout Decision Rules
- **Navigation:** `display:flex; flex-direction:row; justify-content:center; align-items:center; padding:16px 0`
- **Button internals:** `display:flex; flex-direction:column; gap:4px; justify-content:center; align-items:center`
- **Standard `.btn-new`:** `display:inline-flex; flex-direction:row; align-items:center; gap:4px`
- **Use CSS Grid** for two-column feature layouts and pricing tables
- **Use Flexbox** for nav, button groups, badge+label rows, and single-axis lists
- **NEVER** use `position:absolute` to achieve layout alignment
---
## 5. Page Structure & Layout Patterns
> **Source:** Layout Digest (no screenshots available). Rows marked **(inferred)** are derived from component inventory and typographic hierarchy — not visually confirmed.
### 5.1 Section Map
| # | Section | Layout Type | Approx. Height | Key Elements |
|---|---|---|---|---|
| 1 | **Navigation / Header** | `flex row`, full-width, centered | ~64px | Logo, nav links, CTA button, menu toggle |
| 2 | **Hero** | Full-width, centered stack | ~560px (inferred) | h1 (88px Dammit Sans), gradient background, primary CTA pair |
| 3 | **SDK / Quickstart** | Centered, single column | ~300px (inferred) | Code block (`--sentry-bg-code`), copy, badge chip |
| 4 | **Feature Grid** | 3-column CSS Grid (inferred) | ~480px (inferred) | 24px h3s, body copy, icon per feature |
| 5 | **Testimonials / Social Proof** | Horizontal scroll or 3-column (inferred) | ~280px (inferred) | Quote text (27px), attribution (14px), logos |
| 6 | **Product Detail / Tabs** | Tabbed panel, full-width | ~400px (inferred) | Tabs (radius 18px), dropdown, code snippets |
| 7 | **"Everything's Connected" Section** | Centered stack + visual (inferred) | ~360px (inferred) | h2 (60px), paragraph, visual diagram |
| 8 | **Sign-up / CTA Banner** | Centered, constrained width (inferred) | ~240px (inferred) | Email input, label (uppercase), `.btn-new.primary` |
| 9 | **Footer** | Multi-column grid (inferred) | ~200px (inferred) | Nav link groups, legal copy (14px), social icons |
### 5.2 Layout Patterns
**Navigation (confirmed from digest):**
```css
nav[role="navigation"] {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 16px 0;
background-color: transparent; /* overlays gradient hero */
}
```
**Hero Section (inferred):**
- Full-viewport-width gradient background: `var(--sentry-bg-gradient)`
- Content centred within `max-width: 1152px` container
- h1 at `88px / 105.6px` line-height, `text-align: center`, `margin-bottom: 24px`
- CTA pair: likely a primary `.btn-new.primary` + secondary `.btn-new.silent.dark-mode` inline-flex row, `gap: 16px`
**Feature Cards (inferred — 3-column grid at ≥992px):**
```css
.feature-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px; /* var(--sentry-space-lg) */
max-width: 1152px;
margin: 0 auto;
padding: 44px 16px; /* var(--sentry-space-xl) */
}
/* ≤768px: grid-template-columns: 1fr */
```
**Code Block (confirmed from computed styles):**
```css
.code-block {
background-color: rgb(21, 15, 35); /* --sentry-bg-code */
border-radius: 10px; /* --sentry-radius-code */
padding: 44px 20px; /* --sentry-space-xl + nearest grid token */
font-family: var(--sentry-font-body); /* site uses Rubik even for code blocks */
color: var(--sentry-text-primary);
}
```
**Testimonial Row (inferred — horizontal scroll animation):**
- Uses `@keyframes scroll-x` (auto-scroll-x marquee)
- `--row-gap: 3.5rem` (56px) gap between cards
- Cards: `border: 1px solid var(--sentry-border)`, surface `var(--sentry-bg-surface)`
### 5.3 Visual Hierarchy
1. **h1 `88px` Dammit Sans** is the single most dominant element — hero only, never repeated
2. **h2 `60px` Dammit Sans** anchors each major section; always `text-align: center`
3. **Gradient (`--sentry-bg-gradient`)** is the primary brand signal — appears in hero bg, badges, and the animated "new-pill" component
4. **Primary CTA** (`.btn-new.primary`) uses `rgb(106, 95, 193)` — the sentry purple — not the gradient
5. **Badges** inject colour energy at small scale: 10px uppercase Rubik on gradient background
6. Section whitespace rhythm: `44px` top/bottom padding per section (`--sentry-space-xl`)
### 5.4 Content Patterns
- **Hero pattern:** `[gradient bg] [badge chip] [h1] [subtitle paragraph] [CTA pair]`
- **Feature pattern:** `[icon] [h3 24px] [body 14px]` — repeated 3× in grid
- **Quote pattern:** `[27px quote text] [14px attribution + role]` — scrolls horizontally
- **Code + copy pattern:** `[copy left] [code block right]` OR `[code full-width] [label below]`
- **Form pattern:** `[UPPERCASE label] [white input] [primary button]` — always dark bg behind white input
- **Badge + heading:** `[gradient badge "NEW"] [h2]` — badge appears directly above the section title
---
## 6. Component Patterns
### 6.1 Button (`.btn-new`)
**Anatomy:** `<button>` → `[optional icon] [text label]`
**Variants:** `primary` | `silent` | `secondary` | `default` | `quiet` | `snackbar` | `top-navigation` | `subnav` | `gold` | `melon-sunset`
**State Table:**
| State | Background | Border | Color | Other |
|---|---|---|---|---|
| default | `rgb(106,95,193)` | `transparent` | `#fff` | — |
| hover | `rgb(90,79,177)` | `rgb(90,79,177)` | `#fff` | — |
| focus | `rgb(106,95,193)` | — | `#fff` | `outline: 2px solid rgb(106,95,193); offset: 2px` |
| active | `rgb(90,79,177)` | — | `#fff` | — |
| disabled | — | — | — | `cursor: default; opacity: 0.5` |
| silent hover | `rgba(121,98,140,0.075)` | — | `#fff` | — |
| silent dark hover | `rgb(106,95,193)` | — | `#fff` | — |
```tsx
// Production-ready Button component with full state handling
import { ButtonHTMLAttributes, ReactNode } from 'react';
type ButtonVariant = 'primary' | 'silent' | 'secondary' | 'default' | 'quiet' | 'snackbar';
interface SentryButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
variant?: ButtonVariant;
darkMode?: boolean;
children: ReactNode;
loading?: boolean;
}
const variantStyles: Record<ButtonVariant, string> = {
primary: 'bg-[rgb(106,95,193)] border-transparent hover:bg-[rgb(90,79,177)] hover:border-[rgb(90,79,177)]',
silent: 'bg-transparent border-transparent hover:bg-[rgba(121,98,140,0.075)]',
secondary: 'bg-transparent border-[var(--sentry-border)] hover:bg-[rgb(106,95,193)] hover:text-white',
default: 'bg-transparent border-[rgb(207,207,219)] hover:bg-[rgb(236,236,241)] hover:border-[rgb(207,207,219)]',
quiet: 'bg-transparent border-transparent hover:bg-[rgba(106,95,193,0.075)]',
snackbar: 'bg-[rgb(85,76,154)] border-transparent hover:bg-[rgb(85,76,154)]',
};
export const SentryButton = ({
variant = 'primary',
darkMode = false,
children,
loading = false,
disabled,
className = '',
...props
}: SentryButtonProps) => {
const isDark = darkMode || variant === 'primary';
return (
<button
disabled={disabled || loading}
aria-disabled={disabled || loading}
className={[
// Base — always applied
'inline-flex flex-row items-center gap-1',
'px-4 py-3', // 16px / 12px — var(--sentry-space-md / --space-sm)
'rounded-[var(--sentry-radius-md)]', // 8px
'text-sm font-medium tracking-[0.2px] uppercase',
'font-[var(--sentry-font-body)]',
'border-2',
'transition-[background-color,border-color]',
'duration-[var(--sentry-duration-fast)]',
'focus:outline focus:outline-2 focus:outline-[rgb(106,95,193)] focus:outline-offset-2',
'disabled:cursor-default disabled:opacity-50',
isDark ? 'text-white' : 'text-[var(--sentry-text-input)]',
variantStyles[variant],
className,
].join(' ')}
{...props}
>
{loading ? (
<span className="animate-spin w-4 h-4 border-2 border-white border-t-transparent rounded-full" aria-hidden />
) : null}
{children}
</button>
);
};
```
---
### 6.2 Input
**Anatomy:** `<label> + <input type="text|email">`
| State | Background | Border | Shadow |
|---|---|---|---|
| default | `#ffffff` | `1px solid rgb(207,207,219)` | `rgba(0,0,0,0.15) 0px 2px 10px inset` |
| focus | `#ffffff` | `1px solid rgb(106,95,193)` | same + `0 0 0 2px rgba(106,95,193,0.2)` |
| disabled | `rgba(255,255,255,0.5)` | same | none |
| error | `#ffffff` | `1px solid rgb(200,56,82)` | `rgba(200,56,82,0.15) 0px 2px 10px inset` |
```tsx
interface SentryInputProps {
label: string;
id: string;
error?: string;
disabled?: boolean;
type?: string;
}
export const SentryInput = ({ label, id, error, disabled, type = 'text' }: SentryInputProps) => (
<div style={{ display: 'block' }}>
<label
htmlFor={id}
style={{
fontFamily: 'var(--sentry-font-body)',
fontSize: '15px', fontWeight: 500, lineHeight: '21px',
color: 'var(--sentry-text-primary)',
textTransform: 'uppercase',
display: 'block',
marginBottom: '6px',
}}
>
{label}
</label>
<input
id={id}
type={type}
disabled={disabled}
aria-invalid={!!error}
aria-describedby={error ? `${id}-error` : undefined}
style={{
fontFamily: 'var(--sentry-font-body)',
fontSize: '16px', fontWeight: 400, lineHeight: '24px',
color: 'var(--sentry-text-input)', /* rgb(31,22,51) */
backgroundColor: '#ffffff',
borderRadius: 'var(--sentry-radius-sm)', /* 6px */
padding: '8px 12px',
border: error ? '1px solid rgb(200,56,82)' : '1px solid rgb(207,207,219)',
boxShadow: error
? 'rgba(200,56,82,0.15) 0px 2px 10px 0px inset'
: 'rgba(0,0,0,0.15) 0px 2px 10px 0px inset',
width: '100%',
transition: `border-color var(--sentry-duration-fast) var(--sentry-ease),
box-shadow var(--sentry-duration-fast) var(--sentry-ease)`,
opacity: disabled ? 0.5 : 1,
cursor: disabled ? 'not-allowed' : 'text',
}}
/>
{error && (
<span id={`${id}-error`} style={{ color: 'rgb(200,56,82)', fontSize: '14px', marginTop: '4px', display: 'block' }}>
{error}
</span>
)}
</div>
);
```
---
### 6.3 Badge / New Pill
**Anatomy:** `<span class="new-pill">` containing short uppercase text
| State | Background | Transform |
|---|---|---|
| default | `var(--sentry-bg-gradient)` | none |
| hover | gradient position shifts to `98%` | — (CSS background-position animation) |
```tsx
export const SentryBadge = ({ children }: { children: ReactNode }) => (
<span
style={{
fontFamily: 'var(--sentry-font-body)',
fontSize: '10px', fontWeight: 600, lineHeight: '18px',
letterSpacing: '0.25px',
textTransform: 'uppercase',
color: '#ffffff',
backgroundImage: 'var(--sentry-bg-gradient)',
backgroundSize: '200% 100%',
backgroundPosition: '0% 0%',
borderRadius: 'var(--sentry-radius-lg)', /* 12px */
padding: '2px 6px',
display: 'inline-flex', alignItems: 'center',
marginLeft: '4px',
transition: `background-position var(--sentry-duration-fast) var(--sentry-ease)`,
}}
onMouseEnter={e => (e.currentTarget.style.backgroundPosition = '98% 0%')}
onMouseLeave={e => (e.currentTarget.style.backgroundPosition = '0% 0%')}
>
{children}
</span>
);
```
---
### 6.4 Navigation Item
**Anatomy:** `<nav>` > `<a>` or `<button class="btn-new silent dark-mode">`
| State | Background | Color |
|---|---|---|
| default | `transparent` | `#ffffff` |
| hover | `rgba(121,98,140,0.075)` | `#ffffff` |
| focus | transparent | `#ffffff` + `outline: 2px solid rgb(106,95,193)` |
| active (dark-mode) | `rgb(106,95,193)` | `#ffffff` |
```tsx
export const NavItem = ({ href, children }: { href: string; children: ReactNode }) => (
<a
href={href}
style={{
fontFamily: 'var(--sentry-font-body)',
fontSize: '16px', fontWeight: 400, lineHeight: '32px',
color: '#ffffff',
textDecoration: 'none',
padding: '4px 12px',
borderRadius: 'var(--sentry-radius-md)',
transition: `background-color var(--sentry-duration-fast) var(--sentry-ease)`,
display: 'inline-block',
}}
onMouseEnter={e => (e.currentTarget.style.backgroundColor = 'rgba(121,98,140,0.075)')}
onMouseLeave={e => (e.currentTarget.style.backgroundColor = 'transparent')}
>
{children}
</a>
);
```
---
### 6.5 Tab
**Anatomy:** `<button role="tab">` with `border-radius: 18px`
| State | Opacity | Transition |
|---|---|---|
| default (inactive) | `0.6` (inferred) | `opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1)` |
| active | `1.0` | same |
| hover | `0.85` (inferred) | same |
| focus | `1.0` + `outline: 2px solid rgb(106,95,193)` | same |
```tsx
export const SentryTab = ({ active, children, onClick }: { active: boolean; children: ReactNode; onClick: () => void }) => (
<button
role="tab"
aria-selected={active}
onClick={onClick}
style={{
fontFamily: 'var(--sentry-font-body)',
fontSize: '16px', fontWeight: 400, lineHeight: '32px',
color: '#ffffff',
backgroundColor: 'transparent',
border: 'none',
borderRadius: '18px', /* var(--sentry-radius-tab) */
padding: '4px 16px',
opacity: active ? 1 : 0.6,
cursor: 'pointer',
transition: 'opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
}}
>
{children}
</button>
);
```
---
### 6.6 Code Block
**Anatomy:** `<pre>` or `<div class="code-block">` containing `<code>` with `cls_chip` spans for syntax highlights
```tsx
export const SentryCodeBlock = ({ code, highlighted }: { code: string; highlighted?: string }) => (
<div
style={{
fontFamily: 'var(--sentry-font-body)',
fontSize: '16px', fontWeight: 400, lineHeight: '32px',
color: '#ffffff',
backgroundColor: 'rgb(21, 15, 35)', /* --sentry-bg-code */
borderRadius: '10px', /* --sentry-radius-code */
padding: '44px 20px', /* --sentry-space-xl + nearest grid */
display: 'block', overflowX: 'auto',
}}
>
<code style={{ fontFamily: 'var(--sentry-font-mono)' }}>
{/* Syntax-highlighted spans use color: rgb(249,117,131) — --sentry-text-code */}
{code}
</code>
</div>
);
```
---
## 7. Elevation & Depth
```css
:root {
/* Shadow tokens */
--sentry-shadow-sm: rgba(0, 0, 0, 0.10) 0px 1px 3px 0px inset; /* Inset shadow — used on inputs, toggle surfaces */
--sentry-shadow-md: rgba(0, 0, 0, 0.08) 0px 2px 8px 0px; /* Drop shadow — button_primary, cards */
--sentry-shadow-input: rgba(0, 0, 0, 0.15) 0px 2px 10px 0px inset; /* Input field inset — stronger than sm */
/* Border tokens */
--sentry-border-width: 1px;
--sentry-border-color: var(--sentry-border); /* #362d59 — panel/card borders */
--sentry-border-input: rgb(207, 207, 219); /* Input/form field borders — light on white bg */
--sentry-border-btn: 2px solid transparent; /* Button outline placeholder */
--sentry-border-focus: 2px solid rgb(106, 95, 193); /* Focus ring — all interactive elements */
/* Backdrop filter — glassmorphism on button_primary / toggle */
--sentry-backdrop: blur(18px) saturate(1.8);
/* Z-index scale */
--z-base: 0;
--z-raised: 10; /* Cards, panels */
--z-dropdown: 100; /* Dropdowns — margin-bottom: 73px accounts for this */
--z-nav: 200; /* Navigation bar */
--z-modal: 300; /* Modals, overlays */
--z-toast: 400; /* Snackbar / toast notifications */
}
```
### Layering Principles
- Cards sit on `--sentry-bg-surface` (`#181225`) against the `--sentry-bg-app` (`#1F1633`) — depth through **colour value**, not shadow
- Glassmorphism (`backdrop-filter: blur(18px) saturate(1.8)`) applies **only** to the `button_primary` toggle component — not general cards
- **Inset shadows** signal interactive inputs; **drop shadows** signal floating/elevated elements
- The gradient background creates perceived depth — no `z-index` manipulation needed for hero layering
---
## 8. Motion
```css
:root {
/* Duration tokens */
--sentry-duration-fast: 0.2s; /* UI micro-interactions: button hover, input border, badge position */
--sentry-duration-base: 0.3s; /* Tab opacity, menu open/close */
--sentry-duration-slow: 0.75s; /* New-pill gradient animation */
/* Easing tokens */
--sentry-ease-default: ease; /* 236 elements — standard transitions */
--sentry-ease-standard: cubic-bezier(0.4, 0, 0.2, 1); /* Tab transitions — Material-style */
--sentry-ease-snappy: cubic-bezier(0.4, 0, 1, 1); /* Checkbox: border-color/box-shadow 0.15s ease-in-out */
--sentry-ease-out: ease-out; /* Badge gradient: background 0.2s ease-out */
}
/* Named keyframe animations */
@keyframes sentry-fadeIn {
0% { opacity: 0; }
35% { opacity: 1; }
}
@keyframes sentry-float {
0%, 100% { transform: translateY(0px); }
50% { transform: translateY(-0.75rem); } /* -12px vertical float */
}
@keyframes sentry-scroll-x {
/* Testimonial marquee — loops at -50% - (gap/2) */
0% { transform: translateZ(0px); }
100% { transform: translate3d(calc(-50% - (var(--row-gap, 3.5rem) / 2)), 0, 0); }
}
@keyframes sentry-expandSnippet {
0% { max-height: 0px; opacity: 0; }
100% { max-height: 100rem; opacity: 1; }
}
@keyframes sentry-shrinkSnippet {
0% { max-height: 100rem; opacity: 1; }
100% { max-height: 0px; opacity: 0; }
}
@keyframes sentry-logo-rock {
0% { transform: rotate(0deg); }
10% { transform: rotate(0.5deg); }
25% { transform: rotate(1deg); }
50%, 75% { transform: rotate(-1deg); }
90% { transform: rotate(-0.5deg); }
100% { transform: rotate(0deg); }
}
@keyframes sentry-swingDown {
0%–60% { transform: rotate(0deg); }
70% { transform: rotate(-8deg); }
100% { transform: rotate(-7.5deg); }
}
@keyframes sentry-pushUp {
0% { transform: rotate(-7.5deg); }
100% { transform: rotate(0deg); }
}
```
### Motion Application Rules
- **Button hover:** `transition: box-shadow var(--sentry-duration-fast), background-color var(--sentry-duration-fast)` — never transition `all`
- **Tab opacity:** `transition: opacity var(--sentry-duration-base) var(--sentry-ease-standard)` — use the cubic-bezier, not `ease`
- **Badge gradient shift:** `transition: background-position var(--sentry-duration-fast) ease-out`
- **Snippet expand/collapse:** use `max-height` animation, not `height: auto` (which cannot be transitioned)
- **Respect `prefers-reduced-motion`:** Wrap `sentry-float`, `sentry-scroll-x`, and `sentry-logo-rock` in a media query guard — decorative motion only
```css
@media (prefers-reduced-motion: reduce) {
.floating-element { animation: none; }
.marquee { animation-play-state: paused; }
.logo-rock { animation: none; }
}
```
---
## 9. Anti-Patterns & Constraints
1. **Hardcoded hex colours → AI writes `color: #6a5fc1` directly in JSX → Use `var(--sentry-color-interactive)`.**
AI agents default to hardcoding colour values when they cannot find a CSS variable in scope. This makes colours impossible to theme or update globally. Always declare a `--sentry-*` token in `:root` first, then reference it. Never write a hex value into a component style prop.
2. **Wrong font family → AI defaults to `font-family: Inter, sans-serif` or `system-ui` → Use `var(--sentry-font-body)` (Rubik) or `var(--sentry-font-display)` (Dammit Sans).**
Most AI coding agents are trained on codebases that use Inter, Roboto, or system-ui. Sentry uses Rubik for all UI and Dammit Sans exclusively for h1/h2. An agent generating `font-family: 'Inter'` will produce visually incorrect output even if all other tokens are correct.
3. **Off-grid spacing → AI invents `margin: 10px` or replicates `20.3px` from the code block → Use only the defined `--sentry-space-*` scale.**
The extraction found off-grid values (`20.3px`, `2px`, `6px`) that are legacy quirks of the Astro build. AI agents copy extracted values literally. The corrected scale is `4px | 8px | 12px | 16px | 20px | 24px | 44px`. Never introduce a spacing value outside this scale.
4. **Light backgrounds on dark UI → AI generates `background: white` or `background: #f5f5f5` for card surfaces → Always use `var(--sentry-bg-surface)` (`#181225`) or `var(--sentry-bg-app)` (`#1F1633`).**
AI agents trained on general web UI assume light-mode defaults. Sentry's marketing site is dark-only. Any `#fff`, `#f0f0f0`, or `rgb(245,...)` surface colour is incorrect except for `<input>` fields, which intentionally use a white background for contrast.
5. **Pill-shaped buttons → AI may generate `border-radius: 9999px` on buttons because the brand gradient is pill-adjacent → Use `var(--sentry-radius-md)` (8px) for `.btn-new`.**
The border-radius census shows `18px` on tabs and `12px` on badges/pills — AI agents misread these as evidence that the *button* style is pill-shaped. The `.btn-new` element uses **8px** radius. Only the `new-pill` badge and tab elements use larger radii.
6. **Missing focus states → AI omits `outline` styles because they aren't visible in static screenshots → Every interactive element needs `outline: 2px solid rgb(106,95,193); outline-offset: 2px` on focus.**
Focus rings are accessibility requirements. The extraction confirms Sentry's focus style is `rgb(106,95,193)` (sentry purple). Agents that only see hover state data frequently skip focus entirely. Omitting it creates WCAG 2.4.7 failures.
7. **Animating `all` → AI writes `transition: all 0.2s ease` because it's shorter → Specify only the properties that change.**
The extracted `button_primary` style explicitly uses `transition: box-shadow 0.2s, background 0.2s` — not `all`. Animating `all` triggers layout recalculations on every property change, degrading performance. Name only the transitioning properties.
8. **Using `position: absolute` for section layout → AI places hero text absolutely inside gradient containers → Use flexbox centering (`display:flex; justify-content:center; align-items:center`).**
The nav digest confirms `justify-content: center; align-items: center` as the layout primitive. Absolute positioning breaks at non-standard viewport widths and cannot respond to content changes. Reserve `position: absolute` for decorative overlapping elements only.
9. **Generating dynamic Tailwind class names → AI writes `className={\`bg-[${colorVar}]\`}` → Use static class strings or inline `style` props.**
Tailwind's JIT compiler cannot detect dynamically constructed class strings at build time and will purge them. Use either complete static class names (`bg-[rgb(106,95,193)]`) or inline `style` props with `var(--sentry-*)` tokens. Never interpolate a variable into a Tailwind class string.
10. **Using `!important` to override specificity → AI applies `!important` when Bootstrap and Tailwind classes conflict → Fix specificity at the component level, not with overrides.**
Sentry's site loads both Tailwind and Bootstrap. Agents encountering specificity conflicts (common with two utility frameworks) often reach for `!important`, which makes later theming impossible. Instead, scope component styles with a parent class or CSS module, and ensure Sentry tokens are declared in `:root` with sufficient specificity.
11. **Wrong heading font → AI uses Rubik for h1/h2 because it's the body stack → h1 and h2 must use `var(--sentry-font-display)` (Dammit Sans).**
Dammit Sans is a custom `.otf` brand typeface used exclusively for the two largest heading levels. It is not in the Rubik fallback chain. An agent that sees `Rubik` as the body font and applies it universally will produce headings that look generic. h3 and below use Rubik — h1 and h2 use Dammit Sans.
12. **Fabricating shadow values → AI invents `box-shadow: 0 4px 6px rgba(0,0,0,0.1)` → Use only the two extracted shadow tokens.**
Sentry's shadow system is deliberately minimal: a whisper-light drop shadow (`rgba(0,0,0,0.08) 0px 2px 8px`) and an inset shadow for inputs. Generic shadow values from AI training data create visual inconsistency. Use `var(--sentry-shadow-md)` or `var(--sentry-shadow-input)` exclusively.
---
## Appendix A: Complete Token Reference
Every token extracted from the source. §0 CORE TOKENS is the primary AI signal; this appendix is reference material an AI can cross-check against when a curated role is missing.
```css
/* Colours (72) */
--bg-primary: #1F1633;
--bg-secondary: #181225;
--text-primary: #ffffff;
--text-secondary: #ececf1;
--border-color: #362d59;
--bg-primary: #1F1633; /* mode: dark */
--bg-secondary: #181225; /* mode: dark */
--text-primary: #ffffff; /* mode: dark */
--text-secondary: #ececf1; /* mode: dark */
--border-color: #362d59; /* mode: dark */
----gradient-badge-bg: linear-gradient(120deg, rgb(200, 56, 82), rgb(180, 64, 146), rgb(106, 95, 193) 50%, rgb(69, 38, 80) 55%, rgb(69, 38, 80) 100%); /* Gradient from badge background /* reconstructed */ */
--brand-primary-cta: rgb(21, 15, 35); /* Primary CTA background, dominant on 5 buttons — e.g. "button" /* mined from computed styles */ */
--brand-secondary-cta: rgb(121, 98, 140); /* Secondary CTA background, dominant on 1 button — e.g. "div" /* mined from computed styles */ */
--brand-surface-1: rgb(31, 22, 51); /* Brand surface, dominant on 8 elements — e.g. "Skip to main content
" /* mined from computed styles */ */
--sentry-bg-app: #1F1633;
--sentry-bg-surface: #181225;
--sentry-bg-code: rgb(21, 15, 35);
--sentry-text-primary: #ffffff;
--sentry-text-secondary: #ececf1;
--sentry-text-code: rgb(249, 117, 131);
--sentry-accent: rgb(121, 98, 140);
--sentry-purple: rgb(106, 95, 193);
--sentry-border: #362d59;
--primitive-purple-950: #150F23;
--primitive-purple-900: #181225;
--primitive-purple-800: #1F1633;
--primitive-purple-700: #362d59;
--primitive-purple-600: rgb(69, 38, 80);
--primitive-purple-500: rgb(106, 95, 193);
--primitive-purple-400: rgb(121, 98, 140);
--primitive-pink-600: rgb(200, 56, 82);
--primitive-pink-500: rgb(180, 64, 146);
--primitive-pink-400: rgb(194, 24, 91);
--primitive-pink-300: rgb(225, 86, 124);
--primitive-pink-200: rgb(249, 117, 131);
--primitive-white: #ffffff;
--primitive-off-white: #ececf1;
--primitive-input-bg: #ffffff;
--primitive-input-text: rgb(31, 22, 51);
--primitive-input-border: rgb(207, 207, 219);
--primitive-gold-light: rgb(255, 178, 135);
--primitive-orange: rgb(252, 139, 97);
--sentry-bg-gradient: linear-gradient(120deg, rgb(200,56,82), rgb(180,64,146), rgb(106,95,193) 50%, rgb(69,38,80) 55%, rgb(69,38,80) 100%);
--sentry-text-input: rgb(31, 22, 51);
--sentry-text-muted: rgb(121, 98, 140);
--sentry-color-interactive: var(--primitive-purple-500);
--sentry-color-accent: var(--primitive-purple-400);
--sentry-color-danger: rgb(200, 56, 82);
--sentry-color-focus-ring: var(--primitive-purple-500);
--sentry-border-input: rgb(207, 207, 219);
--btn-primary-bg: rgb(106, 95, 193);
--btn-primary-bg-hover: rgb(90, 79, 177);
--btn-primary-focus-ring: rgb(106, 95, 193);
--btn-silent-hover-bg: rgba(121, 98, 140, 0.075);
--btn-silent-dark-hover-bg: rgb(106, 95, 193);
--btn-secondary-hover-bg: rgb(106, 95, 193);
--btn-default-hover-bg: rgb(236, 236, 241);
--btn-snackbar-bg: rgb(85, 76, 154);
--badge-bg: var(--sentry-bg-gradient);
--input-bg: var(--primitive-input-bg);
--input-border: var(--sentry-border-input);
--code-bg: var(--sentry-bg-code);
--type-h1-color: var(--sentry-text-primary);
--type-h2-color: var(--sentry-text-primary);
--type-h3-color: var(--sentry-text-primary);
--type-body-color: var(--sentry-text-primary);
--type-label-color: var(--sentry-text-primary);
--type-code-color: var(--sentry-text-code);
--sentry-border-width: 1px;
--sentry-border-color: var(--sentry-border);
--sentry-border-btn: 2px solid transparent;
--sentry-border-focus: 2px solid rgb(106, 95, 193);
/* Typography (58) */
--font-size-xs: 14px; /* 12 elements — e.g. p "Systems Lead, Anthro", p "Director at Disney S", p "Infrastructure Softw" /* mined from computed styles */ */
--font-size-sm: 15px; /* 2 elements — e.g. label "Your Email:", label "I want to receive th" /* mined from computed styles */ */
--font-size-md: 16px; /* 75 elements — e.g. h3 "Company", h3 "Platform", h3 "Solutions" /* mined from computed styles */ */
--font-size-lg: 20px; /* 3 elements — e.g. div "We wouldn’t have sca", div "Sentry’s high-qualit", div "The signal we get fr" /* mined from computed styles */ */
--font-size-xl: 24px; /* 5 elements — e.g. h3 "Monitor in five line", h3 "Automatically root-c", h3 "Break production les" /* mined from computed styles */ */
--font-size-2xl: 27px; /* 8 elements — e.g. p "Yeah, other tools ex", p "Seer, our AI debugge", p "Five lines of code. " /* mined from computed styles */ */
--font-size-3xl: 60px; /* 9 elements — e.g. h2 "Wake up babe", h2 "Developer first. Alw", h2 "Everything’s connect" /* mined from computed styles */ */
--font-weight-regular: 400; /* 76 elements — e.g. p "Application monitori", p "Drop in the SDK. No ", p "Catch critical issue" /* mined from computed styles */ */
--font-weight-medium: 500; /* 35 elements — e.g. h2 "Wake up babe", h2 "Developer first. Alw", h2 "Everything’s connect" /* mined from computed styles */ */
--font-weight-semibold: 600; /* 4 elements — e.g. h3 "Company", h3 "Platform", h3 "Solutions" /* mined from computed styles */ */
--font-weight-bold: 700; /* 1 element — e.g. h1 "Code breaks, fix it " /* mined from computed styles */ */
--line-height-normal: 32px; /* 57 elements — e.g. p "See -- it's really j", p "Get started with jus", p "Just run this comman" /* mined from computed styles */ */
--line-height-loose: 66px; /* 9 elements — e.g. h2 "Wake up babe", h2 "Developer first. Alw", h2 "Everything’s connect" /* mined from computed styles */ */
--sentry-font-display: "Dammit Sans", sans-serif;
--sentry-font-body: "Rubik", -apple-system, ...;
--sentry-font-mono: "Monaco", "Menlo", "Ubuntu Mono", monospace;
--badge-text: var(--sentry-text-primary);
--input-text: var(--sentry-text-input);
--code-text: var(--sentry-text-primary);
--code-chip-text: var(--sentry-text-code);
--type-h1-line-height: 105.6px;
--type-h1-letter-spacing: normal;
--type-h2-line-height: 66px;
--type-h2-letter-spacing: normal;
--type-h3-line-height: 24px;
--type-h3-letter-spacing: normal;
--type-body-line-height: 20px;
--type-body-letter-spacing: normal;
--type-body-lg-line-height: 32px;
--type-body-lg-letter-spacing: normal;
--type-quote-line-height: 38px;
--type-quote-letter-spacing: normal;
--type-label-line-height: 21px;
--type-label-letter-spacing: normal;
--type-btn-line-height: 18px;
--type-btn-letter-spacing: 0.2px;
--type-badge-line-height: 18px;
--type-badge-letter-spacing: 0.25px;
--type-code-line-height: 24px;
--type-code-letter-spacing: normal;
--type-feature-line-height: 32px;
--type-feature-letter-spacing: normal;
--sentry-font-weight-regular: 400;
--sentry-font-weight-medium: 500;
--sentry-font-weight-semibold: 600;
--sentry-font-weight-bold: 700;
--sentry-font-size-xs: 14px;
--sentry-font-size-sm: 15px;
--sentry-font-size-md: 16px;
--sentry-font-size-lg: 20px;
--sentry-font-size-xl: 24px;
--sentry-font-size-2xl: 27px;
--sentry-font-size-3xl: 60px;
--sentry-font-size-hero: 88px;
--sentry-line-height-normal: 32px;
--sentry-line-height-loose: 66px;
--sentry-line-height-tight: 20px;
--sentry-line-height-h1: 105.6px;
/* Spacing (49) */
--breakpoint-xs: 0px;
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
--breakpoint-lg: 992px;
--breakpoint-xl: 1152px;
--space-xs: 2px; /* 150 elements — e.g. a .no-underline, a .no-underline, a .no-underline /* mined from computed styles */ */
--space-sm: 4px; /* 48 elements — e.g. div .toggle-container, div .toggle-container, div .toggle-container /* mined from computed styles */ */
--space-md: 6px; /* 150 elements — e.g. a .no-underline, a .no-underline, a .no-underline /* mined from computed styles */ */
--space-lg: 16px; /* 49 elements — e.g. nav .flex, nav .flex, div .flex-grid-cell /* mined from computed styles */ */
--space-xl: 20px; /* 48 elements — e.g. ul .list-none, ul .list-none, ul .list-none /* mined from computed styles */ */
--space-2xl: 20.3px; /* 64 elements — e.g. div .code-wrapper, div .code-wrapper, div .code-wrapper /* mined from computed styles */ */
--space-3xl: 44px; /* 64 elements — e.g. div .code-wrapper, div .code-wrapper, div .code-wrapper /* mined from computed styles */ */
--sentry-space-xs: 4px;
--sentry-space-sm: 8px;
--sentry-space-md: 16px;
--sentry-space-lg: 20px;
--sentry-space-xl: 44px;
--type-h1-size: 88px;
--type-h1-margin-bottom: 24px;
--type-h2-size: 60px;
--type-h3-size: 16px;
--type-h3-margin-bottom: 16px;
--type-body-size: 14px;
--type-body-lg-size: 16px;
--type-quote-size: 27px;
--type-label-size: 15px;
--type-label-margin-bottom: 6px;
--type-btn-size: 14px;
--type-badge-size: 10px;
--type-code-size: 16px;
--type-feature-size: 24px;
--sentry-space-1: 4px;
--sentry-space-2: 8px;
--sentry-space-3: 12px;
--sentry-space-4: 16px;
--space-lg: card padding, margin-bottom */
--sentry-space-5: 20px;
--space-xl: section padding increments */
--sentry-space-6: 24px;
--sentry-space-8: 32px;
--sentry-space-11: 44px;
--space-3xl: code block padding, large gaps */
--sentry-space-12: 48px;
--sentry-space-14: 56px;
--breakpoint-640: 640px;
--breakpoint-767: 767px;
--breakpoint-991: 991px;
--breakpoint-1151: 1151px;
--breakpoint-1440: 1440px;
--sentry-container-max: 1152px;
--sentry-container-padding: 16px;
--sentry-container-padding-md: 32px;
/* Radius (13) */
--radius-sm: 6px; /* 1 element — e.g. input .w-full /* mined from computed styles */ */
--radius-md: 8px; /* 40 elements — e.g. button .btn-new "Menu", button .btn-new "Platform", button .btn-new "Products" /* mined from computed styles */ */
--radius-lg: 12px; /* 20 elements — e.g. span .new-pill "NEW", span .new-pill "NEW", span .new-pill "NEW" /* mined from computed styles */ */
--radius-full: 12px 0px 0px 12px; /* 1 element — e.g. div .toggle-container "Marketing Mode" /* mined from computed styles */ */
--sentry-radius-sm: 6px;
--sentry-radius-md: 8px;
--sentry-radius-lg: 12px;
--sentry-radius-tab: 18px;
--badge-radius: var(--sentry-radius-lg);
--input-radius: var(--sentry-radius-sm);
--code-radius: 10px;
--sentry-radius-code: 10px;
--sentry-radius-asymmetric: 12px 0px 0px 12px;
/* Effects (7) */
----backdrop-filter-button_primary: backdrop-filter: blur(18px) saturate(1.8); /* Backdrop filter from button_primary /* reconstructed */ */
--shadow-sm: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px inset; /* 1 element — e.g. div .toggle-track /* mined from computed styles */ */
--shadow-md: rgba(0, 0, 0, 0.08) 0px 2px 8px 0px; /* 1 element — e.g. div .toggle-container /* mined from computed styles */ */
--input-shadow: rgba(0, 0, 0, 0.15) 0px 2px 10px 0px inset;
--sentry-shadow-sm: rgba(0,0,0,0.10) 0px 1px 3px 0px inset;
--sentry-shadow-md: rgba(0,0,0,0.08) 0px 2px 8px 0px;
--sentry-shadow-input: rgba(0,0,0,0.15) 0px 2px 10px 0px inset;
/* Motion (14) */
----motion-fadeIn: @keyframes fadeIn {
0% { opacity: 0; }
35% { opacity: 1; }
}; /* @keyframes fadeIn */
----motion-float: @keyframes float {
0%, 100% { transform: translateY(0px); }
50% { transform: translateY(-0.75rem); }
}; /* @keyframes float */
----motion-logo-rock: @keyframes logo-rock {
0% { transform: rotate(0deg); }
10% { transform: rot… <0.3KB elided>; /* @keyframes logo-rock */
----motion-scroll-x: @keyframes scroll-x {
0% { transform: translateZ(0px); }
100% { transform: translate3d(calc(-50% - (var(--row-gap, 3.5rem) / 2)),0,0); }
}; /* @keyframes scroll-x */
----motion-expandSnippet: @keyframes expandSnippet {
0% { max-height: 0px; opacity: 0; }
100% { max-height: 100rem; opacity: 1; }
}; /* @keyframes expandSnippet */
----motion-shrinkSnippet: @keyframes shrinkSnippet {
0% { max-height: 100rem; opacity: 1; }
100% { max-height: 0px; opacity: 0; }
}; /* @keyframes shrinkSnippet */
----motion-swingDown: @keyframes swingDown {
0% { transform: rotate(0deg); }
60% { transform: rot… <0.3KB elided>; /* @keyframes swingDown */
----motion-pushUp: @keyframes pushUp {
0% { transform: rotate(-7.5deg); }
100% { transform: rotate(0deg); }
}; /* @keyframes pushUp */
----motion-_spin_1vwuf_1: @keyframes _spin_1vwuf_1 {
0% { transform: translate(-50%, -50%) rotate(0deg); }
100% { transform: translate(-50%, -50%) rotate(360deg); }
}; /* @keyframes _spin_1vwuf_1 */
----motion-_thumbRotation_1vwuf_1: @keyframes _thumbRotation_1vwuf_1 {
0% { transform: rotate(-20deg); }
100% { transform: rotate(15deg); }
}; /* @keyframes _thumbRotation_1vwuf_1 */
--duration-fast: 0.2s; /* 135 elements — e.g. button, button, button /* mined from computed styles */ */
--duration-base: 0.3s; /* 9 elements — e.g. button, button, button /* mined from computed styles */ */
--duration-slow: 0.75s; /* 1 element — e.g. span /* mined from computed styles */ */
--ease-default: ease; /* 236 elements — e.g. button, button, button /* mined from computed styles */ */
```
## Appendix B: Token Source Metadata
```yaml
tokenSource: reconstructed-from-computed
confidence: medium
# 10 CSS custom properties found in the page source (high confidence)
# Remaining 26 curated tokens synthesised from computed element styles (medium confidence)
# Brand gradient: reconstructed from badge backgroundImage (low confidence for exact stop positions)
extractedCSSVars: 10
# --bg-primary, --bg-secondary, --text-primary, --text-secondary, --border-color
# --breakpoint-xs, --breakpoint-sm, --breakpoint-md, --breakpoint-lg, --breakpoint-xl
reconstructedTokens: 26
# Method: computed style clustering by hue family and usage context
# Colour clustering: purple hue family (5 stops), pink/red family (5 stops), neutral white
# Spacing clustering: 4px base grid — outliers 20.3px and 6px flagged as off-grid legacy
# Radius clustering: 4 distinct values found (6, 8, 12, 18px) + 1 asymmetric (12px 0 0 12px)
fonts:
- family: Dammit Sans
format: opentype (.otf)
confidence: high — explicitly declared in @font-face
note: Custom brand typeface, not available from CDN — path /astro-assets/fonts/dammitsansv0.2-bold.otf
- family: Rubik
format: woff2 + woff
confidence: high — 5 @font-face declarations (400, 500, 700, italic variants)
- family: Monaco
format: system font (no src)
confidence: high — declared but loaded from OS
libraries:
- tailwind: v3 assumed (no CSS vars in @theme; utility classes detected)
- bootstrap: detected (conflicts may arise with Tailwind; specificity rules apply)
notes:
- The --brand-secondary-cta value (rgb(121,98,140)) was originally reconstructed; mapped to --sentry-accent
- The --bg-app gradient is LOW confidence for exact colour stop positions — verify against live site
- No dark/light mode toggle detected — site appears dark-only
- The body element computed color (rgb(55,65,81)) is a Tailwind default bleed-through, NOT a Sentry token
- 20.3px code block padding is a build artifact, replaced with 20px in the token system
- border-radius 18px (tab) appears only on .tab elements — NOT a general card or button radius
```More from the gallery
Browse all kits →You may also like

Contra
MITPlayful yet professional design system with teal and purple accents, bold typography, and vibrant accent surfaces—built for modern SaaS platforms and landing pages
03
lightboldsaaslanding-page

DoorDash
MITClean, accessible food-delivery system with DoorDash's signature red accent, light neutral palette, and system-font typography—built for rapid product development
03
lightecommsaasmobile

Mercedes-Benz
MITLuxe, minimalist design system with sharp black-and-white contrast and serif typography, crafted for premium automotive and lifestyle brands
05
darkminimalboldecomm