refactor(rithmomachia): extract reusable components from SetupPhase

Extract three reusable components from SetupPhase.tsx to eliminate code
duplication and improve maintainability.

**Components Created:**
- GameRuleCard.tsx (94 lines): Reusable card component for game settings
  - Replaces 4 nearly identical card implementations
  - Supports enabled/disabled states with visual feedback
  - Accepts optional children for custom content (e.g., threshold input)
- SetupHeader.tsx (155 lines): Medieval-style ornamental header
  - Title, subtitle, decorative corners, and guide button
- StartButton.tsx (73 lines): Dramatic start button with animations

**Impact:**
- SetupPhase.tsx: 759 → 308 lines (59% reduction, -451 lines)
- Eliminated ~480 lines of duplicate JSX across 4 game rule cards
- Improved component reusability and consistency
- Cleaner, more maintainable codebase

**Testing:**
- Pre-commit checks passed (format, lint)
- TypeScript: No new errors in changed files
- Ready for manual testing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Thomas Hallock
2025-11-02 06:22:59 -06:00
parent 324a65992f
commit 3abc325ea2
4 changed files with 346 additions and 480 deletions

View File

@@ -0,0 +1,93 @@
import type { ReactNode } from 'react'
import { css } from '../../../../../styled-system/css'
export interface GameRuleCardProps {
title: string
description: string
enabled: boolean
onClick: () => void
dataAttribute?: string
children?: ReactNode
}
export function GameRuleCard({
title,
description,
enabled,
onClick,
dataAttribute,
children,
}: GameRuleCardProps) {
return (
<div
data-setting={dataAttribute}
onClick={onClick}
className={css({
display: 'flex',
flexDirection: children ? 'column' : 'row',
gap: children ? '1vh' : undefined,
justifyContent: children ? undefined : 'space-between',
alignItems: children ? undefined : 'center',
p: '1.5vh',
bg: enabled ? 'rgba(251, 191, 36, 0.25)' : 'rgba(139, 92, 246, 0.1)',
borderRadius: '1vh',
border: '0.3vh solid',
borderColor: enabled ? 'rgba(251, 191, 36, 0.8)' : 'rgba(139, 92, 246, 0.3)',
transition: 'all 0.3s ease',
cursor: 'pointer',
position: 'relative',
overflow: 'hidden',
boxShadow: enabled
? '0 0.5vh 2vh rgba(251, 191, 36, 0.4)'
: '0 0.2vh 0.5vh rgba(0,0,0,0.1)',
_hover: {
bg: enabled ? 'rgba(251, 191, 36, 0.35)' : 'rgba(139, 92, 246, 0.2)',
borderColor: enabled ? 'rgba(251, 191, 36, 1)' : 'rgba(139, 92, 246, 0.5)',
transform: 'translateY(-0.2vh)',
},
_active: {
transform: 'scale(0.98)',
},
})}
>
<div
className={css({
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
flex: children ? undefined : 1,
})}
>
<div className={css({ flex: 1, pointerEvents: 'none' })}>
<div
className={css({
fontWeight: 'bold',
fontSize: '1.6vh',
color: enabled ? '#92400e' : '#7c2d12',
})}
>
{enabled && '✓ '}
{title}
</div>
<div className={css({ fontSize: '1.3vh', color: '#78350f' })}>{description}</div>
</div>
{enabled && (
<div
className={css({
position: 'absolute',
top: 0,
right: 0,
width: '4vh',
height: '4vh',
borderRadius: '0 1vh 0 100%',
bg: 'rgba(251, 191, 36, 0.4)',
pointerEvents: 'none',
})}
/>
)}
</div>
{children}
</div>
)
}

View File

@@ -0,0 +1,153 @@
import { css } from '../../../../../styled-system/css'
export interface SetupHeaderProps {
onOpenGuide: () => void
}
export function SetupHeader({ onOpenGuide }: SetupHeaderProps) {
return (
<div
data-element="title-section"
className={css({
textAlign: 'center',
bg: 'rgba(255, 255, 255, 0.95)',
borderRadius: '1.5vh',
p: '1.5vh',
boxShadow: '0 1vh 3vh rgba(0,0,0,0.5)',
width: '100%',
position: 'relative',
border: '0.3vh solid',
borderColor: 'rgba(251, 191, 36, 0.6)',
backdropFilter: 'blur(10px)',
flexShrink: 0,
})}
>
{/* Ornamental corners */}
<div
className={css({
position: 'absolute',
top: '-0.5vh',
left: '-0.5vh',
width: '2.5vh',
height: '2.5vh',
borderTop: '0.3vh solid',
borderLeft: '0.3vh solid',
borderColor: 'rgba(251, 191, 36, 0.8)',
borderRadius: '1.5vh 0 0 0',
})}
/>
<div
className={css({
position: 'absolute',
top: '-0.5vh',
right: '-0.5vh',
width: '2.5vh',
height: '2.5vh',
borderTop: '0.3vh solid',
borderRight: '0.3vh solid',
borderColor: 'rgba(251, 191, 36, 0.8)',
borderRadius: '0 1.5vh 0 0',
})}
/>
<div
className={css({
position: 'absolute',
bottom: '-0.5vh',
left: '-0.5vh',
width: '2.5vh',
height: '2.5vh',
borderBottom: '0.3vh solid',
borderLeft: '0.3vh solid',
borderColor: 'rgba(251, 191, 36, 0.8)',
borderRadius: '0 0 0 1.5vh',
})}
/>
<div
className={css({
position: 'absolute',
bottom: '-0.5vh',
right: '-0.5vh',
width: '2.5vh',
height: '2.5vh',
borderBottom: '0.3vh solid',
borderRight: '0.3vh solid',
borderColor: 'rgba(251, 191, 36, 0.8)',
borderRadius: '0 0 1.5vh 0',
})}
/>
<h1
className={css({
fontSize: '3.5vh',
fontWeight: 'bold',
mb: '0.5vh',
color: '#7c2d12',
textShadow: '0.15vh 0.15vh 0 rgba(251, 191, 36, 0.5), 0.3vh 0.3vh 0.5vh rgba(0,0,0,0.3)',
letterSpacing: '0.2vh',
})}
>
RITHMOMACHIA
</h1>
<div
className={css({
height: '0.2vh',
width: '60%',
margin: '0 auto 0.5vh',
background: 'linear-gradient(90deg, transparent, rgba(251, 191, 36, 0.8), transparent)',
})}
/>
<p
className={css({
color: '#92400e',
fontSize: '1.8vh',
fontWeight: 'bold',
mb: '0.3vh',
fontStyle: 'italic',
})}
>
The Philosopher's Game
</p>
<p
className={css({
color: '#78350f',
fontSize: '1.2vh',
lineHeight: '1.4',
fontWeight: '500',
mb: '0.8vh',
})}
>
Win by forming mathematical progressions in enemy territory
</p>
<button
type="button"
data-action="open-guide"
onClick={onOpenGuide}
className={css({
bg: 'linear-gradient(135deg, #7c2d12, #92400e)',
color: 'white',
border: '2px solid rgba(251, 191, 36, 0.6)',
borderRadius: '0.8vh',
px: '1.5vh',
py: '0.8vh',
fontSize: '1.3vh',
fontWeight: 'bold',
cursor: 'pointer',
transition: 'all 0.2s',
display: 'flex',
alignItems: 'center',
gap: '0.5vh',
mx: 'auto',
boxShadow: '0 0.3vh 0.8vh rgba(0, 0, 0, 0.3)',
_hover: {
bg: 'linear-gradient(135deg, #92400e, #7c2d12)',
transform: 'translateY(-0.2vh)',
boxShadow: '0 0.5vh 1.2vh rgba(0, 0, 0, 0.4)',
},
})}
>
<span>📖</span>
<span>How to Play</span>
</button>
</div>
)
}

View File

@@ -5,6 +5,9 @@ import { useGameMode } from '@/contexts/GameModeContext'
import { css } from '../../../../../styled-system/css'
import { useRithmomachia } from '../../Provider'
import type { RithmomachiaConfig } from '../../types'
import { GameRuleCard } from './GameRuleCard'
import { SetupHeader } from './SetupHeader'
import { StartButton } from './StartButton'
export interface SetupPhaseProps {
onOpenGuide: () => void
@@ -164,152 +167,7 @@ export function SetupPhase({ onOpenGuide }: SetupPhaseProps) {
{/* Only show setup config when we have enough players */}
{rosterStatus.status !== 'tooFew' && (
<>
{/* Title Section - Compact medieval manuscript style */}
<div
data-element="title-section"
className={css({
textAlign: 'center',
bg: 'rgba(255, 255, 255, 0.95)',
borderRadius: '1.5vh',
p: '1.5vh',
boxShadow: '0 1vh 3vh rgba(0,0,0,0.5)',
width: '100%',
position: 'relative',
border: '0.3vh solid',
borderColor: 'rgba(251, 191, 36, 0.6)',
backdropFilter: 'blur(10px)',
flexShrink: 0,
})}
>
{/* Ornamental corners - smaller */}
<div
className={css({
position: 'absolute',
top: '-0.5vh',
left: '-0.5vh',
width: '2.5vh',
height: '2.5vh',
borderTop: '0.3vh solid',
borderLeft: '0.3vh solid',
borderColor: 'rgba(251, 191, 36, 0.8)',
borderRadius: '1.5vh 0 0 0',
})}
/>
<div
className={css({
position: 'absolute',
top: '-0.5vh',
right: '-0.5vh',
width: '2.5vh',
height: '2.5vh',
borderTop: '0.3vh solid',
borderRight: '0.3vh solid',
borderColor: 'rgba(251, 191, 36, 0.8)',
borderRadius: '0 1.5vh 0 0',
})}
/>
<div
className={css({
position: 'absolute',
bottom: '-0.5vh',
left: '-0.5vh',
width: '2.5vh',
height: '2.5vh',
borderBottom: '0.3vh solid',
borderLeft: '0.3vh solid',
borderColor: 'rgba(251, 191, 36, 0.8)',
borderRadius: '0 0 0 1.5vh',
})}
/>
<div
className={css({
position: 'absolute',
bottom: '-0.5vh',
right: '-0.5vh',
width: '2.5vh',
height: '2.5vh',
borderBottom: '0.3vh solid',
borderRight: '0.3vh solid',
borderColor: 'rgba(251, 191, 36, 0.8)',
borderRadius: '0 0 1.5vh 0',
})}
/>
<h1
className={css({
fontSize: '3.5vh',
fontWeight: 'bold',
mb: '0.5vh',
color: '#7c2d12',
textShadow:
'0.15vh 0.15vh 0 rgba(251, 191, 36, 0.5), 0.3vh 0.3vh 0.5vh rgba(0,0,0,0.3)',
letterSpacing: '0.2vh',
})}
>
RITHMOMACHIA
</h1>
<div
className={css({
height: '0.2vh',
width: '60%',
margin: '0 auto 0.5vh',
background:
'linear-gradient(90deg, transparent, rgba(251, 191, 36, 0.8), transparent)',
})}
/>
<p
className={css({
color: '#92400e',
fontSize: '1.8vh',
fontWeight: 'bold',
mb: '0.3vh',
fontStyle: 'italic',
})}
>
The Philosopher's Game
</p>
<p
className={css({
color: '#78350f',
fontSize: '1.2vh',
lineHeight: '1.4',
fontWeight: '500',
mb: '0.8vh',
})}
>
Win by forming mathematical progressions in enemy territory
</p>
<button
type="button"
data-action="open-guide"
onClick={onOpenGuide}
className={css({
bg: 'linear-gradient(135deg, #7c2d12, #92400e)',
color: 'white',
border: '2px solid rgba(251, 191, 36, 0.6)',
borderRadius: '0.8vh',
px: '1.5vh',
py: '0.8vh',
fontSize: '1.3vh',
fontWeight: 'bold',
cursor: 'pointer',
transition: 'all 0.2s',
display: 'flex',
alignItems: 'center',
gap: '0.5vh',
mx: 'auto',
boxShadow: '0 0.3vh 0.8vh rgba(0, 0, 0, 0.3)',
_hover: {
bg: 'linear-gradient(135deg, #92400e, #7c2d12)',
transform: 'translateY(-0.2vh)',
boxShadow: '0 0.5vh 1.2vh rgba(0, 0, 0, 0.4)',
},
})}
>
<span>📖</span>
<span>How to Play</span>
</button>
</div>
<SetupHeader onOpenGuide={onOpenGuide} />
{/* Game Settings - Compact with flex: 1 to take remaining space */}
<div
@@ -356,82 +214,13 @@ export function SetupPhase({ onOpenGuide }: SetupPhaseProps) {
alignContent: 'start',
})}
>
{/* Point Victory */}
<div
data-setting="point-victory"
<GameRuleCard
title="Point Victory"
description={`Win at ${state.pointWinThreshold}pts`}
enabled={state.pointWinEnabled}
onClick={() => toggleSetting('pointWinEnabled')}
className={css({
display: 'flex',
flexDirection: 'column',
gap: '1vh',
p: '1.5vh',
bg: state.pointWinEnabled
? 'rgba(251, 191, 36, 0.25)'
: 'rgba(139, 92, 246, 0.1)',
borderRadius: '1vh',
border: '0.3vh solid',
borderColor: state.pointWinEnabled
? 'rgba(251, 191, 36, 0.8)'
: 'rgba(139, 92, 246, 0.3)',
transition: 'all 0.3s ease',
cursor: 'pointer',
position: 'relative',
overflow: 'hidden',
boxShadow: state.pointWinEnabled
? '0 0.5vh 2vh rgba(251, 191, 36, 0.4)'
: '0 0.2vh 0.5vh rgba(0,0,0,0.1)',
_hover: {
bg: state.pointWinEnabled
? 'rgba(251, 191, 36, 0.35)'
: 'rgba(139, 92, 246, 0.2)',
borderColor: state.pointWinEnabled
? 'rgba(251, 191, 36, 1)'
: 'rgba(139, 92, 246, 0.5)',
transform: 'translateY(-0.2vh)',
},
_active: {
transform: 'scale(0.98)',
},
})}
dataAttribute="point-victory"
>
<div
className={css({
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
})}
>
<div className={css({ flex: 1, pointerEvents: 'none' })}>
<div
className={css({
fontWeight: 'bold',
fontSize: '1.6vh',
color: state.pointWinEnabled ? '#92400e' : '#7c2d12',
})}
>
{state.pointWinEnabled && ' '}Point Victory
</div>
<div className={css({ fontSize: '1.3vh', color: '#78350f' })}>
Win at {state.pointWinThreshold}pts
</div>
</div>
{state.pointWinEnabled && (
<div
className={css({
position: 'absolute',
top: 0,
right: 0,
width: '4vh',
height: '4vh',
borderRadius: '0 1vh 0 100%',
bg: 'rgba(251, 191, 36, 0.4)',
pointerEvents: 'none',
})}
/>
)}
</div>
{/* Threshold input - only visible when enabled */}
{state.pointWinEnabled && (
<div
data-element="threshold-input-container"
@@ -478,275 +267,35 @@ export function SetupPhase({ onOpenGuide }: SetupPhaseProps) {
/>
</div>
)}
</div>
</GameRuleCard>
{/* Threefold Repetition */}
<div
data-setting="threefold-repetition"
<GameRuleCard
title="Threefold Draw"
description="Same position 3x"
enabled={state.repetitionRule}
onClick={() => toggleSetting('repetitionRule')}
className={css({
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
p: '1.5vh',
bg: state.repetitionRule
? 'rgba(251, 191, 36, 0.25)'
: 'rgba(139, 92, 246, 0.1)',
borderRadius: '1vh',
border: '0.3vh solid',
borderColor: state.repetitionRule
? 'rgba(251, 191, 36, 0.8)'
: 'rgba(139, 92, 246, 0.3)',
transition: 'all 0.3s ease',
cursor: 'pointer',
position: 'relative',
overflow: 'hidden',
boxShadow: state.repetitionRule
? '0 0.5vh 2vh rgba(251, 191, 36, 0.4)'
: '0 0.2vh 0.5vh rgba(0,0,0,0.1)',
_hover: {
bg: state.repetitionRule
? 'rgba(251, 191, 36, 0.35)'
: 'rgba(139, 92, 246, 0.2)',
borderColor: state.repetitionRule
? 'rgba(251, 191, 36, 1)'
: 'rgba(139, 92, 246, 0.5)',
transform: 'translateY(-0.2vh)',
},
_active: {
transform: 'scale(0.98)',
},
})}
>
<div className={css({ flex: 1, pointerEvents: 'none' })}>
<div
className={css({
fontWeight: 'bold',
fontSize: '1.6vh',
color: state.repetitionRule ? '#92400e' : '#7c2d12',
})}
>
{state.repetitionRule && ' '}Threefold Draw
</div>
<div className={css({ fontSize: '1.3vh', color: '#78350f' })}>
Same position 3x
</div>
</div>
{state.repetitionRule && (
<div
className={css({
position: 'absolute',
top: 0,
right: 0,
width: '4vh',
height: '4vh',
borderRadius: '0 1vh 0 100%',
bg: 'rgba(251, 191, 36, 0.4)',
pointerEvents: 'none',
})}
/>
)}
</div>
dataAttribute="threefold-repetition"
/>
{/* Fifty Move Rule */}
<div
data-setting="fifty-move-rule"
<GameRuleCard
title="Fifty-Move Draw"
description="50 moves no event"
enabled={state.fiftyMoveRule}
onClick={() => toggleSetting('fiftyMoveRule')}
className={css({
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
p: '1.5vh',
bg: state.fiftyMoveRule
? 'rgba(251, 191, 36, 0.25)'
: 'rgba(139, 92, 246, 0.1)',
borderRadius: '1vh',
border: '0.3vh solid',
borderColor: state.fiftyMoveRule
? 'rgba(251, 191, 36, 0.8)'
: 'rgba(139, 92, 246, 0.3)',
transition: 'all 0.3s ease',
cursor: 'pointer',
position: 'relative',
overflow: 'hidden',
boxShadow: state.fiftyMoveRule
? '0 0.5vh 2vh rgba(251, 191, 36, 0.4)'
: '0 0.2vh 0.5vh rgba(0,0,0,0.1)',
_hover: {
bg: state.fiftyMoveRule
? 'rgba(251, 191, 36, 0.35)'
: 'rgba(139, 92, 246, 0.2)',
borderColor: state.fiftyMoveRule
? 'rgba(251, 191, 36, 1)'
: 'rgba(139, 92, 246, 0.5)',
transform: 'translateY(-0.2vh)',
},
_active: {
transform: 'scale(0.98)',
},
})}
>
<div className={css({ flex: 1, pointerEvents: 'none' })}>
<div
className={css({
fontWeight: 'bold',
fontSize: '1.6vh',
color: state.fiftyMoveRule ? '#92400e' : '#7c2d12',
})}
>
{state.fiftyMoveRule && ' '}Fifty-Move Draw
</div>
<div className={css({ fontSize: '1.3vh', color: '#78350f' })}>
50 moves no event
</div>
</div>
{state.fiftyMoveRule && (
<div
className={css({
position: 'absolute',
top: 0,
right: 0,
width: '4vh',
height: '4vh',
borderRadius: '0 1vh 0 100%',
bg: 'rgba(251, 191, 36, 0.4)',
pointerEvents: 'none',
})}
/>
)}
</div>
dataAttribute="fifty-move-rule"
/>
{/* Harmony Persistence */}
<div
data-setting="flexible-harmony"
<GameRuleCard
title="Flexible Harmony"
description="Any valid set"
enabled={state.allowAnySetOnRecheck}
onClick={() => toggleSetting('allowAnySetOnRecheck')}
className={css({
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
p: '1.5vh',
bg: state.allowAnySetOnRecheck
? 'rgba(251, 191, 36, 0.25)'
: 'rgba(139, 92, 246, 0.1)',
borderRadius: '1vh',
border: '0.3vh solid',
borderColor: state.allowAnySetOnRecheck
? 'rgba(251, 191, 36, 0.8)'
: 'rgba(139, 92, 246, 0.3)',
transition: 'all 0.3s ease',
cursor: 'pointer',
position: 'relative',
overflow: 'hidden',
boxShadow: state.allowAnySetOnRecheck
? '0 0.5vh 2vh rgba(251, 191, 36, 0.4)'
: '0 0.2vh 0.5vh rgba(0,0,0,0.1)',
_hover: {
bg: state.allowAnySetOnRecheck
? 'rgba(251, 191, 36, 0.35)'
: 'rgba(139, 92, 246, 0.2)',
borderColor: state.allowAnySetOnRecheck
? 'rgba(251, 191, 36, 1)'
: 'rgba(139, 92, 246, 0.5)',
transform: 'translateY(-0.2vh)',
},
_active: {
transform: 'scale(0.98)',
},
})}
>
<div className={css({ flex: 1, pointerEvents: 'none' })}>
<div
className={css({
fontWeight: 'bold',
fontSize: '1.6vh',
color: state.allowAnySetOnRecheck ? '#92400e' : '#7c2d12',
})}
>
{state.allowAnySetOnRecheck && ' '}Flexible Harmony
</div>
<div className={css({ fontSize: '1.3vh', color: '#78350f' })}>
Any valid set
</div>
</div>
{state.allowAnySetOnRecheck && (
<div
className={css({
position: 'absolute',
top: 0,
right: 0,
width: '4vh',
height: '4vh',
borderRadius: '0 1vh 0 100%',
bg: 'rgba(251, 191, 36, 0.4)',
pointerEvents: 'none',
})}
/>
)}
</div>
dataAttribute="flexible-harmony"
/>
</div>
</div>
{/* Start Button - Compact but dramatic */}
<button
type="button"
data-action="start-game"
onClick={startGame}
disabled={startDisabled}
className={css({
width: '100%',
py: '2vh',
bg: startDisabled
? 'rgba(100, 100, 100, 0.5)'
: 'linear-gradient(135deg, rgba(251, 191, 36, 0.95) 0%, rgba(245, 158, 11, 0.95) 100%)',
color: startDisabled ? 'rgba(200, 200, 200, 0.7)' : '#7c2d12',
borderRadius: '1.5vh',
fontSize: '2.5vh',
fontWeight: 'bold',
cursor: startDisabled ? 'not-allowed' : 'pointer',
transition: 'all 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55)',
boxShadow: startDisabled
? '0 0.5vh 1.5vh rgba(0,0,0,0.2)'
: '0 1vh 3vh rgba(251, 191, 36, 0.6), inset 0 -0.3vh 0.5vh rgba(124, 45, 18, 0.3)',
border: '0.3vh solid',
borderColor: startDisabled ? 'rgba(100, 100, 100, 0.3)' : 'rgba(245, 158, 11, 0.8)',
textTransform: 'uppercase',
letterSpacing: '0.3vh',
textShadow: startDisabled
? 'none'
: '0.1vh 0.1vh 0.3vh rgba(124, 45, 18, 0.5), 0 0 1vh rgba(255, 255, 255, 0.3)',
flexShrink: 0,
position: 'relative',
overflow: 'hidden',
_hover: startDisabled
? undefined
: {
transform: 'translateY(-0.5vh) scale(1.02)',
boxShadow:
'0 1.5vh 4vh rgba(251, 191, 36, 0.8), inset 0 -0.3vh 0.5vh rgba(124, 45, 18, 0.4)',
borderColor: 'rgba(251, 191, 36, 1)',
},
_active: startDisabled
? undefined
: {
transform: 'translateY(-0.2vh) scale(0.98)',
},
_before: startDisabled
? undefined
: {
content: '""',
position: 'absolute',
top: 0,
left: '-100%',
width: '100%',
height: '100%',
background:
'linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent)',
animation: 'shimmer 3s infinite',
},
})}
>
BEGIN BATTLE
</button>
<StartButton onClick={startGame} disabled={startDisabled} />
</>
)}
</div>

View File

@@ -0,0 +1,71 @@
import { css } from '../../../../../styled-system/css'
export interface StartButtonProps {
onClick: () => void
disabled: boolean
}
export function StartButton({ onClick, disabled }: StartButtonProps) {
return (
<button
type="button"
data-action="start-game"
onClick={onClick}
disabled={disabled}
className={css({
width: '100%',
py: '2vh',
bg: disabled
? 'rgba(100, 100, 100, 0.5)'
: 'linear-gradient(135deg, rgba(251, 191, 36, 0.95) 0%, rgba(245, 158, 11, 0.95) 100%)',
color: disabled ? 'rgba(200, 200, 200, 0.7)' : '#7c2d12',
borderRadius: '1.5vh',
fontSize: '2.5vh',
fontWeight: 'bold',
cursor: disabled ? 'not-allowed' : 'pointer',
transition: 'all 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55)',
boxShadow: disabled
? '0 0.5vh 1.5vh rgba(0,0,0,0.2)'
: '0 1vh 3vh rgba(251, 191, 36, 0.6), inset 0 -0.3vh 0.5vh rgba(124, 45, 18, 0.3)',
border: '0.3vh solid',
borderColor: disabled ? 'rgba(100, 100, 100, 0.3)' : 'rgba(245, 158, 11, 0.8)',
textTransform: 'uppercase',
letterSpacing: '0.3vh',
textShadow: disabled
? 'none'
: '0.1vh 0.1vh 0.3vh rgba(124, 45, 18, 0.5), 0 0 1vh rgba(255, 255, 255, 0.3)',
flexShrink: 0,
position: 'relative',
overflow: 'hidden',
_hover: disabled
? undefined
: {
transform: 'translateY(-0.5vh) scale(1.02)',
boxShadow:
'0 1.5vh 4vh rgba(251, 191, 36, 0.8), inset 0 -0.3vh 0.5vh rgba(124, 45, 18, 0.4)',
borderColor: 'rgba(251, 191, 36, 1)',
},
_active: disabled
? undefined
: {
transform: 'translateY(-0.2vh) scale(0.98)',
},
_before: disabled
? undefined
: {
content: '""',
position: 'absolute',
top: 0,
left: '-100%',
width: '100%',
height: '100%',
background:
'linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent)',
animation: 'shimmer 3s infinite',
},
})}
>
BEGIN BATTLE
</button>
)
}