{
  "$schema": "../_schema.json",
  "format": "xlsx",
  "element": "sheet",
  "operations": {
    "add": true,
    "set": true,
    "get": true,
    "query": true,
    "remove": true
  },
  "paths": {
    "stable":     ["/<sheetName>"],
    "positional": ["/Sheet1", "/Sheet2"]
  },
  "note": "Add accepts name, position, autoFilter, tabColor, and hidden. autoFilter/tabColor/hidden forward to the same code paths Set uses; `position` is Add-only (reorder an existing sheet with the move command); `freeze` remains Set-only.",
  "properties": {
    "name": {
      "type": "string",
      "description": "sheet tab name. Returned path is /<name>; readback goes through DocumentNode.Path / .Preview rather than Format[].",
      "add": true, "set": true, "get": true,
      "examples": ["--prop name=Summary"],
      "enforcement": "report"
    },
    "autoFilter": {
      "type": "string",
      "description": "range to apply AutoFilter on (e.g. A1:D10). `true` enables on used range.",
      "aliases": ["autofilter"],
      "add": true, "set": true, "get": true,
      "examples": ["--prop autoFilter=A1:D10"],
      "readback": "range string as stored, or boolean true",
      "enforcement": "report"
    },
    "tabColor": {
      "type": "color",
      "description": "sheet tab color.",
      "add": true, "set": true, "get": true,
      "examples": ["--prop tabColor=4472C4"],
      "readback": "#RRGGBB uppercase",
      "enforcement": "report"
    },
    "hidden": {
      "type": "bool",
      "description": "hide the sheet at creation or after the fact.",
      "add": true, "set": true, "get": true,
      "examples": ["--prop hidden=true"],
      "enforcement": "report"
    },
    "freeze": {
      "type": "string",
      "description": "freeze panes anchor (cell ref). A2 freezes row 1; B1 freezes column A; B2 freezes row 1 + column A. `none` / `false` / empty removes the freeze. Set-only on existing sheets.",
      "add": false, "set": true, "get": true,
      "examples": ["--prop freeze=A2", "--prop freeze=B2", "--prop freeze=none"],
      "readback": "top-left cell ref of frozen pane (e.g. A2); absent when no freeze",
      "enforcement": "report"
    },
    "direction": {
      "type": "enum",
      "values": ["rtl", "ltr"],
      "description": "RTL sheet layout (Arabic / Hebrew) — column A renders on the right, column scroll direction inverts. Maps to <sheetView rightToLeft=...>. Canonical key matches Word/PPT.",
      "aliases": ["rtl", "rightToLeft", "righttoleft", "sheet.direction"],
      "add": false, "set": true, "get": true,
      "examples": ["--prop direction=rtl", "--prop rightToLeft=true"],
      "readback": "rtl when set; absent when default (ltr)",
      "enforcement": "report"
    },
    "zoom": {
      "type": "number",
      "description": "sheetView zoom percentage (10-400; out-of-range throws). Alias: zoomscale. Emitted only when non-default (≠100).",
      "add": false, "set": true, "get": true,
      "examples": ["--prop zoom=150"],
      "readback": "zoom percentage 10-400",
      "enforcement": "report"
    },
    "gridlines": {
      "type": "bool",
      "description": "sheetView gridline visibility. Emitted only when hidden (false); default-on is omitted (CONSISTENCY(default-omission)).",
      "add": false, "set": false, "get": true,
      "readback": "true | false",
      "enforcement": "report"
    },
    "headings": {
      "type": "bool",
      "description": "row/column header visibility. Emitted only when hidden (false); default-on is omitted (CONSISTENCY(default-omission)).",
      "add": false, "set": false, "get": true,
      "readback": "row/column headings visible",
      "enforcement": "report"
    },
    "visibility": {
      "type": "enum",
      "values": ["hidden", "veryHidden"],
      "description": "workbook-level sheet state when not visible. Emitted alongside hidden=true; absent for default-visible sheets.",
      "add": false, "set": false, "get": true,
      "readback": "if hidden",
      "enforcement": "report"
    },
    "protect": {
      "type": "bool",
      "description": "sheet protection state. On Set: pass `true` to enable protection, `false` to disable. Use the separate `password` property to set/clear an Excel legacy password hash.",
      "add": false, "set": true, "get": true,
      "readback": "true if sheet protection enabled",
      "enforcement": "report"
    },
    "password": {
      "type": "string",
      "description": "Excel legacy password hash for sheet protection (ECMA-376 14.7.1). On Set: pass plaintext password to hash and apply, or `none` to clear. Implicitly enables protection if not already set. Readback is exposed under 'passwordHash'.",
      "add": false, "set": true, "get": false,
      "examples": ["--prop password=secret123", "--prop password=none"],
      "readback": "n/a (use passwordHash on Get)",
      "enforcement": "report"
    },
    "passwordHash": {
      "type": "string",
      "description": "legacy 16-bit password hash on sheetProtection (@password), as stored in the file. Get-only readback of the 'password' Set property.",
      "add": false, "set": false, "get": true,
      "readback": "4-hex-digit legacy hash when present",
      "enforcement": "report"
    },
    "protection.algorithm": {
      "type": "string",
      "description": "modern (SHA-based) sheet-protection hash algorithm (sheetProtection/@algorithmName), e.g. SHA-512. Get-only; set via 'password' (legacy) or preserve as-is.",
      "add": false, "set": false, "get": true,
      "readback": "algorithm name when modern protection present",
      "enforcement": "report"
    },
    "protection.hash": {
      "type": "string",
      "description": "modern sheet-protection password hash (sheetProtection/@hashValue, base64). Get-only.",
      "add": false, "set": false, "get": true,
      "readback": "base64 hash when modern protection present",
      "enforcement": "report"
    },
    "protection.salt": {
      "type": "string",
      "description": "modern sheet-protection hash salt (sheetProtection/@saltValue, base64). Get-only.",
      "add": false, "set": false, "get": true,
      "readback": "base64 salt when modern protection present",
      "enforcement": "report"
    },
    "protection.spinCount": {
      "type": "number",
      "description": "modern sheet-protection hash iteration count (sheetProtection/@spinCount). Get-only.",
      "add": false, "set": false, "get": true,
      "readback": "integer spin count when modern protection present",
      "enforcement": "report"
    },
    "printTitleRows": {
      "type": "string",
      "description": "rows to repeat at top of every printed page (e.g. 1:1).",
      "add": false, "set": true, "get": false,
      "examples": ["--prop printTitleRows=1:1"],
      "readback": "n/a (set-only)",
      "enforcement": "report"
    },
    "printTitleCols": {
      "type": "string",
      "description": "columns to repeat at left of every printed page (e.g. A:A).",
      "add": false, "set": true, "get": false,
      "examples": ["--prop printTitleCols=A:A"],
      "readback": "n/a (set-only)",
      "enforcement": "report"
    },
    "orientation": {
      "type": "string",
      "description": "PageSetup orientation (portrait | landscape). Emitted only when set on the sheet.",
      "add": false, "set": false, "get": true,
      "readback": "page orientation (portrait|landscape)",
      "enforcement": "report"
    },
    "paperSize": {
      "type": "number",
      "description": "PageSetup paper-size code (OOXML enumeration; e.g. 1=Letter, 9=A4).",
      "add": false, "set": false, "get": true,
      "readback": "OOXML paper size code",
      "enforcement": "report"
    },
    "fitToPage": {
      "type": "string",
      "description": "PageSetup fit-to-page width x height (e.g. '1x1' = fit to one page).",
      "add": false, "set": false, "get": true,
      "readback": "WxH fit-to-page settings",
      "enforcement": "report"
    },
    "printArea": {
      "type": "string",
      "description": "defined-name _xlnm.Print_Area for this sheet. Get returns the A1 range with the leading 'SheetName!' prefix stripped. On Set: pass an A1 range (e.g. A1:C20) or `none` to clear.",
      "add": false, "set": true, "get": true,
      "examples": ["--prop printArea=A1:C20", "--prop printArea=none"],
      "readback": "A1 range string",
      "enforcement": "report"
    },
    "margin.top": {
      "type": "string",
      "description": "PageMargins top margin in inches (e.g. '0.75in').",
      "add": false, "set": false, "get": true,
      "readback": "margin in inches",
      "enforcement": "report"
    },
    "margin.bottom": {
      "type": "string",
      "description": "PageMargins bottom margin in inches.",
      "add": false, "set": false, "get": true,
      "readback": "margin in inches",
      "enforcement": "report"
    },
    "margin.left": {
      "type": "string",
      "description": "PageMargins left margin in inches.",
      "add": false, "set": false, "get": true,
      "readback": "margin in inches",
      "enforcement": "report"
    },
    "margin.right": {
      "type": "string",
      "description": "PageMargins right margin in inches.",
      "add": false, "set": false, "get": true,
      "readback": "margin in inches",
      "enforcement": "report"
    },
    "margin.header": {
      "type": "string",
      "description": "PageMargins header margin in inches (distance from top edge to header).",
      "add": false, "set": false, "get": true,
      "readback": "margin in inches",
      "enforcement": "report"
    },
    "margin.footer": {
      "type": "string",
      "description": "PageMargins footer margin in inches (distance from bottom edge to footer).",
      "add": false, "set": false, "get": true,
      "readback": "margin in inches",
      "enforcement": "report"
    },
    "header": {
      "type": "string",
      "description": "odd-page header text (HeaderFooter/OddHeader). Excel format codes (&L, &C, &R, &P, &D, etc.) pass through verbatim.",
      "add": false, "set": true, "get": true,
      "readback": "raw odd-header text as stored",
      "enforcement": "report"
    },
    "footer": {
      "type": "string",
      "description": "odd-page footer text (HeaderFooter/OddFooter). Excel format codes pass through verbatim.",
      "add": false, "set": true, "get": true,
      "readback": "raw odd-footer text as stored",
      "enforcement": "report"
    },
    "sort": {
      "type": "string",
      "description": "sort the sheet by one or more columns. Set input: comma-separated `Col [dir]` tokens, direction optional, defaults to asc (e.g. `A`, `A asc`, `A asc,B desc`). Use `none` to clear. Get readback: comma-separated `Col:dir` entries (colon-separated, e.g. `A:asc`).",
      "add": false, "set": true, "get": true,
      "examples": ["--prop sort=A", "--prop sort=\"A asc,B desc\"", "--prop sort=none"],
      "readback": "comma-separated `Col:asc|desc` list (e.g. `A:asc`)",
      "enforcement": "report"
    },
    "rowBreaks": {
      "type": "string",
      "description": "manual horizontal page breaks. Comma-separated row indices (1-based) where each break sits above that row.",
      "add": false, "set": false, "get": true,
      "readback": "comma-separated row break indices",
      "enforcement": "report"
    },
    "colBreaks": {
      "type": "string",
      "description": "manual vertical page breaks. Comma-separated column indices (1-based) where each break sits to the left of that column.",
      "add": false, "set": false, "get": true,
      "readback": "comma-separated column break indices",
      "enforcement": "report"
    }
  },
  "children": [
    { "element": "cell",  "pathSegment": "<A1Ref>", "cardinality": "0..n" },
    { "element": "chart", "pathSegment": "chart",   "cardinality": "0..n" }
  ]
}
