@import "tailwindcss"; @import "tw-animate-css"; @import "shadcn/tailwind.css"; @custom-variant dark (&:is(.dark *)); @theme inline { --font-heading: var(--font-display); --font-sans: var(--font-sans); --font-mono: var(--font-mono); --color-sidebar-ring: var(--sidebar-ring); --color-sidebar-border: var(--sidebar-border); --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); --color-sidebar-accent: var(--sidebar-accent); --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); --color-sidebar-primary: var(--sidebar-primary); --color-sidebar-foreground: var(--sidebar-foreground); --color-sidebar: var(--sidebar); --color-chart-5: var(--chart-5); --color-chart-4: var(--chart-4); --color-chart-3: var(--chart-3); --color-chart-2: var(--chart-2); --color-chart-1: var(--chart-1); --color-ring: var(--ring); --color-input: var(--input); --color-border: var(--border); --color-destructive: var(--destructive); --color-accent-foreground: var(--accent-foreground); --color-accent: var(--accent); --color-muted-foreground: var(--muted-foreground); --color-muted: var(--muted); --color-secondary-foreground: var(--secondary-foreground); --color-secondary: var(--secondary); --color-primary-foreground: var(--primary-foreground); --color-primary: var(--primary); --color-popover-foreground: var(--popover-foreground); --color-popover: var(--popover); --color-card-foreground: var(--card-foreground); --color-card: var(--card); --color-foreground: var(--foreground); --color-background: var(--background); --radius-sm: calc(var(--radius) * 0.6); --radius-md: calc(var(--radius) * 0.8); --radius-lg: var(--radius); --radius-xl: calc(var(--radius) * 1.4); --radius-2xl: calc(var(--radius) * 1.8); --radius-3xl: calc(var(--radius) * 2.2); --radius-4xl: calc(var(--radius) * 2.6); } /* * Modern pink -> purple -> blue palette (the app's signature sweep, also * used in app/icon.svg / BrandMark). Dark cool near-black base with a vivid * pink primary; violet/blue fill out charts and the wordmark/icon gradient. */ :root { --background: #f5f3fb; --foreground: #1f1b2e; --card: #ffffff; --card-foreground: #1f1b2e; --popover: #ffffff; --popover-foreground: #1f1b2e; --primary: #db2777; --primary-foreground: #ffffff; --secondary: #ede9fe; --secondary-foreground: #3a2d54; --muted: #efeafd; --muted-foreground: #6b6280; --accent: #ede4fb; --accent-foreground: #4c1d95; --destructive: #dc2626; --border: #e4defa; --input: #e4defa; --ring: #db2777; --chart-1: #db2777; --chart-2: #9333ea; --chart-3: #7c3aed; --chart-4: #2563eb; --chart-5: #0284c7; --radius: 0.75rem; --sidebar: #ede9fe; --sidebar-foreground: #1f1b2e; --sidebar-primary: #db2777; --sidebar-primary-foreground: #ffffff; --sidebar-accent: #ede4fb; --sidebar-accent-foreground: #4c1d95; --sidebar-border: #e4defa; --sidebar-ring: #db2777; } .dark { --background: #15131f; --foreground: #f2f0f7; --card: #1f1b2c; --card-foreground: #f2f0f7; --popover: #1c1829; --popover-foreground: #f2f0f7; --primary: #ec4899; --primary-foreground: #ffffff; --secondary: #2a2440; --secondary-foreground: #e5e1f0; --muted: #272138; --muted-foreground: #a79fc0; --accent: #3a2d54; --accent-foreground: #efeaff; --destructive: #ef4444; --border: color-mix(in srgb, #a78bfa 25%, transparent); --input: color-mix(in srgb, #a78bfa 18%, transparent); --ring: #ec4899; --chart-1: #f472b6; --chart-2: #c084fc; --chart-3: #a78bfa; --chart-4: #60a5fa; --chart-5: #38bdf8; --sidebar: #1c1829; --sidebar-foreground: #f2f0f7; --sidebar-primary: #ec4899; --sidebar-primary-foreground: #ffffff; --sidebar-accent: #3a2d54; --sidebar-accent-foreground: #efeaff; --sidebar-border: color-mix(in srgb, #a78bfa 25%, transparent); --sidebar-ring: #ec4899; } @layer base { * { @apply border-border outline-ring/50; } body { @apply text-foreground; } html { @apply font-sans; } } /* Animated signature-sweep background - sits behind everything; cards use .bp-glass (translucent + blurred) so it shines through instead of being fully hidden behind an opaque card surface. */ body { background-color: var(--background); background-image: radial-gradient(ellipse 80% 60% at 15% 10%, color-mix(in srgb, #ff6fb0 32%, transparent), transparent 60%), radial-gradient(ellipse 70% 60% at 85% 25%, color-mix(in srgb, #4f7fe0 28%, transparent), transparent 60%), radial-gradient(ellipse 75% 65% at 50% 100%, color-mix(in srgb, #b34bde 30%, transparent), transparent 60%); background-repeat: no-repeat; background-size: 140% 140%; background-attachment: fixed; animation: bp-bg-drift 24s ease-in-out infinite; } @keyframes bp-bg-drift { 0% { background-position: 0% 0%, 100% 0%, 50% 100%; } 50% { background-position: 20% 20%, 80% 30%, 60% 80%; } 100% { background-position: 0% 0%, 100% 0%, 50% 100%; } } @media (prefers-reduced-motion: reduce) { body { animation: none; } } /* Signature pink -> purple -> blue sweep (matches app/icon.svg), used for the wordmark and one hero moment - not smeared across every surface. */ .bp-gradient-text { background: linear-gradient(100deg, #ff6fb0, #b34bde 50%, #4f7fe0); background-clip: text; -webkit-background-clip: text; color: transparent; } .bp-gradient-ring { background: linear-gradient(135deg, #ff6fb0, #b34bde 50%, #4f7fe0); } /* Console-module surface: translucent + blurred so the animated background sweep shines through, with a hairline border and soft inset top highlight. */ .bp-glass { background: color-mix(in srgb, var(--card) 55%, transparent); backdrop-filter: blur(20px) saturate(150%); border: 1px solid var(--border); box-shadow: inset 0 1px 0 color-mix(in srgb, var(--foreground) 8%, transparent); transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease; } .bp-glass:hover { background: color-mix(in srgb, var(--card) 62%, transparent); border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); box-shadow: inset 0 1px 0 color-mix(in srgb, var(--foreground) 10%, transparent), 0 10px 30px -14px rgba(0, 0, 0, 0.45); } /* Illuminated indicator dot - reused on connection status and per-actuator transmit indicators. */ .bp-led { display: inline-block; width: 0.5rem; height: 0.5rem; border-radius: 999px; background: var(--muted-foreground); } .bp-led[data-on="true"] { background: var(--primary); } /* Header connection indicator: state-driven color, distinct from the transmit-dot's boolean data-on above. */ .bp-led[data-state="scanning"] { background: var(--muted-foreground); } .bp-led[data-state="connected"] { background: var(--primary); } .bp-led[data-state="recording"] { background: var(--destructive); } /* Thin panel seam - a hardware "trim line," not a plain UI divider. */ .bp-hairline { height: 1px; background: color-mix(in srgb, #a78bfa 35%, transparent); } /* Instrument-readout numerals: tabular mono for actuator %, timers, stats. */ .bp-readout { font-family: var(--font-mono); font-variant-numeric: tabular-nums; letter-spacing: 0.01em; } /* BrandMark's animated variant (dashboard hero): the heart glyph beats, the EKG-style curve glows in the primary accent instead of plain white. */ @keyframes bp-mark-heartbeat { 0%, 100% { opacity: 0.22; transform: scale(1); } 50% { opacity: 0.75; transform: scale(1.1); } } .bp-mark-heart { transform-box: fill-box; transform-origin: center; animation: bp-mark-heartbeat 1.8s ease-in-out infinite; } @keyframes bp-mark-curve-glow { 0%, 100% { filter: drop-shadow(0 0 1px color-mix(in srgb, var(--primary) 50%, transparent)); } 50% { filter: drop-shadow(0 0 5px color-mix(in srgb, var(--primary) 100%, transparent)) drop-shadow(0 0 10px color-mix(in srgb, var(--primary) 70%, transparent)); } } .bp-mark-curve { stroke: #fff; animation: bp-mark-curve-glow 1.8s ease-in-out infinite; } @media (prefers-reduced-motion: reduce) { .bp-mark-heart, .bp-mark-curve { animation: none; } } @keyframes bp-pulse-glow { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--bp-pulse-color, var(--primary)) 55%, transparent); } 50% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--bp-pulse-color, var(--primary)) 0%, transparent); } } .bp-pulse { animation: bp-pulse-glow 2s ease-in-out infinite; } .bp-led[data-state="scanning"] { --bp-pulse-color: var(--muted-foreground); } .bp-led[data-state="recording"] { --bp-pulse-color: var(--destructive); } @media (prefers-reduced-motion: reduce) { .bp-pulse { animation: none; } }