feat: redesign the login screen
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 1.9 MiB |
@@ -18,158 +18,51 @@ import { formatNumber } from '@/utils/storage'
|
||||
|
||||
ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Filler, Tooltip)
|
||||
|
||||
const gridLinesPlugin = {
|
||||
id: 'marketGridLines',
|
||||
beforeDatasetsDraw(chart: Chart) {
|
||||
const { ctx, chartArea, scales } = chart
|
||||
if (!chartArea || !scales.y) return
|
||||
|
||||
const { left, right, top, bottom } = chartArea
|
||||
const yScale = scales.y
|
||||
|
||||
ctx.save()
|
||||
ctx.strokeStyle = 'rgba(255, 255, 255, 0.07)'
|
||||
ctx.lineWidth = 1
|
||||
|
||||
yScale.ticks.forEach((tick) => {
|
||||
const y = yScale.getPixelForValue(tick.value)
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(left, y)
|
||||
ctx.lineTo(right, y)
|
||||
ctx.stroke()
|
||||
})
|
||||
|
||||
const verticalCount = 5
|
||||
for (let i = 0; i <= verticalCount; i += 1) {
|
||||
const x = left + ((right - left) / verticalCount) * i
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(x, top)
|
||||
ctx.lineTo(x, bottom)
|
||||
ctx.stroke()
|
||||
}
|
||||
|
||||
ctx.restore()
|
||||
},
|
||||
}
|
||||
|
||||
ChartJS.register(gridLinesPlugin)
|
||||
|
||||
const marketStore = useMarketStore()
|
||||
|
||||
const AXIS_SCALE = 6100
|
||||
|
||||
function createLineGradient(chart: Chart) {
|
||||
const { ctx, chartArea } = chart
|
||||
if (!chartArea) return '#32d74b'
|
||||
|
||||
const gradient = ctx.createLinearGradient(chartArea.left, 0, chartArea.right, 0)
|
||||
gradient.addColorStop(0, '#22e865')
|
||||
gradient.addColorStop(0.45, '#6fdc3a')
|
||||
gradient.addColorStop(0.78, '#c8e630')
|
||||
gradient.addColorStop(1, '#ffd55e')
|
||||
return gradient
|
||||
}
|
||||
|
||||
function createFillGradient(chart: Chart) {
|
||||
const { ctx, chartArea } = chart
|
||||
if (!chartArea) return 'rgba(50, 215, 75, 0.15)'
|
||||
if (!chartArea) return 'rgba(232, 196, 92, 0.2)'
|
||||
|
||||
const { left, top, right, bottom } = chartArea
|
||||
const width = right - left
|
||||
const height = bottom - top
|
||||
|
||||
// Horizontal: green (left) → purple (right)
|
||||
const horizontal = ctx.createLinearGradient(left, 0, right, 0)
|
||||
horizontal.addColorStop(0, 'rgba(34, 220, 100, 0.72)')
|
||||
horizontal.addColorStop(0.35, 'rgba(34, 200, 90, 0.55)')
|
||||
horizontal.addColorStop(0.62, 'rgba(70, 150, 120, 0.38)')
|
||||
horizontal.addColorStop(0.82, 'rgba(118, 55, 201, 0.52)')
|
||||
horizontal.addColorStop(1, 'rgba(156, 80, 233, 0.62)')
|
||||
|
||||
// Vertical fade: opaque under line → transparent at bottom
|
||||
const vertical = ctx.createLinearGradient(0, top, 0, bottom)
|
||||
vertical.addColorStop(0, 'rgba(255, 255, 255, 0.92)')
|
||||
vertical.addColorStop(0.35, 'rgba(255, 255, 255, 0.45)')
|
||||
vertical.addColorStop(0.7, 'rgba(255, 255, 255, 0.12)')
|
||||
vertical.addColorStop(1, 'rgba(255, 255, 255, 0)')
|
||||
|
||||
// Composite horizontal + vertical fade on offscreen canvas
|
||||
const offscreen = document.createElement('canvas')
|
||||
offscreen.width = Math.max(1, Math.round(width))
|
||||
offscreen.height = Math.max(1, Math.round(height))
|
||||
const offCtx = offscreen.getContext('2d')
|
||||
if (!offCtx) return horizontal
|
||||
|
||||
offCtx.fillStyle = horizontal
|
||||
offCtx.fillRect(0, 0, offscreen.width, offscreen.height)
|
||||
offCtx.globalCompositeOperation = 'destination-in'
|
||||
offCtx.fillStyle = vertical
|
||||
offCtx.fillRect(0, 0, offscreen.width, offscreen.height)
|
||||
|
||||
const pattern = ctx.createPattern(offscreen, 'no-repeat')
|
||||
if (!pattern) return horizontal
|
||||
|
||||
// Align pattern with chart area
|
||||
const matrix = new DOMMatrix().translate(left, top)
|
||||
pattern.setTransform(matrix)
|
||||
return pattern
|
||||
const gradient = ctx.createLinearGradient(0, chartArea.top, 0, chartArea.bottom)
|
||||
gradient.addColorStop(0, 'rgba(244, 214, 120, 0.55)')
|
||||
gradient.addColorStop(0.55, 'rgba(118, 75, 190, 0.28)')
|
||||
gradient.addColorStop(1, 'rgba(118, 75, 190, 0)')
|
||||
return gradient
|
||||
}
|
||||
|
||||
function isLastPoint(context: ScriptableContext<'line'>) {
|
||||
const dataset = context.dataset.data as number[]
|
||||
return context.dataIndex === dataset.length - 1
|
||||
}
|
||||
|
||||
function buildYAxisConfig(values: number[]) {
|
||||
if (!values.length) {
|
||||
return { min: 0, max: 1, ticks: [0, 0.33, 0.66, 1] }
|
||||
}
|
||||
|
||||
function paddedDomain(values: number[]) {
|
||||
if (!values.length) return { min: 0, max: 1 }
|
||||
const min = Math.min(...values)
|
||||
const max = Math.max(...values)
|
||||
const range = max - min || max * 0.02
|
||||
const padding = range * 0.025
|
||||
const yMin = min - padding
|
||||
const yMax = max + padding
|
||||
const step = (yMax - yMin) / 3
|
||||
|
||||
return {
|
||||
min: yMin,
|
||||
max: yMax,
|
||||
ticks: [yMin, yMin + step, yMin + step * 2, yMax],
|
||||
}
|
||||
const range = max - min || max * 0.04
|
||||
const padding = range * 0.18
|
||||
return { min: min - padding, max: max + padding }
|
||||
}
|
||||
|
||||
const yAxisConfig = computed(() => buildYAxisConfig(marketStore.priceHistory))
|
||||
const yDomain = computed(() => paddedDomain(marketStore.priceHistory))
|
||||
|
||||
const chartData = computed(() => ({
|
||||
labels: marketStore.labels,
|
||||
datasets: [
|
||||
{
|
||||
data: marketStore.priceHistory,
|
||||
borderColor: (context: ScriptableContext<'line'>) =>
|
||||
createLineGradient(context.chart),
|
||||
backgroundColor: (context: ScriptableContext<'line'>) =>
|
||||
createFillGradient(context.chart),
|
||||
borderColor: '#f4d678',
|
||||
backgroundColor: (context: ScriptableContext<'line'>) => createFillGradient(context.chart),
|
||||
fill: true,
|
||||
tension: 0.42,
|
||||
pointRadius: (context: ScriptableContext<'line'>) =>
|
||||
isLastPoint(context) ? 3 : 0,
|
||||
pointHoverRadius: (context: ScriptableContext<'line'>) =>
|
||||
isLastPoint(context) ? 4 : 0,
|
||||
pointBackgroundColor: '#ffd55e',
|
||||
pointBorderColor: '#ffd55e',
|
||||
pointBorderWidth: 0,
|
||||
pointHoverBackgroundColor: '#ffd55e',
|
||||
pointHoverBorderColor: '#fff8dc',
|
||||
tension: 0.35,
|
||||
pointRadius: 0,
|
||||
pointHoverRadius: 5,
|
||||
pointHoverBackgroundColor: '#fff8dc',
|
||||
pointHoverBorderColor: '#f4d678',
|
||||
pointHoverBorderWidth: 2,
|
||||
borderWidth: 2,
|
||||
borderWidth: 2.5,
|
||||
},
|
||||
],
|
||||
}))
|
||||
|
||||
const chartOptions = computed(() => {
|
||||
const yAxis = yAxisConfig.value
|
||||
const domain = yDomain.value
|
||||
|
||||
return {
|
||||
responsive: true,
|
||||
@@ -207,22 +100,9 @@ const chartOptions = computed(() => {
|
||||
border: { display: false },
|
||||
},
|
||||
y: {
|
||||
position: 'left' as const,
|
||||
display: true,
|
||||
min: yAxis.min,
|
||||
max: yAxis.max,
|
||||
afterBuildTicks: (axis: { ticks: { value: number }[] }) => {
|
||||
axis.ticks = yAxis.ticks.map((value) => ({ value }))
|
||||
},
|
||||
ticks: {
|
||||
color: 'rgba(174, 185, 210, 0.42)',
|
||||
font: { family: 'Vazirmatn', size: 10, weight: 600 },
|
||||
padding: 2,
|
||||
autoSkip: false,
|
||||
maxTicksLimit: 4,
|
||||
callback: (value: string | number) =>
|
||||
formatNumber(Math.round(Number(value) / AXIS_SCALE)),
|
||||
},
|
||||
display: false,
|
||||
min: domain.min,
|
||||
max: domain.max,
|
||||
grid: { display: false },
|
||||
border: { display: false },
|
||||
},
|
||||
@@ -239,7 +119,7 @@ const chartOptions = computed(() => {
|
||||
|
||||
<style scoped>
|
||||
.market-chart {
|
||||
height: 138px;
|
||||
height: 196px;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
margin-top: 4px;
|
||||
|
||||
+200
-152
@@ -1,12 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import PrimaryButton from '@/components/common/PrimaryButton.vue'
|
||||
import { StaleSessionError } from '@/api/client'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
import { useMarketStore } from '@/stores/market'
|
||||
import { useToast } from '@/composables/useToast'
|
||||
import { illustrations } from '@/assets/illustrations'
|
||||
import loginHero from '@/assets/login/login-hero.jpg'
|
||||
|
||||
const router = useRouter()
|
||||
const authStore = useAuthStore()
|
||||
@@ -17,6 +16,7 @@ const isRegister = ref(false)
|
||||
const username = ref('')
|
||||
const password = ref('')
|
||||
const displayName = ref('')
|
||||
const showPassword = ref(false)
|
||||
const loading = ref(false)
|
||||
|
||||
async function submit() {
|
||||
@@ -48,220 +48,268 @@ async function submit() {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function forgotPassword() {
|
||||
toast.error('بازیابی رمز هنوز فعال نشده است.')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="login-page">
|
||||
<div class="login-page__glow login-page__glow--top" aria-hidden="true" />
|
||||
<div class="login-page__glow login-page__glow--bottom" aria-hidden="true" />
|
||||
<div class="login-screen">
|
||||
<div class="login-screen__frame">
|
||||
<img :src="loginHero" alt="" class="login-screen__hero" />
|
||||
|
||||
<div class="login-card card-enter">
|
||||
<div class="login-card__hero">
|
||||
<img :src="illustrations.treasureChest" alt="" class="login-card__icon" aria-hidden="true" />
|
||||
<h1 class="login-card__title">سرزمین طلا</h1>
|
||||
<p class="login-card__subtitle">
|
||||
{{ isRegister ? 'حساب جدید بساز و ماجراجویی مالی رو شروع کن' : 'وارد حسابت شو و ادامه بده' }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<form class="login-form" @submit.prevent="submit">
|
||||
<form class="login-screen__form" @submit.prevent="submit">
|
||||
<label v-if="isRegister" class="login-field">
|
||||
<span class="login-field__label">نام نمایشی</span>
|
||||
<span class="login-field__icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
|
||||
<circle cx="12" cy="8" r="3.2" />
|
||||
<path d="M5 19.2c1.4-3 3.8-4.5 7-4.5s5.6 1.5 7 4.5" stroke-linecap="round" />
|
||||
</svg>
|
||||
</span>
|
||||
<input
|
||||
v-model="displayName"
|
||||
type="text"
|
||||
class="login-field__input"
|
||||
placeholder="مثلاً علی"
|
||||
placeholder="نام نمایشی"
|
||||
autocomplete="name"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label class="login-field">
|
||||
<span class="login-field__label">نام کاربری</span>
|
||||
<span class="login-field__icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
|
||||
<circle cx="12" cy="8" r="3.2" />
|
||||
<path d="M5 19.2c1.4-3 3.8-4.5 7-4.5s5.6 1.5 7 4.5" stroke-linecap="round" />
|
||||
</svg>
|
||||
</span>
|
||||
<input
|
||||
v-model="username"
|
||||
type="text"
|
||||
class="login-field__input"
|
||||
placeholder="demo"
|
||||
placeholder="نام کاربری"
|
||||
autocomplete="username"
|
||||
dir="ltr"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label class="login-field">
|
||||
<span class="login-field__label">رمز عبور</span>
|
||||
<span class="login-field__icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
|
||||
<rect x="6" y="10.5" width="12" height="8.5" rx="2" />
|
||||
<path d="M9 10.5V8.2a3 3 0 0 1 6 0v2.3" stroke-linecap="round" />
|
||||
</svg>
|
||||
</span>
|
||||
<input
|
||||
v-model="password"
|
||||
type="password"
|
||||
class="login-field__input"
|
||||
placeholder="••••••"
|
||||
autocomplete="current-password"
|
||||
dir="ltr"
|
||||
:type="showPassword ? 'text' : 'password'"
|
||||
placeholder="رمز عبور"
|
||||
:autocomplete="isRegister ? 'new-password' : 'current-password'"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="login-field__eye"
|
||||
:aria-label="showPassword ? 'پنهان کردن رمز' : 'نمایش رمز'"
|
||||
@click="showPassword = !showPassword"
|
||||
>
|
||||
<svg v-if="!showPassword" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
|
||||
<path d="M2.8 12S6.2 6.8 12 6.8 21.2 12 21.2 12 17.8 17.2 12 17.2 2.8 12 2.8 12Z" />
|
||||
<circle cx="12" cy="12" r="2.4" />
|
||||
</svg>
|
||||
<svg v-else viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
|
||||
<path d="M4 5.5 19.5 19" stroke-linecap="round" />
|
||||
<path d="M9.2 9.4A3.2 3.2 0 0 0 12 15.2c.7 0 1.3-.2 1.8-.6M6.2 7.8C4.4 9 2.8 12 2.8 12S6.2 17.2 12 17.2c1.3 0 2.5-.3 3.5-.8M10.2 6.9c.6-.1 1.2-.1 1.8-.1 5.8 0 9.2 5.2 9.2 5.2s-.8 1.2-2.2 2.5" stroke-linecap="round" />
|
||||
</svg>
|
||||
</button>
|
||||
</label>
|
||||
|
||||
<PrimaryButton
|
||||
type="submit"
|
||||
variant="gold"
|
||||
size="lg"
|
||||
full-width
|
||||
:disabled="loading"
|
||||
>
|
||||
<button type="submit" class="login-gold" :disabled="loading">
|
||||
{{ loading ? 'لطفاً صبر کن...' : isRegister ? 'ثبتنام' : 'ورود' }}
|
||||
</PrimaryButton>
|
||||
</button>
|
||||
|
||||
<p class="login-or"><span>یا</span></p>
|
||||
|
||||
<button type="button" class="login-outline" @click="isRegister = !isRegister">
|
||||
{{ isRegister ? 'ورود' : 'ثبتنام' }}
|
||||
</button>
|
||||
|
||||
<button type="button" class="login-forgot" @click="forgotPassword">
|
||||
رمز عبور را فراموش کردهاید؟
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<button type="button" class="login-toggle" @click="isRegister = !isRegister">
|
||||
<template v-if="isRegister">
|
||||
حساب داری؟ <span class="login-toggle__action">وارد شو</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
حساب نداری؟ <span class="login-toggle__action">ثبتنام کن</span>
|
||||
</template>
|
||||
</button>
|
||||
|
||||
<p v-if="!isRegister" class="login-hint">حساب آزمایشی: demo / 123456</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.login-page {
|
||||
position: relative;
|
||||
.login-screen {
|
||||
min-height: 100dvh;
|
||||
background: #07111f;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.login-screen__frame {
|
||||
position: relative;
|
||||
width: min(100%, 430px);
|
||||
height: 100dvh;
|
||||
max-height: 100dvh;
|
||||
overflow: hidden;
|
||||
background: #040817;
|
||||
background: #071427;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.login-page__glow {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
pointer-events: none;
|
||||
.login-screen__hero {
|
||||
width: 100%;
|
||||
flex: 1 1 auto;
|
||||
height: 0;
|
||||
min-height: 0;
|
||||
object-fit: cover;
|
||||
object-position: top center;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.login-page__glow--top {
|
||||
top: -80px;
|
||||
right: -40px;
|
||||
width: 220px;
|
||||
height: 220px;
|
||||
background: radial-gradient(circle, rgba(118, 55, 201, 0.35) 0%, transparent 70%);
|
||||
}
|
||||
|
||||
.login-page__glow--bottom {
|
||||
bottom: -60px;
|
||||
left: -30px;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background: radial-gradient(circle, rgba(244, 174, 33, 0.2) 0%, transparent 70%);
|
||||
}
|
||||
|
||||
.login-card {
|
||||
.login-screen__form {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
max-width: 380px;
|
||||
padding: 28px 22px 22px;
|
||||
border-radius: 24px;
|
||||
background: linear-gradient(145deg, rgba(29, 42, 78, 0.98), rgba(12, 23, 50, 0.98));
|
||||
border: 1px solid rgba(118, 75, 190, 0.45);
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.05),
|
||||
0 16px 40px rgba(0, 0, 0, 0.35),
|
||||
0 0 24px rgba(118, 55, 201, 0.15);
|
||||
}
|
||||
|
||||
.login-card__hero {
|
||||
flex: 0 0 auto;
|
||||
margin-top: -56px;
|
||||
padding: 56px 22px calc(16px + env(safe-area-inset-bottom));
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.login-card__icon {
|
||||
width: 88px;
|
||||
height: 88px;
|
||||
object-fit: contain;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.login-card__title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 800;
|
||||
color: var(--gold-light);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.login-card__subtitle {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.login-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
gap: 12px;
|
||||
background: linear-gradient(180deg, rgba(7, 20, 39, 0) 0%, rgba(7, 20, 39, 0.72) 28px, #071427 56px);
|
||||
}
|
||||
|
||||
.login-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
position: relative;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.login-field__label {
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 700;
|
||||
color: var(--text-main);
|
||||
}
|
||||
|
||||
.login-field__input {
|
||||
.login-field input {
|
||||
width: 100%;
|
||||
min-height: 48px;
|
||||
padding: 12px 14px;
|
||||
height: 52px;
|
||||
border-radius: 14px;
|
||||
border: 1px solid rgba(118, 75, 190, 0.45);
|
||||
background: #040817;
|
||||
color: var(--text-main);
|
||||
border: 1.5px solid #9eb0c9;
|
||||
background: #10233f;
|
||||
color: #fff;
|
||||
font-family: inherit;
|
||||
font-size: 0.9375rem;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
text-align: right;
|
||||
padding: 0 46px 0 46px;
|
||||
outline: none;
|
||||
transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
|
||||
}
|
||||
|
||||
.login-field__input:focus {
|
||||
border-color: rgba(244, 174, 33, 0.65);
|
||||
box-shadow: 0 0 0 3px rgba(244, 174, 33, 0.12);
|
||||
.login-field input::placeholder {
|
||||
color: #8ea2bf;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.login-toggle {
|
||||
width: 100%;
|
||||
margin-top: 16px;
|
||||
padding: 8px;
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-muted);
|
||||
.login-field input:focus {
|
||||
border-color: rgba(232, 184, 74, 0.7);
|
||||
}
|
||||
|
||||
.login-field input:-webkit-autofill {
|
||||
-webkit-text-fill-color: #fff;
|
||||
caret-color: #fff;
|
||||
box-shadow: 0 0 0 1000px #10233f inset;
|
||||
}
|
||||
|
||||
.login-field__icon,
|
||||
.login-field__eye {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
height: 52px;
|
||||
width: 42px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
color: #9eb0c9;
|
||||
}
|
||||
|
||||
.login-field__icon {
|
||||
right: 6px;
|
||||
}
|
||||
|
||||
.login-field__eye {
|
||||
left: 4px;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.login-field__icon svg,
|
||||
.login-field__eye svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.login-gold,
|
||||
.login-outline,
|
||||
.login-forgot {
|
||||
font-family: inherit;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.login-toggle__action {
|
||||
color: var(--gold-light);
|
||||
.login-gold {
|
||||
height: 52px;
|
||||
border: 0;
|
||||
border-radius: 14px;
|
||||
color: #1b2433;
|
||||
font-size: 18px;
|
||||
font-weight: 800;
|
||||
background: linear-gradient(180deg, #f6c453 0%, #e3a31a 100%);
|
||||
box-shadow: 0 8px 16px rgba(210, 150, 20, 0.25);
|
||||
}
|
||||
|
||||
.login-hint {
|
||||
margin-top: 14px;
|
||||
text-align: center;
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-muted);
|
||||
.login-gold:disabled,
|
||||
.login-outline:disabled {
|
||||
opacity: 0.7;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.login-or {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
color: #8ea0b8;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.login-or::before,
|
||||
.login-or::after {
|
||||
content: '';
|
||||
flex: 1;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
.login-or::before {
|
||||
background: linear-gradient(90deg, transparent, rgba(158, 176, 201, 0.85));
|
||||
}
|
||||
|
||||
.login-or::after {
|
||||
background: linear-gradient(90deg, rgba(158, 176, 201, 0.85), transparent);
|
||||
}
|
||||
|
||||
.login-outline {
|
||||
height: 50px;
|
||||
border-radius: 14px;
|
||||
border: 1.5px solid #e0b44a;
|
||||
background: transparent;
|
||||
color: #f2d48a;
|
||||
font-size: 17px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.login-forgot {
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: #9aadc6;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 4px;
|
||||
padding: 4px 0 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user