{
  "_readme": "All site copy lives here. Stand items: label = the link name; tag = the cream tag over the object (tagSide right = beside it, tagBelow = films where it sits under the object); lines = how it is lettered on the object; sign.desktop/phone = where the in-scene label sits ([left, top, width, height] of the frame), sign.style = stamp | plaque | poster (the bin and sack lettering also come as an image layer: assets/hero/labels/), sign.rot = degrees. Edit text, save, refresh. Stand geometry is [left, top, width, height] as fractions of the CROPPED film frame (see site/assets/hero/manifest.json); re-measure only if the film framing changes.",

  "meta": {
    "title": "Melly's Recycling · Miami composting loop",
    "description": "We collect food scraps from Miami homes and businesses, turn them into soil, and send it to local farms. Get a compost bin."
  },

  "hint": "Scroll to run the loop",

  "story": {
    "_how": "Intro captions over the film, one at a time, tied to scroll progress (0 = top, 0.985 = landing). from/to = when each card shows. source = optional tiny line under the sentence. desktop: sky lifts that card into the sky. banner: true = shown in the hero banner's own box, then crossfades into the banner text on landing (keep its to above 1). Each card holds about 0.07.",
    "beats": [
      { "from": 0.020, "to": 0.090, "title": "Miami is running out of room.", "line": "38% of what Miami-Dade throws away is food and yard waste. It doesn't belong in a landfill.", "source": "Miami-Dade County Waste Composition Study, 2021" },
      { "from": 0.110, "to": 0.180, "title": "You make food scraps.", "line": "We haul them away." },
      { "from": 0.225, "to": 0.295, "title": "For every kitchen in town.", "line": "Restaurants, hotels, venues, grocers and caterers." },
      { "from": 0.350, "to": 0.420, "title": "Not the landfill.", "line": "Your scraps go straight to a compost facility." },
      { "from": 0.480, "to": 0.550, "title": "Scraps become soil.", "line": "Heat, air and time turn food into rich, living compost." },
      { "from": 0.600, "to": 0.670, "title": "Local farms grow in it.", "line": "The healthiest soil you can get grows the best food." },
      { "from": 0.730, "to": 0.800, "title": "And it comes back to you.", "line": "Fresh food from farms down the road." },
      { "from": 0.905, "to": 1.010, "title": "Then the loop starts again.", "banner": true }
    ]
  },

  "panel": {
    "eyebrow": "Melly's Recycling",
    "title": "Organic Waste Recycling Services",
    "lede": "Pick something on the stand to look around."
  },

  "loader": {
    "label": "Loading the loop"
  },

  "skip": "Skip to the stand",

  "loopStart": { "desktop": [0.483, 0.389], "phone": [0.492, 0.589] },

  "stand": [
    {
      "id": "bin",
      "label": "Get a compost bin", "tag": "Get a compost bin",
      "href": "/get-a-compost-bin",
      "primary": true,
      "desktop": [0.047, 0.564, 0.141, 0.36],
      "phone":   [0.021, 0.641, 0.125, 0.119]
    },
    {
      "id": "sack",
      "label": "Buy soil", "tag": "Buy soil",
      "href": "/buy-soil",
      "desktop": [0.293, 0.4385, 0.111, 0.1905],
      "phone":   [0.278, 0.598, 0.115, 0.064]
    },
    {
      "id": "oranges",
      "label": "What is the loop?", "tag": "What is the loop?", "tagBelow": ["phone"],
      "href": "/what-is-the-loop",
      "desktop": [0.443, 0.5321, 0.098, 0.0969],
      "phone":   [0.434, 0.631, 0.094, 0.030]
    },
    {
      "id": "eggs",
      "label": "Find local farms", "tag": "Find local farms", "tagBelow": ["phone"],
      "href": "/find-local-farms",
      "desktop": [0.569, 0.5365, 0.104, 0.0925],
      "phone":   [0.569, 0.633, 0.097, 0.028]
    },
    {
      "id": "ethan",
      "label": "Meet Ethan", "tag": "Meet Ethan", "tagSide": "right",
      "href": "/meet-ethan",
      "desktop": [0.42, 0.2844, 0.155, 0.2477],
      "phone":   [0.424, 0.563, 0.125, 0.068]
    }
  ],

  "tagRow": {
    "_how": "Desktop film: these tags sit in one straight row on the counter's green front panel (top edge at y, a fraction of the frame), centred under their objects with even gaps.",
    "desktop": { "y": 0.705, "ids": ["sack", "oranges", "eggs"] }
  },

  "menu": {
    "_how": "The A-frame board is a painted SHOP sign at every screen size: SHOP on the plain strip above the red border (top), the three links inside it, then (cta: true) the two red quote lines under a thin red divider. box = [left, top, width, height] INSIDE the board's red painted border, as fractions of the frame. Everything is sized from the board box (never px breakpoints), so the sign looks the same on every screen. The phone tray carries the full menu.",
    "title": "Shop",
    "items": [
      { "label": "Compost bin", "href": "/get-a-compost-bin" },
      { "label": "Soil", "href": "/buy-soil" },
      { "label": "Local farms", "href": "/find-local-farms" },
      { "label": "Quote a pickup", "href": "/get-a-compost-bin#quote", "cta": true },
      { "label": "Wholesale pricing", "href": "/buy-soil#pricing", "cta": true }
    ],
    "desktop": [0.840, 0.603, 0.101, 0.262],
    "phone":   [0.850, 0.657, 0.103, 0.081],
    "top": {
      "_how": "The plain strip of the board ABOVE the red border, where SHOP is painted. [left, top, width, height] as fractions of the frame.",
      "desktop": [0.822, 0.514, 0.135, 0.080],
      "phone":   [0.827, 0.625, 0.142, 0.0245]
    }
  },

  "ethan": {
    "_how": "performer: stills (layers rise from behind the counter, crossfade wave) | video | frames. For video add files to assets/hero/<film>/ and set e.g. \"video\": { \"webm\": \"ethan-entrance.webm\", \"hevc\": \"ethan-entrance.mov\" }. For frames: \"frames\": { \"pattern\": \"ethan/f{i}.webp\", \"count\": 48, \"fps\": 24 }.",
    "performer": "stills",
    "idle": {
      "breath": 0.012, "breathTime": 2.1, "sway": 0.0045, "swayTime": 3.6, "lean": 0.9, "leanTime": 5.2,
      "_how": "Ethan's life at the stand. every: seconds between moments [min, max]. moments: lean (toward the oranges), tilt (head tilt), pose (crossfade to any extra ethan-<film>-<pose>.png the pipeline found). The wave is never on the timer: he waves when a visitor hovers him or his poster (touch screens: once when the stand goes live). weight = how often. Extra poses join the rotation automatically. For a looping idle clip add \"video\": { \"webm\": \"ethan-idle.webm\", \"hevc\": \"ethan-idle.mov\" } (files in assets/hero/<film>/). Set \"idle\": false to turn it all off.",
      "every": [6, 10],
      "moments": [
        { "type": "lean", "weight": 1 },
        { "type": "tilt", "weight": 1 }
      ]
    }
  },

  "skyline":    { "desktop": 0.11, "phone": 0.48 },
  "groundline": { "desktop": 0.94, "phone": 0.765 },

  "tray": {
    "primary": "bin",
    "grid": ["sack", "oranges", "eggs", "ethan"]
  }
}
