905 lines
No EOL
23 KiB
HTML
905 lines
No EOL
23 KiB
HTML
<!doctype html>
|
|
<html lang="en" data-theme="light">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="color-scheme" content="light dark">
|
|
<title>Petrol Login Demo — Refined Dark Mode</title>
|
|
|
|
<style>
|
|
@import url("https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:wght@400;700&family=Lexend:wght@400;500;600;700&display=swap");
|
|
|
|
:root {
|
|
color-scheme: light;
|
|
|
|
--font-body: "Atkinson Hyperlegible", "Segoe UI", Arial, sans-serif;
|
|
--font-ui: "Lexend", "Segoe UI", Arial, sans-serif;
|
|
|
|
--page: #f2f6f4;
|
|
--page-accent: #e3eeea;
|
|
--surface: #ffffff;
|
|
--surface-alt: #edf4f1;
|
|
--surface-strong: #d9e8e2;
|
|
|
|
--text: #17343a;
|
|
--muted: #64777a;
|
|
--border: #c5d7d2;
|
|
|
|
--petrol: #0b4f58;
|
|
--petrol-deep: #063840;
|
|
--petrol-soft: #d9ebea;
|
|
|
|
--secondary: #dfe9e6;
|
|
--secondary-hover: #d2e1dc;
|
|
--secondary-soft: #edf4f1;
|
|
--on-secondary: #17343a;
|
|
|
|
--teal: #4e978f;
|
|
--mint: #cfe5dc;
|
|
--lavender: #8d87a8;
|
|
--lavender-soft: #eceaf3;
|
|
--sand: #c7aa73;
|
|
--sand-soft: #f2eadc;
|
|
--coral: #c97b70;
|
|
--coral-soft: #f5e5e2;
|
|
|
|
--success: #5f8e72;
|
|
--danger: #a9605c;
|
|
|
|
--focus: #6baea8;
|
|
--shadow-lg: 0 28px 70px rgb(7 56 64 / 13%);
|
|
--shadow-sm: 0 10px 24px rgb(7 56 64 / 8%);
|
|
|
|
--radius-sm: 0.55rem;
|
|
--radius-md: 0.9rem;
|
|
--radius-lg: 1.5rem;
|
|
}
|
|
|
|
html[data-theme="dark"] {
|
|
color-scheme: dark;
|
|
|
|
/* Near-black blue-green foundation */
|
|
--page: #03090B;
|
|
--page-accent: #071216;
|
|
--surface: #0C191D;
|
|
--surface-alt: #11252B;
|
|
--surface-strong: #19343B;
|
|
|
|
--text: #EDF6F4;
|
|
--muted: #AEC1C0;
|
|
--border: #29464D;
|
|
|
|
/* Deep petrol is now the primary colour */
|
|
--petrol: #0E6670;
|
|
--petrol-deep: #0A4F58;
|
|
--petrol-soft: #17383D;
|
|
|
|
/* Secondary blue-green */
|
|
--secondary: #2B5360;
|
|
--secondary-hover: #376775;
|
|
--secondary-soft: #162B32;
|
|
--on-secondary: #EDF6F4;
|
|
|
|
--teal: #6EA9A3;
|
|
--mint: #2D4A45;
|
|
--lavender: #9E99B8;
|
|
--lavender-soft: #292738;
|
|
--sand: #C9AF7D;
|
|
--sand-soft: #393321;
|
|
--coral: #CD8B82;
|
|
--coral-soft: #3B2B29;
|
|
|
|
--success: #8DBA98;
|
|
--danger: #D28F89;
|
|
|
|
--focus: #9FD9D3;
|
|
--shadow-lg: 0 34px 90px rgb(0 0 0 / 48%);
|
|
--shadow-sm: 0 14px 34px rgb(0 0 0 / 34%);
|
|
}
|
|
|
|
|
|
html[data-theme="dark"] body {
|
|
background:
|
|
radial-gradient(
|
|
circle at 82% 10%,
|
|
rgb(43 83 96 / 22%),
|
|
transparent 30%
|
|
),
|
|
radial-gradient(
|
|
circle at 18% 88%,
|
|
rgb(14 102 112 / 12%),
|
|
transparent 34%
|
|
),
|
|
linear-gradient(145deg, var(--page), var(--page-accent));
|
|
}
|
|
|
|
html[data-theme="dark"] .visual-panel {
|
|
background:
|
|
linear-gradient(150deg, rgb(5 48 55 / 98%), rgb(10 79 88 / 96%)),
|
|
linear-gradient(45deg, var(--petrol-deep), var(--petrol));
|
|
}
|
|
|
|
html[data-theme="dark"] .visual-panel::before {
|
|
background: rgb(110 169 163 / 12%);
|
|
}
|
|
|
|
html[data-theme="dark"] .visual-panel::after {
|
|
background: rgb(43 83 96 / 26%);
|
|
}
|
|
|
|
html[data-theme="dark"] .login-panel {
|
|
background: color-mix(in srgb, var(--page-accent) 78%, transparent);
|
|
}
|
|
|
|
html[data-theme="dark"] .login-card {
|
|
background: color-mix(in srgb, var(--surface) 98%, transparent);
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
html {
|
|
font-family: var(--font-body);
|
|
font-size: 18px;
|
|
line-height: 1.62;
|
|
background: var(--page);
|
|
color: var(--text);
|
|
text-rendering: optimizeLegibility;
|
|
}
|
|
|
|
body {
|
|
min-height: 100vh;
|
|
margin: 0;
|
|
background:
|
|
radial-gradient(circle at 12% 10%, color-mix(in srgb, var(--mint) 42%, transparent), transparent 28%),
|
|
radial-gradient(circle at 88% 16%, color-mix(in srgb, var(--lavender-soft) 72%, transparent), transparent 26%),
|
|
linear-gradient(145deg, var(--page), var(--page-accent));
|
|
}
|
|
|
|
button,
|
|
input {
|
|
font: inherit;
|
|
}
|
|
|
|
button,
|
|
a {
|
|
-webkit-tap-highlight-color: transparent;
|
|
}
|
|
|
|
a {
|
|
color: var(--petrol);
|
|
text-decoration-thickness: 0.08em;
|
|
text-underline-offset: 0.18em;
|
|
}
|
|
|
|
a:hover {
|
|
color: var(--petrol-deep);
|
|
}
|
|
|
|
:focus-visible {
|
|
outline: 3px solid var(--focus);
|
|
outline-offset: 3px;
|
|
}
|
|
|
|
.page-shell {
|
|
min-height: 100vh;
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1.05fr) minmax(360px, 0.95fr);
|
|
}
|
|
|
|
.visual-panel {
|
|
position: relative;
|
|
overflow: hidden;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-between;
|
|
min-height: 100vh;
|
|
padding: clamp(2rem, 5vw, 4.5rem);
|
|
color: #effaf8;
|
|
background:
|
|
linear-gradient(150deg, rgb(6 56 64 / 96%), rgb(12 79 87 / 94%)),
|
|
linear-gradient(45deg, #063840, #0b4f58);
|
|
}
|
|
|
|
.visual-panel::before,
|
|
.visual-panel::after {
|
|
content: "";
|
|
position: absolute;
|
|
border-radius: 999px;
|
|
opacity: 0.9;
|
|
filter: blur(2px);
|
|
}
|
|
|
|
.visual-panel::before {
|
|
width: 24rem;
|
|
height: 24rem;
|
|
top: -8rem;
|
|
right: -8rem;
|
|
background: rgb(207 229 220 / 16%);
|
|
}
|
|
|
|
.visual-panel::after {
|
|
width: 18rem;
|
|
height: 18rem;
|
|
left: -7rem;
|
|
bottom: -6rem;
|
|
background: rgb(141 135 168 / 18%);
|
|
}
|
|
|
|
.brand,
|
|
.hero-copy,
|
|
.trust-row {
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
|
|
.brand {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.8rem;
|
|
font-family: var(--font-ui);
|
|
font-weight: 700;
|
|
letter-spacing: -0.02em;
|
|
}
|
|
|
|
.brand-mark {
|
|
display: grid;
|
|
place-items: center;
|
|
width: 2.7rem;
|
|
aspect-ratio: 1;
|
|
border: 1px solid rgb(255 255 255 / 30%);
|
|
border-radius: 0.85rem;
|
|
background: rgb(255 255 255 / 10%);
|
|
backdrop-filter: blur(10px);
|
|
box-shadow: inset 0 1px 0 rgb(255 255 255 / 18%);
|
|
}
|
|
|
|
.brand-mark svg {
|
|
width: 1.55rem;
|
|
height: 1.55rem;
|
|
}
|
|
|
|
.hero-copy {
|
|
max-width: 34rem;
|
|
margin-block: auto;
|
|
padding-block: 4rem;
|
|
}
|
|
|
|
.eyebrow {
|
|
margin: 0 0 0.8rem;
|
|
color: #cfe5dc;
|
|
font-family: var(--font-ui);
|
|
font-size: 0.84rem;
|
|
font-weight: 700;
|
|
letter-spacing: 0.11em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
h1,
|
|
h2 {
|
|
margin: 0;
|
|
font-family: var(--font-ui);
|
|
line-height: 1.14;
|
|
letter-spacing: -0.035em;
|
|
}
|
|
|
|
.hero-copy h1 {
|
|
max-width: 11ch;
|
|
font-size: clamp(2.7rem, 6vw, 5.6rem);
|
|
}
|
|
|
|
.hero-copy p {
|
|
max-width: 34rem;
|
|
margin: 1.4rem 0 0;
|
|
color: rgb(239 250 248 / 82%);
|
|
font-size: 1.08rem;
|
|
}
|
|
|
|
.feature-list {
|
|
display: grid;
|
|
gap: 0.8rem;
|
|
margin: 2rem 0 0;
|
|
padding: 0;
|
|
list-style: none;
|
|
}
|
|
|
|
.feature-list li {
|
|
display: flex;
|
|
gap: 0.7rem;
|
|
align-items: flex-start;
|
|
color: rgb(239 250 248 / 90%);
|
|
}
|
|
|
|
.feature-list svg {
|
|
flex: 0 0 auto;
|
|
width: 1.1rem;
|
|
margin-top: 0.23rem;
|
|
}
|
|
|
|
.trust-row {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 0.75rem;
|
|
color: rgb(239 250 248 / 72%);
|
|
font-size: 0.86rem;
|
|
}
|
|
|
|
.trust-pill {
|
|
padding: 0.35rem 0.62rem;
|
|
border: 1px solid rgb(255 255 255 / 20%);
|
|
border-radius: 999px;
|
|
background: rgb(255 255 255 / 8%);
|
|
}
|
|
|
|
.login-panel {
|
|
position: relative;
|
|
display: grid;
|
|
place-items: center;
|
|
min-height: 100vh;
|
|
padding: clamp(1.2rem, 4vw, 3rem);
|
|
background: color-mix(in srgb, var(--surface) 52%, transparent);
|
|
backdrop-filter: blur(14px);
|
|
}
|
|
|
|
.theme-toggle {
|
|
position: absolute;
|
|
top: 1.3rem;
|
|
right: 1.3rem;
|
|
display: inline-flex;
|
|
gap: 0.35rem;
|
|
padding: 0.32rem;
|
|
border: 1px solid var(--border);
|
|
border-radius: 999px;
|
|
background: color-mix(in srgb, var(--secondary-soft) 92%, transparent);
|
|
box-shadow: var(--shadow-sm);
|
|
}
|
|
|
|
.theme-toggle button {
|
|
display: grid;
|
|
place-items: center;
|
|
width: 2.2rem;
|
|
aspect-ratio: 1;
|
|
padding: 0;
|
|
color: var(--muted);
|
|
border: 0;
|
|
border-radius: 999px;
|
|
background: transparent;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.theme-toggle button[aria-pressed="true"] {
|
|
color: var(--text);
|
|
background: var(--surface-strong);
|
|
}
|
|
|
|
.theme-toggle svg {
|
|
width: 1rem;
|
|
height: 1rem;
|
|
}
|
|
|
|
.login-card {
|
|
width: min(100%, 28rem);
|
|
padding: clamp(1.35rem, 4vw, 2.35rem);
|
|
background: color-mix(in srgb, var(--surface) 97%, transparent);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-lg);
|
|
box-shadow: var(--shadow-lg);
|
|
}
|
|
|
|
.login-card header {
|
|
margin-bottom: 1.8rem;
|
|
}
|
|
|
|
.login-card h2 {
|
|
font-size: clamp(1.8rem, 4vw, 2.35rem);
|
|
}
|
|
|
|
.login-card header p {
|
|
margin: 0.65rem 0 0;
|
|
color: var(--muted);
|
|
}
|
|
|
|
.field {
|
|
margin-bottom: 1.15rem;
|
|
}
|
|
|
|
.field-row {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
gap: 1rem;
|
|
align-items: center;
|
|
margin-bottom: 0.42rem;
|
|
}
|
|
|
|
label {
|
|
font-family: var(--font-ui);
|
|
font-size: 0.93rem;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.field-row a {
|
|
font-size: 0.88rem;
|
|
}
|
|
|
|
.input-wrap {
|
|
position: relative;
|
|
}
|
|
|
|
input[type="email"],
|
|
input[type="password"],
|
|
input[type="text"] {
|
|
width: 100%;
|
|
min-height: 3.15rem;
|
|
padding: 0.78rem 0.95rem;
|
|
color: var(--text);
|
|
background: var(--surface-alt);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-sm);
|
|
transition:
|
|
border-color 140ms ease,
|
|
background-color 140ms ease,
|
|
box-shadow 140ms ease;
|
|
}
|
|
|
|
input::placeholder {
|
|
color: var(--muted);
|
|
opacity: 0.82;
|
|
}
|
|
|
|
input:hover {
|
|
border-color: color-mix(in srgb, var(--border) 55%, var(--petrol));
|
|
}
|
|
|
|
input:focus {
|
|
border-color: var(--petrol);
|
|
background: var(--surface);
|
|
box-shadow: 0 0 0 4px color-mix(in srgb, var(--focus) 22%, transparent);
|
|
outline: none;
|
|
}
|
|
|
|
.password-input {
|
|
padding-right: 3.1rem;
|
|
}
|
|
|
|
.show-password {
|
|
position: absolute;
|
|
inset: 50% 0.55rem auto auto;
|
|
display: grid;
|
|
place-items: center;
|
|
width: 2.2rem;
|
|
aspect-ratio: 1;
|
|
padding: 0;
|
|
color: var(--muted);
|
|
border: 0;
|
|
border-radius: 0.55rem;
|
|
background: transparent;
|
|
transform: translateY(-50%);
|
|
cursor: pointer;
|
|
}
|
|
|
|
.show-password:hover {
|
|
color: var(--text);
|
|
background: var(--surface-strong);
|
|
}
|
|
|
|
.show-password svg {
|
|
width: 1.05rem;
|
|
height: 1.05rem;
|
|
}
|
|
|
|
.form-options {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
gap: 1rem;
|
|
align-items: center;
|
|
margin: 0.2rem 0 1.25rem;
|
|
}
|
|
|
|
.checkbox-label {
|
|
display: inline-flex;
|
|
gap: 0.55rem;
|
|
align-items: center;
|
|
color: var(--muted);
|
|
font-family: var(--font-body);
|
|
font-size: 0.94rem;
|
|
font-weight: 400;
|
|
cursor: pointer;
|
|
}
|
|
|
|
input[type="checkbox"] {
|
|
width: 1.05rem;
|
|
height: 1.05rem;
|
|
margin: 0;
|
|
accent-color: var(--petrol);
|
|
}
|
|
|
|
.primary-button {
|
|
width: 100%;
|
|
min-height: 3.15rem;
|
|
padding: 0.8rem 1rem;
|
|
color: var(--on-primary);
|
|
background: var(--petrol);
|
|
border: 1px solid var(--petrol);
|
|
border-radius: var(--radius-sm);
|
|
font-family: var(--font-ui);
|
|
font-weight: 700;
|
|
cursor: pointer;
|
|
box-shadow: 0 10px 22px color-mix(in srgb, var(--petrol) 22%, transparent);
|
|
transition:
|
|
transform 140ms ease,
|
|
background-color 140ms ease,
|
|
box-shadow 140ms ease;
|
|
}
|
|
|
|
.primary-button:hover {
|
|
background: var(--petrol-deep);
|
|
transform: translateY(-1px);
|
|
box-shadow: 0 14px 30px color-mix(in srgb, var(--petrol) 26%, transparent);
|
|
}
|
|
|
|
.primary-button:active {
|
|
transform: translateY(0);
|
|
}
|
|
|
|
.divider {
|
|
display: grid;
|
|
grid-template-columns: 1fr auto 1fr;
|
|
gap: 0.8rem;
|
|
align-items: center;
|
|
margin: 1.3rem 0;
|
|
color: var(--muted);
|
|
font-size: 0.84rem;
|
|
}
|
|
|
|
.divider::before,
|
|
.divider::after {
|
|
content: "";
|
|
height: 1px;
|
|
background: var(--border);
|
|
}
|
|
|
|
.secondary-button {
|
|
width: 100%;
|
|
min-height: 3rem;
|
|
display: inline-flex;
|
|
justify-content: center;
|
|
gap: 0.7rem;
|
|
align-items: center;
|
|
padding: 0.72rem 1rem;
|
|
color: var(--on-secondary);
|
|
background: var(--secondary);
|
|
border: 1px solid color-mix(in srgb, var(--secondary) 72%, var(--border));
|
|
border-radius: var(--radius-sm);
|
|
font-family: var(--font-ui);
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.secondary-button:hover {
|
|
background: var(--secondary-hover);
|
|
}
|
|
|
|
.secondary-button svg {
|
|
width: 1.15rem;
|
|
height: 1.15rem;
|
|
}
|
|
|
|
.signup-note {
|
|
margin: 1.4rem 0 0;
|
|
color: var(--muted);
|
|
text-align: center;
|
|
font-size: 0.94rem;
|
|
}
|
|
|
|
.helper-message {
|
|
display: none;
|
|
margin: 0.5rem 0 0;
|
|
padding: 0.58rem 0.7rem;
|
|
color: var(--danger);
|
|
background: var(--coral-soft);
|
|
border-left: 0.3rem solid var(--danger);
|
|
border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
|
|
font-size: 0.87rem;
|
|
}
|
|
|
|
.helper-message.visible {
|
|
display: block;
|
|
}
|
|
|
|
.privacy-note {
|
|
width: min(100%, 28rem);
|
|
margin: 1rem auto 0;
|
|
color: var(--muted);
|
|
font-size: 0.82rem;
|
|
text-align: center;
|
|
}
|
|
|
|
@media (max-width: 900px) {
|
|
.page-shell {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.visual-panel {
|
|
min-height: auto;
|
|
padding: 1.5rem 1.2rem 2rem;
|
|
}
|
|
|
|
.hero-copy {
|
|
margin: 2.5rem 0 0;
|
|
padding: 0;
|
|
}
|
|
|
|
.hero-copy h1 {
|
|
max-width: 14ch;
|
|
font-size: clamp(2.4rem, 10vw, 4rem);
|
|
}
|
|
|
|
.feature-list,
|
|
.trust-row {
|
|
display: none;
|
|
}
|
|
|
|
.login-panel {
|
|
min-height: auto;
|
|
padding: 1.2rem 1rem 2.5rem;
|
|
}
|
|
|
|
.theme-toggle {
|
|
top: 1rem;
|
|
right: 1rem;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 520px) {
|
|
html {
|
|
font-size: 17px;
|
|
}
|
|
|
|
.login-card {
|
|
padding: 1.25rem;
|
|
border-radius: 1.15rem;
|
|
}
|
|
|
|
.form-options {
|
|
align-items: flex-start;
|
|
flex-direction: column;
|
|
gap: 0.7rem;
|
|
}
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
*,
|
|
*::before,
|
|
*::after {
|
|
animation-duration: 0.01ms !important;
|
|
animation-iteration-count: 1 !important;
|
|
scroll-behavior: auto !important;
|
|
transition-duration: 0.01ms !important;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<main class="page-shell">
|
|
<section class="visual-panel" aria-labelledby="welcome-title">
|
|
<div class="brand">
|
|
<span class="brand-mark" aria-hidden="true">
|
|
<svg viewBox="0 0 24 24" fill="none">
|
|
<path d="M5 15.5 12 4l7 11.5-7 4.5-7-4.5Z" stroke="currentColor" stroke-width="1.7"/>
|
|
<circle cx="12" cy="12" r="2.2" fill="currentColor"/>
|
|
</svg>
|
|
</span>
|
|
<span>Calmspace</span>
|
|
</div>
|
|
|
|
<div class="hero-copy">
|
|
<p class="eyebrow">Clear space. Clear mind.</p>
|
|
<h1 id="welcome-title">Work with focus, not friction.</h1>
|
|
<p>
|
|
A calmer workspace for planning, tracking and finishing what matters—
|
|
without clutter, noise or unnecessary decisions.
|
|
</p>
|
|
|
|
<ul class="feature-list">
|
|
<li>
|
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
<path d="m5 12 4 4L19 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
</svg>
|
|
Clear visual hierarchy and predictable navigation
|
|
</li>
|
|
<li>
|
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
<path d="m5 12 4 4L19 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
</svg>
|
|
Low-noise colours designed for longer sessions
|
|
</li>
|
|
<li>
|
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
<path d="m5 12 4 4L19 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
</svg>
|
|
Readable typography with generous spacing
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="trust-row" aria-label="Product qualities">
|
|
<span class="trust-pill">Private by design</span>
|
|
<span class="trust-pill">Accessible</span>
|
|
<span class="trust-pill">Distraction-aware</span>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="login-panel" aria-labelledby="login-title">
|
|
<div class="theme-toggle" aria-label="Theme">
|
|
<button type="button" data-theme="light" aria-label="Use light mode" aria-pressed="true">
|
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
<circle cx="12" cy="12" r="4" stroke="currentColor" stroke-width="1.8"/>
|
|
<path d="M12 2v2M12 20v2M4.93 4.93l1.42 1.42M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.42-1.42M17.66 6.34l1.41-1.41" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
|
|
</svg>
|
|
</button>
|
|
|
|
<button type="button" data-theme="dark" aria-label="Use dark mode" aria-pressed="false">
|
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
<path d="M20 15.2A8.3 8.3 0 0 1 8.8 4 8.3 8.3 0 1 0 20 15.2Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
<div>
|
|
<form class="login-card" id="login-form" novalidate>
|
|
<header>
|
|
<h2 id="login-title">Welcome back</h2>
|
|
<p>Sign in to continue to your workspace.</p>
|
|
</header>
|
|
|
|
<div class="field">
|
|
<label for="email">Email address</label>
|
|
<div class="input-wrap">
|
|
<input
|
|
id="email"
|
|
name="email"
|
|
type="email"
|
|
autocomplete="email"
|
|
placeholder="name@example.com"
|
|
required>
|
|
</div>
|
|
<p class="helper-message" id="email-error">
|
|
Enter a valid email address.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="field">
|
|
<div class="field-row">
|
|
<label for="password">Password</label>
|
|
<a href="#">Forgot password?</a>
|
|
</div>
|
|
|
|
<div class="input-wrap">
|
|
<input
|
|
class="password-input"
|
|
id="password"
|
|
name="password"
|
|
type="password"
|
|
autocomplete="current-password"
|
|
placeholder="Enter your password"
|
|
minlength="8"
|
|
required>
|
|
|
|
<button
|
|
class="show-password"
|
|
type="button"
|
|
aria-label="Show password"
|
|
aria-pressed="false">
|
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
<path d="M2.5 12s3.5-5.5 9.5-5.5 9.5 5.5 9.5 5.5-3.5 5.5-9.5 5.5S2.5 12 2.5 12Z" stroke="currentColor" stroke-width="1.7"/>
|
|
<circle cx="12" cy="12" r="2.5" stroke="currentColor" stroke-width="1.7"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
<p class="helper-message" id="password-error">
|
|
Your password must contain at least eight characters.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="form-options">
|
|
<label class="checkbox-label">
|
|
<input type="checkbox" name="remember">
|
|
Keep me signed in
|
|
</label>
|
|
</div>
|
|
|
|
<button class="primary-button" type="submit">
|
|
Sign in
|
|
</button>
|
|
|
|
<div class="divider">or continue with</div>
|
|
|
|
<button class="secondary-button" type="button">
|
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
<circle cx="12" cy="12" r="9" stroke="currentColor" stroke-width="1.7"/>
|
|
<path d="M8.5 12h7M12 8.5v7" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/>
|
|
</svg>
|
|
Single sign-on
|
|
</button>
|
|
|
|
<p class="signup-note">
|
|
New here? <a href="#">Create an account</a>
|
|
</p>
|
|
</form>
|
|
|
|
<p class="privacy-note">
|
|
By signing in, you agree to the terms and privacy policy.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
|
|
<script>
|
|
const root = document.documentElement;
|
|
const themeButtons = document.querySelectorAll("[data-theme]");
|
|
const passwordInput = document.querySelector("#password");
|
|
const passwordToggle = document.querySelector(".show-password");
|
|
const loginForm = document.querySelector("#login-form");
|
|
const emailInput = document.querySelector("#email");
|
|
const emailError = document.querySelector("#email-error");
|
|
const passwordError = document.querySelector("#password-error");
|
|
|
|
const setTheme = (theme) => {
|
|
root.dataset.theme = theme;
|
|
|
|
themeButtons.forEach((button) => {
|
|
button.setAttribute(
|
|
"aria-pressed",
|
|
String(button.dataset.theme === theme)
|
|
);
|
|
});
|
|
|
|
localStorage.setItem("calmspace-theme", theme);
|
|
};
|
|
|
|
const storedTheme = localStorage.getItem("calmspace-theme");
|
|
const preferredTheme = window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
? "dark"
|
|
: "light";
|
|
|
|
setTheme(storedTheme || preferredTheme);
|
|
|
|
themeButtons.forEach((button) => {
|
|
button.addEventListener("click", () => {
|
|
setTheme(button.dataset.theme);
|
|
});
|
|
});
|
|
|
|
passwordToggle.addEventListener("click", () => {
|
|
const isVisible = passwordInput.type === "text";
|
|
|
|
passwordInput.type = isVisible ? "password" : "text";
|
|
passwordToggle.setAttribute("aria-pressed", String(!isVisible));
|
|
passwordToggle.setAttribute(
|
|
"aria-label",
|
|
isVisible ? "Show password" : "Hide password"
|
|
);
|
|
});
|
|
|
|
loginForm.addEventListener("submit", (event) => {
|
|
event.preventDefault();
|
|
|
|
const emailInvalid = !emailInput.validity.valid;
|
|
const passwordInvalid = !passwordInput.validity.valid;
|
|
|
|
emailError.classList.toggle("visible", emailInvalid);
|
|
passwordError.classList.toggle("visible", passwordInvalid);
|
|
|
|
emailInput.setAttribute("aria-invalid", String(emailInvalid));
|
|
passwordInput.setAttribute("aria-invalid", String(passwordInvalid));
|
|
|
|
if (!emailInvalid && !passwordInvalid) {
|
|
alert("Demo only: the login form is visually complete but not connected to a backend.");
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |