# GGM Commerce Styling Architecture

## Complete System Overview

The GGM Commerce plugin uses a **three-layer styling architecture** that provides professional defaults while maintaining full user customization control through Elementor.

---

## The Three Layers

### 1. **widgets.css** (Always Loaded - Structural Layer)
**Location:** `assets/css/widgets.css`

**Purpose:** Provides essential structural and functional CSS needed for widgets to work properly.

**DO Include:**
- Structural CSS (display, flex, grid, position, width, height)
- Functional CSS (transitions, transforms, cursor states, animations)
- Layout properties (align-items, justify-content, gap)
- Responsive breakpoints for layout changes
- Essential accessibility (text-decoration for links, cursor for buttons)

**DO NOT Include:**
- Colors (backgrounds, text, borders)
- Typography (font-family, font-size, font-weight, line-height)
- Spacing values (margin, padding - these are controlled by Elementor or CSS variables)
- Decorative styles (shadows, borders, border-radius)

**Example:**
```css
/* widgets.css - Structural only */
.ggmc-product-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: var(--ggmc-grid-gap, 20px);
}

.ggmc-button {
    display: inline-flex;
    align-items: center;
    cursor: pointer;
    transition: all 0.3s ease;
}
```

---

### 2. **professional-defaults.css** (Conditionally Loaded - Design Layer)
**Location:** `assets/css/professional-defaults.css`

**Purpose:** Provides beautiful default styling when Professional Defaults are enabled in Settings > Widget Styles.

**Loading Condition:**
```php
// Only loads when ggm_commerce_defaults_cleared option is false (defaults ENABLED)
if (!get_option('ggm_commerce_defaults_cleared', false)) {
    wp_enqueue_style('ggmc-professional-defaults', ...);
}
```

**Requirements:**
- **Colors:** ONLY via CSS variables (e.g., `var(--ggmc-primary)`)
- **Typography:** ONLY via CSS variables (e.g., `var(--ggmc-font-family)`)
- **Shadows/Border-radius:** ONLY via CSS variables
- **Spacing:** Via CSS variables where appropriate
- Every styled property MUST have a corresponding Elementor widget control that can override it

**CSS Variables System:**
```css
:root {
    /* Color Variables */
    --ggmc-primary: #2563eb;
    --ggmc-primary-dark: #1d4ed8;
    --ggmc-text-primary: #0f172a;
    --ggmc-text-secondary: #475569;
    --ggmc-text-muted: #64748b;
    --ggmc-background: #ffffff;
    --ggmc-surface: #f8fafc;
    --ggmc-border: #e2e8f0;
    --ggmc-success: #059669;
    --ggmc-warning: #d97706;
    --ggmc-error: #dc2626;

    /* Typography Variables */
    --ggmc-font-family: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --ggmc-font-weight-light: 300;
    --ggmc-font-weight-normal: 400;
    --ggmc-font-weight-medium: 500;
    --ggmc-font-weight-semibold: 600;
    --ggmc-font-weight-bold: 700;

    /* Spacing Variables */
    --ggmc-spacing-xs: 4px;
    --ggmc-spacing-sm: 8px;
    --ggmc-spacing-md: 16px;
    --ggmc-spacing-lg: 24px;
    --ggmc-spacing-xl: 32px;
    --ggmc-spacing-xxl: 48px;

    /* Border Radius */
    --ggmc-radius-sm: 4px;
    --ggmc-radius-md: 6px;
    --ggmc-radius-lg: 8px;

    /* Shadows */
    --ggmc-shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.1);
    --ggmc-shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
    --ggmc-shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
}
```

**Example:**
```css
/* professional-defaults.css - Design with CSS variables */
.elementor-widget-ggmc-add-to-cart .ggmc-button {
    background: var(--ggmc-primary);
    color: #ffffff;
    font-family: var(--ggmc-font-family);
    font-size: 16px;
    font-weight: var(--ggmc-font-weight-semibold);
    padding: 14px 24px;
    border-radius: var(--ggmc-radius-md);
    border: 2px solid var(--ggmc-primary);
}

.elementor-widget-ggmc-add-to-cart .ggmc-button:hover {
    background: var(--ggmc-primary-dark);
    border-color: var(--ggmc-primary-dark);
}
```

---

### 3. **default-widget-styles.php** (Elementor Defaults Layer)
**Location:** `includes/default-widget-styles.php`

**Purpose:** Provides default values for Elementor widget controls when new widgets are created.

**How It Works:**
1. PHP array contains default values for each widget's Elementor controls
2. `GGM_Commerce_Helpers::get_plugin_default_styles()` retrieves these values
3. `get_default_data()` in base widget applies them when widget is created
4. Values become part of widget's saved settings in database
5. User can override via Elementor's Style tab controls

**Loading Condition:**
```php
// Check if defaults have been globally cleared
$defaults_cleared = get_option('ggm_commerce_defaults_cleared', false);

if ($defaults_cleared) {
    return []; // Return empty array - no defaults applied
}

// Load and return defaults
require_once 'default-widget-styles.php';
return ggm_commerce_get_default_styles_config()[$widget_name];
```

**Structure:**
```php
function ggm_commerce_get_default_styles_config() {
    $design_system = [
        'colors' => [
            'primary' => '#2563eb',
            'text_primary' => '#0f172a',
            // ... more colors
        ],
        'typography' => [
            'font_family' => "'Poppins', sans-serif",
            'font_weights' => [
                'normal' => '400',
                'semibold' => '600',
                // ... more weights
            ],
        ],
    ];

    return [
        'ggmc-add-to-cart' => [
            'button_background_color' => $design_system['colors']['primary'],
            'button_color' => '#FFFFFF',
            'button_typography_font_size' => ['size' => '16', 'unit' => 'px'],
            'button_padding' => [
                'top' => '14', 'right' => '24', 'bottom' => '14', 'left' => '24',
                'unit' => 'px', 'isLinked' => false
            ],
            // ... more defaults
        ],
        // ... more widgets
    ];
}
```

---

## How The Layers Work Together

### When Professional Defaults are ENABLED

**Option State:** `ggm_commerce_defaults_cleared` = `false` (or not set)

**What Loads:**
1. ✅ `widgets.css` - Structure and layout
2. ✅ `professional-defaults.css` - Beautiful CSS styling with variables
3. ✅ `default-widget-styles.php` - Elementor control defaults applied to NEW widgets

**Result:**
- NEW widgets get professional Elementor control defaults
- ALL widgets (new and existing) get CSS styling from professional-defaults.css
- User can override ANY style via Elementor's Style tab controls
- CSS variables provide consistent theming across all widgets

**Override Hierarchy:**
1. **User's Elementor control settings** (highest priority - inline styles)
2. CSS from professional-defaults.css
3. Control defaults from default-widget-styles.php
4. Browser defaults (lowest priority)

---

### When Professional Defaults are DISABLED

**Option State:** `ggm_commerce_defaults_cleared` = `true`

**What Loads:**
1. ✅ `widgets.css` - Structure and layout only
2. ❌ `professional-defaults.css` - NOT loaded
3. ❌ `default-widget-styles.php` - Returns empty arrays

**Result:**
- NEW widgets start completely blank (no styling)
- ALL widgets have no CSS styling (structure only)
- User builds styling from scratch via Elementor's Style tab
- Complete control, no predefined aesthetics

---

## The Fundamental Rule

**professional-defaults.css styling + default-widget-styles.php + widget controls = user customizable**

If styling exists in `professional-defaults.css` OR `default-widget-styles.php`, corresponding Elementor widget controls **MUST** exist so users can override those defaults.

---

## Workflow: Adding Styling to a New Widget

### Step 1: Read the Renderer File
```bash
# Verify actual HTML class structure
Read wp-content/plugins/ggm-commerce/widgets/renderers/class-{widget}-renderer.php
```

**Why:** Confirm CSS selectors match actual HTML output.

### Step 2: Add Widget Controls
```php
// In widget class: widgets/tags/widget-{name}.php
protected function register_controls() {
    // Add Style controls for EVERY property you'll style
    $this->add_control(
        'button_background_color',
        [
            'label' => __('Background Color', 'ggm-commerce'),
            'type' => \Elementor\Controls_Manager::COLOR,
            'selectors' => [
                '{{WRAPPER}} .ggmc-button' => 'background-color: {{VALUE}};',
            ],
        ]
    );
}
```

### Step 3: Add CSS to professional-defaults.css
```css
/* Use widget wrapper for specificity */
.elementor-widget-ggmc-your-widget .ggmc-button {
    background: var(--ggmc-primary);
    color: #ffffff;
    /* ... more styling with CSS variables */
}
```

### Step 4: Add PHP Defaults
```php
// In includes/default-widget-styles.php
'ggmc-your-widget' => [
    'button_background_color' => $design_system['colors']['primary'],
    'button_color' => '#FFFFFF',
    'button_padding' => [
        'top' => '14', 'right' => '24', 'bottom' => '14', 'left' => '24',
        'unit' => 'px', 'isLinked' => false
    ],
],
```

### Step 5: Add Static Method to Widget
```php
public static function get_static_default_styles() {
    return self::get_defaults_from_config();
}
```

---

## API Reference

### Helper Methods

```php
// Check if defaults are enabled
GGM_Commerce_Helpers::are_default_styles_enabled(): bool

// Enable defaults globally
GGM_Commerce_Helpers::enable_default_styles(): bool

// Disable defaults globally
GGM_Commerce_Helpers::disable_default_styles(): bool

// Get defaults for specific widget
GGM_Commerce_Helpers::get_plugin_default_styles(string $widget_name): array

// Get list of all widgets with defaults
GGM_Commerce_Helpers::get_widgets_with_defaults(): array
```

### Base Widget Methods

```php
// Override in child widgets to return defaults
public static function get_static_default_styles(): array

// Helper to get defaults from centralized config
protected static function get_defaults_from_config(): array

// Applies defaults when widget is created
public function get_default_data(): array
```

---

## Settings Page

**Location:** GGM Commerce > Settings > Default Styles tab

**Controls:**
- **Status Indicator** - Shows current state (enabled/disabled)
- **"Load All Defaults" Button** - Enables professional styling
- **"Remove All Defaults" Button** - Disables professional styling
- **Design System Reference** - Visual display of colors, typography, spacing

**Important Notes:**
- Toggle affects ONLY new widgets created after the change
- Existing widgets retain their current styling until manually changed
- Individual widgets can always be customized via Elementor regardless of global setting

---

## Common Mistakes to Avoid

### ❌ Wrong: Hardcoded Values in CSS
```css
.product-card {
    background: #ffffff;  /* Never hardcode */
    color: #333333;       /* Never hardcode */
}
```

### ✅ Correct: CSS Variables
```css
.product-card {
    background: var(--ggmc-background);
    color: var(--ggmc-text-primary);
}
```

---

### ❌ Wrong: Assuming Class Names
```css
/* Don't write CSS based on assumptions */
.ggmc-filter-container .filter-group { }
```

### ✅ Correct: Verify from Renderer
```bash
# Read the renderer first to see actual HTML
Read class-product-filter-renderer.php
# Then write accurate selectors
```

---

### ❌ Wrong: No Widget Control for Styled Property
```css
.ggmc-button {
    padding: 20px;  /* No Elementor control exists to override this */
}
```

### ✅ Correct: CSS + Widget Control
```css
.ggmc-button {
    padding: var(--ggmc-spacing-md);
}
```
```php
// AND in widget class:
$this->add_control('button_padding', [...]);
```

---

### ❌ Wrong: Making Control-Level Defaults Conditional
```php
$widget->add_control('button_color', [
    'default' => $some_condition ? '#2563eb' : '',  // ❌ WRONG
]);
```

### ✅ Correct: Unconditional Control Defaults
```php
$widget->add_control('button_color', [
    'default' => '#2563eb',  // ✅ Always has value
]);
```

**Why:** Control-level defaults are used as fallbacks for existing widgets. Making them conditional would affect existing widgets when the condition changes.

---

## File Structure

```
ggm-commerce/
├── assets/
│   └── css/
│       ├── widgets.css                      # Layer 1: Structural CSS (always loaded)
│       └── professional-defaults.css        # Layer 2: Design CSS (conditional)
│
├── includes/
│   ├── default-widget-styles.php           # Layer 3: Elementor defaults config
│   ├── class-helpers.php                   # Helper methods for defaults
│   ├── class-elementor.php                 # CSS enqueueing logic
│   └── class-admin.php                     # Settings page UI
│
├── widgets/
│   ├── class-ggm-commerce-base-widget.php # Base widget with default system
│   └── tags/
│       └── widget-*.php                    # Individual widgets
│
└── docs/
    └── STYLING-ARCHITECTURE.md             # This file
```

---

## Troubleshooting

### Widgets Not Applying Defaults

1. Check option value: `get_option('ggm_commerce_defaults_cleared')` should be `false`
2. Verify `default-widget-styles.php` exists and is readable
3. Clear Elementor cache: Elementor > Tools > Regenerate CSS & Data
4. Try creating a **new** widget (existing ones won't update)
5. Check browser console for CSS loading errors

### Wrong Styling Applied

1. Check widget name matches key in `default-widget-styles.php`
2. Verify control names in defaults match actual control registration
3. Inspect element to see which CSS is actually being applied
4. Check for PHP errors in debug.log
5. Verify `professional-defaults.css` is loading (check Network tab)

### Settings Page Not Showing

1. Verify `includes/class-admin.php` is loaded
2. Check user has admin permissions
3. Look for JavaScript console errors
4. Clear WordPress object cache if using caching plugins

---

## Version History

### Version 1.0 (Current)
- Three-layer architecture with widgets.css, professional-defaults.css, and default-widget-styles.php
- CSS variable system for consistent theming
- Centralized default styling configuration
- Admin settings page with visual toggle
- 15+ widgets with comprehensive default styles
- Full Elementor control override capability
