{
  "_meta": {
    "purpose": "Machine-readable index of the Gather design system. Read this before UI work.",
    "generatedFrom": [
      "src/data/designSystemCatalog.js",
      "src/data/designTokens.js",
      "src/index.css"
    ],
    "regenerate": "npm run design-system:manifest (runs on build and in the pre-commit hook; the dev server serves it live)",
    "verify": "npm run design-system:check",
    "howToUse": [
      "components: what exists, what each is for, where its source file is, its use/avoid guidance, and the behaviors that bind it. Its page is routes.component with {portal} and {component} filled in.",
      "tokens.sections: every custom property in src/index.css as name: value. The admin and agency portals share one token set. Use var(--name) or the matching Tailwind utility, never a literal value.",
      "guidelines.principles: qualities a redesign must keep. guidelines.behaviors: interaction rules that span components; each names the components it binds, and each component lists its behaviors. Entries with standard: \"prototype\" are about the mockup being reviewable, not the product. Rendered at /ui/{portal}/guidelines.",
      "since and because on any entry record when and why a call was made. Keep them when editing the entry.",
      "To add a rule, edit the catalog: a principle, a behavior naming the components it binds, or a component guidance entry. Do not create a markdown rules file."
    ]
  },
  "project": {
    "name": "Gather Mockups",
    "company": "Gather Records",
    "product": "Gather",
    "baseDesignSystemPath": "/ui",
    "baseDesignSystemUrl": "https://gather.orchidux.com/ui"
  },
  "portals": [
    {
      "id": "admin",
      "label": "Admin",
      "description": "Internal Gather staff and Master Admin workflows for agency oversight, billing, refunds, services, and pricing."
    },
    {
      "id": "agency",
      "label": "Agency",
      "description": "Surrogacy agency client workflows for cases, billing, payment methods, receipts, and invoices."
    }
  ],
  "routes": {
    "siteUrl": "https://gather.orchidux.com",
    "home": "/ui",
    "portal": "/ui/{portal}",
    "components": "/ui/{portal}/components",
    "component": "/ui/{portal}/components/{component}",
    "foundation": "/ui/{portal}/foundations/{topic}",
    "tokens": "/ui/{portal}/tokens",
    "guidelines": "/ui/{portal}/guidelines",
    "manifest": "/ui/manifest.json"
  },
  "components": [
    {
      "id": "alert",
      "label": "Alert",
      "description": "Status and notification banners for success, warning, danger, info, and neutral states.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Alert.jsx",
      "behaviors": [
        "billing-state-and-owner",
        "error-scope",
        "failure-copy",
        "action-sequence",
        "motion-explains",
        "not-color-alone",
        "reachable-failure"
      ]
    },
    {
      "id": "autocomplete",
      "label": "Autocomplete",
      "description": "Type-ahead selection input for local option sets.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Autocomplete.jsx",
      "guidance": {
        "use": [
          "Pass label for the visible label, helperText for guidance, and hasError with the error message prop for validation."
        ],
        "avoid": [
          "placeholder as the only label."
        ]
      },
      "behaviors": [
        "forms-keep-context",
        "error-scope",
        "keyboard-focus",
        "not-color-alone"
      ]
    },
    {
      "id": "avatar",
      "label": "Avatar",
      "description": "Identity avatar patterns with initials and image examples across supported sizes.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Avatar.jsx"
    },
    {
      "id": "badge",
      "label": "Badge",
      "description": "Compact labels for status, counts, metadata, and workflow state.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Badge.jsx",
      "behaviors": [
        "billing-state-and-owner",
        "agency-mobile-essentials",
        "not-color-alone"
      ]
    },
    {
      "id": "breadcrumbs",
      "label": "Breadcrumbs",
      "description": "Page hierarchy trail for nested admin and agency workflows.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Breadcrumbs.jsx",
      "behaviors": [
        "keyboard-focus"
      ]
    },
    {
      "id": "button",
      "label": "Button",
      "description": "Primary, secondary, tertiary, destructive, ghost, link, icon, disabled, and loading action states.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Button.jsx",
      "guidance": {
        "use": [
          "Use the current API: type primary, secondary, tertiary, destructive, ghost, or link, and size l, m, s, or xs. Destructive is for actions that remove, cancel, or refund."
        ],
        "avoid": [
          "The legacy filled/outlined type plus color API for new work; it still renders through translation but is not the design."
        ]
      },
      "behaviors": [
        "billing-state-and-owner",
        "agency-mobile-essentials",
        "action-sequence",
        "destructive-scope",
        "keyboard-focus",
        "reachable-failure"
      ]
    },
    {
      "id": "button-group",
      "label": "Button Group",
      "description": "Grouped action controls for related command sets.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/ButtonGroup.jsx",
      "behaviors": [
        "action-sequence",
        "keyboard-focus",
        "reachable-failure"
      ]
    },
    {
      "id": "card",
      "label": "Card",
      "description": "Framed content container for repeated records, summaries, form sections, and contained tools.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Card.jsx",
      "guidance": {
        "use": [
          "Cards hold repeated records, receipt and invoice summaries, form sections, and modal content.",
          "The Card shell owns its 16px padding; content cards set their own inner padding."
        ],
        "avoid": [
          "Nesting a Card inside a Card.",
          "Adding padding classes around the shell."
        ]
      },
      "behaviors": [
        "billing-state-and-owner",
        "agency-mobile-essentials",
        "overlay-trigger-context",
        "trigger-surfaces",
        "motion-explains"
      ]
    },
    {
      "id": "checkbox",
      "label": "Checkbox",
      "description": "Binary selection control with labels, helper text, error, and disabled states.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Checkbox.jsx",
      "behaviors": [
        "selection-scope",
        "keyboard-focus"
      ]
    },
    {
      "id": "circular-progress",
      "label": "Circular Progress",
      "description": "Circular progress indicator for compact completion and loading states.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/CircularProgress.jsx",
      "behaviors": [
        "not-color-alone"
      ]
    },
    {
      "id": "combobox",
      "label": "Combobox",
      "description": "Searchable single-select control for larger option sets.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Combobox.jsx",
      "guidance": {
        "use": [
          "Pass label for the visible label, helperText for guidance, and hasError with the error message prop for validation."
        ],
        "avoid": [
          "placeholder as the only label."
        ]
      },
      "behaviors": [
        "forms-keep-context",
        "error-scope",
        "keyboard-focus",
        "not-color-alone"
      ]
    },
    {
      "id": "datepicker",
      "label": "Datepicker",
      "description": "Date input with calendar picker, helper, error, filled, and disabled states.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Datepicker.jsx",
      "guidance": {
        "use": [
          "Pass label for the visible label, helperText for guidance, and hasError with the error message prop for validation."
        ],
        "avoid": [
          "placeholder as the only label."
        ]
      },
      "behaviors": [
        "forms-keep-context",
        "error-scope",
        "keyboard-focus",
        "not-color-alone"
      ]
    },
    {
      "id": "drag-drop-upload",
      "label": "Drag Drop Upload",
      "description": "Drop-zone upload surface for one or more files with constraints.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/DragDropUpload.jsx"
    },
    {
      "id": "dropdown-button",
      "label": "Dropdown Button",
      "description": "Button-triggered menu action patterns.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/DropdownButton.jsx",
      "behaviors": [
        "action-sequence",
        "destructive-scope",
        "motion-explains",
        "keyboard-focus",
        "reachable-failure"
      ]
    },
    {
      "id": "empty-state",
      "label": "Empty State",
      "description": "Empty, no-result, and onboarding states with optional action affordances.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/EmptyState.jsx",
      "behaviors": [
        "failure-copy"
      ]
    },
    {
      "id": "file-upload",
      "label": "File Upload",
      "description": "Single-file picker styled as a form field, with helper, error, required, disabled, and append-button states.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/FileUpload.jsx",
      "guidance": {
        "use": [
          "Pass label for the visible label, helperText for guidance, and hasError with the error message prop for validation."
        ],
        "avoid": [
          "placeholder as the only label."
        ]
      },
      "behaviors": [
        "forms-keep-context",
        "error-scope",
        "keyboard-focus",
        "not-color-alone"
      ]
    },
    {
      "id": "header",
      "label": "Header",
      "description": "Gather portal header with logo, contact action, and user dropdown.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Header.jsx",
      "guidance": {
        "use": [
          "The agency portal shell: logo, Contact Gather, and the user dropdown. AgencyLayout wraps every /agency page with it."
        ],
        "avoid": [
          "Using it as an admin chrome; admin pages navigate through the Sidebar."
        ]
      },
      "behaviors": [
        "keyboard-focus"
      ]
    },
    {
      "id": "icon-button",
      "label": "Icon Button",
      "description": "Round icon-only button in filled, outlined, neutral, and ghost types for compact actions.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/IconButton.jsx",
      "guidance": {
        "use": [
          "Give every icon button a name: an aria-label, or a Tooltip that names the action. The icon alone is not a label."
        ],
        "avoid": []
      },
      "behaviors": [
        "action-sequence",
        "keyboard-focus",
        "reachable-failure"
      ]
    },
    {
      "id": "input",
      "label": "Input",
      "description": "Text input with labels, icons, add-ons, helper text, error, filled, and disabled states.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Input.jsx",
      "guidance": {
        "use": [
          "Pass label for the visible label, helperText for guidance, and hasError with the error message prop for validation."
        ],
        "avoid": [
          "placeholder as the only label."
        ]
      },
      "behaviors": [
        "forms-keep-context",
        "error-scope",
        "keyboard-focus",
        "not-color-alone"
      ]
    },
    {
      "id": "modal",
      "label": "Modal",
      "description": "Dialog surface for compact forms, confirmations, and focused tasks.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Modal.jsx",
      "behaviors": [
        "overlay-trigger-context",
        "modal-vs-drawer",
        "error-scope",
        "failure-copy",
        "destructive-scope",
        "motion-explains",
        "keyboard-focus",
        "reachable-failure"
      ]
    },
    {
      "id": "multi-select",
      "label": "Multi Select",
      "description": "Multiple-value searchable selection control.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/MultiSelect.jsx",
      "guidance": {
        "use": [
          "Pass label for the visible label, helperText for guidance, and hasError with the error message prop for validation."
        ],
        "avoid": [
          "placeholder as the only label."
        ]
      },
      "behaviors": [
        "forms-keep-context",
        "error-scope",
        "keyboard-focus",
        "not-color-alone"
      ]
    },
    {
      "id": "pagination",
      "label": "Pagination",
      "description": "Numbered collection navigation with disabled and ellipsis states.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Pagination.jsx",
      "behaviors": [
        "selection-scope",
        "selection-context",
        "keyboard-focus",
        "pagination-decided",
        "three-pages-of-fixtures",
        "stable-identities"
      ]
    },
    {
      "id": "phone-input",
      "label": "Phone Input",
      "description": "Phone number field with a country-code selector, sizes, states, and an optional append button.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/PhoneInput.jsx",
      "guidance": {
        "use": [
          "Pass label for the visible label, helperText for guidance, and hasError with the error message prop for validation."
        ],
        "avoid": [
          "placeholder as the only label."
        ]
      },
      "behaviors": [
        "forms-keep-context",
        "error-scope",
        "keyboard-focus",
        "not-color-alone"
      ]
    },
    {
      "id": "progress",
      "label": "Progress",
      "description": "Linear progress indicator for completion, upload, and review state.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Progress.jsx",
      "behaviors": [
        "not-color-alone"
      ]
    },
    {
      "id": "radio",
      "label": "Radio",
      "description": "Single-choice option group with descriptions, helper, error, and disabled states.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Radio.jsx",
      "behaviors": [
        "keyboard-focus"
      ]
    },
    {
      "id": "select",
      "label": "Select",
      "description": "Dropdown select with labels, icons, add-ons, helper, error, and disabled states.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Select.jsx",
      "guidance": {
        "use": [
          "Pass label for the visible label, helperText for guidance, and hasError with the error message prop for validation."
        ],
        "avoid": [
          "placeholder as the only label."
        ]
      },
      "behaviors": [
        "forms-keep-context",
        "error-scope",
        "keyboard-focus",
        "not-color-alone"
      ]
    },
    {
      "id": "sidebar",
      "label": "Sidebar",
      "description": "Side navigation for admin workspaces and design-system reference screens.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Sidebar.jsx",
      "guidance": {
        "use": [
          "The admin portal shell. AdminLayout wraps every /admin page with it."
        ],
        "avoid": [
          "Showing it on agency pages; the agency portal has no sidebar."
        ]
      },
      "behaviors": [
        "keyboard-focus"
      ]
    },
    {
      "id": "switch",
      "label": "Switch",
      "description": "On/off toggle with labels, helper text, error, and disabled states.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Switch.jsx",
      "behaviors": [
        "keyboard-focus",
        "not-color-alone"
      ]
    },
    {
      "id": "table",
      "label": "Table",
      "description": "Data table with selectable rows, sorting, controls, and pagination examples.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Table.jsx",
      "behaviors": [
        "billing-state-and-owner",
        "agency-mobile-essentials",
        "overlay-trigger-context",
        "trigger-surfaces",
        "error-scope",
        "selection-scope",
        "selection-context",
        "motion-explains",
        "keyboard-focus",
        "pagination-decided",
        "three-pages-of-fixtures",
        "stable-identities"
      ]
    },
    {
      "id": "tabs",
      "label": "Tabs",
      "description": "Tab navigation with pills, line, disabled, and multi-tab variants.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Tabs.jsx",
      "behaviors": [
        "keyboard-focus"
      ]
    },
    {
      "id": "textarea",
      "label": "Textarea",
      "description": "Multi-line text input with helper, error, filled, and disabled states.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Textarea.jsx",
      "guidance": {
        "use": [
          "Pass label for the visible label, helperText for guidance, and hasError with the error message prop for validation."
        ],
        "avoid": [
          "placeholder as the only label."
        ]
      },
      "behaviors": [
        "forms-keep-context",
        "error-scope",
        "keyboard-focus",
        "not-color-alone"
      ]
    },
    {
      "id": "toast",
      "label": "Toast",
      "description": "Transient notification feedback with placement, variants, and optional action.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Toast.jsx",
      "behaviors": [
        "error-scope",
        "failure-copy",
        "action-sequence",
        "motion-explains",
        "not-color-alone",
        "reachable-failure"
      ]
    },
    {
      "id": "tooltip",
      "label": "Tooltip",
      "description": "Hover and focus helper text rendered outside clipping containers.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Tooltip.jsx",
      "behaviors": [
        "motion-explains",
        "keyboard-focus"
      ]
    },
    {
      "id": "user-dropdown",
      "label": "User Dropdown",
      "description": "User menu trigger and floating account action list.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/UserDropdown.jsx",
      "behaviors": [
        "motion-explains",
        "keyboard-focus"
      ]
    },
    {
      "id": "wysiwyg",
      "label": "Wysiwyg",
      "description": "Rich-text editor surface for formatted long-form content.",
      "portals": [
        "admin",
        "agency"
      ],
      "source": "src/components/Wysiwyg.jsx",
      "guidance": {
        "use": [
          "Pass label for the visible label, helperText for guidance, and hasError with the error message prop for validation."
        ],
        "avoid": [
          "placeholder as the only label."
        ]
      },
      "behaviors": [
        "forms-keep-context",
        "error-scope",
        "keyboard-focus",
        "not-color-alone"
      ]
    }
  ],
  "foundations": [
    {
      "id": "colors",
      "label": "Colors",
      "description": "Neutral, brand, and semantic palettes for Gather workflows."
    },
    {
      "id": "typography",
      "label": "Typography",
      "description": "Geist font family, sizes, weights, line heights, and letter spacing."
    },
    {
      "id": "spacing",
      "label": "Spacing",
      "description": "Spacing scale used for layout, component gaps, and page rhythm."
    },
    {
      "id": "border-radius",
      "label": "Border Radius",
      "description": "Corner radius scale for controls, cards, and overlays."
    },
    {
      "id": "icon-sizes",
      "label": "Icon Sizes",
      "description": "Icon sizing tokens for controls, navigation, and metadata."
    },
    {
      "id": "opacity",
      "label": "Opacity",
      "description": "Opacity values for disabled, hover, and emphasis states."
    },
    {
      "id": "shadows",
      "label": "Shadows",
      "description": "Elevation shadows for cards, overlays, and floating action surfaces."
    }
  ],
  "tokens": {
    "source": "src/index.css",
    "usage": "var(--<name>) or the matching Tailwind utility. sections are resolved for the admin portal; portalOverrides lists what other portals change or add.",
    "sections": [
      {
        "id": "colors",
        "label": "Colors",
        "description": "Neutral, brand, semantic, and focus colors. Violet, purple, and turquoise names are compatibility aliases for Gather blue.",
        "groups": [
          {
            "id": "neutral",
            "label": "Neutral",
            "tokens": {
              "color-neutral-0": "#FFFFFF",
              "color-neutral-5": "#F9FAFB",
              "color-neutral-10": "#F3F4F6",
              "color-neutral-20": "#E5E7EB",
              "color-neutral-40": "#D1D5DB",
              "color-neutral-60": "#9CA3AF",
              "color-neutral-80": "#6B7280",
              "color-neutral-100": "#111827"
            }
          },
          {
            "id": "brand",
            "label": "Brand",
            "tokens": {
              "color-blue": "#086092",
              "color-blue-light": "#9CBFD3",
              "color-blue-lightest": "#E6F0F6",
              "color-blue-dark": "#21709D",
              "color-blue-darkest": "#054568"
            }
          },
          {
            "id": "compat",
            "label": "Compatibility aliases (resolve to blue)",
            "tokens": {
              "color-violet": "var(--color-blue)",
              "color-violet-light": "var(--color-blue-light)",
              "color-violet-dark": "var(--color-blue-dark)",
              "color-purple": "var(--color-blue)",
              "color-purple-light": "var(--color-blue-light)",
              "color-purple-dark": "var(--color-blue-dark)",
              "color-turquoise": "var(--color-blue)",
              "color-turquoise-light": "var(--color-blue-lightest)",
              "color-turquoise-dark": "var(--color-blue-dark)"
            }
          },
          {
            "id": "semantic",
            "label": "Semantic",
            "tokens": {
              "color-danger": "#DC2626",
              "color-danger-light": "#FEE2E2",
              "color-danger-dark": "#B91C1C",
              "color-danger-darkest": "#7F1D1D",
              "color-success": "#16A34A",
              "color-success-light": "#DCFCE7",
              "color-success-dark": "#15803D",
              "color-success-darkest": "#14532D",
              "color-warning": "#D97706",
              "color-warning-light": "#FEF3C7",
              "color-warning-dark": "#B45309",
              "color-warning-darkest": "#78350F",
              "color-info": "#0284C7",
              "color-info-light": "#E0F2FE",
              "color-info-dark": "#0369A1",
              "color-info-darkest": "#0C4A6E"
            }
          },
          {
            "id": "focus",
            "label": "Focus",
            "tokens": {
              "color-focus-ring": "#93C5FD",
              "color-focus-ring-danger": "#DC262640",
              "color-focus-shadow": "#08609240"
            }
          }
        ]
      },
      {
        "id": "typography",
        "label": "Typography",
        "description": "Font family, size, line height, weight, and letter spacing.",
        "groups": [
          {
            "id": "font-family",
            "label": "Font Family",
            "tokens": {
              "font-family-body": "\"Geist\", system-ui, -apple-system, sans-serif",
              "font-family-heading": "\"Geist\", system-ui, -apple-system, sans-serif",
              "font-family-mono": "\"Geist Mono\", \"SF Mono\", Consolas, monospace"
            }
          },
          {
            "id": "font-size",
            "label": "Font Size",
            "tokens": {
              "font-size-sm": "12px",
              "font-size-base": "14px",
              "font-size-lg": "16px",
              "font-size-xl": "20px",
              "font-size-2xl": "26px",
              "font-size-3xl": "32px",
              "font-size-4xl": "40px"
            }
          },
          {
            "id": "line-height",
            "label": "Line Height",
            "tokens": {
              "line-height-sm": "18px",
              "line-height-base": "22px",
              "line-height-lg": "24px",
              "line-height-xl": "30px",
              "line-height-2xl": "31px",
              "line-height-3xl": "38px",
              "line-height-4xl": "48px"
            }
          },
          {
            "id": "font-weight",
            "label": "Font Weight",
            "tokens": {
              "font-weight-normal": "400",
              "font-weight-medium": "500",
              "font-weight-semibold": "600",
              "font-weight-bold": "700"
            }
          },
          {
            "id": "letter-spacing",
            "label": "Letter Spacing",
            "tokens": {
              "letter-spacing-tighter": "-0.7px",
              "letter-spacing-tight": "-0.35px",
              "letter-spacing-normal": "0px",
              "letter-spacing-wide": "0.35px",
              "letter-spacing-wider": "0.7px",
              "letter-spacing-widest": "1.4px"
            }
          }
        ]
      },
      {
        "id": "spacing",
        "label": "Spacing",
        "description": "Spacing scale for layout, gaps, and component composition.",
        "groups": [
          {
            "id": "spacing",
            "label": "All Spacing Tokens",
            "tokens": {
              "spacing-3xs": "2px",
              "spacing-2xs": "4px",
              "spacing-xs": "8px",
              "spacing-sm": "12px",
              "spacing-md": "16px",
              "spacing-lg": "24px",
              "spacing-xl": "32px",
              "spacing-2xl": "48px",
              "spacing-3xl": "64px",
              "spacing-4xl": "96px"
            }
          }
        ]
      },
      {
        "id": "border-radius",
        "label": "Border Radius",
        "description": "Corner radius scale for controls, cards, overlays, and rounded surfaces.",
        "groups": [
          {
            "id": "radius",
            "label": "All Radius Tokens",
            "tokens": {
              "radius-none": "0px",
              "radius-sm": "4px",
              "radius-md": "6px",
              "radius-lg": "8px",
              "radius-full": "9999px"
            }
          }
        ]
      },
      {
        "id": "border-width",
        "label": "Border Width",
        "description": "Border widths for outlines and separators.",
        "groups": [
          {
            "id": "border-width",
            "label": "All Border Width Tokens",
            "tokens": {
              "border-width-0": "0px",
              "border-width-1": "1px",
              "border-width-2": "2px"
            }
          }
        ]
      },
      {
        "id": "sizing",
        "label": "Sizing",
        "description": "Avatar, icon, control height, and form control sizes.",
        "groups": [
          {
            "id": "avatar",
            "label": "Avatar Sizes",
            "tokens": {
              "avatar-xs": "16px",
              "avatar-sm": "24px",
              "avatar-md": "32px",
              "avatar-lg": "40px",
              "avatar-xl": "48px",
              "avatar-2xl": "64px",
              "avatar-3xl": "128px"
            }
          },
          {
            "id": "icon",
            "label": "Icon Sizes",
            "tokens": {
              "icon-xs": "12px",
              "icon-sm": "16px",
              "icon-md": "20px",
              "icon-lg": "24px",
              "icon-xl": "32px",
              "icon-2xl": "48px"
            }
          },
          {
            "id": "height",
            "label": "Control Heights",
            "tokens": {
              "height-2xs": "4px",
              "height-xs": "8px",
              "height-sm": "12px",
              "height-md": "16px",
              "height-lg": "24px",
              "height-xl": "32px",
              "height-2xl": "48px",
              "height-3xl": "64px",
              "height-4xl": "96px"
            }
          },
          {
            "id": "control",
            "label": "Form Controls",
            "tokens": {
              "checkbox-size": "20px",
              "radio-size": "20px",
              "switch-width": "35px",
              "switch-height": "22px"
            }
          }
        ]
      },
      {
        "id": "layout",
        "label": "Layout",
        "description": "Breakpoints, containers, columns, and gutters.",
        "groups": [
          {
            "id": "breakpoint",
            "label": "Breakpoints",
            "tokens": {
              "breakpoint-xs": "320px",
              "breakpoint-sm": "576px",
              "breakpoint-md": "768px",
              "breakpoint-lg": "992px",
              "breakpoint-xl": "1200px",
              "breakpoint-2xl": "1400px"
            }
          },
          {
            "id": "container",
            "label": "Containers",
            "tokens": {
              "container-sm": "540px",
              "container-md": "720px",
              "container-lg": "960px",
              "container-xl": "1140px",
              "container-2xl": "1320px"
            }
          },
          {
            "id": "grid",
            "label": "Columns and Gutters",
            "tokens": {
              "columns": "12",
              "gutter-sm": "15px",
              "gutter-default": "30px"
            }
          }
        ]
      },
      {
        "id": "opacity",
        "label": "Opacity",
        "description": "Opacity scale for disabled, hover, and emphasis treatments.",
        "groups": [
          {
            "id": "opacity",
            "label": "All Opacity Tokens",
            "tokens": {
              "opacity-0": "0",
              "opacity-10": "0.1",
              "opacity-25": "0.25",
              "opacity-50": "0.5",
              "opacity-60": "0.6",
              "opacity-75": "0.75",
              "opacity-90": "0.9",
              "opacity-100": "1"
            }
          }
        ]
      },
      {
        "id": "shadows",
        "label": "Shadows",
        "description": "Elevation shadows composed from the drop-shadow part tokens.",
        "groups": [
          {
            "id": "composed",
            "label": "Shadows",
            "tokens": {
              "shadow-sm": "0px 2px 4px 0px rgba(0, 0, 0, 0.075)",
              "shadow-md": "0px 8px 16px 0px rgba(0, 0, 0, 0.15)",
              "shadow-lg": "0px 16px 48px 0px rgba(0, 0, 0, 0.176)"
            }
          },
          {
            "id": "parts",
            "label": "Shadow Parts",
            "tokens": {
              "drop-shadow-sm-offset-x": "0px",
              "drop-shadow-sm-offset-y": "2px",
              "drop-shadow-sm-blur": "4px",
              "drop-shadow-sm-spread": "0px",
              "drop-shadow-sm-color": "rgba(0, 0, 0, 0.075)",
              "drop-shadow-md-offset-x": "0px",
              "drop-shadow-md-offset-y": "8px",
              "drop-shadow-md-blur": "16px",
              "drop-shadow-md-spread": "0px",
              "drop-shadow-md-color": "rgba(0, 0, 0, 0.15)",
              "drop-shadow-lg-offset-x": "0px",
              "drop-shadow-lg-offset-y": "16px",
              "drop-shadow-lg-blur": "48px",
              "drop-shadow-lg-spread": "0px",
              "drop-shadow-lg-color": "rgba(0, 0, 0, 0.176)"
            }
          }
        ]
      },
      {
        "id": "z-index",
        "label": "Z-Index",
        "description": "Layering for dropdowns, sticky UI, modals, popovers, and tooltips.",
        "groups": [
          {
            "id": "z-index",
            "label": "All Z-Index Tokens",
            "tokens": {
              "z-dropdown": "1000",
              "z-sticky": "1020",
              "z-fixed": "1030",
              "z-modal-backdrop": "1040",
              "z-modal": "1050",
              "z-popover": "1060",
              "z-tooltip": "1070"
            }
          }
        ]
      }
    ],
    "portalOverrides": {}
  },
  "guidelines": {
    "sections": [
      {
        "id": "principles",
        "label": "Principles",
        "description": "Qualities a redesign must keep."
      },
      {
        "id": "behaviors",
        "label": "Behaviors",
        "description": "Interaction rules that span components and can be checked."
      },
      {
        "id": "prototype-standards",
        "label": "Prototype standards",
        "description": "Rules about the mockup being reviewable, not about the product."
      },
      {
        "id": "for-agents",
        "label": "For agents",
        "description": "Where the machine-readable version lives and how to point an agent at it."
      }
    ],
    "principles": [
      {
        "id": "two-portals-never-ambiguous",
        "title": "Two portals, related but never ambiguous",
        "body": "Admin and agency screens share one system and are never mistakable for each other. The shell says where you are: admin pages have the Sidebar, agency pages have the top Header.",
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "task-first",
        "title": "Dense, calm, task-first",
        "body": "Admin surfaces are working screens. No marketing layouts, oversized hero text, or decorative panels.",
        "portals": [
          "admin"
        ]
      },
      {
        "id": "admin-leads-with-decisions",
        "title": "Admin billing leads with what needs a decision",
        "body": "Failed and grace-period charges, refund approvals, and pending acceptance come first; transactions and service pricing follow.",
        "portals": [
          "admin"
        ]
      },
      {
        "id": "agency-leads-with-cases-and-money",
        "title": "Agency pages lead with the case and the money",
        "body": "Active cases first, then billing preference, payment methods, invoices, and receipt access.",
        "portals": [
          "agency"
        ]
      },
      {
        "id": "sensitive-details-stay-operational",
        "title": "Sensitive details stay operational",
        "body": "Medical, billing, payment-method, and surrogate details are presented plainly and uncluttered, without decoration or drama.",
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "full-width-work-surfaces",
        "title": "Work surfaces use the full width",
        "body": "Dashboards, billing tables, case lists, and receipts span the working area. No narrow content columns on operational screens.",
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "receipts-print",
        "title": "Receipts and invoices print",
        "body": "Receipt and invoice views are legible on paper and identical in content whether opened from the admin or the agency portal.",
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "brand-roles",
        "title": "Gather blue is the brand; state colors mean money and cases",
        "body": "Medical blue is the only brand color. Success, warning, danger, and info are reserved for billing and case state and never used decoratively.",
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "say-it-once",
        "title": "Say it once",
        "body": "Show a count, amount, or status in one place. Do not repeat it across banners, cards, badges, and helper text.",
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "structure-encodes-meaning",
        "title": "Structure encodes meaning",
        "body": "Dividers, numbering, labels, grouping, and cards exist to clarify a relationship. None of them decorates empty space.",
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "show-dont-explain",
        "title": "Show, don't explain",
        "body": "State, placement, affordance, and concise labels do the explaining. No banners, helper paragraphs, onboarding copy, or callouts unless the consequence is high-risk or the brief requires them. If copy seems necessary, redesign the interaction first.",
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "plain-verbs",
        "title": "Plain verbs, consistent names",
        "body": "Actions are written from the user's side of the screen with plain verbs, and the same action carries the same name everywhere.",
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "build-from-catalog",
        "title": "Build from the catalog",
        "body": "Use a project component when one exists; extend or compose before creating a local variant. Never hardcode a value when a token or component prop exists.",
        "portals": [
          "admin",
          "agency"
        ]
      }
    ],
    "behaviors": [
      {
        "id": "billing-state-and-owner",
        "title": "Money always shows its state and its owner",
        "body": "Every failed charge, refund, invoice, receipt, grace period, and billing hold shows its current state, who owns the next step, and the next action right next to it.",
        "components": [
          "table",
          "card",
          "badge",
          "alert",
          "button"
        ],
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "agency-mobile-essentials",
        "title": "Agency mobile keeps the essentials",
        "body": "At 390px an agency flow still shows status, amount, due date, and the action for every case or charge, without horizontal scroll.",
        "components": [
          "table",
          "card",
          "badge",
          "button"
        ],
        "portals": [
          "agency"
        ]
      },
      {
        "id": "overlay-trigger-context",
        "title": "Overlays keep their trigger in view",
        "body": "While a modal is open, the row, card, or item that opened it is marked active. When it closes, that item stays highlighted until the user moves on, and keyboard focus returns to it. The user always knows what they were looking at.",
        "components": [
          "modal",
          "table",
          "card"
        ],
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "trigger-surfaces",
        "title": "Anything that opens something is a control",
        "body": "A row, card, cell, or text region that opens a modal or a detail view has hover, focus, and keyboard behavior, and is a semantic interactive element whenever feasible.",
        "components": [
          "table",
          "card"
        ],
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "modal-vs-drawer",
        "title": "Modal for a short form, a page or drawer for the rest",
        "body": "A modal holds a short form with a few inputs. A form with sections, validation context, or supporting details gets its own page or a drawer, never a scrolling modal.",
        "components": [
          "modal"
        ],
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "forms-keep-context",
        "title": "Forms keep context",
        "body": "Labels stay visible, the user's input survives a validation error, and errors appear only after the user has interacted with the field.",
        "components": [
          "input",
          "textarea",
          "select",
          "combobox",
          "autocomplete",
          "multi-select",
          "datepicker",
          "phone-input",
          "file-upload",
          "wysiwyg"
        ],
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "error-scope",
        "title": "Errors land at the narrowest useful scope",
        "body": "Field errors for validation. Row or form errors for a failed action. Page-level errors only for a failed primary load. A toast only for transient, nonblocking feedback; anything persistent or actionable stays visible in context.",
        "components": [
          "input",
          "textarea",
          "select",
          "combobox",
          "autocomplete",
          "multi-select",
          "datepicker",
          "phone-input",
          "file-upload",
          "wysiwyg",
          "alert",
          "toast",
          "table",
          "modal"
        ],
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "failure-copy",
        "title": "Failures say what, so what, and what next",
        "body": "A failure states what failed, the consequence, and the next useful action in plain language, with a retry, correction, or return path. Raw provider or status-code messages never appear as interface copy.",
        "components": [
          "alert",
          "toast",
          "modal",
          "empty-state"
        ],
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "action-sequence",
        "title": "Actions show their whole sequence",
        "body": "A consequential action moves through ready, pending, failure, recovery or retry, and success. Input is preserved throughout, and it is always clear whether the action took effect.",
        "components": [
          "button",
          "icon-button",
          "button-group",
          "dropdown-button",
          "alert",
          "toast"
        ],
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "destructive-scope",
        "title": "Consequential actions restate their scope",
        "body": "Before a destructive or consequential action runs, such as a refund, a retry, or removing a payment method, the confirmation names exactly what it will affect: which records, how many, what amount, and what cannot be undone.",
        "components": [
          "modal",
          "button",
          "dropdown-button"
        ],
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "selection-scope",
        "title": "Selection scope is explicit",
        "body": "The header control selects the visible rows first; selecting every matching result is a separate, named action. Hidden rows are never selected silently, and a selection is never discarded silently.",
        "components": [
          "table",
          "checkbox",
          "pagination"
        ],
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "selection-context",
        "title": "Selections survive their context, and say so",
        "body": "The selected count and its scope stay visible next to the bulk actions. Pagination, search, filter, sort, refresh, deletion, and partial failure each have a defined effect on the selection.",
        "components": [
          "table",
          "pagination"
        ],
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "motion-explains",
        "title": "Motion explains, never decorates",
        "body": "Inserting or removing content animates the element and the resulting reflow as one move. Overlays animate in and out without shifting what is behind them. Motion is brief and nonblocking, the change reads without it, and reduced-motion gets an instant alternative.",
        "components": [
          "modal",
          "toast",
          "alert",
          "table",
          "card",
          "dropdown-button",
          "tooltip",
          "user-dropdown"
        ],
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "keyboard-focus",
        "title": "Every control works from the keyboard",
        "body": "Every interactive element is reachable by keyboard, in a sensible order, and shows a visible focus state.",
        "components": [
          "button",
          "icon-button",
          "button-group",
          "dropdown-button",
          "input",
          "textarea",
          "select",
          "combobox",
          "autocomplete",
          "multi-select",
          "datepicker",
          "phone-input",
          "file-upload",
          "wysiwyg",
          "checkbox",
          "radio",
          "switch",
          "tabs",
          "pagination",
          "modal",
          "table",
          "breadcrumbs",
          "tooltip",
          "user-dropdown",
          "sidebar",
          "header"
        ],
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "not-color-alone",
        "title": "State never relies on color alone",
        "body": "Status and errors carry text or an icon alongside color, so they read in grayscale and to color-blind users.",
        "components": [
          "badge",
          "alert",
          "toast",
          "input",
          "textarea",
          "select",
          "combobox",
          "autocomplete",
          "multi-select",
          "datepicker",
          "phone-input",
          "file-upload",
          "wysiwyg",
          "progress",
          "circular-progress",
          "switch"
        ],
        "portals": [
          "admin",
          "agency"
        ]
      },
      {
        "id": "pagination-decided",
        "title": "Pagination is decided, not defaulted",
        "body": "A full-page table or list expected to exceed 15 rows uses numbered pagination. Load-more, virtualized scrolling, or a capped recent list is a deliberate choice, and the handoff says why.",
        "components": [
          "table",
          "pagination"
        ],
        "portals": [
          "admin",
          "agency"
        ],
        "standard": "prototype"
      },
      {
        "id": "three-pages-of-fixtures",
        "title": "Paginated collections show three pages",
        "body": "Fixture data covers page 1, page 2, and a partial last page; load-more covers the initial batch plus two more with a partial final batch. Sparse and single-page states exist as secondary fixtures, never as the only demonstration.",
        "components": [
          "table",
          "pagination"
        ],
        "portals": [
          "admin",
          "agency"
        ],
        "standard": "prototype"
      },
      {
        "id": "stable-identities",
        "title": "Paging never loses an item",
        "body": "Items keep stable identities. Changing pages or appending results never duplicates, skips, reorders, or miscounts them.",
        "components": [
          "table",
          "pagination"
        ],
        "portals": [
          "admin",
          "agency"
        ],
        "standard": "prototype"
      },
      {
        "id": "reachable-failure",
        "title": "Every consequential action has a reachable failure",
        "body": "At least one representative failure per consequential action, reachable on purpose through a scenario switch, a query parameter, a fixture, or a resettable success-then-failure cycle. Never random, and never production data.",
        "components": [
          "button",
          "icon-button",
          "button-group",
          "dropdown-button",
          "alert",
          "toast",
          "modal"
        ],
        "portals": [
          "admin",
          "agency"
        ],
        "standard": "prototype"
      }
    ]
  }
}
