Files
Stirling-PDF/frontend/shared/auth/ui/auth.css
T
James BruntonandGitHub 1816bad1ba Unified auth for portal and editor (#6725)
# Description of Changes
Refactor frontend auth to the shared folder and hook it up to both the
portal and editor so they share the same system. Also adds various tasks
to help run the portal, including `task dev:portal` to spawn the portal
with the backend, and `task dev:portal:proxy` to spawn the editor,
portal and backend, and a reverse proxy (at localhost:3000) to allow you
to use both at once to simulate how this will actually be deployed,
allowing you to check whether the seamless transition between the two
actually works.
2026-06-22 16:22:36 +00:00

732 lines
16 KiB
CSS

.auth-fields {
display: flex;
flex-direction: column;
gap: 0.5rem; /* 8px */
margin-bottom: 0.75rem; /* 12px */
}
/* "or" divider between OAuth buttons and the email form (light-mode auth pages) */
.auth-or-divider {
display: flex;
align-items: center;
gap: 0.75rem; /* 12px */
margin: 0.375rem 0 0.5rem; /* 6px 0 8px */
}
.auth-or-divider__rule {
height: 0.0625rem; /* 1px */
flex: 1 1 0%;
background-color: rgb(var(--text-divider-rule-rgb-light) / 0.4);
}
.auth-or-divider__label {
color: rgb(var(--text-divider-label-rgb-light) / 0.4);
font-size: 0.75rem; /* 12px */
white-space: nowrap;
}
.auth-field {
display: flex;
flex-direction: column;
gap: 0.25rem; /* 4px */
}
.auth-label {
font-size: 0.875rem; /* 14px */
color: var(--auth-label-text-light-only);
font-weight: 500;
}
.auth-input {
width: 100%;
padding: 0.625rem 0.75rem; /* 10px 12px */
border: 1px solid var(--auth-input-border-light-only);
border-radius: 0.625rem; /* 10px */
font-size: 0.875rem; /* 14px */
background-color: var(--auth-input-bg-light-only);
color: var(--auth-input-text-light-only);
outline: none;
}
.auth-input:focus {
border-color: var(--auth-border-focus-light-only);
box-shadow: 0 0 0 3px var(--auth-focus-ring-light-only);
}
.auth-button {
width: 100%;
padding: 0.625rem 0.75rem; /* 10px 12px */
border: none;
border-radius: 0.625rem; /* 10px */
background-color: var(--auth-button-bg-light-only);
color: var(--auth-button-text-light-only);
font-size: 0.875rem; /* 14px */
font-weight: 600;
margin-bottom: 0.75rem; /* 12px */
cursor: pointer;
}
.auth-button:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.auth-toggle-wrapper {
text-align: center;
margin-bottom: 0.625rem; /* 10px */
}
.auth-toggle-link {
background: transparent;
border: 0;
color: var(--auth-label-text-light-only);
font-size: 0.875rem; /* 14px */
text-decoration: underline;
cursor: pointer;
}
.auth-toggle-link:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.auth-magic-row {
display: flex;
gap: 0.5rem; /* 8px */
margin-bottom: 0.75rem; /* 12px */
}
.auth-magic-row .auth-input {
flex: 1 1 auto;
}
.auth-magic-button {
padding: 0.875rem 1rem; /* 14px 16px */
border: none;
border-radius: 0.625rem; /* 10px */
background-color: var(--auth-magic-button-bg-light-only);
color: var(--auth-magic-button-text-light-only);
font-size: 0.875rem; /* 14px */
font-weight: 600;
white-space: nowrap;
cursor: pointer;
}
.auth-magic-button:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.auth-terms {
display: flex;
align-items: center;
gap: 0.5rem; /* 8px */
margin-bottom: 0.5rem; /* 8px */
}
.auth-checkbox {
width: 1rem; /* 16px */
height: 1rem; /* 16px */
accent-color: #af3434;
}
.auth-terms-label {
font-size: 0.75rem; /* 12px */
color: var(--auth-label-text-light-only);
}
.auth-terms-label a {
color: inherit;
text-decoration: underline;
}
.auth-confirm {
overflow: hidden;
transition:
max-height 240ms ease,
opacity 200ms ease;
}
/* OAuth Button Styles */
.oauth-container-icons {
display: flex;
margin-bottom: 0.625rem; /* 10px */
justify-content: space-between;
}
.oauth-container-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 0.75rem; /* 12px */
margin-bottom: 0.625rem; /* 10px */
}
.oauth-container-vertical {
display: flex;
flex-direction: column;
gap: 0.875rem; /* 14px */
align-items: stretch;
}
.oauth-container-vertical.oauth-container-single {
align-items: center;
}
.oauth-button-icon {
width: 3.75rem; /* 60px */
height: 3.75rem; /* 60px */
border-radius: 0.875rem; /* 14px */
border: 1px solid var(--auth-input-border-light-only);
background: var(--auth-card-bg-light-only);
cursor: pointer;
box-shadow: 0 0.125rem 0.375rem rgba(0, 0, 0, 0.04); /* 0 2px 6px */
display: flex;
align-items: center;
justify-content: center;
}
.oauth-button-icon:disabled {
cursor: not-allowed;
opacity: 0.6;
}
.oauth-button-grid {
width: 100%;
padding: 1rem; /* 16px */
border-radius: 0.875rem; /* 14px */
border: 1px solid var(--auth-input-border-light-only);
background: var(--auth-card-bg-light-only);
cursor: pointer;
box-shadow: 0 0.125rem 0.375rem rgba(0, 0, 0, 0.04); /* 0 2px 6px */
display: flex;
align-items: center;
justify-content: center;
}
.oauth-button-grid:disabled {
cursor: not-allowed;
opacity: 0.6;
}
.oauth-button-vertical {
width: 100%;
min-height: 3.5rem; /* 56px */
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.875rem 1.5rem; /* 14px 24px */
border: 1px solid var(--auth-input-border-light-only);
border-radius: 999px;
background-color: var(--auth-card-bg-light-only);
font-size: 1rem; /* 16px */
font-weight: 600;
color: var(--auth-text-primary-light-only);
cursor: pointer;
gap: 1rem; /* 16px */
font-family: inherit;
box-shadow: 0 0.125rem 0.5rem rgba(0, 0, 0, 0.08);
transition:
background-color 0.2s ease,
box-shadow 0.2s ease,
transform 0.2s ease,
border-color 0.2s ease;
}
.oauth-button-vertical:hover:not(:disabled) {
background-color: var(--hover-bg);
box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.12);
transform: translateY(-1px);
border-color: var(--border-default);
}
.oauth-button-vertical-tinted {
background: linear-gradient(
90deg,
color-mix(in srgb, var(--oauth-accent) 65%, #0f172a) 0 6px,
#0f172a 6px 100%
);
}
.oauth-button-vertical-tinted:hover:not(:disabled) {
background: linear-gradient(
90deg,
color-mix(in srgb, var(--oauth-accent) 75%, #111827) 0 6px,
#111827 6px 100%
);
}
.oauth-button-vertical-legacy {
min-height: 0;
justify-content: flex-start;
padding: 0.75rem 1rem; /* 12px 16px */
border: 1px solid #d1d5db;
border-radius: 0.75rem; /* 12px */
background-color: var(--auth-card-bg-light-only);
font-weight: 500;
color: var(--auth-text-primary-light-only);
box-shadow: none;
}
.oauth-button-vertical-legacy:hover:not(:disabled) {
background-color: #f3f4f6;
color: var(--auth-text-primary-light-only);
box-shadow: none;
}
.oauth-button-vertical-legacy .mantine-Button-inner,
.oauth-button-vertical-legacy .mantine-Button-label {
justify-content: flex-start;
}
.oauth-button-vertical-legacy .oauth-button-left {
gap: 0.75rem;
}
.oauth-button-vertical-legacy .oauth-icon-wrapper {
width: 1.25rem; /* 20px */
height: 1.25rem; /* 20px */
padding: 0;
background: transparent;
border: none;
border-radius: 0;
}
.oauth-button-vertical-legacy .oauth-button-text {
padding-bottom: 0;
}
.oauth-button-vertical-outline {
background: transparent;
border: 2px solid #0f172a;
color: #0f172a;
box-shadow: none;
}
.oauth-button-vertical-outline:hover:not(:disabled) {
background: #0f172a;
color: #f8fafc;
box-shadow: 0 0.35rem 0.9rem rgba(15, 23, 42, 0.2);
}
.oauth-button-vertical-light {
background: #f8fafc;
color: #0f172a;
border: 1px solid rgba(15, 23, 42, 0.12);
box-shadow: 0 0.25rem 0.75rem rgba(15, 23, 42, 0.12);
}
.oauth-button-vertical-light:hover:not(:disabled) {
background: #eef2f7;
color: #0f172a;
box-shadow: 0 0.35rem 0.9rem rgba(15, 23, 42, 0.16);
}
.oauth-button-vertical:disabled {
cursor: not-allowed;
opacity: 0.6;
box-shadow: none;
transform: none;
}
.oauth-button-vertical:focus-visible {
outline: 3px solid rgba(59, 130, 246, 0.5);
outline-offset: 2px;
}
/* Fix Mantine Button internal spans to not crop content */
.oauth-button-vertical .mantine-Button-inner {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
}
.oauth-button-vertical .mantine-Button-label {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
overflow: visible;
}
.oauth-icon-small {
width: 1.75rem; /* 28px */
height: 1.75rem; /* 28px */
display: block;
}
.oauth-icon-medium {
width: 1.75rem; /* 28px */
height: 1.75rem; /* 28px */
display: block;
}
.oauth-icon-tiny {
width: 1.25rem; /* 20px */
height: 1.25rem; /* 20px */
display: block;
flex-shrink: 0;
}
.oauth-container-vertical.oauth-container-single .oauth-button-vertical {
max-width: 26.25rem; /* 420px */
}
.oauth-button-left {
display: flex;
align-items: center;
gap: 0.875rem;
min-width: 0;
flex: 1 1 auto;
}
.oauth-button-text {
font-size: 1rem;
font-weight: 600;
color: inherit;
line-height: 1.2;
display: inline-flex;
align-items: center;
padding-bottom: 0.0625rem; /* 1px - prevent descender clipping */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.oauth-icon-wrapper {
width: 2.25rem; /* 36px */
height: 2.25rem; /* 36px */
border-radius: 0.75rem; /* 12px */
display: flex;
align-items: center;
justify-content: center;
background: var(--bg-muted);
border: 1px solid var(--auth-input-border-light-only);
}
.oauth-button-vertical-tinted .oauth-icon-wrapper {
background: color-mix(
in srgb,
var(--oauth-accent) 20%,
rgba(255, 255, 255, 0.08)
);
border-color: color-mix(
in srgb,
var(--oauth-accent) 35%,
rgba(255, 255, 255, 0.2)
);
}
.oauth-button-vertical-outline .oauth-icon-wrapper,
.oauth-button-vertical-light .oauth-icon-wrapper {
background: rgba(15, 23, 42, 0.06);
border-color: rgba(15, 23, 42, 0.14);
}
.oauth-button-right {
display: flex;
align-items: center;
justify-content: center;
opacity: 0.85;
flex-shrink: 0;
color: inherit;
}
.oauth-arrow-icon {
width: 1.1rem; /* 18px */
height: 1.1rem; /* 18px */
display: block;
}
.sso-demo-block {
margin-bottom: 1.5rem;
}
.sso-demo-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
gap: 1.25rem;
}
.sso-demo-card {
border: 1px solid var(--auth-input-border-light-only);
border-radius: 1rem;
padding: 1rem;
background: var(--auth-card-bg-light-only);
box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.06);
}
.sso-demo-title {
font-size: 0.875rem;
font-weight: 700;
color: var(--auth-text-primary-light-only);
margin-bottom: 0.75rem;
letter-spacing: 0.01em;
text-transform: uppercase;
}
/* Login Header Styles */
.login-header {
margin-bottom: 1rem; /* 16px */
margin-top: 0.5rem; /* 8px */
}
.login-header-centered {
text-align: center;
margin-bottom: 1.5rem; /* 24px */
}
.login-header-centered .login-header-logos {
justify-content: center;
}
.login-header-centered .login-logo-text {
height: 2.5rem; /* 40px */
}
.login-header-logos {
display: flex;
align-items: center;
gap: 0.75rem; /* 12px */
margin-bottom: 1.25rem; /* 20px */
}
.login-logo-icon {
width: 2.5rem; /* 40px */
height: 2.5rem; /* 40px */
border-radius: 0.5rem; /* 8px */
}
.login-logo-text {
height: 2rem; /* 32px - increased from 24px */
}
.login-title {
font-size: 2rem; /* 32px */
font-weight: 800;
color: var(--auth-text-primary-light-only);
margin: 0 0 0.375rem; /* 0 0 6px */
}
.login-subtitle {
color: var(--auth-text-secondary-light-only);
font-size: 0.875rem; /* 14px */
margin: 0;
}
/* Navigation Link Styles */
.navigation-link-container {
text-align: center;
}
.navigation-link-button {
background: none;
border: none;
color: var(--auth-label-text-light-only);
font-size: 0.875rem; /* 14px */
cursor: pointer;
text-decoration: underline;
}
.navigation-link-button:disabled {
cursor: not-allowed;
opacity: 0.6;
}
/* Message Styles */
.error-message {
padding: 1rem; /* 16px */
background-color: #fef2f2;
border: 1px solid #fecaca;
border-radius: 0.5rem; /* 8px */
margin-bottom: 1.5rem; /* 24px */
}
.error-message-text {
color: #dc2626;
font-size: 0.875rem; /* 14px */
margin: 0;
}
.success-message {
padding: 1rem; /* 16px */
background-color: #f0fdf4;
border: 1px solid #bbf7d0;
border-radius: 0.5rem; /* 8px */
margin-bottom: 1.5rem; /* 24px */
}
.success-message-text {
color: #059669;
font-size: 0.875rem; /* 14px */
margin: 0;
}
/* Field-level error styles */
.auth-field-error {
color: #dc2626;
font-size: 0.6875rem; /* 11px */
margin-top: 0.125rem; /* 2px */
line-height: 1.1;
}
.auth-input-error {
border-color: #dc2626 !important;
}
.auth-input-error:focus {
border-color: #dc2626 !important;
box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.1) !important;
}
/* Shared auth styles extracted from inline */
.auth-section {
margin: 0.75rem 0;
}
.auth-section-sm {
margin: 0.5rem 0;
}
.auth-bottom-row {
display: flex;
align-items: center;
justify-content: space-between;
margin: 0.5rem 0 0.25rem;
}
.auth-bottom-right {
display: flex;
align-items: center;
justify-content: flex-end;
margin-top: 0.5rem;
}
.auth-link-black {
background: transparent;
border: 0;
padding: 0;
margin: 0;
text-decoration: underline;
cursor: pointer;
font-size: 0.875rem; /* 14px */
color: var(--auth-text-primary-light-only);
}
.auth-dot-black {
opacity: 0.5;
padding: 0 0.5rem;
color: var(--auth-text-primary-light-only);
}
/* Email login button - red CTA style matching SaaS version */
.auth-cta-button {
background-color: #af3434 !important;
color: white !important;
border: none !important;
font-weight: 600 !important;
}
.auth-cta-button:hover:not(:disabled) {
background-color: #9a2e2e !important;
}
.auth-cta-button:disabled {
background-color: #af3434 !important;
opacity: 0.6 !important;
}
/* ── Logo block ─────────────────────────────────────────────────────── */
.auth-logo-block {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 2rem;
margin-top: 0.5rem;
animation: authFadeUp 0.4s ease both;
}
.auth-logo-header {
height: 8rem;
width: auto;
}
/* Two logo variants are rendered; show the one matching the active theme. */
.auth-logo-header--dark {
display: none;
}
[data-mantine-color-scheme="dark"] .auth-logo-header--light {
display: none;
}
[data-mantine-color-scheme="dark"] .auth-logo-header--dark {
display: block;
}
/* ── Page entrance animation ────────────────────────────────────────── */
@keyframes authFadeUp {
from {
opacity: 0;
transform: translateY(12px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* ── Expandable trigger button state ────────────────────────────────── */
.auth-expandable-trigger {
transition:
background-color 180ms ease,
box-shadow 180ms ease,
border-color 180ms ease;
}
.auth-expandable-trigger--active {
border-color: #af3434 !important;
box-shadow: 0 0 0 3px rgba(175, 52, 52, 0.12);
}
/* ── Animated expand/collapse via grid-template-rows ───────────────── */
.auth-expand-grid {
display: grid;
grid-template-rows: 0fr;
transition:
grid-template-rows 280ms cubic-bezier(0.4, 0, 0.2, 1),
opacity 220ms ease;
opacity: 0;
}
.auth-expand-grid--open {
grid-template-rows: 1fr;
opacity: 1;
}
.auth-expand-inner {
overflow: hidden;
min-height: 0;
}
/* ── Icon+label group — keeps icons vertically aligned across buttons ── */
.oauth-btn-group {
display: inline-flex;
align-items: center;
min-width: 12.5rem;
}
.oauth-btn-label {
flex: 1;
text-align: center;
}
/* ── Icon helpers inside oauth-button-fullwidth ─────────────────────── */
.auth-at-icon {
font-size: 1.25rem;
line-height: 1;
margin-right: 0.5rem;
display: inline-block;
width: 1.75rem;
text-align: center;
flex-shrink: 0;
}