839 lines
24 KiB
HTML
839 lines
24 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>Ivory & Ink + Pink — ADHD-Friendly Login Demo</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: #FAF8F3;
|
|
--page-accent: #F2ECE4;
|
|
--surface: #FFFEFB;
|
|
--surface-alt: #F8F1EA;
|
|
--surface-strong: #EDE2D7;
|
|
|
|
--text: #262320;
|
|
--muted: #6F6963;
|
|
--border: #DCCFC4;
|
|
|
|
/* Pink extension */
|
|
--primary: #D8739A;
|
|
--primary-hover: #BC5A80;
|
|
--on-primary: #FFFFFF;
|
|
|
|
/* Warm neutral secondary */
|
|
--secondary: #E7DED3;
|
|
--secondary-hover: #D9CEC1;
|
|
--on-secondary: #262320;
|
|
|
|
--accent-1: #E8A9C2; /* soft pink */
|
|
--accent-2: #8A9795; /* cool balancing grey-green */
|
|
--accent-3: #C8A97A; /* warm sand */
|
|
|
|
--danger: #B96B74;
|
|
--danger-soft: #F6E6E9;
|
|
--success: #6E816E;
|
|
--focus: #E9B0C7;
|
|
|
|
--shadow-lg: 0 28px 70px rgb(121 92 78 / 14%);
|
|
--shadow-sm: 0 12px 28px rgb(121 92 78 / 8%);
|
|
--radius-sm: .55rem;
|
|
--radius-md: .9rem;
|
|
--radius-lg: 1.5rem;
|
|
}
|
|
|
|
html[data-theme="dark"] {
|
|
color-scheme: dark;
|
|
--page: #020202;
|
|
--page-accent: #090705;
|
|
--surface: #171411;
|
|
--surface-alt: #231D1A;
|
|
--surface-strong: #35302B;
|
|
|
|
--text: #FAF6F0;
|
|
--muted: #C9C1B7;
|
|
--border: #554D46;
|
|
|
|
/* Pink extension for dark mode */
|
|
--primary: #EB97B7;
|
|
--primary-hover: #D97DA1;
|
|
--on-primary: #31141F;
|
|
|
|
--secondary: #4F4840;
|
|
--secondary-hover: #655D54;
|
|
--on-secondary: #FAF6F0;
|
|
|
|
--accent-1: #F0BFD2;
|
|
--accent-2: #92A19D;
|
|
--accent-3: #CFB27F;
|
|
|
|
--danger: #DA98A0;
|
|
--danger-soft: #412D32;
|
|
--success: #9CAE99;
|
|
--focus: #F1C5D7;
|
|
|
|
--shadow-lg: 0 38px 96px rgb(0 0 0 / 58%);
|
|
--shadow-sm: 0 16px 38px rgb(0 0 0 / 42%);
|
|
}
|
|
|
|
* { 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 14% 12%, rgb(232 169 194 / 18%), transparent 28%),
|
|
radial-gradient(circle at 88% 16%, rgb(138 151 149 / 15%), transparent 26%),
|
|
linear-gradient(145deg, var(--page), var(--page-accent));
|
|
}
|
|
|
|
button, input { font: inherit; }
|
|
a {
|
|
color: var(--primary);
|
|
text-decoration-thickness: .08em;
|
|
text-underline-offset: .18em;
|
|
}
|
|
a:hover { color: var(--primary-hover); }
|
|
|
|
: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, .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: #FFFDF9;
|
|
background:
|
|
radial-gradient(circle at 82% 18%, rgb(232 169 194 / 18%), transparent 30%),
|
|
radial-gradient(circle at 18% 82%, rgb(138 151 149 / 18%), transparent 34%),
|
|
linear-gradient(150deg, #3E352E, #5F5348);
|
|
}
|
|
|
|
.visual-panel::before,
|
|
.visual-panel::after {
|
|
content: "";
|
|
position: absolute;
|
|
border-radius: 999px;
|
|
opacity: .9;
|
|
filter: blur(2px);
|
|
}
|
|
|
|
.visual-panel::before {
|
|
width: 24rem;
|
|
height: 24rem;
|
|
top: -8rem;
|
|
right: -8rem;
|
|
background: rgb(232 169 194 / 18%);
|
|
}
|
|
|
|
.visual-panel::after {
|
|
width: 18rem;
|
|
height: 18rem;
|
|
left: -7rem;
|
|
bottom: -6rem;
|
|
background: rgb(138 151 149 / 18%);
|
|
}
|
|
|
|
.brand, .hero-copy, .trust-row {
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
|
|
.brand {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: .8rem;
|
|
font-family: var(--font-ui);
|
|
font-weight: 700;
|
|
letter-spacing: -.02em;
|
|
}
|
|
|
|
.brand-mark {
|
|
display: grid;
|
|
place-items: center;
|
|
width: 2.7rem;
|
|
aspect-ratio: 1;
|
|
border: 1px solid rgb(255 253 249 / 28%);
|
|
border-radius: .85rem;
|
|
background: rgb(255 253 249 / 9%);
|
|
backdrop-filter: blur(10px);
|
|
box-shadow: inset 0 1px 0 rgb(255 253 249 / 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 .8rem;
|
|
color: #F4D2E0;
|
|
font-family: var(--font-ui);
|
|
font-size: .84rem;
|
|
font-weight: 700;
|
|
letter-spacing: .11em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
h1, h2, h3 {
|
|
margin: 0;
|
|
font-family: var(--font-ui);
|
|
line-height: 1.14;
|
|
letter-spacing: -.035em;
|
|
}
|
|
|
|
.hero-copy h1 {
|
|
max-width: 12ch;
|
|
font-size: clamp(2.7rem, 6vw, 5.3rem);
|
|
}
|
|
|
|
.hero-copy p {
|
|
max-width: 34rem;
|
|
margin: 1.4rem 0 0;
|
|
color: rgb(255 253 249 / 84%);
|
|
font-size: 1.08rem;
|
|
}
|
|
|
|
.feature-list {
|
|
display: grid;
|
|
gap: .8rem;
|
|
margin: 2rem 0 0;
|
|
padding: 0;
|
|
list-style: none;
|
|
}
|
|
|
|
.feature-list li {
|
|
display: flex;
|
|
gap: .7rem;
|
|
align-items: flex-start;
|
|
color: rgb(255 253 249 / 92%);
|
|
}
|
|
|
|
.feature-list svg {
|
|
flex: 0 0 auto;
|
|
width: 1.1rem;
|
|
margin-top: .23rem;
|
|
}
|
|
|
|
.feature-list li:nth-child(1) svg { color: var(--accent-1); }
|
|
.feature-list li:nth-child(2) svg { color: var(--accent-2); }
|
|
.feature-list li:nth-child(3) svg { color: var(--accent-3); }
|
|
|
|
.trust-row {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: .75rem;
|
|
color: rgb(255 253 249 / 78%);
|
|
font-size: .86rem;
|
|
}
|
|
|
|
.trust-pill {
|
|
padding: .35rem .62rem;
|
|
border: 1px solid rgb(255 253 249 / 18%);
|
|
border-radius: 999px;
|
|
background: rgb(255 253 249 / 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(--page-accent) 74%, transparent);
|
|
backdrop-filter: blur(14px);
|
|
}
|
|
|
|
.theme-toggle {
|
|
position: absolute;
|
|
top: 1.3rem;
|
|
right: 1.3rem;
|
|
display: inline-flex;
|
|
gap: .35rem;
|
|
padding: .32rem;
|
|
border: 1px solid var(--border);
|
|
border-radius: 999px;
|
|
background: color-mix(in srgb, var(--surface) 90%, 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 {
|
|
position: relative;
|
|
overflow: hidden;
|
|
width: min(100%, 28rem);
|
|
padding: clamp(1.35rem, 4vw, 2.35rem);
|
|
background: color-mix(in srgb, var(--surface) 98%, transparent);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-lg);
|
|
box-shadow: var(--shadow-lg);
|
|
}
|
|
|
|
.login-card::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0 0 auto;
|
|
height: .28rem;
|
|
background: linear-gradient(90deg, var(--primary), var(--accent-1), var(--accent-2), var(--accent-3));
|
|
}
|
|
|
|
.login-card header { margin-bottom: 1.8rem; }
|
|
|
|
.login-kicker {
|
|
display: inline-flex;
|
|
gap: .5rem;
|
|
align-items: center;
|
|
margin-bottom: .7rem;
|
|
color: var(--muted);
|
|
font-family: var(--font-ui);
|
|
font-size: .78rem;
|
|
font-weight: 700;
|
|
letter-spacing: .08em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.secure-dot {
|
|
width: .52rem;
|
|
height: .52rem;
|
|
border-radius: 999px;
|
|
background: var(--primary);
|
|
box-shadow: 0 0 0 4px color-mix(in srgb, var(--primary) 14%, transparent);
|
|
}
|
|
|
|
.login-card h2 { font-size: clamp(1.8rem, 4vw, 2.35rem); }
|
|
|
|
.login-card header p {
|
|
margin: .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: .42rem;
|
|
}
|
|
|
|
label {
|
|
font-family: var(--font-ui);
|
|
font-size: .93rem;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.field-row a { font-size: .88rem; }
|
|
.input-wrap { position: relative; }
|
|
|
|
input[type="email"],
|
|
input[type="password"],
|
|
input[type="text"] {
|
|
width: 100%;
|
|
min-height: 3.15rem;
|
|
padding: .78rem .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: .82; }
|
|
|
|
input:hover { border-color: color-mix(in srgb, var(--border) 55%, var(--primary)); }
|
|
|
|
input:focus {
|
|
border-color: var(--primary);
|
|
background: var(--surface);
|
|
box-shadow: 0 0 0 4px color-mix(in srgb, var(--focus) 24%, transparent);
|
|
outline: none;
|
|
}
|
|
|
|
.password-input { padding-right: 3.1rem; }
|
|
|
|
.show-password {
|
|
position: absolute;
|
|
inset: 50% .55rem auto auto;
|
|
display: grid;
|
|
place-items: center;
|
|
width: 2.2rem;
|
|
aspect-ratio: 1;
|
|
padding: 0;
|
|
color: var(--muted);
|
|
border: 0;
|
|
border-radius: .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: .2rem 0 1.25rem;
|
|
}
|
|
|
|
.checkbox-label {
|
|
display: inline-flex;
|
|
gap: .55rem;
|
|
align-items: center;
|
|
color: var(--muted);
|
|
font-family: var(--font-body);
|
|
font-size: .94rem;
|
|
font-weight: 400;
|
|
cursor: pointer;
|
|
}
|
|
|
|
input[type="checkbox"] {
|
|
width: 1.05rem;
|
|
height: 1.05rem;
|
|
margin: 0;
|
|
accent-color: var(--primary);
|
|
}
|
|
|
|
.primary-button {
|
|
width: 100%;
|
|
min-height: 3.15rem;
|
|
padding: .8rem 1rem;
|
|
color: var(--on-primary);
|
|
background: var(--primary);
|
|
border: 1px solid var(--primary);
|
|
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(--primary) 22%, transparent);
|
|
}
|
|
|
|
.primary-button:hover {
|
|
background: var(--primary-hover);
|
|
transform: translateY(-1px);
|
|
}
|
|
|
|
.divider {
|
|
display: grid;
|
|
grid-template-columns: 1fr auto 1fr;
|
|
gap: .8rem;
|
|
align-items: center;
|
|
margin: 1.3rem 0;
|
|
color: var(--muted);
|
|
font-size: .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: .7rem;
|
|
align-items: center;
|
|
padding: .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: .94rem;
|
|
}
|
|
|
|
.helper-message {
|
|
display: none;
|
|
margin: .5rem 0 0;
|
|
padding: .58rem .7rem;
|
|
color: var(--danger);
|
|
background: var(--danger-soft);
|
|
border-left: .3rem solid var(--danger);
|
|
border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
|
|
font-size: .87rem;
|
|
}
|
|
|
|
.helper-message.visible { display: block; }
|
|
|
|
.privacy-note {
|
|
width: min(100%, 28rem);
|
|
margin: 1rem auto 0;
|
|
color: var(--muted);
|
|
font-size: .82rem;
|
|
text-align: center;
|
|
}
|
|
|
|
.sample-card {
|
|
width: min(100%, 28rem);
|
|
margin: 1rem auto 0;
|
|
padding: 1.25rem 1.3rem;
|
|
color: var(--text);
|
|
background: color-mix(in srgb, var(--surface) 96%, transparent);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-md);
|
|
box-shadow: var(--shadow-sm);
|
|
}
|
|
|
|
.sample-card__eyebrow {
|
|
margin: 0 0 0.45rem;
|
|
color: var(--primary);
|
|
font-family: var(--font-ui);
|
|
font-size: 0.76rem;
|
|
font-weight: 700;
|
|
letter-spacing: 0.09em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.sample-card h3 {
|
|
margin: 0;
|
|
color: var(--text);
|
|
font-family: var(--font-ui);
|
|
font-size: 1.25rem;
|
|
line-height: 1.22;
|
|
letter-spacing: -0.02em;
|
|
}
|
|
|
|
.sample-card__subheading {
|
|
margin: 0.38rem 0 0;
|
|
color: var(--muted);
|
|
font-family: var(--font-ui);
|
|
font-size: 0.94rem;
|
|
font-weight: 500;
|
|
line-height: 1.45;
|
|
}
|
|
|
|
.sample-card__body {
|
|
margin: 0.9rem 0 0;
|
|
color: var(--text);
|
|
font-family: var(--font-body);
|
|
font-size: 1rem;
|
|
line-height: 1.68;
|
|
}
|
|
|
|
.sample-card__footer {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
gap: 1rem;
|
|
align-items: center;
|
|
margin-top: 1rem;
|
|
padding-top: 0.85rem;
|
|
border-top: 1px solid var(--border);
|
|
color: var(--muted);
|
|
font-size: 0.82rem;
|
|
}
|
|
|
|
.sample-card__badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
padding: 0.25rem 0.5rem;
|
|
color: var(--on-secondary);
|
|
background: var(--secondary);
|
|
border-radius: 999px;
|
|
font-family: var(--font-ui);
|
|
font-size: 0.72rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
@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: .7rem; }
|
|
.sample-card__footer { flex-direction: column; align-items: flex-start; }
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
*, *::before, *::after {
|
|
animation-duration: .01ms !important;
|
|
animation-iteration-count: 1 !important;
|
|
scroll-behavior: auto !important;
|
|
transition-duration: .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>Paper Rose</span>
|
|
</div>
|
|
|
|
<div class="hero-copy">
|
|
<p class="eyebrow">Ivory & Ink + Pink</p>
|
|
<h1 id="welcome-title">Soft warmth. Clear focus.</h1>
|
|
<p>
|
|
This version keeps the warm ivory-and-ink foundation but extends it
|
|
with a polished pink for primary actions, emphasis and a touch of personality.
|
|
</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>
|
|
Warm neutral surfaces with one clear pink action colour
|
|
</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>
|
|
Balanced by grey-green and soft sand supporting accents
|
|
</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>
|
|
Lexend and Atkinson Hyperlegible through the Google Fonts CSS API
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="trust-row" aria-label="Product qualities">
|
|
<span class="trust-pill">Editorial calm</span>
|
|
<span class="trust-pill">Readable</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>
|
|
<div class="login-kicker">
|
|
<span class="secure-dot" aria-hidden="true"></span>
|
|
Secure sign-in
|
|
</div>
|
|
<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>
|
|
|
|
<article class="sample-card" aria-labelledby="sample-card-title">
|
|
<p class="sample-card__eyebrow">Typography sample</p>
|
|
<h3 id="sample-card-title">A warm editorial card heading</h3>
|
|
<p class="sample-card__subheading">
|
|
A concise subheading demonstrates Lexend in a refined ivory-and-pink interface.
|
|
</p>
|
|
<p class="sample-card__body">
|
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere,
|
|
neque vitae facilisis luctus, justo sapien posuere lorem, sed cursus mauris
|
|
erat vel sem. Donec vitae lectus at mi tincidunt suscipit.
|
|
</p>
|
|
<footer class="sample-card__footer">
|
|
<span>Atkinson Hyperlegible body text</span>
|
|
<span class="sample-card__badge">Lexend UI</span>
|
|
</footer>
|
|
</article>
|
|
</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 storageKey = "ivory-ink-pink-theme";
|
|
|
|
const setTheme = (theme) => {
|
|
root.dataset.theme = theme;
|
|
themeButtons.forEach((button) => {
|
|
button.setAttribute("aria-pressed", String(button.dataset.theme === theme));
|
|
});
|
|
localStorage.setItem(storageKey, theme);
|
|
};
|
|
|
|
const storedTheme = localStorage.getItem(storageKey);
|
|
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: this login form is not connected to a backend.");
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|