{
  "version": "3.2",
  "source": "588 Elementor Template Kits \u2014 254,465 widgets across 10,624 JSON files + real-world conversion learnings from client landing pages (Bodystyle Fitness, Hall Brothers, Hypnotherapy, AMWL)",
  "generated": "2026-03-24",
  "stats": "19 section types, 48 builder methods, 29 layout variants",
  "widget_reference": {
    "_note": "Every setting uses Elementor's standard value types: dimension({unit,size,sizes}), spacing({unit,top,right,bottom,left,isLinked}), media({url,id,alt}), icon({value,library}). Responsive overrides: append _mobile or _tablet to any setting key.",
    "_value_types": {
      "dimension": {
        "unit": "px",
        "size": 20,
        "sizes": []
      },
      "spacing": {
        "unit": "px",
        "top": "10",
        "right": "10",
        "bottom": "10",
        "left": "10",
        "isLinked": true
      },
      "media": {
        "url": "https://...",
        "id": "",
        "alt": "description"
      },
      "icon": {
        "value": "fas fa-icon-name",
        "library": "fa-solid"
      },
      "link": {
        "url": "https://...",
        "is_external": false,
        "nofollow": false
      }
    },
    "heading": {
      "count": 73470,
      "use_for": "Section titles, hero headlines, any text heading",
      "key_settings": {
        "title": "string \u2014 the heading text",
        "header_size": "h1|h2|h3|h4|h5|h6|div|span|p",
        "align": "left|center|right",
        "title_color": "hex color",
        "typography_typography": "'custom' to enable font settings",
        "typography_font_family": "font name string",
        "typography_font_weight": "100-900 string",
        "typography_font_size": "dimension",
        "typography_font_size_mobile": "dimension (responsive)",
        "typography_letter_spacing": "dimension",
        "typography_line_height": "dimension (unit: em)",
        "typography_text_transform": "uppercase|lowercase|capitalize|none"
      },
      "helper": "heading_w($cfg, $text, $tag, $align, $color, $size, $weight, $letter_spacing, $line_height, $transform, $size_mobile)"
    },
    "text-editor": {
      "count": 30517,
      "use_for": "Body text, rich HTML content, inline-styled paragraphs",
      "key_settings": {
        "editor": "HTML string \u2014 supports <strong>, <em>, <span style=...>, etc.",
        "align": "left|center|right|justify",
        "align_mobile": "responsive alignment override",
        "text_color": "hex color",
        "typography_typography": "'custom'",
        "typography_font_family": "font name",
        "typography_font_size": "dimension",
        "typography_font_weight": "string",
        "typography_line_height": "dimension (unit: em)"
      },
      "helper": "text_w($cfg, $html, $align, $color, $size)"
    },
    "image": {
      "count": 29416,
      "use_for": "Photos, screenshots, illustrations, logos",
      "key_settings": {
        "image": "media object {url, id, alt, source: 'library'}",
        "image_size": "full|custom|medium|large|thumbnail",
        "image_custom_dimension": "{width, height} \u2014 only when image_size='custom'",
        "align": "left|center|right",
        "width": "dimension (% or px) \u2014 image display width",
        "height": "dimension \u2014 image display height",
        "object-fit": "cover|contain|fill",
        "image_border_radius": "spacing \u2014 rounded corners",
        "image_box_shadow_box_shadow_type": "'yes' to enable shadow",
        "image_box_shadow_box_shadow": "{horizontal, vertical, blur, spread, color}",
        "link": "link object \u2014 makes image clickable"
      },
      "helper": "image_w($url, $alt, $width, $radius, $shadow, $align)"
    },
    "button": {
      "count": 16906,
      "use_for": "CTAs, links, form submits",
      "key_settings": {
        "text": "button label string",
        "link": "link object {url, is_external, nofollow}",
        "align": "left|center|right",
        "size": "xs|sm|md|lg|xl",
        "selected_icon": "icon object \u2014 adds icon to button",
        "icon_align": "left|right",
        "icon_indent": "dimension \u2014 spacing between icon and text",
        "background_color": "hex \u2014 button bg color",
        "button_text_color": "hex \u2014 button text color",
        "border_border": "solid|dashed|dotted|none",
        "border_width": "spacing \u2014 border thickness",
        "border_color": "hex \u2014 border color",
        "border_radius": "spacing \u2014 rounded corners",
        "text_padding": "spacing \u2014 inner padding",
        "typography_typography": "'custom'",
        "typography_font_family": "font name",
        "typography_font_weight": "string",
        "typography_font_size": "dimension"
      },
      "helper": "btn_w($cfg, $text, $url, $bg, $text_color, $border_color, $icon, $align)"
    },
    "icon-box": {
      "count": 13674,
      "use_for": "Feature cards, service lists, info boxes \u2014 REPLACES separate icon+heading+text combo",
      "key_settings": {
        "selected_icon": "icon object",
        "title_text": "string \u2014 box title",
        "description_text": "string \u2014 box description",
        "position": "top|left|right \u2014 icon position relative to text",
        "text_align": "left|center|right",
        "view": "default|stacked|framed \u2014 icon display style",
        "shape": "circle|square \u2014 when view is stacked/framed",
        "primary_color": "hex \u2014 icon color (or bg color when stacked)",
        "secondary_color": "hex \u2014 bg color (stacked) or border color (framed)",
        "title_size": "h1-h6|div|p|span",
        "icon_size": "dimension",
        "icon_space": "dimension \u2014 gap between icon and text",
        "title_bottom_space": "dimension \u2014 gap between title and description",
        "title_color": "hex",
        "description_color": "hex",
        "title_typography_typography": "'custom'",
        "title_typography_font_family": "font name",
        "title_typography_font_weight": "string",
        "title_typography_font_size": "dimension",
        "description_typography_typography": "'custom'",
        "description_typography_font_family": "font name",
        "description_typography_font_size": "dimension",
        "description_typography_line_height": "dimension"
      },
      "helper": "icon_box_w($cfg, $icon, $title, $desc, $icon_color, $position, $view, $shape, $secondary_color, $align)"
    },
    "icon-list": {
      "count": 8940,
      "use_for": "Bullet points with icons \u2014 checkmarks, X marks, feature lists, benefit lists",
      "key_settings": {
        "icon_list": "array of {text, selected_icon: {value, library}, _id}",
        "space_between": "dimension \u2014 gap between items",
        "icon_color": "hex \u2014 icon color for all items",
        "icon_size": "dimension \u2014 icon pixel size",
        "text_color": "hex \u2014 text color for all items",
        "text_indent": "dimension \u2014 gap between icon and text",
        "typography_typography": "'custom'",
        "typography_font_family": "font name",
        "typography_font_size": "dimension",
        "typography_font_size_mobile": "dimension (responsive)",
        "typography_line_height": "dimension (unit: em)"
      },
      "helper": "icon_list_w() \u2014 NEEDED, not yet built",
      "patterns": {
        "benefit_checklist": {
          "icon": "fas fa-check",
          "icon_color": "#4CAF50",
          "text_color": "white or dark depending on bg",
          "use": "Hero bullet points, competitive edge benefits"
        },
        "negative_checklist": {
          "icon": "fas fa-times",
          "icon_color": "#971B2F",
          "text_color": "rgba(255,255,255,0.5) \u2014 faded to show these are the bad things",
          "use": "Competitor negatives in comparison sections"
        }
      }
    },
    "icon": {
      "count": 5883,
      "use_for": "Standalone icons, decorative elements, small indicators",
      "key_settings": {
        "selected_icon": "icon object",
        "view": "default|stacked|framed",
        "shape": "circle|square",
        "primary_color": "hex \u2014 icon color",
        "secondary_color": "hex \u2014 background (stacked) or border (framed)",
        "size": "dimension \u2014 icon size",
        "align": "left|center|right"
      },
      "helper": "icon_w($icon_class, $color, $size, $view, $shape, $secondary_color)"
    },
    "image-box": {
      "count": 5466,
      "use_for": "Team members, service cards with photos, portfolio items",
      "key_settings": {
        "image": "media object {url, id, alt}",
        "title_text": "string",
        "description_text": "string",
        "position": "top|left|right \u2014 image position",
        "text_align": "left|center|right",
        "title_size": "h1-h6|div|p",
        "image_size": "dimension \u2014 image display size",
        "image_space": "dimension \u2014 gap between image and text",
        "image_border_radius": "dimension \u2014 rounded corners",
        "title_bottom_space": "dimension",
        "title_color": "hex",
        "description_color": "hex"
      },
      "helper": "image_box_w($cfg, $img_url, $title, $desc, $align, $img_size, $position)"
    },
    "counter": {
      "count": 3594,
      "use_for": "Statistics, metrics, achievement numbers with animation",
      "key_settings": {
        "starting_number": "integer \u2014 animation start (usually 0)",
        "ending_number": "integer \u2014 target number",
        "prefix": "string \u2014 text before number (e.g. '$')",
        "suffix": "string \u2014 text after number (e.g. '+')",
        "duration": "integer \u2014 animation duration in ms",
        "thousand_separator": "yes|no",
        "thousand_separator_char": "','",
        "title": "string \u2014 label below number",
        "number_color": "hex",
        "title_color": "hex",
        "typography_typography": "'custom' \u2014 for number font",
        "typography_font_family": "font name",
        "typography_font_weight": "string",
        "typography_font_size": "dimension",
        "title_typography_typography": "'custom' \u2014 for label font",
        "title_typography_font_family": "font name",
        "title_typography_font_size": "dimension"
      },
      "helper": "Used directly via PressGo_Element_Factory::widget('counter', ...)"
    },
    "social-icons": {
      "count": 3261,
      "use_for": "Social media links in footer, about sections, team cards",
      "key_settings": {
        "social_icon_list": "array of {social_icon: icon_object, link: link_object, item_icon_color, _id}",
        "icon_size": "dimension",
        "icon_color": "custom|default",
        "icon_primary_color": "hex \u2014 icon color when icon_color='custom'",
        "shape": "circle|square|rounded",
        "align": "left|center|right",
        "icon_spacing": "dimension \u2014 gap between icons",
        "icon_padding": "dimension \u2014 padding inside icon shape",
        "hover_animation": "pop|shrink|grow",
        "columns": "string number \u2014 for grid layout"
      },
      "helper": "social_icons_w($icons, $size, $color, $primary_color, $shape, $align, $spacing)"
    },
    "divider": {
      "count": 7539,
      "use_for": "Section separators, visual breaks between content",
      "key_settings": {
        "color": "hex or rgba \u2014 line color",
        "weight": "dimension \u2014 line thickness",
        "width": "dimension \u2014 line width",
        "gap": "dimension \u2014 vertical space above/below",
        "align": "center|left|right",
        "text": "string \u2014 optional label text on the divider"
      },
      "helper": "divider_w()"
    },
    "spacer": {
      "count": 6637,
      "use_for": "Vertical spacing between elements",
      "key_settings": {
        "space": "dimension \u2014 height in px",
        "space_mobile": "dimension \u2014 responsive height"
      },
      "helper": "spacer_w($px)"
    },
    "toggle": {
      "count": 1043,
      "use_for": "FAQ sections, expandable content (FREE \u2014 use instead of Pro accordion)",
      "key_settings": {
        "tabs": "array of {tab_title, tab_content}",
        "border_color": "hex or rgba",
        "title_color": "hex \u2014 closed state title color",
        "tab_active_color": "hex \u2014 open state title color",
        "title_typography_typography": "'custom'",
        "title_typography_font_family": "font name",
        "title_typography_font_weight": "string",
        "title_typography_font_size": "dimension",
        "content_typography_typography": "'custom'",
        "content_typography_font_family": "font name",
        "content_typography_font_size": "dimension",
        "content_color": "hex",
        "space_between": "integer \u2014 gap between items",
        "toggle_icon_align": "left|right"
      },
      "helper": "Used directly via PressGo_Element_Factory::widget('toggle', ...)"
    },
    "star-rating": {
      "count": 437,
      "use_for": "Review ratings, quality indicators",
      "key_settings": {
        "rating": "number \u2014 0 to 5 (supports decimals like 4.5)",
        "star_style": "star_fontawesome|star_unicode",
        "icon_size": "dimension \u2014 star size",
        "icon_space": "dimension \u2014 gap between stars",
        "stars_color": "hex \u2014 star color",
        "align": "left|center|right",
        "title": "string \u2014 optional label next to stars",
        "title_gap": "dimension \u2014 gap between stars and title"
      },
      "helper": "star_rating_w($rating, $size, $color, $align)"
    },
    "testimonial": {
      "count": 615,
      "use_for": "Customer quotes with avatar, built-in testimonial layout",
      "key_settings": {
        "testimonial_content": "string \u2014 the quote text",
        "testimonial_name": "string \u2014 person's name",
        "testimonial_job": "string \u2014 role/title",
        "testimonial_image": "media object \u2014 avatar image",
        "testimonial_alignment": "left|center|right",
        "image_size": "dimension \u2014 avatar size",
        "image_border_radius": "spacing \u2014 avatar corner radius",
        "content_content_color": "hex",
        "name_text_color": "hex",
        "job_text_color": "hex",
        "content_typography_typography": "'custom'",
        "content_typography_font_family": "font name",
        "content_typography_font_size": "dimension",
        "content_typography_font_style": "normal|italic",
        "name_typography_typography": "'custom'",
        "name_typography_font_family": "font name",
        "name_typography_font_weight": "string"
      },
      "helper": "testimonial_w($cfg, $quote, $name, $role, $image_url, $align)"
    },
    "video": {
      "count": 194,
      "use_for": "YouTube/Vimeo embeds, product demos, explainer videos",
      "key_settings": {
        "youtube_url": "full YouTube URL",
        "vimeo_url": "full Vimeo URL",
        "show_image_overlay": "yes|'' \u2014 show poster image",
        "image_overlay": "media object \u2014 poster image",
        "aspect_ratio": "'169'|'219'|'43'|'32'|'11'",
        "lightbox": "yes|'' \u2014 open in lightbox",
        "_border_radius": "spacing \u2014 rounded corners"
      },
      "helper": "video_w($url, $overlay_img, $border_radius)"
    },
    "google_maps": {
      "count": 594,
      "use_for": "Location maps for businesses, contact pages",
      "key_settings": {
        "address": "string \u2014 full address or place name",
        "height": "dimension \u2014 map height",
        "zoom": "dimension \u2014 zoom level (1-20)",
        "css_filters_css_filter": "'custom' \u2014 enable desaturation",
        "css_filters_saturate": "dimension \u2014 0 for grayscale"
      },
      "helper": "google_map_w($address, $height, $zoom)"
    },
    "progress-bar": {
      "count": 326,
      "use_for": "Skills display, completion indicators, loading bars",
      "key_settings": {
        "title": "string \u2014 bar label",
        "percent": "dimension \u2014 fill percentage",
        "display_percentage": "yes|''",
        "bar_color": "hex \u2014 fill color",
        "bar_bg_color": "hex \u2014 track background",
        "bar_height": "dimension \u2014 bar thickness",
        "bar_border_radius": "spacing \u2014 rounded corners",
        "title_color": "hex",
        "typography_typography": "'custom'"
      },
      "helper": "Used directly via PressGo_Element_Factory::widget('progress-bar', ...)"
    },
    "form": {
      "count": 0,
      "use_for": "Lead capture forms \u2014 Elementor Pro required",
      "key_settings": {
        "form_name": "string \u2014 internal form name",
        "form_fields": "array of {custom_id, _id, field_type, field_label, placeholder, required, width}",
        "field_types": "text, email, tel, textarea, select, date, time, number, url, hidden",
        "field_width": "'50' = half row, '100' = full row",
        "submit_actions": "['email'] \u2014 what happens on submit",
        "email_to": "recipient email address",
        "email_subject": "subject line",
        "email_from": "sender email",
        "email_from_name": "sender display name",
        "email_reply_to": "'field_fld_email' \u2014 prefix 'field_' + the field's _id",
        "email_content_type": "'html' for HTML emails",
        "email_content": "HTML template with [field id='name'] shortcodes",
        "success_message": "string shown after submit",
        "button_text": "submit button text",
        "button_background_color": "hex",
        "button_color": "hex \u2014 button text color",
        "button_width": "'100' for full width",
        "field_border_radius": "number (no unit)",
        "field_border_width": "number",
        "field_border_color": "hex"
      },
      "helper": "form_w() \u2014 NEEDED, not yet built",
      "patterns": {
        "hero_lead_form": {
          "fields": [
            "name (text)",
            "phone (tel)",
            "email (email)",
            "goal (select)",
            "message (textarea, optional)"
          ],
          "button_text": "YES, BOOK MY INTRO SESSION",
          "success_message": "Thank you! We'll be in touch within 24 hours.",
          "note": "Keep to 4-5 fields max. Goal/interest dropdown helps qualify leads."
        },
        "simple_contact": {
          "fields": [
            "name (text)",
            "email (email)",
            "message (textarea)"
          ],
          "button_text": "SEND MESSAGE",
          "note": "Minimum viable form for simple contact pages"
        }
      }
    },
    "self_hosted_video": {
      "count": 0,
      "use_for": "Video without YouTube branding \u2014 keeps visitors on page",
      "implementation": "HTML widget with video tag + poster image + CSS play button overlay",
      "key_pattern": {
        "html": "<div style='position:relative;cursor:pointer;' onclick='...'><img src='POSTER' /><div class='play-btn'>\u25b6</div><video style='display:none'>...</video></div>",
        "play_button_css": "position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); width:72px; height:72px; background:rgba(accent,0.9); border-radius:50%;",
        "onclick": "Hide poster + play button, show video, call .play()"
      },
      "note": "YouTube embeds add channel links, share buttons, and suggested videos that pull visitors off landing pages. Always prefer self-hosted or Bunny CDN for paid traffic pages."
    }
  },
  "layout_patterns": {
    "hero_variants": {
      "split_text_image": {
        "frequency": 0.36,
        "description": "Text left + image right. Most common professional pattern."
      },
      "bg_image_overlay": {
        "frequency": 0.22,
        "description": "Full background image with dark overlay. Dramatic, immersive."
      },
      "centered_no_image": {
        "frequency": 0.18,
        "description": "Centered text on gradient. Clean, modern SaaS feel."
      },
      "creative_multi": {
        "frequency": 0.24,
        "description": "Multi-image grids, video, parallax. Complex layouts."
      }
    },
    "sections_per_page": {
      "average": 10,
      "min": 6,
      "max": 15,
      "mode": 10
    },
    "common_section_order": [
      "hero",
      "social_proof/logos",
      "features/services",
      "about/stats",
      "how_it_works/steps",
      "results/case_study",
      "testimonials",
      "pricing",
      "faq",
      "cta_final",
      "footer"
    ]
  },
  "widget_frequency": {
    "heading": 73470,
    "text-editor": 30517,
    "image": 29416,
    "button": 16906,
    "icon-box": 13674,
    "icon-list": 12381,
    "divider": 7539,
    "spacer": 6637,
    "icon": 5883,
    "image-box": 5466,
    "counter": 3594,
    "social-icons": 3261,
    "toggle": 1043,
    "testimonial": 615,
    "google_maps": 594,
    "star-rating": 437,
    "progress-bar": 326,
    "video": 194
  },
  "typography": {
    "popular_heading_fonts": [
      "Inter",
      "Poppins",
      "Plus Jakarta Sans",
      "Outfit",
      "Manrope",
      "Sora",
      "DM Sans",
      "Montserrat",
      "Playfair Display",
      "Raleway"
    ],
    "popular_body_fonts": [
      "Inter",
      "Poppins",
      "Lato",
      "DM Sans",
      "Manrope",
      "Nunito Sans",
      "Roboto",
      "Barlow",
      "Urbanist"
    ],
    "proven_combinations": [
      {
        "heading": "Inter",
        "body": "Inter",
        "vibe": "clean, modern, SaaS"
      },
      {
        "heading": "Poppins",
        "body": "Inter",
        "vibe": "friendly, approachable"
      },
      {
        "heading": "Playfair Display",
        "body": "Lato",
        "vibe": "elegant, upscale"
      },
      {
        "heading": "Plus Jakarta Sans",
        "body": "Inter",
        "vibe": "contemporary, tech"
      },
      {
        "heading": "Outfit",
        "body": "DM Sans",
        "vibe": "bold, startup"
      },
      {
        "heading": "Manrope",
        "body": "Manrope",
        "vibe": "geometric, minimal"
      },
      {
        "heading": "Sora",
        "body": "Inter",
        "vibe": "futuristic, AI/tech"
      },
      {
        "heading": "Montserrat",
        "body": "Lato",
        "vibe": "professional, corporate"
      }
    ]
  },
  "color_palettes": {
    "popular_accent_colors": [
      {
        "hex": "#4284CB",
        "usage": "blue, trust, SaaS"
      },
      {
        "hex": "#FFDD07",
        "usage": "yellow, energy, attention"
      },
      {
        "hex": "#E64529",
        "usage": "red-orange, urgency, food"
      },
      {
        "hex": "#0145FA",
        "usage": "electric blue, tech, innovation"
      },
      {
        "hex": "#10B981",
        "usage": "emerald green, growth, health"
      },
      {
        "hex": "#FF4E7A",
        "usage": "pink, creative, beauty"
      },
      {
        "hex": "#8B5CF6",
        "usage": "purple, premium, AI"
      },
      {
        "hex": "#F59E0B",
        "usage": "amber, warmth, trust"
      }
    ],
    "dark_bg_colors": [
      "#0F172A",
      "#1A1A2E",
      "#1C1917",
      "#030320",
      "#222831"
    ],
    "light_bg_colors": [
      "#F8FAFC",
      "#FFF8F5",
      "#FFFBEB",
      "#F0F9FF",
      "#F5F3FF"
    ]
  },
  "image_guidelines": {
    "hero_images": {
      "min_width": 800,
      "recommended_width": 1200,
      "orientation": "landscape for bg, portrait/square for split"
    },
    "feature_images": {
      "recommended_width": 600,
      "aspect_ratio": "4:3 or 16:9"
    },
    "pexels_search_strategies": {
      "hero": "{industry} professional {context}",
      "features": "{specific_service} professional quality",
      "about": "team professional people office",
      "testimonials": "happy customer satisfied portrait"
    }
  },
  "section_variants": {
    "_note": "All 19 section types with all 48 builder methods. Set 'variant' key in section config to use non-default.",
    "hero": {
      "default": "Centered text on dark gradient. Bold, impactful. SaaS/tech.",
      "split": "Text left + image right on light bg. Professional. Needs 'image' key.",
      "image": "Full background image with dark overlay. Dramatic. Needs 'image' key.",
      "video": "Centered text + video embed on light bg. Engaging. Needs 'video' key.",
      "gradient": "Colorful gradient bg with wave shape divider. Vibrant, playful.",
      "minimal": "Clean white bg, centered text, no gradient. Simple, elegant.",
      "form": "Split hero: text + bullet points left, lead capture form right. Highest converting hero variant for paid traffic. Requires Elementor Pro for form widget."
    },
    "stats": {
      "default": "White cards with icons, negative margin overlaps hero. After dark hero.",
      "dark": "Dark gradient bg with colored counters. After light sections.",
      "inline": "Minimal horizontal counter row with dividers. Compact accent strip."
    },
    "social_proof": {
      "default": "Industry pill badges on light bg.",
      "dark": "Industry pill badges on dark bg. After light hero."
    },
    "features": {
      "default": "3-column icon-box card grid with accent top borders. Classic. 3 items.",
      "alternating": "Alternating text/image rows (zigzag). 2-4 items with images.",
      "minimal": "Clean icons with text, no card backgrounds. Elegant. 3-6 items.",
      "image_cards": "Image on top of each card. Visual, product-focused. 3 items with images.",
      "grid": "2-column card grid with icons. Best for 4+ features (even count)."
    },
    "steps": {
      "default": "Numbered circles on light bg cards. Traditional, clear.",
      "compact": "Numbered pill badges with connecting divider. Modern SaaS.",
      "timeline": "Vertical timeline with connecting line. Sequential, narrative."
    },
    "results": {
      "default": "Dark gradient with animated counter cards. Dramatic.",
      "bars": "Light bg with animated progress bars. Clean, data-focused."
    },
    "competitive_edge": {
      "default": "Text + icon-list checklist on light bg. Simple. Takes a flat 'benefits' array of strings.",
      "image": "Text + checkmarks left, image right. Visual proof. Needs 'image' key.",
      "cards": "Benefit cards with icons in 3-column grid. Feature-like."
    },
    "testimonials": {
      "default": "3-column cards with star ratings. Balanced. 3 items.",
      "featured": "One large featured quote + smaller cards below. 3+ items.",
      "grid": "2-column card grid with avatars. 4+ items.",
      "minimal": "Centered quotes with dividers, no cards. Elegant."
    },
    "faq": {
      "default": "Centered toggle accordion. Clean, focused.",
      "split": "Header/description left, accordion right. Premium feel."
    },
    "blog": {
      "default": "Posts grid. REQUIRES Elementor Pro."
    },
    "pricing": {
      "default": "Full-width plan cards with feature lists. Standard.",
      "compact": "Left-aligned cards, smaller price, bordered highlight. Modern."
    },
    "logo_bar": {
      "default": "Light bg 'Trusted by' logo row with grayscale filter.",
      "dark": "Dark bg logo row."
    },
    "team": {
      "default": "Full cards with photo, name, role, bio, social links.",
      "compact": "Small photos, name + role only, no bio or cards."
    },
    "gallery": {
      "default": "Image grid with lightbox. Configurable columns.",
      "cards": "2-column image cards with optional captions."
    },
    "newsletter": {
      "default": "Card with headline, description, CTA, privacy note.",
      "inline": "Gradient bar with headline + button side by side."
    },
    "map": {
      "default": "Google Maps embed with optional header. Mobile height auto-scales."
    },
    "cta_final": {
      "default": "Gradient bar with centered text and button. Bold.",
      "card": "White card on light background. Elegant.",
      "image": "Full background image with dark overlay. Dramatic. Needs 'image' key."
    },
    "footer": {
      "default": "Multi-column dark footer with brand, link columns, contact.",
      "light": "White/light bg footer with colored icons."
    },
    "disclaimer": {
      "default": "Small centered disclaimer text. Also renders top-level social_icons."
    }
  },
  "section_rules": {
    "_note": "Guidance for all 19 section types. Sections render in order of the 'sections' array.",
    "hero": "Always first. Match variant to industry: split for services/fitness/healthcare (NEEDS image URL), image for hospitality/events (NEEDS image URL), default for bold SaaS/tech, gradient for creative/startups, minimal for portfolio/consulting, video for courses/demos (NEEDS video URL). Split hero is the most common professional pattern (36% of templates).",
    "stats": "Hard numbers build trust. Default overlaps hero (negative margin) \u2014 ONLY after dark hero. Dark variant after light sections. Inline for compact accent strips. 3-4 items ideal. Values auto-parsed: '2,500+' \u2192 prefix='', number=2500, suffix='+'. Use realistic numbers with commas for thousands.",
    "social_proof": "Industry trust indicators. Place immediately after hero or stats. Dark variant after light hero. Categories are pill badges. Alternative: use logo_bar for client logos instead.",
    "features": "Core value proposition. IMPORTANT: 3 items for default/image_cards, 2-3 for alternating (MUST have image URLs), 3-6 for minimal, 4-6 for grid (even numbers). Each item needs icon, title, desc. NEVER use alternating or image_cards without image URLs \u2014 use default or minimal instead.",
    "steps": "How-it-works process. 3 steps is golden. Compact for modern SaaS, timeline for narrative flow. Each item needs num, title, desc.",
    "results": "Measurable outcomes. Default (dark) for dramatic contrast, bars for data-focused. Metrics need value, label, and individual color hex. CTA optional.",
    "competitive_edge": "Differentiator section. 'default' = simple checklist (benefits is a flat string array, NOT objects). 'image' adds a photo on the right. 'cards' = 3-col grid with {icon, title, desc} items. There is NO comparison_table variant \u2014 it was removed because it's not implemented in the builder.",
    "testimonials": "Customer quotes. KEEP QUOTES SHORT (1-2 sentences max, ~30 words). Default 3-card for balanced coverage, featured when one quote stands out (first item is featured), grid for 4+, minimal for elegant/understated. Items need quote, name, role. Photos optional. Each quote should include one specific detail (a number, a result, a timeframe).",
    "faq": "Toggle widget (FREE). Never use accordion (Pro-only). 4-6 items ideal. Split variant adds description and CTA on left side. Items use q/a keys (not question/answer).",
    "blog": "REQUIRES Elementor Pro. Check before including. Shows recent posts grid. Eyebrow, headline, posts_per_page.",
    "pricing": "2-3 plans recommended. One plan should have highlighted:true. Each plan: name, price (string), period, features (string array), cta, badge. Compact variant for modern/restrained.",
    "logo_bar": "Client/partner logos. Alternative to social_proof. Logos render at fixed 120px width with grayscale filter. Dark variant after light sections.",
    "team": "Team member cards. Default has full details (photo, name, role, bio, social). Compact is name+role+photo only. 3-4 members for default, 4-6 for compact.",
    "gallery": "Image showcase. Default uses Elementor gallery widget with lightbox. Cards variant shows 2-per-row with optional captions. Images can be URL strings or {url, alt, caption} objects.",
    "newsletter": "Email capture. Default has card with headline, description, button, privacy note. Inline is a gradient bar. CTA points to signup URL.",
    "map": "Google Maps embed. Good for local businesses. Height auto-scales to 5/8 on mobile (min 200px). Address, height, zoom configurable.",
    "cta_final": "Strong closing push before footer. Gradient (default) for bold, card for elegant, image for dramatic (needs image URL). Always include trust_line for reassurance.",
    "footer": "Always last visible section \u2014 EVERY page should have a footer. Dark (default) or light variant. Include brand (name + short description), 2-3 link columns, contact info, copyright year, social icons.",
    "disclaimer": "Optional. Very bottom after footer. Small centered text. Also picks up top-level social_icons array.",
    "general_variant_selection": "Don't use 'default' for everything \u2014 pick variants that match the industry. Fitness: split hero, default features, default testimonials. SaaS: default hero, default features, compact steps. Restaurant: image hero, image_cards features, minimal testimonials. Portfolio: minimal hero, minimal features, minimal testimonials."
  },
  "content_quality_rules": {
    "_note": "Derived from analysis of high-converting landing pages. Concise copy converts better.",
    "max_word_counts": {
      "hero_headline": 8,
      "hero_subheadline": 25,
      "feature_title": 4,
      "feature_desc": 20,
      "step_title": 4,
      "step_desc": 20,
      "testimonial_quote": 30,
      "faq_answer": 50,
      "cta_headline": 8,
      "button_text": 4,
      "pricing_description": 12
    },
    "content_patterns": {
      "headlines": "Use power words: Transform, Unlock, Discover, Build, Launch, Grow, Master, Elevate. Avoid: Welcome to, We are, Our company",
      "testimonials": "Include ONE specific detail (a number, a timeframe, a concrete result). Bad: 'Great service!' Good: 'Cut our onboarding from 3 weeks to 2 days.'",
      "features": "Lead with the benefit, not the feature. Bad: 'Advanced analytics dashboard.' Good: 'See what's working in real time.'",
      "cta_buttons": "Action verb + outcome. Bad: 'Submit', 'Click Here'. Good: 'Start Free Trial', 'Book Your Class', 'Get Your Quote'"
    },
    "visual_rhythm": {
      "rule": "Alternate light and dark backgrounds. Never place two same-bg sections adjacent.",
      "typical_flow": [
        "dark_hero",
        "light_stats",
        "light_features",
        "dark_results",
        "light_testimonials",
        "light_faq",
        "dark_cta",
        "dark_footer"
      ],
      "section_count": "7-10 sections for a standard page. More than 12 feels bloated."
    },
    "no_fancy_punctuation": {
      "rule": "Em dashes, en dashes, smart quotes, and ellipses render correctly. Use them freely.",
      "historical_note": "Pre-2026-05-11 builds had a double-escape bug; obsolete now."
    },
    "shorter_copy": {
      "rule": "Landing page copy should be punchy and direct. Max word counts per element: hero headline 8 words, hero subheadline 15 words, bullet points 8 words each, card descriptions 25 words, section headlines 6 words.",
      "reason": "AI-generated copy tends to be too long. Real client feedback consistently asks for shorter, clearer text.",
      "learned_from": "Lindsay Allen (Bodystyle): 'the messaging has to be crystal clear' \u2014 shorter won every time"
    }
  },
  "config_schema_ref": "See config-schema.json for complete config structure with all field types, required/optional flags, examples, variant pairing guide, and industry recommendations.",
  "elementor_technical": {
    "layout": "Flexbox containers (Elementor 3.6+). All layout primitives are containers with flex properties.",
    "hierarchy": "container(outer, direction:column, content_width:boxed) > widget | container(row, direction:row) > container(col, direction:column) > widget",
    "nesting": "Unlimited \u2014 containers nest freely",
    "icon_format": {
      "value": "fas fa-icon-name",
      "library": "fa-solid"
    },
    "icon_libraries": {
      "fa-solid": "fas fa-*",
      "fa-regular": "far fa-*",
      "fa-brands": "fab fa-*"
    },
    "never_use": [
      "_animation (causes elementor-invisible class, content disappears)",
      "Legacy sections/columns (elType: section) \u2014 use containers only"
    ],
    "key_patterns": {
      "outer": "Top-level container: flex column, boxed content, responsive padding (desktop \u2192 3/4 tablet \u2192 1/2 mobile)",
      "row": "Horizontal container: flex row, auto-calculates child widths, stacks on mobile",
      "col": "Vertical container: flex column, holds widgets, flex_gap: 0",
      "spacing": "Via spacer widgets (not flex gap) \u2014 spacers auto-scale 2/3 on mobile"
    },
    "data_storage": "update_post_meta($id, '_elementor_data', wp_slash(wp_json_encode($elements)))"
  },
  "mobile_design_patterns": {
    "_note": "Learned from iterative mobile QA on pressgodigital.com landing pages. These patterns prevent the most common mobile layout issues.",
    "split_hero_mobile": {
      "problem": "Split hero (text-left, image-right) stacks vertically on mobile. Text alignment and padding need overrides.",
      "fixes": [
        "Set align_mobile='center' on headings, subheadlines, and buttons in the text column",
        "Reset padding_mobile to {0, 0, 20, 0} on the text column (removes desktop-only right padding)",
        "Image column needs width_mobile=100% to prevent squeeze",
        "Trust line row (stars + text) needs flex_justify_content_mobile='center' and flex_align_items='center'"
      ]
    },
    "stats_inline_mobile": {
      "problem": "Inline stats (horizontal counter row) can overflow on mobile with 4 items.",
      "fixes": [
        "Use flex_wrap='wrap' on the stats row",
        "Set width_mobile='45%' on each stat column so they wrap to 2x2 grid",
        "Counter font sizes: desktop 36px \u2192 mobile 28px",
        "Label font sizes: desktop 13px \u2192 mobile 11px"
      ]
    },
    "typography_scaling": {
      "rule": "Any heading >= 28px needs explicit mobile size. Rough formula: mobile = desktop * 0.65, min 20px.",
      "examples": {
        "hero_headline": {
          "desktop": 48,
          "mobile": 32
        },
        "section_headline": {
          "desktop": 36,
          "mobile": 26
        },
        "card_title": {
          "desktop": 20,
          "mobile": 18
        },
        "eyebrow": {
          "desktop": 12,
          "mobile": 11
        }
      }
    },
    "section_padding_mobile": {
      "rule": "Desktop section padding (80-100px) is too much on mobile. Use 40-50px top/bottom, 20px sides.",
      "auto_calc": "outer() handles this: tablet = desktop * 3/4, mobile = desktop * 1/2 (min 40px)"
    },
    "button_alignment": {
      "rule": "Buttons in split layouts should be left-aligned on desktop, centered on mobile.",
      "pattern": "align='left', align_mobile='center'"
    },
    "image_sizing": {
      "rule": "Hero images in split layouts need explicit mobile handling to prevent CLS.",
      "pattern": "Set aspect-ratio on image container via custom CSS, use min-height on image columns"
    },
    "testing": {
      "tool": "Puppeteer screenshots at 375x812 (2x DPR) \u2014 test/screenshot-sections.js",
      "critical_checks": [
        "Hero text + buttons centered on mobile",
        "Stats don't overflow horizontally",
        "Feature cards stack cleanly (no text truncation)",
        "Pricing cards are full-width on mobile",
        "FAQ toggle items have enough tap target size",
        "Footer columns stack vertically"
      ]
    },
    "content_width_full": {
      "problem": "content_width: boxed adds max-width via .e-con-inner wrapper that clips content on mobile, especially in multi-column layouts.",
      "fix": "Use content_width: full on ALL containers. Control max-width via custom CSS: selector.e-con { max-width: 1140px; margin: 0 auto; } @media(max-width:767px) { selector.e-con { max-width: 100%; } }",
      "learned_from": "Bodystyle Fitness comparison table \u2014 boxed containers clipped text at 375px viewport"
    },
    "flex_direction_mobile_broken": {
      "problem": "Elementor's flex_direction_mobile setting gets ignored in many cases. Containers revert to column stacking regardless of the setting.",
      "fix": "Use custom_css with !important: @media(max-width:767px){selector.e-con{flex-direction:row!important;}}",
      "learned_from": "Multiple client builds \u2014 this is a consistent Elementor bug"
    },
    "hide_mobile_no_override": {
      "problem": "hide_mobile: hidden adds elementor-hidden class with display:none!important. This CANNOT be overridden with custom CSS.",
      "fix": "Only use hide_mobile for elements you truly never want on mobile. For conditional display, use custom_css media queries instead. For sticky/fixed elements, use Code Snippets plugin instead of Elementor containers.",
      "learned_from": "Bodystyle Fitness sticky mobile CTA bar \u2014 fixed positioning + hide_desktop broke on all devices"
    },
    "icon_text_centering": {
      "problem": "Icon + text side-by-side in a flex row: the text widget stretches to 100% width by default, pushing the pair off-center.",
      "fix": "Set _element_width: auto on BOTH the icon widget AND the text widget. Then use flex_justify_content: center on the parent container.",
      "learned_from": "Bodystyle Fitness comparison table \u2014 icons and text wouldn't center until both had auto width"
    },
    "minimum_text_sizes": {
      "rule": "Minimum readable mobile text: 13px for body/values, 11px for labels/categories. Never go below 11px.",
      "context": "At 375px viewport minus padding (~340px usable), two 48% columns = ~163px each. Keep text short for side-by-side mobile layouts.",
      "learned_from": "Bodystyle Fitness \u2014 11px was barely readable, 13px was the sweet spot for comparison values"
    },
    "dual_layout_pattern": {
      "problem": "Complex layouts (comparison tables, feature grids) that look great on desktop often can't be made responsive with a single Elementor container structure.",
      "fix": "Build TWO versions of the section \u2014 one optimized for desktop (hide on mobile via Elementor responsive visibility), one optimized for mobile (hide on desktop/tablet). More markup but guaranteed to look good on both.",
      "learned_from": "Bodystyle Fitness comparison table, Ardane Medical video embeds \u2014 the only reliable way to handle significantly different desktop vs mobile layouts"
    }
  },
  "cta_popup_pattern": {
    "_note": "For landing pages with a scheduling CTA (Calendly, etc), use this proven pattern.",
    "approach": "Custom HTML modal with iframe \u2014 zero external JS dependencies. Survives WP Rocket, ad blockers, slow CDNs.",
    "implementation": {
      "step_1": "Add HTML widget (widgetType: 'html') to the hero section containing the modal div + script",
      "step_2": "Set all CTA button URLs to '#schedule' (or any anchor)",
      "step_3": "Script uses addEventListener (NOT inline onclick) to intercept #schedule clicks and open modal",
      "step_4": "Iframe src set lazily on first open \u2014 doesn't slow page load"
    },
    "wp_rocket_compatibility": {
      "problem": "WP Rocket's Delay JavaScript rewrites inline onclick to data-rocket-onclick, breaking handlers. Also wraps scripts in type='rocketlazyloadscript'.",
      "solution": "Use ONLY addEventListener (no inline onclick/onmouseover). Add data-no-optimize='1' data-no-defer='1' data-no-minify='1' to the script tag. Also add 'pg-cal' (or your script identifier) to WP Rocket's delay_js_exclusions option.",
      "code_pattern": "document.addEventListener('click', function(e) { var a = e.target.closest('a[href*=\"#schedule\"]'); if (a) { e.preventDefault(); open(); } });"
    },
    "modal_features": [
      "Click overlay to close",
      "X button to close",
      "ESC key to close",
      "Body scroll lock when open",
      "Fade animation (200ms)",
      "Responsive sizing: min(calc(100vw - 24px), 480px) width, min(calc(100dvh - 40px), 660px) height",
      "border-radius: 16px for modern feel",
      "backdrop-filter: blur(3px) on overlay"
    ],
    "calendly_url_params": {
      "hide_event_type_details": "1 \u2014 hides event description sidebar",
      "hide_gdpr_banner": "1 \u2014 hides GDPR cookie banner",
      "primary_color": "hex without # \u2014 brand accent color (may require Calendly Pro)",
      "text_color": "hex without # \u2014 heading text color (may require Calendly Pro)"
    }
  },
  "landing_page_template": {
    "_note": "Proven landing page pattern from pressgodigital.com/get-started. Use Elementor Canvas template for true landing page feel (no header/footer chrome).",
    "page_setup": {
      "template": "Elementor Canvas (elementor_canvas) \u2014 removes theme header/footer",
      "set_via": "update_post_meta($id, '_wp_page_template', 'elementor_canvas')"
    },
    "recommended_section_flow": [
      "hero",
      "stats",
      "features",
      "testimonials",
      "pricing",
      "faq",
      "cta_final",
      "footer"
    ],
    "style_notes": {
      "warm_paper": "Light bg #FAF8F5, dark text #2C2421, muted #7A6E66, gold accent #B8860B. DM Sans for both heading/body. Subtle card shadows. Elegant, not flashy.",
      "boxed_width": "1100px keeps content readable without feeling cramped",
      "section_padding": "100px desktop, auto-scales to 40px mobile"
    },
    "logo_placement": {
      "approach": "Image widget at top of hero section, before headline. Left-aligned desktop, centered mobile.",
      "settings": "width: 140px desktop, 120px mobile. margin_bottom: 8px."
    }
  },
  "conversion_patterns": {
    "_note": "Real-world conversion learnings from paid traffic landing pages. These override template-kit patterns when in conflict.",
    "hero_with_form": {
      "pattern": "Split hero: bullet points + phone CTA left, lead capture form right. Form in hero above fold converts better than CTA button that scrolls to a form below.",
      "form_fields": "Name, Phone, Email, Goal/Interest (select dropdown), Message (optional). Keep it to 4-5 fields max.",
      "mobile": "Form stacks below hero text. Reduce bullet points to 4 on mobile (hide desktop list, show shorter mobile list).",
      "learned_from": "South Coast Hypnotherapy (highest converting hero), adapted for Bodystyle Fitness"
    },
    "comparison_over_features": {
      "pattern": "For businesses competing against big brands (OrangeTheory, Planet Fitness, etc.), a comparison table converts better than a generic features section. People need to see WHY you're different, not just WHAT you offer.",
      "implementation": "Red X + faded text for competitors, green check + bold text for client. Use generic competitor label ('Big Class Gyms') not specific brand names \u2014 avoids legal issues and broadens the comparison.",
      "learned_from": "Bodystyle Fitness \u2014 Lindsay specifically asked for a comparison section; it became the centerpiece of the page"
    },
    "video_self_hosted": {
      "pattern": "Self-hosted video (or Bunny CDN) instead of YouTube embeds. YouTube adds clickable channel links, share buttons, and suggested videos that pull visitors off the landing page.",
      "implementation": "HTML5 video with poster image + CSS play button overlay. On click: hide poster + play button, show video, call .play(). Keeps visitors on page.",
      "learned_from": "Bodystyle Fitness \u2014 YouTube Short converted to self-hosted to eliminate exit points"
    },
    "sticky_mobile_cta": {
      "pattern": "Fixed bottom bar on mobile with phone number + book/form CTA. Visible at all scroll positions.",
      "implementation": "Must use Code Snippets plugin, NOT Elementor fixed positioning with hide_desktop. CSS: position:fixed; bottom:0; display:none on desktop, display:flex on mobile via @media query.",
      "learned_from": "Bodystyle Fitness, Hall Brothers Moving \u2014 Elementor's native fixed + responsive hide doesn't work"
    },
    "client_voice_over_ai_copy": {
      "pattern": "Record client calls, transcribe with Whisper, extract selling points for landing page copy. Real client language converts better than AI-generated marketing speak.",
      "examples": "Lindsay Allen: 'people plateau because there's a limit to what the same moves can do' \u2192 became comparison point. 'our trainers are good enough to customize it even in a group' \u2192 became semi-private selling point.",
      "implementation": "Use mlx-whisper locally for transcription, extract key phrases, use in hero bullets and section copy."
    },
    "brand_guide_compliance": {
      "pattern": "Always use the client's actual brand guide fonts and colors, not what their previous designer used. Kilo used Lexend Giga + Space Grotesk for Bodystyle \u2014 brand guide said Montserrat + Open Sans.",
      "implementation": "Ask for brand guide PDF early. Extract: heading font, body font, primary color, accent color, dark/light backgrounds."
    }
  },
  "code_snippet_patterns": {
    "_note": "These are WordPress Code Snippets (plugin), not Elementor widgets. They handle functionality that Elementor can't do natively.",
    "sticky_mobile_cta": {
      "what": "Fixed bottom bar on mobile with phone + CTA button",
      "why": "Elementor's _position:fixed + hide_desktop/hide_tablet doesn't work (elementor-hidden overrides everything)",
      "implementation": "add_action('wp_footer', ...) with CSS: position:fixed; bottom:0; display:none; @media(max-width:767px){display:flex}"
    },
    "google_ads_tracking": {
      "what": "3 snippets: gtag config (header), form conversion (footer), phone swap (header)",
      "gtag": "add_action('wp_head', ...) with async gtag.js script + gtag('config', 'AW-ID')",
      "form_conversion": "jQuery(document).on('submit_success', '.elementor-form', function(){ gtag('event', 'conversion', {...}) })",
      "phone_swap": "gtag('config', 'AW-ID/LABEL', { phone_conversion_number: 'NUMBER' })"
    }
  },
  "section_schemas": {
    "_note": "Required vs optional fields per section type. 'item_shape' is the per-item object shape used in 'items' arrays. Aliases listed are accepted but the canonical key is listed first.",
    "hero": {
      "required": [
        "headline"
      ],
      "optional": [
        "eyebrow",
        "subheadline",
        "cta_primary",
        "cta_secondary",
        "image"
      ],
      "field_shapes": {
        "cta_primary": "{ text: string, url: string }",
        "cta_secondary": "{ text: string, url: string }",
        "image": "{ url: string, alt?: string } \u2014 only used by variants 'split' and 'image'"
      },
      "fallback_behavior": "Missing cta_primary suppresses button; missing eyebrow suppresses the pill above headline. Headline alone is enough."
    },
    "stats": {
      "required": [
        "items"
      ],
      "optional": [
        "headline",
        "eyebrow"
      ],
      "item_shape": "{ value: string|number, label: string }",
      "value_parsing": "Values are auto-split into prefix/number/suffix. '$2,500+' becomes prefix='$', number=2500, suffix='+'. Non-numeric strings ('many') currently render as 0 (TODO: fall back to plain heading).",
      "min_items": 2,
      "max_items": 4
    },
    "social_proof": {
      "required": [
        "items"
      ],
      "optional": [
        "headline",
        "eyebrow"
      ],
      "item_shape": "{ text: string } OR plain string",
      "note": "Both forms accepted."
    },
    "features": {
      "required": [
        "items"
      ],
      "optional": [
        "headline",
        "eyebrow"
      ],
      "item_shape": "{ icon: { value: string, library: string }, title: string, desc: string }",
      "field_aliases": "'description' is accepted as an alias for 'desc' for forgiveness.",
      "variants_min_items": {
        "default": 2,
        "alternating": 2,
        "minimal": 3,
        "image_cards": 3,
        "grid": 4
      },
      "variants_max_items": {
        "default": 3,
        "alternating": 4,
        "minimal": 6,
        "image_cards": 3,
        "grid": 6
      },
      "auto_wrap_warning": "When variant='default' and items > 3, layout overflows. Use variant='grid' for 4+ items."
    },
    "steps": {
      "required": [
        "items"
      ],
      "optional": [
        "headline",
        "eyebrow"
      ],
      "item_shape": "{ num: string, title: string, desc: string }",
      "field_aliases": "'description' accepted as alias for 'desc'.",
      "note": "'num' is a string ('01' not 1) so leading zeros are preserved."
    },
    "results": {
      "required": [
        "metrics"
      ],
      "optional": [
        "headline",
        "eyebrow",
        "cta"
      ],
      "item_shape_metrics": "{ value: string|number, label: string, color?: string (hex) }",
      "color_validation": "Invalid hex strings fall back to the global accent color silently."
    },
    "competitive_edge": {
      "default_variant": {
        "required": [
          "headline",
          "benefits"
        ],
        "item_shape_benefits": "string (flat array of strings, NOT objects)",
        "field_shapes": {
          "cta": "{ text: string, url: string }"
        }
      },
      "image_variant": {
        "required": [
          "headline",
          "benefits",
          "image"
        ],
        "field_shapes": {
          "image": "{ url: string, alt?: string }"
        }
      },
      "cards_variant": {
        "required": [
          "headline",
          "items"
        ],
        "item_shape_items": "{ icon: { value, library }, title: string, desc: string }"
      },
      "comparison_table_variant": "NOT IMPLEMENTED. Removed from variant list. Use 'default' with a flat benefits string array."
    },
    "testimonials": {
      "required": [
        "items"
      ],
      "optional": [
        "headline",
        "eyebrow"
      ],
      "item_shape": "{ quote: string, name: string, role?: string, image?: { url, alt } }",
      "empty_item_behavior": "Items with empty 'quote' are skipped entirely. Items with empty 'name' suppress the name/role line."
    },
    "faq": {
      "required": [
        "items"
      ],
      "optional": [
        "headline",
        "subheadline",
        "eyebrow",
        "cta"
      ],
      "item_shape": "{ q: string, a: string }",
      "min_items": 1,
      "ideal_items": "4-6"
    },
    "pricing": {
      "required": [
        "plans"
      ],
      "optional": [
        "headline",
        "eyebrow"
      ],
      "item_shape_plans": "{ name: string, price: string, period: string, features: string[], cta: { text, url }, highlighted?: bool, badge?: string }",
      "note": "Exactly one plan can have highlighted=true."
    },
    "cta_final": {
      "required": [
        "headline"
      ],
      "optional": [
        "description",
        "eyebrow",
        "cta",
        "trust_line"
      ],
      "field_shapes": {
        "cta": "{ text: string, url: string }"
      },
      "note": "If cta is missing the button is suppressed but the headline still renders."
    },
    "footer": {
      "required": [
        "brand"
      ],
      "optional": [
        "columns",
        "social_icons",
        "contact"
      ],
      "field_shapes": {
        "brand": "{ name: string, description?: string }",
        "columns": "[{ title: string, links: [{ text: string, url: string }] }]",
        "social_icons": "[{ name: 'twitter'|'github'|'youtube'|'linkedin'|'facebook'|'instagram', url: string }]",
        "contact": "{ email?: string, phone?: string, address?: string }"
      },
      "field_aliases": "Inside columns, 'items' is accepted as an alias for 'links'."
    }
  },
  "validation_behavior": {
    "hard_failures": [
      "Section type not in known list \u2014 rejected.",
      "Missing required field per section_schemas \u2014 rejected with field name.",
      "Malformed JSON \u2014 rejected."
    ],
    "silent_fallbacks": [
      "Unknown variant name \u2014 falls back to 'default' (TODO: emit warning).",
      "Invalid icon class \u2014 icon omitted, no placeholder shown.",
      "Invalid hex color \u2014 falls back to global accent.",
      "Empty item in 'items' array \u2014 that single item is skipped, rest of section renders."
    ],
    "url_sanitization": "Only http(s)://, mailto:, tel:, relative paths starting with /, and #anchors are accepted in CTA url fields. Anything else (javascript:, data:, file:, etc.) is replaced with '#'.",
    "string_escaping": "Headlines, button text, labels: sanitize_text_field. Rich content (descriptions, FAQ answers): wp_kses_post. Raw HTML in headline strings is stripped, not rendered.",
    "value_coercion": {
      "stat_values": "Numeric strings with prefix/suffix get parsed for counter animation. Non-numeric strings currently render as 0 (TODO).",
      "booleans_as_strings": "highlighted: 'true'/'false' is coerced to bool.",
      "numbers_as_strings": "price: '10' and price: 10 both accepted."
    }
  },
  "quickstart_minimal_configs": {
    "_note": "Smallest config that will render each section type cleanly. Use as templates and fill in real content.",
    "hero": {
      "type": "hero",
      "data": {
        "headline": "Your big promise here"
      }
    },
    "stats": {
      "type": "stats",
      "data": {
        "items": [
          {
            "value": "1,200+",
            "label": "Happy customers"
          },
          {
            "value": "98%",
            "label": "Retention"
          },
          {
            "value": "24/7",
            "label": "Support"
          }
        ]
      }
    },
    "features": {
      "type": "features",
      "data": {
        "items": [
          {
            "title": "Fast",
            "desc": "Built for speed.",
            "icon": {
              "value": "fas fa-bolt",
              "library": "fa-solid"
            }
          },
          {
            "title": "Simple",
            "desc": "No learning curve.",
            "icon": {
              "value": "fas fa-check",
              "library": "fa-solid"
            }
          },
          {
            "title": "Solid",
            "desc": "Built to last.",
            "icon": {
              "value": "fas fa-shield",
              "library": "fa-solid"
            }
          }
        ]
      }
    },
    "steps": {
      "type": "steps",
      "data": {
        "items": [
          {
            "num": "01",
            "title": "Sign up",
            "desc": "Create your account in 30 seconds."
          },
          {
            "num": "02",
            "title": "Connect",
            "desc": "Link your tools."
          },
          {
            "num": "03",
            "title": "Go live",
            "desc": "Launch your first campaign."
          }
        ]
      }
    },
    "competitive_edge": {
      "type": "competitive_edge",
      "data": {
        "eyebrow": "WHY US",
        "headline": "Built different",
        "description": "Three things our competitors won't.",
        "benefits": [
          "No long-term contracts",
          "Real human support",
          "Live in 5 minutes"
        ],
        "cta": {
          "text": "Get Started",
          "url": "/"
        }
      }
    },
    "testimonials": {
      "type": "testimonials",
      "data": {
        "items": [
          {
            "quote": "Real quote here.",
            "name": "Real Person",
            "role": "Real Title"
          }
        ]
      }
    },
    "faq": {
      "type": "faq",
      "data": {
        "items": [
          {
            "q": "How does it work?",
            "a": "It just works."
          },
          {
            "q": "How much?",
            "a": "It depends."
          }
        ]
      }
    },
    "pricing": {
      "type": "pricing",
      "data": {
        "plans": [
          {
            "name": "Free",
            "price": "0",
            "period": "forever",
            "features": [
              "Everything basic"
            ],
            "cta": {
              "text": "Start",
              "url": "/"
            }
          },
          {
            "name": "Pro",
            "price": "29",
            "period": "month",
            "features": [
              "Everything"
            ],
            "cta": {
              "text": "Go Pro",
              "url": "/pro"
            },
            "highlighted": true
          }
        ]
      }
    },
    "cta_final": {
      "type": "cta_final",
      "data": {
        "headline": "Ready to start?",
        "description": "It takes 30 seconds.",
        "cta": {
          "text": "Get Started",
          "url": "/"
        }
      }
    },
    "footer": {
      "type": "footer",
      "data": {
        "brand": {
          "name": "Your Brand",
          "description": "Tagline here."
        },
        "columns": [
          {
            "title": "Product",
            "links": [
              {
                "text": "Features",
                "url": "/features"
              },
              {
                "text": "Pricing",
                "url": "/pricing"
              }
            ]
          }
        ],
        "contact": {
          "email": "hello@example.com"
        }
      }
    }
  },
  "known_gotchas": [
    {
      "id": "hero_optionality",
      "rule": "Hero only requires 'headline'. Build with just a headline if the user hasn't given you more \u2014 don't invent.",
      "severity": "high"
    },
    {
      "id": "no_invented_testimonials",
      "rule": "Do NOT generate fake testimonials with first-name-last-initial attribution. If the user hasn't given real quotes, skip the testimonials section or use clearly-labeled placeholder ('TESTIMONIAL 1 \u2014 replace before publishing').",
      "severity": "high"
    },
    {
      "id": "stat_value_format",
      "rule": "Stat values are auto-parsed: '$2,500+' becomes prefix='$', number=2500, suffix='+'. Non-numeric strings currently render as 0 (will be fixed; for now use numeric values).",
      "severity": "low"
    },
    {
      "id": "comparison_table_does_not_exist",
      "rule": "competitive_edge has NO comparison_table variant. Use the default variant with a flat 'benefits' array of strings, OR variant='cards' for a 3-col icon-box layout.",
      "severity": "high"
    },
    {
      "id": "url_schemes",
      "rule": "Only http(s)://, mailto:, tel:, relative paths starting with /, and #anchors are accepted in CTA url fields. Anything else gets stripped to '#'.",
      "severity": "high"
    },
    {
      "id": "footer_columns_links_alias",
      "rule": "Footer columns use 'links' as the canonical key (preferred). 'items' also accepted as alias. Each link is { text, url }.",
      "severity": "medium"
    },
    {
      "id": "features_steps_desc_alias",
      "rule": "Features and steps items use 'desc' as canonical (preferred). 'description' also accepted as alias. Missing desc renders as empty (no Lorem fallback).",
      "severity": "medium"
    },
    {
      "id": "items_count_per_variant",
      "rule": "Each variant has documented min/max item counts (see section_schemas). Going outside the range overflows the layout. Pick the right variant for the count.",
      "severity": "medium"
    }
  ],
  "agent_instructions": [
    "Read section_schemas before building anything \u2014 don't guess field names.",
    "Call inspect_page after add_sections, not screenshot_page (inspect is authoritative; screenshot lags by ~1-3s after multi-write).",
    "Build the page in one add_sections call when possible to avoid cache lag on rapid multi-writes.",
    "Don't generate fake testimonials. If the user hasn't given quotes, skip the section or use obvious placeholders.",
    "Don't try variant names that aren't documented. If you want a layout that isn't listed, ask the user \u2014 don't invent variants.",
    "For long sessions, prefer create_page \u2192 add_sections \u2192 screenshot over editing existing pages \u2014 less cache surface area."
  ]
}