# MPS Design System ## Overview Make Post Sell uses a design token architecture with CSS custom properties as the single source of truth. Mobile-first. CSS Grid only (no Flexbox). Accessible. Respects reduced motion. Supports light and dark themes. ## Architecture Diagram ``` ┌─────────────────────────────────────────────────────────┐ │ tokens.css │ │ Design Tokens (:root) │ │ │ │ Colors · Typography · Spacing · Shape · Elevation │ │ Motion · Z-index · Layout · State overlays │ │ │ │ [data-theme="dark"] overrides │ │ │ │ Base resets · Focus · Selection │ │ Typography utilities (.type-*) │ │ Elevation utilities (.elevation-*) │ │ Surface utilities (.surface-*) │ │ State layer · Ripple effect │ │ Animations · Skeleton loading · Spinner │ │ Spacing utilities (.mt-*, .mb-*, .p-*, .gap-*) │ │ Container utilities (.container, -narrow, -wide) │ └──────────────────────┬──────────────────────────────────┘ │ consumed by ▼ ┌─────────────────────────────────────────────────────────┐ │ common.css │ │ Component Styles │ │ │ │ Body layout · Navigation · Forms · Buttons │ │ Product grid · Cards · Cart · Comments │ │ Wells · Alerts · Ribbons · Footer │ │ Watch mode · Landing page · Login │ │ Responsive breakpoints │ │ │ │ References tokens via var(--token-name, fallback) │ └──────────────────────┬──────────────────────────────────┘ │ rendered in ▼ ┌─────────────────────────────────────────────────────────┐ │ templates/ │ │ Jinja2 Templates │ │ │ │ base.j2 → theme toggle, nav, footer │ │ styleguide.j2 → live component reference │ │ product.j2, content.j2, shop.j2, etc. │ └─────────────────────────────────────────────────────────┘ ``` ## File Map | File | Lines | Purpose | |------|-------|---------| | `static/css/tokens.css` | 775 | Design tokens, utilities, animations, resets | | `static/css/common.css` | 3879 | Component styles consuming tokens | | `templates/styleguide.j2` | 1083 | Live styleguide at `/styleguide` | | `views/misc.py:23` | — | Styleguide view controller | ## Token Categories ### Colors ``` Brand Surface Text Border ────────── ────────── ────────── ────────── --color-green --surface-base --text-primary --border-default --color-blue --surface-dim --text-body --border-light --color-navy --surface-container --text-secondary --border-focus --color-purple --surface-container- --text-muted --border-error --color-danger high --text-faint --color-gold --surface-inverse --text-disabled --text-inverse ``` ### Typography Scale (Major Third 1.250) ``` Token Size Use ────────── ────── ────────────────────── --text-xs 12px Captions, overlines --text-sm 14px Labels, small body --text-base 16px Body text (root) --text-md 18px Large body --text-lg 20px Titles --text-xl 24px Title large --text-2xl 30px Headline 3 --text-3xl 36px Headline 2 --text-4xl 48px Headline 1 --text-5xl 60px Display ``` ### Spacing Scale (4px base) ``` Token Value ────────── ────── --space-0 0 --space-1 4px --space-2 8px --space-3 12px --space-4 16px --space-5 20px --space-6 24px --space-8 32px --space-10 40px --space-12 48px --space-16 64px --space-20 80px --space-24 96px ``` ### Shape (Border Radius) ``` --radius-none 0 Sharp corners --radius-sm 4px Inputs, code blocks --radius-md 8px Cards, buttons --radius-lg 12px Modals, panels --radius-xl 16px Large surfaces --radius-2xl 24px Pills --radius-full 9999px Circles ``` ### Elevation (Box Shadow) ``` --elevation-0 none Flat --elevation-1 subtle Cards at rest --elevation-2 low Raised cards --elevation-3 medium Dropdowns --elevation-4 high Modals --elevation-5 highest Popovers ``` ### Motion ``` Durations Easing ────────────────── ────────────────── --duration-instant 50ms --ease-standard general transitions --duration-fast 100ms --ease-decelerate entrances --duration-normal 200ms --ease-accelerate exits --duration-slow 300ms --ease-emphasize emphasis --duration-slower 400ms --ease-spring playful bounce --duration-entrance 250ms --duration-exit 200ms ``` ### Z-Index Scale ``` --z-base 0 Default stacking --z-dropdown 100 Dropdowns, popovers --z-sticky 200 Sticky headers --z-overlay 300 Overlays, backdrops --z-modal 400 Modals --z-toast 500 Toast notifications --z-ribbon 600 Shop ribbon banner ``` ### Layout Breakpoints ``` --content-narrow 400px Login forms, narrow content --content-width 800px Default content width --content-wide 1200px Wide layouts --bp-tablet 800px Tablet breakpoint --bp-desktop 1200px Desktop breakpoint ``` ## Theme System Light mode is default (`:root`). Dark mode activates via `[data-theme="dark"]` on the `` element. The dark theme overrides all semantic tokens — surfaces, text, borders, brand colors — so components adapt automatically without per-component dark mode rules. ``` Light Dark ────────────────────── ────────────────────── --surface-base: #FFFFFF --surface-base: #0d1117 --text-primary: #333333 --text-primary: #ffffff --border-default: #e0e0e0 --border-default: #7ab9ff --color-green: #a3c765 --color-green: #08e700 --color-navy: #5871ad --color-navy: #7ab9ff ``` Theme toggle: `window.setTheme('dark')` / `window.setTheme('light')`. ## Typography Utilities CSS classes that compose token values into complete type styles: | Class | Size | Weight | Use | |-------|------|--------|-----| | `.type-display` | clamp(36px, 5vw, 60px) | bold | Hero headlines | | `.type-headline-1` | 48px | bold | Page titles | | `.type-headline-2` | 36px | bold | Section titles | | `.type-headline-3` | 30px | bold | Subsection titles | | `.type-title-lg` | 24px | semibold | Card titles | | `.type-title` | 20px | semibold | List titles | | `.type-title-sm` | 16px | semibold | Small titles | | `.type-body-lg` | 18px | regular | Lead paragraphs | | `.type-body` | 16px | regular | Body text | | `.type-body-sm` | 14px | regular | Secondary text | | `.type-label-lg` | 14px | semibold | Form labels | | `.type-label` | 12px | semibold, uppercase | Overline labels | | `.type-caption` | 12px | regular | Captions | | `.type-overline` | 11px | bold, uppercase | Section overlines | | `.type-code` | 0.9em | mono | Inline code | ## Component Library All components are documented with live examples at `/styleguide`. The styleguide is the single source of truth for the component library. If it is not in the styleguide, it does not exist as a pattern. ### Styleguide Sections | Section | ID | Description | |---------|-----|------------| | Tokens | `#tokens` | Raw token reference table | | Colors | `#colors` | Brand, surface, text, border, alert swatches | | Typography | `#typography` | Type scale and utility classes | | Elevation | `#elevation` | Shadow levels | | Motion | `#motion` | Animations, transitions, easing | | Spacing | `#spacing` | Spacing scale visualization | | Shape | `#shape` | Border radius samples | | States | `#states` | Interactive state layers | | Loading | `#loading` | Skeleton and spinner patterns | | Buttons | `#buttons` | Button variants (green, blue, red, navy, outline) | | Forms | `#forms` | Input fields, textareas, selects, settings-form (`.settings-form` / `.settings-form-grid` / `.settings-field` / `.settings-field-hint`) | | Wells | `#wells` | Content wells and containers | | Alerts | `#alerts` | Success, info, warning, danger alerts | | Status | `#status` | Status indicators | | Product Cards | `#cards` | Product grid cards, profile card (`.profile-card-header` / `.profile-avatar` / `.profile-handle` / `.profile-email-reveal`), action button grid (`.action-columns` / `.action-button-grid`), MPS-24 tag chips (`#tag-chips`), MPS-24 sectioned lanes (`#tag-lanes`) | | Cart | `#cart` | Cart and checkout components | | Gift Cards | `#gift-cards` | Gift card purchase, balance check, management | | Comments | `#comments` | Comment form and list | | Toggle | `#toggle` | Toggle switches | | Ribbon | `#ribbon` | Shop ribbon banner | | Environment Banner | `.environment-banner` | Staging/dev environment indicator | | Trial Banner | `.trial-banner` | Trial countdown and expiry notice | | Task Bar | `#taskbar` | Task bar component | | Layout | `#layout` | Grid layout patterns | | Theme System | `#theme` | Theme toggle and dark mode | | Footer | `#footer` | Footer component | ### MPS-20 / MPS-21 components | Class | Where | Description | |---|---|---| | `.cart-negotiation-card` | `cart.j2` | Soft-green "Offer accepted / Auction won" well at the top of a negotiated cart | | `.cart-negotiation-deadline` | `cart.j2` | Pay-by countdown line inside the negotiation card | | `.cart-negotiation-pill` | `cart.j2` | "Offer accepted · quantity locked" pill on line items | | `.offer-pay-cta-actions` | `offer.j2` | Two-col grid: Cancel left, Pay right (stacks on narrow viewports) | | `.offer-pay-deadline-note` | `offer.j2` | Buyer's "Payment due in 23 hours, 14 minutes" copy | | `.offer-pay-link-row` | `offer.j2` | Seller's shareable offer-link with Copy button | | `.offer-respond-deadline-note` | `offer.j2` | "Respond in 5 days, or this offer auto-expires" | | `.auction-winner-pay` | `auction.j2` | "You won this auction!" well with countdown + pay CTA | | `.product-add-disabled-note` | `product.j2` | Caption under disabled Add To Cart when active cart is locked | | `.shop-offers-page` | `user_offers.j2` + `user_bids.j2` + `shop_offers.j2` | Wider page (max-width 1100px) overriding `.one-column` for the offers/bids inbox tables | | `.shop-offers-table` | inbox templates | Responsive table; collapses to per-row block list below 720px | | `.notification-badge` | `base.j2` + `/u/settings` | Danger-color pill showing unread notification count | | `.notification-row` + `.notification-row-unread` | `user_notifications.j2` | Notification list rows; read rows fade to 0.65 opacity, unread rows get an alert-info background + navy left border | | `.notification-row-breadcrumbs` | `user_notifications.j2` | Shop › Product › Offer/Auction/Invoice chain under each row | | `.billing-page` / `.billing-paypal-card` / `.billing-actions` | `billing.j2` | `/billing` redesigned with Grid + tokens (no inline styles) | | `[data-pay-deadline]` | offer + auction + cart | Convention attribute the shared `static/js/pay-countdown.js` (and inline tickers in `offer.js` / `auction.js`) rewrite once per second with a prose human delta ("in 23 hours, 14 minutes, 8 seconds") matching the server-rendered `ago.human()` fallback | ### MPS-24 components — tags, chips, lanes | Class | Where | Description | |---|---|---| | `.tag-chip-strip` | `home.j2`, `shop.j2`, `shop_tag.j2` | Horizontally scrolling row of chips at the top of the shop home; `grid-auto-flow: column` + `overflow-x: auto` so chips swipe on mobile | | `.tag-chip` | every chip strip + bulk tagger | Pill-shaped link, tokens-only colors, hover brightens border + bg | | `.tag-chip-active` | current filter chip | Accent-fill chip; click on home filters the grid in place via `static/js/tag_filter.js` | | `.tag-lane` | `home.j2`, `shop.j2` (layout 2) | One `
` per top tag; capped product count via `shop.home_layout_per_lane_limit` | | `.tag-lane-header` | inside `.tag-lane` | Grid 1fr / auto — lane title left, "See all →" right | | `.tag-lane-grid` | inside `.tag-lane` | Reuses `.serp` grid pattern; horizontal lane is the *outer* layout, items inside still use product grid | | `.tag-list` / `.tag-list-item` | `shop_tags.j2` (bulk tagger) | Operator tag overview: tag pill + product count + view / delete row | | `.tag-product-list` / `.tag-product-row` | `shop_tags.j2` (bulk tagger) | "Apply / Applied" toggle per product per tag | | `.tag-detail-header` | `shop_tag.j2` | Tag detail page header (tag name + back link) | | `[data-tag-strip]` | chip strip | JS hook for `tag_filter.js` | | `[data-tag-grid]` | flat `.serp` | JS hook — items inside carry `data-tag-slugs` for in-place filter | | `[data-tag-slugs]` | `.serp-item` | Space-separated tag slugs the item carries; consumed by `tag_filter.js` | | `.tag-suggest-list` / `.tag-suggest-item` | `shop_tags.j2` (Phase 2) | Suggested-cluster well rendered when operator clicks "Suggest categories from titles + descriptions"; per-cluster grid with label, sample titles, Apply / Dismiss actions | | `.tag-suggest-actions` | `shop_tags.j2` | Apply / Dismiss button row, `grid-auto-flow: column` | | `.product-tag-chips` / `.tag-chip-list` | `product_edit.j2` (Phase 2.7) | Per-product SPA tag editor container; `js-only`, revealed by `product_tags.js`. Chips wrap as inline-level pills (the `