- fg
#000000- bg
#FFFFFF- APCA Lc
- +106
- Use
- foreground on background
Plain
Restraint as a reaction to every bad support tool — teal accent, dark-green canvas, ABC Favorit + Geist Mono. Customer support in Linear's discipline.

Editorial disclaimer
This entry documents observable design-language patterns for educational transfer and AI-agent briefing. Screenshots and trademarks are property of their respective owners. AI2 Design is not affiliated with or endorsed by the featured brand. Inspiration here is about language and rhythm - do not reproduce brand identity, logo, product copy, or proprietary features.
Fair Use & Gallery PolicyCopy the full design language into your agent
A typed, paste-ready design system brief - philosophy, tokens, rules, techniques, and fitness checks. Drop it into Claude, Cursor, v0 or any coding agent and it builds in Plain’s language, not just a screenshot.
Calm operational minimalism carried by a single humanist sans. The canvas is off-white (#f3fbe9) over a deep green-black (#0a2414); ABC Favorit (Regular 400 / Medium 500) carries voice, weight, and rhythm across heading and body alike, with Geist Mono reserved exclusively for tiny eyebrow labels (13px, +0.195px tracking). Display headings step down a wide editorial ladder (80 / 48 / 44 / 24px) with negative px tracking (-1.6 to -0.48px) so type feels bound. A single brand teal (#17b267) and the classic link blue (#0000ee) are the only accents — color as punctuation, never paint. Elevation is delivered through near-invisible multi-layer shadows; motion is one curve at one duration, applied everywhere. Discipline over decoration, coherence over choreography.
Use this capture as a design language transfer brief for my project. Adopt the palette (off-white #f3fbe9 foreground on a deep green-black #0a2414 canvas, with a single brand teal #17b267 accent and classic blue #0000ee for inline links), the single-family typographic system (ABC Favorit Regular/Medium across heading and body, Geist Mono only for tiny mono eyebrow labels), the editorial heading ladder with negative px tracking (80/48/44/24px), the calm spacing scale (4/8/10/12/16/20/24/40/62px on a 1200px bounded container), whisper-quiet multi-layer elevation, the granular radius ladder (6/8/9/10/12px), and the single-curve motion language (cubic-bezier(0.44, 0, 0.56, 1) at 0.4s) across every page and component I ship. Treat this as my project's constitution — any new component I author should pass as if crafted in the same studio. Apply the language, not the source brand's specific copy or identity. When I ask you to build a page or component, enforce these rules by default, and call out any decision that deviates.
- Layout
- Editorial
- Content width
- Bounded
- Framing
- Flat
- Grid strength
- Soft
Near-monochrome calm canvas — off-white foreground #f3fbe9 reading over a deep green-black #0a2414 background does ~95% of the surface work, with pure #000000 and #ffffff appearing in component-level contexts. A single brand teal #17b267 carries every accent, emphasis, and call-to-action; the classic link blue #0000ee is reserved for inline anchor text. Semantic red #e23c3c handles error/destructive state only. Accents stay punctuation, never fill.
- Off-white #f3fbe9 foreground (ABC Favorit 400) is the dominant reading layer over the #0a2414 green-black canvas — pairing maintains 4.5+ contrast for body text
- Brand teal #17b267 (measured 191 occurrences) is the only emphasis accent — buttons, key links, highlighted figures. Keep its surface area under ~5%
- Classic link blue #0000ee (157 occurrences) reserved for inline anchor text within prose — the browser-default-leaning hue is intentional, signaling 'real link, not decorated button'
- Pure neutrals #000000 / #ffffff appear in card/panel contexts and inverted surfaces; the off-white #f3fbe9 and green-black #0a2414 remain the brand pairing
- Semantic red #e23c3c (11 occurrences) is reserved for error and destructive state — never decorative
- Pink #ffbac3 appears only inside an atmospheric conic gradient accent, never as a fill or text color
Gradients (paste-ready)
radial-gradient(50% 50%, rgba(10, 36, 20, 0.5) 0%, rgb(10, 36, 20) 100%) linear-gradient(rgba(10, 36, 20, 0) 20%, rgb(10, 36, 20) 100%) conic-gradient(rgba(255, 186, 195, 0.83) 182.489deg, rgba(255, 186, 195, 0) 339.654deg, rgba(255, 186, 195, 0.83) 360deg)
- Primary family: ABC Favorit (self-hosted woff2). Two weights only: Regular (400) for reading + Medium (500) for UI labels and emphasis. Monospace: Geist Mono, reserved exclusively for tiny eyebrow/kicker labels.
- Weight ladder is strictly 400 / 500 — do not introduce 600 or 700. Emphasis is carried by the 500 Medium step and by size, never by a heavier cut.
- Display tracking is negative and in px, not em: -1.6px on the 80px hero, -0.96px on 48px headings, -0.48px on 24px headings, -0.18px on 18px body. Tracking tightens as size grows — a constant optical correction.
- Heading ladder (observable): 80px/76px hero (ABC Favorit Regular), 48px/50px section heading, 44px/52.8px display, 24px/28px subhead (Regular or Medium 500). Body reads at 18px/24px and 15px/20px.
- Mono eyebrow labels: Geist Mono 13px, weight 500, line-height 19px, letter-spacing +0.195px — the only positive tracking on the page, and the only place mono appears.
- No italic for emphasis — the 500 Medium weight carries it. No second display or serif face; the entire authority is single-family.
- Paragraph measure stays comfortable at body 18px inside the narrow content rails (360–792px); never let prose run the full 1200px container width.
- Base rhythm is a 4px grid. Observed scale: 4 / 8 / 10 / 12 / 16 / 20 / 24 / 30 / 33 / 40 / 60 / 62px — calm and generous, not micro-dense.
- Container max-width 1200px (the dominant bounded rail, frequency 24). Narrow content rails nest inside at 360 / 480 / 592 / 680 / 792px for prose and form clusters.
- Flex/grid gutters draw from 4 / 8 / 10 / 12 / 16 / 20 / 24 / 40 / 62px — the 10 and 20 gaps are the most frequent (card rows, feature grids).
- Section vertical rhythm leans on the larger tokens (40 / 60 / 62px) between major blocks; tighter 16–24px inside cards and content clusters.
- Card padding lands in the 16–24px range on desktop; pull from the scale, never invent magic numbers.
- Elevation is whisper-quiet: multi-layer shadows at 4–18% alpha with sub-pixel-to-low offsets. Surfaces register as edges, not as floating cards.
- The signature lifted surface stacks three layers (e.g. `rgba(0,0,0,0.18) 0 0.66px 0.66px -1.25px, rgba(0,0,0,0.16) 0 2.52px 2.52px -2.5px, rgba(0,0,0,0.06) 0 11px 11px -3.75px`) with negative spread so the bloom is tight, never a halo.
- Default cards use a single near-invisible tint shadow (`rgba(32,39,44,0.04) 0 1.37px 2.66px 0`) — closer to a hairline than a drop-shadow.
- Depth is communicated through the off-white-vs-canvas background shift far more than through shadow stacking.
Techniques
Three-layer whisper shadow
Primary lifted surfaces use a stacked shadow `rgba(0,0,0,0.18) 0px 0.662406px 0.662406px -1.25px, rgba(0,0,0,0.16) 0px 2.51739px 2.51739px -2.5px, rgba(0,0,0,0.06) 0px 11px 11px -3.75px`. Negative spread on each layer keeps the falloff tight; total visible opacity reads under ~18%. Never increase alpha to 'make it pop' — the point is that it barely does.
Hairline tint shadow
Resting cards and inputs use a single `rgba(32, 39, 44, 0.04) 0px 1.37px 2.66038px 0px` — a 4%-alpha tint that behaves like a soft 1px edge rather than elevation. Pair with a 6–9px radius for the default surface.
- Radius ladder is granular and small: 6 / 8 / 9 / 10 / 12px (the captured 12.28px rounds to 12). The 6px and 9px steps are the most frequent — buttons and cards.
- Buttons and inputs default to 6–9px; cards and panels to 9–12px. No large pill radii except for indicator chips.
- Icons are stroke-based at 1.5–2px weight; no filled or duotone variants — they should read as quietly as the type.
- Tap targets minimum 40×40px on pointer, 44×44 on touch.
button-primary- backgroundColor
- #17b267
- textColor
- #f3fbe9
- radius
- 9px
- padding
- 10px 20px
- border
- 1px solid transparent
- boxShadow
- rgba(32, 39, 44, 0.04) 0px 1.37px 2.66038px 0px
- fontFamily
- ABC Favorit Medium
- fontWeight
- 500
- fontSize
- 15px
- lineHeight
- 20px
- letterSpacing
- -0.15px
Tailwind
inline-flex min-h-[40px] items-center gap-2 rounded-[9px] bg-[#17b267] px-5 py-2.5 text-[15px] font-medium leading-5 tracking-[-0.15px] text-[#f3fbe9] shadow-[rgba(32,39,44,0.04)_0px_1.37px_2.66038px_0px] transition-colors duration-[400ms] ease-[cubic-bezier(0.44,0,0.56,1)] hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#17b267] focus-visible:ring-offset-2
button-secondary- backgroundColor
- transparent
- textColor
- #f3fbe9
- radius
- 9px
- padding
- 10px 20px
- border
- 1px solid rgba(243, 251, 233, 0.16)
- boxShadow
- none
- fontFamily
- ABC Favorit Medium
- fontWeight
- 500
- fontSize
- 15px
- lineHeight
- 20px
- letterSpacing
- -0.15px
Tailwind
inline-flex min-h-[40px] items-center gap-2 rounded-[9px] border border-[rgba(243,251,233,0.16)] bg-transparent px-5 py-2.5 text-[15px] font-medium leading-5 tracking-[-0.15px] text-[#f3fbe9] transition-colors duration-[400ms] ease-[cubic-bezier(0.44,0,0.56,1)] hover:border-[rgba(243,251,233,0.32)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#17b267]
card-surface- backgroundColor
- #ffffff
- textColor
- #000000
- radius
- 12px
- padding
- 24px
- border
- none
- boxShadow
- rgba(0, 0, 0, 0.18) 0px 0.662406px 0.662406px -1.25px, rgba(0, 0, 0, 0.16) 0px 2.51739px 2.51739px -2.5px, rgba(0, 0, 0, 0.06) 0px 11px 11px -3.75px
Tailwind
rounded-[12px] bg-white p-6 text-black shadow-[rgba(0,0,0,0.18)_0px_0.662406px_0.662406px_-1.25px,rgba(0,0,0,0.16)_0px_2.51739px_2.51739px_-2.5px,rgba(0,0,0,0.06)_0px_11px_11px_-3.75px] transition-shadow duration-[400ms] ease-[cubic-bezier(0.44,0,0.56,1)]
input-field- backgroundColor
- #ffffff
- textColor
- #000000
- radius
- 6px
- padding
- 10px 12px
- border
- 1px solid #e3e3eb
- boxShadow
- rgba(32, 39, 44, 0.04) 0px 1.37px 2.66038px 0px
- fontFamily
- ABC Favorit Regular
- fontWeight
- 400
- fontSize
- 15px
- lineHeight
- 20px
- letterSpacing
- -0.15px
Tailwind
w-full rounded-[6px] border border-[#e3e3eb] bg-white px-3 py-2.5 text-[15px] leading-5 tracking-[-0.15px] text-black shadow-[rgba(32,39,44,0.04)_0px_1.37px_2.66038px_0px] placeholder:text-[#6e6e7a] transition-colors duration-[400ms] ease-[cubic-bezier(0.44,0,0.56,1)] focus-visible:outline-none focus-visible:border-[#17b267] focus-visible:ring-2 focus-visible:ring-[#17b267]/30
eyebrow-label- color
- #17b267
- fontFamily
- Geist Mono
- fontWeight
- 500
- fontSize
- 13px
- lineHeight
- 19px
- letterSpacing
- 0.195px
- textTransform
- uppercase
Tailwind
font-mono text-[13px] font-medium uppercase leading-[19px] tracking-[0.195px] text-[#17b267]
link-inline- color
- #0000ee
- textDecoration
- underline
- textDecorationColor
- #0000ee
- textDecorationThickness
- 1px
- textUnderlineOffset
- 2px
- transition
- color 400ms cubic-bezier(0.44, 0, 0.56, 1)
Tailwind
text-[#0000ee] underline decoration-[#0000ee] decoration-[1px] underline-offset-2 transition-colors duration-[400ms] ease-[cubic-bezier(0.44,0,0.56,1)] hover:text-[#17b267] hover:decoration-[#17b267] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#17b267]
Easings
cubic-bezier(0.44, 0, 0.56, 1)Scroll patterns
- Framer Motion intersection-triggered opacity + translateY reveals on the single 0.4s curve
- Stagger groups gently (40–80ms) but keep the per-item curve and duration constant — coherence over choreography
- No parallax, no long ambient loops — the page holds to one timing idea throughout
- Single easing: cubic-bezier(0.44, 0, 0.56, 1) — a symmetric ease-in-out that anchors every transition observed (28 occurrences, the only curve captured).
- Single duration: 0.4s. Do not invent a faster micro-duration or a slower ambient tier — uniformity is the signature.
- `color` is the primary animated property in the capture; extend the same curve/duration to opacity and border-color for hover, and to opacity+transform for scroll reveals.
- Framer Motion is the runtime (evidence: window.MotionIsMounted). Use deterministic tweens with the captured curve — no spring physics.
- useReducedMotion mandatory: all animations collapse to opacity-only or disable.
- No loop animations except explicit loaders (the only animation observed is a framer loading spinner).
- Primary CTA is a solid teal button; secondary actions are outline/ghost — never two solid accents competing in the same view.
- Inline links within prose use the classic blue (#0000ee) underline treatment; navigational/button affordances use teal. The two never blur.
- Mono eyebrow labels (Geist Mono, uppercase, 13px) introduce sections — the page's only kicker pattern.
- Accordion: single-open for FAQ; tooltips reveal on hover + focus with a short delay, dismiss on blur.
- Form validation: inline below the field on blur; error state uses the semantic red #e23c3c, never color-only (pair with text).
- Empty/feature states stay text-forward: a one-line label plus a 500-weight action link, not illustration.
- Loading states: skeleton or the framer loading spinner for content; inline state change for buttons. No full-page overlays.
Desktop-first because the audience is operational and technical teams on wide displays, and the content lives in a calm bounded 1200px rail. Mobile reflows the same single-family, single-accent language into the narrower sub-rails (360–792px) without inventing an alternate architecture — the page is the page, just reflowed.
- Observed breakpoints: sm 640 / md 768 / lg 960 / xl 1280 / 2xl 1520. Note lg is 960 (not 1024) and 2xl is 1520 — match the source, don't assume the Tailwind default ladder.
- Container max 1200px; nested content rails at 360 / 480 / 592 / 680 / 792px for prose and form clusters.
- Hide-on-mobile is banned — if a control exists on desktop it must reach mobile via reflow.
- Tap target minimum 44×44 on touch; 40×40 on pointer.
- Typography scales down proportionally: hero 80 → 48 → ~36, headings drop per tier while negative tracking eases (less negative at smaller sizes).
- focus-visible: 2px teal (#17b267) ring with offset on every interactive element. Mandatory — never rely on the default browser outline alone.
- All interactive elements reachable via Tab in logical reading order; never rely on hover to expose actions.
- Color contrast: off-white #f3fbe9 on green-black #0a2414 clears AA for body text; verify the teal #17b267 against its background reaches 4.5:1 for any text use, and 3:1 minimum for large display.
- Inline blue links (#0000ee) must remain distinguishable from body by more than color — keep the underline; never signal a link by hue alone.
- ARIA labels on icon-only buttons; aria-expanded on collapsible regions; aria-live='polite' on toast and status updates.
- Error state (#e23c3c) is always paired with text or an icon — never color-only signaling.
- Motion respects prefers-reduced-motion — the single 0.4s transition reduces to opacity-only or disables.
- Tap targets minimum 44×44 on touch; 40×40 on pointer.
Framer Motion is the confirmed runtime (evidence: window.MotionIsMounted); the page is built on the Framer platform (framerusercontent.com asset hosts, framer-loading-spin animation). Images are framer-optimized PNGs with responsive srcset; the hero loads eagerly (above-fold) while the long feature/logo set is lazy. Icons are stroke-based, 1.5–2px weight.
- Framer Motion `motion.div` with `whileInView` + `viewport={{ once: true }}` for scroll reveals
- Transitions use `ease: [0.44, 0, 0.56, 1]` and `duration: 0.4` — constants only, no springs
- useReducedMotion guard wraps every animation primitive — no exceptions
- Responsive images with `srcset`/`sizes` always set; eager-load only the above-fold hero, lazy-load the rest
- No canvas, no WebGL, no Lottie — static-first, animated-discreet
- Carry the whole page on ABC Favorit at weights 400 and 500 only; reach for Geist Mono exclusively for tiny uppercase eyebrow labels.
- Keep the teal #17b267 as the single emphasis accent and reserve the classic blue #0000ee for inline prose links.
- Apply negative px tracking on display sizes (-1.6 / -0.96 / -0.48 / -0.18px), tightening as size grows.
- Reach for the three-layer whisper shadow or the 4%-tint hairline before any heavier elevation.
- Keep all motion on cubic-bezier(0.44, 0, 0.56, 1) at 0.4s — one curve, one duration, everywhere.
- Bound content to the 1200px rail and nest prose in the narrow 360–792px sub-rails.
- Pass every page through useReducedMotion before shipping.
- Never introduce a second display or serif face — the single-family ABC Favorit commitment is the entire authority.
- Never substitute 600 or 700 weights for the 400/500 ladder — emphasis is the Medium step and size, not a heavier cut.
- Never add a second loud accent alongside the teal — color stays punctuation; the teal works because it's alone.
- Never invent a motion duration outside 0.4s or a second easing beyond cubic-bezier(0.44, 0, 0.56, 1); no springs, no parallax, no ambient loops.
- Never raise the elevation alpha past the captured whisper range (≤18% total) — surfaces register as edges, not floating cards.
- Never use em for display tracking — the px-based negative scale is an optical constant, not layout-relative.
- Never let prose run the full 1200px container width — keep it inside the narrow sub-rails.
- Tailwind v4 @theme inline only — no runtime style concatenation, no CSS-in-JS.
- Spacing scale: 4 / 8 / 10 / 12 / 16 / 20 / 24 / 30 / 33 / 40 / 60 / 62px.
- Container max 1200px; nested rails 360 / 480 / 592 / 680 / 792px — do not exceed 1200.
- Single font family + mono: ABC Favorit (400/500) + Geist Mono (labels only).
- Weight ladder strictly 400 / 500.
- Motion: one duration (0.4s) and one easing (cubic-bezier(0.44, 0, 0.56, 1)). No springs.
- Radius scale: 6 / 8 / 9 / 10 / 12px.
- Brand colors: canvas #0a2414, foreground #f3fbe9, accent teal #17b267, link blue #0000ee, error #e23c3c.
- Container width: no page exceeds 1200px wide; prose stays inside the 360–792px sub-rails.
- Spacing grep: no values outside the 4/8/10/12/16/20/24/30/33/40/60/62px ladder.
- Font-family grep: only ABC Favorit (heading + body) and Geist Mono (eyebrow labels) appear — no serif, no second display face.
- Font-weight grep: only 400 and 500 appear — no 600 or 700.
- Color grep: teal #17b267 is the only emphasis accent; inline links use #0000ee; no second loud accent present.
- Transition grep: every `transition-timing-function` is cubic-bezier(0.44, 0, 0.56, 1) and every duration is 0.4s — no other curve or duration.
- Shadow audit: elevation uses the whisper three-layer stack or the 4% tint hairline; total visible opacity ≤ ~18%.
- Tracking audit: display-size text uses px-based negative tracking (-1.6 / -0.96 / -0.48 / -0.18px), not em.
- Radius audit: every corner draws from 6 / 8 / 9 / 10 / 12px.
- Contrast audit: body text on the darkest background ≥ 4.5:1 (WCAG AA); inline links distinguishable beyond color.
Design tokens
Observed token system
Color, type, spacing, gradients, and stacking order captured from the live page and rendered here as living, paste-ready previews.
Inspector
Observable layers
Structure, breakpoints, motion, fonts, and images captured from the live page and kept paste-ready alongside the tokens.
Depth-first walk of the meaningful sections. 2 nodes across 2 levels, shallow to deep by color.
- body1
- div (×2)
Accessibility
Contrast matrix
296 combinations - 152 pass AA - 98 pass AAA. Each pair is previewed with its real foreground on background; APCA Lc sits alongside the WCAG 2.1 ratio for draft WCAG 3 awareness.
- fg
#FFFFFF- bg
#000000- APCA Lc
- -108
- Use
- background on foreground
- fg
#000000- bg
#FFFFFE- APCA Lc
- +106
- Use
- foreground on background
- fg
#FFFFFE- bg
#000000- APCA Lc
- -108
- Use
- background on foreground
- fg
#000000- bg
#F7FAF9- APCA Lc
- +103
- Use
- foreground on background
- fg
#F7FAF9- bg
#000000- APCA Lc
- -104
- Use
- background on foreground
- fg
#000000- bg
#F3FBE9- APCA Lc
- +102
- Use
- foreground on background
- fg
#F3FBE9- bg
#000000- APCA Lc
- -103
- Use
- background on foreground
- fg
#000000- bg
#F9F6F1- APCA Lc
- +101
- Use
- foreground on background
Images
Image strategy
Observable image posture - total count, lazy-loading ratio, and format mix. The hero image is measured above the fold.
- png23 · 79%
- svg6 · 21%
Hero image
https://framerusercontent.com/images/HniGCslQmEkXBEZ62EGDp5rlLV0.png?scale-down-to=2048&width=4261&height=3478- Format
- PNG
- Dimensions
- 1224x999
- Loading
- auto
- srcset
- yes
- Industry
- saas
- Industry
- developer-tools
- Theme
- Dark
- Added
- 2026-06-23
FAQ
Questions people ask about Plain
3questionsAnswers are pulled from the curator verdict and design brief - the same text your AI agent sees when it paste-reads this page.
Compare this with



