{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "kinetik-tokens",
  "type": "registry:item",
  "title": "Kinetik Tokens",
  "description": "Colour, spacing, radius, type and shadow tokens with dark and light palettes, plus the optional KinetikProvider.",
  "dependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "src/lib/kinetik/tokens/tokens.ts",
      "type": "registry:file",
      "target": "~/lib/kinetik/tokens/tokens.ts",
      "content": "/**\n * Kinetik design tokens.\n *\n * Every colour, spacing step, radius and shadow used by a Kinetik component\n * comes from this file. Components never hard-code a hex value; they read the\n * active palette through `useKinetikTheme()`.\n *\n * Palette: monochrome with one blue. Black and white grounds, the primary\n * accent (`ember`) is the strongest ink and the secondary accent (`ice`) a mid\n * grey. `azure` is a single blue for the few places that want colour: charts,\n * selection, a highlighted action. Status colours keep their hue because they\n * carry meaning. Brand it by overriding `ember` / `ice` / `azure` on the\n * provider. Dark is the primary theme; light is held to\n * the same bar (contrast is checked in the token tests).\n */\n\nexport type ColorScheme = 'dark' | 'light';\n\nexport type Palette = {\n  /** App ground. */\n  background: string;\n  /** Cards, sheets, grouped rows. */\n  surface: string;\n  /** Elements that sit on top of a surface (thumbs, chips, popovers). */\n  surfaceRaised: string;\n  /** Pressed / sunken state of a surface. */\n  surfaceSunken: string;\n  /** Hairlines and outlines. */\n  border: string;\n  /** A stronger outline for focus and active states. */\n  borderStrong: string;\n  /** Primary text. */\n  text: string;\n  /** Secondary text, labels. */\n  textMuted: string;\n  /** Tertiary text, placeholders, disabled. */\n  textSubtle: string;\n  /** Primary accent. */\n  ember: string;\n  /** Ember used for fills behind content (tinted backgrounds). */\n  emberSoft: string;\n  /** Text and icons placed on an ember fill. */\n  onEmber: string;\n  /** Secondary accent. */\n  ice: string;\n  /** Ice used for fills behind content. */\n  iceSoft: string;\n  /** Text and icons placed on an ice fill. */\n  onIce: string;\n  /** The blue accent: fills, chart series, selection. */\n  azure: string;\n  /** Azure used for fills behind content. */\n  azureSoft: string;\n  /** Text and icons placed on an azure fill. */\n  onAzure: string;\n  /** A lighter blue for lines, glows and the far end of azure gradients. */\n  sky: string;\n  success: string;\n  warning: string;\n  danger: string;\n  /** Unfilled part of tracks (sliders, switches). Translucent, so it reads on any surface. */\n  track: string;\n  /** Skeleton base and shimmer colours. */\n  skeleton: string;\n  skeletonHighlight: string;\n  /** Specular highlight colour for glints and sheens. */\n  highlight: string;\n  /** Scrim placed behind sheets and dialogs. */\n  scrim: string;\n};\n\nconst grey = {\n  1000: '#000000',\n  950: '#050505',\n  900: '#0A0A0A',\n  850: '#141414',\n  800: '#1C1C1C',\n  400: '#707070',\n  300: '#A1A1A1',\n  100: '#EDEDED',\n  50: '#FAFAFA',\n} as const;\n\nexport const palettes: Record<ColorScheme, Palette> = {\n  dark: {\n    background: grey[1000],\n    surface: grey[900],\n    surfaceRaised: grey[800],\n    surfaceSunken: grey[950],\n    border: 'rgba(255, 255, 255, 0.08)',\n    borderStrong: 'rgba(255, 255, 255, 0.16)',\n    text: grey[100],\n    textMuted: grey[300],\n    textSubtle: grey[400],\n    ember: '#FFFFFF',\n    emberSoft: 'rgba(255, 255, 255, 0.10)',\n    onEmber: '#000000',\n    ice: '#A3A3A3',\n    iceSoft: 'rgba(255, 255, 255, 0.06)',\n    onIce: '#000000',\n    azure: '#2B6BEF',\n    azureSoft: 'rgba(59, 130, 246, 0.16)',\n    onAzure: '#FFFFFF',\n    sky: '#7AB2FF',\n    success: '#5BE49B',\n    warning: '#FFC857',\n    danger: '#FF6B7A',\n    track: 'rgba(255, 255, 255, 0.12)',\n    skeleton: grey[850],\n    skeletonHighlight: grey[800],\n    highlight: '#FFFFFF',\n    scrim: 'rgba(0, 0, 0, 0.62)',\n  },\n  light: {\n    background: '#FFFFFF',\n    surface: grey[50],\n    surfaceRaised: '#FFFFFF',\n    surfaceSunken: '#F0F0F0',\n    border: 'rgba(0, 0, 0, 0.08)',\n    borderStrong: 'rgba(0, 0, 0, 0.16)',\n    text: grey[900],\n    textMuted: '#555555',\n    textSubtle: '#8A8A8A',\n    ember: '#000000',\n    emberSoft: 'rgba(0, 0, 0, 0.06)',\n    onEmber: '#FFFFFF',\n    ice: '#6B6B6B',\n    iceSoft: 'rgba(0, 0, 0, 0.05)',\n    onIce: '#FFFFFF',\n    azure: '#1F5FE0',\n    azureSoft: 'rgba(31, 95, 224, 0.10)',\n    onAzure: '#FFFFFF',\n    sky: '#3B82F6',\n    success: '#13965A',\n    warning: '#B97A00',\n    danger: '#D63649',\n    track: 'rgba(0, 0, 0, 0.10)',\n    skeleton: '#EDEDED',\n    skeletonHighlight: '#F7F7F7',\n    highlight: '#FFFFFF',\n    scrim: 'rgba(0, 0, 0, 0.36)',\n  },\n};\n\n/** 4 pt spacing scale. */\nexport const space = {\n  0: 0,\n  0.5: 2,\n  1: 4,\n  1.5: 6,\n  2: 8,\n  3: 12,\n  4: 16,\n  5: 20,\n  6: 24,\n  8: 32,\n  10: 40,\n  12: 48,\n  16: 64,\n} as const;\n\nexport const radius = {\n  xs: 6,\n  sm: 10,\n  md: 14,\n  lg: 20,\n  xl: 28,\n  pill: 999,\n} as const;\n\n/** Minimum hit target in points (WCAG 2.5.8 / Apple HIG). */\nexport const minTouchTarget = 44;\n\nexport const font = {\n  size: {\n    xs: 12,\n    sm: 14,\n    md: 16,\n    lg: 18,\n    xl: 22,\n    '2xl': 28,\n    '3xl': 36,\n    '4xl': 48,\n  },\n  weight: {\n    regular: '400',\n    medium: '500',\n    semibold: '600',\n    bold: '700',\n    heavy: '800',\n  },\n  lineHeight: {\n    tight: 1.15,\n    normal: 1.4,\n    relaxed: 1.6,\n  },\n  tracking: {\n    tight: -0.4,\n    normal: 0,\n    wide: 0.6,\n  },\n} as const;\n\n/**\n * Shadows use the cross-platform `boxShadow` style (New Architecture), so the\n * same token renders on iOS, Android and web.\n */\nexport const shadows: Record<ColorScheme, Record<'sm' | 'md' | 'lg', string>> = {\n  dark: {\n    sm: '0px 1px 2px rgba(0, 0, 0, 0.40)',\n    md: '0px 8px 24px rgba(0, 0, 0, 0.45)',\n    lg: '0px 24px 48px rgba(0, 0, 0, 0.55)',\n  },\n  light: {\n    sm: '0px 1px 2px rgba(11, 13, 18, 0.06)',\n    md: '0px 8px 24px rgba(11, 13, 18, 0.08)',\n    lg: '0px 24px 48px rgba(11, 13, 18, 0.12)',\n  },\n};\n\n/** Coloured glow for accent elements. */\nexport function glow(color: string, strength: 'soft' | 'strong' = 'soft'): string {\n  return strength === 'soft'\n    ? `0px 6px 20px ${withAlpha(color, 0.35)}`\n    : `0px 10px 32px ${withAlpha(color, 0.55)}`;\n}\n\n/**\n * Applies an alpha channel to a `#RRGGBB` colour. Other formats are returned\n * unchanged, so callers can pass any token safely. Safe to call from worklets.\n */\nexport function withAlpha(color: string, alpha: number): string {\n  'worklet';\n  const match = /^#([0-9a-f]{6})$/i.exec(color);\n  if (!match?.[1]) return color;\n  const n = parseInt(match[1], 16);\n  const a = Math.min(1, Math.max(0, alpha));\n  return `rgba(${(n >> 16) & 255}, ${(n >> 8) & 255}, ${n & 255}, ${a})`;\n}\n\nexport type Theme = {\n  scheme: ColorScheme;\n  colors: Palette;\n  space: typeof space;\n  radius: typeof radius;\n  font: typeof font;\n  shadow: (typeof shadows)[ColorScheme];\n};\n\nexport function createTheme(scheme: ColorScheme, overrides?: Partial<Palette>): Theme {\n  return {\n    scheme,\n    colors: { ...palettes[scheme], ...overrides },\n    space,\n    radius,\n    font,\n    shadow: shadows[scheme],\n  };\n}\n"
    },
    {
      "path": "src/lib/kinetik/tokens/theme.tsx",
      "type": "registry:file",
      "target": "~/lib/kinetik/tokens/theme.tsx",
      "content": "import { createContext, useContext, useMemo, type ReactNode } from 'react';\nimport { useColorScheme } from 'react-native';\n\nimport { createTheme, type ColorScheme, type Palette, type Theme } from './tokens';\n\nexport type ReduceMotionPreference = 'system' | 'always' | 'never';\n\nexport type KinetikConfig = {\n  theme: Theme;\n  /** Overrides the system reduce-motion setting. */\n  reduceMotion: ReduceMotionPreference;\n  /** Global haptics switch. Individual components can still opt out. */\n  haptics: boolean;\n};\n\nconst KinetikContext = createContext<KinetikConfig | null>(null);\n\nexport type KinetikProviderProps = {\n  children: ReactNode;\n  /** `system` follows the OS appearance. Defaults to `system`. */\n  scheme?: ColorScheme | 'system';\n  /** Partial palette overrides, applied on top of the active scheme. */\n  colors?: Partial<Palette>;\n  /** Defaults to `system`. Use `always` to preview reduced-motion fallbacks. */\n  reduceMotion?: ReduceMotionPreference;\n  /** Defaults to `true`. */\n  haptics?: boolean;\n};\n\n/**\n * Optional root provider. Kinetik components work without it (they follow the\n * system appearance with default tokens); add it to force a scheme, brand the\n * palette, or control motion and haptics app-wide.\n */\nexport function KinetikProvider({\n  children,\n  scheme = 'system',\n  colors,\n  reduceMotion = 'system',\n  haptics = true,\n}: KinetikProviderProps) {\n  const system = useColorScheme();\n  const resolved: ColorScheme =\n    scheme === 'system' ? (system === 'light' ? 'light' : 'dark') : scheme;\n\n  const value = useMemo<KinetikConfig>(\n    () => ({ theme: createTheme(resolved, colors), reduceMotion, haptics }),\n    [resolved, colors, reduceMotion, haptics],\n  );\n\n  return <KinetikContext.Provider value={value}>{children}</KinetikContext.Provider>;\n}\n\nconst fallbackThemes: Record<ColorScheme, Theme> = {\n  dark: createTheme('dark'),\n  light: createTheme('light'),\n};\n\n/** Full Kinetik configuration: theme plus motion and haptics preferences. */\nexport function useKinetikConfig(): KinetikConfig {\n  const config = useContext(KinetikContext);\n  const system = useColorScheme();\n  if (config) return config;\n  return {\n    theme: fallbackThemes[system === 'light' ? 'light' : 'dark'],\n    reduceMotion: 'system',\n    haptics: true,\n  };\n}\n\n/** The active theme (colours, spacing, radius, type, shadows). */\nexport function useKinetikTheme(): Theme {\n  return useKinetikConfig().theme;\n}\n"
    },
    {
      "path": "src/lib/kinetik/tokens/gradient.ts",
      "type": "registry:file",
      "target": "~/lib/kinetik/tokens/gradient.ts",
      "content": "import { Platform, type ViewStyle } from 'react-native';\n\n/**\n * A CSS `linear-gradient(...)` background that works on native (New\n * Architecture `experimental_backgroundImage`) and on the web\n * (`backgroundImage`, passed through by react-native-web).\n *\n * Kept out of tokens.ts so the tokens stay plain data that Node tooling can read.\n */\nexport function gradient(css: string): ViewStyle {\n  return (\n    Platform.OS === 'web' ? { backgroundImage: css } : { experimental_backgroundImage: css }\n  ) as ViewStyle;\n}\n"
    }
  ],
  "meta": {
    "version": "1.0.0",
    "kind": "shared",
    "platforms": [
      "ios",
      "android"
    ],
    "requires": "React Native New Architecture (Reanimated 4)"
  }
}
