# UI Design System

ArchiTools internal design system reference. All UI decisions flow from this document.

---

## Design Philosophy

ArchiTools serves architecture and engineering professionals at Beletage SRL, Urban Switch SRL, and Studii de Teren SRL. The interface must reflect the discipline of the work itself: precise, structured, technically grounded.

**Guiding principles:**

- **Professional over playful.** No rounded bubbly elements, no bright consumer gradients, no emoji-heavy interfaces. The aesthetic is closer to a CAD toolbar than a social media dashboard.
- **Information-dense but not cluttered.** Architecture professionals need data visible at a glance. Favor card-based layouts with clear hierarchy over sparse minimalist voids.
- **Technical confidence.** Use monospaced fonts for data fields, structured grids for layout, and precise spacing. The UI should feel like a well-organized technical drawing.
- **Consistent across tools.** Every module (email signatures, XML generators, future tools) must feel like part of the same platform, not a collection of standalone pages.
- **Dark and light with equal quality.** Both themes are first-class. The dark theme is the default (matching existing tool aesthetics). The light theme must be equally polished.

---

## Color System

### Brand Colors

| Token | Hex | Usage |
|---|---|---|
| `brand-teal` | `#22B5AB` | Primary accent. Beletage brand teal. Used for active states, primary buttons, links, focus rings. |
| `brand-teal-light` | `#2DD4BF` | Hover state for teal elements. |
| `brand-teal-dark` | `#14978F` | Pressed/active state. |

Each company in the group may define an override accent color. The teal serves as the platform default and Beletage-specific accent.

| Company | Accent | Usage Context |
|---|---|---|
| Beletage SRL | `#22B5AB` (teal) | Architecture projects |
| Urban Switch SRL | TBD | Urban planning projects |
| Studii de Teren SRL | TBD | Land survey projects |

The company selector in the header drives the active accent color via a CSS custom property (`--accent`).

### Slate Backgrounds

Derived from Tailwind's `slate` scale. These form the structural palette for both themes.

**Dark theme (default):**

| Token | Tailwind Class | Hex | Usage |
|---|---|---|---|
| `bg-app` | `bg-slate-950` | `#020617` | Application background |
| `bg-card` | `bg-slate-900` | `#0f172a` | Card surfaces |
| `bg-card-elevated` | `bg-slate-800` | `#1e293b` | Elevated cards, dropdowns, popovers |
| `bg-input` | `bg-slate-950` | `#020617` | Input field backgrounds |
| `border-default` | `border-slate-700` | `#334155` | Card borders, dividers |
| `border-subtle` | `border-slate-800` | `#1e293b` | Subtle separators |
| `text-primary` | `text-slate-100` | `#f1f5f9` | Primary text |
| `text-secondary` | `text-slate-400` | `#94a3b8` | Secondary text, labels |
| `text-muted` | `text-slate-500` | `#64748b` | Disabled text, placeholders |

**Light theme:**

| Token | Tailwind Class | Hex | Usage |
|---|---|---|---|
| `bg-app` | `bg-slate-50` | `#f8fafc` | Application background |
| `bg-card` | `bg-white` | `#ffffff` | Card surfaces |
| `bg-card-elevated` | `bg-slate-50` | `#f8fafc` | Elevated cards |
| `bg-input` | `bg-white` | `#ffffff` | Input field backgrounds |
| `border-default` | `border-slate-200` | `#e2e8f0` | Card borders, dividers |
| `border-subtle` | `border-slate-100` | `#f1f5f9` | Subtle separators |
| `text-primary` | `text-slate-900` | `#0f172a` | Primary text |
| `text-secondary` | `text-slate-600` | `#475569` | Secondary text, labels |
| `text-muted` | `text-slate-400` | `#94a3b8` | Disabled text, placeholders |

### Semantic Colors

| Semantic | Light | Dark | Usage |
|---|---|---|---|
| `success` | `#16a34a` (green-600) | `#22c55e` (green-500) | Confirmations, valid states |
| `warning` | `#d97706` (amber-600) | `#f59e0b` (amber-500) | Caution states, non-blocking issues |
| `error` | `#dc2626` (red-600) | `#ef4444` (red-500) | Errors, destructive actions |
| `info` | `#2563eb` (blue-600) | `#3b82f6` (blue-500) | Informational highlights |

Each semantic color has a background variant at 10% opacity for alert/badge backgrounds:
- `bg-success`: `success / 10%` over card background
- Same pattern for `warning`, `error`, `info`

### Theme Implementation

Theme is managed by `next-themes` with the `attribute="class"` strategy. Tailwind's `darkMode: "class"` is enabled. All theme-dependent styles use the `dark:` prefix.

```tsx
// layout.tsx
import { ThemeProvider } from 'next-themes';

<ThemeProvider attribute="class" defaultTheme="dark" enableSystem>
  {children}
</ThemeProvider>
```

CSS custom properties for the accent color are set on `<html>` based on the active company selection:

```css
:root {
  --accent: 34 181 171;          /* #22B5AB in RGB */
  --accent-foreground: 255 255 255;
}
```

Components reference accent via `bg-[rgb(var(--accent))]` or through shadcn/ui's HSL-based theming variables in `globals.css`.

---

## Typography

### Font Stack

Primary: `Inter` (loaded via `next/font/google`), falling back to `system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif`.

Monospace (for code, XML output, data fields): `"JetBrains Mono", "Fira Code", ui-monospace, monospace`.

### Size Scale

All sizes reference Tailwind's default scale. Do not use arbitrary pixel values.

| Token | Tailwind | Size | Usage |
|---|---|---|---|
| `text-xs` | `text-xs` | 0.75rem / 12px | Badges, fine print, metadata |
| `text-sm` | `text-sm` | 0.875rem / 14px | Labels, secondary text, table cells |
| `text-base` | `text-base` | 1rem / 16px | Body text, input values |
| `text-lg` | `text-lg` | 1.125rem / 18px | Card titles, section headers |
| `text-xl` | `text-xl` | 1.25rem / 20px | Page section titles |
| `text-2xl` | `text-2xl` | 1.5rem / 24px | Page titles |
| `text-3xl` | `text-3xl` | 1.875rem / 30px | Dashboard hero stats only |

### Font Weight

| Weight | Tailwind | Usage |
|---|---|---|
| 400 | `font-normal` | Body text |
| 500 | `font-medium` | Labels, table headers, navigation items |
| 600 | `font-semibold` | Card titles, section headers |
| 700 | `font-bold` | Page titles, stat values |

### Line Height

Use Tailwind defaults. Override only for tight stat displays (`leading-tight` / `leading-none` on large numeric values).

---

## Component Library

### Base: shadcn/ui

All interactive components are built on [shadcn/ui](https://ui.shadcn.com/). Components are installed into `src/shared/components/ui/` via the shadcn CLI and customized in place.

**Customization approach:**

1. Install the shadcn/ui component (`npx shadcn@latest add button`).
2. The component lands in `src/shared/components/ui/button.tsx`.
3. Modify theme tokens in `globals.css` to match our color system.
4. Extend component variants if needed (e.g., adding a `brand` variant to `Button`).
5. Never wrap shadcn components in another abstraction layer unless adding substantial logic. Use them directly.

**Key shadcn/ui components in use:**

- `Button` -- primary actions, secondary actions, destructive actions, ghost navigation
- `Input`, `Textarea`, `Select` -- form controls
- `Card`, `CardHeader`, `CardContent`, `CardFooter` -- content containers
- `Dialog`, `AlertDialog` -- modal interactions (replaces `alert()`/`confirm()`)
- `DropdownMenu` -- context menus, overflow actions
- `Tabs` -- in-page mode switching (e.g., simple/advanced toggle)
- `Table` -- data display
- `Badge` -- status indicators, category labels
- `Tooltip` -- icon-only button labels
- `Separator` -- visual dividers
- `Switch`, `Checkbox` -- boolean toggles
- `Breadcrumb` -- navigation breadcrumbs in header
- `Sidebar` -- app shell navigation (shadcn sidebar component)
- `Sheet` -- mobile navigation drawer

---

## Layout System

### App Shell

The application uses a fixed sidebar + header + scrollable content area layout.

```
+--------------------------------------------------+
| [Sidebar]  |  [Header: breadcrumbs | theme | co] |
|            |--------------------------------------|
|  Nav       |                                      |
|  items     |  [Content area]                      |
|            |                                      |
|  grouped   |  max-w-6xl mx-auto px-6 py-6         |
|  by        |                                      |
|  category  |                                      |
|            |                                      |
+--------------------------------------------------+
```

### Sidebar

- Width: `16rem` (256px) expanded, `3rem` (48px) collapsed (icon-only mode).
- Collapsible via a toggle button at the bottom of the sidebar.
- Collapse state persisted to localStorage via a cookie (for SSR compatibility with `next-themes`).
- Background: `bg-slate-900` (dark) / `bg-white` (light) with a right border.
- Navigation items are grouped by category. Groups are driven by the module registry (`src/config/modules.ts`).

**Navigation structure:**

```
INSTRUMENTE (Tools)
  - Semnatura Email
  - Generator XML Word

ADMINISTRARE (Admin)
  - Etichete Proiecte (Project Tags)
  - Configurare (Settings)

(future groups added via module registry)
```

Each nav item displays:
- A Lucide icon (24x24)
- The module label (from `labels.ts`)
- An optional badge (e.g., count of saved configs)

Active state: teal left border + teal-tinted background (`bg-teal-500/10`).

### Header

Fixed at the top of the content area. Contains:

1. **Breadcrumbs** (left): Module group > Module name > Sub-page. Uses shadcn `Breadcrumb`.
2. **Company selector** (center-right): Dropdown to switch active company context. Drives branding colors and available configurations.
3. **Theme toggle** (right): Sun/Moon icon button. Toggles between dark/light via `next-themes`.
4. **User area** (far right, future): Avatar + dropdown for auth when implemented.

Height: `h-14` (56px). Bottom border separator.

### Content Area

- Container: `max-w-6xl mx-auto px-4 sm:px-6 py-6`
- For full-width tools (e.g., XML generator with preview): use `max-w-7xl` or remove max-width constraint.
- Content scrolls independently of sidebar and header.

---

## Card Patterns

### Primary Content Card

The standard content container. Used for forms, configuration panels, output displays.

```tsx
<Card>
  <CardHeader>
    <CardTitle>Configurare Semnatura</CardTitle>
    <CardDescription>Completati datele pentru generarea semnaturii.</CardDescription>
  </CardHeader>
  <CardContent>
    {/* form fields, content */}
  </CardContent>
  <CardFooter>
    {/* action buttons */}
  </CardFooter>
</Card>
```

Styling: `rounded-xl border` with theme-appropriate background. No drop shadows in light mode (border is sufficient). Subtle shadow in dark mode (`shadow-lg shadow-black/20`).

### Stat Card

For dashboard counters and KPIs.

```tsx
<Card className="p-6">
  <div className="flex items-center justify-between">
    <div>
      <p className="text-sm text-muted-foreground">{label}</p>
      <p className="text-3xl font-bold leading-none mt-1">{value}</p>
    </div>
    <div className="rounded-lg bg-teal-500/10 p-3">
      <Icon className="h-6 w-6 text-teal-500" />
    </div>
  </div>
</Card>
```

### Widget Card

For dashboard widgets (quick actions, recent items, external links).

Same structure as primary content card but with a fixed height and internal scroll if content overflows. Header includes an optional "View all" link.

---

## Form Patterns

### Input Groups

Each form field follows this structure:

```tsx
<div className="space-y-2">
  <Label htmlFor="field-id">{labels.fieldName}</Label>
  <Input id="field-id" {...props} />
  <p className="text-xs text-muted-foreground">{labels.fieldHint}</p>
</div>
```

- Labels come from the label constants file (never hardcoded Romanian strings in JSX).
- Hints are optional `text-xs text-muted-foreground` paragraphs below the input.
- Required fields: no asterisk; instead, validation messages appear on submit.

### Form Layout

- Single column for simple forms.
- Two-column grid (`grid grid-cols-1 md:grid-cols-2 gap-4`) for forms with many short fields.
- Full-width fields (textareas, complex inputs) span both columns via `md:col-span-2`.

### Validation Display

Validation errors appear below the field as `text-xs text-destructive`:

```tsx
{error && <p className="text-xs text-destructive">{error}</p>}
```

Input border turns red on error: `border-destructive`.

### Romanian Labels

All user-facing text is sourced from `src/core/i18n/labels.ts`. Components reference label keys:

```tsx
import { labels } from '@/core/i18n/labels';

<Label>{labels.signature.fieldName}</Label>
```

Never write Romanian text directly in JSX. This ensures consistency, makes future i18n possible, and centralizes all copy for review.

### Label File Structure

```ts
// src/core/i18n/labels.ts

export const labels = {
  common: {
    save: 'Salveaza',
    cancel: 'Anuleaza',
    delete: 'Sterge',
    download: 'Descarca',
    copy: 'Copiaza',
    generate: 'Genereaza',
    reset: 'Reseteaza',
    loading: 'Se incarca...',
    noData: 'Nu exista date.',
    confirm: 'Confirmare',
    search: 'Cauta',
  },
  nav: {
    tools: 'Instrumente',
    admin: 'Administrare',
    emailSignature: 'Semnatura Email',
    xmlGenerator: 'Generator XML Word',
    tagManager: 'Etichete Proiecte',
    settings: 'Configurare',
  },
  signature: {
    title: 'Configurator Semnatura Email',
    fieldPrefix: 'Titulatura (prefix)',
    fieldName: 'Nume si Prenume',
    fieldRole: 'Functia',
    fieldPhone: 'Telefon (format 07xxxxxxxx)',
    sectionColors: 'Culori Text',
    sectionLayout: 'Stil & Aranjare',
    sectionOptions: 'Optiuni',
    optionReply: 'Varianta simpla (fara logo/adresa)',
    optionSuperReply: 'Super-simpla (doar nume/telefon)',
    optionSvg: 'Foloseste imagini SVG (calitate maxima)',
    exportHtml: 'Descarca HTML',
    preview: 'Previzualizare Live',
  },
  xml: {
    title: 'Generator XML pentru Word',
    fieldNamespace: 'Namespace URI',
    fieldRootElement: 'Element radacina',
    fieldList: 'Lista de campuri (unul pe linie)',
    modeSimple: 'Simplu',
    modeAdvanced: 'Avansat',
    categoryLabel: 'Categorii de date',
    addCategory: 'Adauga categorie',
    resetPreset: 'Reset categorie la preset',
    clearFields: 'Curata campurile',
    generateAll: 'Genereaza XML pentru toate categoriile',
    downloadCurrent: 'Descarca XML categorie curenta',
    downloadZip: 'Descarca ZIP cu toate XML-urile',
    previewXml: 'XML categorie curenta',
    previewXpath: 'XPaths categorie curenta',
  },
  // Additional module labels added here as modules are built.
} as const;

export type LabelKey = typeof labels;
```

---

## Table Patterns

Data tables use shadcn/ui `Table` components with the following conventions:

- **Header**: `font-medium text-sm text-muted-foreground`, no background color differentiation.
- **Rows**: alternating subtle background on hover (`hover:bg-muted/50`).
- **Sortable columns**: click header to toggle. Arrow indicator next to sorted column.
- **Filtering**: text input above the table, filters by visible columns.
- **Pagination**: below the table. "X of Y results" + page controls.
- **Empty state**: centered message inside the table area using `labels.common.noData`.

For complex data tables, use `@tanstack/react-table` as the headless engine with shadcn/ui table components for rendering.

---

## Dashboard Widgets

The dashboard home page (`/`) uses a responsive grid of widget cards.

### Layout

```tsx
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-4">
  {/* stat cards row */}
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4 mt-4">
  {/* widget cards */}
</div>
```

### Widget Types

1. **Stat counters**: Number of saved signature configs, XML templates, etc. Uses Stat Card pattern.
2. **Recent items**: Last 5 saved/exported items across tools. List format inside a widget card.
3. **Quick actions**: Buttons to jump to common tasks ("New signature", "New XML template"). Grid of icon+label buttons.
4. **External tool links**: If legacy HTML tools are still accessible, link out to them with an "external" icon.

Widgets are defined in a registry and rendered dynamically. Each widget is a self-contained component that fetches its own data.

---

## Icon System

All icons use [Lucide React](https://lucide.dev/) (`lucide-react` package).

**Usage:**

```tsx
import { Mail, FileCode, Settings, ChevronRight } from 'lucide-react';

<Mail className="h-5 w-5" />
```

**Conventions:**

- Navigation icons: `h-5 w-5`
- Inline icons (next to text): `h-4 w-4`
- Stat card icons: `h-6 w-6`
- Button icons: `h-4 w-4 mr-2` (left of label) or `h-4 w-4 ml-2` (right of label)
- Icon-only buttons must have a `Tooltip` or `aria-label`.

**Do not** use SVG icons inline. Do not use icon fonts. Do not mix icon libraries.

---

## Spacing and Grid Conventions

All spacing uses Tailwind's default 4px-based scale.

| Context | Spacing | Tailwind |
|---|---|---|
| Between form fields | 8px | `space-y-2` |
| Between card sections | 16px | `space-y-4` |
| Card internal padding | 24px | `p-6` |
| Grid gap (cards) | 16px | `gap-4` |
| Page padding (desktop) | 24px | `px-6 py-6` |
| Page padding (mobile) | 16px | `px-4 py-4` |

Grid uses Tailwind's `grid` utility with responsive column counts:

- `grid-cols-1` (mobile)
- `md:grid-cols-2` (tablet)
- `lg:grid-cols-3` (desktop)
- `xl:grid-cols-4` (wide desktop, stat cards only)

---

## Responsive Breakpoints

Using Tailwind's default breakpoints:

| Breakpoint | Min-width | Typical device |
|---|---|---|
| `sm` | 640px | Large phone, small tablet |
| `md` | 768px | Tablet portrait |
| `lg` | 1024px | Tablet landscape, small desktop |
| `xl` | 1280px | Desktop |
| `2xl` | 1536px | Wide desktop |

**Behavior:**

- Below `lg`: sidebar collapses to a mobile drawer (shadcn `Sheet`).
- Below `md`: single-column content layout.
- At `lg` and above: sidebar visible, two-column form layouts.
- At `xl` and above: four-column stat card grid.

---

## Animation Guidelines

Animations are minimal and purposeful. This is a professional tool, not a marketing site.

**Allowed animations:**

- **Transitions on interactive elements**: `transition-colors duration-150` on buttons, links, nav items.
- **Sidebar collapse/expand**: `transition-[width] duration-200 ease-in-out`.
- **Card hover elevation** (optional): `transition-shadow duration-150`.
- **Dialog/sheet enter/exit**: Use shadcn/ui defaults (Radix UI built-in animations).
- **Skeleton loading**: `animate-pulse` on placeholder blocks during data loading.

**Not allowed:**

- Page transition animations.
- Bouncing, jiggling, or attention-seeking element animations.
- Parallax or scroll-linked effects.
- Auto-playing animations that loop indefinitely (except loading spinners).
- Transform-based hover effects on buttons (`hover:scale-105` and similar -- this was used in the legacy HTML tools but is too playful for the dashboard).

---

## Accessibility Baseline

- All interactive elements must be keyboard navigable.
- Focus rings: `focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2`.
- Color contrast: minimum 4.5:1 for text, 3:1 for large text and UI elements (WCAG AA).
- Images and icons: `alt` text on informational images, `aria-hidden="true"` on decorative icons, `aria-label` on icon-only buttons.
- Form fields: every `<Input>` has an associated `<Label>` via `htmlFor`/`id`.
- Dialogs: use shadcn/ui `Dialog` which handles focus trapping and `aria-*` attributes.
- No information conveyed by color alone (always pair with text or icon).
- Reduced motion: respect `prefers-reduced-motion` by wrapping non-essential animations in `motion-safe:`.

---

## Summary: Design Tokens Quick Reference

```css
/* globals.css -- theme tokens (simplified) */

:root {
  --background: 0 0% 100%;
  --foreground: 222.2 84% 4.9%;
  --card: 0 0% 100%;
  --card-foreground: 222.2 84% 4.9%;
  --primary: 174 68% 41%;           /* #22B5AB */
  --primary-foreground: 0 0% 100%;
  --muted: 210 40% 96%;
  --muted-foreground: 215.4 16.3% 46.9%;
  --border: 214.3 31.8% 91.4%;
  --ring: 174 68% 41%;
  --radius: 0.75rem;
}

.dark {
  --background: 222.2 84% 2%;       /* #020617 */
  --foreground: 210 40% 93%;
  --card: 222.2 84% 5%;             /* #0f172a */
  --card-foreground: 210 40% 93%;
  --primary: 174 68% 41%;
  --primary-foreground: 0 0% 100%;
  --muted: 217.2 32.6% 17.5%;
  --muted-foreground: 215 20.2% 65.1%;
  --border: 217.2 32.6% 17.5%;
  --ring: 174 68% 41%;
}
```
