Refine login layout with left earth stage and natural sunlight.

Move the globe beside the form, drop the orbit ring, and soften a blue atmospheric limb that fades into space.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-08-04 09:08:44 +08:00
parent 2d92dde8e5
commit 306f90a21c
2 changed files with 180 additions and 76 deletions

View file

@ -6761,13 +6761,14 @@ pre {
--login-field: rgba(255, 255, 255, 0.08);
--login-field-border: rgba(255, 255, 255, 0.14);
--login-danger: #fda29b;
--login-rail-w: clamp(360px, 30vw, 420px);
position: relative;
isolation: isolate;
min-height: 100vh;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
display: grid;
grid-template-columns: minmax(0, 1fr) var(--login-rail-w);
align-items: stretch;
background: #00050a;
font-family: "IBM Plex Sans", "Segoe UI", sans-serif;
color: var(--login-ink);
@ -6779,10 +6780,10 @@ pre {
z-index: 1;
display: flex;
align-items: center;
/* Center earth within the left stage (not under the form rail). */
justify-content: center;
background:
linear-gradient(rgba(0, 0, 0, 0.58), rgba(0, 0, 0, 0.42)),
url("/login-space.webp") center / cover no-repeat;
padding: 3vh calc(var(--login-rail-w) + 3vw) 3vh 5vw;
background: url("/login-space.webp") center / cover no-repeat;
}
.login-page__space::before {
@ -6792,44 +6793,105 @@ pre {
z-index: 2;
pointer-events: none;
background:
linear-gradient(transparent 0%, rgba(0, 0, 0, 0.32) 100%),
linear-gradient(transparent 50%, rgba(0, 0, 0, 0.68) 100%);
linear-gradient(
90deg,
transparent 0%,
transparent 52%,
rgba(0, 5, 12, 0.28) 70%,
rgba(0, 5, 12, 0.68) 88%,
rgba(0, 5, 12, 0.88) 100%
),
linear-gradient(180deg, rgba(0, 0, 0, 0.1) 0%, transparent 30%, transparent 72%, rgba(0, 0, 0, 0.38) 100%);
}
/* Distant sun — upper-left, feeds the lit limb. */
.login-page__sun {
position: absolute;
z-index: 0;
top: -2%;
left: -4%;
width: min(520px, 42vw);
height: min(520px, 42vw);
border-radius: 50%;
pointer-events: none;
background: radial-gradient(
circle at 55% 55%,
rgba(160, 205, 255, 0.26) 0%,
rgba(90, 150, 240, 0.12) 32%,
rgba(50, 110, 210, 0.04) 55%,
transparent 72%
);
filter: blur(8px);
}
.login-planet {
position: absolute;
position: relative;
z-index: 1;
width: 520px;
height: 520px;
width: min(500px, 38vw, 62vmin);
height: min(500px, 38vw, 62vmin);
border-radius: 50%;
transform: scale(2.5) translateY(38%) rotate(12.2deg);
transform: rotate(5deg);
animation: login-planet-enter 1.8s cubic-bezier(0.76, -0.46, 0.37, 0.99) both;
}
.login-planet__railway {
/* Soft blue atmosphere outside the clipped ball — fades into space. */
.login-planet::after {
content: "";
position: absolute;
top: -40px;
left: -40px;
width: calc(100% + 80px);
height: calc(100% + 80px);
z-index: 0;
inset: -10%;
border-radius: 50%;
border: 0.5px dashed rgba(255, 255, 255, 0.48);
animation: login-railway-rotate 40s linear infinite;
pointer-events: none;
background: radial-gradient(
120% 105% at 28% 24%,
transparent 48%,
rgba(40, 100, 210, 0.38) 64%,
rgba(55, 125, 230, 0.18) 74%,
transparent 86%
);
filter: blur(10px);
}
.login-planet__earth {
position: relative;
z-index: 1;
width: 100%;
height: 100%;
border-radius: 50%;
overflow: hidden;
/* Feather the limb into space — no hard circular cut. */
-webkit-mask-image: radial-gradient(circle at 50% 50%, #000 86%, transparent 100%);
mask-image: radial-gradient(circle at 50% 50%, #000 86%, transparent 100%);
box-shadow:
0 0 8px rgba(150, 186, 255, 0.48),
0 0 60px 12px rgba(150, 186, 255, 0.32);
-16px -18px 40px 8px rgba(60, 130, 230, 0.35),
-6px -8px 16px 2px rgba(80, 150, 240, 0.22);
transform-origin: center center;
}
/* Surface light falloff: bright TL → soft mid → deeper BR. */
.login-planet__earth::before {
content: "";
position: absolute;
z-index: 1;
inset: 0;
border-radius: 50%;
pointer-events: none;
background: linear-gradient(
148deg,
rgba(120, 175, 255, 0.22) 0%,
rgba(70, 130, 220, 0.1) 18%,
rgba(40, 90, 180, 0.04) 34%,
transparent 48%,
rgba(0, 12, 36, 0.16) 68%,
rgba(0, 8, 24, 0.36) 86%,
rgba(0, 4, 16, 0.5) 100%
);
}
/*
* Blue atmosphere crescent on the sun limb + soft edge wash that
* dissolves with the feathered mask.
*/
.login-planet__earth::after {
content: "";
position: absolute;
@ -6837,51 +6899,71 @@ pre {
inset: 0;
border-radius: 50%;
pointer-events: none;
background:
radial-gradient(
130% 100% at 6% 10%,
rgba(90, 160, 255, 0.62) 0%,
rgba(50, 120, 230, 0.36) 24%,
rgba(30, 90, 200, 0.12) 46%,
transparent 64%
),
radial-gradient(
circle at 50% 50%,
transparent 72%,
rgba(40, 105, 215, 0.16) 86%,
rgba(55, 130, 235, 0.32) 93%,
rgba(70, 150, 245, 0.12) 98%,
transparent 100%
);
box-shadow:
inset 0 0 8px 4px rgba(59, 104, 196, 0.98),
inset -24px 0 12px 2px rgba(59, 104, 196, 0.08),
inset 0 0 48px 48px rgba(59, 104, 196, 0.28),
inset -48px 0 24px 48px rgba(59, 104, 196, 0.08);
animation: login-earth-inner 1.8s ease-in-out 0.9s both;
inset 28px 32px 36px 4px rgba(70, 140, 235, 0.16),
inset -22px -26px 48px 12px rgba(0, 6, 20, 0.28);
animation: login-earth-inner 2.2s ease-in-out 0.7s both;
}
.login-planet__textures {
position: absolute;
top: 0;
left: 0;
width: 200%;
inset: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 18, 77, 0.18);
background-color: rgba(8, 28, 72, 0.2);
background-image: url("/login-earth-night.webp");
background-size: 50% 100%;
background-repeat: repeat-x;
filter: brightness(2.4) contrast(1.2);
animation: login-earth-spin 60s linear infinite;
will-change: transform;
transform: translate3d(0, 0, 0);
background-size: 200%;
/* Softer map — less crunchy, blends into the limb fade. */
filter: brightness(2.45) contrast(1.02) saturate(1.08);
animation: login-earth-spin 80s linear infinite;
will-change: background-position;
}
.login-page__content {
.login-page__rail {
position: relative;
z-index: 3;
width: min(400px, calc(100% - 40px));
padding: 24px 0;
grid-column: 2;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
min-width: 0;
padding: 48px clamp(32px, 3.5vw, 52px) 48px 8px;
}
.login-card {
width: 100%;
max-width: 340px;
display: flex;
flex-direction: column;
gap: 14px;
padding: 20px 20px 22px;
border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.08);
background: rgba(8, 16, 32, 0.22);
backdrop-filter: blur(8px) saturate(1.08);
-webkit-backdrop-filter: blur(8px) saturate(1.08);
gap: 15px;
padding: 26px 24px 28px;
border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(8, 16, 32, 0.58);
backdrop-filter: blur(16px) saturate(1.12);
-webkit-backdrop-filter: blur(16px) saturate(1.12);
box-shadow:
0 8px 28px rgba(0, 0, 0, 0.18),
inset 0 1px 0 rgba(255, 255, 255, 0.05);
0 18px 48px rgba(0, 0, 0, 0.32),
0 0 0 1px rgba(120, 170, 255, 0.07),
inset 0 1px 0 rgba(255, 255, 255, 0.07);
animation: login-card-in 520ms cubic-bezier(0.22, 1, 0.36, 1) both;
}
@ -7071,42 +7153,30 @@ pre {
@keyframes login-planet-enter {
0% {
transform: scale(1) translateY(0) rotate(-12.2deg);
transform: scale(0.92) rotate(-5deg);
opacity: 0.65;
}
}
@keyframes login-railway-rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
100% {
transform: rotate(5deg);
opacity: 1;
}
}
@keyframes login-earth-spin {
from {
transform: translate3d(0, 0, 0);
background-position: calc(120% + 120px) 0;
}
to {
transform: translate3d(-50%, 0, 0);
background-position: calc(-80% + 120px) 0;
}
}
@keyframes login-earth-inner {
0% {
box-shadow:
inset 0 0 8px 4px rgba(59, 104, 196, 0.98),
inset -24px 0 12px 2px rgba(59, 104, 196, 0.08),
inset 0 0 48px 48px rgba(59, 104, 196, 0.28),
inset -48px 0 24px 48px rgba(59, 104, 196, 0.08);
opacity: 0.55;
}
100% {
box-shadow:
inset 0 0 8px 4px rgba(59, 104, 196, 0.98),
inset 24px 0 12px 2px rgba(59, 104, 196, 0.58),
inset 0 8px 48px 48px rgba(59, 104, 196, 0.28),
inset 48px 0 24px 48px rgba(59, 104, 196, 0.28);
opacity: 1;
}
}
@ -7146,7 +7216,7 @@ pre {
}
@media (prefers-reduced-motion: reduce) {
/* Keep ambient earth / orbit motion; only drop entrance flourishes. */
/* Keep ambient earth spin; only drop entrance flourishes. */
.login-planet,
.login-planet__earth::after,
.login-card,
@ -7156,7 +7226,7 @@ pre {
}
.login-planet {
transform: scale(2.5) translateY(38%) rotate(12.2deg);
transform: rotate(5deg);
}
.login-card__submit:hover:not(:disabled) {
@ -7164,13 +7234,47 @@ pre {
}
}
@media (max-width: 480px) {
@media (max-width: 1200px) {
.login-page {
--login-rail-w: clamp(340px, 34vw, 400px);
}
.login-planet {
transform: scale(1.5) translateY(28%) rotate(12.2deg);
width: min(440px, 40vw, 58vmin);
height: min(440px, 40vw, 58vmin);
}
}
@media (max-width: 820px) {
.login-page {
grid-template-columns: 1fr;
}
.login-page__space {
justify-content: center;
padding: 0;
}
.login-page__space::before {
background:
linear-gradient(180deg, rgba(0, 0, 0, 0.18) 0%, transparent 30%, transparent 48%, rgba(0, 0, 0, 0.72) 100%);
}
.login-planet {
width: min(420px, 78vmin);
height: min(420px, 78vmin);
opacity: 0.9;
}
.login-page__rail {
grid-column: 1;
min-height: 100vh;
padding: 28px 18px 36px;
}
.login-card {
padding: 18px 16px 20px;
max-width: 380px;
padding: 20px 18px 22px;
}
.login-card__brand,

View file

@ -1,18 +1,18 @@
import type { ReactNode } from "react";
/** Auth shell modeled after CuteCloud login: space BG + rotating night-earth + centered form. */
/** Auth shell: night-earth stage on the left, form rail on the right. */
export function LoginShell({ children }: { children: ReactNode }) {
return (
<div className="login-page">
<div className="login-page__space" aria-hidden="true">
<div className="login-page__sun" />
<div className="login-planet">
<div className="login-planet__railway" />
<div className="login-planet__earth">
<div className="login-planet__textures" />
</div>
</div>
</div>
<div className="login-page__content">{children}</div>
<aside className="login-page__rail">{children}</aside>
</div>
);
}