// Use theme variables with namespace to avoid conflicts
@use '../../../../theme/styles/variables.scss' as vars;
@use '../../../../theme/styles/mixins.scss' as mix;
// ============================================
// Hikari Glow Component - Single Glow Color System
// ============================================
//
// IMPORTANT: All glow states are controlled by AnimationBuilder via inline styles.
// CSS does NOT provide any default hover/active/focus behavior.
// The --glow-intensity-scale variable is set inline:
// - Idle: 0 (no glow)
// - Hover: 0.5 (subtle glow)
// - Focus: 0.7 (medium glow)
// - Active: 1.0 (intense glow)
//
// CSS only provides:
// 1. Base structure (::before pseudo-element)
// 2. Intensity classes (dim/soft/bright) for base opacity multiplier
// 3. Transition timing
// Base glow wrapper styles
.hi-glow-wrapper,
.hi-glow-wrapper-block {
position: relative;
// Initialize scale factors - default to 0 (hidden)
--glow-intensity-scale: 0;
--glow-spread-scale: 1.0;
// Create dynamic glow overlay using CSS variables (spotlight effect)
&::before {
content: '';
position: absolute;
inset: 0;
pointer-events: none;
z-index: 2;
border-radius: inherit;
// Use inline style value directly, no fallback
// AnimationBuilder controls this via --glow-intensity-scale
opacity: calc(var(--glow-base-opacity, 1) * var(--glow-intensity-scale));
// Use radial-gradient for acrylic spotlight effect
background: radial-gradient(
circle at var(--glow-x, 50%) var(--glow-y, 50%),
var(--hi-glow-color) 0%,
transparent calc(var(--glow-spread, 1.5) * 100%)
);
// Transition for smooth state changes
transition: opacity 100ms ease-out;
}
// Ensure children (links, buttons) are always clickable
> * {
pointer-events: auto;
position: relative;
z-index: 1;
}
}
// ============================================
// Glow Intensity Levels (Opacity & Spread)
// ============================================
// These classes define the BASE opacity for different glow intensities
// The actual visibility is controlled by --glow-intensity-scale (0 = hidden, 1 = full intensity)
// IMPORTANT: --glow-base-opacity must be defined on the parent, not on ::before
//
// Opacity calculation: base-opacity * intensity-scale
// - Hover (0.5): subtle glow
// - Active (1.0): intense glow (2x hover)
// 30% intensity (subtle, for large surfaces: cards, panels, containers)
.hi-glow-dim {
--glow-spread: 2.4;
--glow-base-opacity: 0.15;
}
// 70% intensity (medium, default for interactive elements: buttons, inputs)
// Hover: 0.30 * 0.5 = 0.15
// Active: 0.30 * 1.0 = 0.30 (visible difference)
.hi-glow-soft {
--glow-spread: 1.6;
--glow-base-opacity: 0.30;
}
// 100% intensity (intense, for emphasis: active states, focus rings)
.hi-glow-bright {
--glow-spread: 1.3;
--glow-base-opacity: 0.50;
}
.hi-glow-wrapper {
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
align-self: flex-start;
// 统一使用 4px 圆角
border-radius: 4px;
overflow: visible;
}
// Block variant for wrapping block-level elements (like Card)
.hi-glow-wrapper-block {
display: flex;
flex-direction: column;
width: 100%;
// 统一使用 4px 圆角
border-radius: 4px;
overflow: visible;
}
// ============================================
// Button Enhancement (Managed by AnimationBuilder)
// ============================================
// Remove transform translateY from button hover when wrapped in glow
.hi-glow-wrapper .hi-button:hover {
transform: none;
}
// Default: No box-shadow - controlled by AnimationBuilder via CSS variables
// The glow wrapper handles all visual feedback through --glow-intensity-scale
.hi-glow-wrapper .hi-button:focus-visible {
box-shadow: none;
}
.hi-glow-wrapper .hi-button:active:not(:disabled) {
box-shadow: none;
transform: none;
}
// Input hover enhancement
.hi-glow-wrapper .hi-input-wrapper:hover {
// No hover effect - handled by glow overlay
}
// ============================================
// Glow Animation Presets
// ============================================
//
// These presets add continuous animation effects to the glow component.
// They are activated by adding the corresponding class to the wrapper.
//
// Note: Preset animations pause during mouse interaction to maintain performance.
// Pulse animation - heartbeat-like pulsing glow
@keyframes glow-pulse {
0%, 100% {
--glow-intensity-scale: 0.5;
}
50% {
--glow-intensity-scale: 1.0;
}
}
.hi-glow-wrapper.pulse::before {
animation: glow-pulse 2s ease-in-out infinite;
}
// Breathe animation - slow, smooth intensity variation
@keyframes glow-breathe {
0%, 100% {
--glow-intensity-scale: 0.3;
}
50% {
--glow-intensity-scale: 1.0;
}
}
.hi-glow-wrapper.breathe::before {
animation: glow-breathe 4s ease-in-out infinite;
}
// Shimmer animation - moving light spot across the element
@keyframes glow-shimmer {
0% {
--glow-x: 20%;
--glow-y: 50%;
}
25% {
--glow-x: 50%;
--glow-y: 80%;
}
50% {
--glow-x: 80%;
--glow-y: 50%;
}
75% {
--glow-x: 50%;
--glow-y: 20%;
}
100% {
--glow-x: 20%;
--glow-y: 50%;
}
}
.hi-glow-wrapper.shimmer::before {
animation: glow-shimmer 3s linear infinite;
}
// Pause preset animations during mouse interaction
.hi-glow-wrapper.pulse:has(:hover)::before,
.hi-glow-wrapper.pulse:has(:active)::before,
.hi-glow-wrapper.breathe:has(:hover)::before,
.hi-glow-wrapper.breathe:has(:active)::before,
.hi-glow-wrapper.shimmer:has(:hover)::before,
.hi-glow-wrapper.shimmer:has(:active)::before {
animation-play-state: paused;
}