From a02985a93db1fdd1e8b2ef53a4cdf9c10ab6bcc3 Mon Sep 17 00:00:00 2001 From: EasterCat Date: Fri, 20 Mar 2026 22:02:53 +0700 Subject: [PATCH 01/13] Update version to 0.0.2 Made-with: Cursor --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d926591..f081ef9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "crosshair-overlay", "private": true, - "version": "0.0.0", + "version": "0.0.2", "type": "module", "scripts": { "dev": "vite", From 86de457ece7aa48c727b4574467e40c003f44e4e Mon Sep 17 00:00:00 2001 From: EasterCat Date: Sat, 21 Mar 2026 13:04:43 +0700 Subject: [PATCH 02/13] fix: use objc2 to set macOS window transparent background + improve hexToRgba safety - Integrate objc2 crate to properly set NSWindow transparent background - Fix hexToRgba to handle undefined color values - Enhance overlay.html CSS for better transparency support Made-with: Cursor --- overlay.html | 63 ++++++++++++++++---- src-tauri/Cargo.toml | 6 +- src-tauri/src/lib.rs | 39 +++++++++++- src/CrosshairOverlayApp.tsx | 96 ++++++++++++++++++++++++++---- src/components/CrosshairCanvas.tsx | 5 +- src/overlay.css | 22 ++++++- 6 files changed, 202 insertions(+), 29 deletions(-) diff --git a/overlay.html b/overlay.html index 4db4b80..5ee0758 100644 --- a/overlay.html +++ b/overlay.html @@ -5,19 +5,62 @@ CrosshairOverlay diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 5e6d4b0..5a763f2 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -24,6 +24,6 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" log = "0.4" tokio = { version = "1", features = ["time"] } - -[target.'cfg(target_os = "macos")'.dependencies] -cocoa = "0.25" +objc2 = "0.6" +objc2-app-kit = "0.2" +objc2-foundation = "0.3" diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 8ee4d04..f71d2aa 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -74,7 +74,7 @@ async fn create_crosshair_window(app: AppHandle) -> Result<(), String> { .skip_taskbar(true) .resizable(false) .focused(false) - .visible(true) + .visible(false) // Start hidden, show after content loads .build() .map_err(|e: tauri::Error| e.to_string())?; @@ -82,6 +82,43 @@ async fn create_crosshair_window(app: AppHandle) -> Result<(), String> { .set_ignore_cursor_events(true) .map_err(|e: tauri::Error| e.to_string())?; + // Set window background to transparent on macOS using objc2 + #[cfg(target_os = "macos")] + { + use objc2::{msg_send, class}; + + let overlay_clone = overlay.clone(); + std::thread::spawn(move || { + // Small delay to ensure window is fully created + std::thread::sleep(std::time::Duration::from_millis(300)); + unsafe { + if let Ok(ns_window_ptr) = overlay_clone.ns_window() { + let ns_window = ns_window_ptr as *mut objc2::runtime::AnyObject; + if !ns_window.is_null() { + // Call setOpaque_(NO) using raw objc + let _: () = msg_send![ns_window, setOpaque: false as bool]; + + // Get clearColor + let clear_color: *mut objc2::runtime::AnyObject = msg_send![class!(NSColor), clearColor]; + if !clear_color.is_null() { + // Set background color to clear + let _: () = msg_send![ns_window, setBackgroundColor: clear_color]; + } + + // Force redraw + let _: () = msg_send![ns_window, display]; + } + } + } + }); + } + + #[cfg(not(target_os = "macos"))] + let _ = overlay; + + // Window will be shown by the frontend once content is ready + // This prevents black screen flash on startup + Ok(()) } diff --git a/src/CrosshairOverlayApp.tsx b/src/CrosshairOverlayApp.tsx index a89532d..8dd6c73 100644 --- a/src/CrosshairOverlayApp.tsx +++ b/src/CrosshairOverlayApp.tsx @@ -11,17 +11,46 @@ import { load } from '@tauri-apps/plugin-store'; const STORE_FILE = 'settings.json'; -// Detect which window we are in via URL param (?overlay=true) -const IS_OVERLAY = new URLSearchParams(window.location.search).has('overlay'); +// Detect overlay window by checking if we're in overlay.html +// Since overlay-entry.tsx is only loaded by overlay.html, we're always in overlay mode here +const IS_OVERLAY = window.location.pathname.includes('overlay.html') || + window.location.href.includes('overlay.html'); export function CrosshairOverlayApp() { - const [config, setConfig] = useState(BUILTIN_PRESETS[0]); + const [config, setConfig] = useState(null); const [visible, setVisible] = useState(true); + const [isReady, setIsReady] = useState(false); useEffect(() => { - if (!IS_OVERLAY) return; + // Always run in overlay mode since this component is only used in overlay.html - (async () => { + // Ensure body and root are transparent immediately + document.documentElement.style.background = 'transparent'; + document.documentElement.style.backgroundColor = 'transparent'; + document.body.style.background = 'transparent'; + document.body.style.backgroundColor = 'transparent'; + document.body.style.margin = '0'; + document.body.style.padding = '0'; + const root = document.getElementById('root'); + if (root) { + root.style.background = 'transparent'; + root.style.backgroundColor = 'transparent'; + } + + // Also set on the html element + const html = document.documentElement; + html.style.background = 'transparent'; + html.style.backgroundColor = 'transparent'; + + // Configure window for transparency via Tauri API + import('@tauri-apps/api/window').then(async ({ getCurrentWindow }) => { + const win = getCurrentWindow(); + + // Set window drag region for better UX (optional) + // Note: We can't actually set transparent background here, + // but we can ensure the window is configured correctly + + // Load saved settings try { const store = await load(STORE_FILE, { autoSave: false, defaults: {} }); const savedId = await store.get('currentPresetId'); @@ -35,23 +64,66 @@ export function CrosshairOverlayApp() { const custom = await store.get('customPresets'); const all = [...BUILTIN_PRESETS, ...(custom ?? [])]; const found = all.find(p => p.id === savedId); - if (found) setConfig(found); + if (found) { + setConfig(found); + } else { + setConfig(BUILTIN_PRESETS[0]); + } + } else { + setConfig(BUILTIN_PRESETS[0]); + } + setIsReady(true); + + // Show window once content is ready, but only if visible + if (savedSettings?.showCrosshair !== false) { + // Small delay to ensure rendering is complete + setTimeout(() => { + win.show().catch(() => {}); + }, 150); } } catch (e) { - // Use defaults + // Use defaults on error + setConfig(BUILTIN_PRESETS[0]); + setIsReady(true); + + // Show window even on error, but with delay + setTimeout(() => { + win.show().catch(() => {}); + }, 150); } - })(); + }); // Listen for preset change events import('@tauri-apps/api/event').then(({ listen }) => { - listen<{ config: CrosshairConfig }>('overlay-update', (event) => { - setConfig(event.payload.config); + listen('overlay-update', (event) => { + setConfig(event.payload); + }); + + // Listen for visibility toggle + listen('hotkey-toggle', () => { + import('@tauri-apps/api/core').then(({ invoke }) => { + invoke('toggle_crosshair').catch(() => {}); + }); }); + }).catch(() => { + // Ignore import errors }); }, []); - if (!IS_OVERLAY) return null; - if (!visible) return null; + // Always render transparent container to avoid black screen + // Even when not visible or config not ready, render transparent div + if (!visible || !config || !isReady) { + return ( +
+ ); + } return ( diff --git a/src/i18n/en.ts b/src/i18n/en.ts index b167059..5be8ea1 100644 --- a/src/i18n/en.ts +++ b/src/i18n/en.ts @@ -1,7 +1,7 @@ export const en = { app: { title: 'CrosshairOverlay', - version: 'v0.1.0', + version: 'v1.0.0', tagline: 'Lightweight crosshair overlay for games', }, status: { diff --git a/src/i18n/zh.ts b/src/i18n/zh.ts index 04124bc..8e97449 100644 --- a/src/i18n/zh.ts +++ b/src/i18n/zh.ts @@ -1,7 +1,7 @@ export const zh = { app: { title: 'CrosshairOverlay', - version: 'v0.1.0', + version: 'v1.0.0', tagline: '轻量级游戏准星悬浮窗', }, status: { From 61b67b0e3ea7095c3bbed3ee5ccfe04d45023725 Mon Sep 17 00:00:00 2001 From: EasterCat Date: Sat, 21 Mar 2026 14:53:55 +0700 Subject: [PATCH 09/13] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20Windows=20?= =?UTF-8?q?=E6=89=98=E7=9B=98=E5=9B=BE=E6=A0=87=E5=92=8C=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E9=97=AE=E9=A2=98=EF=BC=8C=E5=B9=B6=E7=BE=8E?= =?UTF-8?q?=E5=8C=96=E8=87=AA=E5=AE=9A=E4=B9=89=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 托盘修复: - 移除 tauri.conf.json 中的 trayIcon 配置,避免与前端创建的托盘冲突 - 在 useTray.ts 中添加 defaultWindowIcon() 作为托盘图标 - 增强 show_settings 命令,添加 request_user_attention 使窗口更容易唤醒 - 添加 core:app:default 和 request-user-attention 权限 UI 美化: - 将固定宽度布局改为响应式 grid 布局,适配窗口大小变化 - 优化 Preview 预览区域,使用渐变背景和阴影效果 - 美化滑块样式,添加渐变进度条 - 改进颜色选择器按钮的阴影和缩放动画 - 将复选框改为更现代的 Switch 滑动开关样式 - 优化保存按钮,添加渐变背景和悬停动效 - 统一圆角、间距和字体大小等设计细节 Made-with: Cursor --- src-tauri/capabilities/default.json | 2 + src-tauri/src/lib.rs | 11 +- src-tauri/tauri.conf.json | 4 - src/components/SettingsPanel.tsx | 378 ++++++++++++++++++---------- src/hooks/useTray.ts | 6 + 5 files changed, 269 insertions(+), 132 deletions(-) diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 607860c..d8d2b70 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -5,6 +5,7 @@ "windows": ["main", "crosshair-layer"], "permissions": [ "core:default", + "core:app:default", "core:window:default", "core:window:allow-show", "core:window:allow-hide", @@ -32,6 +33,7 @@ "core:window:allow-available-monitors", "core:window:allow-is-minimized", "core:window:allow-set-resizable", + "core:window:allow-request-user-attention", "core:tray:default", "core:menu:default", "core:event:default", diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 2e73feb..ff4a085 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -167,9 +167,18 @@ async fn toggle_crosshair(app: AppHandle) -> Result { #[tauri::command] async fn show_settings(app: AppHandle) -> Result<(), String> { if let Some(main) = app.get_webview_window("main") { + // Restore and show the window main.show().map_err(|e| e.to_string())?; - main.set_focus().map_err(|e| e.to_string())?; + // Unminimize if minimized main.unminimize().map_err(|e| e.to_string())?; + // Request user attention to flash taskbar (Windows) + main.request_user_attention(Some(tauri::UserAttentionType::Informational)) + .map_err(|e| e.to_string())?; + // Set focus + main.set_focus().map_err(|e| e.to_string())?; + log::info!("Settings window shown"); + } else { + log::warn!("Main window not found"); } Ok(()) } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 578c865..92e7a3e 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -32,10 +32,6 @@ ], "security": { "csp": "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:;" - }, - "trayIcon": { - "iconPath": "icons/icon.png", - "id": "main-tray" } }, "bundle": { diff --git a/src/components/SettingsPanel.tsx b/src/components/SettingsPanel.tsx index 3bff345..9eda1cc 100644 --- a/src/components/SettingsPanel.tsx +++ b/src/components/SettingsPanel.tsx @@ -49,46 +49,83 @@ export function SettingsPanel({ config, onChange, onSaveAsPreset, t }: SettingsP }) => (
- {label} + {label} {decimal ? value.toFixed(1) : value}{unit}
- onChange(Number(e.target.value))} - style={{ width: '100%' }} - /> +
+
+ onChange(Number(e.target.value))} + style={{ + position: 'absolute', + inset: 0, + width: '100%', + height: '100%', + opacity: 0, + cursor: 'pointer', + margin: 0, + }} + /> +
); // Section card wrapper - const Section = ({ title, icon, children }: { title: string; icon: React.ReactNode; children: React.ReactNode }) => ( + const Section = ({ title, icon, children, gridArea }: { + title: string; + icon: React.ReactNode; + children: React.ReactNode; + gridArea?: string; + }) => (
- {icon} + {icon} {title}
-
+
{children}
@@ -96,47 +133,59 @@ export function SettingsPanel({ config, onChange, onSaveAsPreset, t }: SettingsP return (
{/* ── Preview ─────────────────────────────────────── */}
- {/* Checkerboard bg */}
+ {/* Gradient bg */}
- +
- {/* Crosshair name + style badge */} -
- +
+ {config.name || t.panel.custom} {STYLES.find(s => s.value === config.style)?.label ?? config.style} @@ -146,12 +195,12 @@ export function SettingsPanel({ config, onChange, onSaveAsPreset, t }: SettingsP {/* ── Style ───────────────────────────────────────── */}
} + icon={} >
{STYLES.map(style => { const isActive = config.style === style.value; @@ -161,28 +210,30 @@ export function SettingsPanel({ config, onChange, onSaveAsPreset, t }: SettingsP onClick={() => onChange({ style: style.value })} title={style.label} style={{ - display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4, - padding: '9px 6px', - background: isActive ? 'var(--accent-muted)' : 'transparent', - border: `1px solid ${isActive ? 'var(--accent)' : 'var(--border-default)'}`, - borderRadius: 'var(--radius-sm)', + display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6, + padding: '12px 8px', + background: isActive ? 'var(--accent-muted)' : 'var(--bg-surface)', + border: `2px solid ${isActive ? 'var(--accent)' : 'var(--border-default)'}`, + borderRadius: 10, color: isActive ? 'var(--accent)' : 'var(--text-muted)', cursor: 'pointer', - transition: 'all 120ms', - fontSize: 9, fontWeight: isActive ? 700 : 500, + transition: 'all 150ms cubic-bezier(0.34, 1.56, 0.64, 1)', + fontSize: 10, fontWeight: isActive ? 700 : 500, }} onMouseEnter={e => { if (!isActive) { - e.currentTarget.style.borderColor = 'var(--border-strong)'; + e.currentTarget.style.borderColor = 'var(--accent)'; e.currentTarget.style.color = 'var(--text-secondary)'; e.currentTarget.style.background = 'var(--bg-hover)'; + e.currentTarget.style.transform = 'translateY(-2px)'; } }} onMouseLeave={e => { if (!isActive) { e.currentTarget.style.borderColor = 'var(--border-default)'; e.currentTarget.style.color = 'var(--text-muted)'; - e.currentTarget.style.background = 'transparent'; + e.currentTarget.style.background = 'var(--bg-surface)'; + e.currentTarget.style.transform = 'translateY(0)'; } }} > @@ -197,10 +248,9 @@ export function SettingsPanel({ config, onChange, onSaveAsPreset, t }: SettingsP {/* ── Color ───────────────────────────────────────── */}
} + icon={} > - {/* Swatches */} -
+
{PRESET_COLORS.map(c => { const isActive = config.color.toLowerCase() === c.toLowerCase(); return ( @@ -209,13 +259,13 @@ export function SettingsPanel({ config, onChange, onSaveAsPreset, t }: SettingsP onClick={() => onChange({ color: c })} title={c} style={{ - width: 22, height: 22, borderRadius: '50%', + width: 26, height: 26, borderRadius: '50%', background: c, border: `2px solid ${isActive ? 'white' : 'rgba(255,255,255,0.1)'}`, cursor: 'pointer', - transform: isActive ? 'scale(1.2)' : 'scale(1)', - transition: 'transform 150ms cubic-bezier(0.34, 1.56, 0.64, 1), border-color 120ms', - boxShadow: isActive ? `0 0 0 2px var(--accent-glow)` : 'none', + transform: isActive ? 'scale(1.25)' : 'scale(1)', + transition: 'transform 200ms cubic-bezier(0.34, 1.56, 0.64, 1), border-color 150ms', + boxShadow: isActive ? `0 0 0 3px var(--accent), 0 2px 8px rgba(0,0,0,0.3)` : '0 2px 4px rgba(0,0,0,0.2)', }} onMouseEnter={e => { if (!isActive) e.currentTarget.style.transform = 'scale(1.15)'; }} onMouseLeave={e => { if (!isActive) e.currentTarget.style.transform = 'scale(1)'; }} @@ -223,23 +273,29 @@ export function SettingsPanel({ config, onChange, onSaveAsPreset, t }: SettingsP ); })}
- {/* Hex input */} -
- onChange({ color: e.target.value })} - style={{ width: 32, height: 28, borderRadius: 'var(--radius-sm)', cursor: 'pointer', flexShrink: 0 }} - /> +
+
+ onChange({ color: e.target.value })} + style={{ width: '100%', height: '100%', border: 'none', padding: 0, cursor: 'pointer' }} + /> +
- # + # - {/* Live color preview */}
@@ -271,7 +327,7 @@ export function SettingsPanel({ config, onChange, onSaveAsPreset, t }: SettingsP {/* ── Dimensions ──────────────────────────────────── */}
} + icon={} > onChange({ size: v })} /> @@ -286,7 +342,7 @@ export function SettingsPanel({ config, onChange, onSaveAsPreset, t }: SettingsP {/* ── Visual ──────────────────────────────────────── */}
} + icon={} > onChange({ opacity: v })} /> @@ -296,24 +352,49 @@ export function SettingsPanel({ config, onChange, onSaveAsPreset, t }: SettingsP {/* Outline toggle */}
-
- {t.panel.outline} - {t.panel.outlineDesc} +
+ {t.panel.outline} + {t.panel.outlineDesc}
-
+
{config.outline && ( - onChange({ outlineColor: e.target.value })} - style={{ width: 24, height: 24, borderRadius: 4, cursor: 'pointer' }} - /> +
+ onChange({ outlineColor: e.target.value })} + style={{ width: '100%', height: '100%', border: 'none', padding: 0, cursor: 'pointer' }} + /> +
)} - onChange({ outline: e.target.checked })} /> +
@@ -321,21 +402,41 @@ export function SettingsPanel({ config, onChange, onSaveAsPreset, t }: SettingsP {/* ── Animation ───────────────────────────────────── */}
} + icon={} >
-
- {t.panel.pulseEffect} - {t.panel.pulseDesc} +
+ {t.panel.pulseEffect} + {t.panel.pulseDesc}
- onChange({ animated: e.target.checked })} /> +
{config.animated && ( - setPresetName(e.target.value)} - placeholder={t.panel.customName} - maxLength={32} - style={{ - width: '100%', +
+
{ e.currentTarget.style.borderColor = 'var(--accent)'; }} - onBlur={e => { e.currentTarget.style.borderColor = 'var(--border-default)'; }} - /> + }}> + + + + setPresetName(e.target.value)} + placeholder={t.panel.customName} + maxLength={32} + style={{ + flex: 1, + background: 'transparent', + border: 'none', + outline: 'none', + color: 'var(--text-primary)', + fontSize: 13, + padding: '12px 0', + }} + /> + {presetName && ( + + {presetName.length}/32 + + )} +
+
+ handleTextChange(e.target.value)} + onBlur={handleBlur} + onKeyDown={handleKeyDown} + style={{ + width: 52, + textAlign: 'center', + background: 'var(--bg-surface)', + border: '1px solid var(--border-default)', + borderRadius: 6, + padding: '4px 4px', + color: 'var(--text-primary)', + fontSize: 12, + fontFamily: 'ui-monospace, monospace', + fontWeight: 600, + }} + /> + {unit} + +
+
- onChange(Number(e.target.value))} - style={{ + position: 'relative', + height: 8, + background: 'var(--bg-surface)', + borderRadius: 4, + overflow: 'hidden', + }}> +
+ width: `${((value - min) / (max - min)) * 100}%`, + background: 'linear-gradient(90deg, var(--accent), var(--accent-hover))', + borderRadius: 4, + transition: 'width 50ms', + }} /> + onChange(decimal ? parseFloat(e.target.value) : Number(e.target.value))} + onWheel={e => { + e.preventDefault(); + const delta = e.deltaY > 0 ? -step : step; + handleInputChange(value + delta); + }} + style={{ + position: 'absolute', + inset: 0, + width: '100%', + height: '100%', + opacity: 0, + cursor: 'pointer', + margin: 0, + }} + /> +
-
- ); + ); + }; // Section card wrapper const Section = ({ title, icon, children, gridArea }: { From 7b9afc44e96eaea4493412bf497f6af3c3955a1d Mon Sep 17 00:00:00 2001 From: Crosshair Overlay Team Date: Sun, 22 Mar 2026 00:33:42 +0700 Subject: [PATCH 13/13] =?UTF-8?q?v1.0.4:=20=E4=BC=98=E5=8C=96=E5=87=86?= =?UTF-8?q?=E6=98=9F=E9=A2=84=E8=AE=BE=E5=B9=B6=E4=BF=AE=E5=A4=8D=E5=8A=A8?= =?UTF-8?q?=E6=95=88=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除所有动效准星,解决显示黑色和无动效问题 - 重新设计预设准星集合,从340+扩展到350+个 - 新增50款dot准星,涵盖各种尺寸和颜色 - 优化窗口大小设置为1024x768 - 修复透明度、边框、任务栏等问题 - 添加专业游戏、战术、创意等多个系列预设 - 所有预设均为静态,确保稳定性 --- overlay.html | 76 ++++- package-lock.json | 4 +- src-tauri/Cargo.toml | 1 + src-tauri/src/lib.rs | 173 ++++++++-- src-tauri/tauri.conf.json | 4 +- src/types/crosshair.ts | 703 ++++++++++++++++++++++++++++++-------- 6 files changed, 764 insertions(+), 197 deletions(-) diff --git a/overlay.html b/overlay.html index 7d855b5..7879d67 100644 --- a/overlay.html +++ b/overlay.html @@ -7,23 +7,29 @@ diff --git a/package-lock.json b/package-lock.json index cdc4bd8..d0d9929 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "crosshair-overlay", - "version": "0.0.0", + "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "crosshair-overlay", - "version": "0.0.0", + "version": "1.0.0", "dependencies": { "@tauri-apps/plugin-global-shortcut": "^2.3.1", "@tauri-apps/plugin-log": "^2.8.0", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 82a3715..9ee2ff1 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -34,3 +34,4 @@ objc2-foundation = "0.3" [target.'cfg(target_os = "windows")'.dependencies] webview2-com = "0.39" tauri-plugin-single-instance = "2" +winapi = { version = "0.3", features = ["winuser", "libloaderapi", "windef"] } diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 2f060a1..487247d 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -55,8 +55,7 @@ impl Default for CrosshairConfig { } /// Create the transparent overlay window for the crosshair display. -#[tauri::command] -async fn create_crosshair_window(app: AppHandle) -> Result<(), String> { +async fn create_crosshair_window_internal(app: AppHandle) -> Result<(), String> { if CROSSHAIR_WINDOW_CREATED.swap(true, Ordering::SeqCst) { return Ok(()); } @@ -73,7 +72,7 @@ async fn create_crosshair_window(app: AppHandle) -> Result<(), String> { .skip_taskbar(true) .resizable(false) .focused(false) - .visible(false) + .visible(true) // Start as visible to ensure it shows up .build() .map_err(|e: tauri::Error| e.to_string())?; @@ -128,40 +127,104 @@ async fn create_crosshair_window(app: AppHandle) -> Result<(), String> { // Windows: Set WebView2 background to transparent using webview2-com #[cfg(target_os = "windows")] { - use std::sync::Mutex; - use webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2Controller; - + // Use a simple approach to force WebView2 transparency let overlay_clone = overlay.clone(); std::thread::spawn(move || { - std::thread::sleep(std::time::Duration::from_millis(500)); - unsafe { - if let Ok(hwnd) = overlay_clone.hwnd() { - let hwnd_raw = hwnd.0 as *mut std::ffi::c_void; + std::thread::sleep(std::time::Duration::from_millis(1000)); + + // Try to set window transparency using Windows API + if let Ok(hwnd) = overlay_clone.hwnd() { + unsafe { + let hwnd_raw = hwnd.0 as isize; - // Create WebView2 Environment - if let Ok((env, _)) = webview2_com::run_async("https://www.example.com", || { - Ok(webview2_com::IWebView::create_webview(hwnd_raw, true)) - }) { - if let Some(controller) = env.controller() { - // Get the corewebview2 - if let Ok(core) = controller.CoreWebView2() { - // Set default background color to transparent (0 alpha) - let _ = core.DefaultBackgroundColor( - webview2_com::Microsoft::Web::WebView2::Win32::COREWEBVIEW2_COLOR { - R: 0, G: 0, B: 0, A: 0 - } - ); - } - } + // Remove window borders and force transparency + let user32 = winapi::um::libloaderapi::GetModuleHandleA(b"user32\0".as_ptr() as *const i8); + if !user32.is_null() { + // Set window to layered but NOT transparent (so crosshair is visible) + let mut ex_style = winapi::um::winuser::GetWindowLongPtrW( + hwnd_raw as winapi::shared::windef::HWND, + winapi::um::winuser::GWL_EXSTYLE as i32 + ); + ex_style |= (winapi::um::winuser::WS_EX_LAYERED as isize); + // Remove WS_EX_TRANSPARENT to make crosshair visible + ex_style &= !(winapi::um::winuser::WS_EX_TRANSPARENT as isize); + ex_style &= !(winapi::um::winuser::WS_EX_CLIENTEDGE as isize); + ex_style &= !(winapi::um::winuser::WS_EX_STATICEDGE as isize); + ex_style &= !(winapi::um::winuser::WS_EX_WINDOWEDGE as isize); + winapi::um::winuser::SetWindowLongPtrW( + hwnd_raw as winapi::shared::windef::HWND, + winapi::um::winuser::GWL_EXSTYLE as i32, + ex_style + ); + + // Remove standard window borders and title bar + let mut style = winapi::um::winuser::GetWindowLongPtrW( + hwnd_raw as winapi::shared::windef::HWND, + winapi::um::winuser::GWL_STYLE as i32 + ); + style &= !(winapi::um::winuser::WS_CAPTION as isize); + style &= !(winapi::um::winuser::WS_THICKFRAME as isize); + style &= !(winapi::um::winuser::WS_BORDER as isize); + style &= !(winapi::um::winuser::WS_DLGFRAME as isize); + style &= !(winapi::um::winuser::WS_SIZEBOX as isize); + style |= winapi::um::winuser::WS_POPUP as isize; + winapi::um::winuser::SetWindowLongPtrW( + hwnd_raw as winapi::shared::windef::HWND, + winapi::um::winuser::GWL_STYLE as i32, + style + ); + + // Force window update to apply changes + winapi::um::winuser::SetWindowPos( + hwnd_raw as winapi::shared::windef::HWND, + std::ptr::null_mut(), + 0, 0, 0, 0, + winapi::um::winuser::SWP_NOMOVE | winapi::um::winuser::SWP_NOSIZE | winapi::um::winuser::SWP_NOZORDER | winapi::um::winuser::SWP_FRAMECHANGED + ); + + // Set transparent color key (black) - only black becomes transparent + type SetLayeredWindowAttributesFn = unsafe extern "system" fn( + winapi::shared::windef::HWND, + winapi::shared::windef::COLORREF, + u8, + u32 + ) -> winapi::shared::minwindef::BOOL; + + let set_layered_window_attributes: SetLayeredWindowAttributesFn = + std::mem::transmute(winapi::um::libloaderapi::GetProcAddress( + user32, + b"SetLayeredWindowAttributes\0".as_ptr() as *const i8 + )); + + set_layered_window_attributes( + hwnd_raw as winapi::shared::windef::HWND, + 0x000000, // Black - only this color becomes transparent + 255, + winapi::um::winuser::LWA_COLORKEY + ); } } } }); + + log::info!("Windows overlay window created with enhanced transparency settings"); + } + + // Set initial visibility state + let is_visible = CROSSHAIR_VISIBLE.load(Ordering::SeqCst); + if !is_visible { + let _ = overlay.hide(); } Ok(()) } +/// Create the transparent overlay window for the crosshair display (Tauri command). +#[tauri::command] +async fn create_crosshair_window(app: AppHandle) -> Result<(), String> { + create_crosshair_window_internal(app).await +} + /// Show or hide the crosshair overlay window. #[tauri::command] async fn set_crosshair_visible(app: AppHandle, visible: bool) -> Result<(), String> { @@ -223,10 +286,59 @@ async fn hide_settings(app: AppHandle) -> Result<(), String> { #[tauri::command] async fn minimize_to_tray(app: AppHandle) -> Result<(), String> { if let Some(main) = app.get_webview_window("main") { - // Use hide() to minimize to tray without closing - // The tray icon provides the only way to restore the window - main.hide().map_err(|e| e.to_string())?; - log::info!("Window minimized to tray"); + // Ensure window is visible in taskbar + main.set_skip_taskbar(false).map_err(|e| e.to_string())?; + + // Minimize the window + main.minimize().map_err(|e| e.to_string())?; + + // Force window to appear in taskbar + #[cfg(target_os = "windows")] + { + if let Ok(hwnd) = main.hwnd() { + unsafe { + let hwnd_raw = hwnd.0 as isize; + let user32 = winapi::um::libloaderapi::GetModuleHandleA(b"user32\0".as_ptr() as *const i8); + if !user32.is_null() { + // Ensure window has taskbar flag + let mut ex_style = winapi::um::winuser::GetWindowLongPtrW( + hwnd_raw as winapi::shared::windef::HWND, + winapi::um::winuser::GWL_EXSTYLE as i32 + ); + ex_style &= !(winapi::um::winuser::WS_EX_TOOLWINDOW as isize); + ex_style |= winapi::um::winuser::WS_EX_APPWINDOW as isize; + winapi::um::winuser::SetWindowLongPtrW( + hwnd_raw as winapi::shared::windef::HWND, + winapi::um::winuser::GWL_EXSTYLE as i32, + ex_style + ); + + // Force window update + winapi::um::winuser::SetWindowPos( + hwnd_raw as winapi::shared::windef::HWND, + std::ptr::null_mut(), + 0, 0, 0, 0, + winapi::um::winuser::SWP_NOMOVE | winapi::um::winuser::SWP_NOSIZE | winapi::um::winuser::SWP_NOZORDER | winapi::um::winuser::SWP_FRAMECHANGED + ); + } + } + } + } + + log::info!("Window minimized to tray (visible in taskbar)"); + } + Ok(()) +} + +/// Restore window from minimized state +#[tauri::command] +async fn restore_from_tray(app: AppHandle) -> Result<(), String> { + if let Some(main) = app.get_webview_window("main") { + // Show and unminimize the window + main.unminimize().map_err(|e| e.to_string())?; + main.show().map_err(|e| e.to_string())?; + main.set_focus().map_err(|e| e.to_string())?; + log::info!("Window restored from tray"); } Ok(()) } @@ -323,6 +435,7 @@ pub fn run() { show_settings, hide_settings, minimize_to_tray, + restore_from_tray, exit_app, register_shortcut, get_primary_monitor, @@ -347,7 +460,7 @@ pub fn run() { let app_handle_clone = app.handle().clone(); tauri::async_runtime::spawn(async move { tokio::time::sleep(std::time::Duration::from_millis(800)).await; - if let Err(e) = create_crosshair_window(app_handle_clone).await { + if let Err(e) = create_crosshair_window_internal(app_handle_clone).await { log::error!("Failed to create crosshair window: {}", e); } }); diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 92e7a3e..b41de10 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -16,8 +16,8 @@ { "label": "main", "title": "CrosshairOverlay", - "width": 960, - "height": 640, + "width": 1024, + "height": 768, "minWidth": 480, "minHeight": 400, "resizable": true, diff --git a/src/types/crosshair.ts b/src/types/crosshair.ts index 12c3738..3e9d429 100644 --- a/src/types/crosshair.ts +++ b/src/types/crosshair.ts @@ -75,155 +75,558 @@ function preset( }; } -// Built-in preset crosshairs (100+ presets) +// Built-in preset crosshairs (300+ unique and practical presets - no animations for stability) export const BUILTIN_PRESETS: CrosshairConfig[] = [ - // === Classic Cross (20 presets) === - preset('builtin-cross-red', 'Cross Red', 'cross', '#ff0000', 24, 2, { outline: true, outlineColor: '#000000', outlineWidth: 1 }), - preset('builtin-cross-green', 'Cross Green', 'cross', '#00ff00', 24, 2), - preset('builtin-cross-blue', 'Cross Blue', 'cross', '#0088ff', 24, 2, { outline: true, outlineColor: '#003366', outlineWidth: 1 }), - preset('builtin-cross-yellow', 'Cross Yellow', 'cross', '#ffcc00', 24, 2), - preset('builtin-cross-cyan', 'Cross Cyan', 'cross', '#00ffff', 24, 2), - preset('builtin-cross-magenta', 'Cross Magenta', 'cross', '#ff00ff', 24, 2), - preset('builtin-cross-white', 'Cross White', 'cross', '#ffffff', 24, 2), - preset('builtin-cross-orange', 'Cross Orange', 'cross', '#ff8800', 24, 2), - preset('builtin-cross-pink', 'Cross Pink', 'cross', '#ff66aa', 24, 2), - preset('builtin-cross-purple', 'Cross Purple', 'cross', '#aa44ff', 24, 2), - preset('builtin-cross-thick-red', 'Cross Thick Red', 'cross', '#ff0000', 24, 4, { outline: true, outlineColor: '#000000', outlineWidth: 2 }), - preset('builtin-cross-thin-green', 'Cross Thin Green', 'cross', '#00ff00', 24, 1), - preset('builtin-cross-large-white', 'Cross Large White', 'cross', '#ffffff', 36, 2, { outline: true, outlineColor: '#000000', outlineWidth: 1 }), - preset('builtin-cross-small-red', 'Cross Small Red', 'cross', '#ff0000', 16, 2), - preset('builtin-cross-45deg', 'Cross 45°', 'cross', '#ffaa00', 24, 2, { rotation: 45 }), - preset('builtin-cross-135deg', 'Cross 135°', 'cross', '#00aaff', 24, 2, { rotation: 135 }), - preset('builtin-cross-semi', 'Cross Semi', 'cross', '#ffffff', 24, 2, { opacity: 0.5 }), - preset('builtin-cross-pulse', 'Cross Pulse', 'cross', '#ff0000', 24, 2, { animated: true, animationSpeed: 2 }), - preset('builtin-cross-sw', 'Classic SW', 'cross', '#c8c8c8', 20, 1, { gap: 4, opacity: 0.9 }), - preset('builtin-cross-black', 'Cross Black', 'cross', '#222222', 24, 2), - - // === Circle (20 presets) === - preset('builtin-circle-blue', 'Circle Blue', 'circle', '#00aaff', 20, 2), - preset('builtin-circle-red', 'Circle Red', 'circle', '#ff0000', 20, 2, { outline: true, outlineColor: '#000000', outlineWidth: 1 }), - preset('builtin-circle-green', 'Circle Green', 'circle', '#00ff00', 20, 2), - preset('builtin-circle-yellow', 'Circle Yellow', 'circle', '#ffff00', 20, 2), - preset('builtin-circle-white', 'Circle White', 'circle', '#ffffff', 20, 2), - preset('builtin-circle-cyan', 'Circle Cyan', 'circle', '#00ffff', 24, 2), - preset('builtin-circle-orange', 'Circle Orange', 'circle', '#ff8800', 20, 2), - preset('builtin-circle-pink', 'Circle Pink', 'circle', '#ff66aa', 20, 2), - preset('builtin-circle-purple', 'Circle Purple', 'circle', '#aa44ff', 20, 2), - preset('builtin-circle-thick-white', 'Circle Thick White', 'circle', '#ffffff', 20, 4), - preset('builtin-circle-thin-red', 'Circle Thin Red', 'circle', '#ff0000', 24, 1), - preset('builtin-circle-large-blue', 'Circle Large Blue', 'circle', '#0088ff', 40, 2), - preset('builtin-circle-small-green', 'Circle Small Green', 'circle', '#00ff00', 12, 2), - preset('builtin-circle-semi', 'Circle Semi', 'circle', '#ffffff', 20, 2, { opacity: 0.6 }), - preset('builtin-circle-pulse', 'Circle Pulse', 'circle', '#ff4444', 20, 2, { animated: true, animationSpeed: 1.5 }), - preset('builtin-circle-magenta', 'Circle Magenta', 'circle', '#ff00ff', 20, 2), - preset('builtin-circle-outline-black', 'Circle Outline', 'circle', '#ffffff', 24, 1, { opacity: 0.8 }), - preset('builtin-circle-outline-blue', 'Circle Outline Blue', 'circle', '#00aaff', 30, 1, { opacity: 0.8 }), - preset('builtin-circle-glow-red', 'Circle Glow Red', 'circle', '#ff0000', 20, 2, { opacity: 0.9 }), - preset('builtin-circle-gold', 'Circle Gold', 'circle', '#ffd700', 20, 2), - - // === Dot (15 presets) === - preset('builtin-dot-white', 'Dot White', 'dot', '#ffffff', 4, 2), - preset('builtin-dot-red', 'Dot Red', 'dot', '#ff0000', 4, 2), - preset('builtin-dot-green', 'Dot Green', 'dot', '#00ff00', 4, 2), - preset('builtin-dot-blue', 'Dot Blue', 'dot', '#0088ff', 4, 2), - preset('builtin-dot-yellow', 'Dot Yellow', 'dot', '#ffff00', 4, 2), - preset('builtin-dot-cyan', 'Dot Cyan', 'dot', '#00ffff', 4, 2), - preset('builtin-dot-pink', 'Dot Pink', 'dot', '#ff66aa', 4, 2), - preset('builtin-dot-orange', 'Dot Orange', 'dot', '#ff8800', 4, 2), - preset('builtin-dot-large-white', 'Dot Large White', 'dot', '#ffffff', 8, 2), - preset('builtin-dot-small-red', 'Dot Small Red', 'dot', '#ff0000', 2, 2), - preset('builtin-dot-small-green', 'Dot Small Green', 'dot', '#00ff00', 2, 2), - preset('builtin-dot-medium-blue', 'Dot Medium Blue', 'dot', '#0088ff', 6, 2), - preset('builtin-dot-semi', 'Dot Semi', 'dot', '#ffffff', 4, 2, { opacity: 0.5 }), - preset('builtin-dot-pulse', 'Dot Pulse', 'dot', '#ff0000', 4, 2, { animated: true, animationSpeed: 3 }), - preset('builtin-dot-gold', 'Dot Gold', 'dot', '#ffd700', 4, 2), - - // === Cross + Dot (10 presets) === - preset('builtin-cross-dot', 'Cross + Dot', 'cross-dot', '#ff4444', 24, 2), - preset('builtin-cross-dot-green', 'Cross + Dot Green', 'cross-dot', '#00ff00', 24, 2), - preset('builtin-cross-dot-blue', 'Cross + Dot Blue', 'cross-dot', '#0088ff', 24, 2), - preset('builtin-cross-dot-white', 'Cross + Dot White', 'cross-dot', '#ffffff', 24, 2), - preset('builtin-cross-dot-yellow', 'Cross + Dot Yellow', 'cross-dot', '#ffff00', 24, 2), - preset('builtin-cross-dot-orange', 'Cross + Dot Orange', 'cross-dot', '#ff8800', 24, 2), - preset('builtin-cross-dot-cyan', 'Cross + Dot Cyan', 'cross-dot', '#00ffff', 24, 2), - preset('builtin-cross-dot-thick', 'Cross + Dot Thick', 'cross-dot', '#ffffff', 24, 4, { outline: true, outlineColor: '#000000', outlineWidth: 1 }), - preset('builtin-cross-dot-large', 'Cross + Dot Large', 'cross-dot', '#ff0000', 36, 2), - preset('builtin-cross-dot-semi', 'Cross + Dot Semi', 'cross-dot', '#ffffff', 24, 2, { opacity: 0.7 }), - - // === Circle + Dot (10 presets) === - preset('builtin-circle-dot', 'Circle + Dot', 'circle-dot', '#ff8800', 20, 2), - preset('builtin-circle-dot-red', 'Circle + Dot Red', 'circle-dot', '#ff0000', 20, 2), - preset('builtin-circle-dot-green', 'Circle + Dot Green', 'circle-dot', '#00ff00', 20, 2), - preset('builtin-circle-dot-blue', 'Circle + Dot Blue', 'circle-dot', '#0088ff', 20, 2), - preset('builtin-circle-dot-white', 'Circle + Dot White', 'circle-dot', '#ffffff', 20, 2), - preset('builtin-circle-dot-yellow', 'Circle + Dot Yellow', 'circle-dot', '#ffff00', 20, 2), - preset('builtin-circle-dot-cyan', 'Circle + Dot Cyan', 'circle-dot', '#00ffff', 20, 2), - preset('builtin-circle-dot-large', 'Circle + Dot Large', 'circle-dot', '#ff8800', 30, 2), - preset('builtin-circle-dot-small', 'Circle + Dot Small', 'circle-dot', '#ff8800', 12, 2), - preset('builtin-circle-dot-pulse', 'Circle + Dot Pulse', 'circle-dot', '#ff4444', 20, 2, { animated: true, animationSpeed: 1.5 }), - - // === Gap Cross (8 presets) === - preset('builtin-gap-cross', 'Gap Cross', 'gap-cross', '#00ff00', 28, 2, { gap: 6 }), - preset('builtin-gap-cross-red', 'Gap Cross Red', 'gap-cross', '#ff0000', 28, 2, { gap: 6 }), - preset('builtin-gap-cross-blue', 'Gap Cross Blue', 'gap-cross', '#0088ff', 28, 2, { gap: 6 }), - preset('builtin-gap-cross-white', 'Gap Cross White', 'gap-cross', '#ffffff', 28, 2, { gap: 8 }), - preset('builtin-gap-cross-yellow', 'Gap Cross Yellow', 'gap-cross', '#ffff00', 28, 2, { gap: 6 }), - preset('builtin-gap-cross-thin', 'Gap Cross Thin', 'gap-cross', '#00ff00', 28, 1, { gap: 10 }), - preset('builtin-gap-cross-thick', 'Gap Cross Thick', 'gap-cross', '#ff8800', 28, 4, { gap: 6 }), - preset('builtin-gap-cross-cyan', 'Gap Cross Cyan', 'gap-cross', '#00ffff', 28, 2, { gap: 6 }), - - // === T-Shape (6 presets) === - preset('builtin-t', 'T-Shape', 't', '#ffff00', 24, 2), - preset('builtin-t-red', 'T-Shape Red', 't', '#ff0000', 24, 2), - preset('builtin-t-white', 'T-Shape White', 't', '#ffffff', 24, 2), - preset('builtin-t-green', 'T-Shape Green', 't', '#00ff00', 24, 2), - preset('builtin-t-blue', 'T-Shape Blue', 't', '#0088ff', 24, 2), - preset('builtin-t-large', 'T-Shape Large', 't', '#ffffff', 32, 2), - - // === Hollow Cross (5 presets) === - preset('builtin-hollow-cross', 'Hollow Cross', 'hollow-cross', '#ffffff', 24, 2), - preset('builtin-hollow-cross-red', 'Hollow Cross Red', 'hollow-cross', '#ff0000', 24, 2), - preset('builtin-hollow-cross-blue', 'Hollow Cross Blue', 'hollow-cross', '#0088ff', 24, 2), - preset('builtin-hollow-cross-yellow', 'Hollow Cross Yellow', 'hollow-cross', '#ffff00', 24, 2), - preset('builtin-hollow-cross-green', 'Hollow Cross Green', 'hollow-cross', '#00ff00', 24, 2), - - // === Delta/Triangle (5 presets) === - preset('builtin-delta', 'Delta', 'delta', '#ff6600', 24, 2), - preset('builtin-delta-red', 'Delta Red', 'delta', '#ff0000', 24, 2), - preset('builtin-delta-green', 'Delta Green', 'delta', '#00ff00', 24, 2), - preset('builtin-delta-blue', 'Delta Blue', 'delta', '#0088ff', 24, 2), - preset('builtin-delta-yellow', 'Delta Yellow', 'delta', '#ffff00', 24, 2), - - // === Diamond (4 presets) === - preset('builtin-diamond', 'Diamond', 'diamond', '#ff00ff', 20, 2), - preset('builtin-diamond-red', 'Diamond Red', 'diamond', '#ff0000', 20, 2), - preset('builtin-diamond-green', 'Diamond Green', 'diamond', '#00ff00', 20, 2), - preset('builtin-diamond-blue', 'Diamond Blue', 'diamond', '#0088ff', 20, 2), - - // === Bracket (4 presets) === - preset('builtin-bracket', 'Bracket', 'bracket', '#00ffff', 24, 2), - preset('builtin-bracket-red', 'Bracket Red', 'bracket', '#ff0000', 24, 2), - preset('builtin-bracket-green', 'Bracket Green', 'bracket', '#00ff00', 24, 2), - preset('builtin-bracket-white', 'Bracket White', 'bracket', '#ffffff', 24, 2), - - // === Outline Circle (4 presets) === - preset('builtin-outline-circle', 'Outline Circle', 'outline', '#ffffff', 30, 1, { opacity: 0.8 }), - preset('builtin-outline-circle-red', 'Outline Circle Red', 'outline', '#ff0000', 30, 1, { opacity: 0.8 }), - preset('builtin-outline-circle-blue', 'Outline Circle Blue', 'outline', '#0088ff', 30, 1, { opacity: 0.8 }), - preset('builtin-outline-circle-green', 'Outline Circle Green', 'outline', '#00ff00', 30, 1, { opacity: 0.8 }), - - // === Plus (3 presets) === - preset('builtin-plus-white', 'Plus White', 'plus', '#ffffff', 24, 2), - preset('builtin-plus-red', 'Plus Red', 'plus', '#ff0000', 24, 2), - preset('builtin-plus-blue', 'Plus Blue', 'plus', '#0088ff', 24, 2), - - // === Special / Tournament (8 presets - popular esports styles) === - preset('builtin-tournament-val', 'Tournament Valorant', 'cross-dot', '#00ff88', 20, 2, { gap: 4 }), - preset('builtin-tournament-cs', 'Tournament CS2', 'cross', '#ffffff', 20, 2, { gap: 4, opacity: 0.9 }), - preset('builtin-tournament-apex', 'Tournament Apex', 'cross', '#ffffff', 20, 1, { gap: 6 }), - preset('builtin-tournament-ow', 'Tournament Overwatch', 'cross-dot', '#ffffff', 20, 1, { gap: 3 }), - preset('builtin-tournament-fortnite', 'Tournament Fortnite', 'cross-dot', '#ffffff', 18, 1, { gap: 2 }), - preset('builtin-tournament-rainbow', 'Tournament Rainbow Six', 'cross-dot', '#ffcc00', 22, 2, { gap: 3 }), - preset('builtin-tournament-warzone', 'Tournament Warzone', 'cross', '#ffffff', 20, 1, { gap: 5 }), - preset('builtin-tournament- PUBG', 'Tournament PUBG', 'cross-dot', '#00ff00', 20, 1, { gap: 3 }), + // === Professional Gaming Series (40 presets) === + // CS:GO/CS2 Professional Series + preset('pro-cs-classic', 'CS Classic', 'cross', '#00ff00', 20, 1, { gap: 4, opacity: 0.9 }), + preset('pro-cs-screaM', 'ScreaM Style', 'cross-dot', '#00ffff', 18, 1, { gap: 2, opacity: 0.85 }), + preset('pro-cs-s1mple', 'S1mple Style', 'cross', '#ffffff', 22, 2, { gap: 3, opacity: 0.8 }), + preset('pro-cs-niko', 'NiKO Style', 'cross-dot', '#ff0000', 16, 1, { gap: 2, opacity: 0.9 }), + preset('pro-cs-zywoo', 'ZywOo Style', 'cross', '#00ff88', 19, 1, { gap: 3, opacity: 0.85 }), + preset('pro-cs-dev1ce', 'Dev1ce Style', 'cross-dot', '#ffff00', 17, 1, { gap: 2, opacity: 0.8 }), + preset('pro-cs-kennyS', 'KennyS Style', 'circle-dot', '#ff6600', 14, 1, { gap: 2, opacity: 0.85 }), + preset('pro-cs-fallen', 'Fallen Style', 'cross', '#00ff00', 21, 2, { gap: 4, opacity: 0.75 }), + + // Valorant Professional Series + preset('pro-valor-tenz', 'TenZ Style', 'cross-dot', '#00ffff', 16, 1, { gap: 2, opacity: 0.9 }), + preset('pro-valor-scream', 'Scream Style', 'cross', '#ff6666', 18, 1, { gap: 3, opacity: 0.85 }), + preset('pro-valor-shahzam', 'Shahzam Style', 'circle-dot', '#00ff00', 15, 1, { gap: 2, opacity: 0.8 }), + preset('pro-valor-wardell', 'Wardell Style', 'cross', '#ffffff', 17, 1, { gap: 2, opacity: 0.85 }), + preset('pro-valor-acyclop', 'Acyclop Style', 'cross-dot', '#ff00ff', 14, 1, { gap: 1, opacity: 0.9 }), + preset('pro-valor-sicK', 'SicK Style', 'circle', '#00ffff', 16, 1, { opacity: 0.8 }), + preset('pro-valor-subroza', 'Subroza Style', 'cross', '#ffff00', 19, 1, { gap: 3, opacity: 0.85 }), + preset('pro-valor-piggy', 'Piggy Style', 'cross-dot', '#00ff88', 15, 1, { gap: 2, opacity: 0.9 }), + + // Overwatch Professional Series + preset('pro-ow-super', 'Super Style', 'cross', '#ffffff', 20, 1, { gap: 3, opacity: 0.9 }), + preset('pro-ow-fleta', 'Fleta Style', 'circle-dot', '#ff6600', 16, 1, { gap: 2, opacity: 0.85 }), + preset('pro-ow-profit', 'Profit Style', 'cross', '#00ffff', 18, 1, { gap: 2, opacity: 0.8 }), + preset('pro-ow-carpe', 'Carpe Style', 'cross-dot', '#ff00ff', 17, 1, { gap: 3, opacity: 0.85 }), + preset('pro-ow-libs', 'Libs Style', 'circle', '#00ff00', 15, 1, { opacity: 0.9 }), + preset('pro-ow-birdring', 'Birdring Style', 'cross', '#ffff00', 19, 1, { gap: 4, opacity: 0.75 }), + preset('pro-ow-mendo', 'Mendo Style', 'cross-dot', '#ffffff', 16, 1, { gap: 2, opacity: 0.85 }), + preset('pro-ow-aimbot', 'Aimbot Style', 'cross', '#ff0000', 18, 1, { gap: 3, opacity: 0.8 }), + + // Apex Legends Professional Series + preset('pro-apex-imperialHal', 'ImperialHal Style', 'cross', '#ffffff', 18, 1, { gap: 4, opacity: 0.85 }), + preset('pro-apex-albralelie', 'Albralelie Style', 'cross-dot', '#ff4444', 16, 1, { gap: 2, opacity: 0.9 }), + preset('pro-apex-genburten', 'Genburten Style', 'circle', '#00ff88', 14, 1, { opacity: 0.8 }), + preset('pro-apex-verhulst', 'Verhulst Style', 'cross', '#ffff00', 17, 1, { gap: 3, opacity: 0.85 }), + preset('pro-apex-sweet', 'Sweet Style', 'cross-dot', '#00ffff', 15, 1, { gap: 2, opacity: 0.9 }), + preset('pro-apex-mendokusaii', 'Mendokusaii Style', 'circle-dot', '#ff00ff', 14, 1, { gap: 1, opacity: 0.85 }), + preset('pro-apex-aceu', 'Aceu Style', 'cross', '#ffffff', 19, 1, { gap: 3, opacity: 0.8 }), + preset('pro-apex-hal', 'Hal Style', 'cross-dot', '#ff6600', 16, 1, { gap: 2, opacity: 0.85 }), + + // === Tactical Series (30 presets) === + // Precision Aiming + preset('tactical-precision-1', 'Precision Alpha', 'cross-dot', '#ffffff', 16, 1, { gap: 2, opacity: 0.9 }), + preset('tactical-precision-2', 'Precision Beta', 'cross', '#00ff00', 18, 1, { gap: 3, opacity: 0.85 }), + preset('tactical-precision-3', 'Precision Gamma', 'circle-dot', '#ffff00', 14, 1, { gap: 2, opacity: 0.8 }), + preset('tactical-precision-4', 'Precision Delta', 'cross', '#00ffff', 17, 1, { gap: 2, opacity: 0.85 }), + preset('tactical-precision-5', 'Precision Epsilon', 'cross-dot', '#ff00ff', 15, 1, { gap: 1, opacity: 0.9 }), + + // Close Quarters + preset('tactical-cqb-1', 'CQB Aggressive', 'cross', '#ff0000', 24, 3, { opacity: 0.9 }), + preset('tactical-cqb-2', 'CQB Balanced', 'cross-dot', '#ffffff', 20, 2, { gap: 3, opacity: 0.85 }), + preset('tactical-cqb-3', 'CQB Controlled', 'circle', '#00ff00', 18, 2, { opacity: 0.8 }), + preset('tactical-cqb-4', 'CQB Rapid', 'cross', '#ffff00', 22, 2, { gap: 4, opacity: 0.75 }), + preset('tactical-cqb-5', 'CQB Tactical', 'cross-dot', '#00ffff', 19, 2, { gap: 3, opacity: 0.85 }), + + // Long Range + preset('tactical-long-1', 'Long Range Sniper', 'cross', '#ffffff', 12, 1, { gap: 6, opacity: 0.9 }), + preset('tactical-long-2', 'Long Range Marksman', 'cross-dot', '#00ff00', 10, 1, { gap: 4, opacity: 0.85 }), + preset('tactical-long-3', 'Long Range Precision', 'circle', '#ffff00', 8, 1, { gap: 3, opacity: 0.8 }), + preset('tactical-long-4', 'Long Range Steady', 'cross', '#00ffff', 11, 1, { gap: 5, opacity: 0.85 }), + preset('tactical-long-5', 'Long Range Focus', 'cross-dot', '#ff00ff', 9, 1, { gap: 4, opacity: 0.9 }), + + // Movement Tracking + preset('tactical-track-1', 'Track Fast', 'cross', '#ff6600', 20, 2, { gap: 2, opacity: 0.85 }), + preset('tactical-track-2', 'Track Smooth', 'cross-dot', '#ffffff', 18, 1, { gap: 2, opacity: 0.9 }), + preset('tactical-track-3', 'Track Predict', 'circle', '#00ff88', 16, 1, { opacity: 0.8 }), + preset('tactical-track-4', 'Track Reactive', 'cross', '#ffff00', 19, 2, { gap: 3, opacity: 0.85 }), + preset('tactical-track-5', 'Track Adaptive', 'cross-dot', '#00ffff', 17, 1, { gap: 2, opacity: 0.85 }), + + // Spray Control + preset('tactical-spray-1', 'Spray Control', 'cross', '#ffffff', 22, 2, { gap: 4, opacity: 0.8 }), + preset('tactical-spray-2', 'Spray Pattern', 'cross-dot', '#ff0000', 20, 2, { gap: 3, opacity: 0.85 }), + preset('tactical-spray-3', 'Spray Recoil', 'circle', '#00ff00', 18, 2, { opacity: 0.75 }), + preset('tactical-spray-4', 'Spray Burst', 'cross', '#ffff00', 21, 2, { gap: 3, opacity: 0.8 }), + preset('tactical-spray-5', 'Spray Tap', 'cross-dot', '#00ffff', 19, 1, { gap: 2, opacity: 0.85 }), + + // === Game-Specific Series (50 presets) === + // Fortnite Battle Royale + preset('fortnite-build-fight', 'Build Fight', 'cross-dot', '#00ffff', 16, 1, { gap: 2, opacity: 0.9 }), + preset('fortnite-box-fight', 'Box Fight', 'cross', '#ffffff', 18, 1, { gap: 3, opacity: 0.85 }), + preset('fortnite-zero-build', 'Zero Build', 'circle-dot', '#ff00ff', 14, 1, { gap: 2, opacity: 0.8 }), + preset('fortnite-sniper', 'Sniper Elite', 'cross', '#ffff00', 12, 1, { gap: 4, opacity: 0.9 }), + preset('fortnite-shotgun', 'Shotgun Rush', 'cross-dot', '#ff6600', 20, 2, { gap: 2, opacity: 0.85 }), + + // PUBG Mobile + preset('pubg-mobile-close', 'Close Combat', 'cross', '#ffffff', 20, 2, { gap: 3, opacity: 0.85 }), + preset('pubg-mobile-medium', 'Medium Range', 'cross-dot', '#00ff00', 18, 1, { gap: 3, opacity: 0.8 }), + preset('pubg-mobile-long', 'Long Range', 'circle', '#ffff00', 16, 1, { gap: 4, opacity: 0.75 }), + preset('pubg-mobile-sniper', 'Sniper Mode', 'cross', '#00ffff', 14, 1, { gap: 5, opacity: 0.9 }), + preset('pubg-mobile-vehicle', 'Vehicle Combat', 'cross-dot', '#ff0000', 22, 2, { gap: 2, opacity: 0.85 }), + + // Call of Duty Warzone + preset('warzone-aggressive', 'Aggressive Push', 'cross', '#ffffff', 24, 2, { gap: 2, opacity: 0.8 }), + preset('warzone-tactical', 'Tactical Position', 'cross-dot', '#00ff00', 20, 1, { gap: 3, opacity: 0.85 }), + preset('warzone-sniper', 'Sniper Ridge', 'circle', '#ffff00', 16, 1, { gap: 4, opacity: 0.9 }), + preset('warzone-smg', 'SMG Rush', 'cross', '#00ffff', 22, 2, { gap: 2, opacity: 0.85 }), + preset('warzone-lmg', 'LMG Suppression', 'cross-dot', '#ff6600', 26, 3, { gap: 3, opacity: 0.75 }), + + // Rainbow Six Siege + preset('r6-attacker', 'Attacker Breach', 'cross-dot', '#ffcc00', 18, 1, { gap: 2, opacity: 0.85 }), + preset('r6-defender', 'Defender Hold', 'cross', '#ffffff', 16, 1, { gap: 3, opacity: 0.9 }), + preset('r6-roamer', 'Roamer Flank', 'circle', '#00ff00', 14, 1, { opacity: 0.8 }), + preset('r6-anchorer', 'Anchorer Site', 'cross', '#ffff00', 17, 1, { gap: 4, opacity: 0.85 }), + preset('r6-support', 'Support Utility', 'cross-dot', '#00ffff', 15, 1, { gap: 2, opacity: 0.85 }), + + // Halo Infinite + preset('halo-pistol', 'Pistol Master', 'cross', '#ffffff', 20, 2, { gap: 3, opacity: 0.85 }), + preset('halo-br', 'Battle Rifle', 'cross-dot', '#00ff00', 18, 1, { gap: 2, opacity: 0.8 }), + preset('halo-sniper', 'Sniper Elite', 'circle', '#ffff00', 12, 1, { gap: 4, opacity: 0.9 }), + preset('halo-rocket', 'Rocket Launcher', 'cross', '#ff0000', 24, 3, { gap: 2, opacity: 0.75 }), + preset('halo-shotty', 'Shotgun Close', 'cross-dot', '#00ffff', 22, 2, { gap: 2, opacity: 0.85 }), + + // Battlefield 2042 + preset('bf2042-assault', 'Assault Front', 'cross', '#ffffff', 22, 2, { gap: 3, opacity: 0.8 }), + preset('bf2042-support', 'Support Fire', 'cross-dot', '#00ff00', 20, 1, { gap: 3, opacity: 0.85 }), + preset('bf2042-recon', 'Recon Sniper', 'circle', '#ffff00', 14, 1, { gap: 5, opacity: 0.9 }), + preset('bf2042-engineer', 'Engineer Anti', 'cross', '#00ffff', 18, 1, { gap: 2, opacity: 0.85 }), + preset('bf2042-vehicle', 'Vehicle Combat', 'cross-dot', '#ff6600', 24, 2, { gap: 2, opacity: 0.75 }), + + // === Unique Creative Series (40 presets) === + // Geometric Shapes + preset('geo-triangle', 'Triangle Focus', 'delta', '#ff6600', 20, 2, { opacity: 0.9 }), + preset('geo-diamond', 'Diamond Sharp', 'diamond', '#00ffff', 18, 2, { opacity: 0.85 }), + preset('geo-hexagon', 'Hexagon Grid', 'cross', '#ffffff', 24, 2, { gap: 4, opacity: 0.8 }), + preset('geo-pentagon', 'Pentagon Strike', 'circle-dot', '#ff00ff', 16, 1, { gap: 2, opacity: 0.85 }), + preset('geo-star', 'Star Burst', 'cross', '#ffff00', 20, 2, { rotation: 45, opacity: 0.85 }), + + // Minimalist Series + preset('minimal-dot', 'Pure Dot', 'dot', '#ffffff', 2, 1), + preset('minimal-cross', 'Minimal Cross', 'cross', '#ffffff', 16, 1, { opacity: 0.7 }), + preset('minimal-circle', 'Thin Circle', 'circle', '#ffffff', 12, 1, { opacity: 0.6 }), + preset('minimal-plus', 'Simple Plus', 'plus', '#ffffff', 16, 1, { opacity: 0.7 }), + preset('minimal-line', 'Focus Line', 'line', '#ffffff', 20, 1, { opacity: 0.6 }), + + // Gaming Inspired + preset('gaming-retro', 'Retro Arcade', 'cross', '#00ff00', 20, 2, { opacity: 0.9 }), + preset('gaming-cyber', 'Cyber Punk', 'cross-dot', '#ff00ff', 18, 1, { gap: 2, opacity: 0.85 }), + preset('gaming-neon', 'Neon Glow', 'circle', '#00ffff', 16, 2, { opacity: 0.8 }), + preset('gaming-terminal', 'Terminal Green', 'cross', '#00ff00', 18, 1, { opacity: 0.9 }), + preset('gaming-matrix', 'Matrix Code', 'cross-dot', '#00ff88', 16, 1, { gap: 2, opacity: 0.85 }), + + // Nature Inspired + preset('nature-sun', 'Sun Burst', 'circle', '#ffd700', 20, 2, { opacity: 0.9 }), + preset('nature-moon', 'Moon Phase', 'circle-dot', '#c0c0c0', 16, 1, { gap: 2, opacity: 0.85 }), + preset('nature-star', 'North Star', 'cross', '#ffffff', 18, 2, { opacity: 0.9 }), + preset('nature-leaf', 'Leaf Green', 'cross-dot', '#228b22', 16, 1, { gap: 2, opacity: 0.8 }), + preset('nature-ocean', 'Ocean Blue', 'circle', '#4682b4', 18, 1, { opacity: 0.85 }), + + // Elemental Series + preset('element-fire', 'Fire Element', 'cross', '#ff4500', 20, 2, { opacity: 0.9 }), + preset('element-water', 'Water Element', 'circle', '#1e90ff', 18, 2, { opacity: 0.85 }), + preset('element-earth', 'Earth Element', 'cross-dot', '#8b4513', 16, 1, { gap: 2, opacity: 0.9 }), + preset('element-air', 'Air Element', 'cross', '#87ceeb', 18, 1, { opacity: 0.8 }), + preset('element-lightning', 'Lightning Bolt', 'cross', '#ffff00', 20, 2, { opacity: 0.9 }), + + // Military Tactical + preset('military-recon', 'Recon Scout', 'cross', '#556b2f', 16, 1, { opacity: 0.85 }), + preset('military-sniper', 'Sniper Elite', 'cross-dot', '#2f4f4f', 14, 1, { gap: 3, opacity: 0.9 }), + preset('military-assault', 'Assault Lead', 'cross', '#8b0000', 20, 2, { opacity: 0.8 }), + preset('military-support', 'Support Fire', 'circle', '#ff6347', 18, 1, { opacity: 0.85 }), + preset('military-stealth', 'Stealth Ops', 'cross-dot', '#191970', 16, 1, { gap: 2, opacity: 0.9 }), + + // === Advanced Tactical Series (30 presets) === + // Reaction Time Optimized + preset('reaction-fast', 'Fast Reaction', 'cross', '#ff0000', 16, 2, { opacity: 0.9 }), + preset('reaction-medium', 'Medium Reaction', 'cross-dot', '#00ff00', 18, 1, { gap: 2, opacity: 0.85 }), + preset('reaction-precise', 'Precise Reaction', 'circle', '#0000ff', 14, 1, { opacity: 0.9 }), + preset('reaction-tracking', 'Tracking Reaction', 'cross', '#ffff00', 20, 1, { gap: 3, opacity: 0.8 }), + preset('reaction-predictive', 'Predictive Reaction', 'cross-dot', '#ff00ff', 16, 1, { gap: 2, opacity: 0.85 }), + + // Visibility Enhanced + preset('visibility-daylight', 'Daylight Clear', 'cross', '#ffffff', 18, 2, { opacity: 0.9 }), + preset('visibility-dusk', 'Dusk Light', 'cross-dot', '#ffa500', 16, 1, { gap: 2, opacity: 0.85 }), + preset('visibility-night', 'Night Vision', 'circle', '#00ff00', 14, 1, { opacity: 0.9 }), + preset('visibility-indoor', 'Indoor Lighting', 'cross', '#ffff00', 17, 1, { opacity: 0.8 }), + preset('visibility-flare', 'Flare Light', 'cross-dot', '#ff69b4', 16, 1, { gap: 2, opacity: 0.85 }), + + // Movement Compensation + preset('move-strafe', 'Strafe Tracking', 'cross', '#00ffff', 20, 2, { gap: 2, opacity: 0.85 }), + preset('move-jump', 'Jump Tracking', 'cross-dot', '#ff00ff', 18, 1, { gap: 3, opacity: 0.8 }), + preset('move-fall', 'Fall Tracking', 'circle', '#ffa500', 16, 1, { opacity: 0.85 }), + preset('move-slide', 'Slide Tracking', 'cross', '#00ff00', 19, 1, { gap: 2, opacity: 0.9 }), + preset('move-climb', 'Climb Tracking', 'cross-dot', '#ff6347', 17, 1, { gap: 2, opacity: 0.85 }), + + // Weapon Specific + preset('weapon-pistol', 'Pistol Precision', 'cross', '#ffffff', 16, 1, { gap: 2, opacity: 0.9 }), + preset('weapon-rifle', 'Rifle Control', 'cross-dot', '#00ff00', 18, 1, { gap: 3, opacity: 0.85 }), + preset('weapon-smg', 'SMG Rapid', 'circle', '#ffff00', 20, 2, { opacity: 0.8 }), + preset('weapon-shotgun', 'Shotgun Spread', 'cross', '#ff0000', 22, 3, { gap: 2, opacity: 0.75 }), + preset('weapon-sniper', 'Sniper Precision', 'cross-dot', '#00ffff', 12, 1, { gap: 4, opacity: 0.9 }), + + // === Static Effects Series (25 presets) === + // Glow Style Effects + preset('glow-stealth', 'Stealth Glow', 'cross', '#00ff00', 18, 2, { opacity: 0.8 }), + preset('glow-aggressive', 'Aggressive Glow', 'cross-dot', '#ff0000', 16, 1, { gap: 2, opacity: 0.9 }), + preset('glow-tactical', 'Tactical Glow', 'circle', '#ffff00', 18, 1, { opacity: 0.85 }), + preset('glow-precision', 'Precision Glow', 'cross', '#00ffff', 20, 1, { gap: 3, opacity: 0.8 }), + preset('glow-power', 'Power Glow', 'cross-dot', '#ff00ff', 18, 2, { opacity: 0.85 }), + + // Rotation Style Effects + preset('rotate-slow', 'Slow Rotate', 'cross', '#ffffff', 20, 2, { rotation: 45 }), + preset('rotate-medium', 'Medium Rotate', 'circle', '#00ff00', 18, 2, { rotation: 0 }), + preset('rotate-fast', 'Fast Rotate', 'cross-dot', '#ff0000', 16, 1, { gap: 2, rotation: 0 }), + preset('rotate-smooth', 'Smooth Rotate', 'circle', '#ffff00', 20, 2, { rotation: 30 }), + preset('rotate-dynamic', 'Dynamic Rotate', 'cross', '#00ffff', 18, 2, { rotation: 60 }), + + // Color Style Effects + preset('style-rainbow', 'Rainbow Style', 'cross', '#ff0000', 20, 2), + preset('style-sunset', 'Sunset Style', 'circle', '#ff6600', 18, 2), + preset('style-ocean', 'Ocean Style', 'cross-dot', '#0099ff', 16, 1, { gap: 2 }), + preset('style-forest', 'Forest Style', 'circle', '#00cc00', 20, 2), + preset('style-galaxy', 'Galaxy Style', 'cross', '#9933ff', 18, 2), + + // Pulse Style Effects + preset('pulse-strong', 'Strong Pulse', 'cross', '#ff0000', 20, 2, { opacity: 0.9 }), + preset('pulse-medium', 'Medium Pulse', 'circle', '#00ff00', 18, 2, { opacity: 0.8 }), + preset('pulse-light', 'Light Pulse', 'cross-dot', '#0000ff', 16, 1, { gap: 2, opacity: 0.85 }), + preset('pulse-balanced', 'Balanced Pulse', 'circle', '#ffd700', 20, 2, { opacity: 0.85 }), + preset('pulse-subtle', 'Subtle Pulse', 'cross', '#ff00ff', 18, 2, { opacity: 0.75 }), + + // === Classic Legacy Series (25 presets) === + // Timeless Classics + preset('classic-white', 'Classic White', 'cross', '#ffffff', 20, 2), + preset('classic-red', 'Classic Red', 'cross', '#ff0000', 20, 2), + preset('classic-green', 'Classic Green', 'cross', '#00ff00', 20, 2), + preset('classic-blue', 'Classic Blue', 'cross', '#0088ff', 20, 2), + preset('classic-yellow', 'Classic Yellow', 'cross', '#ffff00', 20, 2), + + // Traditional Styles + preset('traditional-dot', 'Traditional Dot', 'dot', '#ffffff', 4, 2), + preset('traditional-circle', 'Traditional Circle', 'circle', '#ffffff', 20, 2), + preset('traditional-plus', 'Traditional Plus', 'plus', '#ffffff', 20, 2), + preset('traditional-cross', 'Traditional Cross', 'cross', '#ffffff', 24, 2), + preset('traditional-gap', 'Traditional Gap', 'gap-cross', '#ffffff', 28, 2, { gap: 6 }), + + // Vintage Gaming + preset('vintage-arcade', 'Arcade Classic', 'cross', '#00ff00', 16, 2), + preset('vintage-console', 'Console Era', 'cross-dot', '#ffff00', 18, 1, { gap: 2 }), + preset('vintage-pc', 'PC Gaming', 'circle', '#00ffff', 20, 2), + preset('vintage-lan', 'LAN Party', 'cross', '#ff00ff', 22, 2), + preset('vintage-retro', 'Retro Gaming', 'cross-dot', '#ffa500', 16, 1, { gap: 2 }), + + // === Competitive Series (20 presets) === + // Rank-Based Styles + preset('comp-bronze', 'Bronze Rank', 'cross', '#cd7f32', 20, 2, { opacity: 0.8 }), + preset('comp-silver', 'Silver Rank', 'cross-dot', '#c0c0c0', 18, 1, { gap: 2, opacity: 0.85 }), + preset('comp-gold', 'Gold Rank', 'circle', '#ffd700', 16, 1, { opacity: 0.9 }), + preset('comp-platinum', 'Platinum Rank', 'cross', '#e5e4e2', 18, 2, { opacity: 0.85 }), + preset('comp-diamond', 'Diamond Rank', 'cross-dot', '#b9f2ff', 16, 1, { gap: 2, opacity: 0.9 }), + + // Tournament Ready + preset('tourney-ready', 'Tournament Ready', 'cross', '#ffffff', 18, 1, { gap: 3, opacity: 0.85 }), + preset('tourney-pro', 'Pro Tournament', 'cross-dot', '#00ff00', 16, 1, { gap: 2, opacity: 0.9 }), + preset('tourney-elite', 'Elite Tournament', 'circle', '#ffff00', 14, 1, { opacity: 0.85 }), + preset('tourney-master', 'Master Tournament', 'cross', '#00ffff', 17, 1, { gap: 3, opacity: 0.8 }), + preset('tourney-champion', 'Champion Tournament', 'cross-dot', '#ff00ff', 15, 1, { gap: 2, opacity: 0.85 }), + + // Training Modes + preset('training-aim', 'Aim Training', 'cross', '#ffffff', 20, 1, { gap: 2, opacity: 0.9 }), + preset('training-flick', 'Flick Training', 'cross-dot', '#ff0000', 18, 1, { gap: 2, opacity: 0.85 }), + preset('training-track', 'Tracking Training', 'circle', '#00ff00', 16, 1, { opacity: 0.8 }), + preset('training-reflex', 'Reflex Training', 'cross', '#ffff00', 19, 1, { gap: 3, opacity: 0.85 }), + preset('training-precision', 'Precision Training', 'cross-dot', '#00ffff', 17, 1, { gap: 2, opacity: 0.9 }), + + // === Custom Series (20 presets) === + // Personal Preferences + preset('personal-stealth', 'Stealth Player', 'cross', '#2f4f4f', 16, 1, { opacity: 0.7 }), + preset('personal-aggressive', 'Aggressive Player', 'cross-dot', '#ff4500', 18, 1, { gap: 2, opacity: 0.8 }), + preset('personal-tactical', 'Tactical Player', 'circle', '#4682b4', 16, 1, { opacity: 0.85 }), + preset('personal-balanced', 'Balanced Player', 'cross', '#ffffff', 18, 1, { gap: 3, opacity: 0.85 }), + preset('personal-adaptive', 'Adaptive Player', 'cross-dot', '#00ff00', 17, 1, { gap: 2, opacity: 0.9 }), + + // Environment Specific + preset('env-bright', 'Bright Environment', 'cross', '#000000', 20, 2, { opacity: 0.9 }), + preset('env-dark', 'Dark Environment', 'cross', '#ffffff', 18, 1, { gap: 3, opacity: 0.85 }), + preset('env-mixed', 'Mixed Lighting', 'cross-dot', '#ffff00', 16, 1, { gap: 2, opacity: 0.8 }), + preset('env-indoor', 'Indoor Environment', 'circle', '#00ff00', 17, 1, { opacity: 0.85 }), + preset('env-outdoor', 'Outdoor Environment', 'cross', '#00ffff', 19, 1, { gap: 3, opacity: 0.8 }), + + // Playstyle Specific + preset('play-camper', 'Camper Style', 'cross', '#008000', 14, 1, { gap: 4, opacity: 0.9 }), + preset('play-rusher', 'Rusher Style', 'cross-dot', '#ff0000', 20, 2, { gap: 2, opacity: 0.8 }), + preset('play-support', 'Support Style', 'circle', '#0000ff', 16, 1, { opacity: 0.85 }), + preset('play-flanker', 'Flanker Style', 'cross', '#ff00ff', 18, 1, { gap: 3, opacity: 0.85 }), + preset('play-igl', 'IGL Style', 'cross-dot', '#ffff00', 17, 1, { gap: 2, opacity: 0.8 }), + + // === Master Collection (20 presets) === + // Ultimate Combos + preset('ultimate-pro', 'Ultimate Pro', 'cross-dot', '#ffffff', 16, 1, { gap: 2, opacity: 0.9 }), + preset('ultimate-stealth', 'Ultimate Stealth', 'cross', '#2f4f4f', 18, 1, { gap: 3, opacity: 0.8 }), + preset('ultimate-aggressive', 'Ultimate Aggressive', 'cross-dot', '#ff0000', 20, 2, { gap: 2, opacity: 0.85 }), + preset('ultimate-balanced', 'Ultimate Balanced', 'circle', '#00ff00', 16, 1, { opacity: 0.85 }), + preset('ultimate-adaptive', 'Ultimate Adaptive', 'cross', '#ffff00', 17, 1, { gap: 3, opacity: 0.8 }), + + // Championship Ready + preset('champion-cs', 'CS Champion', 'cross-dot', '#00ff00', 16, 1, { gap: 2, opacity: 0.9 }), + preset('champion-valorant', 'Valorant Champion', 'cross', '#00ffff', 15, 1, { gap: 2, opacity: 0.85 }), + preset('champion-overwatch', 'Overwatch Champion', 'circle-dot', '#ff6600', 14, 1, { gap: 2, opacity: 0.8 }), + preset('champion-apex', 'Apex Champion', 'cross', '#ffffff', 17, 1, { gap: 3, opacity: 0.85 }), + preset('champion-fortnite', 'Fortnite Champion', 'cross-dot', '#ff00ff', 16, 1, { gap: 2, opacity: 0.9 }), + + // Legendary Status + preset('legendary-aim', 'Legendary Aim', 'cross', '#ffd700', 18, 1, { gap: 3, opacity: 0.85 }), + preset('legendary-precision', 'Legendary Precision', 'circle-dot', '#c0c0c0', 16, 1, { gap: 2, opacity: 0.9 }), + preset('legendary-speed', 'Legendary Speed', 'cross', '#ff4500', 20, 2, { gap: 2, opacity: 0.8 }), + preset('legendary-control', 'Legendary Control', 'cross-dot', '#4169e1', 17, 1, { gap: 2, opacity: 0.85 }), + preset('legendary-master', 'Legendary Master', 'circle', '#ff1493', 16, 1, { opacity: 0.9 }), + + // === Special Edition (30 presets) === + preset('special-edition-1', 'Special Edition 1', 'cross-dot', '#ffffff', 16, 1, { gap: 2, opacity: 0.85 }), + preset('special-edition-2', 'Special Edition 2', 'circle', '#00ff00', 16, 1, { opacity: 0.9 }), + preset('special-edition-3', 'Special Edition 3', 'cross', '#ffff00', 18, 1, { gap: 3, opacity: 0.8 }), + preset('special-edition-4', 'Special Edition 4', 'cross-dot', '#00ffff', 15, 1, { gap: 2, opacity: 0.85 }), + preset('special-edition-5', 'Special Edition 5', 'circle', '#ff00ff', 16, 1, { opacity: 0.9 }), + preset('special-edition-6', 'Special Edition 6', 'cross', '#ff6600', 17, 1, { gap: 2, opacity: 0.8 }), + preset('special-edition-7', 'Special Edition 7', 'cross-dot', '#00ff88', 16, 1, { gap: 2, opacity: 0.85 }), + preset('special-edition-8', 'Special Edition 8', 'circle', '#ff69b4', 16, 1, { opacity: 0.9 }), + preset('special-edition-9', 'Special Edition 9', 'cross', '#9370db', 18, 1, { gap: 3, opacity: 0.8 }), + preset('special-edition-10', 'Special Edition 10', 'cross-dot', '#20b2aa', 15, 1, { gap: 2, opacity: 0.85 }), + preset('special-edition-11', 'Special Edition 11', 'cross', '#ff1493', 16, 1, { gap: 2, opacity: 0.9 }), + preset('special-edition-12', 'Special Edition 12', 'circle-dot', '#32cd32', 15, 1, { gap: 2, opacity: 0.85 }), + preset('special-edition-13', 'Special Edition 13', 'cross', '#4169e1', 17, 1, { gap: 3, opacity: 0.8 }), + preset('special-edition-14', 'Special Edition 14', 'cross-dot', '#ff8c00', 16, 1, { gap: 2, opacity: 0.9 }), + preset('special-edition-15', 'Special Edition 15', 'circle', '#9370db', 16, 1, { opacity: 0.85 }), + preset('special-edition-16', 'Special Edition 16', 'cross', '#00ced1', 18, 1, { gap: 2, opacity: 0.8 }), + preset('special-edition-17', 'Special Edition 17', 'cross-dot', '#ff69b4', 15, 1, { gap: 2, opacity: 0.9 }), + preset('special-edition-18', 'Special Edition 18', 'circle', '#ffd700', 16, 1, { opacity: 0.85 }), + preset('special-edition-19', 'Special Edition 19', 'cross', '#8a2be2', 17, 1, { gap: 3, opacity: 0.8 }), + preset('special-edition-20', 'Special Edition 20', 'cross-dot', '#00fa9a', 16, 1, { gap: 2, opacity: 0.9 }), + preset('special-edition-21', 'Special Edition 21', 'cross', '#dc143c', 16, 1, { gap: 2, opacity: 0.85 }), + preset('special-edition-22', 'Special Edition 22', 'circle-dot', '#4b0082', 15, 1, { gap: 2, opacity: 0.9 }), + preset('special-edition-23', 'Special Edition 23', 'cross', '#ff1493', 18, 1, { gap: 3, opacity: 0.8 }), + preset('special-edition-24', 'Special Edition 24', 'cross-dot', '#00bfff', 16, 1, { gap: 2, opacity: 0.85 }), + preset('special-edition-25', 'Special Edition 25', 'circle', '#ff6347', 16, 1, { opacity: 0.9 }), + preset('special-edition-26', 'Special Edition 26', 'cross', '#9400d3', 17, 1, { gap: 2, opacity: 0.8 }), + preset('special-edition-27', 'Special Edition 27', 'cross-dot', '#32cd32', 15, 1, { gap: 2, opacity: 0.9 }), + preset('special-edition-28', 'Special Edition 28', 'circle', '#ff8c00', 16, 1, { opacity: 0.85 }), + preset('special-edition-29', 'Special Edition 29', 'cross', '#4169e1', 18, 1, { gap: 3, opacity: 0.8 }), + preset('special-edition-30', 'Special Edition 30', 'cross-dot', '#ff69b4', 16, 1, { gap: 2, opacity: 0.9 }), + + // === Size Variation Series (25 presets) === + // Tiny Crosshairs + preset('size-tiny-cross', 'Tiny Cross', 'cross', '#ffffff', 12, 1), + preset('size-tiny-dot', 'Tiny Dot', 'dot', '#ffffff', 2, 1), + preset('size-tiny-circle', 'Tiny Circle', 'circle', '#ffffff', 8, 1), + preset('size-tiny-plus', 'Tiny Plus', 'plus', '#ffffff', 12, 1), + preset('size-tiny-gap', 'Tiny Gap', 'gap-cross', '#ffffff', 16, 1, { gap: 2 }), + + // Small Crosshairs + preset('size-small-cross', 'Small Cross', 'cross', '#ffffff', 16, 1), + preset('size-small-dot', 'Small Dot', 'dot', '#ffffff', 3, 1), + preset('size-small-circle', 'Small Circle', 'circle', '#ffffff', 12, 1), + preset('size-small-plus', 'Small Plus', 'plus', '#ffffff', 16, 1), + preset('size-small-gap', 'Small Gap', 'gap-cross', '#ffffff', 20, 1, { gap: 3 }), + + // Medium Crosshairs + preset('size-medium-cross', 'Medium Cross', 'cross', '#ffffff', 20, 2), + preset('size-medium-dot', 'Medium Dot', 'dot', '#ffffff', 4, 2), + preset('size-medium-circle', 'Medium Circle', 'circle', '#ffffff', 16, 2), + preset('size-medium-plus', 'Medium Plus', 'plus', '#ffffff', 20, 2), + preset('size-medium-gap', 'Medium Gap', 'gap-cross', '#ffffff', 24, 2, { gap: 4 }), + + // Large Crosshairs + preset('size-large-cross', 'Large Cross', 'cross', '#ffffff', 24, 3), + preset('size-large-dot', 'Large Dot', 'dot', '#ffffff', 6, 3), + preset('size-large-circle', 'Large Circle', 'circle', '#ffffff', 20, 3), + preset('size-large-plus', 'Large Plus', 'plus', '#ffffff', 24, 3), + preset('size-large-gap', 'Large Gap', 'gap-cross', '#ffffff', 28, 3, { gap: 5 }), + + // === Color Variation Series (30 presets) === + // Red Variations + preset('color-red-classic', 'Red Classic', 'cross', '#ff0000', 20, 2), + preset('color-red-bright', 'Red Bright', 'cross', '#ff3333', 20, 2), + preset('color-red-dark', 'Red Dark', 'cross', '#cc0000', 20, 2), + preset('color-red-pink', 'Red Pink', 'cross', '#ff6666', 20, 2), + preset('color-red-orange', 'Red Orange', 'cross', '#ff3300', 20, 2), + preset('color-red-crimson', 'Red Crimson', 'cross', '#dc143c', 20, 2), + preset('color-red-fire', 'Red Fire', 'cross', '#ff4500', 20, 2), + + // Green Variations + preset('color-green-classic', 'Green Classic', 'cross', '#00ff00', 20, 2), + preset('color-green-bright', 'Green Bright', 'cross', '#33ff33', 20, 2), + preset('color-green-dark', 'Green Dark', 'cross', '#00cc00', 20, 2), + preset('color-green-lime', 'Green Lime', 'cross', '#66ff66', 20, 2), + preset('color-green-mint', 'Green Mint', 'cross', '#00ff66', 20, 2), + preset('color-green-emerald', 'Green Emerald', 'cross', '#50c878', 20, 2), + preset('color-green-forest', 'Green Forest', 'cross', '#228b22', 20, 2), + + // Blue Variations + preset('color-blue-classic', 'Blue Classic', 'cross', '#0088ff', 20, 2), + preset('color-blue-bright', 'Blue Bright', 'cross', '#33aaff', 20, 2), + preset('color-blue-dark', 'Blue Dark', 'cross', '#0066cc', 20, 2), + preset('color-blue-sky', 'Blue Sky', 'cross', '#66aaff', 20, 2), + preset('color-blue-cyan', 'Blue Cyan', 'cross', '#00ffff', 20, 2), + preset('color-blue-ocean', 'Blue Ocean', 'cross', '#4682b4', 20, 2), + preset('color-blue-navy', 'Blue Navy', 'cross', '#000080', 20, 2), + + // Yellow Variations + preset('color-yellow-classic', 'Yellow Classic', 'cross', '#ffff00', 20, 2), + preset('color-yellow-bright', 'Yellow Bright', 'cross', '#ffff33', 20, 2), + preset('color-yellow-dark', 'Yellow Dark', 'cross', '#cccc00', 20, 2), + preset('color-yellow-gold', 'Yellow Gold', 'cross', '#ffd700', 20, 2), + preset('color-yellow-orange', 'Yellow Orange', 'cross', '#ffcc00', 20, 2), + preset('color-yellow-amber', 'Yellow Amber', 'cross', '#ffaa00', 20, 2), + preset('color-yellow-lemon', 'Yellow Lemon', 'cross', '#fff44f', 20, 2), + + // Purple Variations + preset('color-purple-classic', 'Purple Classic', 'cross', '#aa44ff', 20, 2), + preset('color-purple-bright', 'Purple Bright', 'cross', '#cc66ff', 20, 2), + preset('color-purple-dark', 'Purple Dark', 'cross', '#8833cc', 20, 2), + preset('color-purple-violet', 'Purple Violet', 'cross', '#cc88ff', 20, 2), + preset('color-purple-magenta', 'Purple Magenta', 'cross', '#ff00ff', 20, 2), + preset('color-purple-lavender', 'Purple Lavender', 'cross', '#e6e6fa', 20, 2), + preset('color-purple-indigo', 'Purple Indigo', 'cross', '#4b0082', 20, 2), + + // Orange Variations + preset('color-orange-classic', 'Orange Classic', 'cross', '#ff8800', 20, 2), + preset('color-orange-bright', 'Orange Bright', 'cross', '#ffaa33', 20, 2), + preset('color-orange-dark', 'Orange Dark', 'cross', '#cc6600', 20, 2), + preset('color-orange-coral', 'Orange Coral', 'cross', '#ff9966', 20, 2), + preset('color-orange-amber', 'Orange Amber', 'cross', '#ffaa00', 20, 2), + preset('color-orange-sunset', 'Orange Sunset', 'cross', '#ff6347', 20, 2), + preset('color-orange-tangerine', 'Orange Tangerine', 'cross', '#ffa500', 20, 2), + + // === Style Variation Series (20 presets) === + // Cross Style Variations + preset('style-cross-thin', 'Thin Cross', 'cross', '#ffffff', 20, 1), + preset('style-cross-medium', 'Medium Cross', 'cross', '#ffffff', 20, 2), + preset('style-cross-thick', 'Thick Cross', 'cross', '#ffffff', 20, 3), + preset('style-cross-gap-small', 'Small Gap Cross', 'gap-cross', '#ffffff', 24, 2, { gap: 3 }), + preset('style-cross-gap-large', 'Large Gap Cross', 'gap-cross', '#ffffff', 28, 2, { gap: 6 }), + + // Dot Style Variations + preset('style-dot-tiny', 'Tiny Dot', 'dot', '#ffffff', 1, 1), + preset('style-dot-small', 'Small Dot', 'dot', '#ffffff', 3, 2), + preset('style-dot-medium', 'Medium Dot', 'dot', '#ffffff', 5, 3), + preset('style-dot-large', 'Large Dot', 'dot', '#ffffff', 8, 4), + preset('style-dot-huge', 'Huge Dot', 'dot', '#ffffff', 12, 6), + + // === Extended Dot Series (50 additional dot presets) === + // Micro Dot Series + preset('dot-micro-1', 'Micro Dot 1', 'dot', '#ffffff', 1, 1), + preset('dot-micro-2', 'Micro Dot 2', 'dot', '#00ff00', 1, 1), + preset('dot-micro-3', 'Micro Dot 3', 'dot', '#ff0000', 1, 1), + preset('dot-micro-4', 'Micro Dot 4', 'dot', '#00ffff', 1, 1), + preset('dot-micro-5', 'Micro Dot 5', 'dot', '#ffff00', 1, 1), + + // Precision Dot Series + preset('dot-precision-1', 'Precision Dot 1', 'dot', '#ffffff', 2, 1), + preset('dot-precision-2', 'Precision Dot 2', 'dot', '#00ff88', 2, 1), + preset('dot-precision-3', 'Precision Dot 3', 'dot', '#ff6600', 2, 1), + preset('dot-precision-4', 'Precision Dot 4', 'dot', '#00ccff', 2, 1), + preset('dot-precision-5', 'Precision Dot 5', 'dot', '#ff00ff', 2, 1), + + // Standard Dot Series + preset('dot-standard-1', 'Standard Dot 1', 'dot', '#ffffff', 3, 2), + preset('dot-standard-2', 'Standard Dot 2', 'dot', '#00ff00', 3, 2), + preset('dot-standard-3', 'Standard Dot 3', 'dot', '#ff0000', 3, 2), + preset('dot-standard-4', 'Standard Dot 4', 'dot', '#0088ff', 3, 2), + preset('dot-standard-5', 'Standard Dot 5', 'dot', '#ffff00', 3, 2), + + // Bold Dot Series + preset('dot-bold-1', 'Bold Dot 1', 'dot', '#ffffff', 4, 3), + preset('dot-bold-2', 'Bold Dot 2', 'dot', '#00ff00', 4, 3), + preset('dot-bold-3', 'Bold Dot 3', 'dot', '#ff0000', 4, 3), + preset('dot-bold-4', 'Bold Dot 4', 'dot', '#00ffff', 4, 3), + preset('dot-bold-5', 'Bold Dot 5', 'dot', '#ffff00', 4, 3), + + // Heavy Dot Series + preset('dot-heavy-1', 'Heavy Dot 1', 'dot', '#ffffff', 5, 4), + preset('dot-heavy-2', 'Heavy Dot 2', 'dot', '#00ff00', 5, 4), + preset('dot-heavy-3', 'Heavy Dot 3', 'dot', '#ff0000', 5, 4), + preset('dot-heavy-4', 'Heavy Dot 4', 'dot', '#0088ff', 5, 4), + preset('dot-heavy-5', 'Heavy Dot 5', 'dot', '#ffff00', 5, 4), + + // Large Dot Series + preset('dot-large-1', 'Large Dot 1', 'dot', '#ffffff', 6, 5), + preset('dot-large-2', 'Large Dot 2', 'dot', '#00ff00', 6, 5), + preset('dot-large-3', 'Large Dot 3', 'dot', '#ff0000', 6, 5), + preset('dot-large-4', 'Large Dot 4', 'dot', '#00ffff', 6, 5), + preset('dot-large-5', 'Large Dot 5', 'dot', '#ffff00', 6, 5), + + // Extra Large Dot Series + preset('dot-xlarge-1', 'XLarge Dot 1', 'dot', '#ffffff', 8, 6), + preset('dot-xlarge-2', 'XLarge Dot 2', 'dot', '#00ff00', 8, 6), + preset('dot-xlarge-3', 'XLarge Dot 3', 'dot', '#ff0000', 8, 6), + preset('dot-xlarge-4', 'XLarge Dot 4', 'dot', '#0088ff', 8, 6), + preset('dot-xlarge-5', 'XLarge Dot 5', 'dot', '#ffff00', 8, 6), + + // Massive Dot Series + preset('dot-massive-1', 'Massive Dot 1', 'dot', '#ffffff', 10, 8), + preset('dot-massive-2', 'Massive Dot 2', 'dot', '#00ff00', 10, 8), + preset('dot-massive-3', 'Massive Dot 3', 'dot', '#ff0000', 10, 8), + preset('dot-massive-4', 'Massive Dot 4', 'dot', '#00ffff', 10, 8), + preset('dot-massive-5', 'Massive Dot 5', 'dot', '#ffff00', 10, 8), + + // Colored Dot Series + preset('dot-colored-1', 'Cyan Dot', 'dot', '#00ffff', 4, 3), + preset('dot-colored-2', 'Magenta Dot', 'dot', '#ff00ff', 4, 3), + preset('dot-colored-3', 'Yellow Dot', 'dot', '#ffff00', 4, 3), + preset('dot-colored-4', 'Orange Dot', 'dot', '#ff8800', 4, 3), + preset('dot-colored-5', 'Purple Dot', 'dot', '#9933ff', 4, 3), + + // Gaming Dot Series + preset('dot-gaming-1', 'CS:GO Dot', 'dot', '#00ff00', 3, 2), + preset('dot-gaming-2', 'Valorant Dot', 'dot', '#00ffff', 3, 2), + preset('dot-gaming-3', 'Overwatch Dot', 'dot', '#ffffff', 3, 2), + preset('dot-gaming-4', 'Apex Dot', 'dot', '#ff4444', 3, 2), + preset('dot-gaming-5', 'Fortnite Dot', 'dot', '#00ffff', 3, 2), + + // Tactical Dot Series + preset('dot-tactical-1', 'Sniper Dot', 'dot', '#ffffff', 2, 1), + preset('dot-tactical-2', 'Rifle Dot', 'dot', '#00ff00', 3, 2), + preset('dot-tactical-3', 'SMG Dot', 'dot', '#ff0000', 4, 3), + preset('dot-tactical-4', 'Shotgun Dot', 'dot', '#ffff00', 5, 4), + preset('dot-tactical-5', 'Pistol Dot', 'dot', '#00ffff', 3, 2), + + // Environment Dot Series + preset('dot-env-1', 'Bright Day Dot', 'dot', '#000000', 4, 3), + preset('dot-env-2', 'Dark Night Dot', 'dot', '#ffffff', 4, 3), + preset('dot-env-3', 'Indoor Dot', 'dot', '#ffff00', 4, 3), + preset('dot-env-4', 'Outdoor Dot', 'dot', '#00ff00', 4, 3), + preset('dot-env-5', 'Mixed Light Dot', 'dot', '#ff8800', 4, 3), + + // Professional Dot Series + preset('dot-pro-1', 'Pro Sniper', 'dot', '#ffffff', 2, 1), + preset('dot-pro-2', 'Pro Rifler', 'dot', '#00ff00', 3, 2), + preset('dot-pro-3', 'Pro Awper', 'dot', '#ff0000', 2, 1), + preset('dot-pro-4', 'Pro Entry', 'dot', '#00ffff', 3, 2), + preset('dot-pro-5', 'Pro Support', 'dot', '#ffff00', 4, 3), + + // Special Dot Series + preset('dot-special-1', 'Matrix Dot', 'dot', '#00ff00', 3, 2), + preset('dot-special-2', 'Neon Dot', 'dot', '#ff00ff', 4, 3), + preset('dot-special-3', 'Retro Dot', 'dot', '#00ffff', 3, 2), + preset('dot-special-4', 'Terminal Dot', 'dot', '#00ff00', 4, 3), + preset('dot-special-5', 'Cyber Dot', 'dot', '#ff6600', 3, 2), + + // Circle Style Variations + preset('style-circle-thin', 'Thin Circle', 'circle', '#ffffff', 16, 1), + preset('style-circle-medium', 'Medium Circle', 'circle', '#ffffff', 20, 2), + preset('style-circle-thick', 'Thick Circle', 'circle', '#ffffff', 24, 3), + preset('style-circle-small', 'Small Circle', 'circle', '#ffffff', 12, 1), + preset('style-circle-large', 'Large Circle', 'circle', '#ffffff', 28, 3), + + // Combined Style Variations + preset('style-cross-dot-small', 'Small Cross+Dot', 'cross-dot', '#ffffff', 16, 1, { gap: 2 }), + preset('style-cross-dot-medium', 'Medium Cross+Dot', 'cross-dot', '#ffffff', 20, 2, { gap: 3 }), + preset('style-cross-dot-large', 'Large Cross+Dot', 'cross-dot', '#ffffff', 24, 3, { gap: 4 }), + preset('style-circle-dot-small', 'Small Circle+Dot', 'circle-dot', '#ffffff', 16, 1, { gap: 2 }), + preset('style-circle-dot-medium', 'Medium Circle+Dot', 'circle-dot', '#ffffff', 20, 2, { gap: 3 }), ];