{
  "_doc": {
    "coords": "All points are in pixels of the delivered WebP (w x h = its real size). Origin = top-left corner of the image, x to the right, y down; the centre of pixel (i, j) is (i + 0.5, j + 0.5), the same system CSS transform-origin uses. To use a point at display width D: multiply by D / w. Every value was measured from the pixels of the final file.",
    "src / half / screw": "URL of the transparent WebP (lit from the top-left, drawn on a transparent background).",
    "w, h": "Real pixel size of the file.",
    "scissors": "Articulated scissors built from ONE half: the front half is scissors-half.webp as is; the back half is the same image mirrored vertically about the pivot row (CSS: transform-origin: pivot; scaleY(-1)). For an opening angle theta: front = rotate(-theta/2) (blade goes up), back = scaleY(-1) then rotate(+theta/2) (blade goes down), both around pivot. theta = 0 is the closed pair (the tips coincide because tip and pivot are on the same row).",
    "scissors.pivot": "Centre of the pivot hole (sub-pixel circle fit, rms 0.14 px). Rotation centre for both halves and centre of the screw cap.",
    "scissors.tip": "Blade point. Lies on the pivot row (dy = 0.05 px), so the mirrored tip lands on it.",
    "scissors.ring": "Centre of the finger ring opening of the half (the mirrored ring is at [ring.x, 2*pivot.y - ring.y]).",
    "scissors.holeR / countersinkR": "Radius of the see-through pivot hole and of the bevelled countersink around it.",
    "scissors.screwW / screwH / screwSize": "Real size of scissors-screw.webp, and the size (in half-image pixels) to draw it at, centred on pivot, above both halves; it then covers the countersink.",
    "scissors.openDeg": "Largest total opening angle between the blades used by the cut animation (each half turns openDeg/2).",
    "scissors.front / mirror": "front = which image is on top (the unmirrored half); mirror = the back half is mirrored about the pivot row.",
    "scissors.backShade": "CSS filter brightness() for the back half (depth; also hides that its mirrored light comes from below).",
    "scissors.shadow": "CSS drop-shadow on the front half (and on the screw at half the offset): dx, dy, blur in half-image px, alpha = shadow opacity.",
    "scissors.cutEdge": "Cutting edge of the front half (lower silhouette of the blade) as a polyline from where the bevel starts to the tip, measured on the silhouette (the edge is slightly convex). The back half mirrors it about the pivot row.",
    "scissors.cutX": "For opening theta (deg, key), distance in half-image px from the pivot, along the closing axis, where the two cutting edges cross (the point where the hair/text is cut). It lies on the pivot row. Interpolate between keys.",
    "scissorsClosed": "Static closed scissors (a different, real closed pair). pivot = centre of its screw head, screwR = its radius, tip = blade point.",
    "dryer.nozzle": "Centre of the concentrator outlet (where the air leaves). nozzleH = height of the outlet face.",
    "dryer.airAngle": "Direction of the air jet in degrees: 0 = straight to the right, positive = clockwise (downwards), CSS rotate() convention. Measured from the centre line of the concentrator.",
    "comb.teeth": "Line through the tooth tips, from the first to the last tooth (comb lies horizontally, teeth pointing down).",
    "comb.rootY": "y where the teeth start (top of the gaps between teeth). fineFromX = x where the coarse teeth end and the fine teeth begin.",
    "razor.edge": "Cutting edge of the open straight razor (blade on the right, edge facing down, handle on the left): from the heel to where the toe starts to round.",
    "razor.spineY": "y of the blade spine (top edge) over the same span.",
    "clipper.blade": "Line through the tips of the cutting teeth (clipper points right): top end, bottom end. Note: the endpoints are the gold housing lugs; the actual tooth tips span about y 94-426.",
    "spray.nozzle": "Orifice of the trigger-sprayer nozzle (bottle upright, nozzle pointing right). sprayAngle = mist direction, same convention as airAngle.",
    "pole": "Chrome caps for a CSS glass cylinder: top cap sits above the glass, bottom cap below. jointY = y of the cap edge that touches the glass (bottom edge of the top cap / top edge of the bottom cap). glass = [x0, x1] outer width of the collar at that edge: draw the glass this wide (or up to ~4 % narrower) and centred on axisX, tucked 2-3 px under the caps.",
    "brush / pomade": "Decor only: size.",
    "foam": "Shaving-foam patches (decor / razor effect), size only.",
    "drops": "Clear water drops for the dryer / spray effects, size only. The body is ~35 % opaque (rim, highlights and refraction lines stay solid), so text shows through; use them at 10-40 px.",
    "decor": "For decor showing scissors next to the animated pair, use the articulated pair at theta=0 (same design) rather than scissorsClosed, which is a different shear design."
  },
  "version": 1,
  "scissors": {
    "type": "halves",
    "half": "/assets/fx/scissors-half.webp",
    "w": 1400,
    "h": 328,
    "pivot": [
      613.9,
      72.3
    ],
    "tip": [
      1391.9,
      72.3
    ],
    "ring": [
      149.4,
      197.6
    ],
    "holeR": 19.9,
    "countersinkR": 29.4,
    "screw": "/assets/fx/scissors-screw.webp",
    "screwW": 254,
    "screwH": 256,
    "screwSize": [
      61.8,
      62.3
    ],
    "openDeg": 26,
    "front": "half",
    "mirror": "pivotRow",
    "backShade": 0.8,
    "shadow": {
      "dx": 2,
      "dy": 4,
      "blur": 3,
      "alpha": 0.55
    },
    "cutEdge": [
      [
        677.5,
        130.0
      ],
      [
        780,
        125.0
      ],
      [
        930,
        115.4
      ],
      [
        1080,
        105.0
      ],
      [
        1230,
        92.0
      ],
      [
        1380,
        76.1
      ],
      [
        1391.9,
        72.3
      ]
    ],
    "cutX": {
      "0": 778.0,
      "2": 688.3,
      "4": 596.8,
      "6": 528.3,
      "8": 466.8,
      "10": 416.5,
      "12": 374.2,
      "14": 342.0,
      "16": 313.8,
      "18": 289.5,
      "20": 268.8,
      "22": 249.8,
      "24": 234.1,
      "26": 220.8
    }
  },
  "scissorsClosed": {
    "src": "/assets/fx/scissors-closed.webp",
    "w": 1400,
    "h": 505,
    "pivot": [
      713.5,
      251.2
    ],
    "screwR": 32.9,
    "tip": [
      1391.9,
      253.2
    ]
  },
  "dryer": {
    "src": "/assets/fx/dryer.webp",
    "w": 1400,
    "h": 1227,
    "nozzle": [
      1389.2,
      241.0
    ],
    "nozzleH": 46,
    "airAngle": -1.1
  },
  "comb": {
    "src": "/assets/fx/comb.webp",
    "w": 1400,
    "h": 296,
    "teeth": [
      [
        27.0,
        287.5
      ],
      [
        1371.0,
        288.3
      ]
    ],
    "rootY": 103.0,
    "fineFromX": 672.5
  },
  "razor": {
    "src": "/assets/fx/razor.webp",
    "w": 1400,
    "h": 137,
    "edge": [
      [
        886.0,
        127.9
      ],
      [
        1352.0,
        127.9
      ]
    ],
    "spineY": 22.0
  },
  "clipper": {
    "src": "/assets/fx/clipper.webp",
    "w": 1400,
    "h": 458,
    "blade": [
      [
        1390.6,
        71.0
      ],
      [
        1391.1,
        451.0
      ]
    ]
  },
  "brush": {
    "src": "/assets/fx/brush.webp",
    "w": 1200,
    "h": 659
  },
  "spray": {
    "src": "/assets/fx/spray.webp",
    "w": 528,
    "h": 1200,
    "nozzle": [
      521.0,
      52.5
    ],
    "sprayAngle": 0
  },
  "pomade": {
    "src": "/assets/fx/pomade.webp",
    "w": 800,
    "h": 581
  },
  "pole": {
    "top": {
      "src": "/assets/fx/pole-top.webp",
      "w": 480,
      "h": 414,
      "jointY": 410.2,
      "glass": [
        8.0,
        473.0
      ],
      "axisX": 240.5
    },
    "bottom": {
      "src": "/assets/fx/pole-bottom.webp",
      "w": 480,
      "h": 404,
      "jointY": 3.6,
      "glass": [
        7.0,
        473.0
      ],
      "axisX": 240.0
    }
  },
  "foam": [
    {
      "src": "/assets/fx/foam-1.webp",
      "w": 900,
      "h": 394
    },
    {
      "src": "/assets/fx/foam-2.webp",
      "w": 779,
      "h": 432
    },
    {
      "src": "/assets/fx/foam-3.webp",
      "w": 633,
      "h": 500
    }
  ],
  "drops": [
    {
      "src": "/assets/fx/drop-1.webp",
      "w": 123,
      "h": 119
    },
    {
      "src": "/assets/fx/drop-2.webp",
      "w": 248,
      "h": 234
    },
    {
      "src": "/assets/fx/drop-3.webp",
      "w": 178,
      "h": 168
    },
    {
      "src": "/assets/fx/drop-4.webp",
      "w": 93,
      "h": 87
    },
    {
      "src": "/assets/fx/drop-5.webp",
      "w": 212,
      "h": 200
    }
  ]
}