Sentry
MIT
Dark, minimal design system for developer tools with a sophisticated purple palette and refined typography, tailored for error monitoring and performance platforms
Colour (72)
color.codebgvar(--sentry-bg-code)
color.badgebgvar(--sentry-bg-gradient)
color.inputbgvar(--primitive-input-bg)
color.bgprimary#1F1633
color.bgsecondary#181225
color.bordercolor#362d59
color.inputbordervar(--sentry-border-input)
color.sentrybgapp#1F1633
color.textprimary#ffffff
color.typeh1colorvar(--sentry-text-primary)
color.typeh2colorvar(--sentry-text-primary)
color.typeh3colorvar(--sentry-text-primary)
color.btnprimarybgrgb(106, 95, 193)
color.sentryaccentrgb(121, 98, 140)
color.sentrybgcodergb(21, 15, 35)
color.sentryborder#362d59
color.sentrypurplergb(106, 95, 193)
color.brandsurface1rgb(31, 22, 51)
color.btnsnackbarbgrgb(85, 76, 154)
color.textsecondary#ececf1
color.typebodycolorvar(--sentry-text-primary)
color.typecodecolorvar(--sentry-text-code)
color.bgprimary.dark#1F1633
color.primitivewhite#ffffff
color.sentrytextcodergb(249, 117, 131)
color.typelabelcolorvar(--sentry-text-primary)
color.brandprimaryctargb(21, 15, 35)
color.gradientbadgebglinear-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%)
color.primitiveorangergb(252, 139, 97)
color.sentrybgsurface#181225
color.sentryborderbtn2px solid transparent
color.sentrytextinputrgb(31, 22, 51)
color.sentrytextmutedrgb(121, 98, 140)
color.bgsecondary.dark#181225
color.bordercolor.dark#362d59
color.btnsilenthoverbgrgba(121, 98, 140, 0.075)
color.primitiveinputbg#ffffff
color.primitivepink200rgb(249, 117, 131)
color.primitivepink300rgb(225, 86, 124)
color.primitivepink400rgb(194, 24, 91)
color.primitivepink500rgb(180, 64, 146)
color.primitivepink600rgb(200, 56, 82)
color.sentrybggradientlinear-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%)
color.textprimary.dark#ffffff
color.brandsecondaryctargb(121, 98, 140)
color.btndefaulthoverbgrgb(236, 236, 241)
color.btnprimarybghoverrgb(90, 79, 177)
color.primitiveoffwhite#ececf1
Spacing (46)
spacing.breakpointxs0px
spacing.spacexs2px
spacing.spacesm4px
spacing.sentryspace14px
spacing.sentryspacexs4px
spacing.spacemd6px
spacing.typelabelmarginbottom6px
spacing.sentryspace28px
spacing.sentryspacesm8px
spacing.typebadgesize10px
spacing.sentryspace312px
spacing.typebtnsize14px
spacing.typebodysize14px
spacing.typelabelsize15px
spacing.spacelg16px
spacing.typeh3size16px
spacing.sentryspace416px
spacing.typecodesize16px
spacing.sentryspacemd16px
spacing.typebodylgsize16px
spacing.typeh3marginbottom16px
spacing.sentrycontainerpadding16px
spacing.spacexl20px
spacing.sentryspacelg20px
spacing.space2xl20.3px
spacing.typefeaturesize24px
spacing.typeh1marginbottom24px
spacing.typequotesize27px
spacing.sentryspace832px
spacing.sentrycontainerpaddingmd32px
spacing.space3xl44px
spacing.sentryspace1144px
spacing.sentryspacexl44px
spacing.sentryspace1456px
spacing.typeh2size60px
spacing.typeh1size88px
spacing.breakpointsm576px
spacing.breakpoint640640px
spacing.breakpoint767767px
spacing.breakpointmd768px
spacing.breakpoint991991px
spacing.breakpointlg992px
spacing.breakpoint11511151px
spacing.breakpointxl1152px
spacing.sentrycontainermax1152px
spacing.breakpoint14401440px
Radius (13)
badgeradiusvar(--sentry-radius-lg)
inputradiusvar(--sentry-radius-sm)
radiussm6px
sentryradiussm6px
radiusmd8px
sentryradiusmd8px
coderadius10px
sentryradiuscode10px
radiuslg12px
radiusfull12px 0px 0px 12px
sentryradiuslg12px
sentryradiusasymmetric12px 0px 0px 12px
sentryradiustab18px
Shadow (7)
effect.shadowmdrgba(0, 0, 0, 0.08) 0px 2px 8px 0px
effect.shadowsmrgba(0, 0, 0, 0.1) 0px 1px 3px 0px inset
effect.inputshadowrgba(0, 0, 0, 0.15) 0px 2px 10px 0px inset
effect.sentryshadowmdrgba(0,0,0,0.08) 0px 2px 8px 0px
effect.sentryshadowsmrgba(0,0,0,0.10) 0px 1px 3px 0px inset
effect.sentryshadowinputrgba(0,0,0,0.15) 0px 2px 10px 0px inset
effect.backdropfilterbuttonprimarybackdrop-filter: blur(18px) saturate(1.8)
# 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

Vercel
MITClean, minimal developer-focused design system built on Geist typography with light surfaces, precise spacing, and fast interactions for modern web applications
00
lightminimaldeveloper-toolsaas

OpenAI
MITClean, minimal design system for AI-native products built on Next.js and Tailwind, featuring a light monochromatic palette with precise token-based spacing and typography
02
lightminimalsaasdeveloper-tool

Coinbase
MITClean, professional fintech design system with bright blue accents and minimal aesthetic, built for React/Next.js applications and financial platforms
00
lightminimalfintechsaas