// 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
// ============================================
//
// Glow states are controlled by CSS variables updated via mouse events:
// - --glow-x, --glow-y: Position of glow center (percentage, 0-100%)
// - --glow-intensity-scale: Visibility level (0 = hidden, 0.5 = hover, 1.0 = active)
// - --glow-opacity: Direct opacity control (overrides calculated value)
// - --hi-glow-color: Glow color
//
// CSS provides:
// 1. Base structure (::before pseudo-element)
// 2. Intensity classes (dim/soft/bright) for base opacity multiplier
// 3. Smooth transitions for position and opacity
// 4. Fallback :hover and :active states
// Base glow wrapper styles
.hi-glow-wrapper,
.hi-glow-wrapper-block {
position: relative;
&::before {
content: '';
position: absolute;
inset: 0;
pointer-events: none;
z-index: 2;
border-radius: var(--hi-glow-radius, inherit);
opacity: 0;
transition: opacity 0.3s ease-in-out;
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%)
);
}
&:hover::before {
opacity: var(--glow-opacity, 0.15);
}
> * {
pointer-events: auto;
position: relative;
z-index: 1;
}
}
// ============================================
// Glow Blur Levels (Backdrop Blur Effect)
// ============================================
// These classes control the backdrop blur intensity for the glow effect
// None: No blur (default, for crisp glow edges)
.hi-glow-blur-none {
// No additional blur effect
}
// Light: Subtle blur (2px) for soft glow edges
.hi-glow-blur-light {
&::before {
backdrop-filter: blur(2px);
-webkit-backdrop-filter: blur(2px);
}
}
// Medium: Medium blur (4px) for balanced glow effect
.hi-glow-blur-medium {
&::before {
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
}
}
// Heavy: Heavy blur (8px) for intense glow diffusion
.hi-glow-blur-heavy {
&::before {
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
}
}
// ============================================
// 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)
// Very low opacity + wide spread for an almost imperceptible ambient glow
.hi-glow-dim {
--glow-opacity: 0.07;
--glow-spread: 2.4;
&::before {
--glow-opacity: 0.07;
--glow-spread: 2.4;
}
}
// 70% intensity (medium, default for interactive elements: buttons, inputs)
// Balanced opacity + moderate spread for clear but non-distracting feedback
.hi-glow-soft {
--glow-opacity: 0.15;
--glow-spread: 1.6;
&::before {
--glow-opacity: 0.15;
--glow-spread: 1.6;
}
}
// 100% intensity (intense, for emphasis: active states, focus rings)
.hi-glow-bright {
--glow-opacity: 0.30;
--glow-spread: 1.3;
&::before {
--glow-opacity: 0.30;
--glow-spread: 1.3;
}
}
.hi-glow-wrapper {
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
align-self: flex-start;
overflow: visible;
}
// Block variant for wrapping block-level elements (like Card)
.hi-glow-wrapper-block {
display: flex;
flex-direction: column;
width: 100%;
overflow: visible;
}
// ============================================
// Radius Matching
// ============================================
// Glow wrapper must match its child's border-radius.
// Since CSS cannot "inherit upward", we set radius on common child types.
// Components set their own --hi-*-radius tokens in button-vars.scss etc.
.hi-glow-wrapper > .hi-button { border-radius: var(--hi-button-radius, var(--hi-radius-md, 8px)); }
.hi-glow-wrapper > .hi-input,
.hi-glow-wrapper > .hi-textarea,
.hi-glow-wrapper > .hi-search,
.hi-glow-wrapper > .hi-number-input { border-radius: var(--hi-input-radius, var(--hi-radius-md, 8px)); }
.hi-glow-wrapper > li { border-radius: var(--hi-glow-radius, var(--hi-radius-sm, 4px)); }
.hi-glow-wrapper-block > .hi-input,
.hi-glow-wrapper-block > .hi-textarea,
.hi-glow-wrapper-block > .hi-search,
.hi-glow-wrapper-block > .hi-number-input { border-radius: var(--hi-input-radius, var(--hi-radius-md, 8px)); }
// ============================================
// Button Enhancement
// ============================================
// When button is wrapped in glow, let the button handle its own hover effects
// The glow wrapper adds the mouse-following spotlight effect on top
.hi-glow-wrapper .hi-button:hover {
transform: none;
}
// Combine button outline with glow effect
.hi-glow-wrapper .hi-button:focus-visible {
box-shadow:
0 0 0 2px currentColor,
0 0 12px var(--hi-glow-color);
}
// Let button handle its own active state
.hi-glow-wrapper .hi-button:active:not(:disabled) {
box-shadow:
0 0 4px currentColor,
inset 0 1px 0 var(--hi-white-10, rgba(255,255,255,0.1));
transform: translateY(0) scale(0.98);
}
.hi-glow-wrapper .hi-button:focus-visible {
// Combine button outline with glow effect
outline-offset: 2px;
}
.hi-glow-wrapper .hi-button:active:not(:disabled) {
// Let button handle its own active state
}
// 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;
}