{
  "schemaVersion": 1,
  "product": "bicycle-fit-comparison",
  "methodVersion": "1.1.0",
  "inputSchema": {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "title": "Normalized BikeFitDelta comparison",
    "type": "object",
    "required": [
      "version",
      "fields",
      "tables"
    ],
    "properties": {
      "version": {
        "const": 1
      },
      "demo": {
        "type": "boolean"
      },
      "tables": {
        "type": "object",
        "maxProperties": 0
      },
      "fields": {
        "type": "object",
        "required": [
          "refStack",
          "refReach",
          "refHead",
          "refSpacers",
          "refStem",
          "refAngle",
          "newStack",
          "newReach",
          "newHead",
          "newSpacers",
          "newStem",
          "newAngle"
        ],
        "additionalProperties": false,
        "properties": {
          "refStack": {
            "type": "number",
            "minimum": 200,
            "maximum": 1000,
            "description": "Reference frame stack (mm). Vertical distance from the bottom bracket center to the top-center of the head tube. Use the exact frame size and year."
          },
          "refReach": {
            "type": "number",
            "minimum": 100,
            "maximum": 700,
            "description": "Reference frame reach (mm). Horizontal distance from the bottom bracket center to the top-center of the head tube, not handlebar reach."
          },
          "refHead": {
            "type": "number",
            "minimum": 50,
            "maximum": 90,
            "description": "Reference head angle (°). Head tube angle measured from the horizontal. Use degrees from the manufacturer geometry chart."
          },
          "refSpacers": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "description": "Reference total steerer rise (mm). Total distance along the steerer from the frame stack point to the stem-axis center. Include headset cover, spacers, and the stem clamp-center offset. Not just loose spacers."
          },
          "refStem": {
            "type": "number",
            "minimum": 10,
            "maximum": 200,
            "description": "Reference stem length (mm). Center-to-center stem length. Integrated or proprietary cockpits may not follow this model."
          },
          "refAngle": {
            "type": "number",
            "minimum": -45,
            "maximum": 45,
            "description": "Reference stem angle (°). Stem angle relative to perpendicular to the steerer, not the ground. Enter the installed orientation; a negative value lowers the stem."
          },
          "newStack": {
            "type": "number",
            "minimum": 200,
            "maximum": 1000,
            "description": "Candidate frame stack (mm). Vertical distance from the bottom bracket center to the top-center of the head tube. Use the exact frame size and year."
          },
          "newReach": {
            "type": "number",
            "minimum": 100,
            "maximum": 700,
            "description": "Candidate frame reach (mm). Horizontal distance from the bottom bracket center to the top-center of the head tube, not handlebar reach."
          },
          "newHead": {
            "type": "number",
            "minimum": 50,
            "maximum": 90,
            "description": "Candidate head angle (°). Head tube angle measured from the horizontal. Use degrees from the manufacturer geometry chart."
          },
          "newSpacers": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "description": "Candidate total steerer rise (mm). Total distance along the steerer from the frame stack point to the stem-axis center. Include headset cover, spacers, and the stem clamp-center offset. Not just loose spacers."
          },
          "newStem": {
            "type": "number",
            "minimum": 10,
            "maximum": 200,
            "description": "Candidate stem length (mm). Center-to-center stem length. Integrated or proprietary cockpits may not follow this model."
          },
          "newAngle": {
            "type": "number",
            "minimum": -45,
            "maximum": 45,
            "description": "Candidate stem angle (°). Stem angle relative to perpendicular to the steerer, not the ground. Enter the installed orientation; a negative value lowers the stem."
          }
        }
      }
    }
  },
  "execution": "local JavaScript; no hosted calculation API",
  "module": "/assets/domain.mjs",
  "operation": "compute",
  "planVersion": 1,
  "fields": [
    {
      "key": "refStack",
      "label": "Reference frame stack",
      "type": "number",
      "unit": "mm",
      "min": 200,
      "max": 1000,
      "required": true,
      "description": "Vertical distance from the bottom bracket center to the top-center of the head tube. Use the exact frame size and year.",
      "selector": "#field-refStack"
    },
    {
      "key": "refReach",
      "label": "Reference frame reach",
      "type": "number",
      "unit": "mm",
      "min": 100,
      "max": 700,
      "required": true,
      "description": "Horizontal distance from the bottom bracket center to the top-center of the head tube, not handlebar reach.",
      "selector": "#field-refReach"
    },
    {
      "key": "refHead",
      "label": "Reference head angle",
      "type": "number",
      "unit": "°",
      "min": 50,
      "max": 90,
      "required": true,
      "description": "Head tube angle measured from the horizontal. Use degrees from the manufacturer geometry chart.",
      "selector": "#field-refHead"
    },
    {
      "key": "refSpacers",
      "label": "Reference total steerer rise",
      "type": "number",
      "unit": "mm",
      "min": 0,
      "max": 100,
      "required": true,
      "description": "Total distance along the steerer from the frame stack point to the stem-axis center. Include headset cover, spacers, and the stem clamp-center offset. Not just loose spacers.",
      "selector": "#field-refSpacers"
    },
    {
      "key": "refStem",
      "label": "Reference stem length",
      "type": "number",
      "unit": "mm",
      "min": 10,
      "max": 200,
      "required": true,
      "description": "Center-to-center stem length. Integrated or proprietary cockpits may not follow this model.",
      "selector": "#field-refStem"
    },
    {
      "key": "refAngle",
      "label": "Reference stem angle",
      "type": "number",
      "unit": "°",
      "min": -45,
      "max": 45,
      "required": true,
      "description": "Stem angle relative to perpendicular to the steerer, not the ground. Enter the installed orientation; a negative value lowers the stem.",
      "selector": "#field-refAngle"
    },
    {
      "key": "newStack",
      "label": "Candidate frame stack",
      "type": "number",
      "unit": "mm",
      "min": 200,
      "max": 1000,
      "required": true,
      "description": "Vertical distance from the bottom bracket center to the top-center of the head tube. Use the exact frame size and year.",
      "selector": "#field-newStack"
    },
    {
      "key": "newReach",
      "label": "Candidate frame reach",
      "type": "number",
      "unit": "mm",
      "min": 100,
      "max": 700,
      "required": true,
      "description": "Horizontal distance from the bottom bracket center to the top-center of the head tube, not handlebar reach.",
      "selector": "#field-newReach"
    },
    {
      "key": "newHead",
      "label": "Candidate head angle",
      "type": "number",
      "unit": "°",
      "min": 50,
      "max": 90,
      "required": true,
      "description": "Head tube angle measured from the horizontal. Use degrees from the manufacturer geometry chart.",
      "selector": "#field-newHead"
    },
    {
      "key": "newSpacers",
      "label": "Candidate total steerer rise",
      "type": "number",
      "unit": "mm",
      "min": 0,
      "max": 100,
      "required": true,
      "description": "Total distance along the steerer from the frame stack point to the stem-axis center. Include headset cover, spacers, and the stem clamp-center offset. Not just loose spacers.",
      "selector": "#field-newSpacers"
    },
    {
      "key": "newStem",
      "label": "Candidate stem length",
      "type": "number",
      "unit": "mm",
      "min": 10,
      "max": 200,
      "required": true,
      "description": "Center-to-center stem length. Integrated or proprietary cockpits may not follow this model.",
      "selector": "#field-newStem"
    },
    {
      "key": "newAngle",
      "label": "Candidate stem angle",
      "type": "number",
      "unit": "°",
      "min": -45,
      "max": 45,
      "required": true,
      "description": "Stem angle relative to perpendicular to the steerer, not the ground. Enter the installed orientation; a negative value lowers the stem.",
      "selector": "#field-newAngle"
    }
  ],
  "inputShape": {
    "version": 1,
    "fields": "All 12 required fields; numeric values in declared units",
    "tables": {},
    "demo": false
  },
  "output": {
    "raw": [
      "deltaX",
      "deltaY",
      "distance",
      "length",
      "angle",
      "reference",
      "candidate"
    ],
    "lengthUnit": "mm",
    "angleUnit": "degrees"
  },
  "controls": {
    "ready": "html[data-app-ready=\"true\"]",
    "results": "#results",
    "errors": "#input-error",
    "trials": "[data-trial]",
    "swap": "#swap-bikes",
    "share": "#share-plan",
    "export": "#export-plan"
  },
  "assumptions": [
    "Use frame stack, frame reach, and head angle for the exact model year and size. These locate the top of the head tube relative to the bottom bracket.",
    "Total steerer rise is measured along the steerer to the stem-axis center. Include the headset cover, spacers below the stem, and the stem clamp-center offset. For a symmetric clamp, the last term is half the clamp height. Do not add spacers above the stem.",
    "The stem then locates the handlebar-clamp center. Compare that center on both bikes, holding bars, bar rotation, hood position, and saddle position constant. This is not a hand-position or complete bike-fit model.",
    "The inverse solution holds candidate steerer rise fixed and solves continuous stem length and angle. Trial options sample 60–140 mm stems in 10 mm steps at −17°, −10°, −6°, 0°, +6°, +10°, and +17°. They are mathematical examples, not a verified parts catalog or installation advice."
  ],
  "limitations": [
    "A cockpit calculation cannot guarantee fit, comfort, safe component installation, or handling. Validate the setup with a qualified fitter or mechanic.",
    "Trial options are not verified compatible or available components."
  ],
  "example": {
    "version": 1,
    "fields": {
      "refStack": 560,
      "refReach": 385,
      "refHead": 73,
      "refSpacers": 40,
      "refStem": 100,
      "refAngle": -6,
      "newStack": 575,
      "newReach": 390,
      "newHead": 73,
      "newSpacers": 30,
      "newStem": 100,
      "newAngle": -6
    },
    "tables": {},
    "demo": true
  }
}
