Files
odoo-addons/addons/at_master_order/VERA_DESIGN_SYSTEM.md

29 KiB

Vera Design System Guidelines

Master Order Dashboard Design Reference

Version: 1.0
Last Updated: January 2026
Reference Implementation: Bill Tracking Dashboard

This document captures all design patterns, colors, typography, and component styles used in the Bill Tracking Dashboard. Use this as a reference when building new dashboards to maintain consistency.


Table of Contents

  1. Theme System
  2. Color Palette
  3. Typography
  4. Spacing System
  5. Border & Shadows
  6. Odoo Navigation Bar
  7. Dashboard Header Bar
  8. Component Library
  9. Layout Patterns
  10. Responsive Design
  11. Icons
  12. Interactive States
  13. Code Snippets

1. Theme System

1.1 CSS Variables

All theme colors are defined as CSS variables in master_order_theme_variables.scss:

:root {
    // Primary Colors (change per theme)
    --mo-theme-primary: #4682B4;
    --mo-theme-primary-dark: #3A6D99;
    --mo-theme-primary-light: #5B9BD5;
    --mo-theme-primary-pale: #E8F4FC;
    
    // Background Colors
    --mo-theme-background: #F9FAFB;
    --mo-theme-card-bg: #FFFFFF;
    --mo-theme-border: #D9D9D9;
    
    // Text Colors
    --mo-theme-text: #1d1d1f;
    --mo-theme-text-muted: #86868b;
}

1.2 Available Themes

Theme Name Primary Background Use Case
Vera Blue Eye #4682B4 #F9FAFB Default, eye-friendly
Vera Excel #23764A #FFFFFF Excel-like, pure white
Ocean Teal #017e84 #F8F9FA Odoo Enterprise style

1.3 Theme Switcher Component

<!-- Theme Switcher Dots -->
<div class="btd-theme-switcher">
    <button class="btd-theme-dot btd-theme-blue-eye" 
            title="Vera Blue Eye"
            t-on-click="() => this.setTheme('vera_blue_eye')"/>
    <button class="btd-theme-dot btd-theme-excel" 
            title="Vera Excel"
            t-on-click="() => this.setTheme('vera_excel')"/>
    <button class="btd-theme-dot btd-theme-teal" 
            title="Ocean Teal"
            t-on-click="() => this.setTheme('ocean_teal')"/>
</div>

1.4 Using Theme Variables

Always use CSS variables instead of hardcoded colors:

// ✅ GOOD - Theme aware
.my-element {
    color: var(--mo-theme-primary);
    background: var(--mo-theme-background);
    border: 1px solid var(--mo-theme-border);
}

// ❌ BAD - Hardcoded
.my-element {
    color: #4682B4;
    background: #F9FAFB;
}

2. Color Palette

2.1 Primary Theme Colors

Variable Vera Blue Eye Vera Excel Ocean Teal
--mo-theme-primary #4682B4 #23764A #017e84
--mo-theme-primary-dark #3A6D99 #1A5A38 #015d62
--mo-theme-primary-light #5B9BD5 #2D8F5E #02a5ad
--mo-theme-primary-pale #E8F4FC #E8F5ED #E8F8F9

2.2 Status Colors

Status Dot Color Badge Background Text Color
Paid #34c759 #d4edda #155724
Partial var(--mo-theme-primary) --mo-theme-primary-pale --mo-theme-primary
Not Paid #ff3b30 #f8d7da #721c24
Pending #ff9500 #fff3cd #856404

2.3 Background Colors

Element Color Usage
Page Background var(--mo-theme-background) Main dashboard background
Card Background var(--mo-theme-card-bg) / #FFFFFF All cards
Hover Background rgba(0,0,0,0.02) Row hover states
Input Background #f5f5f7 Form inputs, badges

2.4 Semantic Colors

// Success (Green)
$color-success: #34c759;
$color-success-bg: #d4edda;
$color-success-text: #155724;

// Warning (Yellow/Orange)
$color-warning: #ff9500;
$color-warning-bg: #fff3cd;
$color-warning-text: #856404;

// Danger (Red)
$color-danger: #ff3b30;
$color-danger-bg: #f8d7da;
$color-danger-text: #721c24;

// Muted (Gray)
$color-muted: #86868b;
$color-muted-bg: #f5f5f7;

3. Typography

3.1 Font Stack

font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, sans-serif;

3.2 Font Sizes

Element Size Weight Line Height
Page Title 28px 600 1.2
Subtitle 13px 400 1.4
Card Value (Large) 24px 600 1.2
Card Label 12px 500 1.4
Card Sub-text 11px 400 1.4
Customer Name 16px 600 1.3
Bill Number 13px 600 1.4
Badge Text 11px 500 1
Small Text 10px 400 1.4

3.3 Text Colors

Type Color Usage
Primary Text #1d1d1f Headlines, important values
Secondary Text #86868b Labels, descriptions
Muted Text #6c757d Hints, timestamps
Link Text var(--mo-theme-primary) Clickable elements
Danger Text #ff3b30 Negative values, warnings
Success Text #34c759 Positive values

4. Spacing System

4.1 Base Units

Use multiples of 4px for consistency:

Name Size Usage
xs 4px Icon margins, tight gaps
sm 8px Badge padding, small gaps
md 12px Component gaps
lg 16px Section gaps
xl 24px Card padding, grid gaps
2xl 32px Section margins
3xl 48px Major section breaks

4.2 Page Layout

.dashboard {
    padding: 32px 40px 240px 40px; // Top Right Bottom Left
    // Note: 240px bottom for generous scroll space
}

4.3 Card Spacing

.summary-card {
    padding: 20px;
    gap: 24px; // Grid gap between cards
    margin-bottom: 48px; // Before divider
}

.customer-card {
    padding: 20px;
    gap: 16px; // Between elements inside
}

5. Border & Shadows

5.1 Border Radius

Element Radius
Cards (Summary/Customer) 16px
Buttons 8px
Badges 6px
Progress Bars 4px
Small Elements 4px

5.2 Border Color

border: 1px solid var(--mo-theme-border, #D9D9D9);

5.3 Shadows

State Shadow
Default Card 0 2px 12px rgba(0, 0, 0, 0.03)
Hover Card 0 8px 24px rgba(70, 130, 180, 0.15)
Elevated 0 4px 20px rgba(0, 0, 0, 0.04)

5.4 Dividers

// Section Divider
&::after {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 1px;
    background: var(--mo-theme-border, #D9D9D9);
}

6. Odoo Navigation Bar

The main Odoo navigation bar (top menu) follows the theme colors for a cohesive branded experience.

6.1 Navigation Bar Structure

┌─────────────────────────────────────────────────────────────────────────────┐
│ [App Icon] Master Orders │ Dashboard │ Bill Tracking │ ... │ + │ 🔔 │ User │
└─────────────────────────────────────────────────────────────────────────────┘

6.2 Navigation Bar Colors

Element Color
Background var(--mo-theme-primary-dark)
Text rgba(255, 255, 255, 0.85)
Hover Background var(--mo-theme-primary)
Active Menu Item var(--mo-theme-primary)

6.3 Navigation Bar SCSS Override

// Override Odoo's default navbar to follow Master Order theme
.o_main_navbar {
    background-color: var(--mo-theme-primary-dark) !important;
    border-bottom: 1px solid var(--mo-theme-primary-dark) !important;
    
    // App name/brand
    .o_menu_brand {
        color: white !important;
        
        &:hover {
            background-color: var(--mo-theme-primary) !important;
        }
    }
    
    // Menu items
    .o_menu_sections .o_nav_entry {
        color: rgba(255, 255, 255, 0.85) !important;
        
        &:hover, &:focus, &.active {
            background-color: var(--mo-theme-primary) !important;
            color: white !important;
        }
    }
    
    // Dropdown menus
    .dropdown-menu {
        background-color: var(--mo-theme-primary-dark) !important;
        border: 1px solid var(--mo-theme-primary) !important;
        
        .dropdown-item {
            color: rgba(255, 255, 255, 0.85) !important;
            
            &:hover {
                background-color: var(--mo-theme-primary) !important;
                color: white !important;
            }
        }
    }
    
    // Right side icons (systray)
    .o_menu_systray .o_nav_entry {
        color: rgba(255, 255, 255, 0.85) !important;
        
        &:hover {
            background-color: var(--mo-theme-primary) !important;
        }
    }
}

6.4 Theme Color on Navigation

Theme Nav Background Nav Hover
Vera Blue Eye #3A6D99 #4682B4
Vera Excel #1A5A38 #23764A
Ocean Teal #015d62 #017e84

6.5 Important Note

The navigation bar uses !important to override Odoo's default styles. This ensures our theme colors take precedence.


7. Dashboard Header Bar

The header bar is a consistent element across all dashboards. It should always follow the theme colors.

6.1 Header Bar Structure

<div class="dashboard-header">
    <div class="header-left">
        <h2 class="title">
            <i class="fa fa-icon"/> Page Title
        </h2>
        <span class="subtitle">Description text</span>
    </div>
    <div class="header-right">
        <!-- Filters -->
        <div class="filters">
            <label class="filter-toggle">
                <input type="checkbox"/> Filter Label
            </label>
        </div>
        <!-- Theme Switcher -->
        <div class="theme-switcher">...</div>
        <!-- Refresh Button -->
        <button class="refresh-btn">
            <i class="fa fa-refresh"/> Refresh
        </button>
        <!-- View Toggle -->
        <div class="view-toggle">
            <button class="btn-grid"><i class="fa fa-th-large"/></button>
            <button class="btn-list"><i class="fa fa-list"/></button>
        </div>
    </div>
</div>

6.2 Header Bar Styling

.dashboard-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 32px;
    padding: 16px 20px;
    background: var(--mo-theme-card-bg, white);
    border: 1px solid var(--mo-theme-border, #D9D9D9);
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}

6.3 Title with Icon Box

.title {
    font-size: 24px;
    font-weight: 600;
    color: var(--mo-theme-text, #1d1d1f);
    display: flex;
    align-items: center;
    
    i {
        color: var(--mo-theme-primary);
        width: 40px;
        height: 40px;
        display: flex;
        align-items: center;
        justify-content: center;
        background: var(--mo-theme-primary-pale);
        border-radius: 10px;
        margin-right: 12px;
        font-size: 22px;
    }
}

.subtitle {
    font-size: 13px;
    color: var(--mo-theme-text-muted, #86868b);
    margin-top: 4px;
    margin-left: 52px; // Align with title text (after icon)
}

6.4 Filter Toggle

.filter-toggle {
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    font-size: 12px;
    color: var(--mo-theme-text-muted);
    padding: 6px 12px;
    background: var(--mo-theme-primary-pale);
    border-radius: 6px;
    border: 1px solid var(--mo-theme-border, #D9D9D9);
    
    &:hover {
        border-color: var(--mo-theme-primary);
    }
    
    input[type="checkbox"] {
        width: 16px;
        height: 16px;
        accent-color: var(--mo-theme-primary);
    }
}

6.5 Refresh Button

.refresh-btn {
    border-radius: 6px;
    padding: 6px 12px;
    font-size: 12px;
    border: 1px solid var(--mo-theme-primary);
    color: var(--mo-theme-primary);
    background: transparent;
    
    &:hover {
        background: var(--mo-theme-primary);
        color: white;
    }
    
    i {
        margin-right: 4px;
    }
}

6.6 View Toggle

.view-toggle {
    display: flex;
    gap: 2px;
    background: var(--mo-theme-primary-pale);
    padding: 3px;
    border-radius: 8px;
    border: 1px solid var(--mo-theme-border, #D9D9D9);
    
    .btn {
        padding: 6px 12px;
        border-radius: 6px;
        border: none;
        font-size: 12px;
        
        // Inactive state
        &.btn-outline-secondary {
            background: transparent;
            color: var(--mo-theme-text-muted);
            
            &:hover {
                background: rgba(255,255,255,0.7);
                color: var(--mo-theme-primary);
            }
        }
        
        // Active state
        &.btn-primary {
            background: linear-gradient(135deg, 
                var(--mo-theme-primary) 0%, 
                var(--mo-theme-primary-light) 100%);
            color: white;
            box-shadow: 0 2px 8px rgba(70, 130, 180, 0.25);
        }
    }
}

6.7 Theme Switcher Dots

.theme-switcher {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 8px;
    background: rgba(0, 0, 0, 0.04);
    border-radius: 20px;
    
    .theme-dot {
        width: 18px;
        height: 18px;
        border-radius: 50%;
        cursor: pointer;
        transition: transform 0.2s ease, box-shadow 0.2s ease;
        padding: 0;
        
        &:hover {
            transform: scale(1.2);
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
        }
        
        // Each theme has gradient showing primary + background
        &.theme-blue-eye {
            background: linear-gradient(135deg, #4682B4 60%, #F9FAFB 100%);
            border: 1px solid #4682B4;
        }
        
        &.theme-excel {
            background: linear-gradient(135deg, #23764A 60%, #FFFFFF 100%);
            border: 1px solid #23764A;
        }
        
        &.theme-teal {
            background: linear-gradient(135deg, #017e84 60%, #F8F9FA 100%);
            border: 1px solid #017e84;
        }
    }
}

8. Component Library

6.1 Summary Cards

.summary-card {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    padding: 20px;
    background: var(--mo-theme-card-bg, white);
    border-radius: 16px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.04);
    border: 1px solid var(--mo-theme-border, #D9D9D9);
}

.summary-card-icon {
    width: 44px;
    height: 44px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, var(--mo-theme-primary-pale) 0%, white 100%);
    color: var(--mo-theme-primary);
    font-size: 18px;
}

.summary-card-value {
    font-size: 24px;
    font-weight: 600;
    color: #1d1d1f;
}

.summary-card-label {
    font-size: 12px;
    font-weight: 500;
    color: #86868b;
}

.summary-card-sub {
    font-size: 11px;
    color: #86868b;
}

6.2 Customer/Entity Cards

.entity-card {
    background: var(--mo-theme-card-bg, white);
    border-radius: 16px;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.03);
    border: 1px solid var(--mo-theme-border, #D9D9D9);
    padding: 20px;
    cursor: pointer;
    transition: all 0.3s ease;
    
    &:hover {
        box-shadow: 0 8px 24px rgba(70, 130, 180, 0.15);
        border-color: var(--mo-theme-primary);
    }
}

6.3 Status Badges (Dot Style)

.status-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    font-weight: 500;
    white-space: nowrap;
    
    &::before {
        content: "●";
        font-size: 8px;
    }
    
    // Paid - Green
    &.badge-paid {
        color: #34c759;
        &::before { color: #34c759; }
    }
    
    // Partial - Theme Primary
    &.badge-partial {
        color: var(--mo-theme-primary);
        &::before { color: var(--mo-theme-primary); }
    }
    
    // Not Paid - Red
    &.badge-not_paid {
        color: #ff3b30;
        &::before { color: #ff3b30; }
    }
    
    // Pending - Orange
    &.badge-pending {
        color: #ff9500;
        &::before { color: #ff9500; }
    }
}

6.4 Logistics Badges (Pill Style)

.logistics-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 10px;
    border-radius: 6px;
    font-size: 11px;
    font-weight: 500;
    white-space: nowrap;
    
    // Default (CTN count)
    background: #f5f5f7;
    color: #6c757d;
    
    // Sent - Green
    &.badge-sent {
        background: #d4edda;
        color: #155724;
    }
    
    // Remain - Yellow (if has value)
    &.badge-remain.has-value {
        background: #fff3cd;
        color: #856404;
    }
    
    // Remain - Gray (if zero)
    &.badge-remain {
        background: #f5f5f7;
        color: #6c757d;
    }
}

6.5 Progress Bars

.progress-bar-container {
    height: 4px;
    background: #f2f2f7;
    border-radius: 4px;
    overflow: hidden;
}

.progress-bar-fill {
    height: 100%;
    border-radius: 4px;
    transition: width 0.3s ease;
    
    // Default - Theme Primary
    background: linear-gradient(90deg, 
        var(--mo-theme-primary) 0%, 
        var(--mo-theme-primary-light) 100%);
    
    // 100% - Green
    &.complete {
        background: linear-gradient(90deg, #34c759 0%, #30d158 100%);
    }
}

.progress-label {
    font-size: 10px;
    color: var(--mo-theme-primary);
    margin-top: 4px;
}

6.6 Buttons

// Primary Action Button
.btn-primary-action {
    background: linear-gradient(135deg, 
        var(--mo-theme-primary) 0%, 
        var(--mo-theme-primary-light) 100%);
    color: white;
    border: none;
    border-radius: 8px;
    padding: 8px 16px;
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s ease;
    
    &:hover {
        background: linear-gradient(135deg, 
            var(--mo-theme-primary-dark) 0%, 
            var(--mo-theme-primary) 100%);
        box-shadow: 0 4px 12px rgba(70, 130, 180, 0.3);
    }
}

// Icon Button
.btn-icon {
    width: 28px;
    height: 28px;
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid #e5e5ea;
    color: #86868b;
    cursor: pointer;
    transition: all 0.2s ease;
    
    &:hover {
        background: #f5f5f7;
        color: var(--mo-theme-primary);
    }
}

7. Layout Patterns

7.1 Dashboard Structure

<div class="dashboard">
    <!-- Header -->
    <div class="dashboard-header">
        <div class="header-left">
            <h2 class="title"><i class="fa fa-icon"/> Title</h2>
            <span class="subtitle">Description text</span>
        </div>
        <div class="header-right">
            <!-- Filters, Theme Switcher, View Toggle -->
        </div>
    </div>
    
    <!-- Summary Cards -->
    <div class="summary-cards-grid">
        <!-- 5-6 summary cards -->
    </div>
    
    <!-- Divider (CSS ::after) -->
    
    <!-- Main Content -->
    <div class="content-grid">
        <!-- Entity cards or list view -->
    </div>
</div>

7.2 Grid Layouts

// Summary Cards Grid
.summary-cards-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 24px;
}

// Entity Cards Grid
.entity-cards-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 16px;
}

7.3 Card Internal Layout

// Two-row layout for bill items
.bill-row {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px;
    
    .bill-top {
        display: flex;
        justify-content: space-between;
        align-items: flex-start;
    }
    
    .bill-bottom {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 12px;
        flex-wrap: wrap;
    }
}

8. Responsive Design

8.1 Breakpoints

Name Width Target
Desktop > 1024px Full layout
Tablet 768px - 1024px Reduced columns
Mobile 480px - 768px Stacked layout
Small Mobile < 480px Minimal layout

8.2 Responsive SCSS

// Tablet
@media (max-width: 1024px) {
    .dashboard {
        padding: 24px 24px 200px 24px;
    }
    
    .summary-cards-grid {
        grid-template-columns: repeat(3, 1fr);
    }
}

// Mobile
@media (max-width: 768px) {
    .dashboard {
        padding: 16px 16px 180px 16px;
    }
    
    .summary-cards-grid {
        grid-template-columns: repeat(2, 1fr);
        gap: 12px;
    }
    
    .entity-cards-grid {
        grid-template-columns: 1fr;
    }
}

// Small Mobile
@media (max-width: 480px) {
    .summary-cards-grid {
        grid-template-columns: 1fr;
    }
    
    .card-value {
        font-size: 20px;
    }
}

8.3 Scrolling Setup

// Override Odoo container restrictions
.o_action_manager,
.o_action_manager > .o_action,
.o_view_manager_content,
.o_content {
    overflow-y: auto !important;
    overflow-x: hidden !important;
    height: auto !important;
    max-height: none !important;
}

// Dashboard wrapper
.dashboard {
    min-height: 100vh;
    height: auto !important;
    overflow: visible !important; // Let parent scroll
}

9. Icons

9.1 Icon Library

Using Font Awesome 4.x (available in Odoo).

9.2 Common Icons

Use Case Icon Class
Money/Amount 💰 fa-money
Paid/Success fa-check-circle
Outstanding fa-exclamation-circle
Delayed/Time fa-clock-o
Shipping/CTN 📦 fa-cubes
Truck/Sent 🚚 fa-truck
CBM/Volume fa-cube
Remain/Inbox 📥 fa-inbox
Bill/Document 📄 fa-file-text-o
User/Customer 👤 fa-user
Vendor 🏢 fa-building
Payment 💳 fa-credit-card
View/Eye 👁 fa-eye
Refresh 🔄 fa-refresh
Expand/Collapse ▼▲ fa-chevron-down / fa-chevron-up
Grid View fa-th-large
List View fa-list

9.3 Icon Styling

.icon {
    font-size: 18px;
    color: var(--mo-theme-primary);
    
    // In badges
    &.badge-icon {
        font-size: 10px;
        margin-right: 4px;
    }
    
    // In card headers
    &.card-icon {
        width: 44px;
        height: 44px;
        display: flex;
        align-items: center;
        justify-content: center;
        background: var(--mo-theme-primary-pale);
        border-radius: 12px;
    }
}

10. Interactive States

10.1 Hover States

// Card Hover
.card:hover {
    box-shadow: 0 8px 24px rgba(70, 130, 180, 0.15);
    border-color: var(--mo-theme-primary);
}

// Row Hover
.row:hover {
    background: rgba(0, 0, 0, 0.02);
}

// Button Hover
.btn:hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

// Link Hover
a:hover {
    color: var(--mo-theme-primary-dark);
    text-decoration: underline;
}

10.2 Transitions

// Standard transition
transition: all 0.3s ease;

// Smooth cubic bezier
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);

// Quick transition (buttons)
transition: all 0.2s ease;

10.3 Focus States

// Accessible focus
:focus {
    outline: 2px solid var(--mo-theme-primary);
    outline-offset: 2px;
}

// Focus within cards
.card:focus-within {
    border-color: var(--mo-theme-primary);
}

11. Code Snippets

11.1 Complete Summary Card

<div class="btd-card btd-card-blue">
    <div class="btd-card-icon">
        <i class="fa fa-money"></i>
    </div>
    <div class="btd-card-content">
        <span class="btd-card-value">
            <t t-esc="formatCurrency(state.summary.totalAmount)"/>
        </span>
        <span class="btd-card-label">Total Amount</span>
        <span class="btd-card-sub">
            <t t-esc="state.summary.count"/> items
        </span>
    </div>
</div>

11.2 Complete Entity Card

<div class="btd-vendor-card" t-on-click="() => this.toggleEntity(entity.id)">
    <!-- Header -->
    <div class="btd-card-header">
        <div class="btd-vendor-info">
            <i class="fa fa-user"></i>
            <span class="btd-vendor-name"><t t-esc="entity.name"/></span>
        </div>
        <span t-attf-class="btd-status-badge btd-badge-#{entity.status}">
            <t t-esc="getStatusLabel(entity.status)"/>
        </span>
    </div>
    
    <!-- Financial Section -->
    <div class="btd-financial-section">
        <div class="btd-financial-value text-danger">
            <t t-esc="formatCurrency(entity.outstanding)"/>
        </div>
        <div class="btd-financial-label">Outstanding</div>
        
        <!-- Progress Bar -->
        <div class="btd-progress-simple">
            <div class="progress">
                <div class="progress-bar" t-attf-style="width: #{entity.paidPct}%"/>
            </div>
            <span class="btd-progress-label">
                <t t-esc="entity.paidPct"/>% paid
            </span>
        </div>
    </div>
    
    <!-- Logistics Section -->
    <div class="btd-logistics-summary">
        <div class="btd-logistics-item">
            <i class="fa fa-truck"/> 
            <strong><t t-esc="entity.sentCtn"/></strong> / <t t-esc="entity.totalCtn"/> CTN
        </div>
    </div>
    
    <!-- Expand Icon -->
    <div class="btd-card-expand">
        <i t-attf-class="fa #{isExpanded(entity.id) ? 'fa-chevron-up' : 'fa-chevron-down'}"/>
    </div>
</div>

11.3 Complete Bill Row

<div class="btd-bill-row">
    <!-- Top: Bill Info + Amount -->
    <div class="btd-bill-top">
        <div class="btd-bill-info">
            <a class="btd-bill-name" t-on-click.stop="() => this.openBill(bill.id)">
                <t t-esc="bill.name"/>
            </a>
            <span class="btd-bill-ref"><t t-esc="bill.reference"/></span>
            <span class="btd-bill-date"><t t-esc="formatDate(bill.date)"/></span>
        </div>
        <div class="btd-bill-financial">
            <span class="btd-bill-total"><t t-esc="formatCurrency(bill.total)"/></span>
            <span class="btd-bill-outstanding text-danger">
                <t t-esc="formatCurrency(bill.outstanding)"/> owed
            </span>
        </div>
    </div>
    
    <!-- Bottom: Status + Logistics + Actions -->
    <div class="btd-bill-bottom">
        <div class="btd-bill-status">
            <span t-attf-class="btd-bill-badge badge-#{bill.status}">
                <t t-esc="getStatusLabel(bill.status)"/>
            </span>
        </div>
        <div class="btd-bill-logistics">
            <span class="btd-logistics-stat">
                <i class="fa fa-cubes"/> <t t-esc="bill.ctn"/> CTN
            </span>
            <span class="btd-logistics-stat btd-sent">
                <i class="fa fa-truck"/> Sent: <t t-esc="bill.sent"/>
            </span>
            <span t-attf-class="btd-logistics-stat btd-remain #{bill.remain > 0 ? 'has-remain' : ''}">
                <i class="fa fa-inbox"/> Remain: <t t-esc="bill.remain"/>
            </span>
        </div>
        <div class="btd-bill-actions">
            <button class="btn btd-pay-btn" title="Pay">
                <i class="fa fa-credit-card"/>
            </button>
            <button class="btn btn-outline-secondary" title="View">
                <i class="fa fa-eye"/>
            </button>
        </div>
    </div>
</div>

11.4 Theme Setter JavaScript

async setTheme(themeName) {
    // Apply immediately
    document.documentElement.setAttribute('data-mo-theme', themeName);
    document.body?.setAttribute('data-mo-theme', themeName);
    localStorage.setItem('mo_theme', themeName);
    
    // Save to backend
    if (window.moTheme) {
        await window.moTheme.setTheme(themeName);
    }
}

Quick Reference Card

Colors to Remember

Purpose Color
Border #D9D9D9
Background (Eye-friendly) #F9FAFB
Card Background #FFFFFF
Muted Text #86868b
Primary Text #1d1d1f
Success Green #34c759
Warning Yellow #ff9500
Danger Red #ff3b30

Sizes to Remember

Element Size
Card Border Radius 16px
Button Border Radius 8px
Badge Border Radius 6px
Card Padding 20px
Grid Gap 16px - 24px
Page Bottom Padding 240px

Files to Update

Component File
Theme Variables static/src/scss/master_order_theme_variables.scss
Dashboard Styles static/src/scss/[dashboard_name]_dashboard.scss
Templates static/src/xml/[dashboard_name]_templates.xml
JavaScript static/src/js/[dashboard_name]_dashboard.js
Python Model models/res_users.py (for theme field)

This design system ensures visual consistency across all Master Order dashboards.