{
  "meta": {
    "name": "Workshopr Design System",
    "version": "3.0.1",
    "description": "Machine-readable design tokens, component catalog, and rules — the single source of truth for all AI-assisted development",
    "sourceOfTruth": "/design-system/platform-tokens.css",
    "componentSource": "/includes/components/helpers.php",
    "styleGuide": "/design-system/workshopr-style-guide.md",
    "lastUpdated": "2026-04-10",
    "architecture": "LEARN > PLAN > FACILITATE > REFLECT"
  },

  "phases": {
    "learn": {
      "color": "#E54D4D",
      "dark": "#C73E3E",
      "light": "#FEE2E2",
      "veryLight": "#FEF2F2",
      "description": "Discovery, knowledge, content consumption",
      "apps": ["mainsite", "tips", "podcasts"]
    },
    "plan": {
      "color": "#0284C7",
      "dark": "#075985",
      "light": "#E0F2FE",
      "veryLight": "#F0F9FF",
      "description": "Building, creating, structuring workshops",
      "apps": ["planner"]
    },
    "facilitate": {
      "color": "#7C4DFF",
      "dark": "#6D28D9",
      "light": "#DDD6FE",
      "veryLight": "#EDE9FE",
      "description": "Live sessions, real-time assistance",
      "apps": ["coach", "intervention", "facilitator"]
    },
    "reflect": {
      "color": "#10B981",
      "dark": "#059669",
      "light": "#A7F3D0",
      "veryLight": "#D1FAE5",
      "description": "Growth, renewal, skill development",
      "apps": ["dna", "training"]
    }
  },

  "apps": {
    "mainsite": {
      "phase": "learn",
      "primary": "#E54D4D",
      "dark": "#C73E3E",
      "light": "#FEE2E2",
      "veryLight": "#FEF2F2",
      "gradient": "linear-gradient(135deg, #E54D4D 0%, #C73E3E 100%)",
      "shadow": "0 4px 14px rgba(229, 77, 77, 0.25)"
    },
    "tips": {
      "phase": "learn",
      "primary": "#F87171",
      "dark": "#EF4444",
      "light": "#FECACA",
      "veryLight": "#FEE2E2",
      "gradient": "linear-gradient(135deg, #F87171 0%, #EF4444 100%)",
      "shadow": "0 4px 14px rgba(248, 113, 113, 0.25)",
      "categories": {
        "1": { "color": "#991B1B", "name": "Fundamentals" },
        "2": { "color": "#B91C1C", "name": "Engagement" },
        "3": { "color": "#DC2626", "name": "Facilitation" },
        "4": { "color": "#EF4444", "name": "Difficult Moments" },
        "5": { "color": "#F87171", "name": "Activities" },
        "6": { "color": "#FCA5A5", "name": "Reflection" }
      }
    },
    "podcasts": {
      "phase": "learn",
      "primary": "#BE123C",
      "dark": "#9F1239",
      "light": "#FECDD3",
      "veryLight": "#FFE4E6",
      "gradient": "linear-gradient(135deg, #BE123C 0%, #9F1239 100%)",
      "shadow": "0 4px 14px rgba(190, 18, 60, 0.25)",
      "platforms": {
        "spotify": "#1DB954",
        "apple": "#FC3C44",
        "amazon": "#FF9900",
        "youtube": "#FF0000"
      }
    },
    "planner": {
      "phase": "plan",
      "primary": "#0284C7",
      "dark": "#075985",
      "light": "#BAE6FD",
      "veryLight": "#E0F2FE",
      "accent": "#F0F9FF",
      "gradient": "linear-gradient(135deg, #0284C7 0%, #075985 100%)",
      "shadow": "0 4px 14px rgba(2, 132, 199, 0.25)",
      "bodyClass": "planner-page",
      "scopeSelector": ".planner-page"
    },
    "coach": {
      "phase": "facilitate",
      "primary": "#7C4DFF",
      "dark": "#6D28D9",
      "light": "#DDD6FE",
      "veryLight": "#EDE9FE",
      "gradient": "linear-gradient(135deg, #7C4DFF 0%, #6D28D9 100%)",
      "shadow": "0 4px 14px rgba(124, 77, 255, 0.25)",
      "modes": {
        "prep": "#A78BFA",
        "facilitate": "#8B5CF6",
        "synthesize": "#7C3AED",
        "debrief": "#6D28D9"
      },
      "ui": {
        "bg": "#FFFBF8",
        "surface": "#FFFFFF",
        "border": "#E8ECF1"
      }
    },
    "intervention": {
      "phase": "facilitate",
      "primary": "#7C4DFF",
      "dark": "#5B21B6",
      "light": "#DDD6FE",
      "veryLight": "#EDE9FE",
      "gradient": "linear-gradient(135deg, #7C4DFF 0%, #5B21B6 100%)",
      "shadow": "0 4px 14px rgba(124, 77, 255, 0.25)",
      "categories": {
        "1": { "color": "#4C1D95", "name": "Energy & Engagement" },
        "2": { "color": "#5B21B6", "name": "Conflict & Tension" },
        "3": { "color": "#6D28D9", "name": "Participation" },
        "4": { "color": "#7C3AED", "name": "Time & Pacing" },
        "5": { "color": "#8B5CF6", "name": "Focus & Clarity" },
        "6": { "color": "#A78BFA", "name": "Connection & Trust" }
      }
    },
    "facilitator": {
      "phase": "facilitate",
      "primary": "#7C3AED",
      "dark": "#6D28D9",
      "light": "#DDD6FE",
      "veryLight": "#EDE9FE",
      "gradient": "linear-gradient(160deg, #1a0533 0%, #2d1059 40%, #4c1d95 100%)",
      "shadow": "0 4px 14px rgba(124, 58, 237, 0.25)"
    },
    "dna": {
      "phase": "reflect",
      "primary": "#34D399",
      "dark": "#10B981",
      "light": "#6EE7B7",
      "veryLight": "#A7F3D0",
      "gradient": "linear-gradient(135deg, #34D399 0%, #10B981 100%)",
      "shadow": "0 4px 14px rgba(52, 211, 153, 0.25)",
      "categories": {
        "1": { "color": "#047857", "name": "Strengths" },
        "2": { "color": "#059669", "name": "Growth Areas" },
        "3": { "color": "#10B981", "name": "Style" },
        "4": { "color": "#34D399", "name": "History" },
        "5": { "color": "#6EE7B7", "name": "Goals" }
      }
    },
    "training": {
      "phase": "reflect",
      "primary": "#10B981",
      "dark": "#059669",
      "light": "#A7F3D0",
      "veryLight": "#D1FAE5",
      "gradient": "linear-gradient(135deg, #10B981 0%, #059669 100%)",
      "shadow": "0 4px 14px rgba(16, 185, 129, 0.25)"
    }
  },

  "colors": {
    "semantic": {
      "success": { "base": "#22C55E", "dark": "#16A34A", "light": "#BBF7D0", "veryLight": "#DCFCE7" },
      "warning": { "base": "#F59E0B", "dark": "#D97706", "light": "#FDE68A", "veryLight": "#FEF3C7" },
      "error": { "base": "#EF4444", "dark": "#DC2626", "light": "#FECACA", "veryLight": "#FEE2E2" },
      "info": { "base": "#3B82F6", "dark": "#2563EB", "light": "#BFDBFE", "veryLight": "#DBEAFE" }
    },
    "ink": {
      "default": "#2C2416",
      "secondary": "#5C5242",
      "muted": "#78716C",
      "faint": "#A8A29E"
    },
    "backgrounds": {
      "page": "#FEF7F1",
      "pageAlt": "#FFFBF8",
      "surface": "#FFFFFF",
      "muted": "#F5F5F4",
      "subtle": "#FAFAF9"
    },
    "grays": {
      "comment": "Warm stone grays (Tailwind Stone palette)",
      "50": "#FAFAF9",
      "100": "#F5F5F4",
      "200": "#E7E5E4",
      "300": "#D6D3D1",
      "400": "#A8A29E",
      "500": "#78716C",
      "600": "#57534E",
      "700": "#44403C",
      "800": "#292524",
      "900": "#1C1917"
    },
    "navy": {
      "base": "#1A2744",
      "light": "#2E3D5C"
    },
    "text": {
      "dark": "#2C2416",
      "default": "#5C5242",
      "muted": "#78716C",
      "faint": "#A8A29E",
      "inverse": "#FFFFFF"
    }
  },

  "typography": {
    "fonts": {
      "heading": "'Fraunces', Georgia, serif",
      "body": "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"
    },
    "scale": {
      "display": { "size": "2.875rem", "px": 46, "font": "heading", "usage": "Hero/display text" },
      "h1": { "size": "2rem", "px": 32, "font": "heading" },
      "h2": { "size": "1.5rem", "px": 24, "font": "heading" },
      "h3": { "size": "1.25rem", "px": 20, "font": "heading" },
      "h4": { "size": "1.125rem", "px": 18, "font": "body" },
      "body": { "size": "1rem", "px": 16, "font": "body" },
      "ui": { "size": "0.9375rem", "px": 15, "font": "body" },
      "small": { "size": "0.875rem", "px": 14, "font": "body" },
      "meta": { "size": "0.8125rem", "px": 13, "font": "body" },
      "caption": { "size": "0.75rem", "px": 12, "font": "body" },
      "micro": { "size": "0.6875rem", "px": 11, "font": "body" },
      "nano": { "size": "0.625rem", "px": 10, "font": "body" }
    },
    "weights": {
      "normal": 400,
      "medium": 500,
      "semibold": 600,
      "bold": 700
    },
    "lineHeights": {
      "tight": 1.2,
      "snug": 1.35,
      "normal": 1.5,
      "relaxed": 1.625
    },
    "letterSpacing": {
      "tight": "-0.02em",
      "normal": "0",
      "wide": "0.025em"
    }
  },

  "spacing": {
    "baseUnit": "4px",
    "scale": {
      "0.5": "2px",
      "1": "4px",
      "1.5": "6px",
      "2": "8px",
      "2.5": "10px",
      "3": "12px",
      "3.5": "14px",
      "4": "16px",
      "4.5": "18px",
      "5": "20px",
      "6": "24px",
      "8": "32px",
      "10": "40px",
      "12": "48px",
      "16": "64px"
    }
  },

  "layout": {
    "containers": {
      "xs": "480px",
      "sm": "640px",
      "md": "768px",
      "lg": "960px",
      "xl": "1120px",
      "2xl": "1280px"
    },
    "breakpoints": {
      "mobile": "480px",
      "mobileLandscape": "640px",
      "tablet": "768px",
      "tabletLandscape": "960px",
      "desktopSm": "1120px",
      "desktop": "1280px"
    }
  },

  "borders": {
    "radius": {
      "sm": "4px",
      "md": "6px",
      "lg": "8px",
      "xl": "12px",
      "2xl": "16px",
      "full": "9999px"
    }
  },

  "shadows": {
    "xs": "0 1px 2px rgba(0, 0, 0, 0.04)",
    "sm": "0 1px 3px rgba(0, 0, 0, 0.06)",
    "md": "0 4px 6px rgba(0, 0, 0, 0.07)",
    "lg": "0 10px 15px rgba(0, 0, 0, 0.08)",
    "xl": "0 20px 25px rgba(0, 0, 0, 0.10)"
  },

  "animations": {
    "durations": {
      "fast": "150ms",
      "base": "200ms",
      "slow": "300ms",
      "enter": "300ms",
      "exit": "200ms"
    },
    "easings": {
      "default": "ease",
      "in": "cubic-bezier(0.4, 0, 1, 0.2)",
      "out": "cubic-bezier(0, 0, 0.2, 1)",
      "inOut": "cubic-bezier(0.4, 0, 0.2, 1)",
      "spring": "cubic-bezier(0.16, 1, 0.3, 1)",
      "bounce": "cubic-bezier(0.34, 1.56, 0.64, 1)"
    },
    "transitions": {
      "fast": "150ms ease",
      "base": "200ms ease",
      "slow": "300ms ease"
    }
  },

  "icons": {
    "source": "Material Symbols Outlined",
    "sizes": {
      "xs": "14px",
      "sm": "16px",
      "md": "20px",
      "lg": "24px",
      "xl": "32px",
      "2xl": "48px"
    }
  },

  "zIndex": {
    "dropdown": 100,
    "sticky": 200,
    "modalBackdrop": 400,
    "modal": 500,
    "tooltip": 600
  },

  "focus": {
    "ringColor": "rgba(2, 132, 199, 0.5)",
    "ringOffset": "2px",
    "ringWidth": "2px"
  },

  "components": {
    "_comment": "All ws_* PHP helpers from /includes/components/helpers.php. Use these instead of writing raw HTML.",
    "_css": "/includes/components/components.css",
    "_helpers": "/includes/components/helpers.php",
    "_templates": "/includes/components/*.php",

    "ws_badge": {
      "function": "ws_badge(string $text, array $options = []): string",
      "description": "Inline label/tag for metadata display",
      "options": {
        "variant": { "type": "string", "values": ["default", "duration", "category", "status", "outline"], "default": "default" },
        "size": { "type": "string", "values": ["sm", "md", "lg"], "default": "md" },
        "icon": { "type": "string", "description": "Material icon name" },
        "color": { "type": "string", "description": "Hex color for category variant" },
        "status": { "type": "string", "values": ["success", "warning", "error", "info"], "description": "For status variant" },
        "id": { "type": "string" },
        "class": { "type": "string" }
      },
      "convenience": {
        "ws_duration": "ws_duration(string $duration, bool $withIcon = true) — badge with variant=duration, icon=schedule, size=sm",
        "ws_category": "ws_category(string $category, ?string $color = null) — badge with variant=category",
        "ws_status": "ws_status(string $text, string $status = 'info') — badge with variant=status"
      }
    },

    "ws_button": {
      "function": "ws_button(string $text, array $options = []): string",
      "description": "Primary interactive element for actions",
      "options": {
        "variant": { "type": "string", "values": ["primary", "secondary", "ghost", "danger", "outline"], "default": "primary" },
        "size": { "type": "string", "values": ["sm", "md", "lg"], "default": "md" },
        "icon": { "type": "string", "description": "Material icon name" },
        "iconPosition": { "type": "string", "values": ["left", "right"], "default": "left" },
        "href": { "type": "string", "description": "Makes button an <a> tag" },
        "type": { "type": "string", "values": ["button", "submit", "reset"], "default": "button" },
        "disabled": { "type": "bool", "default": false },
        "loading": { "type": "bool", "default": false },
        "fullWidth": { "type": "bool", "default": false },
        "id": { "type": "string" },
        "class": { "type": "string" },
        "attrs": { "type": "array", "description": "Key-value pairs for additional HTML attributes" }
      },
      "convenience": {
        "ws_icon_button": "ws_icon_button(string $icon, array $options = []) — icon-only button with variant=ghost, size=sm"
      }
    },

    "ws_input": {
      "function": "ws_input(string $name, array $options = []): string",
      "description": "Form text input field with label, validation, and helper text",
      "options": {
        "type": { "type": "string", "values": ["text", "email", "password", "number", "url", "tel", "search", "date", "time"], "default": "text" },
        "label": { "type": "string" },
        "placeholder": { "type": "string" },
        "value": { "type": "string" },
        "required": { "type": "bool", "default": false },
        "disabled": { "type": "bool", "default": false },
        "error": { "type": "string", "description": "Error message (activates error state)" },
        "helper": { "type": "string", "description": "Helper text below field" },
        "icon": { "type": "string", "description": "Material icon name" },
        "iconPosition": { "type": "string", "values": ["left", "right"], "default": "left" },
        "size": { "type": "string", "values": ["sm", "md", "lg"], "default": "md" },
        "id": { "type": "string" },
        "class": { "type": "string" },
        "attrs": { "type": "array" }
      }
    },

    "ws_select": {
      "function": "ws_select(string $name, array $selectOptions, array $options = []): string",
      "description": "Dropdown select field",
      "params": {
        "selectOptions": "Associative array of value => label pairs"
      },
      "options": {
        "label": { "type": "string" },
        "value": { "type": "string", "description": "Pre-selected value" },
        "placeholder": { "type": "string" },
        "required": { "type": "bool", "default": false },
        "disabled": { "type": "bool", "default": false },
        "error": { "type": "string" },
        "id": { "type": "string" },
        "class": { "type": "string" }
      }
    },

    "ws_card": {
      "function": "ws_card(string $content, array $options = []): string",
      "description": "Content container with optional link, hover, and elevation",
      "alternatives": {
        "ws_card_start / ws_card_end": "For wrapping arbitrary PHP/HTML content between card open/close tags"
      },
      "options": {
        "variant": { "type": "string", "values": ["content", "interactive", "flat"], "default": "content" },
        "hoverable": { "type": "bool", "default": false },
        "elevated": { "type": "bool", "default": false },
        "bordered": { "type": "bool", "default": false },
        "tag": { "type": "string", "default": "div", "description": "HTML tag (auto-set to 'a' if href provided)" },
        "href": { "type": "string" },
        "id": { "type": "string" },
        "class": { "type": "string" },
        "attrs": { "type": "array" }
      }
    },

    "ws_modal": {
      "function": "ws_modal(string $content, array $options = []): string",
      "description": "Dialog overlay for forms, confirmations, and detail views",
      "alternatives": {
        "ws_modal_start / ws_modal_end": "For wrapping arbitrary PHP/HTML content between modal open/close tags"
      },
      "options": {
        "id": { "type": "string", "required": true },
        "title": { "type": "string" },
        "size": { "type": "string", "values": ["sm", "md", "lg", "xl", "full"], "default": "md" },
        "variant": { "type": "string", "values": ["default", "danger", "branded"], "default": "default" },
        "closable": { "type": "bool", "default": true },
        "backdrop": { "type": "bool", "default": true },
        "headerColor": { "type": "string", "description": "CSS color for header background" },
        "class": { "type": "string" },
        "attrs": { "type": "array" }
      },
      "related": {
        "ws_modal_footer": "ws_modal_footer(array $options) — standardized button layout for modal footers. Options: cancel (string), primary (string|array), left (string)"
      }
    },

    "ws_tabs": {
      "function": "ws_tabs(array $items, array $options = []): string",
      "description": "Tab navigation for switching content panels",
      "params": {
        "items": "Array of {id, label, icon?, count?, active?, disabled?, gated?}"
      },
      "options": {
        "id": { "type": "string" },
        "variant": { "type": "string", "values": ["default", "pills", "underline"], "default": "default" },
        "size": { "type": "string", "values": ["sm", "md"], "default": "md" },
        "scrollable": { "type": "bool", "default": false },
        "class": { "type": "string" }
      }
    },

    "ws_accordion": {
      "function": "ws_accordion(array $items, array $options = []): string",
      "description": "Expandable content sections",
      "params": {
        "items": "Array of {title, content, open?, icon?}"
      },
      "options": {
        "id": { "type": "string" },
        "multiple": { "type": "bool", "default": false, "description": "Allow multiple panels open at once" },
        "variant": { "type": "string", "values": ["default", "bordered", "flush"], "default": "default" },
        "size": { "type": "string", "values": ["sm", "md"], "default": "md" },
        "class": { "type": "string" }
      }
    },

    "ws_alert": {
      "function": "ws_alert(string $message, array $options = []): string",
      "description": "Contextual feedback message",
      "options": {
        "variant": { "type": "string", "values": ["info", "success", "warning", "error"], "default": "info" },
        "title": { "type": "string" },
        "icon": { "type": "string", "description": "Material icon name" },
        "dismissible": { "type": "bool", "default": false },
        "bordered": { "type": "bool", "default": false },
        "filled": { "type": "bool", "default": false },
        "actions": { "type": "string", "description": "Action button HTML" },
        "id": { "type": "string" },
        "class": { "type": "string" },
        "attrs": { "type": "array" }
      }
    },

    "ws_progress": {
      "function": "ws_progress(int|float $value, array $options = []): string",
      "description": "Progress bar with optional label",
      "options": {
        "variant": { "type": "string", "values": ["default", "success", "warning", "error", "brand"], "default": "default" },
        "size": { "type": "string", "values": ["sm", "md", "lg"], "default": "md" },
        "label": { "type": "string" },
        "showValue": { "type": "bool", "default": false },
        "striped": { "type": "bool", "default": false },
        "animated": { "type": "bool", "default": false },
        "indeterminate": { "type": "bool", "default": false },
        "id": { "type": "string" },
        "class": { "type": "string" },
        "attrs": { "type": "array" }
      }
    },

    "ws_avatar": {
      "function": "ws_avatar(string $name, array $options = []): string",
      "description": "User avatar with initials fallback",
      "options": {
        "image": { "type": "string", "description": "Image URL" },
        "size": { "type": "string", "values": ["xs", "sm", "md", "lg", "xl"], "default": "md" },
        "color": { "type": "string", "description": "Background color for initials" },
        "ring": { "type": "bool", "default": false },
        "status": { "type": "string", "values": ["online", "offline", "busy"], "description": "Status indicator dot" },
        "id": { "type": "string" },
        "class": { "type": "string" },
        "attrs": { "type": "array" }
      }
    },

    "ws_hero": {
      "function": "ws_hero(string $title, string $accent = '', array $options = []): string",
      "description": "Full-width hero section with badge, title, subtitle, buttons, stats, and optional image",
      "options": {
        "badge": { "type": "string", "description": "Badge text above title" },
        "badgeIcon": { "type": "string", "description": "Material icon in badge" },
        "subtitle": { "type": "string", "description": "Description paragraph below title" },
        "buttons": { "type": "array", "description": "Array of button HTML strings (use ws_button())" },
        "stats": { "type": "array", "description": "Array of {value, label} items" },
        "statColor": { "type": "string", "default": "#E54D4D" },
        "image": { "type": "string", "description": "Image URL for hero visual" },
        "imageAlt": { "type": "string" },
        "id": { "type": "string" },
        "class": { "type": "string" }
      }
    },

    "ws_banner": {
      "function": "ws_banner(string $message, array $options = []): string",
      "description": "Full-width announcement/promotional banner",
      "options": {
        "variant": { "type": "string", "values": ["default", "brand", "success", "warning", "dark"], "default": "default" },
        "icon": { "type": "string" },
        "action": { "type": "string", "description": "Action link text" },
        "href": { "type": "string" },
        "onclick": { "type": "string", "description": "JS onclick handler" },
        "dismissible": { "type": "bool", "default": false },
        "centered": { "type": "bool", "default": true },
        "id": { "type": "string" },
        "class": { "type": "string" }
      }
    },

    "ws_section_header": {
      "function": "ws_section_header(string $title, array $options = []): string",
      "description": "Centered section heading with optional subtitle, description, and label",
      "options": {
        "subtitle": { "type": "string", "description": "Secondary heading (italic, brand color)" },
        "description": { "type": "string", "description": "Paragraph below heading" },
        "tag": { "type": "string", "values": ["h2", "h3"], "default": "h2" },
        "align": { "type": "string", "values": ["left", "center"], "default": "center" },
        "label": { "type": "string", "description": "Small label above heading" },
        "id": { "type": "string" },
        "class": { "type": "string" }
      }
    },

    "ws_feature_card": {
      "function": "ws_feature_card(string $title, string $description, array $options = []): string",
      "description": "Icon + title + description card for feature/benefit lists",
      "options": {
        "icon": { "type": "string", "description": "Material icon name (rendered via icon() helper)" },
        "svg": { "type": "string", "description": "Raw SVG string (alternative to icon)" },
        "variant": { "type": "string", "values": ["default", "compact", "coming-soon"], "default": "default" },
        "href": { "type": "string", "description": "Makes card a link" },
        "id": { "type": "string" },
        "class": { "type": "string" },
        "attrs": { "type": "array" }
      }
    },

    "ws_level_up_grid": {
      "function": "ws_level_up_grid(array $options = []): string",
      "description": "Cross-promotional grid of all Workshopr apps grouped by facilitation phase (Learn, Plan, Facilitate, Reflect). Used on landing pages to drive users across the ecosystem. Phase colors applied automatically per card.",
      "options": {
        "current_app": { "type": "string", "description": "App key to exclude from the grid (e.g., 'intervention', 'planner', 'tips')" },
        "eyebrow": { "type": "string", "default": "More from Workshopr", "description": "Small label above the section title" },
        "title": { "type": "string", "default": "Level Up Your Facilitation", "description": "Section heading" },
        "apps": { "type": "array", "description": "Override the built-in app catalog" },
        "id": { "type": "string" },
        "class": { "type": "string" }
      },
      "app_catalog": {
        "learn": ["library", "academy", "podcasts"],
        "plan": ["planner", "hybrid"],
        "facilitate": ["facilitator", "sidekick", "intervention", "tips"],
        "reflect": ["dna", "coach", "roi"]
      }
    },

    "ws_stat": {
      "function": "ws_stat(string $value, string $label, array $options = []): string",
      "description": "Single stat display with value and label",
      "options": {
        "color": { "type": "string", "description": "Value color (hex or CSS var)" },
        "icon": { "type": "string" },
        "id": { "type": "string" },
        "class": { "type": "string" }
      },
      "related": {
        "ws_stats": "ws_stats(array $stats, array $options = []) — group of stats with dividers. Stats: [{value, label, color?}]"
      }
    },

    "ws_empty_state": {
      "function": "ws_empty_state(string $title, array $options = []): string",
      "description": "Placeholder for empty content areas",
      "options": {
        "description": { "type": "string" },
        "icon": { "type": "string", "default": "inbox" },
        "action": { "type": "string", "description": "Action button text" },
        "actionHref": { "type": "string" },
        "actionVariant": { "type": "string", "default": "primary" },
        "id": { "type": "string" },
        "class": { "type": "string" }
      }
    },

    "ws_breadcrumb": {
      "function": "ws_breadcrumb(array $items, array $options = []): string",
      "description": "Navigation breadcrumb trail",
      "params": {
        "items": "Array of {label, href?}. Last item should have no href."
      },
      "options": {
        "id": { "type": "string" },
        "class": { "type": "string" },
        "separator": { "type": "string", "default": "/" }
      }
    },

    "ws_checklist": {
      "function": "ws_checklist(array $items, array $options = []): string",
      "description": "List with check icons for feature lists and requirements",
      "params": {
        "items": "Array of checklist item strings"
      },
      "options": {
        "icon": { "type": "string", "default": "check_circle" },
        "variant": { "type": "string", "values": ["default", "compact"], "default": "default" },
        "id": { "type": "string" },
        "class": { "type": "string" }
      }
    },

    "ws_skeleton": {
      "function": "ws_skeleton(array $options = []): string",
      "description": "Loading placeholder skeleton",
      "options": {
        "variant": { "type": "string", "values": ["text", "circle", "rect", "card"], "default": "text" },
        "width": { "type": "string" },
        "height": { "type": "string" },
        "lines": { "type": "int", "default": 1, "description": "Number of text lines" },
        "id": { "type": "string" },
        "class": { "type": "string" }
      }
    },

    "ws_toast_container": {
      "function": "ws_toast_container(): string",
      "description": "Toast notification container (call once in page footer). Toasts triggered via JS: wsToast('message', 'success')"
    },

    "ws_tooltip": {
      "function": "ws_tooltip(string $text, array $options = []): string",
      "description": "Tooltip attributes to add to an element",
      "options": {
        "position": { "type": "string", "values": ["top", "bottom", "left", "right"], "default": "top" },
        "variant": { "type": "string", "values": ["default", "dark"], "default": "default" },
        "arrow": { "type": "bool", "default": true }
      }
    },

    "ws_form_row": {
      "function": "ws_form_row(string $content, array $options = []): string",
      "description": "Form field wrapper with label, helper text, and error state",
      "options": {
        "label": { "type": "string" },
        "required": { "type": "bool", "default": false },
        "helper": { "type": "string" },
        "error": { "type": "string" },
        "inline": { "type": "bool", "default": false, "description": "Horizontal label + field layout" },
        "columns": { "type": "int", "description": "Grid columns this row spans" },
        "id": { "type": "string" },
        "class": { "type": "string" }
      }
    },

    "ws_prompt_select": {
      "function": "ws_prompt_select(string $label, string $name, array $selectOptions, array $opts = []): string",
      "description": "Inline prompt + select dropdown (e.g. 'I need help with [Goal...]')",
      "options": {
        "value": { "type": "string" },
        "onchange": { "type": "string" },
        "variant": { "type": "string" },
        "id": { "type": "string" },
        "class": { "type": "string" }
      }
    },

    "ws_chip_input": {
      "function": "ws_chip_input(string $name, array $options = []): string",
      "description": "Email/tag input with add/remove chip functionality",
      "options": {
        "label": { "type": "string" },
        "placeholder": { "type": "string" },
        "type": { "type": "string", "default": "email" },
        "addIcon": { "type": "string" },
        "addText": { "type": "string" },
        "removeIcon": { "type": "string" },
        "id": { "type": "string" },
        "class": { "type": "string" },
        "attrs": { "type": "array" }
      }
    },

    "ws_radio_card_group": {
      "function": "ws_radio_card_group(string $name, array $items, array $options = []): string",
      "description": "Card-style radio selector grid",
      "params": {
        "items": "Array of {value, label, icon?, description?, checked?, disabled?}"
      },
      "options": {
        "label": { "type": "string" },
        "columns": { "type": "int" },
        "id": { "type": "string" },
        "class": { "type": "string" }
      }
    },

    "ws_checkbox_card_group": {
      "function": "ws_checkbox_card_group(array $items, array $options = []): string",
      "description": "Toggle switch list with icons",
      "params": {
        "items": "Array of {id, title, description?, icon?, iconColor?, checked?, highlight?}"
      },
      "options": {
        "label": { "type": "string" },
        "id": { "type": "string" },
        "class": { "type": "string" }
      }
    },

    "ws_listing_card": {
      "function": "ws_listing_card(array $card): string",
      "description": "Content listing card (exercise, workshop, etc.) from prepareCardData()"
    },

    "ws_suggestion_card": {
      "function": "ws_suggestion_card(array $options): string",
      "description": "Activity recommendation card with add button",
      "options": {
        "id": { "type": "string" },
        "name": { "type": "string" },
        "type": { "type": "string" },
        "duration": { "type": "string" },
        "category": { "type": "string" },
        "reason": { "type": "string" },
        "icon": { "type": "string" },
        "class": { "type": "string" }
      }
    },

    "ws_activity_badge": {
      "function": "ws_activity_badge(string $type, array $options = []): string",
      "description": "Activity type badge (exercise/icebreaker/break/custom)",
      "params": {
        "type": "exercise | icebreaker | break | custom"
      },
      "options": {
        "text": { "type": "string" },
        "size": { "type": "string", "values": ["sm", "md"], "default": "md" },
        "id": { "type": "string" },
        "class": { "type": "string" }
      }
    },

    "ws_energy_arc_card": {
      "function": "ws_energy_arc_card(array $options = []): string",
      "description": "Session retrospective card for the Coach/Facilitator apps. Renders an eyebrow header (label + progress + status), a score with interpretive tinted-pill badge, a sparkline chart with time-axis labels, and a 2x2 grid of fixed-width bar-fill metrics. Light (canonical) and dark themes. Max width 340px.",
      "options": {
        "showHeader": { "type": "bool", "default": true, "description": "Set false when hosting the card inside a section that provides its own title (e.g. ws_planner_inspector_rail)." },
        "eyebrow":    { "type": "string", "default": "Energy Arc" },
        "timeUsed":   { "type": "string", "description": "Muted top-middle text, e.g. '8 of 8h used'" },
        "status":     { "type": "array", "shape": { "text": "string", "type": "success|warning|danger|info|neutral" } },
        "score":      { "type": "int", "range": "0..scoreMax" },
        "scoreMax":   { "type": "int", "default": 100 },
        "scoreBadge": { "type": "array", "shape": { "text": "string", "type": "success|warning|danger|info|neutral", "variant": "pill|note (default: pill)" } },
        "chartData":  { "type": "array", "shape": "[{time: string, value: 0..100}]" },
        "timeLabels": { "type": "array", "description": "x-axis tick labels rendered evenly below the chart" },
        "metrics":    { "type": "array", "shape": "[{label, value, fill 0..100, barColor?}]", "max": 4 },
        "theme":      { "type": "string", "values": ["light", "dark"], "default": "light" },
        "accent":     { "type": "string", "description": "Override accent color" },
        "id":         { "type": "string" },
        "class":      { "type": "string" },
        "attrs":      { "type": "array" }
      }
    },

    "ws_planner_activity_inspector": {
      "function": "ws_planner_activity_inspector(array $options = []): string",
      "description": "Right-column rail in the Workshop Planner — selected-activity mode. Sibling of ws_planner_inspector_rail; shares the visual shell but surfaces activity-specific sections (identity, overview, energy impact, logistics, facilitator notes, when-it-runs, and actions). Render this when the user has an agenda item selected; render ws_planner_inspector_rail otherwise.",
      "options": {
        "type":        { "type": "string", "values": ["exercise", "icebreaker", "break", "custom"], "default": "exercise", "description": "Drives the left-border stripe, energy-bar fill, net-badge tint, bullet color, note rule, and button hover." },
        "duration":    { "type": "string", "description": "Composed into the eyebrow, e.g. '60 min'" },
        "groupSize":   { "type": "string", "description": "Composed into the eyebrow, e.g. '6–12 ppl'" },
        "title":       { "type": "string", "description": "Activity title (required)" },
        "tags":        { "type": "array", "description": "Small tag strings rendered under the title in mono uppercase" },
        "closable":    { "type": "bool", "default": true, "description": "Show the × close control" },
        "overview":    { "type": "string", "description": "Description paragraph in the display/serif font. Doubles as the Overview tab body when instructions are provided." },
        "instructions": { "type": "array|string|null", "description": "Step-by-step facilitator instructions. Array of strings renders as a numbered list; string is rendered as HTML (caller owns markup). When present, the Overview section becomes a tabbed panel: Overview · Instructions." },
        "activeTab":   { "type": "string", "values": ["overview", "instructions"], "default": "overview", "description": "Which tab renders active on first paint." },
        "energy":      { "type": "array|null", "shape": { "net": "string (e.g. '+16')", "dimensions": "[{label, delta, fill 0..100}]" } },
        "logistics":   { "type": "array", "description": "String bullets rendered in a 2-col mono grid" },
        "notes":       { "type": "array|null", "shape": { "body": "string", "author": "string", "date": "string", "canAdd": "bool" } },
        "context":     { "type": "array|null", "shape": { "time": "string", "description": "string" } },
        "actions":     { "type": "array", "description": "Primary action row: [{label, icon?, action, href?}]. Grid auto-divides into equal columns." },
        "destructive": { "type": "array|null", "description": "Single destructive action, rendered full-width below the primary row." },
        "id":    { "type": "string" },
        "class": { "type": "string" },
        "attrs": { "type": "array" }
      }
    },

    "ws_planner_inspector_rail": {
      "function": "ws_planner_inspector_rail(array $options = []): string",
      "description": "Right-column inspector sidebar inside the Workshop Planner — default mode. Three opinionated sections: Energy (wraps ws_energy_arc_card), Coach suggests (list of icon+eyebrow+line+meta items), and Facilitators (avatar stack + presence blurb). Each section is optional. The Energy section auto-sets showHeader=false on the wrapped card and defaults the score-badge variant to 'note'. Render ws_planner_activity_inspector instead when the user has an agenda item selected.",
      "options": {
        "energy": {
          "type": "array|null",
          "shape": { "title": "string", "meta": "string", "card": "ws_energy_arc_card options" }
        },
        "coach": {
          "type": "array|null",
          "shape": { "title": "string", "meta": "string", "items": "[{icon, pre, line (HTML allowed for <em>), meta, action, href?}]" }
        },
        "facilitators": {
          "type": "array|null",
          "shape": { "title": "string", "meta": "string", "avatars": "[{initials, bg}]", "presence": "{name, status}" }
        },
        "id":    { "type": "string" },
        "class": { "type": "string" },
        "attrs": { "type": "array" }
      }
    },

    "ws_planner_library_rail": {
      "function": "ws_planner_library_rail(array $options = []): string",
      "description": "Left-column sidebar inside the Workshop Planner. Composes search, an optional top-level categories nav, one or more stacked sections (each optionally collapsible with an icon, and either a flat item list, an onboarding 'instructions' block, or a filter + category-buttons grid that drills into items via app-level JS), and an optional footer CTA. Every activity item is rendered via ws_planner_card (size=sm). Designed for v1 planner parity — see /planner/app2.php for the full adoption.",
      "options": {
        "search":     { "type": "array|null", "shape": { "placeholder": "string", "kbd": "string", "name": "string", "value": "string" } },
        "categories": { "type": "array|null", "shape": { "title": "string", "count": "string", "items": "[{label,color,count?,active?,href?,id?}]" } },
        "sections":   {
          "type": "array",
          "shape": "[{title, meta?, icon?, kind? ('items'|'instructions'), collapsible?, defaultOpen?, filter? {name,options [{value,label,selected?}]}, categoryButtons? [{id,name,icon?,count?,type?}], items: [ws_planner_card options | {icon,body} for instructions], showMore?, id?}]"
        },
        "footer":     { "type": "array|null", "shape": { "label": "string", "button": { "text": "string", "icon": "string", "id": "string", "action?": "string", "href?": "string" } } },
        "id":         { "type": "string" },
        "class":      { "type": "string" },
        "attrs":      { "type": "array" }
      }
    },

    "ws_planner_card": {
      "function": "ws_planner_card(string $title, array $options = []): string",
      "description": "Agenda/timeline card used in the Workshop Planner (exercise/icebreaker/break/custom). Available in lg (timeline) and sm (palette) sizes with default/selected/disabled states. SM cards surface a swap icon on hover (and on focus-within / touch devices); disabled SM cards never reveal it. SM accepts an optional meta subtitle (e.g. '6-12 ppl') rendered under the title.",
      "params": {
        "title": "string — card title"
      },
      "options": {
        "type": { "type": "string", "values": ["exercise", "icebreaker", "break", "custom"], "default": "exercise" },
        "duration": { "type": "string|int", "description": "e.g. '60m' or integer minutes" },
        "size": { "type": "string", "values": ["lg", "sm"], "default": "lg" },
        "state": { "type": "string", "values": ["default", "selected", "disabled"], "default": "default" },
        "draggable": { "type": "bool", "default": false, "description": "Show drag handle (lg only)" },
        "actions": { "type": "array", "description": "Action keys: swap, delete, edit (lg only)" },
        "meta": { "type": "string", "description": "Secondary line (sm only), e.g. '6-12 ppl'" },
        "href": { "type": "string" },
        "id": { "type": "string" },
        "class": { "type": "string" },
        "attrs": { "type": "array" }
      }
    },

    "ws_results_overlay": {
      "function": "ws_results_overlay(array $options): string",
      "description": "Operation outcome display panel",
      "options": {
        "id": { "type": "string" },
        "variant": { "type": "string" },
        "title": { "type": "string" },
        "icon": { "type": "string" },
        "buttonText": { "type": "string" },
        "buttonId": { "type": "string" },
        "listId": { "type": "string" },
        "class": { "type": "string" }
      }
    },

    "ws_audio_recorder": {
      "function": "ws_audio_recorder(array $options = []): string",
      "description": "Voice note capture via MediaRecorder API",
      "options": {
        "id": { "type": "string" },
        "entity_type": { "type": "string" },
        "entity_id": { "type": "string" },
        "class": { "type": "string" },
        "attrs": { "type": "array" }
      }
    },

    "ws_audio_player": {
      "function": "ws_audio_player(string $src, array $options = []): string",
      "description": "Voice note playback component",
      "options": {
        "duration": { "type": "string" },
        "label": { "type": "string" },
        "note_id": { "type": "string" },
        "deletable": { "type": "bool", "default": false },
        "id": { "type": "string" },
        "class": { "type": "string" },
        "attrs": { "type": "array" }
      }
    }
  },

  "rules": {
    "_comment": "Mandatory constraints for all AI-assisted development on this project",

    "componentFirst": {
      "rule": "ALWAYS use ws_* components before writing raw HTML",
      "detail": "Before creating any button, input, modal, card, badge, alert, or other UI element, check if a ws_* helper exists. If it does, use it. If it doesn't, suggest creating one.",
      "severity": "mandatory",
      "checkCommand": "grep 'function ws_' /includes/components/helpers.php"
    },

    "tokenFirst": {
      "rule": "ALWAYS use platform tokens for all styling",
      "detail": "Colors, spacing, typography, radii, shadows — use CSS variables from /design-system/platform-tokens.css. Never hardcode hex colors or pixel values when a token exists.",
      "severity": "mandatory",
      "source": "/design-system/platform-tokens.css",
      "examples": {
        "do": ["var(--space-4)", "var(--text-primary)", "var(--radius-lg)", "var(--shadow-md)", "var(--font-heading)"],
        "dont": ["16px", "#1E1E26", "8px", "0 4px 6px rgba(0,0,0,0.07)", "'Fraunces'"]
      }
    },

    "phaseColors": {
      "rule": "Each app MUST use its phase color — never mix phases",
      "detail": "Planner = blue (#0284C7), Coach/Facilitator = purple (#7C4DFF/#7C3AED), Mainsite = red (#E54D4D), DNA/Training = green (#10B981). Using red in planner or blue in coach is a bug.",
      "severity": "mandatory",
      "mapping": {
        "learn": { "color": "#E54D4D", "apps": ["mainsite", "tips", "podcasts"] },
        "plan": { "color": "#0284C7", "apps": ["planner"] },
        "facilitate": { "color": "#7C4DFF", "apps": ["coach", "intervention", "facilitator"] },
        "reflect": { "color": "#10B981", "apps": ["dna", "training"] }
      }
    },

    "appScopedOverrides": {
      "rule": "App-specific component overrides MUST use the app's body class scope",
      "detail": "Planner uses body class 'planner-page' with CSS scope '.planner-page'. This ensures ws_* components adapt to the app's phase color without affecting other apps.",
      "severity": "mandatory",
      "apps": {
        "planner": {
          "bodyClass": "planner-page",
          "cssScope": ".planner-page",
          "bridgeFile": "/planner/css/components/_component-bridge.css",
          "overrides": [
            ".planner-page .ws-btn--primary uses planner gradient",
            ".planner-page .ws-btn--primary icons must be white",
            ".planner-page .ws-btn--secondary uses planner-primary blue",
            ".planner-page .ws-input:focus uses planner-primary border"
          ]
        }
      }
    },

    "iconLibrary": {
      "rule": "Use Material Symbols Outlined for ALL icons",
      "detail": "Never use Font Awesome, Heroicons, SVG icon sets, or emoji as icons. All icons come from Google Material Symbols Outlined with the standard optical size 24, weight 400, FILL 0, GRAD 0.",
      "severity": "mandatory",
      "cdn": "https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0",
      "helper": "icon(string $name) from /includes/icon.php renders the <span> tag"
    },

    "typography": {
      "rule": "Headings use Fraunces, body uses Inter (or Source Sans 3 for older pages)",
      "detail": "All heading elements (h1-h3, card titles, hero text) use var(--font-heading) = Fraunces. Body text, labels, buttons use var(--font-body) = Inter. Never use system fonts directly.",
      "severity": "mandatory"
    },

    "noFrameworks": {
      "rule": "Vanilla JS and CSS only — no React, Vue, Tailwind, or CSS frameworks",
      "detail": "The frontend is intentionally framework-free. Do not introduce npm-based UI frameworks, CSS utility frameworks, or JS component libraries unless explicitly requested.",
      "severity": "mandatory"
    },

    "newComponentProcess": {
      "rule": "New UI patterns go in the design system, not inline",
      "detail": "If you need UI that doesn't exist as a ws_* component: 1) Create the PHP function in /includes/components/helpers.php, 2) Create the template in /includes/components/, 3) Add CSS to /includes/components/components.css, 4) Add a demo page in /design-system/components/, 5) Then use it in the app.",
      "severity": "mandatory"
    },

    "databaseAccess": {
      "rule": "All database queries MUST use PDO prepared statements",
      "detail": "Never concatenate user input into SQL strings. Always use parameterized queries with $pdo->prepare() and $stmt->execute().",
      "severity": "mandatory"
    },

    "cssArchitecture": {
      "rule": "Follow the established CSS architecture for each app",
      "globalFiles": {
        "tokens": "/design-system/platform-tokens.css",
        "components": "/includes/components/components.css",
        "listingRedesign": "/css/listing-redesign.css",
        "detailFieldguide": "/css/detail-fieldguide.css"
      },
      "appFiles": {
        "planner": {
          "variables": "/planner/css/base/_variables.css",
          "main": "/planner/css/planner-v2.css",
          "bridge": "/planner/css/components/_component-bridge.css"
        },
        "facilitator": {
          "main": "/css/facilitator/facilitator.css",
          "participant": "/css/facilitator/participant.css",
          "summary": "/css/facilitator/summary.css"
        },
        "coach": {
          "main": "/coach/css/coach.css"
        },
        "library": {
          "landing": "/css/library/library-landing.css",
          "collections": "/css/library/library-collections.css",
          "goals": "/css/library/library-goals.css",
          "shared": "/css/listing-redesign.css",
          "detail": "/css/detail-fieldguide.css"
        }
      }
    },

    "globalHeader": {
      "rule": "Use the unified global header component for all app pages",
      "detail": "Include /includes/global-header.php with the appropriate property: library, planner, coach, intervention, tips, podcasts, dna, academy.",
      "file": "/includes/global-header.php"
    },

    "writingStyle": {
      "rule": "All user-facing content must follow the Workshopr writing style guide",
      "file": "/content/workshopr_writing_style_guide.md",
      "severity": "mandatory"
    },

    "designSystemUpdates": {
      "rule": "When CSS changes are made, update the design system documentation",
      "detail": "Update relevant files in /design-system/ and add a note to the change-log.",
      "severity": "recommended"
    }
  }
}