styling

Three layers, composable

1. Sensible defaults. Drop a component in — it works. 2. CSS custom properties on any ancestor re-skin every component below (tokens cross the shadow boundary by inheritance). 3. ::part() for piercing the shadow to target specific internals when tokens don't cover it.

Default (tier 1)

Each example wraps the same <atproto-post> in a <div> that sets different custom properties. No JS, no selector wizardry — the component inherits the tokens and re-skins itself.

Warm accent, small radii, serif

--atproto-accent: #ea580c;
--atproto-accent-soft: rgba(234,88,12,0.12);
--atproto-radius: 4px;
--atproto-font: Georgia, serif;

Compact density

--atproto-space-3: 0.4rem;
--atproto-space-4: 0.6rem;
--atproto-font-size: 0.85rem;
--atproto-font-size-sm: 0.78rem;
--atproto-line-height: 1.35;

Elevated (shadow, borderless)

--atproto-shadow: 0 10px 40px -12px rgba(17,133,254,0.35);
--atproto-border: transparent;
--atproto-radius: 16px;

Editorial serif

--atproto-font: "Iowan Old Style", Georgia, serif;
--atproto-font-size: 1rem;
--atproto-letter-spacing-tight: -0.015em;
--atproto-radius: 2px;

When tokens don't reach deep enough, use ::part() to target the component's named internals. Every high-level component documents its parts on its page.

atproto-post::part(article) {
  box-shadow: var(--atproto-shadow-lg);
  border-color: var(--accent);
}
atproto-post::part(avatar) { border-radius: 4px }
atproto-post::part(counts) {
  background: var(--atproto-accent-soft);
  padding: 0.5rem 0.75rem;
  border-radius: 8px;
}

Every named custom property the library reads. Override at any ancestor — tokens cross the shadow boundary by inheritance, so setting --atproto-accent on body restyles every component below.

Colors

Base palette + interactive states + semantic.

TokenPurpose
--atproto-bg Element background
--atproto-text Primary text
--atproto-muted Secondary text
--atproto-accent Links, counts, focus
--atproto-accent-soft Tints (pill bgs, hover rings)
--atproto-accent-hover Link hover color
--atproto-hover-bg Button/card hover background
--atproto-focus-ring Focus outline color
--atproto-border Card borders, separators
--atproto-subtle Lower-contrast fill for stripes
--atproto-link Explicit link color (defaults to accent)
--atproto-link-visited Visited link color
--atproto-error Error state accent
--atproto-warning Warning accent (gate-badge)
--atproto-success Success accent

Typography

Font stacks, size scale, weight, rhythm.

TokenPurpose
--atproto-font Sans stack
--atproto-font-mono Mono stack (code, CIDs)
--atproto-font-size-xs 0.75rem
--atproto-font-size-sm 0.85rem
--atproto-font-size 0.95rem (body default)
--atproto-font-size-lg 1.15rem
--atproto-font-size-xl 1.5rem (profile name)
--atproto-line-height 1.5 (body)
--atproto-line-height-tight 1.25 (headings)
--atproto-letter-spacing-tight -0.01em (headings)
--atproto-font-weight 400
--atproto-font-weight-semibold 600
--atproto-font-weight-bold 700

Spacing + radii + sizes

Consistent scales for layout rhythm.

TokenPurpose
--atproto-space-1..6 0.25 / 0.5 / 0.75 / 1 / 1.25 / 1.5 rem
--atproto-radius-sm 4px (tight inputs)
--atproto-radius-inner 8px (inside cards)
--atproto-radius 12px (default card)
--atproto-radius-lg 16px (outer containers)
--atproto-radius-pill 999px (badges, chips)
--atproto-avatar-size{,-sm,-lg} 40 / 24 / 80 px
--atproto-max-width 560px (content cap)

Elevation + motion

Shadows are opt-in (default flat); transition drives every hover.

TokenPurpose
--atproto-shadow Applied shadow (default: none)
--atproto-shadow-sm 1px preset
--atproto-shadow-md 4px preset
--atproto-shadow-lg 10px spread preset
--atproto-transition-duration 0.15s
--atproto-transition-easing ease
--atproto-transition Bundled color/bg/border/shadow/transform transition