{
  "version": "0.9.0",
  "artifact": "landometer-design-identity-playground-v0.9.0",
  "controls": [
    {
      "id": "skip-main",
      "accessibleName": "Skip to main content",
      "userJob": "Bypass the repeated header",
      "effect": "Navigate to #main",
      "keyboardTouch": "Enter or touch",
      "feedback": "Main content receives the navigation target",
      "recovery": "Continue with sequential keyboard navigation",
      "finalState": "Main content receives the navigation target",
      "failureRecovery": "Continue with sequential keyboard navigation",
      "browserTest": "Invoke #skip-main using Enter or touch; assert: Navigate to #main; then verify: Main content receives the navigation target; recovery: Continue with sequential keyboard navigation."
    },
    {
      "id": "home-link",
      "accessibleName": "Landometer — return to the start",
      "userJob": "Return to the opening invitation",
      "effect": "Navigate to #top",
      "keyboardTouch": "Enter or touch",
      "feedback": "Opening scene is in view",
      "recovery": "Use browser Back or scroll",
      "finalState": "Opening scene is in view",
      "failureRecovery": "Use browser Back or scroll",
      "browserTest": "Invoke #home-link using Enter or touch; assert: Navigate to #top; then verify: Opening scene is in view; recovery: Use browser Back or scroll."
    },
    {
      "id": "theme-cycle",
      "accessibleName": "Theme state and next theme",
      "userJob": "Cycle between device preference, Light, and Dark from one quiet control",
      "effect": "Advance system → light → dark → system; update icon, accessible label, URL, and local preference",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "The icon, aria-label, resolved theme, and URL update immediately",
      "recovery": "Continue cycling until device preference is restored",
      "finalState": "Exactly one of system, light, or dark is active and persisted locally",
      "failureRecovery": "Continue cycling until device preference is restored",
      "browserTest": "Click #theme-cycle three times; assert system → light → dark → system, one visible matching SVG icon, updated aria-label, and URL state after each click."
    },
    {
      "id": "language-cycle",
      "accessibleName": "Current language and next language",
      "userJob": "Switch between Thai and English from one quiet control",
      "effect": "Toggle th ↔ en; update visible state, accessible label, URL, and local preference",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "TH/EN state and all governed bilingual content update immediately",
      "recovery": "Activate once more to return to the previous language",
      "finalState": "Exactly one locale is visible and persisted locally",
      "failureRecovery": "Activate once more to return to the previous language",
      "browserTest": "Click #language-cycle twice; assert TH → EN → TH, one active locale, updated aria-label, and URL state after each click."
    },
    {
      "id": "start",
      "accessibleName": "Open the practice fixture",
      "userJob": "Reach the interactive work-object comparison",
      "effect": "Navigate to #play",
      "keyboardTouch": "Enter or touch",
      "feedback": "Playground is in view",
      "recovery": "Use browser Back or scroll",
      "finalState": "Playground is in view",
      "failureRecovery": "Use browser Back or scroll",
      "browserTest": "Invoke #start using Enter or touch; assert: Navigate to #play; then verify: Playground is in view; recovery: Use browser Back or scroll."
    },
    {
      "id": "work-select",
      "accessibleName": "Work in progress",
      "userJob": "Choose a screen, map, report, or message",
      "effect": "Update the same-object comparison and recipe locally",
      "keyboardTouch": "Native select behavior",
      "feedback": "Object label, assisted copy, and recipe update",
      "recovery": "Choose another object; default is screen",
      "finalState": "Object label, assisted copy, and recipe update",
      "failureRecovery": "Choose another object; default is screen",
      "browserTest": "Invoke #work-select using Native select behavior; assert: Update the same-object comparison and recipe locally; then verify: Object label, assisted copy, and recipe update; recovery: Choose another object; default is screen."
    },
    {
      "id": "view-baseline",
      "accessibleName": "Baseline",
      "userJob": "Inspect the generic baseline",
      "effect": "Show the same fixture facts with weak hierarchy and a needs-revision label",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "aria-pressed and proof state update",
      "recovery": "Select Assisted",
      "finalState": "aria-pressed and proof state update",
      "failureRecovery": "Select Assisted",
      "browserTest": "Invoke #view-baseline using Enter, Space, or touch; assert: Show the same fixture facts with weak hierarchy and a needs-revision label; then verify: aria-pressed and proof state update; recovery: Select Assisted."
    },
    {
      "id": "view-assisted",
      "accessibleName": "Assisted",
      "userJob": "Inspect the design-system-assisted presentation",
      "effect": "Show the same fixture facts with clear hierarchy and a named next action",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "aria-pressed and proof state update",
      "recovery": "Select Baseline",
      "finalState": "aria-pressed and proof state update",
      "failureRecovery": "Select Baseline",
      "browserTest": "Invoke #view-assisted using Enter, Space, or touch; assert: Show the same fixture facts with clear hierarchy and a named next action; then verify: aria-pressed and proof state update; recovery: Select Baseline."
    },
    {
      "id": "lens-dna",
      "accessibleName": "Brand DNA",
      "userJob": "Inspect Clear, Grounded, and Energetic outcomes",
      "effect": "Open the Brand DNA tab panel",
      "keyboardTouch": "Enter, Space, Arrow keys, Home, End, or touch",
      "feedback": "aria-selected and visible tab panel update",
      "recovery": "Choose another lens",
      "finalState": "aria-selected and visible tab panel update",
      "failureRecovery": "Choose another lens",
      "browserTest": "Invoke #lens-dna using Enter, Space, Arrow keys, Home, End, or touch; assert: Open the Brand DNA tab panel; then verify: aria-selected and visible tab panel update; recovery: Choose another lens."
    },
    {
      "id": "lens-voice",
      "accessibleName": "Brand Voice",
      "userJob": "Inspect the evidence-bound message sequence",
      "effect": "Open the Brand Voice tab panel",
      "keyboardTouch": "Enter, Space, Arrow keys, Home, End, or touch",
      "feedback": "aria-selected and visible tab panel update",
      "recovery": "Choose another lens",
      "finalState": "aria-selected and visible tab panel update",
      "failureRecovery": "Choose another lens",
      "browserTest": "Invoke #lens-voice using Enter, Space, Arrow keys, Home, End, or touch; assert: Open the Brand Voice tab panel; then verify: aria-selected and visible tab panel update; recovery: Choose another lens."
    },
    {
      "id": "lens-visual",
      "accessibleName": "Brand Visual",
      "userJob": "Inspect visual hierarchy, brand atmosphere, and the route to dataviz examples",
      "effect": "Open the Brand Visual tab panel, atmosphere controls, and discoverable dataviz route",
      "keyboardTouch": "Enter, Space, Arrow keys, Home, End, or touch",
      "feedback": "aria-selected, visible tab panel, and proof surface update",
      "recovery": "Choose another lens",
      "finalState": "aria-selected, visible tab panel, and proof surface update",
      "failureRecovery": "Choose another lens",
      "browserTest": "Invoke #lens-visual using Enter, Space, Arrow keys, Home, End, or touch; assert: Open the Brand Visual panel, atmosphere controls, and #open-dataviz route; then verify aria-selected, visible panel, and proof surface update."
    },
    {
      "id": "surface-measure",
      "accessibleName": "Measure atmosphere",
      "userJob": "Preview the Measure closure surface on the same object",
      "effect": "Apply the governed Measure gradient fixture",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "aria-pressed and proof atmosphere update",
      "recovery": "Choose Ground or Cultivate",
      "finalState": "aria-pressed and proof atmosphere update",
      "failureRecovery": "Choose Ground or Cultivate",
      "browserTest": "Invoke #surface-measure using Enter, Space, or touch; assert: Apply the governed Measure gradient fixture; then verify: aria-pressed and proof atmosphere update; recovery: Choose Ground or Cultivate."
    },
    {
      "id": "surface-ground",
      "accessibleName": "Ground atmosphere",
      "userJob": "Preview the Ground transition surface on the same object",
      "effect": "Apply the governed Ground gradient fixture",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "aria-pressed and proof atmosphere update",
      "recovery": "Choose Measure or Cultivate",
      "finalState": "aria-pressed and proof atmosphere update",
      "failureRecovery": "Choose Measure or Cultivate",
      "browserTest": "Invoke #surface-ground using Enter, Space, or touch; assert: Apply the governed Ground gradient fixture; then verify: aria-pressed and proof atmosphere update; recovery: Choose Measure or Cultivate."
    },
    {
      "id": "surface-cultivate",
      "accessibleName": "Cultivate atmosphere",
      "userJob": "Preview the Cultivate invitation surface on the same object",
      "effect": "Apply the governed Cultivate gradient fixture",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "aria-pressed and proof atmosphere update",
      "recovery": "Choose Measure or Ground",
      "finalState": "aria-pressed and proof atmosphere update",
      "failureRecovery": "Choose Measure or Ground",
      "browserTest": "Invoke #surface-cultivate using Enter, Space, or touch; assert: Apply the governed Cultivate gradient fixture; then verify: aria-pressed and proof atmosphere update; recovery: Choose Measure or Ground."
    },
    {
      "id": "open-dataviz",
      "accessibleName": "Go to the dataviz examples",
      "userJob": "Move directly from Brand Visual to implementation examples",
      "effect": "Open #library-dataviz, update the fragment, scroll it into view, and focus its summary",
      "keyboardTouch": "Enter or touch",
      "feedback": "Data visualization group opens with three fundamentals and nine CityMETER-derived treatment cards",
      "recovery": "Close the native details group or use browser Back",
      "finalState": "#library-dataviz is open and its summary has focus",
      "failureRecovery": "Navigate to #library-dataviz and open it manually",
      "browserTest": "Select #lens-visual then invoke #open-dataviz; assert #library-dataviz.open, location.hash, focused summary, three chart figures, three visible tables, and nine .citymeter-chart-card examples."
    },
    {
      "id": "open-color-from-visual",
      "accessibleName": "Choose color and surface by job",
      "userJob": "Move directly from Brand Visual to role-based color guidance",
      "effect": "Open #library-color, update the fragment, scroll it into view, and focus its summary",
      "keyboardTouch": "Enter or touch",
      "feedback": "Color, surface, and data-palette routes open with six visual choices",
      "recovery": "Close the native details group or use browser Back",
      "finalState": "#library-color is open and its summary has focus",
      "failureRecovery": "Navigate to #library-color and open it manually",
      "browserTest": "Select #lens-visual then invoke #open-color-from-visual; assert #library-color.open, location.hash, focused summary, eight role labels, six .color-route-card examples, and the 4/8/12+ category rule."
    },
    {
      "id": "stage-select",
      "accessibleName": "Where is the work now",
      "userJob": "Inspect what may adapt at one work stage",
      "effect": "Update stage-specific adaptable guidance",
      "keyboardTouch": "Native select behavior",
      "feedback": "Selected stage and adaptable content update",
      "recovery": "Choose Frame",
      "finalState": "Selected stage and adaptable content update",
      "failureRecovery": "Choose Frame",
      "browserTest": "Invoke #stage-select using Native select behavior; assert: Update stage-specific adaptable guidance; then verify: Selected stage and adaptable content update; recovery: Choose Frame."
    },
    {
      "id": "check-1",
      "accessibleName": "Start with the person, work, place, or decision",
      "userJob": "Self-check copy entry point",
      "effect": "Update local checklist count",
      "keyboardTouch": "Space or touch",
      "feedback": "Native checked state and count update",
      "recovery": "Uncheck; no data is saved",
      "finalState": "Native checked state and count update",
      "failureRecovery": "Uncheck; no data is saved",
      "browserTest": "Invoke #check-1 using Space or touch; assert: Update local checklist count; then verify: Native checked state and count update; recovery: Uncheck; no data is saved."
    },
    {
      "id": "check-2",
      "accessibleName": "Keep what is known with its source, date, and place",
      "userJob": "Self-check evidence context",
      "effect": "Update local checklist count",
      "keyboardTouch": "Space or touch",
      "feedback": "Native checked state and count update",
      "recovery": "Uncheck; no data is saved",
      "finalState": "Native checked state and count update",
      "failureRecovery": "Uncheck; no data is saved",
      "browserTest": "Invoke #check-2 using Space or touch; assert: Update local checklist count; then verify: Native checked state and count update; recovery: Uncheck; no data is saved."
    },
    {
      "id": "check-3",
      "accessibleName": "State status, boundary, and limitation honestly",
      "userJob": "Self-check evidence boundary",
      "effect": "Update local checklist count",
      "keyboardTouch": "Space or touch",
      "feedback": "Native checked state and count update",
      "recovery": "Uncheck; no data is saved",
      "finalState": "Native checked state and count update",
      "failureRecovery": "Uncheck; no data is saved",
      "browserTest": "Invoke #check-3 using Space or touch; assert: Update local checklist count; then verify: Native checked state and count update; recovery: Uncheck; no data is saved."
    },
    {
      "id": "check-4",
      "accessibleName": "Compose one focal idea, perceptual quiet, and readable proof",
      "userJob": "Self-check visual hierarchy",
      "effect": "Update local checklist count",
      "keyboardTouch": "Space or touch",
      "feedback": "Native checked state and count update",
      "recovery": "Uncheck; no data is saved",
      "finalState": "Native checked state and count update",
      "failureRecovery": "Uncheck; no data is saved",
      "browserTest": "Invoke #check-4 using Space or touch; assert: Update local checklist count; then verify: Native checked state and count update; recovery: Uncheck; no data is saved."
    },
    {
      "id": "check-5",
      "accessibleName": "End with one useful next action",
      "userJob": "Self-check action integrity",
      "effect": "Update local checklist count",
      "keyboardTouch": "Space or touch",
      "feedback": "Native checked state and count update",
      "recovery": "Uncheck; no data is saved",
      "finalState": "Native checked state and count update",
      "failureRecovery": "Uncheck; no data is saved",
      "browserTest": "Invoke #check-5 using Space or touch; assert: Update local checklist count; then verify: Native checked state and count update; recovery: Uncheck; no data is saved."
    },
    {
      "id": "copy-recipe",
      "accessibleName": "Copy recipe",
      "userJob": "Take the 60-second recipe into real work",
      "effect": "Copy the visible recipe to the local clipboard",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "Live status confirms copy success or fallback",
      "recovery": "Recipe stays visible and selectable when clipboard access fails",
      "finalState": "Live status confirms copy success or fallback",
      "failureRecovery": "Recipe stays visible and selectable when clipboard access fails",
      "browserTest": "Invoke #copy-recipe using Enter, Space, or touch; assert: Copy the visible recipe to the local clipboard; then verify: Live status confirms copy success or fallback; recovery: Recipe stays visible and selectable when clipboard access fails."
    },
    {
      "id": "recipe-text",
      "accessibleName": "Selectable recipe",
      "userJob": "Read or manually copy the complete recipe",
      "effect": "Native text selection only",
      "keyboardTouch": "Native textarea selection",
      "feedback": "Visible selection",
      "recovery": "Content is readonly and cannot be lost",
      "finalState": "Visible selection",
      "failureRecovery": "Content is readonly and cannot be lost",
      "browserTest": "Invoke #recipe-text using Native textarea selection; assert: Native text selection only; then verify: Visible selection; recovery: Content is readonly and cannot be lost."
    },
    {
      "id": "open-library",
      "accessibleName": "Open the Implementation Library",
      "userJob": "Reach implementation detail without complicating the opening route",
      "effect": "Navigate to #implementation-library",
      "keyboardTouch": "Enter or touch",
      "feedback": "The seven collapsed library groups are in view",
      "recovery": "Use browser Back or scroll",
      "finalState": "Implementation Library heading and disclosure groups are visible",
      "failureRecovery": "Scroll to #implementation-library",
      "browserTest": "Invoke #open-library; assert location.hash or target position resolves to #implementation-library and seven details groups are present."
    },
    {
      "id": "open-color-library",
      "accessibleName": "Open color, surfaces, and data palettes",
      "userJob": "Reach role-based color guidance directly from the library gateway",
      "effect": "Open #library-color, update the fragment, scroll it into view, and focus its summary",
      "keyboardTouch": "Enter or touch",
      "feedback": "Color roles, six visual routes, and the 4/8/12+ category rule are visible",
      "recovery": "Close the native details group or use browser Back",
      "finalState": "#library-color is open and its summary has focus",
      "failureRecovery": "Navigate to #library-color and open it manually",
      "browserTest": "Invoke #open-color-library; assert #library-color.open, location.hash, focused summary, eight role labels, six .color-route-card examples, and working routes to the realistic fixture and complete atlas."
    },
    {
      "id": "download-system",
      "accessibleName": "Download Design System v0.9.0",
      "userJob": "Keep the human-readable authoring master beside the work",
      "effect": "Download assets/downloads/landometer-design-system-v0.9.0.md",
      "keyboardTouch": "Enter or touch",
      "feedback": "Browser download starts for the exact Markdown master",
      "recovery": "Open the same-origin href directly",
      "finalState": "The 399,725-byte owner-approved v0.9.0-r4 Markdown file is available locally",
      "failureRecovery": "Open the same-origin href directly or use the Resources group",
      "browserTest": "Inspect #download-system href and download attribute; request the href and assert HTTP 200, 269767 bytes, and SHA-256 00d931254d21931952d29fdde7a00e2c3a5b4f875504a1bf72fee316bf5d4e68."
    },
    {
      "id": "library-color-toggle",
      "accessibleName": "Color, surfaces, and data palettes",
      "userJob": "Choose color by role and reach realistic or exhaustive implementation examples",
      "effect": "Toggle #library-color using native details behavior",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "Eight color roles, six visual routes, a category-capacity rule, and reference actions expand or collapse",
      "recovery": "Activate the same summary again",
      "finalState": "The native open state matches the user's choice",
      "failureRecovery": "All routes remain inspectable in source and the summary works without JavaScript",
      "browserTest": "Invoke #library-color-toggle; assert parent details.open, eight role labels, six .color-route-card examples, solid/state, gradient, scale, category, opacity/layer, and line/stroke routes, then invoke again to close."
    },
    {
      "id": "library-foundations-toggle",
      "accessibleName": "Foundations",
      "userJob": "Inspect type, logo, surface, gradient, composition, and opportunity-led application examples",
      "effect": "Toggle #library-foundations using native details behavior",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "Four foundation specimens and eight creative application sketches expand or collapse",
      "recovery": "Activate the same summary again",
      "finalState": "The native open state matches the user's choice",
      "failureRecovery": "All summary controls remain usable without JavaScript",
      "browserTest": "Invoke #library-foundations-toggle; assert parent details.open, visible type/logo/atmosphere/composition specimens, and eight .opportunity-card concept sketches; invoke again to close."
    },
    {
      "id": "complete-color-atlas-toggle",
      "accessibleName": "Open every governed color, gradient, and scale",
      "userJob": "Inspect the complete source-backed color reference after the fast overview",
      "effect": "Toggle #complete-color-atlas using native details behavior",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "Brand, foundation, semantic, gradient, categorical, quantitative, map, opacity, and depth references expand or collapse",
      "recovery": "Activate the same summary again",
      "finalState": "The native open state matches the user's choice and exact values remain available in source",
      "failureRecovery": "Native details behavior remains usable without JavaScript",
      "browserTest": "Open #library-foundations, invoke #complete-color-atlas-toggle, assert the atlas contains 17 foundation pairs, seven semantic roles, ten categorical records, 18 scale records with 41/5/7/9 cells, map pairs, and eight opacity values; invoke again to close."
    },
    {
      "id": "library-components-toggle",
      "accessibleName": "Interface components",
      "userJob": "Inspect the complete shared component contract and representative specimens",
      "effect": "Toggle #library-components using native details behavior",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "Thirteen component contracts, representative specimens, and four component ensembles expand or collapse",
      "recovery": "Activate the same summary again",
      "finalState": "The native open state matches the user's choice",
      "failureRecovery": "All summary controls remain usable without JavaScript",
      "browserTest": "Invoke #library-components-toggle; assert parent details.open, thirteen component names in the contract matrix, and four component-ensemble cards; invoke again to close."
    },
    {
      "id": "library-dataviz-toggle",
      "accessibleName": "Data visualization and maps",
      "userJob": "Inspect question-first dataviz rules and accessible examples",
      "effect": "Toggle #library-dataviz using native details behavior",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "Chart chooser, boundary, three fundamentals, three tables, nine CityMETER-derived treatments, and three question-led extensions expand or collapse",
      "recovery": "Activate the same summary again",
      "finalState": "The native open state matches the user's choice",
      "failureRecovery": "All examples remain in source and the summary works without JavaScript",
      "browserTest": "Invoke #library-dataviz-toggle; assert parent details.open, three .dataviz-pattern figures, three .dataviz-table tables, nine .citymeter-chart-card examples, three extension cards, no-data and zero states; invoke again to close."
    },
    {
      "id": "library-experience-toggle",
      "accessibleName": "Experience patterns",
      "userJob": "Inspect Intent → AHA cases, success path, truthful recovery, semantic motion, CTA integrity, ethical loops, recipient value, and contextual discovery",
      "effect": "Toggle #library-experience using native details behavior",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "Three positive cases plus one deletion test, See → Understand → Decide → Act → Learn, state recovery, motion, CTA state proof, ethical loop, network ladder, and contextual search expand or collapse",
      "recovery": "Activate the same summary again",
      "finalState": "The native open state matches the user's choice",
      "failureRecovery": "All summary controls remain usable without JavaScript",
      "browserTest": "Invoke #library-experience-toggle; assert parent details.open, three positive intent cases plus one rejected static case, five experience stages, semantic motion fixture, CTA table and local state proof, ethical loop, recipient ladder, and contextual-search form."
    },
    {
      "id": "motion-replay",
      "accessibleName": "Replay sequence",
      "userJob": "Inspect how semantic motion orders object, meaning, and next action",
      "effect": "Replay the local MOTION-FIXTURE-0.1 sequence once without moving focus or causing an external effect",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "The visible event log records object at 0ms, meaning settled at 120ms, and action settled at 320ms",
      "recovery": "Use Pause · show final; reduced-motion resolves directly to the final state",
      "finalState": "The complete object, source_limited status, context, limitation, and next action are visible",
      "failureRecovery": "The complete final meaning is visible by default and without JavaScript",
      "browserTest": "Open #library-experience, invoke #motion-replay, assert data-phase object → meaning → final and three visible log entries; under prefers-reduced-motion assert immediate final state."
    },
    {
      "id": "motion-show-final",
      "accessibleName": "Pause · show final",
      "userJob": "Stop the local motion sequence and inspect the complete meaning",
      "effect": "Cancel pending fixture timers and set #motion-lab to its complete final phase",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "The event log states that the sequence paused and final meaning is shown",
      "recovery": "Replay the sequence when useful",
      "finalState": "All semantic content is visible with no pending transition",
      "failureRecovery": "The no-JavaScript baseline already shows the final state",
      "browserTest": "Invoke #motion-replay then #motion-show-final before 320ms; assert data-phase final, one paused log entry, and no later log mutation."
    },
    {
      "id": "cta-eligibility",
      "accessibleName": "I reviewed this fixture's object, source, and limitation",
      "userJob": "Satisfy the visible eligibility requirement before the local action becomes available",
      "effect": "Toggle only the local CTA fixture between ineligible and eligible",
      "keyboardTouch": "Space or touch",
      "feedback": "The missing-requirement explanation updates and #cta-execute becomes enabled or disabled",
      "recovery": "Uncheck before execution or reset the completed fixture",
      "finalState": "Eligibility and the available consequence remain visible together",
      "failureRecovery": "The fixture starts ineligible and no action occurs",
      "browserTest": "Open #library-experience; assert #cta-execute is disabled with a visible reason; check #cta-eligibility and assert the button becomes enabled without network or persistence."
    },
    {
      "id": "cta-execute",
      "accessibleName": "Create local receipt",
      "userJob": "Inspect pending, duplicate prevention, and a verifiable local-only completion receipt",
      "effect": "Run one deterministic local timer and update only #cta-fixture; no save, delivery, network, or remote mutation occurs",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "The button and eligibility control disable during PENDING_LOCAL; a COMPLETE_LOCAL_REFERENCE receipt then appears",
      "recovery": "Use #cta-reset after completion",
      "finalState": "The receipt names object, local status, no external effect, and recovery",
      "failureRecovery": "If JavaScript is unavailable, the static CTA contract matrix remains visible and this fixture is omitted",
      "browserTest": "Satisfy #cta-eligibility and invoke #cta-execute; assert pending state disables duplicate execution, then complete state shows object/status/effect/recovery and reveals #cta-reset."
    },
    {
      "id": "cta-reset",
      "accessibleName": "Reset fixture",
      "userJob": "Recover from the completed local reference state and exercise the contract again",
      "effect": "Clear the local CTA timer/state and restore the initial ineligible state",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "The receipt returns to no action, eligibility clears, and execute is disabled with its reason",
      "recovery": "Review the boundary and enable eligibility again",
      "finalState": "The CTA fixture is in its deterministic initial state",
      "failureRecovery": "Reload the page; no state is persisted",
      "browserTest": "After local completion invoke #cta-reset; assert ineligible state, unchecked eligibility, disabled execute, hidden reset, and no persisted state after reload."
    },
    {
      "id": "context-case",
      "accessibleName": "Switch among four current CityMETER record examples",
      "userJob": "Inspect how the same contextual-search pattern adapts to four real CityMETER records",
      "effect": "Update the local event snapshot, icon, source link, and editable query without making a request",
      "keyboardTouch": "Native select behavior",
      "feedback": "Event, date, cause, active field, place hierarchy, source URL, and query update together",
      "recovery": "Choose the Tha Sai flood example to restore the default",
      "finalState": "Exactly one current-record example is represented consistently across snapshot and query",
      "failureRecovery": "Keep the current visible example or reload to restore Tha Sai",
      "browserTest": "Open #library-experience; cycle #context-case through tha-sai, krok-phra, bueng-lak, and na-to; assert icon, event, place, source href, and query update with no request."
    },
    {
      "id": "context-source",
      "accessibleName": "Open source record",
      "userJob": "Inspect the public CityMETER record used to compose the active reference query",
      "effect": "Open the selected public CityMETER API record in a new tab after explicit activation",
      "keyboardTouch": "Enter or touch",
      "feedback": "The source record opens while the playground remains available",
      "recovery": "Close the source tab and return to the preserved playground",
      "finalState": "The selected event source URL is inspectable; no product record is mutated",
      "failureRecovery": "Keep the visible snapshot and do not treat it as independently verified ground truth",
      "browserTest": "For each #context-case value assert #context-source targets the matching landometer.com public API URL and includes noopener noreferrer external."
    },
    {
      "id": "context-query",
      "accessibleName": "Editable, auto-composed query",
      "userJob": "Inspect and edit the public-safe query composed from the active current-record CityMETER context",
      "effect": "Edit only the local search field; no request, save, telemetry, or product state change occurs",
      "keyboardTouch": "Native search-input behavior",
      "feedback": "The exact query remains visible before any external navigation",
      "recovery": "Undo edits or restore the visible context terms manually",
      "finalState": "The field contains the user-confirmed event, date/cause where known, active-field label, intent keyword, and place hierarchy",
      "failureRecovery": "Do not submit; copy or revise a generic public-safe query instead",
      "browserTest": "Open #library-experience; assert the default #context-query includes ปี 2567 อุทกภัย, 27 พฤศจิกายน 2567, ยอดผู้เสียชีวิต, หมู่บ้านท่าไทร, องค์การบริหารส่วนตำบล เกาะยอ, อำเภอเมืองสงขลา, and จังหวัดสงขลา; edit it and assert no request or persistence before explicit submit."
    },
    {
      "id": "context-search-google",
      "accessibleName": "Search sources with Google",
      "userJob": "Continue a visible public-safe intent into an explicit external search",
      "effect": "Submit the exact visible q value to https://www.google.com/search in a new tab after explicit activation",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "A new external search tab opens while the playground state remains available",
      "recovery": "Close the external tab, return to the preserved playground, or copy/edit the query",
      "finalState": "The Landometer form contributes only the confirmed visible q; returned material remains discovery_only",
      "failureRecovery": "Keep the current page and use the visible query as a manual copy fallback",
      "browserTest": "Intercept #context-search-form submission through #context-search-google; assert action, method=get, target=_blank, rel includes noopener+noreferrer, exact current name=q value, and no udm submitter parameter without allowing navigation."
    },
    {
      "id": "context-search-google-ai",
      "accessibleName": "Synthesize with Google AI Mode",
      "userJob": "Ask Google AI Mode to synthesize the same visible public-safe intent while keeping source verification explicit",
      "effect": "Submit the exact visible q plus submitter parameter udm=50 to https://www.google.com/search in a new tab after explicit activation",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "The Google AI Mode route is requested in a new external tab while the visible query and playground state remain available; the provider may redirect or decline",
      "recovery": "Close the external tab, return to the preserved playground, choose ordinary Search, or edit/copy the visible query",
      "finalState": "The Landometer form contributes only the confirmed visible q and explicit udm=50 route; synthesized material remains discovery_only and requires source verification",
      "failureRecovery": "Keep the exact query visible and copy it to the documented google.com/ai entry point if the direct route is unavailable; do not silently switch jobs or treat AI synthesis as a source",
      "browserTest": "Intercept #context-search-form submission through #context-search-google-ai; assert action, method=get, target=_blank, rel includes noopener+noreferrer, exact current name=q value, clicked submitter name=udm and value=50, and no hidden prompt or automatic navigation."
    },
    {
      "id": "library-products-toggle",
      "accessibleName": "Product adaptations",
      "userJob": "Inspect bounded adaptation templates without universalizing product facts",
      "effect": "Toggle #library-products using native details behavior",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "CityMETER, CityWiki, CityChat, and ijji templates expand or collapse",
      "recovery": "Activate the same summary again",
      "finalState": "The native open state matches the user's choice",
      "failureRecovery": "All summary controls remain usable without JavaScript",
      "browserTest": "Invoke #library-products-toggle; assert parent details.open and four labelled product templates with a product-specific boundary on each."
    },
    {
      "id": "library-resources-toggle",
      "accessibleName": "Resources and release records",
      "userJob": "Inspect downloadable documentation and governed release records",
      "effect": "Toggle #library-resources using native details behavior",
      "keyboardTouch": "Enter, Space, or touch",
      "feedback": "Download metadata, delivery records, accepted application note, approved patch history, version-locked skill, llms navigation aid, and discovery-state gates expand or collapse",
      "recovery": "Activate the same summary again",
      "finalState": "The native open state matches the user's choice",
      "failureRecovery": "All summary controls remain usable without JavaScript",
      "browserTest": "Invoke #library-resources-toggle; assert parent details.open, governed authoring-master bytes/hash, resource records, llms disclosure, v0.9.0 authoring skill, approved patch history, and publication discovery-state table."
    },
    {
      "id": "resource-download-system",
      "accessibleName": "Download Markdown",
      "userJob": "Download the authoring master from the Resources group",
      "effect": "Download assets/downloads/landometer-design-system-v0.9.0.md",
      "keyboardTouch": "Enter or touch",
      "feedback": "Browser download starts for the exact Markdown master",
      "recovery": "Use #download-system or open the href directly",
      "finalState": "The whitespace-normalized authoring master is available locally",
      "failureRecovery": "Use #download-system or open the href directly",
      "browserTest": "Assert #resource-download-system matches #download-system href and download behavior; verify HTTP 200, byte count, and SHA-256."
    },
    {
      "id": "resource-manifest",
      "accessibleName": "Site Manifest 2.1",
      "userJob": "Inspect machine-readable artifact identity and evidence boundary",
      "effect": "Navigate to site-manifest.v0.9.0.json",
      "keyboardTouch": "Enter or touch",
      "feedback": "Manifest resource opens",
      "recovery": "Use browser Back",
      "finalState": "The versioned Manifest 2.1 JSON is visible",
      "failureRecovery": "Use #manifest-link in the footer",
      "browserTest": "Inspect #resource-manifest href; request it and assert HTTP 200 plus artifact version 0.9.0."
    },
    {
      "id": "resource-build-card",
      "accessibleName": "Build Card v0.9.0",
      "userJob": "Inspect authoring and publication decisions",
      "effect": "Navigate to build-card.v0.9.0.yml",
      "keyboardTouch": "Enter or touch",
      "feedback": "Build Card resource opens",
      "recovery": "Use browser Back",
      "finalState": "The versioned Build Card YAML is visible",
      "failureRecovery": "Open the path directly from the repository",
      "browserTest": "Inspect #resource-build-card href; request it and assert HTTP 200 plus dsVersion 0.9.0."
    },
    {
      "id": "resource-control-inventory",
      "accessibleName": "Control Inventory",
      "userJob": "Inspect every focusable control contract",
      "effect": "Navigate to control-inventory.v0.9.0.json",
      "keyboardTouch": "Enter or touch",
      "feedback": "Control Inventory resource opens",
      "recovery": "Use browser Back",
      "finalState": "The versioned control inventory JSON is visible",
      "failureRecovery": "Open the path directly from the repository",
      "browserTest": "Inspect #resource-control-inventory href; request it and assert HTTP 200 plus exact parity with source control IDs."
    },
    {
      "id": "resource-manual-gates",
      "accessibleName": "Manual QA gates",
      "userJob": "Inspect what still blocks a conformance claim",
      "effect": "Navigate to qa/v0.9.0-manual-gates.md",
      "keyboardTouch": "Enter or touch",
      "feedback": "Manual gate document opens",
      "recovery": "Use browser Back",
      "finalState": "Open manual identity, media, dataviz, responsive, and accessibility gates are visible",
      "failureRecovery": "Open the path directly from the repository",
      "browserTest": "Inspect #resource-manual-gates href; request it and assert HTTP 200 plus source_limited and machineValidation pending boundaries."
    },
    {
      "id": "resource-implementation-notes",
      "accessibleName": "Read application record",
      "userJob": "Inspect how the artifact applies the approved share, contextual source-search, external AI-synthesis, and positive-example guidance",
      "effect": "Navigate to implementation-notes.v0.9.0.md",
      "keyboardTouch": "Enter or touch",
      "feedback": "The same-origin non-normative artifact application record opens",
      "recovery": "Use browser Back",
      "finalState": "The note visibly distinguishes artifact-specific implementation evidence from the owner-approved v0.9.0-r4 master",
      "failureRecovery": "Open the same-origin path directly from the repository",
      "browserTest": "Inspect #resource-implementation-notes href/type; request it and assert HTTP 200, accepted artifact-record/non-normative authority, IMPL-SHARE-01, IMPL-SEARCH-EXT-01, IMPL-AI-EXT-01, and IMPL-EXAMPLE-01."
    },
    {
      "id": "resource-llms",
      "accessibleName": "Open machine discovery aid",
      "userJob": "Give a machine reader a concise route to current public-safe references and boundaries",
      "effect": "Navigate to the project-path llms.txt navigation aid",
      "keyboardTouch": "Enter or touch",
      "feedback": "The same-origin text resource opens",
      "recovery": "Use browser Back or open the human-readable master",
      "finalState": "Current version, status, canonical object, sources, product boundary, and no-agent-action rule are visible",
      "failureRecovery": "Use the Manifest, Build Card, or authoring master directly",
      "browserTest": "Inspect #resource-llms href/type; request it and assert HTTP 200 plus version 0.9.0, source_limited, DV-FIXTURE-0.1, contextual-search boundary, and no bounded agent action."
    },
    {
      "id": "resource-normative-patch",
      "accessibleName": "Open approved proposal",
      "userJob": "Inspect the immutable proposal that was owner-approved and integrated into authoring revision r1",
      "effect": "Navigate to the versioned normative-patch proposal in the public repository",
      "keyboardTouch": "Enter or touch",
      "feedback": "The original hash-locked proposal Markdown opens in a new tab",
      "recovery": "Close the tab or return to the implementation library",
      "finalState": "The approved value-proof, surface-contrast, Thai-type, color-reference, visual-first, and Source-Search-versus-AI-synthesis input is available for audit",
      "failureRecovery": "Open normative-patches/landometer-design-system-v0.9.0.proposal.md directly in the repository",
      "browserTest": "Inspect #resource-normative-patch href/target/rel; assert it points to the immutable proposal path and describes it as approved integration input rather than a separate active authority."
    },
    {
      "id": "resource-refinement-skill",
      "accessibleName": "Open v0.9.0 skill",
      "userJob": "Apply or audit work against the owner-approved v0.9.0-r4 authoring master",
      "effect": "Navigate to the project-versioned skill folder in the public repository",
      "keyboardTouch": "Enter or touch",
      "feedback": "The version-locked authoring skill folder opens in a new tab",
      "recovery": "Close the tab or return to the implementation library",
      "finalState": "The integrated master, Build Card template, release lock, and pending machine-package boundary are available for reuse",
      "failureRecovery": "Open skill/apply-landometer-design-system-v0-9-0 directly in the repository",
      "browserTest": "Inspect #resource-refinement-skill href/target/rel; assert it points to the v0.9.0 skill folder and opens without changing the playground state."
    },
    {
      "id": "resource-standalone",
      "accessibleName": "Download standalone HTML",
      "userJob": "Keep or hand off the exact current Color Set and UI build as one self-contained file",
      "effect": "Download landometer-design-system-v0.9.0-standalone.color-srgb-04.ui-20260821-01.html",
      "keyboardTouch": "Enter or touch",
      "feedback": "The browser downloads the single-file snapshot",
      "recovery": "Open the same-origin href directly or return to Resources",
      "finalState": "A standalone HTML file with embedded display fonts and images is available",
      "failureRecovery": "Use the production page or retry the direct download",
      "browserTest": "Inspect #resource-standalone href/download; request the file, assert HTTP 200, data-standalone=true, no relative display assets, and exact embedded atlas coverage."
    },
    {
      "id": "return-play",
      "accessibleName": "Try another work object",
      "userJob": "Return to the comparison",
      "effect": "Navigate to #play",
      "keyboardTouch": "Enter or touch",
      "feedback": "Playground is in view",
      "recovery": "Use browser Back or scroll",
      "finalState": "Playground is in view",
      "failureRecovery": "Use browser Back or scroll",
      "browserTest": "Invoke #return-play using Enter or touch; assert: Navigate to #play; then verify: Playground is in view; recovery: Use browser Back or scroll."
    },
    {
      "id": "manifest-link",
      "accessibleName": "Manifest 2.1",
      "userJob": "Inspect release identity and evidence boundary",
      "effect": "Navigate to site-manifest.v0.9.0.json",
      "keyboardTouch": "Enter or touch",
      "feedback": "Manifest resource opens",
      "recovery": "Use browser Back",
      "finalState": "Manifest resource opens",
      "failureRecovery": "Use browser Back",
      "browserTest": "Invoke #manifest-link using Enter or touch; assert: Navigate to site-manifest.v0.9.0.json; then verify: Manifest resource opens; recovery: Use browser Back."
    },
    {
      "id": "github-link",
      "accessibleName": "GitHub source",
      "userJob": "Inspect the public repository",
      "effect": "Navigate to montri-th/Landometer",
      "keyboardTouch": "Enter or touch",
      "feedback": "Repository opens",
      "recovery": "Use browser Back",
      "finalState": "Repository opens",
      "failureRecovery": "Use browser Back",
      "browserTest": "Invoke #github-link using Enter or touch; assert: Navigate to montri-th/Landometer; then verify: Repository opens; recovery: Use browser Back."
    },
    {
      "id": "v090-btn-demo",
      "accessibleName": "ปุ่มรองแคปซูล / Secondary capsule",
      "userJob": "demonstrate the capsule secondary action shape",
      "effect": "",
      "keyboardTouch": "",
      "feedback": "",
      "recovery": "",
      "finalState": "focus/hover/active states render on the capsule",
      "failureRecovery": "none needed; stateless",
      "browserTest": "playwright: computed border-radius 999px; focus outline = var(--focus-ring)",
      "navigationOrEffect": "local demo only; no navigation"
    },
    {
      "id": "v090-btn-star",
      "accessibleName": "ตัวอย่างปุ่มวงกลม บันทึก / Circle icon button demo",
      "userJob": "demonstrate icon-only circle + FILL active state",
      "effect": "",
      "keyboardTouch": "",
      "feedback": "",
      "recovery": "",
      "finalState": "aria-pressed true/false; icon FILL 1 when pressed",
      "failureRecovery": "re-click restores",
      "browserTest": "playwright: click toggles aria-pressed; border-radius 50%; 44x44",
      "navigationOrEffect": "toggles aria-pressed and icon FILL axis locally"
    },
    {
      "id": "v090-play-stagger",
      "accessibleName": "เล่น skank stagger / Play skank stagger",
      "userJob": "replay the 60ms Riddim list reveal",
      "effect": "",
      "keyboardTouch": "",
      "feedback": "",
      "recovery": "",
      "finalState": "list items reveal once with 60ms offsets",
      "failureRecovery": "reduced-motion: button is inert and final state shows",
      "browserTest": "playwright: class is-playing applied; reduced-motion emulation shows static",
      "navigationOrEffect": "replays a one-shot CSS animation on #v090-list"
    },
    {
      "id": "v090-play-settle",
      "accessibleName": "เล่น one-drop settle / Play one-drop settle",
      "userJob": "replay the settle easing on the result card",
      "effect": "",
      "keyboardTouch": "",
      "feedback": "",
      "recovery": "",
      "finalState": "card lands once with --motion-ease-settle",
      "failureRecovery": "reduced-motion inert",
      "browserTest": "playwright: class is-settling applied once",
      "navigationOrEffect": "replays one-shot settle animation"
    },
    {
      "id": "v090-evidence-panel",
      "accessibleName": "ชั้นหลักฐาน (L2) / Evidence layer (L2)",
      "userJob": "open the full source/method/limitation behind the claim",
      "effect": "",
      "keyboardTouch": "",
      "feedback": "",
      "recovery": "",
      "finalState": "details[open] with full evidence text",
      "failureRecovery": "toggle closes; state harmless",
      "browserTest": "playwright: summary click sets open=true",
      "navigationOrEffect": "native details disclosure"
    },
    {
      "id": "v090-copy-link",
      "accessibleName": "คัดลอกลิงก์สถานะนี้ให้เพื่อน / Copy this exact state",
      "userJob": "copy an exact-link + provenance draft per [SHARE-01]",
      "effect": "",
      "keyboardTouch": "",
      "feedback": "",
      "recovery": "",
      "finalState": "role=status line confirms copied or shows manual fallback",
      "failureRecovery": "on clipboard denial: fallback message tells the user to copy the URL manually; nothing lost",
      "browserTest": "playwright: click yields 'คัดลอกแล้ว…' status; clipboard text contains canonical URL + receipt",
      "navigationOrEffect": "writes URL + receipt line to clipboard; no send occurs"
    },
    {
      "id": "v090-citymeter-link",
      "accessibleName": "montri-th.github.io/CityMETER",
      "userJob": "follow the [XPRODUCT-01] path to CityMETER with honest status",
      "effect": "",
      "keyboardTouch": "",
      "feedback": "",
      "recovery": "",
      "finalState": "CityMETER site opens",
      "failureRecovery": "back returns with state preserved by URL params",
      "browserTest": "manual: link opens; status label states early go-to-market per MBB §5.1",
      "navigationOrEffect": "external navigation (rel=noopener)"
    }
  ],
  "artifactBuild": "ui-20260821-01"
}
