{ "schemaVersion": 2, "generatedAt": "2026-05-21T00:00:00.000Z", "title": "Design System: dab", "extensions": { "colorMeta": { "canvas": { "role": "neutral", "displayName": "Lifted Canvas", "canonical": "oklch(22.6% 0.005 35)", "tonalRamp": ["#0c090b", "#1b181a", "#221f21", "#2a2729", "#423f42", "#555259", "#747178", "#a3a1a8"] }, "zinc-900": { "role": "neutral", "displayName": "Chrome", "canonical": "oklch(19.4% 0.005 35)", "tonalRamp": ["#0c090b", "#1b181a", "#221f21", "#2a2729", "#423f42", "#555259", "#747178", "#a3a1a8"] }, "zinc-800": { "role": "neutral", "displayName": "Elevated", "canonical": "oklch(25.5% 0.005 35)", "tonalRamp": ["#0c090b", "#1b181a", "#221f21", "#2a2729", "#423f42", "#555259", "#747178", "#a3a1a8"] }, "accent-500": { "role": "primary", "displayName": "Bookmark Coral", "canonical": "oklch(60.3% 0.219 357)", "tonalRamp": ["#5b143b", "#76174a", "#941b58", "#b8226e", "#db3a8b", "#f06da6", "#f9a8d4", "#fbcfe8"] }, "accent-400": { "role": "primary", "displayName": "Bookmark Coral (light)", "canonical": "oklch(68.3% 0.196 357)", "tonalRamp": ["#5b143b", "#76174a", "#941b58", "#b8226e", "#db3a8b", "#f06da6", "#f9a8d4", "#fbcfe8"] }, "accent-600": { "role": "primary", "displayName": "Bookmark Coral (deep)", "canonical": "oklch(52.6% 0.198 357)", "tonalRamp": ["#5b143b", "#76174a", "#941b58", "#b8226e", "#db3a8b", "#f06da6", "#f9a8d4", "#fbcfe8"] } }, "typographyMeta": { "display": { "displayName": "Display (Fraunces)", "purpose": "Page H1 inside PageHeader, and the brand wordmark in the header. One serif moment per page; never on cards, dialogs, or section titles." }, "body": { "displayName": "Body (Hanken Grotesk 450)", "purpose": "Default content. The 450 weight is intentional: heavier than 400 to resist halation on dark surfaces for astigmatic readers." }, "caption": { "displayName": "Caption (Hanken uppercase tracking)", "purpose": "Catalog-card overlines.
content in definition lists, table column headers, meta labels. Always uppercase with 0.1em tracking." }, "mono": { "displayName": "Mono (JetBrains Mono)", "purpose": "Mono-shaped values only: UUIDs, DAV URLs, host labels, ETags, sync tokens. Never decorative." } }, "shadows": [ { "name": "dialog-scrim-backdrop", "value": "background-color: rgba(12, 9, 11, 0.6); backdrop-filter: blur(4px);", "purpose": "Native backdrop. 4px blur is cosmetic, not structural." }, { "name": "dialog-lift", "value": "0 25px 50px -12px rgba(0, 0, 0, 0.25)", "purpose": "Native only. The single context where a heavy shadow earns its place." } ], "motion": [ { "name": "default-transition-duration", "value": "75ms", "purpose": "Tailwind default override via --default-transition-duration. Scoped to specific properties; never transition-all." }, { "name": "fade-in", "value": "fade-in 0.4s ease-out both", "purpose": "Main content entrance on page load." }, { "name": "slide-up", "value": "slide-up 0.35s ease-out both", "purpose": "Page-level content wrappers, route changes, toast entrance." }, { "name": "scale-fade", "value": "scale-fade 0.3s cubic-bezier(0.16, 1, 0.3, 1) both", "purpose": "Dialog open, popover entrance, scale-from-origin reveals." }, { "name": "shimmer", "value": "shimmer 1.5s ease-in-out infinite", "purpose": "Loading skeleton background sweep." }, { "name": "stagger-step", "value": "60ms", "purpose": "Increment between sibling entrance animations. Capped at 8 items (480ms ceiling)." }, { "name": "brand-glyph-rotate", "value": "transform: rotate(-6deg); transition: transform 200ms", "purpose": "Layers brand glyph signature hover. The single 'a person made this' moment in the chrome." } ], "breakpoints": [ { "name": "sm", "value": "640px" }, { "name": "md", "value": "768px" }, { "name": "lg", "value": "1024px" }, { "name": "xl", "value": "1280px" } ] }, "components": [ { "name": "Primary Button", "kind": "button", "refersTo": "button-primary", "description": "The primary CTA. Solid coral-magenta fill, white text, never a gradient. Used at most twice per page.", "html": "", "css": ".ds-btn-primary { display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; height: 2.5rem; padding: 0 1rem; border: none; border-radius: 0.75rem; background-color: #b8226e; color: #ffffff; font-family: 'Hanken Grotesk', ui-sans-serif, system-ui, sans-serif; font-size: 0.875rem; font-weight: 500; line-height: 1; cursor: pointer; transition: background-color 75ms, transform 75ms; } .ds-btn-primary:hover { background-color: #db3a8b; } .ds-btn-primary:active { transform: scale(0.98); } .ds-btn-primary:focus-visible { outline: none; box-shadow: 0 0 0 2px #221f21, 0 0 0 4px rgba(219, 58, 139, 0.5); } .ds-btn-primary:disabled { opacity: 0.6; cursor: not-allowed; }" }, { "name": "Secondary Button", "kind": "button", "refersTo": "button-secondary", "description": "Bordered neutral fill on Elevated surfaces. Resting state inside a card; primary nav buttons in the header.", "html": "", "css": ".ds-btn-secondary { display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; height: 2.5rem; padding: 0 1rem; border: 1px solid rgba(66, 63, 66, 0.6); border-radius: 0.75rem; background-color: rgba(42, 39, 41, 0.6); color: #e5e4e5; font-family: 'Hanken Grotesk', ui-sans-serif, system-ui, sans-serif; font-size: 0.875rem; font-weight: 500; line-height: 1; cursor: pointer; transition: background-color 75ms, transform 75ms; } .ds-btn-secondary:hover { background-color: rgba(66, 63, 66, 0.6); } .ds-btn-secondary:active { transform: scale(0.98); }" }, { "name": "Danger Button", "kind": "button", "refersTo": "button-danger", "description": "Confirm-shaped destructive actions (Revoke, Delete). Red tint with red text, never a solid red fill.", "html": "", "css": ".ds-btn-danger { display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; height: 2rem; padding: 0 0.75rem; border: 1px solid rgba(248, 113, 113, 0.2); border-radius: 0.75rem; background-color: rgba(248, 113, 113, 0.1); color: #fca5a5; font-family: 'Hanken Grotesk', ui-sans-serif, system-ui, sans-serif; font-size: 0.75rem; font-weight: 500; line-height: 1; cursor: pointer; transition: background-color 75ms, transform 75ms; } .ds-btn-danger:hover { background-color: rgba(248, 113, 113, 0.2); } .ds-btn-danger:active { transform: scale(0.98); }" }, { "name": "Ghost Button", "kind": "button", "refersTo": "button-ghost", "description": "Inline row actions, icon-only buttons, dialog 'Cancel' on light contexts.", "html": "", "css": ".ds-btn-ghost { display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; height: 2.5rem; padding: 0 1rem; border: none; border-radius: 0.75rem; background-color: transparent; color: #a3a1a8; font-family: 'Hanken Grotesk', ui-sans-serif, system-ui, sans-serif; font-size: 0.875rem; font-weight: 500; line-height: 1; cursor: pointer; transition: background-color 75ms, color 75ms, transform 75ms; } .ds-btn-ghost:hover { background-color: rgba(42, 39, 41, 0.7); color: #f5f4f4; } .ds-btn-ghost:active { transform: scale(0.97); }" }, { "name": "Card (Default)", "kind": "card", "refersTo": "card-default", "description": "The labeled shelf. One per record (calendar, address book, PAT, file row). Tonal layering on canvas, no shadow.", "html": "

Personal calendar

Active

Family events and birthdays.

Modified 2 days ago

", "css": ".ds-card { border: 1px solid rgba(66, 63, 66, 0.6); border-radius: 1rem; background-color: rgba(27, 24, 26, 0.5); padding: 1.25rem; font-family: 'Hanken Grotesk', ui-sans-serif, system-ui, sans-serif; color: #f5f4f4; } @media (min-width: 640px) { .ds-card { padding: 1.5rem; } } .ds-card-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.75rem; margin-bottom: 0.5rem; } .ds-card-title { font-size: 1rem; font-weight: 600; color: #f5f4f4; margin: 0; line-height: 1.4; } .ds-card-desc { font-size: 0.875rem; color: #a3a1a8; margin: 0; line-height: 1.55; font-weight: 450; } .ds-card-meta { font-size: 0.75rem; color: #747178; margin: 0.5rem 0 0; } .ds-badge { display: inline-flex; align-items: center; gap: 0.25rem; border: 1px solid; border-radius: 9999px; padding: 0.125rem 0.5rem; font-size: 0.75rem; font-weight: 500; } .ds-badge-success { border-color: rgba(52, 211, 153, 0.2); background-color: rgba(52, 211, 153, 0.1); color: #6ee7b7; }" }, { "name": "Input", "kind": "input", "refersTo": "input", "description": "Single-line text input. Soft-cornered, zinc-800 fill on canvas, focus ring uses the coral-magenta at 30% opacity.", "html": "", "css": ".ds-input { width: 100%; border: 1px solid rgba(66, 63, 66, 0.6); border-radius: 0.75rem; background-color: rgba(42, 39, 41, 0.8); padding: 0.625rem 1rem; color: #f5f4f4; font-family: 'Hanken Grotesk', ui-sans-serif, system-ui, sans-serif; font-size: 0.875rem; font-weight: 450; line-height: 1.55; outline: none; transition: border-color 75ms, box-shadow 75ms; } .ds-input::placeholder { color: #747178; } .ds-input:focus { border-color: rgba(219, 58, 139, 0.5); box-shadow: 0 0 0 1px rgba(219, 58, 139, 0.3); } .ds-input:focus-visible { box-shadow: 0 0 0 2px #221f21, 0 0 0 4px rgba(219, 58, 139, 0.5); }" }, { "name": "Badge (Accent)", "kind": "chip", "refersTo": "badge-accent", "description": "Pill-shaped chip in the bookmark-coral tone. Used for 'Active' nav states and accent-toned tags. Rare.", "html": "Active", "css": ".ds-badge { display: inline-flex; align-items: center; gap: 0.25rem; border: 1px solid; border-radius: 9999px; padding: 0.125rem 0.5rem; font-size: 0.75rem; font-weight: 500; font-family: 'Hanken Grotesk', ui-sans-serif, system-ui, sans-serif; } .ds-badge-accent { border-color: rgba(219, 58, 139, 0.2); background-color: rgba(219, 58, 139, 0.1); color: #f9a8d4; }" }, { "name": "Header (Brand)", "kind": "nav", "refersTo": "header", "description": "Sticky chrome at the top of every authed page. Layers glyph rotates -6deg on hover. Nav pills with active state in accent tone.", "html": "
", "css": ".ds-header { position: sticky; top: 0; z-index: 50; border-bottom: 1px solid rgba(42, 39, 41, 0.6); background-color: rgba(27, 24, 26, 0.95); backdrop-filter: blur(4px); font-family: 'Hanken Grotesk', ui-sans-serif, system-ui, sans-serif; } .ds-header-inner { max-width: 80rem; margin: 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 0.75rem 1rem; } @media (min-width: 640px) { .ds-header-inner { padding: 0.75rem 1.5rem; } } .ds-brand { display: inline-flex; align-items: center; gap: 0.75rem; color: inherit; text-decoration: none; transition: opacity 75ms; } .ds-brand:hover { opacity: 0.8; } .ds-brand-icon { display: inline-grid; place-items: center; width: 2.25rem; height: 2.25rem; color: #f06da6; transition: transform 200ms; } .ds-brand:hover .ds-brand-icon { transform: rotate(-6deg); } .ds-brand-text { display: none; } @media (min-width: 640px) { .ds-brand-text { display: block; } } .ds-brand-text strong { display: block; font-size: 0.875rem; font-weight: 600; color: #f5f4f4; } .ds-brand-text small { display: block; font-size: 0.75rem; color: #a3a1a8; } .ds-nav { display: flex; align-items: center; gap: 0.25rem; } .ds-nav-link { padding: 0.375rem 0.75rem; border-radius: 0.5rem; font-size: 0.875rem; color: #a3a1a8; text-decoration: none; transition: background-color 75ms, color 75ms; } .ds-nav-link:hover { background-color: rgba(42, 39, 41, 0.7); color: #f5f4f4; } .ds-nav-link-active { background-color: rgba(219, 58, 139, 0.1); color: #f9a8d4; }" }, { "name": "Copyable", "kind": "custom", "refersTo": "copyable", "description": "Mono value + Copy button. The receipt for any operation that produces a URL or token. Toast confirms on success; no celebratory animation.", "html": "
dab_pat_4f3a8b2c1e9d7f6a5b4c3d2e1f0a9b8c
", "css": ".ds-copyable { display: flex; align-items: stretch; gap: 0.5rem; border: 1px solid rgba(66, 63, 66, 0.6); border-radius: 0.75rem; background-color: rgba(27, 24, 26, 0.6); padding: 0.5rem; font-family: 'Hanken Grotesk', ui-sans-serif, system-ui, sans-serif; } .ds-copyable-value { flex: 1; min-width: 0; overflow-x: auto; padding: 0.375rem 0.5rem; font-family: 'JetBrains Mono', 'SF Mono', monospace; font-size: 0.875rem; color: #e5e4e5; white-space: nowrap; } .ds-copyable-btn { display: inline-flex; align-items: center; gap: 0.375rem; flex-shrink: 0; padding: 0 0.625rem; border: 1px solid rgba(66, 63, 66, 0.6); border-radius: 0.5rem; background-color: rgba(42, 39, 41, 0.6); color: #e5e4e5; font-size: 0.75rem; font-weight: 500; cursor: pointer; transition: background-color 75ms; } .ds-copyable-btn:hover { background-color: rgba(66, 63, 66, 0.6); }" }, { "name": "Page Header", "kind": "custom", "refersTo": "page-header", "description": "The placard at the top of each wing. Layers-tinted icon, Fraunces display H1, Hanken body description. One per page.", "html": "

Your profile

The identifiers and discovery URLs your DAV clients use to reach this account.

", "css": ".ds-page-header { margin-bottom: 1.5rem; padding-bottom: 1.5rem; border-bottom: 1px solid rgba(42, 39, 41, 0.6); display: flex; flex-direction: column; gap: 1rem; } @media (min-width: 640px) { .ds-page-header { flex-direction: row; align-items: flex-end; justify-content: space-between; } } .ds-page-header-row { display: flex; align-items: flex-start; gap: 1rem; font-family: 'Hanken Grotesk', ui-sans-serif, system-ui, sans-serif; } .ds-page-header-icon { margin-top: 0.25rem; color: #f06da6; } .ds-page-header-title { margin: 0; font-family: 'Fraunces', ui-serif, Georgia, serif; font-size: 1.875rem; font-weight: 800; line-height: 1.05; letter-spacing: -0.025em; color: #fafaf9; font-variation-settings: 'opsz' 32, 'SOFT' 60; } @media (min-width: 640px) { .ds-page-header-title { font-size: 2.25rem; } } .ds-page-header-desc { margin: 0.25rem 0 0; max-width: 42rem; font-size: 0.875rem; color: #a3a1a8; line-height: 1.55; font-weight: 450; } @media (min-width: 640px) { .ds-page-header-desc { font-size: 1rem; } }" } ], "narrative": { "northStar": "The private wing of the library.", "overview": "dab is the small reading room behind tessera's front desk. Each subject's opaque five-word host is the placard at the entrance to a wing of stacks; inside, three labeled shelves hold calendars, contacts, and files. The control-plane UI is a place to organize what is on those shelves, hand visitors (DAV clients) a shelfmark, and leave. Nothing on this surface wants your attention longer than necessary.\n\nThe aesthetic is institutional-print restraint with a single warm bookmark slip. Fraunces (warm variable serif) does the ceremonial work on page H1s and the brand mark, the way a typeset placard sits above a row of stacks. Hanken Grotesk does the steady labor everywhere else. Coral-magenta (#db3a8b) appears rarely, never as decoration. Its power is rarity.\n\nThe whole system explicitly rejects the share-link product (Dropbox / iCloud / Drive), the enterprise NAS appliance (Nextcloud / ownCloud / Synology), the AI-template dark-mode default, and the cheerful-Apple pastel calendar aesthetic. dab is not a daily driver; the design is sized for the four-times-a-year visit and the sixty-second task, and every surface should read like a labeled shelf rather than a marketing tile.", "keyCharacteristics": [ "Lifted-canvas dark only (#221f21); no light-mode toggle.", "One coral-magenta accent, one warm serif, one warm sans, one mono. Nothing more.", "Catalog-card density: each row carries display name, internal name (mono), one timestamp, the URL in a collapsed disclosure.", "Personality budget spent on the Layers glyph -rotate-6 on hover, the serif H1, the gold-magenta CTA, and the footer heart. Nowhere else.", "75ms default transition, scoped to specific properties. Never transition-all." ], "rules": [ { "name": "The One Bookmark Rule", "body": "Coral-magenta is the primary CTA, the active nav state, the footer heart, and nothing else. Never a background fill. Never a gradient. Never a decorative shadow. Never as a row stripe. If a third coral-magenta element appears on a page, one of the three is wrong.", "section": "colors" }, { "name": "The Lifted Canvas Rule", "body": "Body background is #221f21, not zinc-950, not #000. Lifting prevents halation for astigmatic readers and gives the surface hierarchy room to express depth without shadows. Don't push canvas darker for 'drama'; it makes the wing feel like a basement.", "section": "colors" }, { "name": "The Warm-Shifted Zinc Rule", "body": "Override stock zinc in @theme with the warm-shifted values. Stock zinc leans cool/clinical; the warm shift reads as 'neutral' rather than 'cool gray' and rhymes with cream paper. The warmth should be felt, not seen.", "section": "colors" }, { "name": "The Serif Once Rule", "body": "Fraunces appears on the page H1 inside PageHeader and on the brand mark in the header — nowhere else. Section titles, card titles, dialog titles all use Hanken. Spreading the serif across cards turns the wing into a museum gift shop. One serif moment per page.", "section": "typography" }, { "name": "The 450 Floor Rule", "body": "Body text never drops below font-weight 450. No font-light, no font-thin. Light strokes halate on dark surfaces for ~33% of users. The 450 floor is set on and cascades; only override upward.", "section": "typography" }, { "name": "The Mono For Mono-Shaped Values Rule", "body": "JetBrains Mono is reserved for values that are themselves machine-shaped: UUIDs, DAV URLs, host labels, ETags, sync tokens. Never use mono for 'tech feel' — that's the AI-template reflex. A user-facing display name is not mono.", "section": "typography" }, { "name": "The Tonal-First Rule", "body": "Depth comes from tone, not shadow. If you need something to feel raised, give it a lighter zinc fill — don't reach for box-shadow. Shadows on cards or buttons read as decoration; they earn their place only on .", "section": "elevation" }, { "name": "The Sticky Header Blur Rule", "body": "Header is bg-zinc-900/95 backdrop-blur-sm (4px). Never backdrop-blur-xl (24px) — the larger radius is ~6x more expensive per frame and barely distinguishable at high background opacity.", "section": "elevation" }, { "name": "The One-H1-Per-Page Rule", "body": "Every authed page has exactly one display H1 inside PageHeader. The dashboard's tile titles are H2 / CardTitle, not H1. The serif appears once.", "section": "components" }, { "name": "The Borderless Hover Rule", "body": "Hover transitions stay within the same hue family. Borders never cross-fade between zinc and accent; doing so produces a muddy intermediate even at 75ms. Use background tint shifts (hover:bg-zinc-700/60) for hover state, not border-color transitions.", "section": "components" }, { "name": "The 75ms Default Rule", "body": "--default-transition-duration: 75ms overrides Tailwind's 150ms default. Anything that feels sluggish at 75ms is either animating a layout property (don't) or has too many properties in scope (also don't). Scope transitions explicitly. Never transition-all.", "section": "components" } ], "dos": [ "Do use accent-600 for the primary CTA fill, hovering to accent-500. Solid, never a gradient.", "Do keep the page H1 in Fraunces via font-display. One serif H1 per page. Section titles and card titles are Hanken.", "Do treat each list row as a labeled shelf: display name, internal name (mono), one timestamp, the URL in a collapsed
. No charts, no sparklines, no KPI tiles.", "Do copy tessera's footer spacing (py-3 mobile, py-2 sm+). The suite reads consistent because the footer is.", "Do make the brand glyph rotate -rotate-6 on hover. That single micro-interaction carries the 'a person made this' message; everything else stays still.", "Do render calendar color as a h-3 w-3 rounded-full dot beside the display name. Solid fill, 1px border in zinc-700/60. No tinted background, no soft-pastel pill.", "Do return the user to the URL as the receipt. After PAT or collection creation, the page shows the URL inside Copyable. No 'Successfully created!' banner.", "Do respect prefers-reduced-motion via the global rule. No per-element guards.", "Do use tonal layering for depth (Chrome / Canvas / Elevated / Hover). Reach for shadow-2xl only on ." ], "donts": [ "Don't make dab feel like Dropbox, iCloud, or Google Drive. No tile-grid file browser. No 'Upgrade to Pro' banner. No share-link modal with social buttons. No 'Recents' carousel. No '+ New' floating action button.", "Don't make dab feel like Nextcloud, ownCloud, or Synology DSM. No Bootstrap-styled 'Files / Contacts / Calendar' tab bar. No left-rail accordion. No cyan-on-gray palette. No 'App Center' landing page.", "Don't ship any AI-template dark-mode signal: no neon-on-near-black, no gradient meshes, no glassmorphism (backdrop-blur-xl is forbidden), no gradient text (background-clip: text + gradient is banned), no shield-plus-checkmark hero icon, no 'Your data, secure' hero copy.", "Don't drift into the iCloud-style 'soft pastel' calendar aesthetic. Calendar color is one 12px dot, not a tinted pill. No pastel event-pill mocks anywhere in the UI.", "Don't use transition-all. Always scope to the properties that change.", "Don't animate border hue shifts (zinc → accent on hover). The intermediate hues read as muddy even at 75ms. Use background tint shifts instead.", "Don't use shadow-lg or shadow-xl on interactive elements. Reserve shadow-2xl for . No colored accent shadows (shadow-accent-500/10) anywhere.", "Don't use font-light or font-thin. Body weight floor is 450.", "Don't use side-stripe borders (left/right border-l >1px as a colored accent on cards or rows). Universal ban; rewrite with leading icons or full borders instead.", "Don't add a 'Welcome back, {name}!' or 'Successfully created!' banner. The user knows their name. The row appearing is the success.", "Don't put Fraunces on more than one element per page. Cards, dialogs, badges, and buttons all use Hanken. The serif is the signature, not decoration.", "Don't use mono for 'tech feel.' JetBrains Mono is for mono-shaped values (URLs, IDs, ETags, host labels) only." ] } }