{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "weather-dashboard-shadcnui",
  "type": "registry:component",
  "title": "Weather Dashboard",
  "description": "Immersive weather dashboard with hourly charting, weekly outlook, and live air-quality alerts",
  "registryDependencies": [
    "button"
  ],
  "dependencies": [
    "framer-motion",
    "react"
  ],
  "files": [
    {
      "path": "@uitripled/react-shadcn/src/components/components/weather/weather-dashboard.tsx",
      "content": "\"use client\";\n\nimport type React from \"react\";\n\nimport { Badge } from \"@/components/ui/badge\";\nimport { Button } from \"@/components/ui/button\";\nimport { motion, type Variants } from \"framer-motion\";\nimport {\n  CalendarDays,\n  Cloud,\n  CloudLightning,\n  CloudRain,\n  Droplets,\n  Gauge,\n  LucideIcon,\n  MapPin,\n  RefreshCcw,\n  Sun,\n  Sunrise,\n  Sunset,\n  Umbrella,\n  Wind,\n} from \"lucide-react\";\nimport { useMemo } from \"react\";\nimport {\n  Area,\n  AreaChart,\n  CartesianGrid,\n  ResponsiveContainer,\n  Tooltip,\n  XAxis,\n} from \"recharts\";\n\ntype WeatherCondition = \"sunny\" | \"rain\" | \"cloudy\" | \"storm\";\n\ntype HourlyForecast = {\n  time: string;\n  temperature: number;\n  feelsLike: number;\n  precipitationChance: number;\n  windSpeed: number;\n  condition: WeatherCondition;\n};\n\ntype WeeklyForecast = {\n  day: string;\n  high: number;\n  low: number;\n  precipitationChance: number;\n  condition: WeatherCondition;\n};\n\ntype WeatherMetric = {\n  label: string;\n  value: string;\n  description: string;\n  icon: LucideIcon;\n};\n\ntype AirQualityMetric = {\n  label: string;\n  value: string;\n  status: string;\n  description: string;\n};\n\ntype AlertSeverity = \"Advisory\" | \"Watch\" | \"Warning\";\n\ntype WeatherAlert = {\n  title: string;\n  description: string;\n  severity: AlertSeverity;\n  icon: LucideIcon;\n};\n\ntype WeatherData = {\n  location: string;\n  updatedAt: string;\n  current: {\n    temperature: number;\n    feelsLike: number;\n    summary: string;\n    condition: WeatherCondition;\n    humidity: number;\n    precipitationChance: number;\n    windSpeed: number;\n    pressure: number;\n    sunrise: string;\n    sunset: string;\n  };\n  hourly: HourlyForecast[];\n  weekly: WeeklyForecast[];\n  airQuality: AirQualityMetric[];\n  alerts: WeatherAlert[];\n};\n\nconst STATIC_WEATHER_DATA: WeatherData = {\n  location: \"San Francisco, CA\",\n  updatedAt: \"2024-07-12T16:00:00.000Z\",\n  current: {\n    temperature: 64,\n    feelsLike: 62,\n    summary: \"Mostly sunny with a coastal breeze\",\n    condition: \"sunny\",\n    humidity: 62,\n    precipitationChance: 15,\n    windSpeed: 12,\n    pressure: 1016,\n    sunrise: \"2024-07-12T13:58:00.000Z\",\n    sunset: \"2024-07-13T03:33:00.000Z\",\n  },\n  hourly: [\n    {\n      time: \"2024-07-12T16:00:00.000Z\",\n      temperature: 60,\n      feelsLike: 59,\n      precipitationChance: 10,\n      windSpeed: 10,\n      condition: \"sunny\",\n    },\n    {\n      time: \"2024-07-12T17:00:00.000Z\",\n      temperature: 61,\n      feelsLike: 60,\n      precipitationChance: 12,\n      windSpeed: 11,\n      condition: \"sunny\",\n    },\n    {\n      time: \"2024-07-12T18:00:00.000Z\",\n      temperature: 62,\n      feelsLike: 61,\n      precipitationChance: 12,\n      windSpeed: 12,\n      condition: \"sunny\",\n    },\n    {\n      time: \"2024-07-12T19:00:00.000Z\",\n      temperature: 63,\n      feelsLike: 62,\n      precipitationChance: 15,\n      windSpeed: 13,\n      condition: \"sunny\",\n    },\n    {\n      time: \"2024-07-12T20:00:00.000Z\",\n      temperature: 64,\n      feelsLike: 63,\n      precipitationChance: 18,\n      windSpeed: 14,\n      condition: \"sunny\",\n    },\n    {\n      time: \"2024-07-12T21:00:00.000Z\",\n      temperature: 65,\n      feelsLike: 64,\n      precipitationChance: 20,\n      windSpeed: 14,\n      condition: \"sunny\",\n    },\n    {\n      time: \"2024-07-12T22:00:00.000Z\",\n      temperature: 66,\n      feelsLike: 65,\n      precipitationChance: 20,\n      windSpeed: 13,\n      condition: \"sunny\",\n    },\n    {\n      time: \"2024-07-12T23:00:00.000Z\",\n      temperature: 65,\n      feelsLike: 64,\n      precipitationChance: 18,\n      windSpeed: 12,\n      condition: \"sunny\",\n    },\n    {\n      time: \"2024-07-13T00:00:00.000Z\",\n      temperature: 63,\n      feelsLike: 62,\n      precipitationChance: 15,\n      windSpeed: 11,\n      condition: \"cloudy\",\n    },\n    {\n      time: \"2024-07-13T01:00:00.000Z\",\n      temperature: 61,\n      feelsLike: 60,\n      precipitationChance: 12,\n      windSpeed: 10,\n      condition: \"cloudy\",\n    },\n    {\n      time: \"2024-07-13T02:00:00.000Z\",\n      temperature: 59,\n      feelsLike: 58,\n      precipitationChance: 10,\n      windSpeed: 9,\n      condition: \"cloudy\",\n    },\n    {\n      time: \"2024-07-13T03:00:00.000Z\",\n      temperature: 58,\n      feelsLike: 57,\n      precipitationChance: 8,\n      windSpeed: 8,\n      condition: \"cloudy\",\n    },\n  ],\n  weekly: [\n    {\n      day: \"2024-07-12\",\n      high: 66,\n      low: 56,\n      precipitationChance: 20,\n      condition: \"sunny\",\n    },\n    {\n      day: \"2024-07-13\",\n      high: 65,\n      low: 55,\n      precipitationChance: 25,\n      condition: \"sunny\",\n    },\n    {\n      day: \"2024-07-14\",\n      high: 64,\n      low: 54,\n      precipitationChance: 30,\n      condition: \"cloudy\",\n    },\n    {\n      day: \"2024-07-15\",\n      high: 63,\n      low: 54,\n      precipitationChance: 40,\n      condition: \"cloudy\",\n    },\n    {\n      day: \"2024-07-16\",\n      high: 62,\n      low: 53,\n      precipitationChance: 45,\n      condition: \"rain\",\n    },\n    {\n      day: \"2024-07-17\",\n      high: 64,\n      low: 54,\n      precipitationChance: 30,\n      condition: \"sunny\",\n    },\n    {\n      day: \"2024-07-18\",\n      high: 67,\n      low: 55,\n      precipitationChance: 15,\n      condition: \"sunny\",\n    },\n  ],\n  airQuality: [\n    {\n      label: \"US AQI\",\n      value: \"42\",\n      status: \"Good\",\n      description:\n        \"Clear coastal air with minimal particulate matter detected.\",\n    },\n    {\n      label: \"PM2.5\",\n      value: \"8.6 µg/m³\",\n      status: \"Low particulate levels\",\n      description: \"Fine particulates remain well below daily thresholds.\",\n    },\n    {\n      label: \"Dust Index\",\n      value: \"18.4 µg/m³\",\n      status: \"Minimal dust\",\n      description: \"Marine influence keeps airborne dust concentrations low.\",\n    },\n  ],\n  alerts: [\n    {\n      title: \"Mild onshore breeze continues\",\n      description:\n        \"Expect a gentle westerly wind through the afternoon with choppy bay waters.\",\n      severity: \"Advisory\",\n      icon: Wind,\n    },\n    {\n      title: \"Low rain chance through weekend\",\n      description:\n        \"Stray mist possible near the coast late nights, but dry for most plans.\",\n      severity: \"Watch\",\n      icon: Umbrella,\n    },\n  ],\n};\n\nconst containerVariants: Variants = {\n  hidden: { opacity: 0 },\n  visible: {\n    opacity: 1,\n    transition: {\n      staggerChildren: 0.1,\n      delayChildren: 0.2,\n    },\n  },\n};\n\nconst itemVariants: Variants = {\n  hidden: { opacity: 0, y: 16 },\n  visible: {\n    opacity: 1,\n    y: 0,\n    transition: { duration: 0.4, ease: \"easeOut\" },\n  },\n};\n\nconst listItemVariants: Variants = {\n  hidden: { opacity: 0, y: 12 },\n  visible: {\n    opacity: 1,\n    y: 0,\n    transition: { duration: 0.35, ease: \"easeOut\" },\n  },\n};\n\nconst SEVERITY_STYLES: Record<AlertSeverity, string> = {\n  Advisory: \"bg-blue-500/20 text-blue-600 dark:text-blue-400\",\n  Watch: \"bg-amber-500/20 text-amber-600 dark:text-amber-400\",\n  Warning: \"bg-red-500/20 text-red-600 dark:text-red-400\",\n};\n\nconst CONDITION_ICONS: Record<WeatherCondition, LucideIcon> = {\n  sunny: Sun,\n  rain: CloudRain,\n  cloudy: Cloud,\n  storm: CloudLightning,\n};\n\nfunction formatHour(timestamp: string, timezone?: string) {\n  return new Intl.DateTimeFormat(undefined, {\n    hour: \"numeric\",\n    hour12: true,\n    timeZone: timezone,\n  }).format(new Date(timestamp));\n}\n\nfunction formatDay(timestamp: string, timezone?: string) {\n  return new Intl.DateTimeFormat(undefined, {\n    weekday: \"short\",\n    timeZone: timezone,\n  }).format(new Date(timestamp));\n}\n\nfunction formatTime(timestamp: string, timezone?: string) {\n  return new Intl.DateTimeFormat(undefined, {\n    hour: \"numeric\",\n    minute: \"2-digit\",\n    hour12: true,\n    timeZone: timezone,\n  }).format(new Date(timestamp));\n}\n\nfunction describeHumidity(value: number) {\n  if (value >= 70) return \"Humid – expect a touch of mugginess\";\n  if (value <= 30) return \"Dry air – hydrate frequently\";\n  return \"Comfortable humidity for outdoor plans\";\n}\n\nfunction describeWind(speed: number) {\n  if (speed >= 25) return \"Breezy with gusts – secure loose items\";\n  if (speed >= 15) return \"Noticeable breeze across the bay\";\n  return \"Light winds – calm conditions\";\n}\n\nfunction describePressure(value: number) {\n  if (value >= 1020) return \"High pressure holding – skies stay stable\";\n  if (value <= 1005) return \"Low pressure developing – expect shifts\";\n  return \"Steady pressure – minimal change expected\";\n}\n\nfunction describePrecipitation(chance: number) {\n  if (chance >= 60) return \"Keep rain gear handy\";\n  if (chance >= 30) return \"Spotty showers possible\";\n  return \"Minimal chance of precipitation\";\n}\n\nexport function WeatherDashboard(): React.ReactElement {\n  const activeView = \"today\";\n  const weatherData = STATIC_WEATHER_DATA;\n\n  const weatherMetrics = useMemo<WeatherMetric[]>(() => {\n    return [\n      {\n        label: \"Humidity\",\n        value: weatherData.current.humidity + \"%\",\n        description: describeHumidity(weatherData.current.humidity),\n        icon: Droplets,\n      },\n      {\n        label: \"Wind\",\n        value: weatherData.current.windSpeed + \" mph\",\n        description: describeWind(weatherData.current.windSpeed),\n        icon: Wind,\n      },\n      {\n        label: \"Pressure\",\n        value: weatherData.current.pressure + \" hPa\",\n        description: describePressure(weatherData.current.pressure),\n        icon: Gauge,\n      },\n      {\n        label: \"Precipitation\",\n        value: weatherData.current.precipitationChance + \"%\",\n        description: describePrecipitation(\n          weatherData.current.precipitationChance\n        ),\n        icon: Umbrella,\n      },\n    ];\n  }, [weatherData]);\n\n  const hourlyChartData = useMemo(\n    () =>\n      weatherData.hourly.slice(0, 12).map((hour) => ({\n        name: formatHour(hour.time),\n        temperature: hour.temperature,\n        feelsLike: hour.feelsLike,\n      })),\n    [weatherData]\n  );\n\n  const hourlyForecast = weatherData.hourly.slice(0, 8);\n  const weeklyForecast = weatherData.weekly.slice(0, 7);\n  const airQualityMetrics = weatherData.airQuality;\n  const alerts = weatherData.alerts;\n\n  const updatedMinutesAgo = useMemo(() => {\n    const updatedDate = new Date(weatherData.updatedAt);\n    const diffMinutes = Math.floor(\n      (Date.now() - updatedDate.getTime()) / (1000 * 60)\n    );\n    if (diffMinutes <= 1) return \"Updated moments ago\";\n    if (diffMinutes < 60) return \"Updated \" + diffMinutes + \" minutes ago\";\n    const diffHours = Math.floor(diffMinutes / 60);\n    if (diffHours === 1) return \"Updated about an hour ago\";\n    return \"Updated \" + diffHours + \" hours ago\";\n  }, [weatherData.updatedAt]);\n\n  return (\n    <main className=\"relative min-h-screen overflow-hidden bg-background\">\n      <div className=\"relative mx-auto flex min-h-screen flex-col gap-8 py-12 lg:gap-12 lg:py-16\">\n        <header className=\"flex flex-col gap-4 md:flex-row md:items-center md:justify-between\">\n          <div className=\"space-y-3\">\n            <Badge\n              variant=\"outline\"\n              className=\"inline-flex items-center gap-2 rounded-full border-border/50 bg-background/55 px-4 py-1.5 text-xs uppercase tracking-[0.2em] text-foreground/70 backdrop-blur\"\n            >\n              <CalendarDays className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n              7-Day Coastal Outlook\n            </Badge>\n\n            <div>\n              <h1 className=\"text-3xl font-semibold tracking-tight text-foreground md:text-4xl\">\n                Coastal Weather Overview\n              </h1>\n              <p className=\"mt-2 flex flex-wrap items-center gap-2 text-sm text-foreground/70\">\n                <MapPin className=\"h-4 w-4\" aria-hidden=\"true\" />\n                {weatherData.location}\n                <span aria-live=\"polite\" className=\"text-foreground/50\">\n                  · {updatedMinutesAgo}\n                </span>\n              </p>\n            </div>\n          </div>\n\n          <div className=\"flex flex-wrap items-center gap-2\">\n            {[\"today\", \"week\", \"radar\"].map((view) => (\n              <Button\n                key={view}\n                type=\"button\"\n                variant={view === activeView ? \"default\" : \"ghost\"}\n                aria-pressed={view === activeView}\n                className=\"rounded-lg px-4 py-2 text-sm uppercase tracking-[0.1em]\"\n              >\n                {view === \"today\" && \"Today\"}\n                {view === \"week\" && \"Week\"}\n                {view === \"radar\" && \"Radar\"}\n              </Button>\n            ))}\n            <Button\n              type=\"button\"\n              variant=\"outline\"\n              size=\"sm\"\n              onClick={() => undefined}\n              className=\"gap-2 rounded-lg text-xs uppercase tracking-[0.15em]\"\n            >\n              <RefreshCcw className=\"h-4 w-4\" aria-hidden=\"true\" />\n              Refresh\n            </Button>\n          </div>\n        </header>\n\n        <motion.div\n          variants={containerVariants}\n          initial=\"hidden\"\n          animate=\"visible\"\n          className=\"grid gap-6 md:gap-8 lg:grid-cols-1\"\n          aria-busy={false}\n          aria-live=\"polite\"\n        >\n          <motion.article\n            variants={itemVariants}\n            className=\"group relative overflow-hidden rounded-2xl border border-border/40 bg-background/60 p-6 backdrop-blur transition-all hover:border-border/60 hover:shadow-lg\"\n            role=\"article\"\n            aria-label=\"Current weather conditions\"\n          >\n            <div className=\"absolute inset-0 bg-gradient-to-br from-foreground/[0.04] via-transparent to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100 -z-10\" />\n\n            <div className=\"relative flex flex-col gap-6\">\n              <div className=\"flex flex-col gap-3\">\n                <div className=\"flex items-center gap-3\">\n                  <div className=\"rounded-full border border-border/40 bg-background/60 p-3\">\n                    <Sun className=\"h-6 w-6 text-primary\" aria-hidden=\"true\" />\n                  </div>\n                  <div>\n                    <p className=\"text-xs uppercase tracking-[0.2em] text-foreground/70\">\n                      Right Now\n                    </p>\n                    <p className=\"text-sm text-foreground/60\">\n                      {weatherData.current.summary}\n                    </p>\n                  </div>\n                </div>\n\n                <div className=\"flex flex-col gap-1\">\n                  <div className=\"flex flex-wrap items-baseline gap-3\">\n                    <span className=\"text-5xl font-semibold tracking-tight text-foreground md:text-6xl\">\n                      {weatherData.current.temperature}°\n                    </span>\n                    <span className=\"text-sm text-foreground/60\">\n                      Feels like {weatherData.current.feelsLike}°\n                    </span>\n                  </div>\n                  <p className=\"text-sm text-foreground/70\">\n                    {\"Chance of rain \" +\n                      weatherData.current.precipitationChance +\n                      \"% · Sunrise \" +\n                      formatTime(weatherData.current.sunrise) +\n                      \" · Sunset \" +\n                      formatTime(weatherData.current.sunset)}\n                  </p>\n                </div>\n              </div>\n\n              <motion.div\n                role=\"list\"\n                className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\"\n                initial=\"hidden\"\n                animate=\"visible\"\n                variants={containerVariants}\n              >\n                {weatherMetrics.map((metric) => (\n                  <motion.div\n                    key={metric.label}\n                    role=\"listitem\"\n                    variants={listItemVariants}\n                    whileHover={{ y: -4 }}\n                    transition={{ duration: 0.2 }}\n                    className=\"flex items-start gap-3 rounded-xl border border-border/30 bg-background/40 p-4 transition-all hover:border-border/50 hover:bg-background/60\"\n                  >\n                    <span className=\"flex h-10 w-10 items-center justify-center rounded-full border border-border/40 bg-background/60 text-foreground/70\">\n                      <metric.icon className=\"h-4 w-4\" aria-hidden=\"true\" />\n                    </span>\n                    <div className=\"space-y-1\">\n                      <p className=\"text-xs font-semibold uppercase tracking-[0.2em] text-foreground/60\">\n                        {metric.label}\n                      </p>\n                      <p className=\"text-lg font-semibold text-foreground\">\n                        {metric.value}\n                      </p>\n                      <p className=\"text-xs text-foreground/60\">\n                        {metric.description}\n                      </p>\n                    </div>\n                  </motion.div>\n                ))}\n              </motion.div>\n\n              <div className=\"flex flex-col gap-3 rounded-xl border border-border/30 bg-background/30 p-4\">\n                <div className=\"flex items-center justify-between text-sm text-foreground/70\">\n                  <div className=\"flex items-center gap-2\">\n                    <Sunrise className=\"h-4 w-4\" aria-hidden=\"true\" />\n                    Sunrise\n                  </div>\n                  <span className=\"text-foreground\">\n                    {formatTime(weatherData.current.sunrise)}\n                  </span>\n                </div>\n                <div className=\"flex items-center justify-between text-sm text-foreground/70\">\n                  <div className=\"flex items-center gap-2\">\n                    <Sunset className=\"h-4 w-4\" aria-hidden=\"true\" />\n                    Sunset\n                  </div>\n                  <span className=\"text-foreground\">\n                    {formatTime(weatherData.current.sunset)}\n                  </span>\n                </div>\n              </div>\n            </div>\n          </motion.article>\n\n          <motion.article\n            variants={itemVariants}\n            className=\"group relative overflow-hidden rounded-2xl border border-border/40 bg-background/60 p-6 backdrop-blur transition-all hover:border-border/60 hover:shadow-lg \"\n            role=\"article\"\n            aria-label=\"Hourly forecast chart\"\n          >\n            <div className=\"absolute inset-0 bg-gradient-to-br from-foreground/[0.04] via-transparent to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100 -z-10\" />\n\n            <div className=\"relative flex flex-col gap-6\">\n              <div className=\"flex flex-wrap items-center justify-between gap-3\">\n                <div>\n                  <h2 className=\"text-sm font-semibold uppercase tracking-[0.25em] text-foreground\">\n                    Hourly Forecast\n                  </h2>\n                  <p className=\"text-xs text-foreground/60\">\n                    Temperature trend and precipitation chance through the\n                    evening\n                  </p>\n                </div>\n                <Badge className=\"rounded-full bg-primary/20 text-xs uppercase tracking-[0.2em] text-primary\">\n                  Live radar calibrated\n                </Badge>\n              </div>\n\n              <div style={{ width: \"100%\", height: 260 }} className=\"relative\">\n                <ResponsiveContainer width=\"100%\" height=\"100%\">\n                  <AreaChart\n                    data={hourlyChartData}\n                    margin={{ top: 10, right: 16, left: -20, bottom: 0 }}\n                  >\n                    <defs>\n                      <linearGradient\n                        id=\"temperatureGradient\"\n                        x1=\"0\"\n                        y1=\"0\"\n                        x2=\"0\"\n                        y2=\"1\"\n                      >\n                        <stop\n                          offset=\"5%\"\n                          stopColor=\"hsl(var(--primary))\"\n                          stopOpacity={0.45}\n                        />\n                        <stop\n                          offset=\"95%\"\n                          stopColor=\"hsl(var(--primary))\"\n                          stopOpacity={0.05}\n                        />\n                      </linearGradient>\n                    </defs>\n                    <CartesianGrid\n                      strokeDasharray=\"3 3\"\n                      stroke=\"hsl(var(--border))\"\n                      opacity={0.25}\n                      vertical={false}\n                    />\n                    <XAxis\n                      dataKey=\"name\"\n                      stroke=\"hsl(var(--foreground))\"\n                      opacity={0.6}\n                      style={{ fontSize: \"11px\" }}\n                    />\n                    <Tooltip\n                      cursor={{ stroke: \"hsl(var(--primary) / 0.3)\" }}\n                      contentStyle={{\n                        backgroundColor: \"hsl(var(--background) / 0.8)\",\n                        border: \"1px solid hsl(var(--border))\",\n                        borderRadius: \"12px\",\n                        backdropFilter: \"blur(12px)\",\n                        padding: \"10px 12px\",\n                      }}\n                      labelStyle={{\n                        color: \"hsl(var(--foreground))\",\n                        fontWeight: 600,\n                      }}\n                      formatter={(value: any, key: any) => [\n                        value?.toString() + \"°\",\n                        key === \"feelsLike\" ? \"Feels like\" : \"Temperature\",\n                      ]}\n                    />\n                    <Area\n                      type=\"natural\"\n                      dataKey=\"temperature\"\n                      stroke=\"hsl(var(--primary))\"\n                      strokeWidth={2.5}\n                      fill=\"url(#temperatureGradient)\"\n                      activeDot={{ r: 5 }}\n                    />\n                    <Area\n                      type=\"natural\"\n                      dataKey=\"feelsLike\"\n                      stroke=\"hsl(var(--foreground) / 0.4)\"\n                      strokeDasharray=\"6 4\"\n                      strokeWidth={2}\n                      fillOpacity={0}\n                      activeDot={{ r: 4 }}\n                    />\n                  </AreaChart>\n                </ResponsiveContainer>\n              </div>\n\n              <motion.ul\n                role=\"list\"\n                className=\"grid gap-3 sm:grid-cols-2 xl:grid-cols-4\"\n                variants={containerVariants}\n                initial=\"hidden\"\n                animate=\"visible\"\n              >\n                {hourlyForecast.map((hour) => {\n                  const Icon = CONDITION_ICONS[hour.condition];\n                  return (\n                    <motion.li\n                      key={hour.time}\n                      role=\"listitem\"\n                      variants={listItemVariants}\n                      className=\"group/hour flex flex-col gap-2 rounded-xl border border-border/30 bg-background/40 p-4 text-left transition-all hover:border-border/50 hover:bg-background/60\"\n                    >\n                      <p className=\"text-xs uppercase tracking-[0.2em] text-foreground/60\">\n                        {formatHour(hour.time)}\n                      </p>\n                      <div className=\"flex items-center justify-between\">\n                        <span className=\"text-lg font-semibold text-foreground\">\n                          {hour.temperature}°\n                        </span>\n                        <span className=\"text-xs text-foreground/60\">\n                          {hour.feelsLike}° feels\n                        </span>\n                      </div>\n                      <div className=\"flex items-center justify-between text-sm text-foreground/70\">\n                        <div className=\"flex items-center gap-2\">\n                          <span className=\"flex h-8 w-8 items-center justify-center rounded-full border border-border/40 bg-background/50 text-foreground/70\">\n                            <Icon className=\"h-4 w-4\" aria-hidden=\"true\" />\n                          </span>\n                          <span>{hour.windSpeed} mph winds</span>\n                        </div>\n                        <span className=\"text-xs text-foreground/60\">\n                          {hour.precipitationChance}% rain\n                        </span>\n                      </div>\n                    </motion.li>\n                  );\n                })}\n              </motion.ul>\n            </div>\n          </motion.article>\n\n          <motion.article\n            variants={itemVariants}\n            className=\"group relative overflow-hidden rounded-2xl border border-border/40 bg-background/60 p-6 backdrop-blur transition-all hover:border-border/60 hover:shadow-lg \"\n            role=\"article\"\n            aria-label=\"7 day extended forecast\"\n          >\n            <div className=\"absolute inset-0 bg-gradient-to-br from-foreground/[0.04] via-transparent to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100 -z-10\" />\n\n            <div className=\"relative flex flex-col gap-6\">\n              <div className=\"flex flex-wrap items-center justify-between gap-3\">\n                <div>\n                  <h2 className=\"text-sm font-semibold uppercase tracking-[0.25em] text-foreground\">\n                    Weekly Outlook\n                  </h2>\n                  <p className=\"text-xs text-foreground/60\">\n                    Plan ahead with precipitation risk and temperature swings\n                  </p>\n                </div>\n                <Button\n                  variant=\"ghost\"\n                  size=\"sm\"\n                  className=\"gap-2 rounded-lg text-xs uppercase tracking-[0.15em] text-foreground/70 hover:text-foreground\"\n                >\n                  Export\n                </Button>\n              </div>\n\n              <motion.ul\n                role=\"list\"\n                className=\"grid gap-3 sm:grid-cols-2 xl:grid-cols-3\"\n                initial=\"hidden\"\n                animate=\"visible\"\n                variants={containerVariants}\n              >\n                {weeklyForecast.map((day, index) => {\n                  const Icon = CONDITION_ICONS[day.condition];\n                  return (\n                    <motion.li\n                      key={day.day + \"-\" + index}\n                      role=\"listitem\"\n                      variants={listItemVariants}\n                      whileHover={{ y: -4 }}\n                      transition={{ duration: 0.2 }}\n                      className=\"flex flex-col gap-3 rounded-xl border border-border/30 bg-background/40 p-4 transition-all hover:border-border/50 hover:bg-background/60\"\n                    >\n                      <div className=\"flex items-center justify-between text-sm text-foreground/70\">\n                        <span className=\"text-xs uppercase tracking-[0.2em]\">\n                          {formatDay(day.day)}\n                        </span>\n                        <span>{day.precipitationChance}% rain</span>\n                      </div>\n                      <div className=\"flex items-center justify-between\">\n                        <div className=\"flex items-center gap-3\">\n                          <span className=\"flex h-10 w-10 items-center justify-center rounded-full border border-border/40 bg-background/50 text-foreground/70\">\n                            <Icon className=\"h-5 w-5\" aria-hidden=\"true\" />\n                          </span>\n                          <div>\n                            <p className=\"text-lg font-semibold text-foreground\">\n                              {day.high}°\n                            </p>\n                            <p className=\"text-xs text-foreground/60\">\n                              Low {day.low}°\n                            </p>\n                          </div>\n                        </div>\n                        <Badge\n                          variant=\"outline\"\n                          className=\"rounded-full border-border/40 bg-background/50 px-3 py-1 text-[11px] uppercase tracking-[0.15em] text-foreground/60\"\n                        >\n                          {day.condition === \"sunny\" && \"Clear\"}\n                          {day.condition === \"cloudy\" && \"Clouds\"}\n                          {day.condition === \"rain\" && \"Showers\"}\n                          {day.condition === \"storm\" && \"Storm\"}\n                        </Badge>\n                      </div>\n                    </motion.li>\n                  );\n                })}\n              </motion.ul>\n            </div>\n          </motion.article>\n\n          <motion.article\n            variants={itemVariants}\n            className=\"group relative overflow-hidden rounded-2xl border border-border/40 bg-background/60 p-6 backdrop-blur transition-all hover:border-border/60 hover:shadow-lg\"\n            role=\"article\"\n            aria-label=\"Air quality and weather alerts\"\n          >\n            <div className=\"absolute inset-0 bg-gradient-to-br from-foreground/[0.04] via-transparent to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100 -z-10\" />\n\n            <div className=\"relative flex flex-col gap-6\">\n              <div className=\"flex flex-wrap items-center justify-between gap-3\">\n                <div>\n                  <h2 className=\"text-sm font-semibold uppercase tracking-[0.25em] text-foreground\">\n                    Air Quality & Alerts\n                  </h2>\n                  <p className=\"text-xs text-foreground/60\">\n                    Live monitoring for coastal neighborhoods\n                  </p>\n                </div>\n                <Badge className=\"rounded-full bg-emerald-500/20 text-xs uppercase tracking-[0.2em] text-emerald-600 dark:text-emerald-400\">\n                  {airQualityMetrics[0]?.status ?? \"Stable\"}\n                </Badge>\n              </div>\n\n              <motion.ul\n                role=\"list\"\n                className=\"grid gap-3\"\n                initial=\"hidden\"\n                animate=\"visible\"\n                variants={containerVariants}\n              >\n                {airQualityMetrics.map((metric) => (\n                  <motion.li\n                    key={metric.label}\n                    role=\"listitem\"\n                    variants={listItemVariants}\n                    className=\"rounded-xl border border-border/30 bg-background/40 p-4\"\n                  >\n                    <div className=\"flex items-center justify-between\">\n                      <p className=\"text-xs uppercase tracking-[0.2em] text-foreground/60\">\n                        {metric.label}\n                      </p>\n                      <span className=\"text-sm font-semibold text-foreground\">\n                        {metric.value}\n                      </span>\n                    </div>\n                    <p className=\"mt-2 text-sm text-foreground/70\">\n                      {metric.status}\n                    </p>\n                    <p className=\"text-xs text-foreground/60\">\n                      {metric.description}\n                    </p>\n                  </motion.li>\n                ))}\n              </motion.ul>\n\n              <div>\n                <h3 className=\"text-xs font-semibold uppercase tracking-[0.2em] text-foreground/60\">\n                  Local alerts\n                </h3>\n                <motion.ul\n                  role=\"list\"\n                  className=\"mt-3 space-y-3\"\n                  initial=\"hidden\"\n                  animate=\"visible\"\n                  variants={containerVariants}\n                >\n                  {alerts.map((alert) => {\n                    const Icon = alert.icon;\n                    return (\n                      <motion.li\n                        key={alert.title}\n                        role=\"listitem\"\n                        variants={listItemVariants}\n                        className=\"flex items-start gap-3 rounded-xl border border-border/30 bg-background/40 p-4\"\n                      >\n                        <span className=\"flex h-10 w-10 items-center justify-center rounded-full border border-border/40 bg-background/60 text-foreground/70\">\n                          <Icon className=\"h-5 w-5\" aria-hidden=\"true\" />\n                        </span>\n                        <div className=\"flex-1 space-y-1\">\n                          <div className=\"flex flex-wrap items-center gap-2\">\n                            <p className=\"text-sm font-semibold text-foreground\">\n                              {alert.title}\n                            </p>\n                            <span\n                              className={\n                                SEVERITY_STYLES[alert.severity] +\n                                \" rounded-full px-2 py-1 text-[11px] uppercase tracking-[0.15em]\"\n                              }\n                            >\n                              {alert.severity}\n                            </span>\n                          </div>\n                          <p className=\"text-xs text-foreground/60\">\n                            {alert.description}\n                          </p>\n                        </div>\n                      </motion.li>\n                    );\n                  })}\n                </motion.ul>\n              </div>\n            </div>\n          </motion.article>\n        </motion.div>\n      </div>\n    </main>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/uitripled/weather-dashboard-shadcnui.tsx"
    }
  ]
}