18 KiB
| name | description | colors | typography | rounded | spacing | components | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Teqo | Field ops and public voice for Jorge Solla — campaign desk first, owned channel second. |
|
|
|
|
|
Design System: Teqo
1. Overview
Creative North Star: "The Field Desk"
Teqo’s visual system is a sober ops surface for people organizing under pressure. Design defaults to /campanha: stone-white surfaces, Inter, and brand red as a signal (primary actions, selection, status urgency) — never as spectacle or brochure chrome. Staff screens can be information-dense; leadership paths stay phone-first with larger touch targets and obvious next actions.
Public themes (editorial, petition, and the home brand-red body) share the same token contract and primary red, but they are surface variants. When inventing new UI, start from the campaign desk unless the task is explicitly a public/marketing page.
The system rejects generic SaaS dashboards (purple gradients, hero-metric templates, identical card grids, AI-startup chrome) and traditional Brazilian campaign kitsch (clipart flags, shouty all-caps, brochure clutter). Sovereignty and clarity beat decoration.
Key Characteristics:
- Product register: familiar shadcn affordances, earned consistency over surprise
- Restrained color strategy: neutrals dominate; primary red ≤ ~10% of any screen
- Hybrid elevation: flat lists/forms; light lift only for priority or overlay surfaces
- Confident and compact controls — denser desktop, phone-first leadership paths
- Semantic status colors (support / estimate / cadence) carry meaning, not fashion
2. Colors
A stone-neutral desk with one mobilizing red. Semantic pastels mark operational state; they never replace the primary action color.
Primary
- Mandate Red (
#c51414): Primary buttons, focus rings, active nav, brand emphasis on/campanhaand editorial/petition themes. Use for the one clear next action. - Header Crimson (
#ae1603): Public site header bar (--site-header) and home body gradient anchor — inherited across themes so the masthead stays constant.
Secondary
- Stone Wash (
#f5f5f4/#f4f4f5): Secondary buttons, muted fills, hover washes. Quiet structure, not a second brand.
Tertiary
- Petition Gold (
#ffcf2e): Petition-theme CTA only (data-theme='petition'). Forbidden as a general accent on campaign screens.
Neutral
- Desk White (
#ffffff): Page and card background on campaign. - Ink Stone (
#1c1917): Body text and strong labels. - Quiet Ink (
#6b7280): Muted labels, secondary metadata — keep contrast ≥ 4.5:1 on white. - Hairline Stone (
#e7e5e4/rgb(28 25 23 / 12%)): Borders and dividers. - Field Border (
#d6d3d1): Visible input stroke on white cards. - Rail Mist (
#fafaf9): Campaign sidebar rail.
Semantic (campaign ops)
- Scope / territory chips: warm peach (
#fff5ed/#6b2d15) - Support & estimates: green engaged/confirmed, amber disputed/pending, red negative/overdue — use only via Badge variants, never invent parallel hues
Named Rules
The Signal Red Rule. Mandate Red is for primary action, focus, and urgency. It must not wash backgrounds, decorate cards, or paint inactive chrome.
The Theme Contract Rule. New surfaces reuse the shadcn token names (primary, muted, field-*, etc.). Do not introduce one-off hex outside a data-theme block.
3. Typography
Display Font: Inter (with ui-sans-serif, system-ui, sans-serif)
Body Font: Inter (same stack)
Label/Mono Font: Inter for UI labels; mono only for code snippets
Character: One tuned sans for the whole product desk — no display serif in app chrome. Public article heroes may use larger extrabold Inter; campaign headings stay left-aligned section titles.
Hierarchy
- Headline (600,
1.5rem/text-2xl, tight tracking): Page and section titles on/campanha. - Title (500,
1rem/text-base): Card titles, dialog titles. - Body (400,
0.875rem/text-sm, leading ~1.5): Default UI copy; prose max ~65–75ch when reading length matters. - Label (500,
0.75rem/text-xs): Badges, meta, table headers. Never all-caps tracked eyebrows as section scaffolding.
Named Rules
The One Family Rule. Inter everywhere in product UI. No decorative display faces in buttons, labels, or data.
The Fixed Scale Rule. Prefer rem/Tailwind steps over fluid clamp() headings inside the campaign shell.
4. Elevation
Hybrid: most of the desk is flat. Depth comes from tonal layers (sidebar rail, muted fills, hairline rings) and from overlays when the user must focus.
Lists, forms, filters, and table rows stay flat. Cards may use a light ring (ring-1 ring-foreground/10) without drop shadow. Soft ambient lift is reserved for priority overview panels and for floating UI (dialogs, sheets, drawers, popovers).
Shadow Vocabulary
- Flat desk (no shadow): Default for rows, forms, filters, most cards.
- Priority lift (soft ambient, low opacity): Overview / insight panels that must read as “above” the list — keep blur soft and shadow light; if it looks like a 2014 app, the shadow is too dark.
- Overlay (modal/sheet/popover system shadow): Only for temporary focus layers.
Named Rules
The Flat-By-Default Rule. Surfaces are flat at rest. Lift appears for priority or overlay — never as default card decoration across a grid.
5. Components
Controls feel confident and compact: short primary buttons, dense toolbars, phone-first tap targets where leaderships work.
Buttons
- Shape: Gently rounded (
rounded-lg≈ 8px; smaller sizes clamp toward--radius-md) - Primary: Mandate Red fill, white text, height 32px default; primary submit may use
font-bold - Hover / Focus: Primary hover at ~80% opacity; focus-visible ring
ring-3 ring-ring/50with border-ring - Secondary / Outline / Ghost / Destructive: Standard shadcn variants; destructive is tinted text/fill, not a second brand red for routine actions
- Active: Slight
translate-y-pxpress
Chips / Badges
- Style: Pill (
rounded-4xl), height 20px,text-xsmedium - State: Semantic variants (
support-*,estimate-*,scope,tse) — status meaning only; do not invent decorative chip colors
Cards / Containers
- Corner Style:
rounded-xl(~12px) - Background: Card white on desk white — separation via hairline ring, not heavy shadow
- Shadow Strategy: Flat by default; priority lift only when the panel is an overview/insight surface
- Internal Padding:
--card-spacingdefault 16px (spacing(4)), sm 12px
Inputs / Fields
- Style: Campaign forces
--radius-md(~6px) on input/select triggers (overrides publicrounded-fullinput). Visible--field-borderon white. - Focus: Border primary +
ring-3 ring-primary/30 - Error / Disabled: Destructive border/ring; disabled uses field-disabled tokens at reduced opacity
- Touch: Keep leadership-facing controls generous; public Input uses larger py for form comfort
Navigation
- Campaign shell: Light stone sidebar rail on desktop; mobile top bar in Mandate Red with white wordmark — intentional field-mode contrast (phone in the street vs desk rail), not Signal Red Rule drift.
- Active: Primary-tinted or bold text — red signals location, not decoration
- Public header: Header Crimson bar, constant across themes
Status Badge (signature)
Operational meaning for leadership/support/estimates. Always use Badge variants tied to CSS tokens — never hardcode greens/ambers that drift from --support-* / --estimate-*.
Territorial class (E10) is a four-step ladder scanned down a 25-row column, so its variants must stay mutually legible: reduto estimate-confirmed (green, achieved), expansão estimate-pending (amber, asks for work), manutenção secondary (grey, routine), marginal outline (hairline). sem_base gets no badge — absent data is the em dash the neighboring columns already use. The map lives in territorialClassBadgeVariant; the class never renders without its "por quê" line.
The same ladder has a second, unavoidable encoding: B13 colors the map's proportional bubbles by territorial class, and Leaflet paints SVG with literal hex, not CSS variables. territorialClassMapFill (municipalityLabels.ts) is therefore the one place allowed to restate this palette as hex, and it must be re-derived by hand whenever --support-* / --estimate-* move — the two ladders are the same semantic scale and drifting them apart breaks the list↔map read. sem_base there is the shared NO_DATA_FILL (choroplethColorScale.ts), the same grey the choropleth uses for missing data.
Campaign list system (Pass 2 W1 — canonical, do not fork)
Every /campanha list surface composes the shared pieces in src/components/campaign/shared/: CampaignTable (columns as data over house ui/Table; rounded-xl border container), CampaignSearchForm / CampaignFilterChips as the toolbar, CampaignListFooter (count + pagination), CampaignListEmptyState (Empty with icon + CTA, min-h-72 border), all inside CampaignListPendingBoundary so navigation dims the RESULTS region ("Feel the action"). Rich headers (sort + filter popovers) are the municipality islands (MunicipalitySortableHead/MunicipalityHeaderFilter) — the reference implementation, not yet generalized. Cell-level explanation IS generalized (B23 seam, first consumer E10's "Classe"): a column declares cellTooltip: (row) => ReactNode and CampaignTable wraps that cell in CampaignCellTooltip; returning null for a row leaves it untouched. The contract is that the tooltip is REDUNDANT — the same content must already be text in the cell (visible, or sr-only behind a badge), because Radix mounts tooltip content only on open and the table adds no tab stops. The hover primitive is shared/CampaignHoverTooltip (hover + keyboard focus + touch tap). New list = new column definitions + these shells; a bespoke table needs a documented exception (precedents: planos cards, TerritoryOverviewTable).
6. Do's and Don'ts
Do:
- Do treat
/campanhaas the design default: stone desk, Inter, Signal Red for the next action. - Do keep primary red rare — one clear CTA per region beats a sea of red buttons.
- Do use semantic Badge tokens for support/estimate/cadence state.
- Do keep leadership paths phone-first: obvious actions, larger taps, plain language.
- Do meet WCAG 2.2 AA (contrast, keyboard, focus rings,
prefers-reduced-motion). - Do reuse shadcn primitives (
Button,Input,Badge,Card, dialogs/sheets) for consistency.
Don't:
- Don't ship generic SaaS dashboards — purple gradients, hero-metric templates, identical card grids, AI-startup chrome.
- Don't ship traditional Brazilian campaign kitsch — clipart flags, shouty all-caps, brochure clutter.
- Don't use side-stripe borders (
border-left/border-right> 1px) as accent decoration. - Don't use gradient text or glassmorphism as default chrome.
- Don't put tiny uppercase tracked eyebrows above every section.
- Don't use Petition Gold or home body gradients inside the campaign desk.
- Don't invent display fonts for UI labels, buttons, or data.
- Don't lift every card; flat is the desk’s resting state.
7. Evolution
This file is the living owner of Teqo's visual decisions — a working document, not a snapshot. The old single-source-of-brand guardrail (kit 1313 as the only authority; "never re-derive lockups or palette") is retired. The official kit assets in public/campaign-kit/ stay available — and their technical usage quirks still apply when used — but they no longer bind new design work.
Public campaign archive actions (C233, 2026-09-26). On campaign-branded public archive/read surfaces, the primary action is campaign red with white text. Kit yellow is an orientation and keyboard-focus signal — hero edge, restrained eyebrow, current-location underline, and high-contrast focus outline — never the competing CTA fill. This keeps one action dominant, separates public campaign expression from Petition Gold, and makes keyboard location unmistakable over both light and dark media surfaces.
Public campaign home as editorial evidence (S1, 2026-09-28). The campaign home uses a mobilization→evidence rhythm: brand-red opening and final participation frame the page; cream/white reading chapters carry principles, dated work and trajectory. Principles are long-form chapters paired with documentary photography (sticky on desktop, inline on mobile/reduced motion), never an equal-card grid. Developed public-work cases use a source-visible two-era record that separates institutional sphere, date and delivery phase. Yellow remains an orientation/focus/source signal, not a competing CTA; on a red field the primary CTA may be white with dark-red ink, while light fields use the canonical red/white action. This pattern replaces the old repeated-card campaign page because it gives authentic photography room, makes attribution auditable and preserves one dominant action in every color context.
Embedded support-kit builder (S5, 2026-09-28). Personalization on the public campaign home is one continuous, progressively disclosed section inside #cards, not a numbered wizard or a separate funnel. Name begins the live preview; optional photo and dobradinha appear as inline invitations; a kit tray accumulates only valid pieces and never covers content or focus. Desktop pairs a sticky live preview with the scrolling controls; mobile keeps previews and the tray inline. The full /cards studio remains the owner of the six models and deep links. This keeps the action inside the home’s editorial rhythm, reduces modal/context switching, and makes optional inputs feel additive instead of required.
How rules change:
- Decide, then update the owner. When a better pattern wins — anti-slop review (
design-taste-frontend/gpt-taste), a reference study (awesome-design-md), a redesign pass (redesign-existing-projects), or implementation judgment — update this file in the same change and say why. A pattern that only lives in code or in an agent's head is drift, not design. - Scope by surface. Sections 1–6 describe the
/campanhaoperate desk first; public/persuade surfaces (site, petition, campaign page) may pick a different visual world, but they inherit the token contract and the access/consent constraints. - Tokens move through code. Change
colors,typography,rounded,componentsvia the existing shadcn /data-themeplumbing; this file records intent, the CSS stays the executable truth. Keep both in sync in the same change. - Material changes keep the human gate. A material visual change (visible identity, hierarchy, brand direction) still goes through the plan-issue/work-issue hi-fi gate: propose, show, merge. Token-neutral refinements follow the normal PR review.
- Keep it current. Stale rules here mislead every agent that reads this file — delete what no longer holds instead of accumulating contradictions.