{
  "$schema": "../_schema.json",
  "format": "pptx",
  "element": "shape",
  "operations": {
    "add": true,
    "set": true,
    "get": true,
    "query": true,
    "remove": true
  },
  "paths": {
    "stable": [
      "/slide[N]/shape[@id=ID]"
    ],
    "positional": [
      "/slide[N]/shape[N]"
    ]
  },
  "note": "Positional /shape[N] enumerates ALL shapes on the slide including layout-inherited placeholders — new shapes typically land at the end, not at /shape[1]. `add` echoes the canonical /shape[@id=ID] path; prefer that for follow-up Set/Get. effective.* keys (direction, size, font, color, bold) are read-only inheritance-resolved values walked up the placeholder→layout→master→defaults chain; suppressed when the corresponding direct key is set. Each pairs with effective.*.src naming the writing layer. Cross-format note: `color=` on pptx shapes unambiguously sets text/run color. The same bare `color=` key is rejected on xlsx cells (ambiguous with fill) — use `font.color` for text or `fill` for background when working with xlsx cells.",
  "extends": "_shared/shape",
  "properties": {
    "size": {
      "type": "font-size",
      "description": "font size — Add/Set forwards to the first run; Get returns the bare size when every run shares the same explicit FontSize (non-mixed). When sizes are mixed or no run carries an explicit size, bare size is suppressed and the inheritance-resolved effective.size is emitted instead.",
      "aliases": ["fontSize", "fontsize", "font.size"],
      "add": true, "set": true, "get": true,
      "examples": ["--prop size=14", "--prop size=14pt", "--prop size=10.5pt"],
      "readback": "unit-qualified pt (e.g. \"32pt\") when all runs share one explicit FontSize; suppressed when sizes are mixed (read per-run size on the inner run) or absent (read effective.size)",
      "enforcement": "report"
    },
    "evaluated": {
      "type": "bool",
      "description": "cross-handler protocol flag — emitted on shapes whose body contains an <a:fld> dynamic field (slide number, date-time, footer, etc.). True when every dynamic field has cached text the renderer can show; false when at least one is empty (view text substitutes #OCLI_NOTEVAL!{type}; view issues emits subtype slide_field_not_evaluated). PowerPoint always re-renders fields on open, so there is no cache_stale equivalent. Read this via get --json instead of pattern-matching the sentinel.",
      "add": false, "set": false, "get": true,
      "readback": "true|false (true ⇒ all <a:fld> shapes on this node carry display text)",
      "enforcement": "report"
    },
    "isTitle": {
      "type": "bool",
      "description": "true when this shape is the slide title placeholder (or a content placeholder configured as title). Always emitted on every shape so query selectors like `shape[isTitle=true]` and `shape[isTitle=false]` resolve uniformly. Read-only — title-ness is determined by placeholder type at Add time, not as a settable property.",
      "add": false, "set": false, "get": true,
      "readback": "true|false (always present)",
      "enforcement": "report"
    },
    "opacity": {
      "type": "number",
      "description": "fill opacity (0.0 - 1.0). Requires a fill to attach to — opacity alone (without fill/gradient/pattern) has no effect in OOXML.",
      "requires": [
        "fill"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop opacity=0.5 --prop fill=FF0000"
      ],
      "readback": "number in [0, 1]",
      "enforcement": "strict"
    },
    "geometry": {
      "type": "string",
      "description": "Preset shape geometry (default: rect). The values list below is illustrative, not exhaustive — many more OOXML presets are accepted (handler-as-truth): pie, arc, chord, the directional arrows (leftArrow, upArrow, downArrow), star4/star6/star8/star10, hexagon/heptagon/octagon/decagon/dodecagon, cloud, plus the callout* family, etc. Any preset the handler recognizes round-trips.",
      "aliases": [
        "preset",
        "shape"
      ],
      "values": [
        "rect",
        "roundRect",
        "ellipse",
        "triangle",
        "diamond",
        "parallelogram",
        "rightArrow",
        "star5"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop geometry=ellipse",
        "--prop preset=roundRect"
      ],
      "readback": "preset name (e.g. \"ellipse\", \"roundRect\")",
      "enforcement": "strict"
    },
    "adj": {
      "type": "string",
      "description": "Preset adjust handles (a:prstGeom/a:avLst/a:gd). Controls the parametric proportions of a preset (arrow tail/head size, roundRect corner radius, star inner ratio, etc.). Format is \"name:formula\" where formula is an OOXML guide formula such as \"val 6000\". Multiple handles are comma-separated.",
      "aliases": [],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop geometry=leftArrow --prop adj=adj1:val 80000",
        "--prop geometry=roundRect --prop adj=adj:val 16667",
        "--prop adj=\"adj1:val 6000,adj2:val 12000\""
      ],
      "readback": "comma-separated name:formula handles (e.g. \"adj1:val 80000\")",
      "enforcement": "lenient"
    },
    "textFill": {
      "type": "string",
      "description": "Fill applied to the text glyphs (a:rPr fill). Accepts a color (solid glyph fill) or round-trips a gradient. The legacy alias 'textGradient' canonicalizes to 'textFill' on readback.",
      "aliases": [
        "textGradient"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop textFill=FF0000"
      ],
      "readback": "canonical textFill value",
      "enforcement": "lenient"
    },
    "textWarp": {
      "type": "string",
      "description": "WordArt text warp preset applied to the shape's text body (a:bodyPr/a:prstTxWarp @prst). Use 'none' to remove. The HTML preview surfaces the active warp as a data-textwarp attribute + a 'text-warp' marker class on the shape; real PowerPoint renders the per-glyph warp path.",
      "values": [
        "none",
        "textNoShape",
        "textPlain",
        "textArchUp",
        "textArchDown",
        "textCircle",
        "textWave1",
        "textWave2",
        "textInflate",
        "textDeflate",
        "textCanUp",
        "textCanDown"
      ],
      "add": false,
      "set": true,
      "get": true,
      "examples": [
        "--prop textWarp=textArchUp",
        "--prop textWarp=textWave1"
      ],
      "readback": "warp preset name (e.g. \"textArchUp\")",
      "enforcement": "report"
    },
    "font.latin": {
      "type": "string",
      "description": "Latin-script font slot only (a:latin). Use to target ASCII/European text without overwriting CJK / complex-script slots.",
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop font.latin=Calibri"
      ],
      "readback": "typeface (only emitted when it differs from the bare 'font' slot)",
      "enforcement": "report"
    },
    "font.ea": {
      "type": "string",
      "description": "East-Asian font slot (a:ea) — Chinese / Japanese / Korean text.",
      "aliases": [
        "font.eastasia",
        "font.eastasian"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop font.ea=\"メイリオ\""
      ],
      "readback": "typeface (only emitted when it differs from the bare 'font' slot)",
      "enforcement": "report"
    },
    "font.cs": {
      "type": "string",
      "description": "Complex-script font slot (a:cs) — Arabic / Hebrew / Thai etc.",
      "aliases": [
        "font.complexscript",
        "font.complex"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop font.cs=\"Arabic Typesetting\""
      ],
      "readback": "typeface",
      "enforcement": "report"
    },
    "direction": {
      "type": "enum",
      "values": [
        "ltr",
        "rtl"
      ],
      "description": "paragraph reading direction (a:pPr rtl). Use 'rtl' for Arabic / Hebrew layouts.",
      "aliases": [
        "dir",
        "rtl"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop direction=rtl"
      ],
      "readback": "rtl, or ltr. Set direction=ltr pins ltr explicitly by writing rtl=\"0\" so the paragraph overrides any inherited master/layout RTL; Add omits rtl when ltr (relies on the default). Clearing direction removes the attribute.",
      "enforcement": "report"
    },
    "margin": {
      "type": "length",
      "description": "uniform internal padding (text inset) for shape body (a:bodyPr lIns/tIns/rIns/bIns). Also accepts a 4-value 'l,t,r,b' form on Set.",
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop margin=4",
        "--prop margin=0.1in"
      ],
      "readback": "unit-qualified length (e.g. '14.4pt' / '0.36cm') when all four insets are equal; otherwise 'l,t,r,b' with '-' for unset sides",
      "enforcement": "report"
    },
    "textDirection": {
      "type": "string",
      "description": "shape text rotation (a:bodyPr @vert) — works on shapes/textboxes, not just table cells. horizontal|vertical90|vertical270|eaVert|stacked. Round-trips through the same canonical vocabulary as table-cell textDirection. Note: the Get readback key is lowercase 'textdirection'.",
      "aliases": [
        "textdir",
        "vert"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop textDirection=vertical270",
        "--prop textDirection=stacked"
      ],
      "readback": "horizontal|vertical90|vertical270|stacked",
      "enforcement": "report"
    },
    "strike": {
      "type": "enum",
      "description": "strikethrough on shape text. Single and double are distinct OOXML tokens (sngStrike / dblStrike); Word splits these into `strike` + `dstrike`, PowerPoint folds both into one attribute.",
      "values": [
        "none",
        "single",
        "double"
      ],
      "aliases": [
        "strikethrough",
        "font.strike",
        "font.strikethrough"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop strike=single",
        "--prop strike=double",
        "--prop strike=true"
      ],
      "readback": "single | double | none. Boolean `true` on add/set is accepted as an alias for `single`.",
      "enforcement": "report"
    },
    "highlight": {
      "type": "color",
      "description": "text highlight color behind the glyphs (a:highlight). Unlike Word's fixed named-color list, accepts any color (hex, named, rgb(), scheme names like accent1). 'none'/'false' removes the highlight.",
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop highlight=FFFF00",
        "--prop highlight=accent1",
        "--prop highlight=none"
      ],
      "readback": "#RRGGBB hex (or scheme color name) read from the first run's a:highlight",
      "enforcement": "report"
    },
    "cap": {
      "type": "enum",
      "description": "letter-case rendering mode for shape text (rPr/cap).",
      "values": [
        "none",
        "small",
        "all"
      ],
      "aliases": [
        "allCaps",
        "allcaps",
        "smallCaps",
        "smallcaps"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop cap=all",
        "--prop allCaps=true"
      ],
      "readback": "none | small | all",
      "enforcement": "report"
    },
    "lang": {
      "type": "string",
      "description": "BCP-47 language tag. lang lives per-run (drawingML a:rPr/@lang) — a shape has no language of its own, only an aggregate of differently-tongued runs. add/set on a shape is a convenience that writes the FIRST run's rPr; read it back at run scope (/shape[N]/paragraph[P]/run[R]). Not surfaced at shape level: a first-run projection cannot say which language each run is, and a newly added run would not inherit it.",
      "aliases": [
        "altLang",
        "altlang"
      ],
      "add": true,
      "set": true,
      "get": false,
      "examples": [
        "--prop lang=en-US"
      ],
      "readback": "run scope only (/shape[N]/paragraph[P]/run[R])",
      "enforcement": "report"
    },
    "spacing": {
      "type": "number",
      "description": "character spacing in 1/100 pt (drawingML rPr/@spc).",
      "aliases": [
        "spc",
        "charspacing",
        "letterspacing"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop spacing=200"
      ],
      "readback": "integer",
      "enforcement": "report"
    },
    "kern": {
      "type": "number",
      "description": "minimum kerning size in 1/100 pt (drawingML rPr/@kern). Get surfaces the raw integer via long-tail rPr attribute readback.",
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop kern=1200"
      ],
      "readback": "integer",
      "enforcement": "report"
    },
    "autoFit": {
      "type": "enum",
      "values": [
        "normal",
        "shrink",
        "shape",
        "none"
      ],
      "aliases": [
        "autofit"
      ],
      "add": true,
      "set": true,
      "get": true,
      "description": "text body auto-fit mode. 'normal'/'shrink' shrinks text to fit (normAutofit); 'shape' resizes the shape to fit text; 'none' overflows. Aliases (Add+Set): true/shrink → normal, resize → shape, false → none.",
      "examples": [
        "--prop autoFit=normal",
        "--prop autoFit=shrink",
        "--prop autoFit=shape",
        "--prop autoFit=none"
      ],
      "readback": "normal | shape | none",
      "enforcement": "report"
    },
    "fontScale": {
      "type": "string",
      "aliases": [
        "fontscale"
      ],
      "add": true,
      "set": true,
      "get": true,
      "description": "normAutofit font-scale (shrink-to-fit text ratio). Input as a percent: bare integer 0-100 (75 → 75%) or N% form ('75%'). Stored as OOXML thousandths-of-percent (75000); readback emits the raw OOXML integer.",
      "examples": [
        "--prop fontScale=75",
        "--prop fontScale=75%"
      ],
      "readback": "OOXML thousandths-of-percent (e.g. 75000)",
      "enforcement": "report"
    },
    "lnSpcReduction": {
      "type": "string",
      "aliases": [
        "lnspcreduction",
        "lineSpaceReduction",
        "linespacereduction",
        "lineSpacingReduction",
        "linespacingreduction"
      ],
      "add": true,
      "set": true,
      "get": true,
      "description": "normAutofit line-space reduction (shrink-to-fit spacing ratio). Input as a percent: bare integer 0-100 (20 → 20%) or N% form ('20%'). Stored as OOXML thousandths-of-percent (20000); readback emits the raw OOXML integer.",
      "examples": [
        "--prop lnSpcReduction=20",
        "--prop lineSpaceReduction=20%"
      ],
      "readback": "OOXML thousandths-of-percent (e.g. 20000)",
      "enforcement": "report"
    },
    "lineSpacing": {
      "type": "string",
      "description": "line spacing for shape paragraphs (multiplier or pt).",
      "aliases": [
        "linespacing"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop lineSpacing=1.5x"
      ],
      "readback": "1.5x or 18pt",
      "enforcement": "report"
    },
    "spaceBefore": {
      "type": "length",
      "aliases": [
        "spacebefore"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop spaceBefore=6pt"
      ],
      "readback": "unit-qualified pt",
      "enforcement": "report"
    },
    "spaceAfter": {
      "type": "length",
      "aliases": [
        "spaceafter"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop spaceAfter=6pt"
      ],
      "readback": "unit-qualified pt",
      "enforcement": "report"
    },
    "gradient": {
      "type": "string",
      "description": "gradient fill spec. Linear: 'C1-C2[-ANGLE]' or 'LINEAR;C1;C2;ANGLE'. Radial: 'radial:C1-C2[-FOCUS]' (focus: tl/tr/bl/br/center). Path: 'path:C1-C2[-FOCUS]'. Per-stop position: 'C@PCT' (e.g. 'FF0000@0-0000FF@100').",
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop gradient=\"FF0000-0000FF\"",
        "--prop gradient=\"FF0000-0000FF-90\"",
        "--prop gradient=\"LINEAR;FF0000;0000FF;45\"",
        "--prop gradient=\"radial:4B0082-1E90FF-center\""
      ],
      "readback": "linear: 'linear;C1;C2;ANGLE' (semicolon-separated, degree integer). radial/path: 'radial:C1-C2-FOCUS' / 'path:C1-C2-FOCUS'. When gradient is present, 'fill' reads back as 'gradient' unless a solidFill also exists.",
      "enforcement": "report"
    },
    "pattern": {
      "type": "string",
      "description": "pattern fill: 'preset' or 'preset:fg' or 'preset:fg:bg' (defaults: fg=000000, bg=FFFFFF).",
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop pattern=\"diagBrick:FF0000:FFFFFF\""
      ],
      "readback": "preset:fg_color[:bg_color] e.g. diagBrick:#FF0000:#FFFFFF",
      "enforcement": "report"
    },
    "image": {
      "type": "string",
      "description": "image (blip) fill: path to a local image file used as the shape fill.",
      "aliases": [
        "imagefill"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop image=/path/to/photo.png"
      ],
      "readback": "\"true\" when shape has an image (blipFill) fill",
      "enforcement": "report"
    },
    "fillRect": {
      "type": "string",
      "description": "image-fill stretch insets as \"l,t,r,b\" in thousandths of a percent (perMille). Positive insets letterbox the image inside the shape; negative insets oversize it (cover-style framing). Applies to an image (blipFill) shape; consumed alongside image=.",
      "aliases": [
        "fillrect"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop image=/path/photo.png --prop fillRect=0,-36364,0,-85860"
      ],
      "readback": "\"l,t,r,b\" perMille when the shape's blipFill stretch carries non-zero insets",
      "enforcement": "report"
    },
    "srcRect": {
      "type": "string",
      "description": "image-fill source crop as \"l,t,r,b\" in thousandths of a percent (perMille) — the fraction trimmed from each edge of the source image before it fills the shape. Applies to an image (blipFill) shape; consumed alongside image=.",
      "aliases": [
        "srcrect"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop image=/path/photo.png --prop srcRect=10000,0,10000,0"
      ],
      "readback": "\"l,t,r,b\" perMille when the shape's blipFill carries a srcRect crop",
      "enforcement": "report"
    },
    "lineWidth": {
      "type": "length",
      "description": "outline width.",
      "aliases": [
        "linewidth"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop lineWidth=1pt"
      ],
      "readback": "length in pt (e.g. \"1pt\")",
      "enforcement": "report"
    },
    "lineDash": {
      "type": "enum",
      "description": "outline dash pattern (drawingML prstDash). Also reachable as the third segment of the compound line='color:width:style' form.",
      "aliases": [
        "linedash",
        "line.dash"
      ],
      "values": [
        "solid",
        "dot",
        "dash",
        "dashDot",
        "lgDash",
        "lgDashDot",
        "lgDashDotDot",
        "sysDot",
        "sysDash",
        "sysDashDot",
        "sysDashDotDot",
        "longdash",
        "longdashdot"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop lineDash=dash",
        "--prop lineDash=dashDot",
        "--prop lineDash=sysDash",
        "--prop line=FF0000:1.5:dash"
      ],
      "readback": "canonical OOXML prstDash token (solid | dot | dash | dashDot | lgDash | lgDashDot | lgDashDotDot | sysDot | sysDash | sysDashDot | sysDashDotDot). 'longdash'/'longdashdot' are accepted on input as aliases for lgDash/lgDashDot. 'dashDotDot' has no native enum member; it is accepted as an alias for sysDashDotDot (Get readback returns sysDashDotDot).",
      "enforcement": "report"
    },
    "lineGradient": {
      "type": "string",
      "description": "gradient outline (drawingML <a:ln>/<a:gradFill>). Accepts a stop list 'color@pos,color@pos,...' (pos in percent) with an optional 'angle=Ndeg' segment, mirroring the fill gradient form. Set/Add replace any solid outline color. Get readback is emitted under the canonical key 'line.gradient'.",
      "aliases": [
        "linegradient",
        "line.gradient"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop lineGradient=\"FF0000@0,0000FF@100\"",
        "--prop lineGradient=\"FF0000@0,00FF00@50,0000FF@100,angle=90deg\""
      ],
      "readback": "gradient stop string (canonical key line.gradient)",
      "enforcement": "report"
    },
    "lineCap": {
      "type": "enum",
      "description": "line end cap style (drawingML <a:ln @cap>). Affects how the stroke terminates at endpoints (and dash gaps for dashed strokes).",
      "aliases": [
        "linecap",
        "line.cap"
      ],
      "values": [
        "round",
        "flat",
        "square"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop lineCap=round"
      ],
      "readback": "round | flat | square",
      "enforcement": "report"
    },
    "lineJoin": {
      "type": "enum",
      "description": "line join style at shape corners (drawingML <a:ln> child <a:round/> | <a:bevel/> | <a:miter/>). Accepts compound 'miter:<lim>' to also set the miter limit in one key.",
      "aliases": [
        "linejoin",
        "line.join"
      ],
      "values": [
        "round",
        "bevel",
        "miter"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop lineJoin=miter",
        "--prop lineJoin=miter:800000"
      ],
      "readback": "round | bevel | miter",
      "enforcement": "report"
    },
    "miterLimit": {
      "type": "number",
      "description": "miter join limit (drawingML <a:miter @lim>) in 1000ths of a percent (e.g. 800000 = 800%). Implies lineJoin=miter when set without an explicit lineJoin.",
      "aliases": [
        "miterlimit",
        "miter.limit",
        "line.miterlimit"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop miterLimit=800000"
      ],
      "readback": "integer (1000ths of a percent)",
      "enforcement": "report"
    },
    "cmpd": {
      "type": "enum",
      "description": "compound line style (drawingML <a:ln @cmpd>) for double/triple/asymmetric strokes.",
      "aliases": [
        "compoundLine",
        "compoundline",
        "line.compound"
      ],
      "values": [
        "sng",
        "dbl",
        "thickThin",
        "thinThick",
        "tri"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop cmpd=dbl",
        "--prop cmpd=thickThin"
      ],
      "readback": "canonical OOXML token (sng | dbl | thickThin | thinThick | tri)",
      "enforcement": "report"
    },
    "lineAlign": {
      "type": "enum",
      "description": "stroke alignment relative to the path (drawingML <a:ln @algn>). 'ctr' centers the stroke on the path; 'in' insets it inside the shape boundary.",
      "aliases": [
        "linealign",
        "line.align"
      ],
      "values": [
        "ctr",
        "in"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop lineAlign=ctr"
      ],
      "readback": "ctr | in",
      "enforcement": "report"
    },
    "headEnd": {
      "type": "enum",
      "description": "arrowhead at the line's start (drawingML <a:headEnd type=...>). Supported on any outline (shape or connector), not connector-only.",
      "aliases": [
        "headend",
        "arrowStart",
        "arrowstart"
      ],
      "values": [
        "none",
        "triangle",
        "stealth",
        "diamond",
        "oval",
        "arrow"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop headEnd=triangle"
      ],
      "readback": "canonical OOXML token (none | triangle | stealth | diamond | oval | arrow)",
      "enforcement": "report"
    },
    "tailEnd": {
      "type": "enum",
      "description": "arrowhead at the line's end (drawingML <a:tailEnd type=...>). Supported on any outline (shape or connector).",
      "aliases": [
        "tailend",
        "arrowEnd",
        "arrowend"
      ],
      "values": [
        "none",
        "triangle",
        "stealth",
        "diamond",
        "oval",
        "arrow"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop tailEnd=arrow"
      ],
      "readback": "canonical OOXML token (none | triangle | stealth | diamond | oval | arrow)",
      "enforcement": "report"
    },
    "list": {
      "type": "string",
      "description": "list style for shape paragraphs (bullet|numbered|alpha|roman|none|<char>).",
      "aliases": [
        "liststyle"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop list=bullet"
      ],
      "readback": "list style token of the first paragraph",
      "enforcement": "report"
    },
    "link": {
      "type": "string",
      "description": "click-action target for the shape. Accepts an absolute URI (https://, mailto:, tel:, …), slide[N] for an in-deck jump (1-based; the target slide must already exist), or a named navigation action (firstslide, lastslide, nextslide, previousslide, endshow). Pass 'none' or empty to clear.",
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop link=https://example.com",
        "--prop link=slide[3]",
        "--prop link=nextslide"
      ],
      "readback": "URL / slide[N] / named action",
      "enforcement": "report"
    },
    "tooltip": {
      "type": "string",
      "description": "tooltip / screen-tip text for hyperlink. Applied together with `link` in a single set/add call; standalone tooltip without link is not supported (no hyperlink relationship to attach to). Set-side may update an existing hyperlink's tooltip in-place without re-supplying link.",
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop link=https://example.com --prop tooltip=\"click here\""
      ],
      "readback": "hyperlink screen-tip text",
      "enforcement": "report"
    },
    "animation": {
      "type": "string",
      "description": "animation effect spec.",
      "aliases": [
        "animate"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop animation=fade"
      ],
      "readback": "synthesized effect spec of the form \"effect-class-durationMs\" (e.g. \"fade-entrance-400\"), resolved from the slide Timing tree; absent when the shape has no animation",
      "enforcement": "report"
    },
    "effective.direction": {
      "type": "enum",
      "values": [
        "rtl",
        "ltr"
      ],
      "description": "resolved reading direction inherited from placeholder→layout→master→presentation defaults. Suppressed when 'direction' is set directly on the shape.",
      "add": false,
      "set": false,
      "get": true,
      "readback": "rtl | ltr",
      "enforcement": "report"
    },
    "effective.size": {
      "type": "length",
      "description": "resolved font size inherited from placeholder→layout→master→presentation defaults. Suppressed when 'size' is set directly on the shape.",
      "add": false,
      "set": false,
      "get": true,
      "readback": "unit-qualified pt (e.g. \"18pt\")",
      "enforcement": "report"
    },
    "effective.font": {
      "type": "string",
      "description": "resolved font name inherited from placeholder→layout→master→presentation defaults. Suppressed when 'font' is set directly on the shape.",
      "add": false,
      "set": false,
      "get": true,
      "readback": "font name",
      "enforcement": "report"
    },
    "effective.color": {
      "type": "color",
      "description": "resolved text color inherited from placeholder→layout→master→presentation defaults. Suppressed when 'color' is set directly on the shape.",
      "add": false,
      "set": false,
      "get": true,
      "readback": "#-prefixed uppercase hex (scheme colors pass through)",
      "enforcement": "report"
    },
    "effective.bold": {
      "type": "bool",
      "description": "resolved bold inherited from placeholder→layout→master→presentation defaults. Suppressed when 'bold' is set directly on the shape.",
      "add": false,
      "set": false,
      "get": true,
      "readback": "true/false",
      "enforcement": "report"
    },
    "effective.italic": { "type": "bool", "description": "resolved italic via cascade.", "add": false, "set": false, "get": true, "readback": "true/false", "enforcement": "report" },
    "effective.underline": { "type": "string", "description": "resolved underline via cascade.", "add": false, "set": false, "get": true, "readback": "single/double/none", "enforcement": "report" },
    "effective.strike": { "type": "string", "description": "resolved strike via cascade.", "add": false, "set": false, "get": true, "readback": "single/double/none", "enforcement": "report" },
    "effective.font.latin": { "type": "string", "description": "resolved Latin font via cascade.", "add": false, "set": false, "get": true, "readback": "font name", "enforcement": "report" },
    "effective.font.ea": { "type": "string", "description": "resolved East Asian font via cascade.", "add": false, "set": false, "get": true, "readback": "font name", "enforcement": "report" },
    "effective.font.cs": { "type": "string", "description": "resolved complex script font via cascade.", "add": false, "set": false, "get": true, "readback": "font name", "enforcement": "report" },
    "effective.align": { "type": "string", "description": "resolved paragraph alignment via cascade.", "add": false, "set": false, "get": true, "readback": "left/center/right/justify", "enforcement": "report" },
    "effective.lineSpacing": { "type": "string", "description": "resolved line spacing via cascade.", "add": false, "set": false, "get": true, "readback": "multiplier (e.g. 1.5x) or fixed pt", "enforcement": "report" },
    "effective.spaceBefore": { "type": "length", "description": "resolved spaceBefore via cascade.", "add": false, "set": false, "get": true, "readback": "unit-qualified pt", "enforcement": "report" },
    "effective.spaceAfter": { "type": "length", "description": "resolved spaceAfter via cascade.", "add": false, "set": false, "get": true, "readback": "unit-qualified pt", "enforcement": "report" },
    "effective.size.src": { "type": "string", "description": "path of the cascade layer that wrote effective.size.", "add": false, "set": false, "get": true, "readback": "path string", "enforcement": "report" },
    "effective.font.src": { "type": "string", "description": "path of the cascade layer that wrote effective.font.", "add": false, "set": false, "get": true, "readback": "path string", "enforcement": "report" },
    "effective.font.latin.src": { "type": "string", "description": "path of the cascade layer that wrote effective.font.latin.", "add": false, "set": false, "get": true, "readback": "path string", "enforcement": "report" },
    "effective.font.ea.src": { "type": "string", "description": "path of the cascade layer that wrote effective.font.ea.", "add": false, "set": false, "get": true, "readback": "path string", "enforcement": "report" },
    "effective.font.cs.src": { "type": "string", "description": "path of the cascade layer that wrote effective.font.cs.", "add": false, "set": false, "get": true, "readback": "path string", "enforcement": "report" },
    "effective.color.src": { "type": "string", "description": "path of the cascade layer that wrote effective.color.", "add": false, "set": false, "get": true, "readback": "path string", "enforcement": "report" },
    "effective.bold.src": { "type": "string", "description": "path of the cascade layer that wrote effective.bold.", "add": false, "set": false, "get": true, "readback": "path string", "enforcement": "report" },
    "effective.italic.src": { "type": "string", "description": "path of the cascade layer that wrote effective.italic.", "add": false, "set": false, "get": true, "readback": "path string", "enforcement": "report" },
    "effective.underline.src": { "type": "string", "description": "path of the cascade layer that wrote effective.underline.", "add": false, "set": false, "get": true, "readback": "path string", "enforcement": "report" },
    "effective.strike.src": { "type": "string", "description": "path of the cascade layer that wrote effective.strike.", "add": false, "set": false, "get": true, "readback": "path string", "enforcement": "report" },
    "effective.align.src": { "type": "string", "description": "path of the cascade layer that wrote effective.align.", "add": false, "set": false, "get": true, "readback": "path string", "enforcement": "report" },
    "effective.lineSpacing.src": { "type": "string", "description": "path of the cascade layer that wrote effective.lineSpacing.", "add": false, "set": false, "get": true, "readback": "path string", "enforcement": "report" },
    "effective.spaceBefore.src": { "type": "string", "description": "path of the cascade layer that wrote effective.spaceBefore.", "add": false, "set": false, "get": true, "readback": "path string", "enforcement": "report" },
    "effective.spaceAfter.src": { "type": "string", "description": "path of the cascade layer that wrote effective.spaceAfter.", "add": false, "set": false, "get": true, "readback": "path string", "enforcement": "report" },
    "id": {
      "type": "number",
      "description": "cNvPr shape id; @id in /shape[@id=ID]. add honors a caller-supplied id so dump-replay keeps it stable for spTgt animation refs; immutable after creation.",
      "add": true,
      "set": false,
      "get": true,
      "readback": "integer shape id",
      "enforcement": "report"
    },
    "zorder": {
      "type": "number",
      "description": "1-based z-order in slide shape tree. On add/set, repositions the shape within the shape tree (1 = back).",
      "aliases": ["z-order", "order"],
      "add": true,
      "set": true,
      "get": true,
      "examples": ["--prop zorder=1"],
      "readback": "1-based integer (1 = back)",
      "enforcement": "report"
    },
    "bevel": {
      "type": "string",
      "add": true,
      "set": true,
      "get": true,
      "description": "3-D top bevel descriptor (sp3d.bevelT). Form: 'preset[-width[-height]]' with width/height in points; height defaults to width. Preset values: angle, artDeco, circle, convex, coolSlant, cross, divot, hardEdge, relaxedInset, riblet, slope, softRound. Example: 'circle-6-6'.",
      "examples": [
        "--prop bevel=circle",
        "--prop bevel=circle-6",
        "--prop bevel=angle-8-4"
      ],
      "readback": "'preset' alone when width=height=6pt (OOXML default — 'circle-6' reads back as 'circle'), 'preset-N' when width=height=N (symmetric, e.g. 'circle-4'), or 'preset-widthPt-heightPt' when width≠height. Surfaces when sp3d.bevelT is present.",
      "enforcement": "report"
    },
    "bevelBottom": {
      "type": "string",
      "add": true,
      "set": true,
      "get": true,
      "description": "3-D bottom bevel descriptor (sp3d.bevelB). Same grammar as 'bevel'. Single-size shorthand 'preset-N' sets width=height=N.",
      "examples": [
        "--prop bevelBottom=circle-4",
        "--prop bevelBottom=circle-4-4"
      ],
      "readback": "'preset' alone when default size (6pt), 'preset-N' when width=height=N (symmetric), or 'preset-widthPt-heightPt' when width≠height.",
      "enforcement": "report"
    },
    "depth": {
      "type": "length",
      "add": true,
      "set": true,
      "get": true,
      "description": "3-D extrusion height (sp3d @extrusionH). Accepts the canonical length input forms — bare number is points, also accepts pt/cm/in/px/emu suffix. 'none' or '0' clears.",
      "examples": [
        "--prop depth=10",
        "--prop depth=10pt",
        "--prop depth=0.5cm",
        "--prop depth=none"
      ],
      "readback": "bare numeric points (e.g. '10', '14.17').",
      "enforcement": "report"
    },
    "lighting": {
      "type": "string",
      "add": true,
      "set": true,
      "get": true,
      "description": "3-D scene lighting rig name (scene3d.lightRig @rig). OOXML preset rig values: threePt, balanced, soft, harsh, flood, contrasting, morning, sunrise, sunset, chilly, freezing, flat, twoPt, glow, brightRoom.",
      "examples": [
        "--prop lighting=threePt",
        "--prop lighting=balanced"
      ],
      "readback": "OOXML preset light rig token.",
      "enforcement": "report"
    },
    "material": {
      "type": "string",
      "add": true,
      "set": true,
      "get": true,
      "description": "3-D preset material (sp3d.prstMaterial). Accepted tokens (case-insensitive): clear, darkEdge (alias dkEdge), flat, matte, metal, plastic, powder, softEdge, softMetal, translucentPowder, warmMatte, wireframe (alias wire).",
      "examples": [
        "--prop material=metal",
        "--prop material=plastic"
      ],
      "readback": "OOXML preset material token.",
      "enforcement": "report"
    },
    "reflection": {
      "type": "string",
      "description": "reflection effect. Accepts 'true' / 'tight' / 'half' / 'full' to enable a reflection of varying length, or 'none' to clear.",
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop reflection=true",
        "--prop reflection=half",
        "--prop reflection=full"
      ],
      "readback": "tight | half | full (mapped from a:reflection @endPos: <70000=tight, <95000=half, else=full).",
      "enforcement": "report"
    },
    "shadow": {
      "type": "string",
      "description": "outer shadow. Pass a color (e.g. '000000') or 'true' (defaults to black). Routed to text-level rPr for text-only shapes.",
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop shadow=#808080",
        "--prop shadow=none",
        "--prop shadow=000000",
        "--prop shadow=true"
      ],
      "readback": "compound '#RRGGBB-blurPt-angleDeg-distPt-opacityPct' (e.g. '#000000-4-45-3-40'). Color is a '#'-prefixed 6-digit hex (the alpha is carried solely by the trailing opacity field, never double-encoded as an alpha byte); blur, distance in pt; angle in degrees; opacity in percent (0-100).",
      "enforcement": "report"
    },
    "innerShadow": {
      "type": "string",
      "description": "inner shadow (a:innerShdw) as `color-blur-angle-dist-opacity` (mirrors `shadow`). Input color is hex (with or without `#`, 6- or 8-digit `RRGGBBAA`) or a scheme name (with optional +lumMod/+shade transforms); blur/dist in points; angle in degrees; opacity 0-100. Rendered as a CSS inset box-shadow in the HTML preview.",
      "aliases": [
        "innershadow"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop innerShadow=000000",
        "--prop innerShadow=FF0000-4-45-3-60"
      ],
      "readback": "compound '#RRGGBB-blurPt-angleDeg-distPt-opacityPct' (e.g. '#FF0000-4-45-3-60'). Color is a '#'-prefixed 6-digit hex (alpha carried solely by the trailing opacity field); blur, distance in pt; angle in degrees; opacity in percent (0-100).",
      "enforcement": "report"
    },
    "glow": {
      "type": "string",
      "description": "glow effect. Pass a color (e.g. '4472C4') or 'true' (defaults to accent blue).",
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop glow=#4472C4",
        "--prop glow=4472C4",
        "--prop glow=true"
      ],
      "readback": "compound '#RRGGBBAA-radiusPt-opacityPct' (e.g. '#4472C4BF-8-75'). Color is CSS-form 8-digit hex with leading # (alpha last); radius in pt; opacity in percent.",
      "enforcement": "report"
    },
    "flipH": {
      "type": "bool",
      "aliases": ["flipHorizontal"],
      "description": "Flip horizontally (Office-API alias of flip=h).",
      "add": true,
      "set": true,
      "get": true,
      "examples": ["--prop flipH=true"],
      "readback": "true when the shape carries a horizontal flip",
      "enforcement": "report"
    },
    "flipV": {
      "type": "bool",
      "aliases": ["flipVertical"],
      "description": "Flip vertically (Office-API alias of flip=v).",
      "add": true,
      "set": true,
      "get": true,
      "examples": ["--prop flipV=true"],
      "readback": "true when the shape carries a vertical flip",
      "enforcement": "report"
    },
    "lineOpacity": {
      "type": "number",
      "add": true,
      "set": true,
      "get": true,
      "requires": ["line"],
      "description": "shape outline alpha as fraction (0..1). Requires an outline (line/lineColor) to attach to. Surfaces when the outline carries an a:alpha child.",
      "examples": [
        "--prop line=FF0000:2:solid --prop lineOpacity=0.5"
      ],
      "readback": "fraction 0..1",
      "enforcement": "report"
    },
    "x": {
      "type": "length",
      "description": "x in EMU/length form (e.g. 2cm). pptx absolute positioning.",
      "aliases": [
        "left"
      ],
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop x=2",
        "--prop x=2cm",
        "--prop x=1in",
        "--prop x=72pt"
      ],
      "readback": "length string (FormatEmu)",
      "enforcement": "strict"
    },
    "y": {
      "type": "string",
      "description": "y in EMU/length form (e.g. 2cm). pptx absolute positioning.",
      "add": true,
      "set": true,
      "get": true,
      "examples": [
        "--prop y=3",
        "--prop y=3cm"
      ],
      "enforcement": "report",
      "aliases": [
        "top"
      ],
      "readback": "length string (FormatEmu)"
    },
    "width": {
      "type": "string",
      "description": "width in EMU/length form (e.g. 2cm). pptx absolute positioning.",
      "add": true,
      "set": true,
      "get": true,
      "aliases": [
        "w"
      ],
      "examples": [
        "--prop width=4",
        "--prop width=6cm",
        "--prop width=5cm"
      ],
      "enforcement": "report",
      "readback": "length string (FormatEmu)"
    },
    "height": {
      "type": "string",
      "description": "height in EMU/length form (e.g. 2cm). pptx absolute positioning.",
      "add": true,
      "set": true,
      "get": true,
      "aliases": [
        "h"
      ],
      "examples": [
        "--prop height=3",
        "--prop height=3cm"
      ],
      "enforcement": "report",
      "readback": "length string (FormatEmu)"
    }
  }
}
