mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-19 15:06:20 +00:00
+62
-2
@@ -109,5 +109,65 @@
|
||||
"groupforum.message.hide": "Hide message",
|
||||
"group.forum.enable.caption": "Enable / Disable group forum",
|
||||
"group.forum.enable.help": "If you disable the group forum, all posts will also be deleted!",
|
||||
"groupforum.view.no_threads": "There are currently no active threads"
|
||||
}
|
||||
"groupforum.view.no_threads": "There are currently no active threads",
|
||||
"login.username": "Name of your Habbo",
|
||||
"login.forgot_password": "Forgotten your password?",
|
||||
|
||||
"nitro.login.firsttime.title": "First time here?",
|
||||
"nitro.login.firsttime.text": "Don't have a Habbo yet?",
|
||||
"nitro.login.firsttime.link": "You can create one here",
|
||||
"nitro.login.card.title": "What's your Habbo called?",
|
||||
|
||||
"nitro.login.server.offline.short": "The gameserver isn't running right now. Please try again in a moment.",
|
||||
"nitro.login.server.offline.long": "The gameserver isn't running right now, so new accounts can't be created. Please try again in a moment.",
|
||||
"nitro.login.server.checking": "Checking…",
|
||||
"nitro.login.server.retry": "Retry",
|
||||
|
||||
"nitro.login.register.title": "Habbo Details",
|
||||
"nitro.login.register.next": "Next",
|
||||
"nitro.login.register.finish": "Finish",
|
||||
"nitro.login.register.creating": "Creating…",
|
||||
|
||||
"nitro.login.register.intro.credentials": "Let's create your account. Enter your email and pick a password — we'll check that email isn't already in use.",
|
||||
"nitro.login.register.intro.avatar": "Now it's time to make your own Habbo character! To make your own Habbo, please start by choosing your Habbo Name.",
|
||||
"nitro.login.register.intro.room": "Last step — pick a starter room, or skip and create your own later.",
|
||||
|
||||
"nitro.login.register.confirm.label": "Confirm password",
|
||||
"nitro.login.register.username.placeholder": "HabboName",
|
||||
|
||||
"nitro.login.register.hotlooks.count": "%count% looks available",
|
||||
"nitro.login.register.hotlooks.none": "No hot looks loaded",
|
||||
|
||||
"nitro.login.register.room.skip.title": "I'm okay — I'll create my own rooms",
|
||||
"nitro.login.register.room.skip.description": "Skip for now and start with an empty hotel inventory.",
|
||||
"nitro.login.register.room.loading": "Loading rooms…",
|
||||
"nitro.login.register.room.error": "Could not load room options. You can still skip this step.",
|
||||
|
||||
"nitro.login.register.success": "Welcome aboard, %username%! Your account is ready — log in below with the password you just chose.",
|
||||
|
||||
"nitro.login.forgot.title": "Reset password",
|
||||
"nitro.login.forgot.email.label": "Email address",
|
||||
"nitro.login.forgot.send": "Send email",
|
||||
"nitro.login.forgot.success": "Email sent! If an account matches that address you'll find a reset link in your inbox shortly (check spam if it doesn't show up within a minute).",
|
||||
|
||||
"nitro.login.error.missing_credentials": "Please enter both your Habbo name and password.",
|
||||
"nitro.login.error.invalid_credentials": "Invalid Habbo name or password.",
|
||||
"nitro.login.error.too_many_attempts": "Too many attempts. Try again in %seconds%s.",
|
||||
"nitro.login.error.turnstile": "Please complete the security check.",
|
||||
"nitro.login.error.server_offline": "The gameserver is not running. Please try again later.",
|
||||
"nitro.login.error.login_unreachable": "Unable to reach the login service. Please try again.",
|
||||
"nitro.login.error.register_failed": "Unable to create your account.",
|
||||
"nitro.login.error.register_unreachable": "Unable to reach the registration service.",
|
||||
"nitro.login.error.forgot_failed": "Unable to send a reset email right now.",
|
||||
"nitro.login.error.forgot_unreachable": "Unable to reach the password reset service.",
|
||||
"nitro.login.error.missing_fields": "Please fill in every field.",
|
||||
"nitro.login.error.invalid_email": "Please enter a valid email address.",
|
||||
"nitro.login.error.password_too_short": "Your password must be at least 8 characters.",
|
||||
"nitro.login.error.password_mismatch": "Passwords do not match.",
|
||||
"nitro.login.error.email_taken": "This email is already in use.",
|
||||
"nitro.login.error.missing_username": "Please choose a Habbo name.",
|
||||
"nitro.login.error.username_length": "Habbo name must be 3–16 characters.",
|
||||
"nitro.login.error.username_taken": "This Habbo name is already taken.",
|
||||
"nitro.login.error.missing_email": "Please enter your email address."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
[
|
||||
{
|
||||
"_gender": "m",
|
||||
"_figure": "hr-155-40.hd-180-10.ch-255-1408.lg-280-64.sh-290-64.ha-1003-64",
|
||||
"_hash": "b5d1a24d16c9d516b3d793c66d152b77"
|
||||
},
|
||||
{
|
||||
"_gender": "f",
|
||||
"_figure": "hr-515-34.hd-629-8.ch-665-1408.lg-715-1320.sh-740-1408.he-1608",
|
||||
"_hash": "694573ec86cf5346f1c88b1017f069f8"
|
||||
},
|
||||
{
|
||||
"_gender": "f",
|
||||
"_figure": "hr-890-36.hd-629-8.ch-685-71.lg-715-71.sh-3068-71-73.ha-1018.fa-1202-71.ca-1802",
|
||||
"_hash": "10b9a935209e6c213e54108474186dc8"
|
||||
},
|
||||
{
|
||||
"_gender": "m",
|
||||
"_figure": "hr-115-42.hd-209-1.ch-255-73.lg-3078-82.sh-300-64",
|
||||
"_hash": "1457ce2369b982bcce30e8307c005d98"
|
||||
},
|
||||
{
|
||||
"_gender": "m",
|
||||
"_figure": "hr-115-40.hd-190-14.ch-235-1408.lg-280-1408.sh-908-1408.he-1608",
|
||||
"_hash": "d35b7492386963d7612341b222f7f5d9"
|
||||
},
|
||||
{
|
||||
"_gender": "m",
|
||||
"_figure": "hr-115-31.hd-180-14.ch-210-64.lg-3023-91.sh-300-91",
|
||||
"_hash": "b49e529b7604fbd3596951bc69d6551b"
|
||||
},
|
||||
{
|
||||
"_gender": "m",
|
||||
"_figure": "hr-100.hd-180-1.ch-210-1408.lg-270-64.sh-300-64.ha-1002-64.cc-260-64",
|
||||
"_hash": "f052b0ccc54cfa933d473b433b154ef5"
|
||||
},
|
||||
{
|
||||
"_gender": "m",
|
||||
"_figure": "hr-125-34.hd-205-14.ch-235-1408.lg-285-81.sh-300-64.wa-3211-64-64",
|
||||
"_hash": "08c77292a4462c36f0393820d5753de3"
|
||||
},
|
||||
{
|
||||
"_gender": "f",
|
||||
"_figure": "hr-890-31.hd-600-1.ch-822-71.lg-715-74.he-1602-71",
|
||||
"_hash": "4102a76da4bca25d5125b75d9ea1ca14"
|
||||
},
|
||||
{
|
||||
"_gender": "f",
|
||||
"_figure": "hr-515-35.hd-628-14.ch-667.lg-696-73.he-1606-82.ca-1810.cp-3124-81",
|
||||
"_hash": "4987ff565ec8e6ecedb31b08c2b017a6"
|
||||
}
|
||||
]
|
||||
@@ -45,6 +45,11 @@
|
||||
"login.register.endpoint": "${api.url}/api/auth/register",
|
||||
"login.forgot.endpoint": "${api.url}/api/auth/forgot-password",
|
||||
"login.logout.endpoint": "${api.url}/api/auth/logout",
|
||||
"login.health.endpoint": "${api.url}/api/health",
|
||||
"login.check-email.endpoint": "${api.url}/api/auth/check-email",
|
||||
"login.check-username.endpoint": "${api.url}/api/auth/check-username",
|
||||
"login.room_templates.endpoint": "${api.url}/api/auth/room-templates",
|
||||
"login.remember.endpoint": "${api.url}/api/auth/remember",
|
||||
"login.turnstile.enabled": false,
|
||||
"login.turnstile.sitekey": "",
|
||||
"avatar.mandatory.libraries": [
|
||||
+59
-9
@@ -35,7 +35,6 @@ export const App: FC<{}> = props =>
|
||||
setPrepareTrigger(prev => prev + 1);
|
||||
}, []);
|
||||
|
||||
// Listen for socket closed events (code 1000 "Bye" - server rejected SSO)
|
||||
useNitroEvent(NitroEventType.SOCKET_CLOSED, showSessionExpired);
|
||||
|
||||
useMessageEvent<LoadGameUrlEvent>(LoadGameUrlEvent, event =>
|
||||
@@ -57,26 +56,77 @@ export const App: FC<{}> = props =>
|
||||
{
|
||||
if(!window.NitroConfig) throw new Error('NitroConfig is not defined!');
|
||||
|
||||
const ssoTicket = window.NitroConfig['sso.ticket'];
|
||||
let ssoTicket = window.NitroConfig['sso.ticket'];
|
||||
let configInitError: unknown = null;
|
||||
|
||||
if(!ssoTicket || ssoTicket === '')
|
||||
{
|
||||
// Configuration is loaded lazily — fetch it up-front so the login
|
||||
// screen toggle and Turnstile keys are available before we decide.
|
||||
let configInitError: unknown = null;
|
||||
try { await GetConfiguration().init(); }
|
||||
catch(e) { configInitError = e; }
|
||||
|
||||
const rawLoginEnabled = GetConfiguration().getValue<unknown>('login.screen.enabled', false);
|
||||
const loginScreenEnabled = rawLoginEnabled === true || rawLoginEnabled === 'true' || rawLoginEnabled === 1;
|
||||
|
||||
if(configInitError)
|
||||
{
|
||||
NitroLogger.error('[LoginScreen] Failed to load renderer-config.json — cannot resolve login.screen.enabled', configInitError);
|
||||
}
|
||||
|
||||
if(!configInitError)
|
||||
{
|
||||
let storedRemember: string | null = null;
|
||||
try { storedRemember = window.localStorage.getItem('nitro.remember.token'); }
|
||||
catch {}
|
||||
|
||||
if(storedRemember)
|
||||
{
|
||||
const rememberUrlTemplate = GetConfiguration().getValue<string>('login.remember.endpoint', '/api/auth/remember');
|
||||
const rememberUrl = GetConfiguration().interpolate(rememberUrlTemplate);
|
||||
try
|
||||
{
|
||||
const response = await fetch(rememberUrl, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
'X-Requested-With': 'NitroRememberMe'
|
||||
},
|
||||
body: JSON.stringify({ rememberToken: storedRemember })
|
||||
});
|
||||
if(response.ok)
|
||||
{
|
||||
const payload = await response.json();
|
||||
const ticket = typeof payload.ssoTicket === 'string' ? payload.ssoTicket : '';
|
||||
if(ticket)
|
||||
{
|
||||
window.NitroConfig['sso.ticket'] = ticket;
|
||||
ssoTicket = ticket;
|
||||
try
|
||||
{
|
||||
if(typeof payload.rememberToken === 'string' && payload.rememberToken.length)
|
||||
window.localStorage.setItem('nitro.remember.token', payload.rememberToken);
|
||||
}
|
||||
catch {}
|
||||
}
|
||||
}
|
||||
else if(response.status === 401)
|
||||
{
|
||||
try { window.localStorage.removeItem('nitro.remember.token'); } catch {}
|
||||
}
|
||||
}
|
||||
catch {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!ssoTicket || ssoTicket === '')
|
||||
{
|
||||
const rawLoginEnabled = GetConfiguration().getValue<unknown>('login.screen.enabled', false);
|
||||
const loginScreenEnabled = rawLoginEnabled === true || rawLoginEnabled === 'true' || rawLoginEnabled === 1;
|
||||
|
||||
if(loginScreenEnabled)
|
||||
{
|
||||
try { await GetLocalizationManager().init(); }
|
||||
catch(localizationErr) { NitroLogger.error('[LoginScreen] Localization init failed', localizationErr); }
|
||||
|
||||
setIsReady(false);
|
||||
setShowLogin(true);
|
||||
return;
|
||||
@@ -110,7 +160,7 @@ export const App: FC<{}> = props =>
|
||||
eventMode: 'none',
|
||||
failIfMajorPerformanceCaveat: false,
|
||||
roundPixels: true,
|
||||
useBackBuffer // Keep disabled by default unless explicitly enabled in NitroConfig
|
||||
useBackBuffer
|
||||
});
|
||||
|
||||
await GetConfiguration().init();
|
||||
|
||||
+870
-119
File diff suppressed because it is too large
Load Diff
@@ -64,6 +64,9 @@ export const PurseView: FC<{}> = props => {
|
||||
|
||||
const logoutUrl = GetConfigurationValue<string>('login.logout.endpoint', '/api/auth/logout');
|
||||
const ssoTicket = (window.NitroConfig?.['sso.ticket'] as string) ?? '';
|
||||
let rememberToken = '';
|
||||
try { rememberToken = window.localStorage.getItem('nitro.remember.token') ?? ''; }
|
||||
catch { /* localStorage may be disabled */ }
|
||||
|
||||
try
|
||||
{
|
||||
@@ -76,11 +79,12 @@ export const PurseView: FC<{}> = props => {
|
||||
'Accept': 'application/json',
|
||||
'X-Requested-With': 'NitroPurseLogout'
|
||||
},
|
||||
body: JSON.stringify({ ssoTicket })
|
||||
body: JSON.stringify({ ssoTicket, rememberToken })
|
||||
});
|
||||
}
|
||||
catch { /* best-effort — proceed with local logout regardless */ }
|
||||
|
||||
try { window.localStorage.removeItem('nitro.remember.token'); } catch { /* noop */ }
|
||||
if(window.NitroConfig) window.NitroConfig['sso.ticket'] = '';
|
||||
window.location.reload();
|
||||
}, []);
|
||||
|
||||
+296
-18
@@ -1,18 +1,3 @@
|
||||
/* ─── Classic Login View ─────────────────────────────────────────────────
|
||||
Port of the old Nitro HotelView background layering, used exclusively by
|
||||
the login screen. Assets are driven by ui-config.json:
|
||||
loginview.images.background → .login-background
|
||||
loginview.images.background.colour → .nitro-login-view base colour
|
||||
loginview.images.sun → .login-sun
|
||||
loginview.images.drape → .login-drape
|
||||
loginview.images.left → .login-left
|
||||
loginview.images.right → .login-right
|
||||
loginview.images.right.repeat → .login-right-repeat
|
||||
|
||||
Class names are deliberately prefixed so HotelView.css rules
|
||||
(.left { left: 18vw !important } etc.) cannot clobber us.
|
||||
--------------------------------------------------------------------- */
|
||||
|
||||
.nitro-login-view {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
@@ -82,7 +67,7 @@
|
||||
background-position: right bottom;
|
||||
}
|
||||
|
||||
/* ─── Foreground Login Card Stack ───────────────────────────────────── */
|
||||
/* ─── Foreground Login Card Stack ─── */
|
||||
|
||||
.nitro-login-view .login-stack {
|
||||
position: absolute;
|
||||
@@ -167,6 +152,22 @@
|
||||
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 0 0 2px rgba(63, 106, 133, 0.3);
|
||||
}
|
||||
|
||||
.nitro-login-card .remember-me {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 11px;
|
||||
color: #0a2e45;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
margin: -2px 0 2px 0;
|
||||
}
|
||||
|
||||
.nitro-login-card .remember-me input[type="checkbox"] {
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nitro-login-card .submit-row {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@@ -242,8 +243,6 @@
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* Modal overlay used for register + forgot password dialogs */
|
||||
|
||||
.nitro-login-modal {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
@@ -259,3 +258,282 @@
|
||||
max-width: calc(100% - 40px);
|
||||
}
|
||||
|
||||
.nitro-login-modal .dialog.dialog-avatar {
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
/* ─── Multi-step register dialog ─── */
|
||||
|
||||
.nitro-login-card .register-intro {
|
||||
background: #eef4f8;
|
||||
border: 1px solid #b6cfdd;
|
||||
border-radius: 4px;
|
||||
padding: 6px 8px;
|
||||
font-size: 11px;
|
||||
line-height: 1.4;
|
||||
color: #0a2e45;
|
||||
}
|
||||
|
||||
.nitro-login-card .step-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.nitro-login-card .step-footer-split {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.nitro-login-card .step-indicator {
|
||||
font-size: 11px;
|
||||
color: #134b6e;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.nitro-login-card .back-button {
|
||||
background: #d5e2eb;
|
||||
}
|
||||
|
||||
/* ─── Avatar builder (pre-login) ─── */
|
||||
|
||||
.nitro-login-card .gender-row {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 22px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.nitro-login-card .gender-row label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nitro-login-card .avatar-builder {
|
||||
display: grid;
|
||||
grid-template-columns: 74px 1fr 74px;
|
||||
gap: 6px;
|
||||
align-items: stretch;
|
||||
background: repeating-linear-gradient(
|
||||
0deg,
|
||||
#ffffff 0,
|
||||
#ffffff 8px,
|
||||
#e5ecf1 8px,
|
||||
#e5ecf1 16px
|
||||
);
|
||||
border: 1px solid #7595ac;
|
||||
border-radius: 6px;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.nitro-login-card .avatar-part-col,
|
||||
.nitro-login-card .avatar-color-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.nitro-login-card .avatar-part-row,
|
||||
.nitro-login-card .avatar-color-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 3px;
|
||||
min-height: 44px;
|
||||
}
|
||||
|
||||
.nitro-login-card .arrow-btn {
|
||||
width: 16px;
|
||||
height: 20px;
|
||||
line-height: 1;
|
||||
padding: 0;
|
||||
border: 1px solid #7595ac;
|
||||
border-radius: 3px;
|
||||
background: #ffffff;
|
||||
color: #0a2e45;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
box-shadow: inset 0 1px rgba(255, 255, 255, 0.8), 0 1px rgba(0, 0, 0, 0.15);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.nitro-login-card .arrow-btn:hover {
|
||||
background: #e9f1f7;
|
||||
}
|
||||
|
||||
.nitro-login-card .part-preview {
|
||||
flex: 1;
|
||||
height: 44px;
|
||||
border: 1px solid #7595ac;
|
||||
border-radius: 3px;
|
||||
background: #ffffff;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: inset 0 1px rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
.nitro-login-card .part-preview img {
|
||||
image-rendering: pixelated;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
max-width: none;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.nitro-login-card .part-preview-hr img,
|
||||
.nitro-login-card .part-preview-hd img {
|
||||
width: 40px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.nitro-login-card .part-preview-ch img {
|
||||
width: 50px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.nitro-login-card .part-preview-lg img {
|
||||
width: 50px;
|
||||
margin-top: -8px;
|
||||
}
|
||||
|
||||
.nitro-login-card .part-preview-sh img {
|
||||
width: 50px;
|
||||
margin-top: -22px;
|
||||
}
|
||||
|
||||
.nitro-login-card .color-swatch {
|
||||
flex: 1;
|
||||
height: 18px;
|
||||
border: 1px solid #7595ac;
|
||||
border-radius: 3px;
|
||||
box-shadow: inset 0 1px rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
|
||||
.nitro-login-card .avatar-preview {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
min-height: 130px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.nitro-login-card .avatar-preview img {
|
||||
max-width: 100%;
|
||||
max-height: 140px;
|
||||
image-rendering: pixelated;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
}
|
||||
|
||||
.nitro-login-card .hot-looks-row {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.nitro-login-card .server-offline {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 6px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.nitro-login-card .server-offline .retry-link {
|
||||
background: #ffffff;
|
||||
border: 1px solid #3f6a85;
|
||||
border-radius: 4px;
|
||||
padding: 2px 10px;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
color: #0a2e45;
|
||||
cursor: pointer;
|
||||
box-shadow: inset 0 1px rgba(255, 255, 255, 0.8), 0 1px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.nitro-login-card .server-offline .retry-link:disabled {
|
||||
opacity: 0.55;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.nitro-login-card .hot-looks-button {
|
||||
padding: 4px 14px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
/* ─── Room template picker (step 3) ─── */
|
||||
|
||||
.nitro-login-card .room-templates-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
max-height: 260px;
|
||||
overflow-y: auto;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
.nitro-login-card .room-template-option {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
padding: 8px 10px;
|
||||
border: 1px solid #b6cfdd;
|
||||
border-radius: 4px;
|
||||
background: #eef4f8;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.15s, background 0.15s;
|
||||
}
|
||||
|
||||
.nitro-login-card .room-template-option:hover {
|
||||
border-color: #7fa9c3;
|
||||
}
|
||||
|
||||
.nitro-login-card .room-template-option.selected {
|
||||
border-color: #2e6b92;
|
||||
background: #d9e8f2;
|
||||
}
|
||||
|
||||
.nitro-login-card .room-template-option input[type="radio"] {
|
||||
margin: 2px 0 0 0;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nitro-login-card .room-template-thumb {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
object-fit: cover;
|
||||
border-radius: 3px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.nitro-login-card .room-template-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.nitro-login-card .room-template-title {
|
||||
font-weight: 700;
|
||||
font-size: 12px;
|
||||
color: #0a2e45;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.nitro-login-card .room-template-description {
|
||||
font-size: 11px;
|
||||
color: #2a4a5c;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user