diff --git a/src/login/glass/GlassAmbientBackground.tsx b/src/login/glass/GlassAmbientBackground.tsx index 351fdeb..dfa0381 100644 --- a/src/login/glass/GlassAmbientBackground.tsx +++ b/src/login/glass/GlassAmbientBackground.tsx @@ -10,60 +10,86 @@ export function GlassAmbientBackground({ children }: { children: React.ReactNode <>
{children} > diff --git a/src/login/glass/glass-theme.css b/src/login/glass/glass-theme.css index 7cb1351..8bbb6cd 100644 --- a/src/login/glass/glass-theme.css +++ b/src/login/glass/glass-theme.css @@ -24,11 +24,16 @@ --glass-shadow: 0 14px 44px hsla(220 40% 16% / 0.18); --glass-shadow-elevated: 0 24px 64px hsla(220 40% 12% / 0.24); - /* Ambient background blobs — saturated and fairly opaque so the glass has something to refract */ - --glass-ambient-1: hsla(250 85% 62% / 0.55); - --glass-ambient-2: hsla(320 80% 58% / 0.5); - --glass-ambient-3: hsla(190 90% 52% / 0.48); - --glass-ambient-4: hsla(40 95% 58% / 0.42); + /* + * Soft ambient background palette. + * Pastel, heavily blurred blobs for a calm liquid-glass feeling. + */ + --glass-ambient-1: hsla(250 90% 70% / 0.45); + --glass-ambient-2: hsla(320 85% 68% / 0.4); + --glass-ambient-3: hsla(190 90% 62% / 0.38); + --glass-ambient-4: hsla(40 95% 65% / 0.34); + --glass-ambient-5: hsla(140 80% 60% / 0.26); + --glass-ambient-6: hsla(10 90% 66% / 0.3); /* Text stability on busy backgrounds */ --glass-text-shadow: 0 1px 2px hsla(0 0% 0% / 0.1); @@ -45,11 +50,13 @@ --glass-shadow: 0 14px 44px hsla(0 0% 0% / 0.45); --glass-shadow-elevated: 0 24px 64px hsla(0 0% 0% / 0.55); - /* Dark-mode blobs: still vivid but not overwhelming */ - --glass-ambient-1: hsla(250 85% 58% / 0.4); - --glass-ambient-2: hsla(320 80% 55% / 0.36); - --glass-ambient-3: hsla(190 90% 50% / 0.36); - --glass-ambient-4: hsla(40 95% 55% / 0.3); + /* Dark-mode blobs: vivid enough to refract, soft enough to not distract */ + --glass-ambient-1: hsla(250 90% 58% / 0.38); + --glass-ambient-2: hsla(320 85% 56% / 0.34); + --glass-ambient-3: hsla(190 90% 54% / 0.32); + --glass-ambient-4: hsla(40 95% 58% / 0.28); + --glass-ambient-5: hsla(140 80% 50% / 0.22); + --glass-ambient-6: hsla(10 90% 58% / 0.26); --glass-text-shadow: 0 1px 3px hsla(0 0% 0% / 0.4); } @@ -126,6 +133,37 @@ ); } +/* Dark mode card sheen — cool tinted gradient instead of a white glare */ +@media (prefers-color-scheme: dark) { + .glass { + background: linear-gradient( + 145deg, + hsla(220 30% 26% / 0.35) 0%, + hsla(220 20% 12% / 0.12) 55%, + hsla(220 30% 22% / 0.28) 100% + ), + var(--glass-bg); + box-shadow: + inset 0 1px 0 0 var(--glass-border-highlight), + inset 0 0 0 1px hsla(0 0% 100% / 0.05), + var(--glass-shadow); + } + + .glass-solid { + background: linear-gradient( + 145deg, + hsla(220 30% 22% / 0.3) 0%, + hsla(220 20% 10% / 0.08) 55%, + hsla(220 30% 18% / 0.22) 100% + ), + var(--glass-bg-solid); + box-shadow: + inset 0 1px 0 0 var(--glass-border-highlight), + inset 0 0 0 1px hsla(0 0% 100% / 0.05), + var(--glass-shadow); + } +} + /* Fallback for browsers without backdrop-filter support */ @supports not (backdrop-filter: blur(12px)) { .glass { @@ -140,14 +178,18 @@ } } -/* Ambient background blobs — keep some definition so the glass can refract them */ +/* + * Ambient background blobs. + * Huge, very soft, slowly drifting color clouds. + * The heavy blur makes them feel like liquid light. + */ .glass-ambient-blob { position: absolute; border-radius: 50%; - filter: blur(44px); + filter: blur(90px); opacity: 0.85; will-change: transform, opacity; - animation: glass-float 20s ease-in-out infinite alternate; + animation: glass-float 28s ease-in-out infinite alternate; } @media (prefers-reduced-motion: reduce) { @@ -159,47 +201,68 @@ @keyframes glass-float { 0% { - transform: translate3d(0, 0, 0) scale(1); + transform: translate3d(0, 0, 0) scale(1) rotate(0deg); } 100% { - transform: translate3d(30px, -40px, 0) scale(1.15); + transform: translate3d(60px, -70px, 0) scale(1.22) rotate(12deg); } } -/* Extra mesh layer behind the card: sharper color bands for stronger refraction */ -.glass-ambient-mesh { +/* + * Aurora-like flowing gradient bands. + * Long, elliptical, heavily blurred shapes that drift across the screen. + */ +.glass-ambient-aurora { position: absolute; - inset: 0; + border-radius: 50%; + filter: blur(110px); opacity: 0.7; - background: radial-gradient( - circle at 20% 30%, - var(--glass-ambient-1) 0%, - transparent 45% - ), - radial-gradient(circle at 80% 20%, var(--glass-ambient-2) 0%, transparent 40%), - radial-gradient(circle at 60% 80%, var(--glass-ambient-3) 0%, transparent 45%), - radial-gradient(circle at 30% 75%, var(--glass-ambient-4) 0%, transparent 40%); - filter: blur(28px); will-change: transform; - animation: glass-mesh-drift 30s ease-in-out infinite alternate; - pointer-events: none; + animation: glass-aurora-drift 36s ease-in-out infinite alternate; } @media (prefers-reduced-motion: reduce) { - .glass-ambient-mesh { + .glass-ambient-aurora { animation: none; opacity: 0.5; } } -@keyframes glass-mesh-drift { +@keyframes glass-aurora-drift { 0% { - transform: scale(1) translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) scale(1) rotate(-6deg); } 100% { - transform: scale(1.08) translate3d(-20px, 10px, 0); + transform: translate3d(-80px, 40px, 0) scale(1.18) rotate(8deg); + } +} + +/* + * Subtle vignette overlay. + * Darkens the edges so the eye is drawn to the glass card in the center. + */ +.glass-vignette { + position: absolute; + inset: 0; + pointer-events: none; + background: radial-gradient( + ellipse at center, + transparent 0%, + transparent 50%, + hsla(0 0% 0% / 0.06) 100% + ); +} + +@media (prefers-color-scheme: dark) { + .glass-vignette { + background: radial-gradient( + ellipse at center, + transparent 0%, + transparent 45%, + hsla(0 0% 0% / 0.35) 100% + ); } } diff --git a/src/login/tailwind.css b/src/login/tailwind.css index 600932c..bd8e46f 100644 --- a/src/login/tailwind.css +++ b/src/login/tailwind.css @@ -31,6 +31,14 @@ --color-glass-border: var(--glass-border); --color-glass-shadow: var(--glass-shadow); + /* Alert/status tokens */ + --color-info: var(--info); + --color-info-foreground: var(--info-foreground); + --color-success: var(--success); + --color-success-foreground: var(--success-foreground); + --color-warning: var(--warning); + --color-warning-foreground: var(--warning-foreground); + --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px); --radius-lg: var(--radius); @@ -55,11 +63,20 @@ --accent-foreground: hsl(222.2 47.4% 11.2%); --destructive: hsl(0 84.2% 60.2%); --destructive-foreground: hsl(210 40% 98%); - --border: hsl(214.3 31.8% 91.4%); - --input: hsl(214.3 31.8% 91.4%); + /* Darker border for better visibility on light glass backgrounds */ + --border: hsl(214.3 25% 78%); + --input: hsl(214.3 25% 78%); --ring: hsl(222.2 84% 4.9%); --radius: 0.625rem; + /* Status colors */ + --info: hsl(210 80% 52%); + --info-foreground: hsl(210 40% 98%); + --success: hsl(142 76% 36%); + --success-foreground: hsl(210 40% 98%); + --warning: hsl(38 92% 50%); + --warning-foreground: hsl(210 40% 98%); + /* Page gradient visible behind the glass card */ --page-bg-gradient: linear-gradient( 135deg, @@ -85,12 +102,20 @@ --muted-foreground: hsl(215 20.2% 65.1%); --accent: hsl(217.2 32.6% 17.5%); --accent-foreground: hsl(210 40% 98%); - --destructive: hsl(0 62.8% 30.6%); + --destructive: hsl(0 72% 58%); --destructive-foreground: hsl(210 40% 98%); - --border: hsl(217.2 32.6% 17.5%); - --input: hsl(217.2 32.6% 17.5%); + /* Lighter border so dividers remain visible on dark glass backgrounds */ + --border: hsl(217.2 25% 34%); + --input: hsl(217.2 25% 34%); --ring: hsl(212.7 26.8% 83.9%); + --info: hsl(210 80% 62%); + --info-foreground: hsl(222 47% 6%); + --success: hsl(142 70% 50%); + --success-foreground: hsl(222 47% 6%); + --warning: hsl(38 92% 58%); + --warning-foreground: hsl(222 47% 6%); + --page-bg-gradient: linear-gradient( 135deg, hsl(222 47% 6%) 0%, @@ -371,24 +396,41 @@ #kc-current-locale-link { display: inline-flex; align-items: center; - gap: 0.25rem; + gap: 0.35rem; height: 2rem; border-radius: 9999px; - border: 1px solid var(--color-border); - background: var(--color-background); - padding: 0 0.5rem; + border: 1px solid var(--glass-border); + background: var(--glass-bg); + box-shadow: + inset 0 1px 0 0 var(--glass-border-highlight), + 0 1px 2px hsla(0 0% 0% / 0.05); + padding: 0 0.65rem; font-size: 0.75rem; font-weight: 500; - color: var(--color-muted-foreground); + color: var(--color-foreground); cursor: pointer; transition: border-color 150ms ease, - background-color 150ms ease; + background-color 150ms ease, + box-shadow 150ms ease; + } + + #kc-current-locale-link::after { + content: ""; + width: 0.4rem; + height: 0.4rem; + border: solid currentColor; + border-width: 0 1.5px 1.5px 0; + transform: rotate(45deg) translateY(-2px); + opacity: 0.7; } #kc-current-locale-link:hover, #kc-current-locale-link[aria-expanded="true"] { - background: var(--color-muted); + background: var(--glass-bg-solid); + box-shadow: + inset 0 1px 0 0 var(--glass-border-highlight), + 0 2px 4px hsla(0 0% 0% / 0.08); } .kcLocaleListClass { @@ -450,10 +492,86 @@ .alert-error.kcAlertClass, .pf-m-danger.kcAlertClass { border-color: var(--color-destructive); - background: color-mix(in oklab, var(--color-destructive) 10%, transparent); + background: color-mix(in oklab, var(--color-destructive) 12%, transparent); color: var(--color-destructive); } + .pf-m-info.kcAlertClass { + border-color: var(--color-info); + background: color-mix(in oklab, var(--color-info) 12%, transparent); + color: var(--color-info); + } + + .pf-m-success.kcAlertClass { + border-color: var(--color-success); + background: color-mix(in oklab, var(--color-success) 12%, transparent); + color: var(--color-success); + } + + .pf-m-warning.kcAlertClass { + border-color: var(--color-warning); + background: color-mix(in oklab, var(--color-warning) 12%, transparent); + color: var(--color-warning); + } + + /* Info/error page message boxes. + Only the .instruction paragraph is highlighted; action links stay plain. */ + #kc-info-message, + #kc-error-message { + display: grid; + gap: 0.875rem; + } + + #kc-info-message .instruction, + #kc-error-message .instruction { + margin: 0; + border-radius: var(--radius-md); + border: 1px solid var(--color-border); + border-left-width: 4px; + padding: 0.875rem 1rem; + font-size: 0.875rem; + line-height: 1.5; + } + + #kc-info-message .instruction { + border-color: var(--color-info); + border-left-color: var(--color-info); + background: color-mix(in oklab, var(--color-info) 10%, transparent); + color: var(--color-info); + } + + #kc-error-message .instruction { + border-color: var(--color-destructive); + border-left-color: var(--color-destructive); + background: color-mix(in oklab, var(--color-destructive) 14%, transparent); + color: var(--color-destructive); + font-weight: 500; + } + + @media (prefers-color-scheme: dark) { + #kc-error-message .instruction { + background: color-mix(in oklab, var(--color-destructive) 24%, transparent); + color: var(--color-destructive-foreground); + } + } + + #kc-info-message p:not(.instruction), + #kc-error-message p:not(.instruction) { + margin: 0; + } + + #kc-info-message a, + #kc-error-message a { + color: var(--color-primary); + text-decoration: none; + font-weight: 500; + } + + #kc-info-message a:hover, + #kc-error-message a:hover { + text-decoration: underline; + } + .kcFormSocialAccountListButtonClass { display: flex; align-items: center; @@ -818,7 +936,7 @@ content: ""; flex: 1; height: 1px; - background: var(--color-border); + background: color-mix(in oklab, var(--color-border) 70%, var(--color-foreground)); } .kcCommonLogoIdP { @@ -864,17 +982,7 @@ background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20fill%3D%22%23FC3F1D%22%20d%3D%22M16.376%2012.644L21%202h-3.842l-4.624%2010.644h3.842zM13.915%2024v-3.733c0-2.822-.352-3.64-1.407-5.988L6.933%202H3l7.124%2015.709V24h3.79z%22%2F%3E%3C%2Fsvg%3E"); } - #social-yandex.kcFormSocialAccountListButtonClass::before { - content: ""; - display: inline-block; - width: 18px; - height: 18px; - flex: 0 0 18px; - background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20fill%3D%22%23FC3F1D%22%20d%3D%22M16.376%2012.644L21%202h-3.842l-4.624%2010.644h3.842zM13.915%2024v-3.733c0-2.822-.352-3.64-1.407-5.988L6.933%202H3l7.124%2015.709V24h3.79z%22%2F%3E%3C%2Fsvg%3E"); - background-size: contain; - background-repeat: no-repeat; - background-position: center; - } + /* Yandex icon is rendered by .kcCommonLogoIdP::before above; no extra pseudo-element needed. */ #social-vk .kcCommonLogoIdP::before, #social-vkontakte .kcCommonLogoIdP::before {