duoops 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +181 -0
  3. package/bin/dev.cmd +3 -0
  4. package/bin/dev.js +7 -0
  5. package/bin/run.cmd +3 -0
  6. package/bin/run.js +8 -0
  7. package/dist/commands/act.d.ts +12 -0
  8. package/dist/commands/act.js +61 -0
  9. package/dist/commands/ask.d.ts +8 -0
  10. package/dist/commands/ask.js +22 -0
  11. package/dist/commands/init.d.ts +5 -0
  12. package/dist/commands/init.js +97 -0
  13. package/dist/commands/job/logs.d.ts +13 -0
  14. package/dist/commands/job/logs.js +26 -0
  15. package/dist/commands/measure/calculate.d.ts +19 -0
  16. package/dist/commands/measure/calculate.js +208 -0
  17. package/dist/commands/measure/component.d.ts +5 -0
  18. package/dist/commands/measure/component.js +23 -0
  19. package/dist/commands/measure/seed.d.ts +5 -0
  20. package/dist/commands/measure/seed.js +62 -0
  21. package/dist/commands/pipelines/list.d.ts +14 -0
  22. package/dist/commands/pipelines/list.js +62 -0
  23. package/dist/commands/pipelines/show.d.ts +13 -0
  24. package/dist/commands/pipelines/show.js +68 -0
  25. package/dist/commands/portal.d.ts +8 -0
  26. package/dist/commands/portal.js +139 -0
  27. package/dist/commands/undo.d.ts +5 -0
  28. package/dist/commands/undo.js +35 -0
  29. package/dist/index.d.ts +1 -0
  30. package/dist/index.js +1 -0
  31. package/dist/lib/ai/agent.d.ts +6 -0
  32. package/dist/lib/ai/agent.js +139 -0
  33. package/dist/lib/ai/model.d.ts +2 -0
  34. package/dist/lib/ai/model.js +22 -0
  35. package/dist/lib/ai/tools/editing.d.ts +3 -0
  36. package/dist/lib/ai/tools/editing.js +61 -0
  37. package/dist/lib/ai/tools/filesystem.d.ts +4 -0
  38. package/dist/lib/ai/tools/filesystem.js +44 -0
  39. package/dist/lib/ai/tools/gitlab.d.ts +4 -0
  40. package/dist/lib/ai/tools/gitlab.js +81 -0
  41. package/dist/lib/ai/tools/measure.d.ts +3 -0
  42. package/dist/lib/ai/tools/measure.js +26 -0
  43. package/dist/lib/config.d.ts +18 -0
  44. package/dist/lib/config.js +72 -0
  45. package/dist/lib/gitlab/client.d.ts +6 -0
  46. package/dist/lib/gitlab/client.js +18 -0
  47. package/dist/lib/gitlab/index.d.ts +6 -0
  48. package/dist/lib/gitlab/index.js +49 -0
  49. package/dist/lib/gitlab/provider.d.ts +14 -0
  50. package/dist/lib/gitlab/provider.js +72 -0
  51. package/dist/lib/gitlab/types.d.ts +34 -0
  52. package/dist/lib/gitlab/types.js +5 -0
  53. package/dist/lib/integrations/bigquery-sink.d.ts +12 -0
  54. package/dist/lib/integrations/bigquery-sink.js +47 -0
  55. package/dist/lib/logger.d.ts +2 -0
  56. package/dist/lib/logger.js +11 -0
  57. package/dist/lib/measure/bigquery-service.d.ts +2 -0
  58. package/dist/lib/measure/bigquery-service.js +54 -0
  59. package/dist/lib/measure/carbon-calculator.d.ts +13 -0
  60. package/dist/lib/measure/carbon-calculator.js +125 -0
  61. package/dist/lib/measure/cli-utils.d.ts +2 -0
  62. package/dist/lib/measure/cli-utils.js +107 -0
  63. package/dist/lib/measure/intensity-provider.d.ts +6 -0
  64. package/dist/lib/measure/intensity-provider.js +34 -0
  65. package/dist/lib/measure/power-profile-repository.d.ts +19 -0
  66. package/dist/lib/measure/power-profile-repository.js +129 -0
  67. package/dist/lib/measure/types.d.ts +137 -0
  68. package/dist/lib/measure/types.js +1 -0
  69. package/dist/lib/measure/zone-mapper.d.ts +16 -0
  70. package/dist/lib/measure/zone-mapper.js +104 -0
  71. package/dist/lib/state.d.ts +4 -0
  72. package/dist/lib/state.js +21 -0
  73. package/dist/portal/assets/index-BP8FwWqA.css +1 -0
  74. package/dist/portal/assets/index-MU6EBerh.js +188 -0
  75. package/dist/portal/duoops.svg +4 -0
  76. package/dist/portal/index.html +24 -0
  77. package/dist/portal/vite.svg +1 -0
  78. package/oclif.manifest.json +415 -0
  79. package/package.json +103 -0
@@ -0,0 +1,129 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ export class PowerProfileRepository {
4
+ dataDir;
5
+ awsMachines = null;
6
+ cpuPhysicalSpecs = null;
7
+ cpuProfiles = null;
8
+ gcpMachines = null;
9
+ constructor(dataDir) {
10
+ this.dataDir = dataDir;
11
+ }
12
+ async getCpuPowerProfile(provider, machineType) {
13
+ const profile = await this.getMachineProfile(provider, machineType);
14
+ if (!profile)
15
+ return null;
16
+ let basePowerProfile = null;
17
+ let cpuName;
18
+ if (profile.cpuPowerProfile && profile.cpuPowerProfile.length > 0) {
19
+ basePowerProfile = profile.cpuPowerProfile;
20
+ cpuName = profile.matchedCpuProfile || profile.platformCpu;
21
+ }
22
+ else if (profile.matchedCpuProfile) {
23
+ const cpuProfiles = this.loadCpuProfiles();
24
+ const rawCpu = cpuProfiles[profile.matchedCpuProfile];
25
+ if (rawCpu) {
26
+ basePowerProfile = this.normalizePowerPoints(rawCpu.power_profile);
27
+ cpuName = profile.matchedCpuProfile;
28
+ }
29
+ }
30
+ if (!basePowerProfile)
31
+ return null;
32
+ // Apply physical vCPU correction for accurate power estimation
33
+ // Formula: power_per_vm = (TDP / physical_threads) * vm_vcpus * ratio
34
+ // The base profile has watts scaled by vm_vcpus, we need to correct by dividing
35
+ // by vm_vcpus and multiplying by (vm_vcpus / physical_threads)
36
+ const physicalSpec = cpuName ? this.findPhysicalSpec(cpuName) : null;
37
+ if (physicalSpec && physicalSpec.threads > 0 && profile.vcpus > 0) {
38
+ // The gcp_machine_power_profiles.json has: watts = TDP * ratio * vm_vcpus (inflated)
39
+ // Correct formula: watts = TDP * ratio * (vm_vcpus / physical_threads)
40
+ // Correction factor = correct / inflated = 1 / physical_threads
41
+ const correctionFactor = 1 / physicalSpec.threads;
42
+ return basePowerProfile.map((p) => ({
43
+ percentage: p.percentage,
44
+ watts: p.watts * correctionFactor,
45
+ }));
46
+ }
47
+ // Fallback: return profile as-is (may be overestimated for GCP)
48
+ return basePowerProfile;
49
+ }
50
+ async getMachineProfile(provider, machineType) {
51
+ const machines = this.loadMachineData(provider);
52
+ const raw = machines[machineType];
53
+ if (!raw)
54
+ return null;
55
+ const powerProfile = raw.cpu_power_profile ? this.normalizePowerPoints(raw.cpu_power_profile) : [];
56
+ return {
57
+ cpuPowerProfile: powerProfile,
58
+ machineType,
59
+ matchedCpuProfile: raw.matched_cpu_profile,
60
+ memoryGb: this.normalizeNumber(raw.memory_gb),
61
+ platformCpu: raw.platform_cpu,
62
+ scope3EmissionsHourly: raw.scope3_emissions_hourly,
63
+ vcpus: this.normalizeNumber(raw.vcpus),
64
+ };
65
+ }
66
+ listMachines(provider) {
67
+ const machines = this.loadMachineData(provider);
68
+ return Object.keys(machines).sort();
69
+ }
70
+ findPhysicalSpec(cpuName) {
71
+ const specs = this.loadCpuPhysicalSpecs();
72
+ // Try exact match first
73
+ if (specs[cpuName] && typeof specs[cpuName] === 'object' && 'threads' in specs[cpuName]) {
74
+ return specs[cpuName];
75
+ }
76
+ // Try partial match
77
+ for (const [key, spec] of Object.entries(specs)) {
78
+ if (key === '_metadata')
79
+ continue;
80
+ if (cpuName.includes(key) || key.includes(cpuName)) {
81
+ return spec;
82
+ }
83
+ }
84
+ return null;
85
+ }
86
+ loadCpuPhysicalSpecs() {
87
+ if (!this.cpuPhysicalSpecs) {
88
+ this.cpuPhysicalSpecs = this.loadJsonFile('cpu_physical_specs.json');
89
+ }
90
+ return this.cpuPhysicalSpecs;
91
+ }
92
+ loadCpuProfiles() {
93
+ if (!this.cpuProfiles) {
94
+ this.cpuProfiles = this.loadJsonFile('cpu_power_profiles.json');
95
+ }
96
+ return this.cpuProfiles;
97
+ }
98
+ loadJsonFile(filename) {
99
+ const filePath = path.join(this.dataDir, filename);
100
+ const raw = fs.readFileSync(filePath, 'utf8');
101
+ return JSON.parse(raw);
102
+ }
103
+ loadMachineData(provider) {
104
+ if (provider === 'gcp') {
105
+ if (!this.gcpMachines) {
106
+ this.gcpMachines = this.loadJsonFile('gcp_machine_power_profiles.json');
107
+ }
108
+ return this.gcpMachines;
109
+ }
110
+ if (!this.awsMachines) {
111
+ this.awsMachines = this.loadJsonFile('aws_machine_power_profiles.json');
112
+ }
113
+ return this.awsMachines;
114
+ }
115
+ normalizeNumber(value) {
116
+ if (typeof value === 'number')
117
+ return value;
118
+ if (!value)
119
+ return 0;
120
+ const parsed = Number.parseFloat(value);
121
+ return Number.isFinite(parsed) ? parsed : 0;
122
+ }
123
+ normalizePowerPoints(points) {
124
+ return points.map((p) => ({
125
+ percentage: Number(p.percentage),
126
+ watts: Number(p.watts),
127
+ })).sort((a, b) => a.percentage - b.percentage);
128
+ }
129
+ }
@@ -0,0 +1,137 @@
1
+ export type CloudProvider = 'aws' | 'gcp';
2
+ export interface CliCalculateOptions {
3
+ awsEndTime?: string;
4
+ awsInstanceId?: string;
5
+ awsPeriod?: number;
6
+ awsRegion?: string;
7
+ awsStartTime?: string;
8
+ budget?: number;
9
+ cpuTimeseries?: string;
10
+ failOnBudget?: boolean;
11
+ fromCloudwatch?: boolean;
12
+ gitlab?: boolean;
13
+ machine?: string;
14
+ outJson?: string;
15
+ outMd?: string;
16
+ postNote?: boolean;
17
+ provider?: CloudProvider;
18
+ ramSizeTimeseries?: string;
19
+ ramUsedTimeseries?: string;
20
+ region?: string;
21
+ runnerTags?: string;
22
+ }
23
+ export interface PowerPoint {
24
+ percentage: number;
25
+ watts: number;
26
+ }
27
+ export interface MachineProfile {
28
+ cpuPowerProfile: PowerPoint[];
29
+ machineType: string;
30
+ matchedCpuProfile?: string;
31
+ memoryGb: number;
32
+ platformCpu?: string;
33
+ scope3EmissionsHourly?: number;
34
+ vcpus: number;
35
+ }
36
+ export interface TimeseriesPoint {
37
+ timestamp: string;
38
+ value: number;
39
+ }
40
+ export interface GcpMetricPointValue {
41
+ doubleValue?: number;
42
+ int64Value?: number | string;
43
+ }
44
+ export interface GcpMetricPoint {
45
+ interval?: {
46
+ endTime?: string;
47
+ startTime?: string;
48
+ };
49
+ value?: GcpMetricPointValue;
50
+ }
51
+ export interface GcpTimeSeries {
52
+ points?: GcpMetricPoint[];
53
+ }
54
+ export interface GcpMonitoringResponse {
55
+ timeSeries?: GcpTimeSeries[];
56
+ }
57
+ export interface CloudWatchMetricDataResult {
58
+ Id?: string;
59
+ Timestamps?: Array<Date | number | string>;
60
+ Values?: Array<number | string>;
61
+ }
62
+ export interface CloudWatchMetricDataEnvelope {
63
+ MetricDataResults?: CloudWatchMetricDataResult[];
64
+ metricDataResults?: CloudWatchMetricDataResult[];
65
+ }
66
+ export type CloudWatchMetricDataResultArray = CloudWatchMetricDataResult[];
67
+ export interface CloudWatchDatapoint {
68
+ Average?: number;
69
+ Maximum?: number;
70
+ Minimum?: number;
71
+ Sum?: number;
72
+ Timestamp?: Date | number | string;
73
+ }
74
+ export interface CloudWatchDatapointResponse {
75
+ Datapoints?: CloudWatchDatapoint[];
76
+ }
77
+ export interface LegacyTimeseriesPoint {
78
+ timestamp?: Date | number | string;
79
+ Timestamp?: Date | number | string;
80
+ value?: number | string;
81
+ Value?: number | string;
82
+ }
83
+ export type LegacyTimeseriesArray = LegacyTimeseriesPoint[];
84
+ export type TimestampLike = Date | number | string;
85
+ export type NumericLike = number | string;
86
+ export type TimeseriesFileInput = CloudWatchDatapointResponse | CloudWatchMetricDataEnvelope | CloudWatchMetricDataResultArray | GcpMonitoringResponse | LegacyTimeseriesArray;
87
+ export interface JobInput {
88
+ cpuTimeseries: TimeseriesPoint[];
89
+ machineType: string;
90
+ provider: CloudProvider;
91
+ ramSizeTimeseries: TimeseriesPoint[];
92
+ ramUsedTimeseries: TimeseriesPoint[];
93
+ region: string;
94
+ }
95
+ export interface EmissionsResult {
96
+ carbonIntensity: number;
97
+ cpuEmissions: number;
98
+ cpuEnergyKwh: number;
99
+ machineType: string;
100
+ provider: CloudProvider;
101
+ pue: number;
102
+ ramEmissions: number;
103
+ ramEnergyKwh: number;
104
+ region: string;
105
+ runtimeHours: number;
106
+ scope3Emissions: number;
107
+ totalEmissions: number;
108
+ }
109
+ export interface GitLabContext {
110
+ jobId: number;
111
+ jobToken: string;
112
+ mergeRequestIid?: number;
113
+ pipelineId?: number;
114
+ projectId: number;
115
+ serverUrl: string;
116
+ }
117
+ export interface CarbonReport {
118
+ json: Record<string, unknown>;
119
+ markdown: string;
120
+ summary: string;
121
+ }
122
+ export interface BudgetOptions {
123
+ carbonBudgetGrams?: number;
124
+ failOnBreach?: boolean;
125
+ }
126
+ export interface BudgetResult {
127
+ budgetConfigured: boolean;
128
+ limitGrams?: number;
129
+ overBudget: boolean;
130
+ }
131
+ export type ErrorLike = boolean | Error | null | number | string | undefined;
132
+ export interface AwsInstanceSummary {
133
+ instanceId: string;
134
+ name?: string;
135
+ state?: string;
136
+ type?: string;
137
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,16 @@
1
+ import { CloudProvider } from './types.js';
2
+ export interface ZoneResolution {
3
+ pue: number;
4
+ zone: string;
5
+ }
6
+ export declare class ZoneMapper {
7
+ private readonly dataDir;
8
+ private readonly fallbackPue;
9
+ private readonly awsZoneMapping;
10
+ private readonly gcpZoneMapping;
11
+ private runtimePueData;
12
+ constructor(dataDir: string, fallbackPue?: number);
13
+ resolve(provider: CloudProvider, region: string): ZoneResolution;
14
+ private loadRuntimePueData;
15
+ private normalizeRegion;
16
+ }
@@ -0,0 +1,104 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ export class ZoneMapper {
4
+ dataDir;
5
+ fallbackPue;
6
+ awsZoneMapping = {
7
+ 'ap-northeast-1': { pue: 1.2, zone: 'JP-TK' },
8
+ 'ap-south-1': { pue: 1.22, zone: 'IN-NO' },
9
+ 'ap-southeast-1': { pue: 1.2, zone: 'SG' },
10
+ 'eu-central-1': { pue: 1.16, zone: 'DE' },
11
+ 'eu-west-1': { pue: 1.18, zone: 'IE' },
12
+ 'eu-west-2': { pue: 1.18, zone: 'GB' },
13
+ 'us-east-1': { pue: 1.18, zone: 'US-NE-ISNE' },
14
+ 'us-east-2': { pue: 1.18, zone: 'US-MIDA-PJM' },
15
+ 'us-west-1': { pue: 1.15, zone: 'US-CAL-CISO' },
16
+ 'us-west-2': { pue: 1.14, zone: 'US-NW-PACW' },
17
+ };
18
+ gcpZoneMapping = {
19
+ 'asia-east1': 'TW',
20
+ 'asia-east2': 'HK',
21
+ 'asia-northeast1': 'JP-TK',
22
+ 'asia-northeast2': 'JP-KN',
23
+ 'asia-northeast3': 'KR',
24
+ 'asia-south1': 'IN-WE',
25
+ 'asia-southeast1': 'SG',
26
+ 'asia-southeast2': 'ID-JW',
27
+ 'australia-southeast1': 'AU-NSW',
28
+ 'europe-north1': 'FI',
29
+ 'europe-west1': 'BE',
30
+ 'europe-west2': 'GB',
31
+ 'europe-west3': 'DE',
32
+ 'europe-west4': 'NL',
33
+ 'europe-west6': 'CH',
34
+ 'us-central1': 'US-CENT-SWPP',
35
+ 'us-east1': 'US-NE-ISNE',
36
+ 'us-east4': 'US-MIDA-PJM',
37
+ 'us-west1': 'US-CAL-CISO',
38
+ 'us-west2': 'US-NW-PACW',
39
+ 'us-west3': 'US-SW-AZPS',
40
+ 'us-west4': 'US-NW-NEVP',
41
+ };
42
+ runtimePueData = null;
43
+ constructor(dataDir, fallbackPue = 1.2) {
44
+ this.dataDir = dataDir;
45
+ this.fallbackPue = fallbackPue;
46
+ }
47
+ resolve(provider, region) {
48
+ const normalizedRegion = this.normalizeRegion(region, provider);
49
+ if (provider === 'gcp') {
50
+ const runtime = this.loadRuntimePueData();
51
+ const runtimeRegion = runtime?.regions?.[normalizedRegion];
52
+ const runtimePue = runtimeRegion?.industryStandardPUE;
53
+ const runtimeZone = runtimeRegion?.zone;
54
+ const zone = runtimeZone && runtimeZone !== 'FALLBACK'
55
+ ? runtimeZone
56
+ : this.gcpZoneMapping[normalizedRegion];
57
+ if (!zone) {
58
+ throw new Error(`No zone mapping for GCP region ${normalizedRegion}`);
59
+ }
60
+ return {
61
+ pue: runtimePue || this.fallbackPue,
62
+ zone,
63
+ };
64
+ }
65
+ const awsMapping = this.awsZoneMapping[normalizedRegion];
66
+ if (!awsMapping) {
67
+ throw new Error(`No zone mapping for AWS region ${normalizedRegion}`);
68
+ }
69
+ return {
70
+ pue: awsMapping.pue || this.fallbackPue,
71
+ zone: awsMapping.zone,
72
+ };
73
+ }
74
+ loadRuntimePueData() {
75
+ if (this.runtimePueData)
76
+ return this.runtimePueData;
77
+ const filePath = path.join(this.dataDir, 'runtime-pue-mappings.json');
78
+ if (!fs.existsSync(filePath)) {
79
+ return null;
80
+ }
81
+ try {
82
+ const raw = fs.readFileSync(filePath, 'utf8');
83
+ this.runtimePueData = JSON.parse(raw);
84
+ return this.runtimePueData;
85
+ }
86
+ catch {
87
+ return null;
88
+ }
89
+ }
90
+ normalizeRegion(region, provider) {
91
+ if (provider === 'gcp') {
92
+ // Convert us-central1-a to us-central1
93
+ if (/^[a-z]+-[a-z0-9]+-[a-z]$/.test(region)) {
94
+ return region.split('-').slice(0, 2).join('-');
95
+ }
96
+ return region;
97
+ }
98
+ // Convert us-east-1a to us-east-1
99
+ if (/^[a-z]+-[a-z]+-[0-9][a-z]$/.test(region)) {
100
+ return region.slice(0, -1);
101
+ }
102
+ return region;
103
+ }
104
+ }
@@ -0,0 +1,4 @@
1
+ export declare const DUOOPS_DIR: string;
2
+ export declare const PATCHES_DIR: string;
3
+ export declare const ensureDuoOpsDir: () => void;
4
+ export declare const getLatestPatch: () => null | string;
@@ -0,0 +1,21 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ export const DUOOPS_DIR = path.join(process.cwd(), '.duoops');
4
+ export const PATCHES_DIR = path.join(DUOOPS_DIR, 'patches');
5
+ export const ensureDuoOpsDir = () => {
6
+ if (!fs.existsSync(PATCHES_DIR)) {
7
+ fs.mkdirSync(PATCHES_DIR, { recursive: true });
8
+ }
9
+ };
10
+ export const getLatestPatch = () => {
11
+ if (!fs.existsSync(PATCHES_DIR))
12
+ return null;
13
+ const files = fs.readdirSync(PATCHES_DIR)
14
+ .filter(f => f.endsWith('.patch'))
15
+ .map(f => ({
16
+ name: f,
17
+ time: fs.statSync(path.join(PATCHES_DIR, f)).mtime.getTime()
18
+ }))
19
+ .sort((a, b) => b.time - a.time);
20
+ return files.length > 0 ? path.join(PATCHES_DIR, files[0].name) : null;
21
+ };
@@ -0,0 +1 @@
1
+ @layer properties{@supports ((-webkit-hyphens:none) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial}}}@layer theme{:root,:host{--font-sans:"Inter",system-ui,sans-serif;--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-200:oklch(88.5% .062 18.334);--color-red-400:oklch(70.4% .191 22.216);--color-red-900:oklch(39.6% .141 25.723);--color-amber-500:oklch(76.9% .188 70.08);--color-emerald-500:oklch(69.6% .17 162.48);--color-blue-300:oklch(80.9% .105 251.813);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-purple-500:oklch(62.7% .265 303.9);--color-zinc-100:oklch(96.7% .001 286.375);--color-zinc-200:oklch(92% .004 286.32);--color-zinc-300:oklch(87.1% .006 286.286);--color-zinc-400:oklch(70.5% .015 286.067);--color-zinc-500:oklch(55.2% .016 285.938);--color-zinc-600:oklch(44.2% .017 285.786);--color-zinc-700:oklch(37% .013 285.805);--color-zinc-800:oklch(27.4% .006 286.033);--color-zinc-900:oklch(21% .006 285.885);--color-zinc-950:oklch(14.1% .005 285.823);--color-black:#000;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-4xl:56rem;--container-6xl:72rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wider:.05em;--radius-md:calc(var(--radius) - 2px);--radius-lg:var(--radius);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--animate-bounce:bounce 1s infinite;--blur-sm:8px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-border:hsl(var(--border));--color-background:hsl(var(--background));--color-foreground:hsl(var(--foreground))}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::-moz-placeholder{opacity:1}::placeholder{opacity:1}@supports (not (-webkit-appearance:-apple-pay-button)) or (contain-intrinsic-size:1px){::-moz-placeholder{color:currentColor}::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::-moz-placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*{border-color:var(--color-border)}body{background-color:var(--color-background);color:var(--color-foreground)}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.inset-0{inset:calc(var(--spacing)*0)}.top-0{top:calc(var(--spacing)*0)}.top-1\/2{top:50%}.right-0{right:calc(var(--spacing)*0)}.right-3{right:calc(var(--spacing)*3)}.left-4{left:calc(var(--spacing)*4)}.z-50{z-index:50}.mx-auto{margin-inline:auto}.my-2{margin-block:calc(var(--spacing)*2)}.my-3{margin-block:calc(var(--spacing)*3)}.my-4{margin-block:calc(var(--spacing)*4)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-3{margin-top:calc(var(--spacing)*3)}.mt-4{margin-top:calc(var(--spacing)*4)}.mt-auto{margin-top:auto}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-1\.5{margin-bottom:calc(var(--spacing)*1.5)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-8{margin-bottom:calc(var(--spacing)*8)}.flex{display:flex}.grid{display:grid}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.h-1{height:calc(var(--spacing)*1)}.h-1\.5{height:calc(var(--spacing)*1.5)}.h-3{height:calc(var(--spacing)*3)}.h-3\.5{height:calc(var(--spacing)*3.5)}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-8{height:calc(var(--spacing)*8)}.h-14{height:calc(var(--spacing)*14)}.h-80{height:calc(var(--spacing)*80)}.h-full{height:100%}.h-screen{height:100vh}.max-h-48{max-height:calc(var(--spacing)*48)}.w-1{width:calc(var(--spacing)*1)}.w-1\.5{width:calc(var(--spacing)*1.5)}.w-3{width:calc(var(--spacing)*3)}.w-3\.5{width:calc(var(--spacing)*3.5)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-6{width:calc(var(--spacing)*6)}.w-8{width:calc(var(--spacing)*8)}.w-64{width:calc(var(--spacing)*64)}.w-full{width:100%}.max-w-4xl{max-width:var(--container-4xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-md{max-width:var(--container-md)}.max-w-none{max-width:none}.max-w-sm{max-width:var(--container-sm)}.min-w-0{min-width:calc(var(--spacing)*0)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.animate-bounce{animation:var(--animate-bounce)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-pointer{cursor:pointer}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.list-none{list-style-type:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0\.5{gap:calc(var(--spacing)*.5)}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*6)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*6)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*8)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*8)*calc(1 - var(--tw-space-y-reverse)))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.scroll-smooth{scroll-behavior:smooth}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-red-900\/50{border-color:#82181a80}@supports (color:color-mix(in lab,red,red)){.border-red-900\/50{border-color:color-mix(in oklab,var(--color-red-900)50%,transparent)}}.border-zinc-700{border-color:var(--color-zinc-700)}.border-zinc-800{border-color:var(--color-zinc-800)}.border-zinc-800\/50{border-color:#27272a80}@supports (color:color-mix(in lab,red,red)){.border-zinc-800\/50{border-color:color-mix(in oklab,var(--color-zinc-800)50%,transparent)}}.bg-amber-500\/80{background-color:#f99c00cc}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/80{background-color:color-mix(in oklab,var(--color-amber-500)80%,transparent)}}.bg-black\/50{background-color:#00000080}@supports (color:color-mix(in lab,red,red)){.bg-black\/50{background-color:color-mix(in oklab,var(--color-black)50%,transparent)}}.bg-blue-500{background-color:var(--color-blue-500)}.bg-emerald-500{background-color:var(--color-emerald-500)}.bg-purple-500{background-color:var(--color-purple-500)}.bg-red-900\/20{background-color:#82181a33}@supports (color:color-mix(in lab,red,red)){.bg-red-900\/20{background-color:color-mix(in oklab,var(--color-red-900)20%,transparent)}}.bg-zinc-100{background-color:var(--color-zinc-100)}.bg-zinc-600{background-color:var(--color-zinc-600)}.bg-zinc-800{background-color:var(--color-zinc-800)}.bg-zinc-800\/50{background-color:#27272a80}@supports (color:color-mix(in lab,red,red)){.bg-zinc-800\/50{background-color:color-mix(in oklab,var(--color-zinc-800)50%,transparent)}}.bg-zinc-900{background-color:var(--color-zinc-900)}.bg-zinc-900\/30{background-color:#18181b4d}@supports (color:color-mix(in lab,red,red)){.bg-zinc-900\/30{background-color:color-mix(in oklab,var(--color-zinc-900)30%,transparent)}}.bg-zinc-900\/50{background-color:#18181b80}@supports (color:color-mix(in lab,red,red)){.bg-zinc-900\/50{background-color:color-mix(in oklab,var(--color-zinc-900)50%,transparent)}}.bg-zinc-900\/80{background-color:#18181bcc}@supports (color:color-mix(in lab,red,red)){.bg-zinc-900\/80{background-color:color-mix(in oklab,var(--color-zinc-900)80%,transparent)}}.bg-zinc-950{background-color:var(--color-zinc-950)}.bg-zinc-950\/50{background-color:#09090b80}@supports (color:color-mix(in lab,red,red)){.bg-zinc-950\/50{background-color:color-mix(in oklab,var(--color-zinc-950)50%,transparent)}}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.p-6{padding:calc(var(--spacing)*6)}.px-1{padding-inline:calc(var(--spacing)*1)}.px-1\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-6{padding-inline:calc(var(--spacing)*6)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-2\.5{padding-block:calc(var(--spacing)*2.5)}.py-3{padding-block:calc(var(--spacing)*3)}.py-6{padding-block:calc(var(--spacing)*6)}.py-12{padding-block:calc(var(--spacing)*12)}.pt-4{padding-top:calc(var(--spacing)*4)}.pr-2{padding-right:calc(var(--spacing)*2)}.pr-16{padding-right:calc(var(--spacing)*16)}.pl-1{padding-left:calc(var(--spacing)*1)}.pl-4{padding-left:calc(var(--spacing)*4)}.pl-8{padding-left:calc(var(--spacing)*8)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.leading-6{--tw-leading:calc(var(--spacing)*6);line-height:calc(var(--spacing)*6)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.whitespace-pre-wrap{white-space:pre-wrap}.text-blue-400{color:var(--color-blue-400)}.text-blue-500{color:var(--color-blue-500)}.text-red-200{color:var(--color-red-200)}.text-red-400{color:var(--color-red-400)}.text-zinc-100{color:var(--color-zinc-100)}.text-zinc-200{color:var(--color-zinc-200)}.text-zinc-300{color:var(--color-zinc-300)}.text-zinc-400{color:var(--color-zinc-400)}.text-zinc-500{color:var(--color-zinc-500)}.text-zinc-600{color:var(--color-zinc-600)}.text-zinc-700{color:var(--color-zinc-700)}.text-zinc-950{color:var(--color-zinc-950)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.underline{text-decoration-line:underline}.opacity-50{opacity:.5}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.duration-500{--tw-duration:.5s;transition-duration:.5s}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.\[animation-delay\:-0\.3s\]{animation-delay:-.3s}.\[animation-delay\:-0\.15s\]{animation-delay:-.15s}.\[animation-delay\:0\.2s\]{animation-delay:.2s}.\[animation-delay\:0\.4s\]{animation-delay:.4s}.group-open\/reasoning\:rotate-90:is(:where(.group\/reasoning):is([open],:popover-open,:open) *){rotate:90deg}.selection\:bg-zinc-800 ::-moz-selection{background-color:var(--color-zinc-800)}.selection\:bg-zinc-800 ::selection{background-color:var(--color-zinc-800)}.selection\:bg-zinc-800::-moz-selection{background-color:var(--color-zinc-800)}.selection\:bg-zinc-800::selection{background-color:var(--color-zinc-800)}.placeholder\:text-zinc-600::-moz-placeholder{color:var(--color-zinc-600)}.placeholder\:text-zinc-600::placeholder{color:var(--color-zinc-600)}.last\:mb-0:last-child{margin-bottom:calc(var(--spacing)*0)}.last\:border-0:last-child{border-style:var(--tw-border-style);border-width:0}@media(hover:hover){.hover\:bg-zinc-200:hover{background-color:var(--color-zinc-200)}.hover\:bg-zinc-800\/20:hover{background-color:#27272a33}@supports (color:color-mix(in lab,red,red)){.hover\:bg-zinc-800\/20:hover{background-color:color-mix(in oklab,var(--color-zinc-800)20%,transparent)}}.hover\:bg-zinc-900:hover{background-color:var(--color-zinc-900)}.hover\:text-blue-300:hover{color:var(--color-blue-300)}.hover\:text-zinc-100:hover{color:var(--color-zinc-100)}.hover\:text-zinc-400:hover{color:var(--color-zinc-400)}}.focus\:border-zinc-700:focus{border-color:var(--color-zinc-700)}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-zinc-700:focus{--tw-ring-color:var(--color-zinc-700)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:opacity-50:disabled{opacity:.5}@media(min-width:48rem){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}}:root{--background:0 0% 100%;--foreground:222.2 84% 4.9%;--card:0 0% 100%;--card-foreground:222.2 84% 4.9%;--popover:0 0% 100%;--popover-foreground:222.2 84% 4.9%;--primary:222.2 47.4% 11.2%;--primary-foreground:210 40% 98%;--secondary:210 40% 96.1%;--secondary-foreground:222.2 47.4% 11.2%;--muted:210 40% 96.1%;--muted-foreground:215.4 16.3% 46.9%;--accent:210 40% 96.1%;--accent-foreground:222.2 47.4% 11.2%;--destructive:0 84.2% 60.2%;--destructive-foreground:210 40% 98%;--border:214.3 31.8% 91.4%;--input:214.3 31.8% 91.4%;--ring:222.2 84% 4.9%;--radius:.5rem}.dark{--background:222.2 84% 4.9%;--foreground:210 40% 98%;--card:222.2 84% 4.9%;--card-foreground:210 40% 98%;--popover:222.2 84% 4.9%;--popover-foreground:210 40% 98%;--primary:210 40% 98%;--primary-foreground:222.2 47.4% 11.2%;--secondary:217.2 32.6% 17.5%;--secondary-foreground:210 40% 98%;--muted:217.2 32.6% 17.5%;--muted-foreground:215 20.2% 65.1%;--accent:217.2 32.6% 17.5%;--accent-foreground:210 40% 98%;--destructive:0 62.8% 30.6%;--destructive-foreground:210 40% 98%;--border:217.2 32.6% 17.5%;--input:217.2 32.6% 17.5%;--ring:212.7 26.8% 83.9%}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}@keyframes bounce{0%,to{animation-timing-function:cubic-bezier(.8,0,1,1);transform:translateY(-25%)}50%{animation-timing-function:cubic-bezier(0,0,.2,1);transform:none}}