@alpic-ai/ui 0.0.0-staging.dcd2ccb → 0.0.0-staging.e051bb2

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.
@@ -5,7 +5,7 @@ import * as _$class_variance_authority_types0 from "class-variance-authority/typ
5
5
 
6
6
  //#region src/components/alert.d.ts
7
7
  declare const alertVariants: (props?: ({
8
- variant?: "default" | "destructive" | "warning" | "success" | null | undefined;
8
+ variant?: "destructive" | "default" | "success" | "warning" | null | undefined;
9
9
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
10
10
  interface AlertProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof alertVariants> {}
11
11
  declare function Alert({
@@ -6,7 +6,7 @@ import * as _$class_variance_authority_types0 from "class-variance-authority/typ
6
6
 
7
7
  //#region src/components/avatar.d.ts
8
8
  declare const avatarVariants: (props?: ({
9
- size?: "xs" | "sm" | "md" | "lg" | "xl" | null | undefined;
9
+ size?: "sm" | "lg" | "xs" | "md" | "xl" | null | undefined;
10
10
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
11
11
  type AvatarSize = NonNullable<VariantProps<typeof avatarVariants>["size"]>;
12
12
  type AvatarStatus = "online";
@@ -4,7 +4,7 @@ import * as _$class_variance_authority_types0 from "class-variance-authority/typ
4
4
 
5
5
  //#region src/components/badge.d.ts
6
6
  declare const badgeVariants: (props?: ({
7
- variant?: "warning" | "success" | "secondary" | "primary" | "error" | null | undefined;
7
+ variant?: "primary" | "secondary" | "success" | "warning" | "error" | null | undefined;
8
8
  size?: "sm" | "md" | null | undefined;
9
9
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
10
10
  interface BadgeProps extends React.ComponentProps<"span">, VariantProps<typeof badgeVariants> {}
@@ -5,7 +5,7 @@ import * as _$class_variance_authority_types0 from "class-variance-authority/typ
5
5
 
6
6
  //#region src/components/button.d.ts
7
7
  declare const buttonVariants: (props?: ({
8
- variant?: "destructive" | "secondary" | "primary" | "tertiary" | "link" | "link-muted" | null | undefined;
8
+ variant?: "link" | "primary" | "secondary" | "tertiary" | "link-muted" | "destructive" | null | undefined;
9
9
  size?: "default" | "icon" | "icon-rounded" | "pill" | null | undefined;
10
10
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
11
11
  interface ButtonProps extends React.ComponentProps<"button">, VariantProps<typeof buttonVariants> {
@@ -23,7 +23,7 @@ declare function DropdownMenuGroup({
23
23
  ...props
24
24
  }: React.ComponentProps<typeof DropdownMenuPrimitive.Group>): _$react_jsx_runtime0.JSX.Element;
25
25
  declare const dropdownMenuItemVariants: (props?: ({
26
- variant?: "default" | "destructive" | null | undefined;
26
+ variant?: "destructive" | "default" | null | undefined;
27
27
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
28
28
  declare function DropdownMenuItem({
29
29
  className,
@@ -6,7 +6,6 @@ import { Separator } from "./separator.mjs";
6
6
  import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from "./sheet.mjs";
7
7
  import { useIsMobile } from "../hooks/use-mobile.mjs";
8
8
  import { Skeleton } from "./skeleton.mjs";
9
- import { PanelLeftClose, PanelLeftOpen } from "lucide-react";
10
9
  import { jsx, jsxs } from "react/jsx-runtime";
11
10
  import { cva } from "class-variance-authority";
12
11
  import * as React from "react";
@@ -132,8 +131,7 @@ function Sidebar({ side = "left", variant = "sidebar", collapsible = "offcanvas"
132
131
  });
133
132
  }
134
133
  function SidebarTrigger({ className, onClick, ...props }) {
135
- const { state, isMobile, openMobile, toggleSidebar } = useSidebar();
136
- const isOpen = isMobile ? openMobile : state === "expanded";
134
+ const { toggleSidebar } = useSidebar();
137
135
  return /* @__PURE__ */ jsxs(Button, {
138
136
  "data-sidebar": "trigger",
139
137
  "data-slot": "sidebar-trigger",
@@ -145,12 +143,35 @@ function SidebarTrigger({ className, onClick, ...props }) {
145
143
  toggleSidebar();
146
144
  },
147
145
  ...props,
148
- children: [isOpen ? /* @__PURE__ */ jsx(PanelLeftClose, { className: "size-4.5" }) : /* @__PURE__ */ jsx(PanelLeftOpen, { className: "size-4.5" }), /* @__PURE__ */ jsx("span", {
146
+ children: [/* @__PURE__ */ jsx(SidebarToggleIcon, { className: "size-4.5" }), /* @__PURE__ */ jsx("span", {
149
147
  className: "sr-only",
150
148
  children: "Toggle Sidebar"
151
149
  })]
152
150
  });
153
151
  }
152
+ function SidebarToggleIcon({ className, ...props }) {
153
+ return /* @__PURE__ */ jsxs("svg", {
154
+ viewBox: "0 0 20 20",
155
+ fill: "none",
156
+ "aria-hidden": "true",
157
+ className,
158
+ ...props,
159
+ children: [/* @__PURE__ */ jsx("rect", {
160
+ x: "2.75",
161
+ y: "2.75",
162
+ width: "14.5",
163
+ height: "14.5",
164
+ rx: "4",
165
+ stroke: "currentColor",
166
+ strokeWidth: "1.5"
167
+ }), /* @__PURE__ */ jsx("path", {
168
+ d: "M10 4.75V15.25",
169
+ stroke: "currentColor",
170
+ strokeWidth: "1.5",
171
+ strokeLinecap: "round"
172
+ })]
173
+ });
174
+ }
154
175
  function SidebarRail({ className, ...props }) {
155
176
  const { toggleSidebar } = useSidebar();
156
177
  return /* @__PURE__ */ jsx("button", {
@@ -182,22 +203,16 @@ function SidebarHeader({ className, icon, title, children, ...props }) {
182
203
  return /* @__PURE__ */ jsxs("div", {
183
204
  "data-slot": "sidebar-header",
184
205
  "data-sidebar": "header",
185
- className: cn("flex flex-col gap-2 p-2 group-data-[collapsible=icon]:items-center", className),
206
+ className: cn("flex flex-col gap-2 p-2", className),
186
207
  ...props,
187
208
  children: [/* @__PURE__ */ jsxs("div", {
188
- className: "flex h-8 items-center gap-2 px-2 group-data-[collapsible=icon]:justify-center group-data-[collapsible=icon]:gap-0 group-data-[collapsible=icon]:px-0",
209
+ className: "flex h-8 items-center gap-2 px-3",
189
210
  children: [
190
- /* @__PURE__ */ jsxs("div", {
191
- className: "relative shrink-0",
192
- children: [/* @__PURE__ */ jsx("span", {
193
- className: "transition-opacity group-data-[collapsible=icon]:group-hover:opacity-0",
194
- children: icon
195
- }), /* @__PURE__ */ jsx("div", {
196
- className: "absolute inset-0 flex items-center justify-center opacity-0 transition-opacity group-data-[collapsible=icon]:group-hover:opacity-100",
197
- children: /* @__PURE__ */ jsx(SidebarTrigger, { className: "!size-4 !p-0" })
198
- })]
211
+ /* @__PURE__ */ jsx("div", {
212
+ className: "shrink-0",
213
+ children: icon
199
214
  }),
200
- title && /* @__PURE__ */ jsx("span", {
215
+ /* @__PURE__ */ jsx("span", {
201
216
  className: "text-foreground text-md min-w-0 truncate font-medium group-data-[collapsible=icon]:hidden",
202
217
  children: title
203
218
  }),
@@ -232,7 +247,7 @@ function SidebarGroup({ className, ...props }) {
232
247
  return /* @__PURE__ */ jsx("div", {
233
248
  "data-slot": "sidebar-group",
234
249
  "data-sidebar": "group",
235
- className: cn("relative flex w-full min-w-0 flex-col p-2", className),
250
+ className: cn("relative flex w-full min-w-0 flex-col", className),
236
251
  ...props
237
252
  });
238
253
  }
@@ -272,7 +287,7 @@ function SidebarMenuItem({ className, ...props }) {
272
287
  return /* @__PURE__ */ jsx("li", {
273
288
  "data-slot": "sidebar-menu-item",
274
289
  "data-sidebar": "menu-item",
275
- className: cn("group/menu-item relative", className),
290
+ className: cn("group/menu-item relative px-3", className),
276
291
  ...props
277
292
  });
278
293
  }
@@ -4,7 +4,7 @@ import * as _$class_variance_authority_types0 from "class-variance-authority/typ
4
4
 
5
5
  //#region src/components/skeleton.d.ts
6
6
  declare const skeletonVariants: (props?: ({
7
- shape?: "rectangle" | "circle" | null | undefined;
7
+ shape?: "circle" | "rectangle" | null | undefined;
8
8
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
9
9
  interface SkeletonProps extends React.ComponentProps<"div">, VariantProps<typeof skeletonVariants> {}
10
10
  declare function Skeleton({
@@ -4,8 +4,8 @@ import * as _$class_variance_authority_types0 from "class-variance-authority/typ
4
4
 
5
5
  //#region src/components/spinner.d.ts
6
6
  declare const spinnerVariants: (props?: ({
7
- variant?: "secondary" | "primary" | null | undefined;
8
- size?: "sm" | "md" | "lg" | "xl" | null | undefined;
7
+ variant?: "primary" | "secondary" | null | undefined;
8
+ size?: "sm" | "lg" | "md" | "xl" | null | undefined;
9
9
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
10
10
  interface SpinnerProps extends Omit<React.ComponentProps<"svg">, "children">, VariantProps<typeof spinnerVariants> {}
11
11
  declare function Spinner({
@@ -4,7 +4,7 @@ import * as _$class_variance_authority_types0 from "class-variance-authority/typ
4
4
 
5
5
  //#region src/components/status-dot.d.ts
6
6
  declare const statusDotVariants: (props?: ({
7
- variant?: "destructive" | "warning" | "success" | "muted" | null | undefined;
7
+ variant?: "destructive" | "success" | "warning" | "muted" | null | undefined;
8
8
  pulse?: boolean | null | undefined;
9
9
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
10
10
  interface StatusDotProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof statusDotVariants> {}
@@ -6,7 +6,7 @@ import * as _$class_variance_authority_types0 from "class-variance-authority/typ
6
6
 
7
7
  //#region src/components/tabs.d.ts
8
8
  declare const tabsTriggerVariants: (props?: ({
9
- variant?: "default" | "pill" | "line" | null | undefined;
9
+ variant?: "line" | "default" | "pill" | null | undefined;
10
10
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
11
11
  declare function Tabs({
12
12
  className,
@@ -14,7 +14,7 @@ declare function Tabs({
14
14
  ...props
15
15
  }: React.ComponentProps<typeof TabsPrimitive.Root>): _$react_jsx_runtime0.JSX.Element;
16
16
  declare const tabsListVariants: (props?: ({
17
- variant?: "default" | "line" | null | undefined;
17
+ variant?: "line" | "default" | null | undefined;
18
18
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
19
19
  declare function TabsList({
20
20
  className,
@@ -0,0 +1,34 @@
1
+ import * as _$react_jsx_runtime0 from "react/jsx-runtime";
2
+ import { ReactNode } from "react";
3
+
4
+ //#region src/components/typography.d.ts
5
+ declare function H1({
6
+ children,
7
+ className
8
+ }: {
9
+ children: ReactNode;
10
+ className?: string;
11
+ }): _$react_jsx_runtime0.JSX.Element;
12
+ declare function H2({
13
+ children,
14
+ className
15
+ }: {
16
+ children: ReactNode;
17
+ className?: string;
18
+ }): _$react_jsx_runtime0.JSX.Element;
19
+ declare function H3({
20
+ children,
21
+ className
22
+ }: {
23
+ children: ReactNode;
24
+ className?: string;
25
+ }): _$react_jsx_runtime0.JSX.Element;
26
+ declare function H4({
27
+ children,
28
+ className
29
+ }: {
30
+ children: ReactNode;
31
+ className?: string;
32
+ }): _$react_jsx_runtime0.JSX.Element;
33
+ //#endregion
34
+ export { H1, H2, H3, H4 };
@@ -0,0 +1,29 @@
1
+ import { cn } from "../lib/cn.mjs";
2
+ import { jsx } from "react/jsx-runtime";
3
+ //#region src/components/typography.tsx
4
+ function H1({ children, className }) {
5
+ return /* @__PURE__ */ jsx("h1", {
6
+ className: cn("scroll-m-20 type-display-sm font-bold", className),
7
+ children
8
+ });
9
+ }
10
+ function H2({ children, className }) {
11
+ return /* @__PURE__ */ jsx("h2", {
12
+ className: cn("scroll-m-20 type-display-xs font-semibold", className),
13
+ children
14
+ });
15
+ }
16
+ function H3({ children, className }) {
17
+ return /* @__PURE__ */ jsx("h3", {
18
+ className: cn("scroll-m-20 type-text-lg font-semibold", className),
19
+ children
20
+ });
21
+ }
22
+ function H4({ children, className }) {
23
+ return /* @__PURE__ */ jsx("h4", {
24
+ className: cn("scroll-m-20 type-text-md font-semibold", className),
25
+ children
26
+ });
27
+ }
28
+ //#endregion
29
+ export { H1, H2, H3, H4 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alpic-ai/ui",
3
- "version": "0.0.0-staging.dcd2ccb",
3
+ "version": "0.0.0-staging.e051bb2",
4
4
  "description": "Alpic design system — shared UI components",
5
5
  "type": "module",
6
6
  "exports": {
@@ -23,13 +23,13 @@
23
23
  "src"
24
24
  ],
25
25
  "peerDependencies": {
26
- "lucide-react": "^1.0.0",
27
- "react": "^19.0.0",
28
- "react-dom": "^19.0.0",
26
+ "lucide-react": "^1.8.0",
27
+ "react": "^19.2.5",
28
+ "react-dom": "^19.2.5",
29
29
  "react-hook-form": "^7.72.1",
30
- "sonner": "^2.0.0",
31
- "tailwindcss": "^4.0.0",
32
- "tw-animate-css": "^1.0.0"
30
+ "sonner": "^2.0.7",
31
+ "tailwindcss": "^4.2.2",
32
+ "tw-animate-css": "^1.4.0"
33
33
  },
34
34
  "dependencies": {
35
35
  "@radix-ui/react-accordion": "^1.2.12",
@@ -59,14 +59,14 @@
59
59
  "@tailwindcss/postcss": "^4.2.2",
60
60
  "@types/react": "19.2.14",
61
61
  "@types/react-dom": "19.2.3",
62
- "lucide-react": "^1.7.0",
62
+ "lucide-react": "^1.8.0",
63
63
  "react-hook-form": "^7.72.1",
64
64
  "shx": "^0.4.0",
65
65
  "sonner": "^2.0.7",
66
66
  "tailwindcss": "^4.2.2",
67
- "tsdown": "^0.21.7",
67
+ "tsdown": "^0.21.9",
68
68
  "tw-animate-css": "^1.4.0",
69
- "typescript": "^6.0.2"
69
+ "typescript": "^6.0.3"
70
70
  },
71
71
  "scripts": {
72
72
  "build": "shx rm -rf dist && tsdown",
@@ -2,7 +2,6 @@
2
2
 
3
3
  import { Slot } from "@radix-ui/react-slot";
4
4
  import { cva, type VariantProps } from "class-variance-authority";
5
- import { PanelLeftClose, PanelLeftOpen } from "lucide-react";
6
5
  import * as React from "react";
7
6
 
8
7
  import { useIsMobile } from "../hooks/use-mobile";
@@ -231,9 +230,7 @@ function Sidebar({
231
230
  }
232
231
 
233
232
  function SidebarTrigger({ className, onClick, ...props }: React.ComponentProps<typeof Button>) {
234
- const { state, isMobile, openMobile, toggleSidebar } = useSidebar();
235
-
236
- const isOpen = isMobile ? openMobile : state === "expanded";
233
+ const { toggleSidebar } = useSidebar();
237
234
 
238
235
  return (
239
236
  <Button
@@ -248,12 +245,21 @@ function SidebarTrigger({ className, onClick, ...props }: React.ComponentProps<t
248
245
  }}
249
246
  {...props}
250
247
  >
251
- {isOpen ? <PanelLeftClose className="size-4.5" /> : <PanelLeftOpen className="size-4.5" />}
248
+ <SidebarToggleIcon className="size-4.5" />
252
249
  <span className="sr-only">Toggle Sidebar</span>
253
250
  </Button>
254
251
  );
255
252
  }
256
253
 
254
+ function SidebarToggleIcon({ className, ...props }: React.ComponentProps<"svg">) {
255
+ return (
256
+ <svg viewBox="0 0 20 20" fill="none" aria-hidden="true" className={className} {...props}>
257
+ <rect x="2.75" y="2.75" width="14.5" height="14.5" rx="4" stroke="currentColor" strokeWidth="1.5" />
258
+ <path d="M10 4.75V15.25" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />
259
+ </svg>
260
+ );
261
+ }
262
+
257
263
  function SidebarRail({ className, ...props }: React.ComponentProps<"button">) {
258
264
  const { toggleSidebar } = useSidebar();
259
265
 
@@ -316,21 +322,14 @@ function SidebarHeader({ className, icon, title, children, ...props }: SidebarHe
316
322
  <div
317
323
  data-slot="sidebar-header"
318
324
  data-sidebar="header"
319
- className={cn("flex flex-col gap-2 p-2 group-data-[collapsible=icon]:items-center", className)}
325
+ className={cn("flex flex-col gap-2 p-2", className)}
320
326
  {...props}
321
327
  >
322
- <div className="flex h-8 items-center gap-2 px-2 group-data-[collapsible=icon]:justify-center group-data-[collapsible=icon]:gap-0 group-data-[collapsible=icon]:px-0">
323
- <div className="relative shrink-0">
324
- <span className="transition-opacity group-data-[collapsible=icon]:group-hover:opacity-0">{icon}</span>
325
- <div className="absolute inset-0 flex items-center justify-center opacity-0 transition-opacity group-data-[collapsible=icon]:group-hover:opacity-100">
326
- <SidebarTrigger className="!size-4 !p-0" />
327
- </div>
328
- </div>
329
- {title && (
330
- <span className="text-foreground text-md min-w-0 truncate font-medium group-data-[collapsible=icon]:hidden">
331
- {title}
332
- </span>
333
- )}
328
+ <div className="flex h-8 items-center gap-2 px-3">
329
+ <div className="shrink-0">{icon}</div>
330
+ <span className="text-foreground text-md min-w-0 truncate font-medium group-data-[collapsible=icon]:hidden">
331
+ {title}
332
+ </span>
334
333
  <SidebarTrigger className="ml-auto shrink-0 group-data-[collapsible=icon]:hidden" />
335
334
  </div>
336
335
  {children}
@@ -376,7 +375,7 @@ function SidebarGroup({ className, ...props }: React.ComponentProps<"div">) {
376
375
  <div
377
376
  data-slot="sidebar-group"
378
377
  data-sidebar="group"
379
- className={cn("relative flex w-full min-w-0 flex-col p-2", className)}
378
+ className={cn("relative flex w-full min-w-0 flex-col", className)}
380
379
  {...props}
381
380
  />
382
381
  );
@@ -453,7 +452,7 @@ function SidebarMenuItem({ className, ...props }: React.ComponentProps<"li">) {
453
452
  <li
454
453
  data-slot="sidebar-menu-item"
455
454
  data-sidebar="menu-item"
456
- className={cn("group/menu-item relative", className)}
455
+ className={cn("group/menu-item relative px-3", className)}
457
456
  {...props}
458
457
  />
459
458
  );
@@ -0,0 +1,19 @@
1
+ import type { ReactNode } from "react";
2
+
3
+ import { cn } from "../lib/cn";
4
+
5
+ export function H1({ children, className }: { children: ReactNode; className?: string }) {
6
+ return <h1 className={cn("scroll-m-20 type-display-sm font-bold", className)}>{children}</h1>;
7
+ }
8
+
9
+ export function H2({ children, className }: { children: ReactNode; className?: string }) {
10
+ return <h2 className={cn("scroll-m-20 type-display-xs font-semibold", className)}>{children}</h2>;
11
+ }
12
+
13
+ export function H3({ children, className }: { children: ReactNode; className?: string }) {
14
+ return <h3 className={cn("scroll-m-20 type-text-lg font-semibold", className)}>{children}</h3>;
15
+ }
16
+
17
+ export function H4({ children, className }: { children: ReactNode; className?: string }) {
18
+ return <h4 className={cn("scroll-m-20 type-text-md font-semibold", className)}>{children}</h4>;
19
+ }
@@ -62,7 +62,7 @@ export const AllVariants: Story = () => (
62
62
  <Sidebar collapsible="icon">
63
63
  <TeamHeader />
64
64
  <SidebarContent>
65
- <SidebarGroup className="px-3">
65
+ <SidebarGroup>
66
66
  <SidebarGroupContent>
67
67
  <SidebarMenu>
68
68
  <SidebarMenuItem>
@@ -118,7 +118,7 @@ export const AllVariants: Story = () => (
118
118
  <Sidebar collapsible="icon">
119
119
  <TeamHeader />
120
120
  <SidebarContent>
121
- <SidebarGroup className="px-3">
121
+ <SidebarGroup>
122
122
  <SidebarGroupLabel>Workspace</SidebarGroupLabel>
123
123
  <SidebarGroupContent>
124
124
  <SidebarMenu>
@@ -146,7 +146,7 @@ export const AllVariants: Story = () => (
146
146
  </SidebarGroupContent>
147
147
  </SidebarGroup>
148
148
  <SidebarSeparator />
149
- <SidebarGroup className="px-3">
149
+ <SidebarGroup>
150
150
  <SidebarGroupLabel>Account</SidebarGroupLabel>
151
151
  <SidebarGroupContent>
152
152
  <SidebarMenu>
@@ -180,7 +180,7 @@ export const AllVariants: Story = () => (
180
180
  <Sidebar collapsible="icon">
181
181
  <TeamHeader />
182
182
  <SidebarContent>
183
- <SidebarGroup className="px-3">
183
+ <SidebarGroup>
184
184
  <SidebarGroupContent>
185
185
  <SidebarMenu>
186
186
  {["skeleton-1", "skeleton-2", "skeleton-3", "skeleton-4", "skeleton-5"].map((key) => (
@@ -214,7 +214,7 @@ export const AllVariants: Story = () => (
214
214
  </div>
215
215
  </SidebarHeader>
216
216
  <SidebarContent>
217
- <SidebarGroup className="px-3">
217
+ <SidebarGroup>
218
218
  <SidebarGroupContent>
219
219
  <SidebarMenu>
220
220
  <SidebarMenuItem>
@@ -106,6 +106,8 @@
106
106
  /* animations */
107
107
  --animate-accordion-down: accordion-down 200ms ease-out;
108
108
  --animate-accordion-up: accordion-up 200ms ease-out;
109
+ --animate-beacon-ring-core: beacon-ring-core 2.2s ease-in-out infinite;
110
+ --animate-beacon-ring-pulse: beacon-ring-pulse 2.2s ease-in-out infinite;
109
111
  }
110
112
 
111
113
  @keyframes accordion-down {
@@ -126,6 +128,32 @@
126
128
  }
127
129
  }
128
130
 
131
+ @keyframes beacon-ring-core {
132
+ 0%,
133
+ 100% {
134
+ opacity: 0.55;
135
+ transform: scale(0.98);
136
+ }
137
+ 50% {
138
+ opacity: 0.85;
139
+ transform: scale(1.02);
140
+ }
141
+ }
142
+
143
+ @keyframes beacon-ring-pulse {
144
+ 0%,
145
+ 100% {
146
+ opacity: 0.88;
147
+ transform: scale(1);
148
+ filter: drop-shadow(0 0 0 rgba(59, 130, 246, 0));
149
+ }
150
+ 50% {
151
+ opacity: 1;
152
+ transform: scale(1.02);
153
+ filter: drop-shadow(0 0 8px rgba(59, 130, 246, 0.24));
154
+ }
155
+ }
156
+
129
157
  /* ─── Dark mode ───────────────────────────────────────────────────────────── */
130
158
 
131
159
  .dark {