Files
EpicNext-Cms/src/app/globals.css
T
openhands b59d6c21af
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 55s
feat: prioritize game iframe, gated register terms and polished register page
Fetch the Nitro client iframe with high priority so the browser starts the
game document before competing resources, and replace the bare /client
spinner with a branded boot screen. Preconnect and eager loading were already
in place; typing support for the iframe fetchPriority prop is added in a
React type augmentation.

Rework the register terms block into a single clickable accept control with
a custom check state, error shake and inline hint, and dim the submit button
until the terms are accepted. The register page gets labeled sections
(account details / credentials), a corrected banner overlay, translated
show/hide toggles and a captcha slot that reserves height to avoid layout
shifts. English is the source of truth; other locales fall back to it.
2026-08-29 21:14:02 +02:00

1879 lines
45 KiB
CSS

@import "tailwindcss";
@plugin "@tailwindcss/forms";
@plugin "@tailwindcss/typography";
@custom-variant dark (&:where(.dark, .dark *));
@theme {
--font-sans:
var(--font-nunito), "Nunito", ui-sans-serif, system-ui, -apple-system,
"Segoe UI", sans-serif;
--breakpoint-sm: 40rem;
--breakpoint-md: 48rem;
--breakpoint-lg: 64rem;
--breakpoint-xl: 80rem;
--breakpoint-2xl: 96rem;
--radius-sm: 8px;
--radius-md: 12px;
--radius-lg: 16px;
--shadow-card: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04);
--shadow-card-hover:
0 8px 24px rgba(0, 0, 0, 0.1), 0 2px 6px rgba(0, 0, 0, 0.06);
}
/* Default theme variables. ThemeVars may override these at runtime. */
:root {
--color-primary: #eeb425;
--color-primary-hover: #d4a01f;
--color-primary-foreground: #1a1a2e;
--color-background: #f4f6f9;
--color-foreground: #0f172a;
--color-card: #ffffff;
--color-card-foreground: #0f172a;
--color-popover: #ffffff;
--color-popover-foreground: #0f172a;
--color-secondary: #f1f5f9;
--color-secondary-foreground: #0f172a;
--color-muted: #f1f5f9;
--color-muted-foreground: #6b7280;
--color-destructive: #ef4444;
--color-destructive-foreground: #ffffff;
--color-border: #e2e8f0;
--color-input: #e2e8f0;
--color-ring: #eeb425;
--color-surface: #ffffff;
--color-dropdown: #ffffff;
--color-navbar: #ffffff;
--color-navbar-text: #1e293b;
--color-text: #0f172a;
--color-text-muted: #6b7280;
--color-text-readable: #0f172a;
--color-text-muted-readable: #6b7280;
--color-primary-readable: #000000;
--color-accent-readable: #006b49;
--color-primary-foreground-readable: #1a1a2e;
--color-accent-foreground-readable: #000000;
--color-navbar-text-readable: #1e293b;
--color-accent: #10b981;
--color-accent-foreground: #000000;
--color-success: #16a34a;
--color-warning: #eab308;
--color-error: #ef4444;
--color-info: #0ea5e9;
--color-danger: #ef4444;
--gradient-from: #f59e0b;
--gradient-to: #10b981;
--button-color: #eeb425;
--button-text-color: #1a1a2e;
--button-text-color-readable: #1a1a2e;
--button-secondary-color: #22c55e;
--button-secondary-text-color: #ffffff;
--button-secondary-text-color-readable: #000000;
--button-secondary-hover-color: var(--color-success);
--button-danger-color: #ef4444;
--button-danger-text-color: #ffffff;
--button-danger-text-color-readable: #000000;
--button-danger-hover-color: #dc2626;
--button-outline-color: #eeb425;
--button-outline-text-color: #1a1a2e;
--button-outline-text-color-readable: #1a1a2e;
--button-outline-hover-color: #d4a01f;
--border-radius: 12px;
--border-color: #eeb425;
--font-family: var(--font-nunito), "Nunito", sans-serif;
--size-heading-h1: 32px;
--size-heading-h2: 24px;
--size-heading-h3: 20px;
--avatar-border-radius: 10px;
--avatar-border-color: #eeb425;
--badge-background: #eeb425;
--badge-text-color: #000000;
--badge-border-radius: 6px;
--card-border-radius: 14px;
--link-color: #eeb425;
--link-hover-color: #d4a01f;
--link-color-readable: #000000;
--link-hover-color-readable: #000000;
--color-surface-text-readable: #0f172a;
--color-dropdown-text-readable: #0f172a;
--color-pill-text-readable: #0f172a;
--color-badge-text-readable: #000000;
--color-overlay-text-readable: #ffffff;
--input-border-color: #d1d5db;
--input-focus-color: #eeb425;
--navbar-height: 56px;
--muted: var(--color-text-muted);
--border-subtle: color-mix(in srgb, var(--color-text-muted) 18%, transparent);
}
/* Dark mode colors + readable contrast vars are generated by ThemeVars. */
html.dark input,
html.dark select,
html.dark textarea {
background: #11151c;
color: var(--color-text-readable, var(--color-text));
}
html.dark .admin-page table,
html.dark .admin-card {
border-color: var(--admin-border);
}
html.dark .currency,
html.dark .article-img {
background: #1f242d;
}
html {
scroll-behavior: smooth;
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
}
body {
font-family: var(--font-family);
color: var(--color-text-readable, var(--color-text, #0f172a));
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* Mobile-friendly improvements for every screen */
button,
a,
input,
select,
textarea,
summary,
[role="button"],
[role="menuitem"] {
touch-action: manipulation;
}
/* Momentum scrolling on iOS */
* {
-webkit-overflow-scrolling: touch;
}
/* Prevent iOS zoom on input focus */
@media (max-width: 48rem) {
input,
select,
textarea {
font-size: 16px;
}
}
/* Semantic colors: safe across every complete light/dark preset. */
.theme-text-muted {
color: var(--color-text-muted-readable);
}
.theme-text-subtle {
color: var(--color-text-subtle-readable);
}
.theme-text-disabled {
color: var(--color-text-disabled-readable);
}
.theme-status-success,
.theme-status-warning,
.theme-status-error,
.theme-status-info {
border: 1px solid var(--status-border);
background: var(--status-background);
color: var(--status-text);
}
.theme-status-success {
--status-border: var(--color-success-border);
--status-background: var(--color-success-subtle);
--status-text: var(--color-success-text-readable);
}
.theme-status-warning {
--status-border: var(--color-warning-border);
--status-background: var(--color-warning-subtle);
--status-text: var(--color-warning-text-readable);
}
.theme-status-error {
--status-border: var(--color-error-border);
--status-background: var(--color-error-subtle);
--status-text: var(--color-error-text-readable);
}
.theme-status-info {
--status-border: var(--color-info-border);
--status-background: var(--color-info-subtle);
--status-text: var(--color-info-text-readable);
}
::-webkit-scrollbar-thumb {
border-radius: 100px;
border: 4px solid transparent;
background-clip: content-box;
background-color: #2c3039;
}
::-webkit-scrollbar {
width: 12px;
}
::-webkit-scrollbar-track {
background: transparent;
}
/* Theme-aware scrollbars inside the admin panel */
[data-admin] ::-webkit-scrollbar {
width: 10px;
height: 10px;
}
[data-admin] ::-webkit-scrollbar-thumb {
background-color: color-mix(
in srgb,
var(--admin-text-muted) 32%,
transparent
);
}
[data-admin] ::-webkit-scrollbar-thumb:hover {
background-color: color-mix(
in srgb,
var(--admin-text-muted) 55%,
transparent
);
}
/* ── Atom theme components ────────────────────────────────── */
@layer components {
.nav-item {
@apply flex h-auto md:h-[54px] items-center text-[13px] font-bold px-3 md:px-4 relative;
color: var(--color-navbar-text-readable, var(--color-navbar-text, #64748b));
letter-spacing: 0.03em;
text-transform: uppercase;
white-space: nowrap;
transition:
color 0.15s ease-in-out,
background-color 0.15s ease-in-out;
border-radius: 0.5rem;
}
.nav-item:hover {
color: var(--color-primary-readable, var(--color-primary));
background-color: color-mix(in srgb, var(--color-primary) 8%, transparent);
}
.nav-item[aria-current="page"] {
color: var(--color-primary-readable, var(--color-primary));
background-color: color-mix(in srgb, var(--color-primary) 10%, transparent);
}
.nav-item:focus-visible {
outline: 2px solid var(--color-primary-readable, var(--color-primary));
outline-offset: 2px;
}
.dropdown-item {
@apply block py-2.5 px-4 text-sm font-semibold rounded-lg mx-1;
color: var(--color-dropdown-text-readable, var(--color-text-readable));
transition:
background-color 0.1s ease-in-out,
color 0.1s ease-in-out;
}
.dropdown-item:hover {
background-color: color-mix(in srgb, var(--color-primary) 12%, transparent);
color: var(--color-primary-readable, var(--color-primary));
}
.dropdown-item:focus-visible {
outline: 2px solid var(--color-primary-readable, var(--color-primary));
outline-offset: -2px;
}
.dropdown-menu {
background-color: var(--color-dropdown);
border: 1px solid
color-mix(in srgb, var(--color-text-muted) 14%, transparent);
box-shadow: 0 8px 32px color-mix(in srgb, rgb(0, 0, 0) 20%, transparent);
}
}
/* ── Site background: Habbo sky ── */
.site-bg {
background: linear-gradient(
180deg,
color-mix(in srgb, var(--color-primary) 4%, #b3d9f7) 0%,
color-mix(in srgb, var(--color-primary) 6%, #d4e8fa) 25%,
color-mix(in srgb, var(--color-primary) 8%, #e8f0f8) 50%,
color-mix(in srgb, var(--color-primary) 10%, #f0e8d8) 75%,
color-mix(in srgb, var(--color-primary) 14%, var(--color-background)) 100%
);
background-attachment: fixed;
position: relative;
}
/* Habbo-style clouds */
.site-bg::before {
content: "";
position: fixed;
inset: 0;
pointer-events: none;
z-index: -1;
background:
radial-gradient(
ellipse 240px 60px at 15% 8%,
rgba(255, 255, 255, 0.5) 0%,
transparent 100%
),
radial-gradient(
ellipse 320px 70px at 35% 12%,
rgba(255, 255, 255, 0.4) 0%,
transparent 100%
),
radial-gradient(
ellipse 200px 50px at 55% 6%,
rgba(255, 255, 255, 0.45) 0%,
transparent 100%
),
radial-gradient(
ellipse 280px 65px at 75% 10%,
rgba(255, 255, 255, 0.5) 0%,
transparent 100%
),
radial-gradient(
ellipse 180px 45px at 90% 5%,
rgba(255, 255, 255, 0.35) 0%,
transparent 100%
),
radial-gradient(
ellipse 260px 55px at 50% 18%,
rgba(255, 255, 255, 0.25) 0%,
transparent 100%
),
radial-gradient(
ellipse 200px 40px at 20% 22%,
rgba(255, 255, 255, 0.2) 0%,
transparent 100%
);
}
/* Subtle primary glow */
.site-bg::after {
content: "";
position: fixed;
inset: 0;
pointer-events: none;
z-index: -1;
background:
radial-gradient(
ellipse 600px 400px at 20% 0%,
color-mix(in srgb, var(--color-primary) 10%, transparent) 0%,
transparent 100%
),
radial-gradient(
ellipse 500px 300px at 80% 0%,
color-mix(in srgb, var(--color-primary) 6%, transparent) 0%,
transparent 100%
);
}
html.dark .site-bg {
background: linear-gradient(
180deg,
color-mix(in srgb, var(--color-primary) 6%, #0a0e1a) 0%,
color-mix(in srgb, var(--color-primary) 8%, #10152a) 30%,
color-mix(in srgb, var(--color-primary) 10%, #161c30) 60%,
color-mix(in srgb, var(--color-primary) 12%, #0f141f) 100%
);
background-attachment: fixed;
}
html.dark .site-bg::before {
opacity: 0.08;
background:
radial-gradient(
ellipse 240px 60px at 15% 8%,
rgba(200, 210, 255, 0.5) 0%,
transparent 100%
),
radial-gradient(
ellipse 320px 70px at 35% 12%,
rgba(200, 210, 255, 0.4) 0%,
transparent 100%
),
radial-gradient(
ellipse 200px 50px at 55% 6%,
rgba(200, 210, 255, 0.45) 0%,
transparent 100%
),
radial-gradient(
ellipse 280px 65px at 75% 10%,
rgba(200, 210, 255, 0.5) 0%,
transparent 100%
),
radial-gradient(
ellipse 180px 45px at 90% 5%,
rgba(200, 210, 255, 0.35) 0%,
transparent 100%
),
radial-gradient(
ellipse 260px 55px at 50% 18%,
rgba(200, 210, 255, 0.25) 0%,
transparent 100%
),
radial-gradient(
ellipse 200px 40px at 20% 22%,
rgba(200, 210, 255, 0.2) 0%,
transparent 100%
);
}
html.dark .site-bg::after {
background:
radial-gradient(
ellipse 600px 400px at 20% 0%,
color-mix(in srgb, var(--color-primary) 14%, transparent) 0%,
transparent 100%
),
radial-gradient(
ellipse 500px 300px at 80% 0%,
color-mix(in srgb, var(--color-primary) 8%, transparent) 0%,
transparent 100%
);
}
/* Admin must not inherit the public wallpaper — solid HK canvas only. */
body.site-bg:has([data-admin]),
html.dark body.site-bg:has([data-admin]) {
background: var(--admin-canvas);
background-image: none;
background-blend-mode: normal;
}
.article-body {
line-height: 1.7;
}
.article-body img {
max-width: 100%;
height: auto;
border-radius: 8px;
}
.article-body p {
margin: 0 0 0.85rem;
}
.article-body a {
text-decoration: underline;
}
.text-muted {
color: var(--color-text-muted-readable, var(--color-text-muted));
}
.text-nav {
color: var(--color-navbar-text-readable, var(--color-navbar-text));
}
.text-shadow {
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
}
.text-shadow-sm {
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}
.hover-lift {
transition:
transform 0.2s ease,
box-shadow 0.2s ease;
}
.hover-lift:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-card-hover);
}
/* ── App component classes (used across the converted pages) ── */
h1 {
font-size: var(--size-heading-h1, 30px);
font-weight: 800;
margin: 0.2em 0 0.5em;
}
h2 {
font-size: var(--size-heading-h2, 22px);
font-weight: 700;
}
h3 {
font-size: var(--size-heading-h3, 18px);
font-weight: 700;
}
a {
color: var(--link-color-readable, var(--link-color));
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.muted {
color: var(--color-text-muted-readable, var(--color-text-muted));
font-size: 0.875rem;
}
.hero {
background: linear-gradient(
135deg,
color-mix(in srgb, var(--gradient-from) 14%, var(--color-navbar)),
color-mix(in srgb, var(--gradient-to) 8%, var(--color-navbar))
);
border: 1px solid color-mix(in srgb, var(--color-primary) 20%, transparent);
border-radius: var(--radius-lg);
padding: 2rem 2.25rem;
box-shadow: var(--shadow-card);
margin-bottom: 1.5rem;
}
.card {
background: var(--color-surface);
color: var(--color-surface-text-readable, var(--color-text-readable));
border: 1px solid color-mix(in srgb, var(--color-text-muted) 12%, transparent);
border-radius: var(--card-border-radius);
box-shadow: var(--shadow-card);
padding: 1.1rem 1.25rem;
transition:
transform 0.2s ease,
box-shadow 0.2s ease;
}
.card:hover {
box-shadow: var(--shadow-card-hover);
}
.card.hover:hover {
transform: translateY(-3px);
box-shadow: var(--shadow-card-hover);
}
.article-img {
width: 100%;
height: 140px;
object-fit: cover;
display: block;
background: linear-gradient(135deg, #fde68a, #fbbf24);
}
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.4rem;
padding: 0.5rem 1.1rem;
border-radius: var(--border-radius);
border: 2px solid transparent;
font-family: inherit;
font-weight: 700;
font-size: 14px;
cursor: pointer;
transition: all 0.18s ease;
background: color-mix(
in srgb,
var(--color-text-muted) 14%,
var(--color-surface)
);
color: var(--color-text-readable, var(--color-text));
text-decoration: none;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
text-decoration: none;
}
.btn-primary {
background: var(--button-color);
color: var(--button-text-color-readable, var(--button-text-color));
}
.btn-secondary {
background: var(--button-secondary-color);
color: var(
--button-secondary-text-color-readable,
var(--button-secondary-text-color)
);
}
.btn-danger {
background: var(--button-danger-color);
color: var(
--button-danger-text-color-readable,
var(--button-danger-text-color)
);
}
.btn-outline {
background: transparent;
border-color: var(--button-outline-color);
color: var(
--button-outline-text-color-readable,
var(--button-outline-text-color)
);
}
input,
select,
textarea {
font-family: inherit;
font-size: 14px;
padding: 0.55rem 0.8rem;
border: 2px solid color-mix(in srgb, var(--color-text-muted) 20%, transparent);
border-radius: var(--radius-sm);
background: var(--color-surface);
color: var(--color-text-readable, var(--color-text));
outline: none;
transition:
border-color 0.2s ease,
box-shadow 0.2s ease;
}
input:focus,
select:focus,
textarea:focus {
border-color: var(--color-primary);
box-shadow: 0 0 0 3px
color-mix(in srgb, var(--color-primary) 15%, transparent);
}
table {
width: 100%;
border-collapse: collapse;
}
th {
text-align: left;
color: var(--color-text-muted-readable, var(--color-text-muted));
font-size: 0.78rem;
text-transform: uppercase;
letter-spacing: 0.04em;
padding: 0.5rem 0.6rem;
font-weight: 700;
}
td {
padding: 0.6rem 0.6rem;
border-top: 1px solid
color-mix(in srgb, var(--color-text-muted) 10%, transparent);
}
tbody tr {
transition: background 0.15s ease;
}
tbody tr:hover {
background: color-mix(in srgb, var(--color-primary) 5%, transparent);
}
.avatar {
border-radius: var(--avatar-border-radius);
background: var(--color-surface);
border: 2px solid var(--avatar-border-color);
}
.currency {
display: inline-flex;
align-items: center;
gap: 0.4rem;
font-weight: 800;
font-size: 0.85rem;
padding: 0.2rem 0.6rem 0.2rem 0.2rem;
border-radius: 999px;
background: var(--color-surface);
border: 1px solid color-mix(in srgb, var(--color-text-muted) 15%, transparent);
color: var(--color-pill-text-readable, var(--color-text-readable));
}
.nav-credit-icon {
background: #e9b124 url("/assets/images/icons/currency/credits.png") center
no-repeat;
background-size: contain;
outline: 1px solid #b26d18;
}
.nav-ducket-icon {
background: #c44aac url("/assets/images/icons/currency/duckets.png") center
no-repeat;
background-size: contain;
outline: 1px solid #812378;
}
.nav-diamond-icon {
background: #caf1f3 url("/assets/images/icons/currency/diamonds.png") center
no-repeat;
background-size: contain;
outline: 1px solid #6caff4;
}
/* ── Admin panel (Housekeeping) ─────────────────────────────────
Modern, consistent styling for all admin content pages. */
.admin-page {
scroll-margin-top: 1rem;
}
/* Hub chrome already shows the section title — soften page-level heroes. */
.admin-hub-panel > .space-y-6 > div:first-child > h1.text-3xl {
font-size: 1.15rem;
letter-spacing: -0.01em;
}
/* Page heading */
.admin-page main > h1:first-child,
.admin-page > h1:first-child {
margin-top: 0;
}
/* Cards used inside admin pages */
.admin-card {
background: var(--admin-surface);
color: var(--admin-text);
border: 1px solid var(--admin-border);
border-radius: 16px;
box-shadow: var(--shadow-card);
padding: 1.25rem;
transition: box-shadow 0.2s ease;
}
/* Card with filter/search bar — compact horizontal layout */
.admin-filter-bar {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
align-items: center;
margin-bottom: 1.25rem;
}
.admin-filter-bar input,
.admin-filter-bar select {
flex: 1;
min-width: 200px;
}
/* Compact stat row for list pages (counts, summaries) */
.admin-stat-row {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
margin-bottom: 1.25rem;
}
.admin-stat-chip {
display: inline-flex;
align-items: center;
gap: 0.4rem;
padding: 0.4rem 0.75rem;
background: color-mix(in srgb, var(--admin-accent) 8%, var(--admin-surface));
border: 1px solid color-mix(in srgb, var(--admin-accent) 15%, transparent);
border-radius: 999px;
font-size: 0.78rem;
font-weight: 600;
}
/* Tables */
.admin-page table {
width: 100%;
background: var(--admin-surface);
border: 1px solid var(--admin-border);
border-radius: 16px;
overflow: hidden;
box-shadow: var(--shadow-card);
border-collapse: separate;
border-spacing: 0;
}
.admin-page thead th {
background: color-mix(in srgb, var(--admin-accent) 8%, var(--admin-surface));
color: var(--admin-text);
border-bottom: 1px solid var(--admin-border);
white-space: nowrap;
font-size: 0.68rem;
font-weight: 700;
letter-spacing: 0.05em;
text-transform: uppercase;
padding: 0.75rem 0.9rem;
}
.admin-page td {
padding: 0.7rem 0.9rem;
border-top: 1px solid
color-mix(in srgb, var(--admin-text-muted) 8%, transparent);
font-size: 0.88rem;
}
.admin-page tbody tr {
transition: background 0.12s ease;
}
.admin-page tbody tr:hover {
background: color-mix(in srgb, var(--admin-accent) 4%, transparent);
}
.admin-page thead tr:first-child th:first-child {
border-radius: 16px 0 0 0;
}
.admin-page thead tr:first-child th:last-child {
border-radius: 0 16px 0 0;
}
/* Section heading inside admin pages */
.admin-section-title {
font-size: 0.9rem;
font-weight: 700;
margin: 1.5rem 0 0.75rem;
color: var(--admin-text);
}
.admin-section-title:first-child {
margin-top: 0;
}
.admin-info-item {
display: flex;
flex-direction: column;
gap: 0.15rem;
}
/* Empty state */
.admin-empty {
text-align: center;
padding: 2.5rem 1rem;
color: var(--admin-text-muted);
font-size: 0.85rem;
}
/* ── Public design system (faithful to the atom theme) ──────────
content-card = surface card with a primary-tinted header (icon +
title + subtitle) and a padded body — the signature atom block. */
.content-card {
display: flex;
flex-direction: column;
width: 100%;
background: var(--color-surface);
color: var(
--color-surface-text-readable,
var(--color-text-readable, var(--color-text))
);
border: 1px solid
color-mix(
in srgb,
var(--color-text-muted-readable, var(--color-text-muted)) 12%,
transparent
);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-card);
overflow: hidden;
transition: box-shadow 0.2s ease;
}
.content-card:hover {
box-shadow: var(--shadow-card-hover);
}
.content-card-head {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.9rem 1.1rem;
background: linear-gradient(
135deg,
color-mix(in srgb, var(--color-primary) 10%, var(--color-surface)),
color-mix(in srgb, var(--color-primary) 5%, var(--color-surface))
);
border-bottom: 1px solid
color-mix(
in srgb,
var(--color-text-muted-readable, var(--color-text-muted)) 8%,
transparent
);
}
.content-card-icon {
flex: none;
width: 44px;
height: 44px;
border-radius: 999px;
display: grid;
place-items: center;
font-size: 1.25rem;
background: linear-gradient(
135deg,
color-mix(in srgb, var(--color-primary) 22%, var(--color-surface)),
color-mix(in srgb, var(--color-primary) 12%, var(--color-surface))
);
box-shadow: inset 0 0 0 1px
color-mix(in srgb, var(--color-primary) 30%, transparent);
}
.content-card-head-text {
min-width: 0;
flex: 1;
}
.content-card-title {
margin: 0;
font-weight: 700;
font-size: 1rem;
line-height: 1.3;
color: var(
--color-surface-text-readable,
var(--color-text-readable, var(--color-text))
);
}
.content-card-subtitle {
margin: 0.15rem 0 0;
font-size: 0.78rem;
color: var(--color-text-muted-readable, var(--color-text-muted));
}
.content-card-action {
flex: none;
}
.content-card-body {
padding: 1.1rem;
}
/* Responsive card grids (atom: 1 / sm2 / md3 / lg4). */
.card-grid {
display: grid;
gap: 1rem;
grid-template-columns: 1fr;
}
@media (min-width: 40rem) {
.card-grid.sm-2 {
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: 48rem) {
.card-grid.md-2 {
grid-template-columns: repeat(2, 1fr);
}
.card-grid.md-3 {
grid-template-columns: repeat(3, 1fr);
}
}
@media (min-width: 64rem) {
.card-grid.lg-3 {
grid-template-columns: repeat(3, 1fr);
}
.card-grid.lg-4 {
grid-template-columns: repeat(4, 1fr);
}
}
/* Stat tiles (value in the primary colour + muted label). */
.stat-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
gap: 0.85rem;
}
.stat-block {
background: var(--color-background);
border: 1px solid
color-mix(
in srgb,
var(--color-text-muted-readable, var(--color-text-muted)) 12%,
transparent
);
border-radius: 12px;
padding: 0.85rem 1rem;
text-align: center;
}
.stat-block-value {
font-size: 1.6rem;
font-weight: 800;
line-height: 1.1;
color: var(--color-primary-readable, var(--color-primary));
}
.stat-block-label {
margin-top: 0.2rem;
font-size: 0.78rem;
color: var(--color-text-muted-readable, var(--color-text-muted));
}
/* Empty states */
.empty-state {
text-align: center;
padding: 2rem 1rem;
}
.empty-state-icon {
font-size: 2rem;
margin-bottom: 0.4rem;
}
/* Online / offline pill */
.online-badge {
display: inline-flex;
align-items: center;
gap: 0.35rem;
font-size: 0.74rem;
font-weight: 700;
padding: 0.1rem 0.55rem 0.1rem 0.45rem;
border-radius: 999px;
background: color-mix(
in srgb,
var(--color-text-muted-readable, var(--color-text-muted)) 14%,
transparent
);
color: var(--color-text-muted-readable, var(--color-text-muted));
}
.online-badge.online {
background: color-mix(in srgb, var(--color-success) 16%, transparent);
color: var(--color-success);
}
.online-dot {
width: 8px;
height: 8px;
border-radius: 999px;
background: currentColor;
}
.online-badge.online .online-dot {
background: var(--color-success);
box-shadow: 0 0 0 3px
color-mix(in srgb, var(--color-success) 22%, transparent);
}
/* Leaderboard rank chip */
.rank-badge {
display: inline-grid;
place-items: center;
min-width: 2.1rem;
height: 2.1rem;
padding: 0 0.35rem;
border-radius: 999px;
font-weight: 800;
font-size: 0.95rem;
background: var(--color-background);
border: 1px solid
color-mix(
in srgb,
var(--color-text-muted-readable, var(--color-text-muted)) 18%,
transparent
);
}
.rank-badge.rank-1 {
background: color-mix(in srgb, var(--color-warning) 20%, transparent);
border-color: var(--color-warning);
}
.rank-badge.rank-2 {
background: color-mix(in srgb, #94a3b8 22%, transparent);
border-color: #94a3b8;
}
.rank-badge.rank-3 {
background: color-mix(in srgb, #f97316 20%, transparent);
border-color: #f97316;
}
/* ── Radio sidebar ──────────────────────────────────────────── */
.radio-layout {
display: flex;
gap: 1.5rem;
align-items: flex-start;
}
.radio-sidebar {
flex: none;
width: 200px;
position: sticky;
top: 5rem;
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.radio-sidebar-link:hover {
background: color-mix(in srgb, var(--color-primary) 10%, transparent);
text-decoration: none;
}
@media (max-width: 48rem) {
.radio-layout {
flex-direction: column;
}
.radio-sidebar {
position: static;
width: 100%;
flex-direction: row;
flex-wrap: wrap;
gap: 0.25rem;
padding-bottom: 0.5rem;
border-bottom: 1px solid
color-mix(
in srgb,
var(--color-text-muted-readable, var(--color-text-muted)) 14%,
transparent
);
overflow-x: auto;
}
.radio-sidebar-head {
display: none;
}
.radio-sidebar-link {
font-size: 0.82rem;
padding: 0.35rem 0.6rem;
white-space: nowrap;
}
}
/* ── Skeleton shimmer animation ─────────────────────────────── */
@keyframes shimmer {
0% {
opacity: 0.6;
}
50% {
opacity: 1;
}
100% {
opacity: 0.6;
}
}
/* Footer CMS info popup */
.cms-info-trigger {
appearance: none;
border: 0;
background: transparent;
color: var(--color-primary-readable, var(--color-primary));
cursor: pointer;
font: inherit;
font-size: 0.78rem;
font-weight: 800;
line-height: 1;
padding: 0.35rem 0.5rem;
text-decoration: underline;
text-decoration-thickness: 2px;
text-underline-offset: 3px;
}
.cms-info-trigger:hover,
.cms-info-trigger:focus-visible {
color: var(--color-primary-readable, var(--color-primary));
}
.cms-info-trigger:focus-visible,
.cms-info-close:focus-visible {
outline: 3px solid color-mix(in srgb, var(--color-primary) 42%, transparent);
outline-offset: 3px;
}
.cms-info-backdrop {
position: fixed;
inset: 0;
z-index: 1000;
display: grid;
place-items: center;
padding: 1rem;
background: rgba(8, 10, 14, 0.68);
backdrop-filter: blur(6px);
}
.cms-info-dialog {
position: relative;
width: min(440px, 100%);
border: 1px solid
color-mix(
in srgb,
var(--color-primary) 30%,
color-mix(in srgb, var(--color-text-muted) 22%, transparent)
);
border-radius: 8px;
background:
linear-gradient(
135deg,
color-mix(in srgb, var(--color-primary) 12%, transparent),
transparent 42%
),
var(--color-surface);
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.34);
color: var(
--color-surface-text-readable,
var(--color-text-readable, var(--color-text))
);
padding: 1.25rem;
}
.cms-info-close {
position: absolute;
top: 0.75rem;
right: 0.75rem;
display: grid;
width: 2rem;
height: 2rem;
place-items: center;
border: 1px solid
color-mix(
in srgb,
var(--color-text-muted-readable, var(--color-text-muted)) 18%,
transparent
);
border-radius: 999px;
background: color-mix(in srgb, var(--color-surface) 84%, transparent);
color: var(--color-text-muted-readable, var(--color-text-muted));
cursor: pointer;
font-weight: 900;
line-height: 1;
}
.cms-info-close:hover {
color: var(
--color-surface-text-readable,
var(--color-text-readable, var(--color-text))
);
border-color: color-mix(in srgb, var(--color-primary) 40%, transparent);
}
.cms-info-kicker {
color: var(--color-primary-readable, var(--color-primary));
font-size: 0.74rem;
font-weight: 900;
letter-spacing: 0;
text-transform: uppercase;
}
.cms-info-dialog h2 {
margin: 0.2rem 2.2rem 0 0;
font-size: 1.75rem;
font-weight: 900;
line-height: 1.1;
}
.cms-info-badge {
display: inline-flex;
align-items: center;
margin-top: 0.65rem;
border: 1px solid color-mix(in srgb, var(--color-primary) 34%, transparent);
border-radius: 999px;
background: color-mix(in srgb, var(--color-primary) 14%, transparent);
color: var(
--color-surface-text-readable,
var(--color-text-readable, var(--color-text))
);
font-size: 0.75rem;
font-weight: 900;
padding: 0.3rem 0.6rem;
}
.cms-info-copy {
margin: 0.9rem 0 0;
color: var(--color-text-muted-readable, var(--color-text-muted));
font-size: 0.92rem;
line-height: 1.55;
}
.cms-info-grid {
display: grid;
gap: 0.5rem;
grid-template-columns: repeat(3, minmax(0, 1fr));
margin: 1rem 0 0;
}
.cms-info-grid div {
border: 1px solid
color-mix(
in srgb,
var(--color-text-muted-readable, var(--color-text-muted)) 14%,
transparent
);
border-radius: 8px;
background: color-mix(in srgb, var(--color-background) 68%, transparent);
padding: 0.7rem;
}
.cms-info-grid dt {
color: var(--color-text-muted-readable, var(--color-text-muted));
font-size: 0.68rem;
font-weight: 800;
text-transform: uppercase;
}
.cms-info-grid dd {
margin: 0.18rem 0 0;
color: var(
--color-surface-text-readable,
var(--color-text-readable, var(--color-text))
);
font-size: 0.8rem;
font-weight: 900;
line-height: 1.25;
}
.cms-info-credit-list {
display: grid;
gap: 0.5rem;
margin-top: 1rem;
}
.cms-info-credit {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
border: 1px solid color-mix(in srgb, var(--color-primary) 18%, transparent);
border-radius: 8px;
background: color-mix(in srgb, var(--color-primary) 8%, transparent);
padding: 0.65rem 0.75rem;
}
.cms-info-credit span {
color: var(
--color-surface-text-readable,
var(--color-text-readable, var(--color-text))
);
font-weight: 900;
}
.cms-info-credit small {
color: var(--color-text-muted-readable, var(--color-text-muted));
font-size: 0.74rem;
font-weight: 700;
text-align: right;
}
@media (max-width: 520px) {
.cms-info-dialog {
padding: 1rem;
}
.cms-info-grid {
grid-template-columns: 1fr;
}
.cms-info-credit {
align-items: flex-start;
flex-direction: column;
gap: 0.2rem;
}
.cms-info-credit small {
text-align: left;
}
}
/* ── Mobile responsive overrides ──────────────────────────── */
@media (max-width: 48rem) {
h1 {
font-size: clamp(1.25rem, 5vw, var(--size-heading-h1, 30px));
}
h2 {
font-size: clamp(1.1rem, 4vw, var(--size-heading-h2, 22px));
}
.hero {
padding: 1.25rem 1rem;
}
.card {
padding: 0.85rem 1rem;
}
.admin-card {
padding: 0.85rem;
}
.admin-filter-bar input,
.admin-filter-bar select {
min-width: 140px;
}
.admin-page td,
.admin-page th {
white-space: nowrap;
padding: 0.5rem 0.6rem;
font-size: 0.78rem;
}
.stat-grid {
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}
.btn {
font-size: 13px;
padding: 0.4rem 0.85rem;
}
.content-card-head {
padding: 0.7rem 0.85rem;
}
.content-card-body {
padding: 0.85rem;
}
.nav-item {
white-space: normal;
text-wrap: balance;
font-size: 12px;
padding: 0.5rem 0.75rem;
height: auto;
min-height: 44px;
}
.dropdown-item {
font-size: 13px;
padding: 0.6rem 0.85rem;
}
}
/* make tables scroll on small screens */
@media (max-width: 640px) {
table {
display: block;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
}
/* ── Admin (HK) semantic token remap ──────────────────────────────────────
Shared shadcn UI primitives (Button, Badge, Input, Select, Card, Table,
Tabs, Dialog, Switch, Checkbox, Tooltip, …) are built on the site's
semantic tokens (--color-background, --color-primary, --color-popover,
--color-border, --color-ring, --color-muted-foreground, …). On admin
pages we remap those tokens onto the admin palette so every embedded
component renders with the admin theme and guaranteed contrast, without
touching any component file.
Gated by `body:has([data-admin])` so the public site is completely
unaffected. This also covers Radix portals (Dialog/Select/Dropdown/
Popover/Tooltip) which mount under <body>. */
body:has([data-admin]) {
/* Full public→admin token remap so shadcn + body + leftover
public utilities all inherit the admin palette with contrast. */
--color-background: var(--admin-canvas);
--color-foreground: var(--admin-text);
--color-card: var(--admin-surface);
--color-card-foreground: var(--admin-text);
--color-popover: var(--admin-surface-elevated);
--color-popover-foreground: var(--admin-text);
--color-primary: var(--admin-accent);
--color-primary-hover: color-mix(in srgb, var(--admin-accent) 84%, #000000);
--color-primary-foreground: var(--admin-accent-foreground);
--color-secondary: color-mix(
in srgb,
var(--admin-accent) 14%,
var(--admin-surface)
);
--color-secondary-foreground: var(--admin-text);
--color-muted: color-mix(in srgb, var(--admin-text) 9%, var(--admin-surface));
--color-muted-foreground: var(--admin-text-muted);
--color-accent: color-mix(
in srgb,
var(--admin-accent) 16%,
var(--admin-surface)
);
--color-accent-foreground: var(--admin-text);
--color-destructive: var(--admin-error);
--color-destructive-foreground: var(--admin-error-foreground);
--color-border: var(--admin-border);
--color-input: var(--admin-border);
--color-ring: var(--admin-accent);
/* Public Atom tokens still referenced by body / .muted / inputs */
--color-text: var(--admin-text);
--color-text-readable: var(--admin-text);
--color-text-muted: var(--admin-text-muted);
--color-text-muted-readable: var(--admin-text-muted);
--color-surface: var(--admin-surface);
--color-surface-text-readable: var(--admin-text);
--color-dropdown: var(--admin-surface);
--color-dropdown-text-readable: var(--admin-text);
--input-border-color: var(--admin-border);
--input-focus-color: var(--admin-accent);
--muted: var(--admin-text-muted);
--border-subtle: color-mix(in srgb, var(--admin-text-muted) 22%, transparent);
color: var(--admin-text);
background-color: var(--admin-canvas);
font-family: var(--font-family);
}
/* Admin forms / boxes follow admin tokens in both light and dark. */
body:has([data-admin])
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not(
[type="file"]
):not([type="color"]),
body:has([data-admin]) select,
body:has([data-admin]) textarea {
background-color: var(--admin-surface-elevated);
color: var(--admin-text);
border-color: var(--admin-border);
caret-color: var(--admin-text);
}
body:has([data-admin]) input::placeholder,
body:has([data-admin]) textarea::placeholder {
color: var(--admin-text-muted);
opacity: 0.85;
}
body:has([data-admin]) .muted,
body:has([data-admin]) .admin-empty,
body:has([data-admin]) .text-muted-foreground {
color: var(--admin-text-muted);
}
body:has([data-admin]) .admin-card,
body:has([data-admin]) .admin-page table {
background: var(--admin-surface);
color: var(--admin-text);
border-color: var(--admin-border);
}
body:has([data-admin]) .btn-outline {
color: var(--admin-text);
border-color: var(--admin-border);
background: transparent;
}
body:has([data-admin]) .btn-outline:hover {
background: color-mix(in srgb, var(--admin-accent) 12%, transparent);
color: var(--admin-text);
}
/* Override public html.dark input hardcodes inside admin. */
html.dark
body:has([data-admin])
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not(
[type="file"]
):not([type="color"]),
html.dark body:has([data-admin]) select,
html.dark body:has([data-admin]) textarea {
background: var(--admin-surface-elevated);
color: var(--admin-text);
}
/* Opaque floating surfaces for Radix portals (Select / Dropdown / Popover / Dialog).
Without this, bg-popover can resolve transparent and lists paint over forms. */
body:has([data-admin]) [data-slot="select-content"],
body:has([data-admin]) [data-slot="dropdown-menu-content"],
body:has([data-admin]) [data-slot="dropdown-menu-sub-content"],
body:has([data-admin]) [data-slot="popover-content"],
body:has([data-admin]) [data-slot="context-menu-content"],
body:has([data-admin]) [data-slot="dialog-content"],
body:has([data-admin]) [data-slot="sheet-content"] {
background-color: var(--admin-surface-elevated);
color: var(--admin-text);
border-color: var(--admin-border);
box-shadow:
0 18px 48px rgba(0, 0, 0, 0.45),
0 4px 12px rgba(0, 0, 0, 0.25);
}
body:has([data-admin]) [data-slot="select-trigger"],
body:has([data-admin]) [data-slot="dropdown-menu-trigger"] {
background-color: var(--admin-surface-elevated);
color: var(--admin-text);
border-color: var(--admin-border);
}
body:has([data-admin]) [data-slot="select-item"][data-highlighted],
body:has([data-admin]) [data-slot="select-item"]:focus,
body:has([data-admin]) [data-slot="dropdown-menu-item"][data-highlighted],
body:has([data-admin]) [data-slot="dropdown-menu-item"]:focus,
body:has([data-admin]) [data-slot="context-menu-item"][data-highlighted],
body:has([data-admin]) [data-slot="context-menu-item"]:focus {
background-color: color-mix(
in srgb,
var(--admin-accent) 18%,
var(--admin-surface-elevated)
);
color: var(--admin-text);
}
body:has([data-admin]) [data-slot="card"] {
background-color: var(--admin-surface);
color: var(--admin-text);
border-color: var(--admin-border);
}
/* ── Details/summary open states for nav ──────────────────── */
details[open] > summary .details-open\:hidden {
display: none;
}
details[open] > summary .details-open\:block {
display: block;
}
details[open] > summary .details-open\:rotate-180 {
transform: rotate(180deg);
}
/* ── Public error / 404 screen ───────────────────────────── */
@keyframes error-screen-rise {
from {
opacity: 0;
transform: translateY(14px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.error-screen {
position: relative;
isolation: isolate;
display: grid;
place-items: center;
min-height: min(70vh, 36rem);
padding: 2rem 1rem 3rem;
}
.error-screen-glow {
pointer-events: none;
position: absolute;
inset: 10% 15% auto;
height: 12rem;
border-radius: 50%;
background: radial-gradient(
ellipse at center,
color-mix(in srgb, var(--color-primary) 35%, transparent),
transparent 70%
);
filter: blur(8px);
z-index: 0;
opacity: 0.85;
}
.error-screen-panel {
position: relative;
z-index: 1;
width: min(100%, 28rem);
text-align: center;
padding: 2.25rem 1.75rem 2rem;
border-radius: 1.25rem;
border: 1px solid
color-mix(in srgb, var(--color-primary) 28%, var(--border-subtle));
background: linear-gradient(
165deg,
color-mix(in srgb, var(--color-primary) 10%, var(--color-surface)),
var(--color-surface)
);
box-shadow:
0 20px 48px color-mix(in srgb, rgb(0, 0, 0) 18%, transparent),
inset 0 1px 0 color-mix(in srgb, var(--color-primary) 18%, transparent);
animation: error-screen-rise 0.45s ease-out both;
}
.error-screen-code {
margin: 0 0 0.65rem;
font-family: var(--font-pixel), "Courier New", monospace;
font-size: clamp(2.75rem, 9vw, 3.75rem);
font-weight: 700;
letter-spacing: 0.06em;
line-height: 1;
color: var(--color-primary-readable, var(--color-primary));
text-shadow: 0 0 36px
color-mix(in srgb, var(--color-primary) 45%, transparent);
}
.error-screen-title {
margin: 0 0 0.4rem;
font-size: 1.4rem;
font-weight: 800;
letter-spacing: -0.02em;
color: var(--color-text);
}
.error-screen-subtitle {
margin: 0 0 0.85rem;
font-size: 1rem;
font-weight: 600;
color: var(--color-text);
opacity: 0.88;
}
.error-screen-body {
margin: 0 0 1.5rem;
font-size: 0.95rem;
line-height: 1.55;
color: var(--color-text-muted);
}
.error-screen-actions {
display: flex;
flex-wrap: wrap;
gap: 0.65rem;
justify-content: center;
}
.error-screen-actions .btn {
display: inline-flex;
align-items: center;
gap: 0.45rem;
}
.error-screen-btn-icon {
width: 1rem;
height: 1rem;
flex-shrink: 0;
}
.error-screen-footer {
margin-top: 1.25rem;
}
.error-screen-digest {
margin: 0;
font-size: 0.72rem;
color: var(--color-text-muted);
font-variant-numeric: tabular-nums;
word-break: break-all;
}
@media (prefers-reduced-motion: reduce) {
.error-screen-panel {
animation: none;
}
}
/* ── Premium effects ── */
@keyframes float {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-8px);
}
}
@keyframes shimmer-glow {
0% {
opacity: 0.4;
}
50% {
opacity: 1;
}
100% {
opacity: 0.4;
}
}
@keyframes gradient-shift {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
@keyframes fade-in-up {
from {
opacity: 0;
transform: translateY(16px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes scale-in {
from {
opacity: 0;
transform: scale(0.95);
}
to {
opacity: 1;
transform: scale(1);
}
}
@keyframes pulse-glow {
0%,
100% {
box-shadow: 0 0 8px
color-mix(in srgb, var(--color-primary) 25%, transparent);
}
50% {
box-shadow: 0 0 24px
color-mix(in srgb, var(--color-primary) 45%, transparent);
}
}
.animate-float {
animation: float 4s ease-in-out infinite;
}
.animate-shimmer {
animation: shimmer-glow 2.5s ease-in-out infinite;
}
.animate-gradient {
background-size: 200% 200%;
animation: gradient-shift 8s ease infinite;
}
.animate-fade-in-up {
animation: fade-in-up 0.6s ease-out both;
}
.animate-scale-in {
animation: scale-in 0.4s ease-out both;
}
.animate-pulse-glow {
animation: pulse-glow 2s ease-in-out infinite;
}
.animate-shake {
animation: shake 0.45s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
}
@keyframes shake {
10%,
90% {
transform: translateX(-2px);
}
20%,
80% {
transform: translateX(4px);
}
30%,
50%,
70% {
transform: translateX(-6px);
}
40%,
60% {
transform: translateX(6px);
}
}
/* Glass morphism */
.glass {
background: color-mix(in srgb, var(--color-surface) 70%, transparent);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border: 1px solid color-mix(in srgb, var(--color-text-muted) 10%, transparent);
}
.glass-strong {
background: color-mix(in srgb, var(--color-surface) 85%, transparent);
backdrop-filter: blur(32px);
-webkit-backdrop-filter: blur(32px);
border: 1px solid color-mix(in srgb, var(--color-text-muted) 12%, transparent);
}
/* Premium card with depth */
.card-premium {
background: var(--color-surface);
border: 1px solid color-mix(in srgb, var(--color-text-muted) 10%, transparent);
border-radius: var(--radius-lg);
box-shadow:
0 1px 3px rgba(0, 0, 0, 0.04),
0 4px 12px rgba(0, 0, 0, 0.04),
0 12px 32px rgba(0, 0, 0, 0.04);
transition:
transform 0.25s ease,
box-shadow 0.25s ease;
}
.card-premium:hover {
transform: translateY(-3px);
box-shadow:
0 1px 3px rgba(0, 0, 0, 0.04),
0 6px 16px rgba(0, 0, 0, 0.06),
0 16px 40px rgba(0, 0, 0, 0.08);
}
/* Gradient border wrapper */
.gradient-border {
position: relative;
border-radius: var(--radius-lg);
background: linear-gradient(
135deg,
var(--color-primary),
color-mix(in srgb, var(--color-primary) 50%, var(--color-accent))
);
padding: 1px;
}
.gradient-border > * {
border-radius: calc(var(--radius-lg) - 1px);
}
/* Input focus glow */
.input-glow:focus {
outline: none;
border-color: var(--color-primary);
box-shadow:
0 0 0 3px color-mix(in srgb, var(--color-primary) 15%, transparent),
0 0 20px color-mix(in srgb, var(--color-primary) 10%, transparent);
}
.input-glow {
transition:
border-color 0.25s ease,
box-shadow 0.25s ease;
}
/* Typing cursor blink */
@keyframes blink {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0;
}
}
.typing-cursor::after {
content: "|";
animation: blink 0.8s step-end infinite;
margin-left: 2px;
font-weight: 300;
color: var(--color-primary);
}
/* Number count-up */
@keyframes count-up {
from {
opacity: 0;
transform: translateY(12px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.animate-count {
animation: count-up 0.6s ease-out both;
}
/* Premium button shine */
.btn-shine {
position: relative;
overflow: hidden;
}
.btn-shine::after {
content: "";
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: linear-gradient(
transparent 0%,
transparent 35%,
color-mix(in srgb, white 8%, transparent) 50%,
transparent 65%,
transparent 100%
);
transform: rotate(25deg);
transition: all 0.5s ease;
pointer-events: none;
}
.btn-shine:hover::after {
left: 100%;
}
/* Staggered children animation */
.stagger-children > * {
animation: fade-in-up 0.5s ease-out both;
}
.stagger-children > *:nth-child(1) {
animation-delay: 0.05s;
}
.stagger-children > *:nth-child(2) {
animation-delay: 0.1s;
}
.stagger-children > *:nth-child(3) {
animation-delay: 0.15s;
}
.stagger-children > *:nth-child(4) {
animation-delay: 0.2s;
}
.stagger-children > *:nth-child(5) {
animation-delay: 0.25s;
}
.stagger-children > *:nth-child(6) {
animation-delay: 0.3s;
}
.stagger-children > *:nth-child(7) {
animation-delay: 0.35s;
}
.stagger-children > *:nth-child(8) {
animation-delay: 0.4s;
}