{
  "name": "shadwire",
  "version": "0.2.0",
  "license": "MIT",
  "licenseUrl": "https://github.com/edumoraes/shadwire/blob/main/LICENSE",
  "attribution": {
    "derivedFrom": "shadcn/ui",
    "url": "https://ui.shadcn.com",
    "license": "MIT",
    "notice": "Component anatomy, variant class strings and the default theme tokens derive from shadcn/ui. Files installed into an application carry no attribution requirement of their own; see https://github.com/edumoraes/shadwire/blob/main/NOTICE."
  },
  "items": [
    {
      "name": "button",
      "type": "component",
      "title": "Button",
      "description": "Displays a button or a link styled as a button.",
      "whenToUse": "Any clickable action. Use tag: :a for a link that looks like a button, size: :icon for icon-only. For a set of related actions use button-group; for a menu of actions use dropdown-menu."
    },
    {
      "name": "badge",
      "type": "component",
      "title": "Badge",
      "description": "A small inline label for status, counts, or categories.",
      "whenToUse": "Non-interactive status or metadata next to content. For a clickable pill use button with size: :sm; for a keyboard key use kbd."
    },
    {
      "name": "card",
      "type": "component",
      "title": "Card",
      "description": "A container for grouping related content with header, body, and footer slots.",
      "whenToUse": "Grouping related content into a bordered surface. For a compact list row use item; for a placeholder state use empty."
    },
    {
      "name": "alert",
      "type": "component",
      "title": "Alert",
      "description": "A callout for important inline messages.",
      "whenToUse": "Persistent inline messages inside the page. Compose ui_alert_title and ui_alert_description inside it; a ui_icon placed first gets its own column and the text lines up beside it. For a message that interrupts the user use alert-dialog; for transient feedback use sonner."
    },
    {
      "name": "separator",
      "type": "component",
      "title": "Separator",
      "description": "A thin rule that visually divides content.",
      "whenToUse": "Dividing sections or menu groups. Inside a menu prefer that menu's own separator (ui_dropdown_menu_separator, ui_context_menu_separator)."
    },
    {
      "name": "avatar",
      "type": "component",
      "title": "Avatar",
      "description": "A user or entity image with a text fallback.",
      "whenToUse": "Representing a person or account. Always supply fallback for when the image fails to load."
    },
    {
      "name": "accordion",
      "type": "component",
      "title": "Accordion",
      "description": "Vertically stacked sections that expand and collapse.",
      "whenToUse": "Several collapsible sections, typically FAQs. For a single collapsible region use collapsible; for switching between peer views use tabs."
    },
    {
      "name": "scroll-area",
      "type": "component",
      "title": "Scroll Area",
      "description": "A scrollable region with styled scrollbars.",
      "whenToUse": "Constraining a long list or panel to a fixed height with consistent scrollbars across browsers."
    },
    {
      "name": "icon",
      "type": "component",
      "title": "Icon",
      "description": "A Lucide icon with shadcn-style size variants.",
      "whenToUse": "Any icon. Names are Lucide kebab-case. Decorative by default (aria-hidden); pass label: when the icon carries meaning on its own."
    },
    {
      "name": "input",
      "type": "component",
      "title": "Input",
      "description": "A single-line text field.",
      "whenToUse": "Free-text entry. For multi-line use textarea; with an addon or button attached use input-group; wrap in field for a label and error."
    },
    {
      "name": "label",
      "type": "component",
      "title": "Label",
      "description": "An accessible caption bound to a form control.",
      "whenToUse": "Labelling a standalone control. Inside a field block prefer ui_field_label, which wires the description and error for you."
    },
    {
      "name": "textarea",
      "type": "component",
      "title": "Textarea",
      "description": "A multi-line text field.",
      "whenToUse": "Free-text entry spanning several lines. For one line use input."
    },
    {
      "name": "checkbox",
      "type": "component",
      "title": "Checkbox",
      "description": "A binary control for opting in or selecting many items.",
      "whenToUse": "Independent on/off choices, or multi-select in a list. For a single setting that applies immediately use switch; for one-of-many use radio-group."
    },
    {
      "name": "radio-group",
      "type": "component",
      "title": "Radio Group",
      "description": "A set of mutually exclusive options.",
      "whenToUse": "Picking exactly one of a few visible options. For many options use select; for a compact toolbar-style choice use toggle-group."
    },
    {
      "name": "switch",
      "type": "component",
      "title": "Switch",
      "description": "A toggle for a setting that takes effect immediately.",
      "whenToUse": "On/off settings, especially ones that apply instantly. For a value submitted with a form use checkbox."
    },
    {
      "name": "skeleton",
      "type": "component",
      "title": "Skeleton",
      "description": "A placeholder block shown while content loads.",
      "whenToUse": "Preserving layout during loading. For an indeterminate inline busy indicator use spinner; for measurable progress use progress."
    },
    {
      "name": "progress",
      "type": "component",
      "title": "Progress",
      "description": "A bar showing completion toward a known total.",
      "whenToUse": "Progress you can measure. When the duration is unknown use spinner; when you are waiting on content use skeleton."
    },
    {
      "name": "table",
      "type": "component",
      "title": "Table",
      "description": "A styled HTML table with header, body, and footer sections.",
      "whenToUse": "Presenting rows of data you render yourself. For built-in sorting, filtering, pagination and row selection use data-table."
    },
    {
      "name": "breadcrumb",
      "type": "component",
      "title": "Breadcrumb",
      "description": "A trail showing the current page's position in the hierarchy.",
      "whenToUse": "Showing where the user is in a nested structure. For moving between top-level sections use navigation-menu."
    },
    {
      "name": "pagination",
      "type": "component",
      "title": "Pagination",
      "description": "Navigation controls for moving between pages of results.",
      "whenToUse": "Paging through server-rendered result sets. The data-table component brings its own pagination."
    },
    {
      "name": "tabs",
      "type": "component",
      "title": "Tabs",
      "description": "Switches between peer views in the same space.",
      "whenToUse": "Alternate views of comparable content. Triggers must live inside ui_tabs_list. For expanding sections that can be open at once use accordion."
    },
    {
      "name": "dialog",
      "type": "component",
      "title": "Dialog",
      "description": "A modal window overlaying the page.",
      "whenToUse": "Focused tasks that interrupt the current flow. For a destructive confirmation use alert-dialog; for a side panel use sheet; for a bottom sheet use drawer. Always include ui_dialog_title, visually hidden if needed."
    },
    {
      "name": "alert-dialog",
      "type": "component",
      "title": "Alert Dialog",
      "description": "A modal that interrupts the user to confirm a consequential action.",
      "whenToUse": "Confirming destructive or irreversible actions — it cannot be dismissed by clicking outside. For ordinary modal content use dialog."
    },
    {
      "name": "sheet",
      "type": "component",
      "title": "Sheet",
      "description": "A panel that slides in from an edge of the screen.",
      "whenToUse": "Secondary content or forms alongside the page, anchored to an edge. For a centred modal use dialog; for app navigation use sidebar."
    },
    {
      "name": "tooltip",
      "type": "component",
      "title": "Tooltip",
      "description": "A short hint shown on hover or focus.",
      "whenToUse": "Naming an icon-only control or adding a brief hint. Never put interactive content inside — use popover or hover-card for that."
    },
    {
      "name": "popover",
      "type": "component",
      "title": "Popover",
      "description": "A floating panel anchored to a trigger.",
      "whenToUse": "Rich or interactive content anchored to a control, opened by click. For a plain hint use tooltip; for a list of actions use dropdown-menu."
    },
    {
      "name": "dropdown-menu",
      "type": "component",
      "title": "Dropdown Menu",
      "description": "A menu of actions or options triggered by a button.",
      "whenToUse": "Row actions, overflow menus, and account menus. For right-click use context-menu; for an application menu bar use menubar; for choosing a form value use select."
    },
    {
      "name": "select",
      "type": "component",
      "title": "Select",
      "description": "A styled control for choosing one option from a list.",
      "whenToUse": "Choosing a single form value from many options. For a searchable list use combobox; for the plain browser control use native-select; for a few visible options use radio-group."
    },
    {
      "name": "sidebar",
      "type": "component",
      "title": "Sidebar",
      "description": "A composable, collapsible application sidebar.",
      "whenToUse": "Primary application navigation. Wrap the app in ui_sidebar_provider and put page content in ui_sidebar_inset. For a temporary edge panel use sheet."
    },
    {
      "name": "sidebar-01",
      "type": "block",
      "title": "Sidebar 01",
      "description": "A documentation-style dashboard layout with a collapsible sidebar, version switcher, and search.",
      "whenToUse": "Scaffolding a full dashboard page rather than assembling the sidebar yourself. Install the sidebar component instead when you want to compose your own layout."
    },
    {
      "name": "aspect-ratio",
      "type": "component",
      "title": "Aspect Ratio",
      "description": "Constrains its content to a fixed width-to-height ratio.",
      "whenToUse": "Keeping images, video, or embeds at a consistent shape while they scale."
    },
    {
      "name": "spinner",
      "type": "component",
      "title": "Spinner",
      "description": "An indeterminate loading indicator.",
      "whenToUse": "Waits of unknown length, including inside a button. For measurable progress use progress; for content placeholders use skeleton."
    },
    {
      "name": "kbd",
      "type": "component",
      "title": "Kbd",
      "description": "Displays a keyboard key or shortcut.",
      "whenToUse": "Documenting keyboard shortcuts. Inside a menu row prefer that menu's shortcut helper, such as ui_dropdown_menu_shortcut."
    },
    {
      "name": "empty",
      "type": "component",
      "title": "Empty",
      "description": "A placeholder for when there is nothing to show.",
      "whenToUse": "Empty lists, no search results, or first-run states. For loading use skeleton."
    },
    {
      "name": "item",
      "type": "component",
      "title": "Item",
      "description": "A compact row with media, text, and trailing actions.",
      "whenToUse": "List rows such as settings, files, or people. For a larger bordered surface use card."
    },
    {
      "name": "input-group",
      "type": "component",
      "title": "Input Group",
      "description": "An input with attached addons, text, or buttons.",
      "whenToUse": "Prefixes, suffixes, or buttons attached to a field. Use ui_input_group_input or ui_input_group_textarea inside, never a bare input."
    },
    {
      "name": "button-group",
      "type": "component",
      "title": "Button Group",
      "description": "Related buttons joined into a single control.",
      "whenToUse": "Segmenting related actions such as previous/next. For selecting among options use toggle-group."
    },
    {
      "name": "field",
      "type": "component",
      "title": "Field",
      "description": "Form field layout with label, description, and error message.",
      "whenToUse": "The standard wrapper for every form control — never lay out form rows with bare divs. Group related fields with ui_field_group, and related checkboxes or radios with ui_field_set plus ui_field_legend."
    },
    {
      "name": "native-select",
      "type": "component",
      "title": "Native Select",
      "description": "The browser's native select element, styled to match.",
      "whenToUse": "When you want native mobile pickers and no JavaScript. For a styled listbox use select; for search use combobox."
    },
    {
      "name": "collapsible",
      "type": "component",
      "title": "Collapsible",
      "description": "A single region that expands and collapses.",
      "whenToUse": "One show/hide region. For several coordinated sections use accordion."
    },
    {
      "name": "toggle",
      "type": "component",
      "title": "Toggle",
      "description": "A two-state button that stays pressed.",
      "whenToUse": "A single on/off control in a toolbar, such as bold. For several related toggles use toggle-group; for a settings switch use switch."
    },
    {
      "name": "toggle-group",
      "type": "component",
      "title": "Toggle Group",
      "description": "A set of toggle buttons acting as one control.",
      "whenToUse": "Choosing between two to seven options in a compact toolbar. For form semantics use radio-group; for actions use button-group."
    },
    {
      "name": "slider",
      "type": "component",
      "title": "Slider",
      "description": "Selects a numeric value from a range by dragging.",
      "whenToUse": "Imprecise numeric input such as volume or price. For an exact number use input with type: :number."
    },
    {
      "name": "hover-card",
      "type": "component",
      "title": "Hover Card",
      "description": "A rich preview card shown on hover.",
      "whenToUse": "Previewing linked content, such as a user profile. For a short hint use tooltip; for click-triggered content use popover."
    },
    {
      "name": "input-otp",
      "type": "component",
      "title": "Input OTP",
      "description": "A segmented field for one-time passcodes.",
      "whenToUse": "Verification codes split into boxes. For ordinary text use input."
    },
    {
      "name": "drawer",
      "type": "component",
      "title": "Drawer",
      "description": "A panel that slides up from the bottom of the screen.",
      "whenToUse": "Mobile-friendly overlays anchored to the bottom edge. For a side panel use sheet; for a centred modal use dialog."
    },
    {
      "name": "context-menu",
      "type": "component",
      "title": "Context Menu",
      "description": "A menu opened by right-clicking a region.",
      "whenToUse": "Right-click actions on an element. For a button-triggered menu use dropdown-menu."
    },
    {
      "name": "menubar",
      "type": "component",
      "title": "Menubar",
      "description": "A horizontal application menu bar.",
      "whenToUse": "Desktop-style application menus such as File and Edit. For a single button menu use dropdown-menu; for site navigation use navigation-menu."
    },
    {
      "name": "navigation-menu",
      "type": "component",
      "title": "Navigation Menu",
      "description": "Site navigation with optional rich dropdown panels.",
      "whenToUse": "Primary site navigation in a header. For application menus use menubar; for showing location use breadcrumb."
    },
    {
      "name": "command",
      "type": "component",
      "title": "Command",
      "description": "A searchable, keyboard-driven list of commands.",
      "whenToUse": "Command palettes and searchable pickers. Put it inside dialog for a ⌘K palette; combine with popover for a combobox."
    },
    {
      "name": "calendar",
      "type": "component",
      "title": "Calendar",
      "description": "A month grid for selecting a date or a date range.",
      "whenToUse": "Showing an inline month view, for a single date or a range. For a date field that opens the grid in a popover use date-picker."
    },
    {
      "name": "resizable",
      "type": "component",
      "title": "Resizable",
      "description": "Panels the user can resize by dragging a handle.",
      "whenToUse": "Split layouts with user-adjustable panes, such as a list and detail view."
    },
    {
      "name": "carousel",
      "type": "component",
      "title": "Carousel",
      "description": "A horizontally or vertically swipeable set of slides.",
      "whenToUse": "Browsing images or cards one at a time. For a scrollable region without slide semantics use scroll-area."
    },
    {
      "name": "combobox",
      "type": "component",
      "title": "Combobox",
      "description": "A searchable single-select built from popover, command, and button.",
      "whenToUse": "Choosing one option from a long list where typing to filter matters. For short lists use select; for the native control use native-select. This item installs its parts rather than a Ui::ComboboxComponent — compose them yourself."
    },
    {
      "name": "date-picker",
      "type": "component",
      "title": "Date Picker",
      "description": "A date field that opens a calendar in a popover.",
      "whenToUse": "Picking a date in a form: as a button, as a typed text field, as a range, or as a date of birth. For an always-visible month grid use calendar. There is no Ui::DatePickerComponent — this item installs the parts plus the ui-date-picker controller that keeps the field and the calendar in step, and you compose them."
    },
    {
      "name": "sonner",
      "type": "component",
      "title": "Sonner",
      "description": "Transient toast notifications.",
      "whenToUse": "Brief confirmations that do not need acknowledgement. For messages that stay on the page use alert; for ones requiring a decision use alert-dialog."
    },
    {
      "name": "chart",
      "type": "component",
      "title": "Chart",
      "description": "Composable charts drawn with D3: bars, lines, areas, pies, radars and radial bars, with a tooltip and a legend, in the Shadwire theme tokens.",
      "whenToUse": "Visualising series data. Compose ui_chart from the parts you need — grid, axes, series, label lists, tooltip, legend — or draw your own D3 layer with ui_chart_layer. Pins d3 via importmap and needs Stimulus. For plain tabular numbers use table."
    },
    {
      "name": "data-table",
      "type": "component",
      "title": "Data Table",
      "description": "A table with sorting, filtering, pagination, and row selection.",
      "whenToUse": "Tabular data that needs interaction out of the box. When you only need markup and styling use table."
    }
  ],
  "base": {
    "files": [
      {
        "target": "app/components/ui_component.rb",
        "type": "component",
        "content": "# frozen_string_literal: true\n\nclass UiComponent < ViewComponent::Base\n  # What a Tailwind utility sets, for #class_names. Each pattern's first capture\n  # names the property when one pattern covers several (`px` and `py` are both\n  # spacing, and do not conflict).\n  TAILWIND_COLOURS = %w[\n    primary secondary destructive muted accent background foreground card popover input ring border\n    transparent current white black inherit chart-1 chart-2 chart-3 chart-4 chart-5\n    sidebar sidebar-primary sidebar-accent sidebar-border sidebar-ring\n  ].join(\"|\")\n  TAILWIND_LENGTH = '(?:\\d+(?:\\.\\d+)?(?:/\\d+)?|px|auto|full|fit|max|min|screen|none|[sdl]vh|[2-7]?xs|sm|md|lg|[2-7]?xl|prose|\\[.+\\]|\\(.+\\))'\n  TAILWIND_PROPERTIES = {\n    \"colour\" => /\\A(bg|text|border|ring|outline|fill|stroke)-(?:#{TAILWIND_COLOURS})(?:-foreground)?(?:\\/\\d+)?\\z/,\n    \"font-size\" => /\\A(text)-(?:xs|sm|base|lg|xl|\\dxl)\\z/,\n    \"text-align\" => /\\A()text-(?:left|center|right|justify|start|end)\\z/,\n    \"font-weight\" => /\\A(font)-(?:thin|light|normal|medium|semibold|bold|extrabold|black)\\z/,\n    \"dimension\" => /\\A(h|w|size|min-w|min-h|max-w|max-h)-#{TAILWIND_LENGTH}\\z/,\n    \"aspect-ratio\" => %r{\\A(aspect)-(?:auto|square|video|\\d+/\\d+|\\[.+\\])\\z},\n    \"spacing\" => /\\A(p|px|py|pt|pr|pb|pl|m|mx|my|mt|mr|mb|ml|gap|gap-x|gap-y)-#{TAILWIND_LENGTH}\\z/,\n    \"shadow\" => /\\A(shadow)(?:-(?:none|2xs|xs|sm|md|lg|xl|2xl))?\\z/,\n    \"radius\" => /\\A(rounded(?:-[trbl]|-[tb][lr])?)(?:-(?:none|xs|sm|md|lg|xl|2xl|3xl|full|\\[.+\\]))?\\z/,\n    \"border-width\" => /\\A(border(?:-[trblxy])?)(?:-(?:0|2|4|8))?\\z/,\n    \"display\" => /\\A()(?:block|inline-block|inline|flex|inline-flex|grid|inline-grid|hidden|contents|table)\\z/,\n    \"position\" => /\\A()(?:static|fixed|absolute|relative|sticky)\\z/,\n    \"alignment\" => /\\A(items|justify|self|content)-(?:start|end|center|between|around|evenly|stretch|baseline|auto|normal)\\z/,\n    \"line-height\" => /\\A(leading)-(?:none|tight|snug|normal|relaxed|loose|\\d+)\\z/,\n    \"letter-spacing\" => /\\A(tracking)-(?:tighter|tight|normal|wide|wider|widest)\\z/,\n    \"opacity\" => /\\A(opacity)-\\d+\\z/,\n    \"overflow\" => /\\A(overflow(?:-[xy])?)-(?:auto|hidden|visible|scroll|clip)\\z/,\n    \"whitespace\" => /\\A(whitespace)-(?:normal|nowrap|pre|pre-line|pre-wrap)\\z/,\n    \"cursor\" => /\\A(cursor)-(?:default|pointer|not-allowed|wait|text|move)\\z/\n  }.freeze\n\n  # A shorthand given later also overrides the longhands before it: `p-0`\n  # after `px-4` leaves no horizontal padding.\n  TAILWIND_SHORTHANDS = {\n    \"spacing:p\" => %w[spacing:px spacing:py spacing:pt spacing:pr spacing:pb spacing:pl],\n    \"spacing:px\" => %w[spacing:pr spacing:pl],\n    \"spacing:py\" => %w[spacing:pt spacing:pb],\n    \"spacing:m\" => %w[spacing:mx spacing:my spacing:mt spacing:mr spacing:mb spacing:ml],\n    \"spacing:mx\" => %w[spacing:mr spacing:ml],\n    \"spacing:my\" => %w[spacing:mt spacing:mb],\n    \"spacing:gap\" => %w[spacing:gap-x spacing:gap-y],\n    \"dimension:size\" => %w[dimension:w dimension:h],\n    \"radius:rounded\" => %w[radius:rounded-t radius:rounded-r radius:rounded-b radius:rounded-l\n                           radius:rounded-tl radius:rounded-tr radius:rounded-bl radius:rounded-br],\n    \"border-width:border\" => %w[border-width:border-x border-width:border-y border-width:border-t\n                                border-width:border-r border-width:border-b border-width:border-l]\n  }.freeze\n\n  class << self\n    # The classes in order, less each one a later class overrides. What shadcn's\n    # cn() does with tailwind-merge, for the utilities in TAILWIND_PROPERTIES;\n    # any other class is kept as given.\n    def merge_classes(classes)\n      taken = {}\n\n      classes.to_s.split.reverse.select { |name|\n        keys = tailwind_keys(name)\n        next true unless keys\n        next false if taken.key?(keys.first)\n\n        keys.each { |key| taken[key] = true }\n      }.reverse.join(\" \")\n    end\n\n    # [what the class sets, what else it overrides], each under the class's\n    # variants and importance — `hover:bg-accent` and `bg-primary` set\n    # different things, and so do `h-8!` and `h-9`. Nil for anything that is\n    # not a utility listed above.\n    def tailwind_keys(name)\n      cache = (@tailwind_keys ||= {})\n\n      cache.fetch(name) do\n        cache.clear if cache.size > 10_000\n        cache[name] = compute_tailwind_keys(name)\n      end\n    end\n\n    private\n\n    def compute_tailwind_keys(name)\n      variants, _, utility = name.rpartition(\":\")\n      important = utility.end_with?(\"!\")\n      utility = utility.delete_suffix(\"!\")\n\n      TAILWIND_PROPERTIES.each do |group, pattern|\n        match = pattern.match(utility) or next\n        property = \"#{group}:#{match[1]}\"\n\n        return [ property, *TAILWIND_SHORTHANDS.fetch(property, []) ].map { |key| [ variants, important, key ] }\n      end\n      nil\n    end\n  end\n\n  private\n\n  # Rails' class_names, with Tailwind conflicts settled the way cn() settles\n  # them upstream: of two utilities that set the same thing, the one given\n  # later wins. Without it both reach the page and the stylesheet's order —\n  # not the order given — picks one, so `class: \"w-80\"` lost to a component's\n  # own `w-full`, and the outline Item's border to its base's transparent one.\n  #\n  # Rails escapes each token and marks the result safe; dropping tokens leaves\n  # the rest as escaped, so it stays marked — a plain string would be escaped\n  # twice on its way into the attribute.\n  def class_names(*args)\n    UiComponent.merge_classes(super).html_safe\n  end\n\n  def extract_class_name(attrs, class_name)\n    [ attrs.delete(:class), class_name ].compact_blank.join(\" \")\n  end\n\n  def fetch_variant(mapping, key, fallback:)\n    variant = key.presence&.to_sym || fallback.to_sym\n\n    mapping.fetch(variant) { mapping.fetch(fallback.to_sym) }\n  end\n\n  def html_attrs\n    @attrs\n  end\nend\n"
      },
      {
        "target": "vendor/shadwire/shadwire.css",
        "type": "css",
        "content": "@custom-variant dark (&:is(.dark *));\n\n@theme inline {\n  --color-background: var(--background);\n  --color-foreground: var(--foreground);\n  --color-card: var(--card);\n  --color-card-foreground: var(--card-foreground);\n  --color-popover: var(--popover);\n  --color-popover-foreground: var(--popover-foreground);\n  --color-primary: var(--primary);\n  --color-primary-foreground: var(--primary-foreground);\n  --color-secondary: var(--secondary);\n  --color-secondary-foreground: var(--secondary-foreground);\n  --color-muted: var(--muted);\n  --color-muted-foreground: var(--muted-foreground);\n  --color-accent: var(--accent);\n  --color-accent-foreground: var(--accent-foreground);\n  --color-destructive: var(--destructive);\n  --color-destructive-foreground: var(--destructive-foreground);\n  --color-border: var(--border);\n  --color-input: var(--input);\n  --color-ring: var(--ring);\n  --color-chart-1: var(--chart-1);\n  --color-chart-2: var(--chart-2);\n  --color-chart-3: var(--chart-3);\n  --color-chart-4: var(--chart-4);\n  --color-chart-5: var(--chart-5);\n  --color-sidebar: var(--sidebar);\n  --color-sidebar-foreground: var(--sidebar-foreground);\n  --color-sidebar-primary: var(--sidebar-primary);\n  --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);\n  --color-sidebar-accent: var(--sidebar-accent);\n  --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);\n  --color-sidebar-border: var(--sidebar-border);\n  --color-sidebar-ring: var(--sidebar-ring);\n  --radius-sm: calc(var(--radius) - 4px);\n  --radius-md: calc(var(--radius) - 2px);\n  --radius-lg: var(--radius);\n  --radius-xl: calc(var(--radius) + 4px);\n  --animate-accordion-down: accordion-down 0.2s ease-out;\n  --animate-accordion-up: accordion-up 0.2s ease-out;\n  --animate-dialog-in: dialog-in 0.15s ease-out;\n  --animate-dialog-out: dialog-out 0.15s ease-in;\n  --animate-sheet-in-right: sheet-in-from-right 0.3s ease-out;\n  --animate-sheet-out-right: sheet-out-to-right 0.2s ease-in;\n  --animate-sheet-in-left: sheet-in-from-left 0.3s ease-out;\n  --animate-sheet-out-left: sheet-out-to-left 0.2s ease-in;\n  --animate-sheet-in-top: sheet-in-from-top 0.3s ease-out;\n  --animate-sheet-out-top: sheet-out-to-top 0.2s ease-in;\n  --animate-sheet-in-bottom: sheet-in-from-bottom 0.3s ease-out;\n  --animate-sheet-out-bottom: sheet-out-to-bottom 0.2s ease-in;\n  --animate-tooltip-in: tooltip-in 0.15s ease-out;\n  --animate-popover-in: popover-in 0.15s ease-out;\n  --animate-collapsible-down: collapsible-down 0.2s ease-out;\n  --animate-collapsible-up: collapsible-up 0.2s ease-out;\n}\n\n@keyframes accordion-down {\n  from {\n    height: 0;\n  }\n  to {\n    height: var(--radix-accordion-content-height);\n  }\n}\n\n@keyframes accordion-up {\n  from {\n    height: var(--radix-accordion-content-height);\n  }\n  to {\n    height: 0;\n  }\n}\n\n@keyframes collapsible-down {\n  from {\n    height: 0;\n  }\n  to {\n    height: var(--radix-collapsible-content-height);\n  }\n}\n\n@keyframes collapsible-up {\n  from {\n    height: var(--radix-collapsible-content-height);\n  }\n  to {\n    height: 0;\n  }\n}\n\n@keyframes dialog-in {\n  from {\n    opacity: 0;\n    transform: scale(0.95);\n  }\n  to {\n    opacity: 1;\n    transform: scale(1);\n  }\n}\n\n@keyframes dialog-out {\n  from {\n    opacity: 1;\n    transform: scale(1);\n  }\n  to {\n    opacity: 0;\n    transform: scale(0.95);\n  }\n}\n\n@keyframes overlay-in {\n  from {\n    opacity: 0;\n  }\n  to {\n    opacity: 1;\n  }\n}\n\n@keyframes sheet-in-from-right {\n  from {\n    transform: translateX(100%);\n  }\n  to {\n    transform: translateX(0);\n  }\n}\n\n@keyframes sheet-out-to-right {\n  from {\n    transform: translateX(0);\n  }\n  to {\n    transform: translateX(100%);\n  }\n}\n\n@keyframes sheet-in-from-left {\n  from {\n    transform: translateX(-100%);\n  }\n  to {\n    transform: translateX(0);\n  }\n}\n\n@keyframes sheet-out-to-left {\n  from {\n    transform: translateX(0);\n  }\n  to {\n    transform: translateX(-100%);\n  }\n}\n\n@keyframes sheet-in-from-top {\n  from {\n    transform: translateY(-100%);\n  }\n  to {\n    transform: translateY(0);\n  }\n}\n\n@keyframes sheet-out-to-top {\n  from {\n    transform: translateY(0);\n  }\n  to {\n    transform: translateY(-100%);\n  }\n}\n\n@keyframes sheet-in-from-bottom {\n  from {\n    transform: translateY(100%);\n  }\n  to {\n    transform: translateY(0);\n  }\n}\n\n@keyframes sheet-out-to-bottom {\n  from {\n    transform: translateY(0);\n  }\n  to {\n    transform: translateY(100%);\n  }\n}\n\n/* Opacity-only so the per-side centering transform (-translate-x-1/2, …) is\n   not clobbered by an animated `transform` mid-open. */\n@keyframes tooltip-in {\n  from {\n    opacity: 0;\n  }\n  to {\n    opacity: 1;\n  }\n}\n\n@keyframes popover-in {\n  from {\n    opacity: 0;\n  }\n  to {\n    opacity: 1;\n  }\n}\n\n:root {\n  /* The theme is a class, not a media query, so the browser cannot infer it.\n     Without this, UA-painted chrome — select popups, scrollbars, the date and\n     time input pickers, autofill — stays light while the page goes dark. */\n  color-scheme: light;\n  --radius: 0.5rem;\n  --background: oklch(1 0 0);\n  --foreground: oklch(0.145 0 0);\n  --card: oklch(1 0 0);\n  --card-foreground: oklch(0.145 0 0);\n  --popover: oklch(1 0 0);\n  --popover-foreground: oklch(0.145 0 0);\n  --primary: oklch(0.205 0 0);\n  --primary-foreground: oklch(0.985 0 0);\n  --secondary: oklch(0.97 0 0);\n  --secondary-foreground: oklch(0.205 0 0);\n  --muted: oklch(0.97 0 0);\n  --muted-foreground: oklch(0.556 0 0);\n  --accent: oklch(0.97 0 0);\n  --accent-foreground: oklch(0.205 0 0);\n  --destructive: oklch(0.577 0.245 27.325);\n  --destructive-foreground: oklch(0.985 0 0);\n  --border: oklch(0.922 0 0);\n  --input: oklch(0.922 0 0);\n  --ring: oklch(0.708 0 0);\n  --chart-1: oklch(0.646 0.222 41.116);\n  --chart-2: oklch(0.6 0.118 184.704);\n  --chart-3: oklch(0.398 0.07 227.392);\n  --chart-4: oklch(0.828 0.189 84.429);\n  --chart-5: oklch(0.769 0.188 70.08);\n  --sidebar: oklch(0.985 0 0);\n  --sidebar-foreground: oklch(0.145 0 0);\n  --sidebar-primary: oklch(0.205 0 0);\n  --sidebar-primary-foreground: oklch(0.985 0 0);\n  --sidebar-accent: oklch(0.97 0 0);\n  --sidebar-accent-foreground: oklch(0.205 0 0);\n  --sidebar-border: oklch(0.922 0 0);\n  --sidebar-ring: oklch(0.708 0 0);\n}\n\n.dark {\n  color-scheme: dark;\n  --background: oklch(0.145 0 0);\n  --foreground: oklch(0.985 0 0);\n  --card: oklch(0.205 0 0);\n  --card-foreground: oklch(0.985 0 0);\n  --popover: oklch(0.205 0 0);\n  --popover-foreground: oklch(0.985 0 0);\n  --primary: oklch(0.922 0 0);\n  --primary-foreground: oklch(0.205 0 0);\n  --secondary: oklch(0.269 0 0);\n  --secondary-foreground: oklch(0.985 0 0);\n  --muted: oklch(0.269 0 0);\n  --muted-foreground: oklch(0.708 0 0);\n  --accent: oklch(0.269 0 0);\n  --accent-foreground: oklch(0.985 0 0);\n  --destructive: oklch(0.704 0.191 22.216);\n  --destructive-foreground: oklch(0.985 0 0);\n  --border: oklch(1 0 0 / 10%);\n  --input: oklch(1 0 0 / 15%);\n  --ring: oklch(0.556 0 0);\n  --chart-1: oklch(0.488 0.243 264.376);\n  --chart-2: oklch(0.696 0.17 162.48);\n  --chart-3: oklch(0.769 0.188 70.08);\n  --chart-4: oklch(0.627 0.265 303.9);\n  --chart-5: oklch(0.645 0.246 16.439);\n  --sidebar: oklch(0.205 0 0);\n  --sidebar-foreground: oklch(0.985 0 0);\n  --sidebar-primary: oklch(0.488 0.243 264.376);\n  --sidebar-primary-foreground: oklch(0.985 0 0);\n  --sidebar-accent: oklch(0.269 0 0);\n  --sidebar-accent-foreground: oklch(0.985 0 0);\n  --sidebar-border: oklch(1 0 0 / 10%);\n  --sidebar-ring: oklch(0.556 0 0);\n}\n\n@layer base {\n  * {\n    @apply border-border outline-ring/50;\n  }\n  body {\n    @apply bg-background text-foreground;\n  }\n}\n\n@layer components {\n  .shadwire-scroll-area-viewport {\n    scrollbar-width: none;\n    -ms-overflow-style: none;\n  }\n\n  .shadwire-scroll-area-viewport::-webkit-scrollbar {\n    display: none;\n  }\n\n  /* The select popup is drawn by the browser, but its options inherit `color`\n     from the select — a near-white token in dark mode — while their own\n     background stays transparent, so the UA paints its light surface behind\n     white text. Pinning both to the system pair keeps the popup legible and in\n     step with `color-scheme`. Every select the registry styles needs this. */\n  [data-slot=\"native-select\"] option,\n  [data-slot=\"native-select\"] optgroup,\n  [data-slot=\"calendar-caption-select\"] option {\n    background-color: Canvas;\n    color: CanvasText;\n  }\n\n  /* Native inputs cannot render pseudo-element glyphs in Firefox, so the check\n     ships as a background image. A stroked path has no gradient equivalent and\n     a data URI cannot read a custom property, so this glyph — alone among the\n     control indicators — stays a literal, kept in step with\n     --primary-foreground by hand. Re-theming that token does not reach it;\n     making it follow would mean overlaying a real <svg>, which would break the\n     `peer` relationship the labels rely on. */\n  .shadwire-checkbox:checked {\n    background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fafafa' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E\");\n    background-size: 0.75rem;\n    background-position: center;\n    background-repeat: no-repeat;\n  }\n\n  .dark .shadwire-checkbox:checked {\n    background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23171717' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E\");\n  }\n\n  /* A gradient can read a custom property where a data URI cannot, so the dot\n     is --primary in both modes and needs no .dark twin. The half-pixel ramp is\n     antialiasing, not geometry: the dot is 0.5rem across, as upstream. */\n  .shadwire-radio:checked {\n    background-image: radial-gradient(circle at center, var(--primary) 0 calc(0.25rem - 0.5px), transparent 0.25rem);\n    background-size: 1rem;\n    background-position: center;\n    background-repeat: no-repeat;\n  }\n\n  .shadwire-switch {\n    background-image: radial-gradient(circle at center, var(--background) 0 calc(0.5rem - 0.5px), transparent 0.5rem);\n    background-size: 1rem 1rem;\n    background-position: left 1px center;\n    background-repeat: no-repeat;\n    transition: background-position 150ms ease-in-out, background-color 150ms ease-in-out;\n  }\n\n  .shadwire-switch:checked {\n    background-position: right 1px center;\n  }\n\n  .dark .shadwire-switch {\n    background-image: radial-gradient(circle at center, var(--foreground) 0 calc(0.5rem - 0.5px), transparent 0.5rem);\n  }\n\n  .dark .shadwire-switch:checked {\n    background-image: radial-gradient(circle at center, var(--primary-foreground) 0 calc(0.5rem - 0.5px), transparent 0.5rem);\n  }\n}\n\n[dir=\"rtl\"] [data-slot=\"scroll-area-scrollbar\"][data-orientation=\"vertical\"] {\n  right: auto;\n  left: 0;\n  border-right: 1px solid transparent;\n  border-left: 0;\n}\n\n/* The ::backdrop pseudo-element cannot be styled with Tailwind utilities. */\ndialog[data-slot=\"dialog-content\"]:not([open]),\ndialog[data-slot=\"alert-dialog-content\"]:not([open]),\ndialog[data-slot=\"sheet-content\"]:not([open]),\ndialog[data-slot=\"drawer-content\"]:not([open]) {\n  display: none;\n}\n\ndialog[data-slot=\"dialog-content\"]::backdrop,\ndialog[data-slot=\"alert-dialog-content\"]::backdrop,\ndialog[data-slot=\"sheet-content\"]::backdrop,\ndialog[data-slot=\"drawer-content\"]::backdrop {\n  background-color: oklch(0 0 0 / 0.5);\n}\n\ndialog[data-state=\"open\"]::backdrop {\n  animation: overlay-in 0.15s ease-out;\n}\n\n/* Sidebar menu-button tooltips surface only while the sidebar is collapsed to\n   icons. The ui-tooltip controller still toggles [hidden] on hover/focus, so\n   the gate keeps the content hidden in every other state. */\n[data-slot=\"sidebar-menu-button-tooltip-content\"] {\n  display: none;\n}\n\n[data-collapsible=\"icon\"] [data-slot=\"sidebar-menu-button-tooltip-content\"]:not([hidden]) {\n  display: block;\n}\n\n/* Sonner toasts animate in/out by flipping data-state between the JS append\n   (closed) and the next frame (open), and back to closed on dismiss. */\n[data-slot=\"sonner-toast\"] {\n  transition: transform 0.25s ease, opacity 0.25s ease;\n}\n\n[data-slot=\"sonner-toast\"][data-state=\"closed\"] {\n  opacity: 0;\n  transform: translateY(0.75rem) scale(0.98);\n}\n\n[data-slot=\"sonner-toast\"][data-state=\"open\"] {\n  opacity: 1;\n  transform: translateY(0) scale(1);\n}\n"
      }
    ],
    "gems": [
      "view_component",
      "lucide-rails"
    ],
    "tailwind": {
      "version": "4",
      "css": "shadwire.css"
    }
  }
}
