{
  "version": "0.2-research",
  "date": "2026-09-07",
  "classification": "Original OpenClaw contributor proposal. Apple guidance informs interaction; no Apple endorsement, native certification, live service integration or upstream adoption is implied.",
  "scope": {
    "platforms": [
      "iOS",
      "macOS",
      "Linux"
    ],
    "remove_section": "Agent behavior",
    "place_voice_under": "Components / Voice",
    "excluded": [
      "watchOS and glasses showcases",
      "a replacement agent-state documentation section",
      "unverified booking, Wallet, microphone or flight-status integrations"
    ]
  },
  "page_copy": {
    "components": {
      "title": "Useful parts. Familiar actions.",
      "intro": "Build with controls people understand, then compose them around real moments: a journey, a stay, a table, a ticket."
    },
    "materials": {
      "title": "Light through the shell.",
      "intro": "Glass brings the controls forward. A quiet reading layer holds the detail. Blue depth and restrained rose warmth give the surface its OpenClaw character."
    },
    "platforms": {
      "title": "At home on each screen.",
      "intro": "One visual language, shaped for iOS, macOS and Linux. Preserve the task; adapt the navigation, density and input."
    },
    "voice": {
      "title": "An open channel.",
      "intro": "A voice control shaped by the claw: composed at rest, responsive when you speak, and clear about what is being heard or played."
    }
  },
  "documentation_structure": [
    {
      "section": "Actions",
      "components": [
        "Button",
        "Icon button",
        "Menu button",
        "Context menu"
      ]
    },
    {
      "section": "Input and selection",
      "components": [
        "Text field",
        "Search",
        "Checkbox and switch",
        "Segmented choice",
        "Stepper",
        "Slider",
        "Date range",
        "Time picker"
      ]
    },
    {
      "section": "Navigation and layout",
      "components": [
        "Tabs",
        "Sidebar",
        "Toolbar",
        "Disclosure",
        "List",
        "Comparison table",
        "Sheet and dialog"
      ]
    },
    {
      "section": "Feedback and media",
      "components": [
        "Inline message",
        "Progress",
        "Empty and error states",
        "Image gallery",
        "Voice channel"
      ]
    },
    {
      "section": "Everyday components",
      "components": [
        "Flight",
        "Journey",
        "Hotel stay",
        "Reservation",
        "World time",
        "Ticket"
      ]
    }
  ],
  "component_definition": {
    "rule": "A component is a reusable interaction contract: input data, visible anatomy, behavior, states, keyboard and assistive access. A decorated content container alone is a card specimen.",
    "each_example_contains": [
      "A working primary interaction",
      "A visible state change or edited value",
      "A meaningful empty, unavailable or error case",
      "Keyboard access with a visible focus indicator",
      "A short usage rule and real data requirements"
    ],
    "demo_rule": "Use a clear Sample data or Interactive example label. Local changes may work fully; provider booking, actual audio capture, valid pass issuance and live status must not be implied."
  },
  "material_system": {
    "source_ids": [
      "materials",
      "color",
      "layout",
      "scroll-views",
      "accessibility"
    ],
    "default": "Glass is the normal visual treatment for app chrome, floating toolbars, menus and the voice control. Do not add a site-level glass/flat preference switch.",
    "layers": [
      {
        "name": "Shell backdrop",
        "role": "A softly enlarged crop or abstract colour field derived from the approved shell. Broad blue volume and a small rose reflection remain recognisable at a distance.",
        "limits": "Treat the selected raster as a framed image; it is not a seamless tile, 3D material or procedural texture. Do not put plate edges behind small text."
      },
      {
        "name": "Reading surface",
        "role": "A standard material or mostly opaque surface for schedules, prices, fields, long copy and tickets.",
        "limits": "Retain stable contrast while the backdrop moves or scrolls. No stacked translucent cards within translucent cards."
      },
      {
        "name": "Glass chrome",
        "role": "One coherent, light-catching functional layer. Gentle edge light, moderate blur and restrained tint reveal the backdrop without competing with labels.",
        "limits": "Regular material is the default; clear glass is reserved for compact controls over rich media and needs background-specific contrast proof."
      },
      {
        "name": "Focus and selection",
        "role": "An independent semantic ring, fill and label treatment above material.",
        "limits": "Focus must survive forced colours, increased contrast, reduced transparency and absent blur."
      }
    ],
    "web_starting_values": {
      "classification": "Experimental CSS starting values, not Apple tokens or a reproduction of native Liquid Glass",
      "chrome_background_light": "rgba(248,251,253,0.78)",
      "chrome_background_dark": "rgba(18,30,39,0.84)",
      "reading_background_light": "rgba(250,252,253,0.96)",
      "reading_background_dark": "rgba(17,26,32,0.96)",
      "blur_px": 20,
      "saturation": 1.12,
      "shell_art_opacity_range": [
        0.12,
        0.22
      ],
      "control_radius_px": 12,
      "surface_radius_px": 20,
      "control_target_css_px": 44,
      "focus_width_css_px": 3,
      "focus_offset_css_px": 3,
      "transition_ms": 180
    },
    "accessibility": "Keep the default glass appearance when supported. Respect system reduced transparency, reduced motion and higher contrast; these are accessibility adaptations of the default. Use a solid surface when backdrop blur is unsupported. The shell may disappear without losing any information.",
    "implementation_boundary": "Apple native material APIs provide adaptive behavior that CSS backdrop-filter does not replicate. A web or Linux presentation should be described as OpenClaw glass inspired by this hierarchy, not native Apple Liquid Glass."
  },
  "app_icon": {
    "source_ids": [
      "app-icons"
    ],
    "proposal": "Keep the exact approved standalone claw as the main foreground shape. Use a simple blue or neutral background with a restrained shell-derived light field. Preserve the open channel in all appearances.",
    "apple_delivery": "Prepare unmasked square 1024×1024 layers for iOS/macOS; prefer vector foregrounds and let Icon Composer/system masking and lighting finish the icon. Test default, dark, clear and tinted appearances. Do not bake duplicate interlayer shadows or highlights into the master.",
    "linux_delivery": "Provide a separate correctly named scalable icon and raster sizes appropriate to the chosen Linux packaging. The desktop decides masking and decoration; a macOS asset preview is not a Linux integration.",
    "preview_boundary": "A rounded-square specimen on the website is an app-icon concept, not an exported Icon Composer document or verified installed app icon."
  },
  "type": {
    "source_ids": [
      "typography",
      "labels"
    ],
    "rules": [
      "Use OpenClaw Display for short editorial headings and prominent destinations. Use the OpenClaw Text companion for dense UI, schedules, forms, instructions and everyday reading.",
      "Use regular or medium weights for compact information. Tabular numerals can stabilise times and prices when the actual OpenClaw Text build supports them.",
      "Preserve airport names, local dates, currency and error detail when text grows; stack rows before truncating essential information.",
      "In native iOS integration, scale OpenClaw Text through native text styles/metrics and support Dynamic Type and Bold Text. A custom font must implement these behaviors; choosing its family does not provide them automatically.",
      "In native macOS integration, respect control metrics and support content zoom; HIG explicitly says macOS has no Dynamic Type.",
      "On the web use rem-based OpenClaw Text with system-ui fallback for unsupported scripts or unavailable font files. Native wrappers retain system fallback where platform/accessibility integration requires it. Do not bundle Apple system fonts as a cross-platform webfont."
    ],
    "units": "Apple native point recommendations do not define CSS pixels. The proposal uses 44 CSS px web targets; native platforms retain appropriate hit regions and text settings.",
    "delivery_status": "Family role is a v2 design decision. The font workstream is producing OpenClaw Text; verify its delivered character coverage, files and rendered small-size proof before publishing implementation claims."
  },
  "standard_components": [
    {
      "id": "button",
      "name": "Button",
      "purpose": "Initiate one clear action.",
      "working_example": "Save an editable local travel note, show progress then Saved, and keep the note recoverable.",
      "states": [
        "default",
        "hover",
        "pressed",
        "focus",
        "loading",
        "disabled"
      ],
      "requirements": [
        "Use a specific verb and visibly different press state.",
        "Keep the action label during loading; prevent duplicate submission.",
        "Explain unavailable actions near the control when useful; do not rely on hover."
      ],
      "source_ids": [
        "buttons",
        "feedback"
      ]
    },
    {
      "id": "icon-button",
      "name": "Icon button",
      "purpose": "Offer a familiar compact action.",
      "working_example": "Show or hide journey details; the accessible name changes with the action.",
      "states": [
        "default",
        "pressed",
        "focus",
        "selected",
        "disabled"
      ],
      "requirements": [
        "Keep the symbol conventional; reserve the claw for identity.",
        "Provide a programmatic action name and desktop tooltip.",
        "Do not use an icon-only control when a word resolves ambiguity."
      ],
      "source_ids": [
        "buttons",
        "offering-help",
        "voiceover"
      ]
    },
    {
      "id": "text-field",
      "name": "Text field",
      "purpose": "Capture one piece of information.",
      "working_example": "Edit a reservation name; validation explains a missing required value without erasing text.",
      "states": [
        "empty",
        "filled",
        "focused",
        "invalid",
        "disabled"
      ],
      "requirements": [
        "Persistent label, appropriate input type and autocomplete.",
        "Inline error linked to the field; validation timed to the task.",
        "Text areas handle longer messages."
      ],
      "source_ids": [
        "text-fields"
      ]
    },
    {
      "id": "search",
      "name": "Search and filter",
      "purpose": "Find items within a clear scope.",
      "working_example": "Search sample destinations; filter Nonstop and reset; show updated count and no-results recovery.",
      "states": [
        "empty",
        "typing",
        "results",
        "no-results",
        "loading",
        "error"
      ],
      "requirements": [
        "Keyboard-operable suggestions with named clear action.",
        "Retain search text and selected filters on failure.",
        "Separate narrowing results from purchasing a result."
      ],
      "source_ids": [
        "search-fields",
        "lists-and-tables"
      ]
    },
    {
      "id": "choice",
      "name": "Selection controls",
      "purpose": "Choose options with predictable selection rules.",
      "working_example": "Switch between Economy and Premium using a single-choice group; independently select baggage with checkboxes.",
      "states": [
        "selected",
        "unselected",
        "mixed where valid",
        "disabled"
      ],
      "requirements": [
        "Use radio behavior for one choice and checkbox behavior for independent choices.",
        "A setting switch applies its state immediately; do not disguise submission as a switch.",
        "State is represented in text/shape and semantics, not only tint."
      ],
      "source_ids": [
        "toggles",
        "segmented-controls"
      ]
    },
    {
      "id": "stepper",
      "name": "Guest stepper",
      "purpose": "Adjust a small bounded count precisely.",
      "working_example": "Change guests from 1 to 6 and update a reservation summary.",
      "states": [
        "minimum",
        "adjustable",
        "maximum",
        "invalid-entry"
      ],
      "requirements": [
        "Give decrement and increment buttons object-specific accessible names.",
        "State the minimum/maximum and expose a numeric entry alternative.",
        "Do not silently change room allocation when guest count changes."
      ],
      "source_ids": [
        "text-fields",
        "buttons"
      ]
    },
    {
      "id": "slider",
      "name": "Range slider",
      "purpose": "Explore a numeric range.",
      "working_example": "Adjust a nightly budget; a numeric field and filtered count update with the value.",
      "states": [
        "default",
        "focus",
        "dragging",
        "disabled"
      ],
      "requirements": [
        "Expose current value, minimum, maximum and unit.",
        "Arrow keys and direct numeric entry avoid a drag-only interaction.",
        "Use system volume controls for actual device volume."
      ],
      "source_ids": [
        "sliders"
      ]
    },
    {
      "id": "date-range",
      "name": "Date range",
      "purpose": "Select an arrival and departure date.",
      "working_example": "Choose check-in and check-out; show three nights, allow typed dates, and reset the range.",
      "states": [
        "start-empty",
        "end-empty",
        "selected-range",
        "invalid-range",
        "unavailable-date"
      ],
      "requirements": [
        "Name both endpoints; announce full dates and range state.",
        "Prevent checkout on/before check-in with an explicit correction.",
        "Month navigation, keyboard entry and locale formatting must all work.",
        "Changing a range updates a draft; any reservation update remains a separate review/action."
      ],
      "source_ids": [
        "pickers",
        "text-fields",
        "voiceover",
        "temporal-plain-date"
      ]
    },
    {
      "id": "time-picker",
      "name": "Time picker",
      "purpose": "Choose a time in an explicit place.",
      "working_example": "Select a dinner time, switching between displayed local and home-zone equivalents without changing the instant.",
      "states": [
        "selected",
        "unavailable-slot",
        "invalid-time"
      ],
      "requirements": [
        "Show the date and location zone when ambiguity matters.",
        "Honor 12/24-hour locale convention and avoid ambiguous bare abbreviations.",
        "Unavailable restaurant slots are data states, not free text guesses."
      ],
      "source_ids": [
        "pickers",
        "text-fields"
      ]
    },
    {
      "id": "tabs",
      "name": "Tabs and segmented choice",
      "purpose": "Move among destinations or related views.",
      "working_example": "Switch Flight / Stay / Reservation in a specimen while preserving edits in each.",
      "states": [
        "selected",
        "unselected",
        "focused"
      ],
      "requirements": [
        "Top-level navigation and local filtering are distinct contracts.",
        "Use correct keyboard model and associated panels.",
        "Do not make an action such as Book behave like a tab."
      ],
      "source_ids": [
        "tab-bars",
        "segmented-controls"
      ]
    },
    {
      "id": "menu",
      "name": "Menu and context menu",
      "purpose": "Expose a compact set of relevant actions.",
      "working_example": "A More menu opens Details, Copy itinerary and Remove sample; each acts on its named item.",
      "states": [
        "closed",
        "open",
        "focused-item",
        "unavailable-item"
      ],
      "requirements": [
        "Escape closes and returns focus; arrows navigate.",
        "Context-only actions also exist in the visible interface.",
        "A submenu is justified by a real group, not ornamental hierarchy."
      ],
      "source_ids": [
        "menus",
        "context-menus"
      ]
    },
    {
      "id": "list-table",
      "name": "List and comparison table",
      "purpose": "Compare text-heavy information.",
      "working_example": "Sort sample flights by departure, duration and total; select one for details.",
      "states": [
        "loading",
        "populated",
        "selected",
        "empty",
        "error"
      ],
      "requirements": [
        "Real table headers and announced sort direction on wide layouts.",
        "Compact layouts preserve label/value association; do not squeeze six columns into a phone.",
        "Selected row and destination detail remain related for assistive technology."
      ],
      "source_ids": [
        "lists-and-tables",
        "collections",
        "split-views"
      ]
    },
    {
      "id": "sheet",
      "name": "Sheet and dialog",
      "purpose": "Complete a scoped edit without losing context.",
      "working_example": "Edit a hotel check-in note; Save commits, Cancel restores the prior value.",
      "states": [
        "closed",
        "editing",
        "invalid",
        "saving",
        "saved",
        "failed"
      ],
      "requirements": [
        "Keep an edit buffer and define every dismiss path.",
        "Focus the dialog meaningfully, contain focus if modal, then restore it.",
        "A full booking journey needs a full page or sequence, not a tiny overflowing modal."
      ],
      "source_ids": [
        "sheets",
        "popovers",
        "alerts"
      ]
    },
    {
      "id": "feedback",
      "name": "Feedback and recovery",
      "purpose": "Explain local progress and outcomes.",
      "working_example": "Refresh a sample flight, then choose Current, Stale or Unavailable sample responses.",
      "states": [
        "loading",
        "success",
        "partial",
        "stale",
        "error"
      ],
      "requirements": [
        "Use progress only when there is real work; percentages need measurable completion.",
        "Place freshness/error beside the affected value.",
        "Preserve prior content on failure and name the retry."
      ],
      "source_ids": [
        "progress-indicators",
        "feedback",
        "loading"
      ]
    },
    {
      "id": "gallery",
      "name": "Image gallery",
      "purpose": "Inspect visual content while retaining context.",
      "working_example": "Change among three sample hotel photos using previous/next and labeled thumbnails.",
      "states": [
        "selected-image",
        "loading",
        "missing-image"
      ],
      "requirements": [
        "Use meaningful alt text and a count such as Photo 2 of 3.",
        "Do not autoplay or require swipe alone.",
        "Keep rate terms and room facts as live text outside photography."
      ],
      "source_ids": [
        "collections",
        "images",
        "voiceover"
      ]
    }
  ],
  "specialized_components": [
    {
      "id": "flight",
      "name": "Flight",
      "purpose": "Know when and where the next leg happens.",
      "anatomy": [
        "Airline and flight number",
        "Origin and destination names + codes",
        "Departure and arrival local date/time",
        "Scheduled versus estimated labels",
        "Gate/terminal when known",
        "Status source and last-checked time"
      ],
      "working_example": "Expand leg details; switch a labeled sample status; toggle airport-local/home-zone detail without silently replacing the primary local times.",
      "states": [
        "scheduled",
        "delayed",
        "boarding if reported",
        "departed",
        "arrived if confirmed",
        "cancelled",
        "status-unavailable",
        "stale"
      ],
      "requirements": [
        "Do not derive Boarding solely from a clock countdown.",
        "Gate time, takeoff, touchdown and gate arrival are different events; label the type supplied.",
        "Show +1 day alongside the full arrival date; do not calculate duration from displayed local clock values.",
        "Keep the previous verified state during failed refresh and mark its age.",
        "No invented gate, terminal, operating carrier or confidence percentage."
      ],
      "source_ids": [
        "labels",
        "feedback",
        "lists-and-tables",
        "duffel-offers",
        "flightaware-data"
      ],
      "sample": {
        "kind": "fictional",
        "label": "Sample flight — not a live service",
        "flight": "Cloudline CL208",
        "origin": "New York JFK",
        "destination": "London Heathrow LHR",
        "departure": "2026-09-17T22:10:00-04:00",
        "origin_zone": "America/New_York",
        "arrival": "2026-09-18T10:00:00+01:00",
        "destination_zone": "Europe/London",
        "elapsed": "6h 50m",
        "gate": null,
        "status": "Scheduled",
        "freshness": "Sample snapshot · 17 September 2026, 18:00 New York time"
      }
    },
    {
      "id": "journey",
      "name": "Journey",
      "purpose": "See connected plans in chronological order.",
      "anatomy": [
        "Trip title and local date groups",
        "Flight/stay/event rows",
        "Transport links",
        "Selection and detail pane"
      ],
      "working_example": "Filter one day, expand a leg, and select a place for address/details. Keep actual bookings separate from editable personal notes.",
      "states": [
        "planning",
        "upcoming",
        "in-progress",
        "completed",
        "partial-import"
      ],
      "requirements": [
        "Sort cross-zone events by resolved instants where available, while preserving local date labels.",
        "A hotel date range is not a single midnight timestamp.",
        "Do not claim a transfer is feasible from time gap alone; terminal changes, border control and airline policy may matter.",
        "Map illustrations need an explicit label and a textual route/address alternative."
      ],
      "source_ids": [
        "lists-and-tables",
        "split-views",
        "maps",
        "layout"
      ],
      "sample": {
        "kind": "fictional",
        "title": "A few days in London",
        "dates": "18–21 September 2026",
        "label": "Sample journey"
      }
    },
    {
      "id": "hotel",
      "name": "Hotel stay",
      "purpose": "Make dates, room and terms easy to inspect.",
      "anatomy": [
        "Property name and address",
        "Check-in and check-out calendar dates",
        "Number of nights and guests",
        "Room/rate description",
        "Total amount/currency and price scope",
        "Check-in/out time policy",
        "Cancellation/payment terms from source"
      ],
      "working_example": "Edit a date range and guest count, view a local sample room, and recalculate only explicitly defined sample totals.",
      "states": [
        "available-offer",
        "selected",
        "booking-pending",
        "confirmed",
        "modified",
        "cancelled",
        "availability-unknown"
      ],
      "requirements": [
        "Store check-in/out as calendar dates in the property’s context; changing viewer zone must not move the stay.",
        "Check-in time is a property policy, not evidence that a room is ready.",
        "Separate room photos, star classification and guest review scores.",
        "Show total and any known excluded/conditional fees before a real booking action.",
        "Availability and terms must be refreshed for changed dates or occupancy."
      ],
      "source_ids": [
        "pickers",
        "collections",
        "labels",
        "booking-search",
        "booking-dates",
        "temporal-plain-date"
      ],
      "sample": {
        "kind": "fictional",
        "name": "Harbour House",
        "city": "London",
        "checkin": "2026-09-18",
        "checkout": "2026-09-21",
        "zone": "Europe/London",
        "nights": 3,
        "guests": 2,
        "checkin_policy": "After 15:00 local time",
        "checkout_policy": "Before 11:00 local time",
        "label": "Sample stay — no reservation exists"
      }
    },
    {
      "id": "reservation",
      "name": "Reservation",
      "purpose": "Understand a place, party size and booking outcome.",
      "anatomy": [
        "Venue and location",
        "Local date/time + zone",
        "Party size",
        "Reference and status",
        "Relevant terms and contact route"
      ],
      "working_example": "Choose a sample time and party size, review a complete draft, then create only a clearly labeled local example confirmation.",
      "states": [
        "draft",
        "request-sent",
        "confirmed",
        "change-pending",
        "cancelled",
        "outcome-unknown"
      ],
      "requirements": [
        "A submitted request is not confirmed until the provider says so.",
        "Cancellation requires the actual reservation and applicable terms; closing a sheet does not cancel a booking.",
        "Keep reference private in shared views.",
        "A changed party size/time is a new availability check in a real product."
      ],
      "source_ids": [
        "pickers",
        "sheets",
        "alerts",
        "feedback",
        "privacy"
      ],
      "sample": {
        "kind": "fictional",
        "venue": "The Lantern",
        "local_date": "2026-09-19",
        "local_time": "19:30",
        "zone": "Europe/London",
        "party": 2,
        "label": "Local reservation example"
      }
    },
    {
      "id": "world-time",
      "name": "World time",
      "purpose": "Compare the same moment in different places.",
      "anatomy": [
        "City",
        "Local date and clock time",
        "Zone/offset detail",
        "Day relation when dates differ"
      ],
      "working_example": "Change a reference instant and compare London and New York, with a button to return to Now.",
      "states": [
        "live-now",
        "chosen-moment",
        "zone-unavailable"
      ],
      "requirements": [
        "Use IANA zone IDs in data; show city names rather than relying on ambiguous abbreviations.",
        "A changed reference time updates all clocks to the same instant.",
        "Account for date rollover and daylight-saving transitions.",
        "A ticking seconds display does not need screen-reader announcements every second."
      ],
      "source_ids": [
        "labels",
        "pickers",
        "voiceover",
        "temporal-plain-date"
      ],
      "sample": {
        "label": "Same moment",
        "instant": "2026-09-18T14:00:00Z",
        "London": "15:00 · 18 Sep · BST",
        "New York": "10:00 · 18 Sep · EDT"
      }
    },
    {
      "id": "ticket",
      "name": "Ticket",
      "purpose": "Reach the valid pass and useful event details quickly.",
      "anatomy": [
        "Event or travel title",
        "Venue/route and date",
        "Seat/class when known",
        "Validity and issuer",
        "Credential reveal area",
        "Issuer/Wallet route when supported"
      ],
      "working_example": "Reveal and hide a non-scannable demo pass, inspect seat details and switch sample valid/expired/transferred states.",
      "states": [
        "preview",
        "available",
        "hidden-credential",
        "expired",
        "voided",
        "transferred",
        "issuer-access-required"
      ],
      "requirements": [
        "Public examples use non-scannable placeholders and a persistent Not valid for entry label.",
        "Use issuer-supported pass assets and APIs; do not draw arbitrary codes and label them valid.",
        "For rotating/mobile-only tickets, point to the issuer route; screenshots may not work.",
        "A Share itinerary action omits credential payload; Transfer ticket follows the issuer flow and must not be imitated by sharing an image.",
        "Wallet buttons appear only when the actual signed pass/integration is available.",
        "Do not put names, booking references or barcodes in ambient previews by default."
      ],
      "source_ids": [
        "wallet",
        "privacy",
        "notifications",
        "ticketmaster-moving-barcode",
        "ticketmaster-transfer",
        "apple-wallet-start",
        "apple-wallet-pass"
      ],
      "sample": {
        "label": "Demo pass — not valid for entry",
        "event": "Evening at the Observatory",
        "date": "19 September 2026",
        "doors": "18:30 local",
        "start": "19:00 local",
        "seat": "Section A · Row 4 · Seat 12",
        "credential": "Hidden non-scannable placeholder"
      }
    }
  ],
  "platforms": [
    {
      "id": "ios",
      "name": "iOS",
      "source_ids": [
        "designing-for-ios",
        "tab-bars",
        "toolbars",
        "pickers",
        "sheets",
        "typography"
      ],
      "navigation": "Stable top-level tabs where the product needs separate destinations; top navigation supplies a contextual title and back action.",
      "layout": "One main column, a compact journey summary and expandable details; keep important controls reachable and above keyboard and safe-area insets.",
      "glass": "Use native material-backed navigation and controls in an actual app. In this web specimen, show the proposed hierarchy without imitating system permissions or biometric prompts.",
      "input": "Touch-first targets, labeled controls, native text/date entry where suitable, keyboard and VoiceOver support.",
      "example": "Flight summary → details → chosen date review, with back navigation preserving the prior selection."
    },
    {
      "id": "macos",
      "name": "macOS",
      "source_ids": [
        "designing-for-macos",
        "sidebars",
        "split-views",
        "toolbars",
        "typography"
      ],
      "navigation": "Sidebar for destinations, toolbar for current-view actions and search; expose native commands in the menu bar in a real app.",
      "layout": "Resizable window, optional list/detail split, selected row visible, comparison columns where width supports them.",
      "glass": "Native chrome may use material and vibrancy; keep dense tables on a stable reading surface.",
      "input": "Command shortcuts, pointer hover, keyboard traversal, selectable text and resizable columns. Essential actions remain reachable if the bottom of the window is offscreen.",
      "example": "Journey list beside selected flight, with a detail inspector for fare or ticket information."
    },
    {
      "id": "linux",
      "name": "Linux",
      "source_ids": [
        "gnome-header-bars",
        "gnome-adaptive"
      ],
      "navigation": "Use the host toolkit and desktop conventions for window management, titlebar and menus. A GNOME header bar is one reference, not a rule for every Linux desktop.",
      "layout": "The same content adapts to narrow tiled windows and wider desktop use; do not assume a large display or pointer-only input.",
      "glass": "Use OpenClaw’s glass within the content/chrome the app owns. Provide solid fallback; do not assume desktop-background blur or a specific compositor.",
      "input": "Control-based shortcuts where conventional, standard file and text behavior, keyboard access and the host assistive stack. Do not paint fake macOS traffic lights as functional controls.",
      "example": "A compact journey list with contextual details and a host-appropriate header bar."
    }
  ],
  "voice": {
    "id": "open-channel",
    "name": "Open channel",
    "source_ids": [
      "playing-audio",
      "feedback",
      "voiceover",
      "privacy",
      "motion"
    ],
    "visual": "A stable glass capsule holds a small approved claw mark and a single open, curved channel. The channel borrows the negative-space rhythm of the claw; keep familiar microphone and stop icons on actual controls. The logo geometry itself does not deform.",
    "states": [
      {
        "id": "idle",
        "label": "Ready when you are",
        "visual": "Quiet open channel, no motion",
        "action": "Start voice"
      },
      {
        "id": "listening",
        "label": "Listening",
        "visual": "Small, bounded movement follows actual input level",
        "action": "Stop listening"
      },
      {
        "id": "transcribing",
        "label": "Preparing your words",
        "visual": "Still channel with a brief progress cue if needed",
        "action": "Edit transcript"
      },
      {
        "id": "speaking",
        "label": "Speaking",
        "visual": "Movement follows actual playback level",
        "action": "Stop speaking"
      },
      {
        "id": "muted",
        "label": "Microphone off",
        "visual": "Static channel and conventional microphone-off symbol",
        "action": "Turn on microphone"
      },
      {
        "id": "unavailable",
        "label": "Voice unavailable",
        "visual": "Static neutral surface and readable explanation",
        "action": "Type instead"
      }
    ],
    "anatomy": [
      "State label",
      "Explicit input/output route when active",
      "Start or stop button named for its actual action",
      "Readable correctable transcript",
      "A visible text alternative"
    ],
    "demo": "A Play voice animation action may simulate these states locally, labeled Visual simulation — microphone off. Start listening must not claim live capture unless getUserMedia/native capture actually succeeds.",
    "behavior": [
      "Initiate recording only from an explicit user action and the appropriate system permission flow. Keep access explanation specific to this feature.",
      "Ending capture and stopping playback are separate actions. Neither silently implies cancellation of an unrelated task.",
      "Do not auto-unmute or resume private playback after a device interruption. Pause playback when headphones disconnect; expose the route before resuming.",
      "Use actual levels for a real meter. A prerecorded visual loop is a demonstration, not evidence that sound is captured.",
      "Keep speech controls familiar; do not repurpose system volume or media transport commands for unrelated actions.",
      "Preserve transcript on failure so people can correct and continue through text. Do not read private ticket credentials aloud by default."
    ],
    "accessibility": [
      "The moving channel is decorative and hidden from the accessibility tree. State and transcript carry the meaning.",
      "Announce start, stop and meaningful errors once; do not announce every amplitude sample or every streamed token.",
      "Reduced motion uses a static shape and text with equal functionality. Sound and haptics are optional reinforcement.",
      "No drag, press-and-hold, voice-only or pointer-only action is required. A keyboard user can start, stop, edit and switch to text."
    ],
    "brand_boundary": "This is an original OpenClaw voice motif, not a copy of Siri, a rotating orb, or an Apple system-control asset."
  },
  "data_integrity": {
    "flight_times": "Keep scheduled, estimated and actual values distinct. Store instants with offsets/zone information when provided; if the provider gives local wall time plus an airport zone, resolve them together. Display departure in the origin zone and arrival in the destination zone, with explicit dates across midnight. Elapsed duration comes from instants/provider duration, never subtraction of two displayed clock strings.",
    "calendar_dates": "Keep hotel check-in/check-out as calendar dates; do not parse YYYY-MM-DD as a UTC instant and then display it in the viewer’s zone. The property’s check-in/out times are separate policy values. Nights are date differences, not elapsed milliseconds divided by 24 hours.",
    "freshness": "Distinguish data observedAt, fetchedAt and validUntil. A successful fetch does not guarantee that a gate/status changed recently. Unknown stays unknown. Display a last-checked label and a stale/offline state; no invented universal refresh cadence.",
    "pricing": "Use amount plus explicit currency and scope (per person, per room/night, or total). A search offer is not a booking. Revalidate availability and price before a real purchase; show changed material terms before completion.",
    "pass_security": "Treat barcode payloads, booking reference/name combinations and access links as sensitive. Redact in public previews, notifications, logs and shared screenshots. Do not promise screenshot prevention or equate a hidden Share button with secure non-transferability."
  },
  "verification": [
    "At 320 CSS px and 200% content enlargement, no essential airport, date, currency, field error or action is clipped.",
    "Keyboard-only: open menus, change tabs, choose dates, adjust a value, dismiss a dialog, reveal ticket detail and stop voice. Focus stays visible and returns logically.",
    "Screen reader: each repeated action identifies its object; date cells include full date and selection state; result changes announce once.",
    "Material: test light/dark, moving bright/dark backdrops, reduced transparency/motion, forced colours and no backdrop-filter.",
    "Flight: test cross-midnight arrival, DST change, missing gate, conflicting scheduled/estimated time, stale status and offline refresh.",
    "Stay: test month/year rollover, leap day, DST weekend, invalid checkout and changed guest count.",
    "Ticket: test hidden credential, expired/voided/transferred sample, unavailable Wallet action and issuer-only dynamic barcode.",
    "Live-service capability, native window behavior, microphone capture, Wallet issuance and physical-device presentation require separate integration verification."
  ]
}
