{
  "schema_version": "facebook-ad-mockup.v1",
  "specification_version": "meta-image-guidance.2026-09-27",
  "scope": {
    "format": "single-image",
    "placements": [
      "facebook_feed",
      "instagram_feed",
      "facebook_stories",
      "instagram_stories",
      "facebook_reels",
      "instagram_reels"
    ],
    "unsupported": [
      "ads_on_facebook_reels_overlay",
      "video",
      "carousel",
      "catalog",
      "dynamic_creative",
      "automated_expansion"
    ]
  },
  "required_groups": {
    "project": [
      "title",
      "purpose",
      "buyer",
      "offer",
      "intended_action",
      "reviewer",
      "production_owner"
    ],
    "advertiser": [
      "page_name",
      "avatar_asset_id"
    ],
    "copy": [
      "primary_text",
      "headline",
      "description",
      "display_domain",
      "destination_url",
      "cta"
    ],
    "feed_asset": [
      "asset_id",
      "source_sha256",
      "width",
      "height",
      "treatment",
      "crop",
      "protected_content"
    ],
    "vertical_asset": [
      "asset_id",
      "source_sha256",
      "width",
      "height",
      "treatment",
      "crop",
      "protected_content"
    ],
    "evidence": [
      "claims",
      "asset_permission",
      "destination_observation"
    ],
    "placement_decisions": [
      "facebook_feed",
      "instagram_feed",
      "facebook_stories",
      "instagram_stories",
      "facebook_reels",
      "instagram_reels"
    ],
    "route_states": [
      "feed",
      "vertical"
    ]
  },
  "placement_decision_values": [
    "Use",
    "Adjust crop",
    "Replace asset",
    "Hold",
    "Native check"
  ],
  "states": {
    "preview": [
      "Preview available",
      "Preview incomplete"
    ],
    "technical": [
      "Pass",
      "Needs changes",
      "Unknown",
      "Unsupported"
    ],
    "handoff": [
      "Ready for review",
      "Hold"
    ],
    "meta_native": [
      "Not checked",
      "Externally verified"
    ]
  },
  "state_rules": [
    "A local action never changes meta_native to Externally verified.",
    "Ready for review means the local production record is complete enough for its named reviewer; it is not Meta verification, publication approval or launch authorization.",
    "Unresolved Meta-native checks do not by themselves force the production handoff to Hold.",
    "Missing purpose, required identity, destination, Feed art or vertical art creates a stable Hold request.",
    "A Feed-only issue does not hold an independently complete vertical route, and the reverse also applies.",
    "Copy, CTA, destination, asset or protected-content edits invalidate dependent checks and exports.",
    "Presentation-only changes invalidate the affected mockup rendering without invalidating unchanged clean art or factual evidence.",
    "Every Unknown or Hold includes a stable request ID, owner or assignment request, reason, exact evidence/action and blocked state.",
    "A valid supplied native or external request preserves its field and request_id byte-for-byte; subject is a human label and never replaces field. New IDs derive from the exact field value.",
    "A damaged imported envelope is rejected atomically and does not replace the last accepted project."
  ],
  "working_guidance": {
    "feed_4_5": [
      1440,
      1800
    ],
    "vertical_9_16": [
      1440,
      2560
    ],
    "approximate_vertical_safe_zone_percent": {
      "top": 14,
      "bottom": 35,
      "left": 6,
      "right": 6
    },
    "reels_disclaimer_bottom_clear_percent": 40,
    "text_guidance": {
      "facebook_feed": {
        "primary": "50-150",
        "headline": 27
      },
      "instagram_feed": {
        "primary": 125,
        "headline": 40
      },
      "facebook_stories": {
        "primary": 125,
        "headline": 40
      },
      "instagram_stories": {
        "primary": 125
      },
      "facebook_reels": {
        "primary": 40,
        "headline_android_only": 55
      },
      "instagram_reels": {
        "primary": 44
      }
    },
    "treatment": "Warnings only; native Meta placement preview and safe-zone guardrail remain authoritative."
  },
  "exports": [
    "full_context_mockup_png",
    "clean_feed_art_png",
    "clean_vertical_art_png",
    "production_handoff_markdown",
    "lossless_project_json"
  ],
  "parity_fields": [
    "project",
    "advertiser",
    "copy",
    "destination",
    "assets",
    "treatments",
    "crops",
    "protected_content",
    "placement_decisions",
    "evidence",
    "unknowns",
    "states",
    "route_states",
    "native_requests"
  ],
  "counting": "Use Intl.Segmenter grapheme counting when available and codepoint fallback; exact Meta counting remains Unknown.",
  "source_urls": [
    "https://www.facebook.com/business/ads-guide",
    "https://www.facebook.com/business/help/103816146375741",
    "https://www.facebook.com/business/help/980593475366490",
    "https://www.facebook.com/business/help/1497214480351034"
  ]
}
