From 6f9d81ca681f6f6270b45e3dfe223f8e0d40efce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=91=A3=E5=AE=8F=E5=87=AF?= Date: Sat, 23 May 2026 17:43:46 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend-web/src/components/ui/sidebar.tsx | 338 ++-- frontend-web/src/styles/globals.css | 1640 +++++++++--------- offline-backend-20260512/backend/config.yaml | 2 +- offline-backend-20260512/config.yaml | 2 +- 4 files changed, 991 insertions(+), 991 deletions(-) diff --git a/frontend-web/src/components/ui/sidebar.tsx b/frontend-web/src/components/ui/sidebar.tsx index f6c5e3e4..f544abf3 100644 --- a/frontend-web/src/components/ui/sidebar.tsx +++ b/frontend-web/src/components/ui/sidebar.tsx @@ -397,53 +397,53 @@ function SidebarGroup({ className, ...props }: React.ComponentProps<"div">) { ); } -const SidebarGroupLabel = React.forwardRef< - HTMLDivElement, - React.ComponentProps<"div"> & { asChild?: boolean } ->(({ className, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "div"; - - return ( - svg]:size-4 [&>svg]:shrink-0", - "group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0", - className, - )} - {...props} - /> - ); -}); - -SidebarGroupLabel.displayName = "SidebarGroupLabel"; +const SidebarGroupLabel = React.forwardRef< + HTMLDivElement, + React.ComponentProps<"div"> & { asChild?: boolean } +>(({ className, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "div"; -const SidebarGroupAction = React.forwardRef< - HTMLButtonElement, - React.ComponentProps<"button"> & { asChild?: boolean } ->(({ className, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button"; - - return ( - svg]:size-4 [&>svg]:shrink-0", - // Increases the hit area of the button on mobile. - "after:absolute after:-inset-2 md:after:hidden", - "group-data-[collapsible=icon]:hidden", - className, - )} - {...props} - /> - ); -}); - -SidebarGroupAction.displayName = "SidebarGroupAction"; + return ( + svg]:size-4 [&>svg]:shrink-0", + "group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0", + className, + )} + {...props} + /> + ); +}); + +SidebarGroupLabel.displayName = "SidebarGroupLabel"; + +const SidebarGroupAction = React.forwardRef< + HTMLButtonElement, + React.ComponentProps<"button"> & { asChild?: boolean } +>(({ className, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button"; + + return ( + svg]:size-4 [&>svg]:shrink-0", + // Increases the hit area of the button on mobile. + "after:absolute after:-inset-2 md:after:hidden", + "group-data-[collapsible=icon]:hidden", + className, + )} + {...props} + /> + ); +}); + +SidebarGroupAction.displayName = "SidebarGroupAction"; function SidebarGroupContent({ className, @@ -503,99 +503,99 @@ const sidebarMenuButtonVariants = cva( }, ); -const SidebarMenuButton = React.forwardRef< - HTMLButtonElement, - React.ComponentProps<"button"> & { - asChild?: boolean; - isActive?: boolean; - tooltip?: string | React.ComponentProps; - } & VariantProps ->( - ( - { - asChild = false, - isActive = false, - variant = "default", - size = "default", - tooltip, - className, - ...props - }, - ref, - ) => { - const Comp = asChild ? Slot : "button"; - const { isMobile, state } = useSidebar(); - - const button = ( - - ); - - if (!tooltip) { - return button; - } - - if (typeof tooltip === "string") { - tooltip = { - children: tooltip, - }; - } - - return ( - - {button} - - ); - }, -); - -SidebarMenuButton.displayName = "SidebarMenuButton"; +const SidebarMenuButton = React.forwardRef< + HTMLButtonElement, + React.ComponentProps<"button"> & { + asChild?: boolean; + isActive?: boolean; + tooltip?: string | React.ComponentProps; + } & VariantProps +>( + ( + { + asChild = false, + isActive = false, + variant = "default", + size = "default", + tooltip, + className, + ...props + }, + ref, + ) => { + const Comp = asChild ? Slot : "button"; + const { isMobile, state } = useSidebar(); -const SidebarMenuAction = React.forwardRef< - HTMLButtonElement, - React.ComponentProps<"button"> & { - asChild?: boolean; - showOnHover?: boolean; - } ->(({ className, asChild = false, showOnHover = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button"; - - return ( - svg]:size-4 [&>svg]:shrink-0", - // Increases the hit area of the button on mobile. - "after:absolute after:-inset-2 md:after:hidden", - "peer-data-[size=sm]/menu-button:top-1", - "peer-data-[size=default]/menu-button:top-1.5", - "peer-data-[size=lg]/menu-button:top-2.5", - "group-data-[collapsible=icon]:hidden", - showOnHover && - "peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0", - className, - )} - {...props} - /> - ); -}); - -SidebarMenuAction.displayName = "SidebarMenuAction"; + const button = ( + + ); + + if (!tooltip) { + return button; + } + + if (typeof tooltip === "string") { + tooltip = { + children: tooltip, + }; + } + + return ( + + {button} + + ); + }, +); + +SidebarMenuButton.displayName = "SidebarMenuButton"; + +const SidebarMenuAction = React.forwardRef< + HTMLButtonElement, + React.ComponentProps<"button"> & { + asChild?: boolean; + showOnHover?: boolean; + } +>(({ className, asChild = false, showOnHover = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button"; + + return ( + svg]:size-4 [&>svg]:shrink-0", + // Increases the hit area of the button on mobile. + "after:absolute after:-inset-2 md:after:hidden", + "peer-data-[size=sm]/menu-button:top-1", + "peer-data-[size=default]/menu-button:top-1.5", + "peer-data-[size=lg]/menu-button:top-2.5", + "group-data-[collapsible=icon]:hidden", + showOnHover && + "peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0", + className, + )} + {...props} + /> + ); +}); + +SidebarMenuAction.displayName = "SidebarMenuAction"; function SidebarMenuBadge({ className, @@ -686,37 +686,37 @@ function SidebarMenuSubItem({ ); } -const SidebarMenuSubButton = React.forwardRef< - HTMLAnchorElement, - React.ComponentProps<"a"> & { - asChild?: boolean; - size?: "sm" | "md"; - isActive?: boolean; - } ->(({ asChild = false, size = "md", isActive = false, className, ...props }, ref) => { - const Comp = asChild ? Slot : "a"; - - return ( - svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-hidden focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", - "data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground", - size === "sm" && "text-xs", - size === "md" && "text-sm", - "group-data-[collapsible=icon]:hidden", - className, - )} - {...props} - /> - ); -}); - -SidebarMenuSubButton.displayName = "SidebarMenuSubButton"; +const SidebarMenuSubButton = React.forwardRef< + HTMLAnchorElement, + React.ComponentProps<"a"> & { + asChild?: boolean; + size?: "sm" | "md"; + isActive?: boolean; + } +>(({ asChild = false, size = "md", isActive = false, className, ...props }, ref) => { + const Comp = asChild ? Slot : "a"; + + return ( + svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-hidden focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", + "data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground", + size === "sm" && "text-xs", + size === "md" && "text-sm", + "group-data-[collapsible=icon]:hidden", + className, + )} + {...props} + /> + ); +}); + +SidebarMenuSubButton.displayName = "SidebarMenuSubButton"; export { Sidebar, diff --git a/frontend-web/src/styles/globals.css b/frontend-web/src/styles/globals.css index 52db6193..3e08cac3 100644 --- a/frontend-web/src/styles/globals.css +++ b/frontend-web/src/styles/globals.css @@ -1,821 +1,821 @@ -@import "tailwindcss"; -@import "tw-animate-css"; - -@source "../node_modules/streamdown/dist/index.js"; - -/* Heading */ -@source inline("text-{xs,sm,base,lg,xl,2xl,3xl,4xl,5xl,6xl}"); -@source inline("font-{normal,medium,semibold,bold,extrabold}"); -@source inline("leading-{none,tight,snug,normal,relaxed,loose}"); - -/* Spacing */ -@source inline("m{t,b,l,r,x,y}-{0,1,2,3,4,5,6,8,10,12,16,20,24}"); -@source inline("p{t,b,l,r,x,y}-{0,1,2,3,4,5,6,8,10,12,16,20,24}"); -@source inline("space-{x,y}-{1,2,3,4,5,6,8}"); - -/* List */ -@source inline("list-{disc,decimal,none,inside,outside}"); - -/* Text */ -@source inline("text-{left,center,right,justify}"); -@source inline("text-{slate,gray,zinc,neutral,stone}-{50,100,200,300,400,500,600,700,800,900,950}"); -@source inline("italic"); -@source inline("underline"); -@source inline("line-through"); - -/* Code */ -@source inline("font-mono"); -@source inline("bg-{slate,gray,zinc,muted}-{50,100,200}"); -@source inline("rounded{,-sm,-md,-lg,-xl}"); -@source inline("border{,-2,-4}"); -@source inline("border-{slate,gray,zinc,border}-{200,300}"); - -/* Blockquote */ -@source inline("border-l-{2,4}"); -@source inline("border-l-{slate,gray,primary}-{300,400,500}"); - -/* Link */ -@source inline("text-{blue,primary,accent}-{500,600,700}"); -@source inline("hover:text-{blue,primary,accent}-{600,700,800}"); -@source inline("hover:underline"); - -/* Table */ -@source inline("border-collapse"); -@source inline("table-auto"); -@source inline("w-full"); -@source inline("divide-{x,y}"); -@source inline("divide-{slate,gray,border}-{200,300}"); - -/* Image */ -@source inline("max-w-{xs,sm,md,lg,xl,2xl,full}"); -@source inline("h-auto"); -@source inline("object-cover"); - -/* Horizontal Rule */ -@source inline("border-t"); -@source inline("border-{slate,gray,border}-{200,300}"); - -/* General */ -@source inline("block"); -@source inline("inline"); -@source inline("inline-block"); -@source inline("break-words"); -@source inline("overflow-{auto,hidden,x-auto}"); -@source inline("whitespace-pre-wrap"); - -/* Shadcn Colors */ -@source inline("text-{foreground,muted-foreground,primary,secondary,accent}"); -@source inline("bg-{background,muted,primary,secondary,accent}"); -@source inline("border-{border,input}"); - -@custom-variant dark (&:is(.dark *)); - -@theme { - --font-sans: - ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", - "Segoe UI Symbol", "Noto Color Emoji"; - - --animate-fade-in: fade-in 1.1s; - @keyframes fade-in { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } - } - - --animate-fade-in-up: fade-in-up 0.15s ease-in-out forwards; - @keyframes fade-in-up { - 0% { - opacity: 0; - transform: translateY(1rem) scale(1.2); - } - 100% { - opacity: 1; - } - } - - --animate-bouncing: bouncing 0.5s infinite alternate; - @keyframes bouncing { - to { - opacity: 0.1; - transform: translateY(-8px); - } - } - - --animate-skeleton-entrance: skeleton-entrance 0.35s ease-out forwards; - @keyframes skeleton-entrance { - 0% { - opacity: 0; - transform: scaleX(0); - } - 100% { - opacity: 1; - transform: scaleX(1); - } - } - - --animate-suggestion-in: suggestion-in 0.2s ease-out forwards; - @keyframes suggestion-in { - 0% { - opacity: 0; - transform: translateY(-1.25rem); - } - 100% { - opacity: 1; - transform: translateY(0); - } - } - - --animate-wave: wave 0.6s ease-in-out 2; - @keyframes wave { - 0%, - 100% { - transform: rotate(0deg); - } - 25% { - transform: rotate(20deg); - } - 50% { - transform: rotate(0deg); - } - 75% { - transform: rotate(20deg); - } - } - - --animate-breathe-stop: breathe-stop 1.8s ease-in-out infinite; - @keyframes breathe-stop { - 0%, - 100% { - transform: scale(1); - box-shadow: - 0 0 0 0 rgba(217, 33, 33, 0.14), - 0 8px 24px -14px rgba(217, 33, 33, 0.35); - } - 50% { - transform: scale(1.06); - box-shadow: - 0 0 0 10px rgba(217, 33, 33, 0), - 0 14px 32px -16px rgba(217, 33, 33, 0.45); - } - } -} - -@theme inline { - --radius-sm: calc(var(--radius) - 4px); - --radius-md: calc(var(--radius) - 2px); - --radius-lg: var(--radius); - --radius-xl: calc(var(--radius) + 4px); - --radius-2xl: calc(var(--radius) + 8px); - --radius-3xl: calc(var(--radius) + 12px); - --radius-4xl: calc(var(--radius) + 16px); - --color-background: var(--background); - --color-foreground: var(--foreground); - --color-card: var(--card); - --color-card-foreground: var(--card-foreground); - --color-popover: var(--popover); - --color-popover-foreground: var(--popover-foreground); - --color-primary: var(--primary); - --color-primary-foreground: var(--primary-foreground); - --color-secondary: var(--secondary); - --color-secondary-foreground: var(--secondary-foreground); - --color-muted: var(--muted); - --color-muted-foreground: var(--muted-foreground); - --color-accent: var(--accent); - --color-accent-foreground: var(--accent-foreground); - --color-destructive: var(--destructive); - --color-border: var(--border); - --color-input: var(--input); - --color-ring: var(--ring); - --color-chart-1: var(--chart-1); - --color-chart-2: var(--chart-2); - --color-chart-3: var(--chart-3); - --color-chart-4: var(--chart-4); - --color-chart-5: var(--chart-5); - --color-sidebar: var(--sidebar); - --color-sidebar-foreground: var(--sidebar-foreground); - --color-sidebar-primary: var(--sidebar-primary); - --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); - --color-sidebar-accent: var(--sidebar-accent); - --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); - --color-sidebar-border: var(--sidebar-border); - --color-sidebar-ring: var(--sidebar-ring); - --animate-aurora: aurora 8s ease-in-out infinite alternate; - @keyframes aurora { - 0% { - background-position: 0% 50%; - transform: rotate(-5deg) scale(0.9); - } - 25% { - background-position: 50% 100%; - transform: rotate(5deg) scale(1.1); - } - 50% { - background-position: 100% 50%; - transform: rotate(-3deg) scale(0.95); - } - 75% { - background-position: 50% 0%; - transform: rotate(3deg) scale(1.05); - } - 100% { - background-position: 0% 50%; - transform: rotate(-5deg) scale(0.9); - } - } - --animate-shine: shine var(--duration) infinite linear; - @keyframes shine { - 0% { - background-position: 0% 0%; - } - 50% { - background-position: 100% 100%; - } - to { - background-position: 0% 0%; - } - } -} - -:root { - --workspace-brand: #f5222d; - --workspace-brand-foreground: #ffffff; - --brand-200: #feeded; - --brand-900: #cf1322; - --brand-950: #a8071a; - --radius: 0.75rem; - --background: oklch(1 0 0); - --foreground: oklch(0.22 0.02 25); - --card: oklch(1 0.002 95); - --card-foreground: oklch(0.22 0.02 25); - --popover: oklch(1 0.002 95); - --popover-foreground: oklch(0.22 0.02 25); - --primary: oklch(0.52 0.19 27); - --primary-foreground: oklch(0.99 0 0); - --secondary: oklch(0.955 0.008 95); - --secondary-foreground: oklch(0.32 0.04 25); - --muted: oklch(0.965 0.006 95); - --muted-foreground: oklch(0.48 0.02 25); - --accent: oklch(0.96 0.04 25); - --accent-foreground: oklch(0.35 0.12 25); - --destructive: oklch(0.577 0.245 27.325); - --border: oklch(0.9 0.008 95); - --input: oklch(0.9 0.01 95); - --ring: oklch(0.52 0.19 27 / 0.35); - --chart-1: oklch(0.646 0.222 41.116); - --chart-2: oklch(0.6 0.118 184.704); - --chart-3: oklch(0.398 0.07 227.392); - --chart-4: oklch(0.828 0.189 84.429); - --chart-5: oklch(0.769 0.188 70.08); - --sidebar: oklch(0.995 0.003 95); - --sidebar-foreground: oklch(0.28 0.02 25); - --sidebar-primary: oklch(0.52 0.19 27); - --sidebar-primary-foreground: oklch(0.99 0 0); - --sidebar-accent: oklch(0.978 0.018 70); - --sidebar-accent-foreground: oklch(0.32 0.05 32); - --sidebar-border: oklch(0.92 0.01 85); - --sidebar-ring: oklch(0.52 0.19 27 / 0.4); -} - -.dark { - --workspace-brand: #3b82f6; - --workspace-brand-foreground: #ffffff; - --background: oklch(0.208 0.042 264); - --foreground: oklch(0.96 0.005 240); - --card: oklch(0.265 0.04 260); - --card-foreground: oklch(0.96 0.005 240); - --popover: oklch(0.245 0.04 262); - --popover-foreground: oklch(0.96 0.005 240); - --primary: oklch(0.623 0.214 259); - --primary-foreground: oklch(0.99 0 0); - --secondary: oklch(0.32 0.038 260); - --secondary-foreground: oklch(0.96 0.005 240); - --muted: oklch(0.30 0.035 260); - --muted-foreground: oklch(0.68 0.02 240); - --accent: oklch(0.35 0.06 260); - --accent-foreground: oklch(0.96 0.005 240); - --destructive: oklch(0.704 0.191 22.216); - --border: oklch(1 0 0 / 12%); - --input: oklch(1 0 0 / 14%); - --ring: oklch(0.623 0.214 259 / 0.45); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.185 0.04 265); - --sidebar-foreground: oklch(0.94 0.005 240); - --sidebar-primary: oklch(0.623 0.214 259); - --sidebar-primary-foreground: oklch(0.99 0 0); - --sidebar-accent: oklch(0.30 0.055 260); - --sidebar-accent-foreground: oklch(0.96 0.005 240); - --sidebar-border: oklch(1 0 0 / 10%); - --sidebar-ring: oklch(0.623 0.214 259 / 0.45); - font-weight: 300; -} - -@layer base { - * { - @apply border-border outline-ring/50; - } - body { - @apply bg-background text-foreground; - } - - [data-sidebar="menu-button"][data-active="true"] { - box-shadow: inset 3px 0 0 var(--primary); - font-weight: 600; - } - - [data-sidebar="menu-button"][data-active="true"] svg { - color: var(--primary); - } - - .container-md { - width: 100%; - @media (width >= 40rem) { - max-width: 40rem; - } - @media (width >= 48rem) { - max-width: 48rem; - } - @media (width >= 64rem) { - max-width: 64rem; - } - @media (width >= 80rem) { - max-width: 80rem; - } - } - - .ambilight { - pointer-events: none; - opacity: 0; - transition: opacity 1s ease-in-out; - } - - .ambilight:before, - .ambilight:after { - content: ""; - pointer-events: none; - position: absolute; - left: 0; - top: 0; - background: linear-gradient( - 45deg, - #fb0094, - #0000ff, - #00ff00, - #ffff00, - #ff0000, - #fb0094, - #0000ff, - #00ff00, - #ffff00, - #ff0000 - ); - background-size: 400%; - width: 100%; - height: 100%; - border-radius: 10px; - z-index: -1; - animation: ambilight 40s ease-in-out infinite; - } - - .ambilight.enabled { - opacity: 1; - } - - .dark .ambilight:before, - .dark .ambilight:after { - opacity: 0.85; - } - - @keyframes ambilight { - 0% { - background-position: 0 0; - } - 50% { - background-position: 400% 0; - } - 100% { - background-position: 0 0; - } - } - - .ambilight:after { - filter: blur(60px); - } - - .golden-text { - background: linear-gradient(135deg, #d19e1d 0%, #e9c665 50%, #e3a812 100%); - -webkit-background-clip: text; - background-clip: text; - -webkit-text-fill-color: transparent; - text-fill-color: transparent; - } - - *::-webkit-scrollbar { - width: 10px; - height: 10px; - } - - *::-webkit-scrollbar-track { - background: transparent; - } - - *::-webkit-scrollbar-thumb { - border: 2px solid transparent; - border-radius: 999px; - background: linear-gradient(180deg, rgb(241 89 89 / 0.82), rgb(214 36 36 / 0.9)) - padding-box; - } - - .workspace-shell { - background: #ffffff; - } - - .dark .workspace-shell { - background: var(--background); - } - - .workspace-panel { - border: 1px solid #f0d7d0; - background: #ffffff; - box-shadow: - 0 32px 72px -46px rgb(98 63 42 / 0.35), - 0 12px 28px -22px rgb(170 91 75 / 0.24); - } - - .dark .workspace-panel { - border: 1px solid oklch(1 0 0 / 10%); - background: var(--card); - box-shadow: none; - } - - .workspace-user-bubble { - max-width: min(82%, 42rem); - border: 1px solid rgb(255 255 255 / 0.14); - border-radius: 1.6rem 1.6rem 0.5rem 1.6rem; - background: linear-gradient(135deg, #ff5b67 0%, #ef334d 58%, #df213e 100%); - color: white; - box-shadow: - 0 22px 40px -28px rgb(215 39 55 / 0.72), - 0 10px 20px -16px rgb(155 18 34 / 0.48); - } - - .workspace-user-bubble a, - .workspace-user-bubble code { - color: inherit; - } - - .workspace-user-bubble code { - background: rgb(255 255 255 / 0.18); - border-radius: 0.5rem; - padding: 0.1rem 0.35rem; - } - - .workspace-assistant-card { - position: relative; - width: 100%; - border: 1px solid #f1d9d3; - border-radius: 1.75rem; - background: rgb(255 255 255 / 0.94); - box-shadow: - 0 28px 48px -42px rgb(120 74 55 / 0.38), - 0 6px 18px -14px rgb(165 93 73 / 0.2); - } - - .workspace-assistant-card::before { - content: ""; - position: absolute; - top: 1rem; - left: 1rem; - width: 0.45rem; - height: calc(100% - 2rem); - border-radius: 999px; - background: linear-gradient(180deg, rgb(255 110 110 / 0.92), rgb(233 45 45 / 0.15)); - opacity: 0.88; - } - - .workspace-assistant-card > * { - position: relative; - z-index: 1; - } - - .workspace-assistant-card .prose, - .workspace-assistant-card [data-state] { - width: 100%; - } - - .workspace-assistant-card .my-3 { - margin-block: 0.25rem; - } - - .workspace-chat-toolbar { - border: 1px solid rgb(255 255 255 / 0.22); - background: rgb(255 255 255 / 0.14); - color: white; - backdrop-filter: blur(18px); - } - - @keyframes sandbox-preview-enter { - 0% { - opacity: 0; - transform: translateY(14px) scale(0.985); - } - 100% { - opacity: 1; - transform: translateY(0) scale(1); - } - } - - @keyframes sandbox-preview-glow { - 0%, - 100% { - box-shadow: - 0 0 0 0 rgb(227 39 39 / 0), - 0 8px 20px -16px rgb(227 39 39 / 0.1); - } - 50% { - box-shadow: - 0 0 0 8px rgb(227 39 39 / 0.08), - 0 18px 34px -18px rgb(227 39 39 / 0.3); - } - } - - @keyframes sandbox-preview-badge { - 0%, - 100% { - transform: translateY(0); - opacity: 0.88; - } - 50% { - transform: translateY(-1px); - opacity: 1; - } - } - - @keyframes sandbox-scroll-button-in { - 0% { - opacity: 0; - transform: translateY(-45%) scale(0.96); - } - 100% { - opacity: 1; - transform: translateY(-50%) scale(1); - } - } -} - -/* ─── Tiptap writing editor ─────────────────────────────────────────────── */ -.tiptap-writing-editor .ProseMirror { - outline: none; - min-height: 320px; - caret-color: var(--primary); - padding-bottom: 6rem; /* ensure last paragraph isn't flush against the bottom */ -} - -.tiptap-writing-editor .ProseMirror p { - margin-bottom: 1rem; - line-height: 1.8; - font-size: 0.9375rem; /* 15px */ - color: var(--foreground); - text-indent: 2em; /* 段落首行缩进 */ -} - -.tiptap-writing-editor .ProseMirror h1 { - font-size: 1.625rem; - font-weight: 700; - letter-spacing: -0.025em; - margin-top: 2rem; - margin-bottom: 0.75rem; - padding-bottom: 0.5rem; - border-bottom: 1px solid var(--border); - color: var(--foreground); - line-height: 1.25; -} - -.tiptap-writing-editor .ProseMirror h1:first-child { - margin-top: 0; -} - -.tiptap-writing-editor .ProseMirror h2 { - font-size: 1.25rem; - font-weight: 600; - letter-spacing: -0.015em; - margin-top: 1.75rem; - margin-bottom: 0.625rem; - color: var(--foreground); - line-height: 1.35; -} - -.tiptap-writing-editor .ProseMirror h3 { - font-size: 1.0625rem; - font-weight: 600; - letter-spacing: -0.01em; - margin-top: 1.25rem; - margin-bottom: 0.5rem; - color: var(--foreground); - line-height: 1.4; -} - -.tiptap-writing-editor .ProseMirror h2:first-child, -.tiptap-writing-editor .ProseMirror h3:first-child { - margin-top: 0; -} - -.tiptap-writing-editor .ProseMirror strong { - font-weight: 600; -} - -.tiptap-writing-editor .ProseMirror em { - font-style: italic; -} - -.tiptap-writing-editor .ProseMirror s { - text-decoration: line-through; - opacity: 0.6; -} - -.tiptap-writing-editor .ProseMirror ul { - list-style-type: disc; - margin-left: 1.5rem; - margin-bottom: 1rem; - font-size: 0.9375rem; - color: var(--foreground); -} - -.tiptap-writing-editor .ProseMirror ol { - list-style-type: decimal; - margin-left: 1.5rem; - margin-bottom: 1rem; - font-size: 0.9375rem; - color: var(--foreground); -} - -.tiptap-writing-editor .ProseMirror li { - line-height: 1.8; - margin-bottom: 0.25rem; -} - -.tiptap-writing-editor .ProseMirror li > p { - margin-bottom: 0.25rem; - text-indent: 0; /* 列表项内段落不缩进 */ -} - -.tiptap-writing-editor .ProseMirror blockquote { - border-left: 3px solid var(--border); - padding-left: 1rem; - margin: 1.25rem 0; - font-style: italic; - font-size: 0.9375rem; - color: var(--muted-foreground); -} - -.tiptap-writing-editor .ProseMirror pre { - background: var(--muted); - border-radius: 0.5rem; - padding: 1rem 1.25rem; - margin: 1rem 0 1.25rem; - overflow-x: auto; - border: 1px solid var(--border); -} - -.tiptap-writing-editor .ProseMirror pre code { - background: transparent; - padding: 0; - font-size: 0.8125rem; /* 13px */ - font-family: ui-monospace, 'Cascadia Code', 'Fira Code', monospace; - color: var(--foreground); - line-height: 1.7; -} - -.tiptap-writing-editor .ProseMirror code { - background: var(--muted); - padding: 0.15rem 0.4rem; - border-radius: 0.25rem; - font-size: 0.8125rem; - font-family: ui-monospace, 'Cascadia Code', 'Fira Code', monospace; - color: var(--foreground); - border: 1px solid var(--border); -} - -.tiptap-writing-editor .ProseMirror hr { - border: none; - border-top: 1px solid var(--border); - margin: 2rem 0; -} - -.tiptap-writing-editor .ProseMirror a { - color: var(--primary); - text-decoration: underline; - text-underline-offset: 3px; - text-decoration-thickness: 1px; - transition: opacity 0.15s; -} - -.tiptap-writing-editor .ProseMirror a:hover { - opacity: 0.75; -} - -/* Placeholder */ -.tiptap-writing-editor .ProseMirror p.is-editor-empty:first-child { - text-indent: 0; /* 占位文案不缩进 */ -} - -.tiptap-writing-editor .ProseMirror p.is-editor-empty:first-child::before { - content: attr(data-placeholder); - color: var(--muted-foreground); - pointer-events: none; - float: left; - height: 0; - opacity: 0.6; -} - -/* Selection highlight — use color-mix to avoid the background+opacity mismatch */ -.tiptap-writing-editor .ProseMirror ::selection { - background: color-mix(in srgb, #f87171 35%, transparent); -} - -/* AI rewrite — highlight the selected range while the menu / preview is open */ -.ai-rewrite-highlight { - background: color-mix(in srgb, #fbbf24 30%, transparent); - border-radius: 2px; - transition: background 0.2s ease; -} -.dark .ai-rewrite-highlight { - background: color-mix(in srgb, #fbbf24 18%, transparent); -} - -:root { - --container-width-xs: calc(var(--spacing) * 72); - --container-width-sm: calc(var(--spacing) * 144); - --container-width-md: calc(var(--spacing) * 204); - --container-width-lg: calc(var(--spacing) * 256); -} - -/* ── Landing 态输入框 Gemini 风格:旋转彩色描边 + 多色柔光阴影 ───────── */ -/* 关键:::before 转动的彩色锥形渐变 + ::after 内嵌白板遮罩中央,只在 1.5px 边缘可见模糊彩光 */ -.gemini-shadow { - box-shadow: - 0 0 20px rgba(66, 133, 244, 0.10), - 0 0 40px rgba(219, 68, 55, 0.05), - 0 0 60px rgba(244, 180, 0, 0.05), - 0 0 80px rgba(15, 157, 88, 0.05); -} -.dark .gemini-shadow { - box-shadow: - 0 0 24px rgba(66, 133, 244, 0.20), - 0 0 48px rgba(219, 68, 55, 0.10), - 0 0 72px rgba(244, 180, 0, 0.10), - 0 0 96px rgba(15, 157, 88, 0.10); -} - -.gemini-gradient-border { - position: relative; - background: var(--background); - border-radius: 1.5rem; - z-index: 0; - overflow: hidden; -} -.gemini-gradient-border::before { - content: ''; - position: absolute; - width: 200%; - height: 200%; - top: -50%; - left: -50%; - background: conic-gradient( - from 0deg, - #4285F4 0deg, - #DB4437 90deg, - #F4B400 180deg, - #0F9D58 270deg, - #4285F4 360deg - ); - z-index: -2; - animation: gemini-rotate 4s linear infinite; - filter: blur(10px); - pointer-events: none; -} -.gemini-gradient-border::after { - content: ''; - position: absolute; - inset: 2.5px; - background: var(--background); - border-radius: calc(1.5rem - 2px); - z-index: -1; -} - -@keyframes gemini-rotate { - to { - transform: rotate(360deg); - } -} - -* { - border-color: var(--border); - outline-color: var(--ring); +@import "tailwindcss"; +@import "tw-animate-css"; + +@source "../node_modules/streamdown/dist/index.js"; + +/* Heading */ +@source inline("text-{xs,sm,base,lg,xl,2xl,3xl,4xl,5xl,6xl}"); +@source inline("font-{normal,medium,semibold,bold,extrabold}"); +@source inline("leading-{none,tight,snug,normal,relaxed,loose}"); + +/* Spacing */ +@source inline("m{t,b,l,r,x,y}-{0,1,2,3,4,5,6,8,10,12,16,20,24}"); +@source inline("p{t,b,l,r,x,y}-{0,1,2,3,4,5,6,8,10,12,16,20,24}"); +@source inline("space-{x,y}-{1,2,3,4,5,6,8}"); + +/* List */ +@source inline("list-{disc,decimal,none,inside,outside}"); + +/* Text */ +@source inline("text-{left,center,right,justify}"); +@source inline("text-{slate,gray,zinc,neutral,stone}-{50,100,200,300,400,500,600,700,800,900,950}"); +@source inline("italic"); +@source inline("underline"); +@source inline("line-through"); + +/* Code */ +@source inline("font-mono"); +@source inline("bg-{slate,gray,zinc,muted}-{50,100,200}"); +@source inline("rounded{,-sm,-md,-lg,-xl}"); +@source inline("border{,-2,-4}"); +@source inline("border-{slate,gray,zinc,border}-{200,300}"); + +/* Blockquote */ +@source inline("border-l-{2,4}"); +@source inline("border-l-{slate,gray,primary}-{300,400,500}"); + +/* Link */ +@source inline("text-{blue,primary,accent}-{500,600,700}"); +@source inline("hover:text-{blue,primary,accent}-{600,700,800}"); +@source inline("hover:underline"); + +/* Table */ +@source inline("border-collapse"); +@source inline("table-auto"); +@source inline("w-full"); +@source inline("divide-{x,y}"); +@source inline("divide-{slate,gray,border}-{200,300}"); + +/* Image */ +@source inline("max-w-{xs,sm,md,lg,xl,2xl,full}"); +@source inline("h-auto"); +@source inline("object-cover"); + +/* Horizontal Rule */ +@source inline("border-t"); +@source inline("border-{slate,gray,border}-{200,300}"); + +/* General */ +@source inline("block"); +@source inline("inline"); +@source inline("inline-block"); +@source inline("break-words"); +@source inline("overflow-{auto,hidden,x-auto}"); +@source inline("whitespace-pre-wrap"); + +/* Shadcn Colors */ +@source inline("text-{foreground,muted-foreground,primary,secondary,accent}"); +@source inline("bg-{background,muted,primary,secondary,accent}"); +@source inline("border-{border,input}"); + +@custom-variant dark (&:is(.dark *)); + +@theme { + --font-sans: + ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", + "Segoe UI Symbol", "Noto Color Emoji"; + + --animate-fade-in: fade-in 1.1s; + @keyframes fade-in { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } + } + + --animate-fade-in-up: fade-in-up 0.15s ease-in-out forwards; + @keyframes fade-in-up { + 0% { + opacity: 0; + transform: translateY(1rem) scale(1.2); + } + 100% { + opacity: 1; + } + } + + --animate-bouncing: bouncing 0.5s infinite alternate; + @keyframes bouncing { + to { + opacity: 0.1; + transform: translateY(-8px); + } + } + + --animate-skeleton-entrance: skeleton-entrance 0.35s ease-out forwards; + @keyframes skeleton-entrance { + 0% { + opacity: 0; + transform: scaleX(0); + } + 100% { + opacity: 1; + transform: scaleX(1); + } + } + + --animate-suggestion-in: suggestion-in 0.2s ease-out forwards; + @keyframes suggestion-in { + 0% { + opacity: 0; + transform: translateY(-1.25rem); + } + 100% { + opacity: 1; + transform: translateY(0); + } + } + + --animate-wave: wave 0.6s ease-in-out 2; + @keyframes wave { + 0%, + 100% { + transform: rotate(0deg); + } + 25% { + transform: rotate(20deg); + } + 50% { + transform: rotate(0deg); + } + 75% { + transform: rotate(20deg); + } + } + + --animate-breathe-stop: breathe-stop 1.8s ease-in-out infinite; + @keyframes breathe-stop { + 0%, + 100% { + transform: scale(1); + box-shadow: + 0 0 0 0 rgba(217, 33, 33, 0.14), + 0 8px 24px -14px rgba(217, 33, 33, 0.35); + } + 50% { + transform: scale(1.06); + box-shadow: + 0 0 0 10px rgba(217, 33, 33, 0), + 0 14px 32px -16px rgba(217, 33, 33, 0.45); + } + } +} + +@theme inline { + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --radius-2xl: calc(var(--radius) + 8px); + --radius-3xl: calc(var(--radius) + 12px); + --radius-4xl: calc(var(--radius) + 16px); + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); + --animate-aurora: aurora 8s ease-in-out infinite alternate; + @keyframes aurora { + 0% { + background-position: 0% 50%; + transform: rotate(-5deg) scale(0.9); + } + 25% { + background-position: 50% 100%; + transform: rotate(5deg) scale(1.1); + } + 50% { + background-position: 100% 50%; + transform: rotate(-3deg) scale(0.95); + } + 75% { + background-position: 50% 0%; + transform: rotate(3deg) scale(1.05); + } + 100% { + background-position: 0% 50%; + transform: rotate(-5deg) scale(0.9); + } + } + --animate-shine: shine var(--duration) infinite linear; + @keyframes shine { + 0% { + background-position: 0% 0%; + } + 50% { + background-position: 100% 100%; + } + to { + background-position: 0% 0%; + } + } +} + +:root { + --workspace-brand: #f5222d; + --workspace-brand-foreground: #ffffff; + --brand-200: #feeded; + --brand-900: #cf1322; + --brand-950: #a8071a; + --radius: 0.75rem; + --background: oklch(1 0 0); + --foreground: oklch(0.22 0.02 25); + --card: oklch(1 0.002 95); + --card-foreground: oklch(0.22 0.02 25); + --popover: oklch(1 0.002 95); + --popover-foreground: oklch(0.22 0.02 25); + --primary: oklch(0.52 0.19 27); + --primary-foreground: oklch(0.99 0 0); + --secondary: oklch(0.955 0.008 95); + --secondary-foreground: oklch(0.32 0.04 25); + --muted: oklch(0.965 0.006 95); + --muted-foreground: oklch(0.48 0.02 25); + --accent: oklch(0.96 0.04 25); + --accent-foreground: oklch(0.35 0.12 25); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.9 0.008 95); + --input: oklch(0.9 0.01 95); + --ring: oklch(0.52 0.19 27 / 0.35); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --sidebar: oklch(0.995 0.003 95); + --sidebar-foreground: oklch(0.28 0.02 25); + --sidebar-primary: oklch(0.52 0.19 27); + --sidebar-primary-foreground: oklch(0.99 0 0); + --sidebar-accent: oklch(0.978 0.018 70); + --sidebar-accent-foreground: oklch(0.32 0.05 32); + --sidebar-border: oklch(0.92 0.01 85); + --sidebar-ring: oklch(0.52 0.19 27 / 0.4); +} + +.dark { + --workspace-brand: #3b82f6; + --workspace-brand-foreground: #ffffff; + --background: oklch(0.208 0.042 264); + --foreground: oklch(0.96 0.005 240); + --card: oklch(0.265 0.04 260); + --card-foreground: oklch(0.96 0.005 240); + --popover: oklch(0.245 0.04 262); + --popover-foreground: oklch(0.96 0.005 240); + --primary: oklch(0.623 0.214 259); + --primary-foreground: oklch(0.99 0 0); + --secondary: oklch(0.32 0.038 260); + --secondary-foreground: oklch(0.96 0.005 240); + --muted: oklch(0.30 0.035 260); + --muted-foreground: oklch(0.68 0.02 240); + --accent: oklch(0.35 0.06 260); + --accent-foreground: oklch(0.96 0.005 240); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 12%); + --input: oklch(1 0 0 / 14%); + --ring: oklch(0.623 0.214 259 / 0.45); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.185 0.04 265); + --sidebar-foreground: oklch(0.94 0.005 240); + --sidebar-primary: oklch(0.623 0.214 259); + --sidebar-primary-foreground: oklch(0.99 0 0); + --sidebar-accent: oklch(0.30 0.055 260); + --sidebar-accent-foreground: oklch(0.96 0.005 240); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.623 0.214 259 / 0.45); + font-weight: 300; +} + +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } + + [data-sidebar="menu-button"][data-active="true"] { + box-shadow: inset 3px 0 0 var(--primary); + font-weight: 600; + } + + [data-sidebar="menu-button"][data-active="true"] svg { + color: var(--primary); + } + + .container-md { + width: 100%; + @media (width >= 40rem) { + max-width: 40rem; + } + @media (width >= 48rem) { + max-width: 48rem; + } + @media (width >= 64rem) { + max-width: 64rem; + } + @media (width >= 80rem) { + max-width: 80rem; + } + } + + .ambilight { + pointer-events: none; + opacity: 0; + transition: opacity 1s ease-in-out; + } + + .ambilight:before, + .ambilight:after { + content: ""; + pointer-events: none; + position: absolute; + left: 0; + top: 0; + background: linear-gradient( + 45deg, + #fb0094, + #0000ff, + #00ff00, + #ffff00, + #ff0000, + #fb0094, + #0000ff, + #00ff00, + #ffff00, + #ff0000 + ); + background-size: 400%; + width: 100%; + height: 100%; + border-radius: 10px; + z-index: -1; + animation: ambilight 40s ease-in-out infinite; + } + + .ambilight.enabled { + opacity: 1; + } + + .dark .ambilight:before, + .dark .ambilight:after { + opacity: 0.85; + } + + @keyframes ambilight { + 0% { + background-position: 0 0; + } + 50% { + background-position: 400% 0; + } + 100% { + background-position: 0 0; + } + } + + .ambilight:after { + filter: blur(60px); + } + + .golden-text { + background: linear-gradient(135deg, #d19e1d 0%, #e9c665 50%, #e3a812 100%); + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; + text-fill-color: transparent; + } + + *::-webkit-scrollbar { + width: 10px; + height: 10px; + } + + *::-webkit-scrollbar-track { + background: transparent; + } + + *::-webkit-scrollbar-thumb { + border: 2px solid transparent; + border-radius: 999px; + background: linear-gradient(180deg, rgb(241 89 89 / 0.82), rgb(214 36 36 / 0.9)) + padding-box; + } + + .workspace-shell { + background: #ffffff; + } + + .dark .workspace-shell { + background: var(--background); + } + + .workspace-panel { + border: 1px solid #f0d7d0; + background: #ffffff; + box-shadow: + 0 32px 72px -46px rgb(98 63 42 / 0.35), + 0 12px 28px -22px rgb(170 91 75 / 0.24); + } + + .dark .workspace-panel { + border: 1px solid oklch(1 0 0 / 10%); + background: var(--card); + box-shadow: none; + } + + .workspace-user-bubble { + max-width: min(82%, 42rem); + border: 1px solid rgb(255 255 255 / 0.14); + border-radius: 1.6rem 1.6rem 0.5rem 1.6rem; + background: linear-gradient(135deg, #ff5b67 0%, #ef334d 58%, #df213e 100%); + color: white; + box-shadow: + 0 22px 40px -28px rgb(215 39 55 / 0.72), + 0 10px 20px -16px rgb(155 18 34 / 0.48); + } + + .workspace-user-bubble a, + .workspace-user-bubble code { + color: inherit; + } + + .workspace-user-bubble code { + background: rgb(255 255 255 / 0.18); + border-radius: 0.5rem; + padding: 0.1rem 0.35rem; + } + + .workspace-assistant-card { + position: relative; + width: 100%; + border: 1px solid #f1d9d3; + border-radius: 1.75rem; + background: rgb(255 255 255 / 0.94); + box-shadow: + 0 28px 48px -42px rgb(120 74 55 / 0.38), + 0 6px 18px -14px rgb(165 93 73 / 0.2); + } + + .workspace-assistant-card::before { + content: ""; + position: absolute; + top: 1rem; + left: 1rem; + width: 0.45rem; + height: calc(100% - 2rem); + border-radius: 999px; + background: linear-gradient(180deg, rgb(255 110 110 / 0.92), rgb(233 45 45 / 0.15)); + opacity: 0.88; + } + + .workspace-assistant-card > * { + position: relative; + z-index: 1; + } + + .workspace-assistant-card .prose, + .workspace-assistant-card [data-state] { + width: 100%; + } + + .workspace-assistant-card .my-3 { + margin-block: 0.25rem; + } + + .workspace-chat-toolbar { + border: 1px solid rgb(255 255 255 / 0.22); + background: rgb(255 255 255 / 0.14); + color: white; + backdrop-filter: blur(18px); + } + + @keyframes sandbox-preview-enter { + 0% { + opacity: 0; + transform: translateY(14px) scale(0.985); + } + 100% { + opacity: 1; + transform: translateY(0) scale(1); + } + } + + @keyframes sandbox-preview-glow { + 0%, + 100% { + box-shadow: + 0 0 0 0 rgb(227 39 39 / 0), + 0 8px 20px -16px rgb(227 39 39 / 0.1); + } + 50% { + box-shadow: + 0 0 0 8px rgb(227 39 39 / 0.08), + 0 18px 34px -18px rgb(227 39 39 / 0.3); + } + } + + @keyframes sandbox-preview-badge { + 0%, + 100% { + transform: translateY(0); + opacity: 0.88; + } + 50% { + transform: translateY(-1px); + opacity: 1; + } + } + + @keyframes sandbox-scroll-button-in { + 0% { + opacity: 0; + transform: translateY(-45%) scale(0.96); + } + 100% { + opacity: 1; + transform: translateY(-50%) scale(1); + } + } +} + +/* ─── Tiptap writing editor ─────────────────────────────────────────────── */ +.tiptap-writing-editor .ProseMirror { + outline: none; + min-height: 320px; + caret-color: var(--primary); + padding-bottom: 6rem; /* ensure last paragraph isn't flush against the bottom */ +} + +.tiptap-writing-editor .ProseMirror p { + margin-bottom: 1rem; + line-height: 1.8; + font-size: 0.9375rem; /* 15px */ + color: var(--foreground); + text-indent: 2em; /* 段落首行缩进 */ +} + +.tiptap-writing-editor .ProseMirror h1 { + font-size: 1.625rem; + font-weight: 700; + letter-spacing: -0.025em; + margin-top: 2rem; + margin-bottom: 0.75rem; + padding-bottom: 0.5rem; + border-bottom: 1px solid var(--border); + color: var(--foreground); + line-height: 1.25; +} + +.tiptap-writing-editor .ProseMirror h1:first-child { + margin-top: 0; +} + +.tiptap-writing-editor .ProseMirror h2 { + font-size: 1.25rem; + font-weight: 600; + letter-spacing: -0.015em; + margin-top: 1.75rem; + margin-bottom: 0.625rem; + color: var(--foreground); + line-height: 1.35; +} + +.tiptap-writing-editor .ProseMirror h3 { + font-size: 1.0625rem; + font-weight: 600; + letter-spacing: -0.01em; + margin-top: 1.25rem; + margin-bottom: 0.5rem; + color: var(--foreground); + line-height: 1.4; +} + +.tiptap-writing-editor .ProseMirror h2:first-child, +.tiptap-writing-editor .ProseMirror h3:first-child { + margin-top: 0; +} + +.tiptap-writing-editor .ProseMirror strong { + font-weight: 600; +} + +.tiptap-writing-editor .ProseMirror em { + font-style: italic; +} + +.tiptap-writing-editor .ProseMirror s { + text-decoration: line-through; + opacity: 0.6; +} + +.tiptap-writing-editor .ProseMirror ul { + list-style-type: disc; + margin-left: 1.5rem; + margin-bottom: 1rem; + font-size: 0.9375rem; + color: var(--foreground); +} + +.tiptap-writing-editor .ProseMirror ol { + list-style-type: decimal; + margin-left: 1.5rem; + margin-bottom: 1rem; + font-size: 0.9375rem; + color: var(--foreground); +} + +.tiptap-writing-editor .ProseMirror li { + line-height: 1.8; + margin-bottom: 0.25rem; +} + +.tiptap-writing-editor .ProseMirror li > p { + margin-bottom: 0.25rem; + text-indent: 0; /* 列表项内段落不缩进 */ +} + +.tiptap-writing-editor .ProseMirror blockquote { + border-left: 3px solid var(--border); + padding-left: 1rem; + margin: 1.25rem 0; + font-style: italic; + font-size: 0.9375rem; + color: var(--muted-foreground); +} + +.tiptap-writing-editor .ProseMirror pre { + background: var(--muted); + border-radius: 0.5rem; + padding: 1rem 1.25rem; + margin: 1rem 0 1.25rem; + overflow-x: auto; + border: 1px solid var(--border); +} + +.tiptap-writing-editor .ProseMirror pre code { + background: transparent; + padding: 0; + font-size: 0.8125rem; /* 13px */ + font-family: ui-monospace, 'Cascadia Code', 'Fira Code', monospace; + color: var(--foreground); + line-height: 1.7; +} + +.tiptap-writing-editor .ProseMirror code { + background: var(--muted); + padding: 0.15rem 0.4rem; + border-radius: 0.25rem; + font-size: 0.8125rem; + font-family: ui-monospace, 'Cascadia Code', 'Fira Code', monospace; + color: var(--foreground); + border: 1px solid var(--border); +} + +.tiptap-writing-editor .ProseMirror hr { + border: none; + border-top: 1px solid var(--border); + margin: 2rem 0; +} + +.tiptap-writing-editor .ProseMirror a { + color: var(--primary); + text-decoration: underline; + text-underline-offset: 3px; + text-decoration-thickness: 1px; + transition: opacity 0.15s; +} + +.tiptap-writing-editor .ProseMirror a:hover { + opacity: 0.75; +} + +/* Placeholder */ +.tiptap-writing-editor .ProseMirror p.is-editor-empty:first-child { + text-indent: 0; /* 占位文案不缩进 */ +} + +.tiptap-writing-editor .ProseMirror p.is-editor-empty:first-child::before { + content: attr(data-placeholder); + color: var(--muted-foreground); + pointer-events: none; + float: left; + height: 0; + opacity: 0.6; +} + +/* Selection highlight — use color-mix to avoid the background+opacity mismatch */ +.tiptap-writing-editor .ProseMirror ::selection { + background: color-mix(in srgb, #f87171 35%, transparent); +} + +/* AI rewrite — highlight the selected range while the menu / preview is open */ +.ai-rewrite-highlight { + background: color-mix(in srgb, #fbbf24 30%, transparent); + border-radius: 2px; + transition: background 0.2s ease; +} +.dark .ai-rewrite-highlight { + background: color-mix(in srgb, #fbbf24 18%, transparent); +} + +:root { + --container-width-xs: calc(var(--spacing) * 72); + --container-width-sm: calc(var(--spacing) * 144); + --container-width-md: calc(var(--spacing) * 204); + --container-width-lg: calc(var(--spacing) * 256); +} + +/* ── Landing 态输入框 Gemini 风格:旋转彩色描边 + 多色柔光阴影 ───────── */ +/* 关键:::before 转动的彩色锥形渐变 + ::after 内嵌白板遮罩中央,只在 1.5px 边缘可见模糊彩光 */ +.gemini-shadow { + box-shadow: + 0 0 20px rgba(66, 133, 244, 0.10), + 0 0 40px rgba(219, 68, 55, 0.05), + 0 0 60px rgba(244, 180, 0, 0.05), + 0 0 80px rgba(15, 157, 88, 0.05); +} +.dark .gemini-shadow { + box-shadow: + 0 0 24px rgba(66, 133, 244, 0.20), + 0 0 48px rgba(219, 68, 55, 0.10), + 0 0 72px rgba(244, 180, 0, 0.10), + 0 0 96px rgba(15, 157, 88, 0.10); +} + +.gemini-gradient-border { + position: relative; + background: var(--background); + border-radius: 1.5rem; + z-index: 0; + overflow: hidden; +} +.gemini-gradient-border::before { + content: ''; + position: absolute; + width: 200%; + height: 200%; + top: -50%; + left: -50%; + background: conic-gradient( + from 0deg, + #4285F4 0deg, + #DB4437 90deg, + #F4B400 180deg, + #0F9D58 270deg, + #4285F4 360deg + ); + z-index: -2; + animation: gemini-rotate 4s linear infinite; + filter: blur(10px); + pointer-events: none; +} +.gemini-gradient-border::after { + content: ''; + position: absolute; + inset: 2.5px; + background: var(--background); + border-radius: calc(1.5rem - 2px); + z-index: -1; +} + +@keyframes gemini-rotate { + to { + transform: rotate(360deg); + } +} + +* { + border-color: var(--border); + outline-color: var(--ring); } \ No newline at end of file diff --git a/offline-backend-20260512/backend/config.yaml b/offline-backend-20260512/backend/config.yaml index 3208a97c..fe958e7a 100644 --- a/offline-backend-20260512/backend/config.yaml +++ b/offline-backend-20260512/backend/config.yaml @@ -132,7 +132,7 @@ agents_api: enabled: true database: - backend: mysql + backend: memory # 临时:MySQL 服务器挂了,先跑内存;恢复后改回 mysql mysql_url: $MYSQL_DATABASE_URL pool_size: 10 echo_sql: false diff --git a/offline-backend-20260512/config.yaml b/offline-backend-20260512/config.yaml index 7df8818e..46387e68 100644 --- a/offline-backend-20260512/config.yaml +++ b/offline-backend-20260512/config.yaml @@ -114,7 +114,7 @@ skills: agents_api: enabled: true database: - backend: mysql + backend: memory # 临时:MySQL 服务器挂了,先跑内存;恢复后改回 mysql mysql_url: $MYSQL_DATABASE_URL pool_size: 10 echo_sql: false