/* Dark registration forms. Borders are lightened to keep 3:1 against the card, text stays above 4.5:1, and the
accent only marks focus and the main action. The eye button only appears once the script runs. */
.dk{--dk-bg:#111722;--dk-field:#0b1019;--dk-ink:#e8edf5;--dk-muted:#9aa4b5;--dk-line:#6b7588;--dk-rule:#232c3b;--dk-accent:#a3e635;--dk-accent-ink:#0b1019;
--dk-ring:rgba(163,230,53,.28);--dk-error:#f87171;
background:var(--dk-bg);color:var(--dk-ink);border:1px solid var(--dk-rule);border-radius:20px;padding:32px 30px 28px;font-size:.92rem;line-height:1.45;
box-shadow:0 24px 50px -24px rgba(0,0,0,.7),inset 0 1px 0 rgba(255,255,255,.04)}
.dk--violet{--dk-accent:#a78bfa;--dk-ring:rgba(167,139,250,.3)}
.dk-brand{display:flex;align-items:center;gap:10px;font-weight:700;margin-bottom:20px}
.dk-mark{width:32px;height:32px;border-radius:9px;background:var(--dk-accent);color:var(--dk-accent-ink);display:grid;place-items:center}
.dk-title{font-size:1.4rem;font-weight:750;letter-spacing:-.02em;line-height:1.2}
.dk-sub{color:var(--dk-muted);margin:6px 0 20px}
.dk-req{color:var(--dk-accent);font-weight:700}
.dk-field{margin-bottom:16px;min-width:0}
.dk-label{display:block;font-size:.84rem;font-weight:600;margin-bottom:6px}
.dk-input{display:block;width:100%;min-width:0;font:inherit;color:var(--dk-ink);background:var(--dk-field);border:1px solid var(--dk-line);border-radius:10px;padding:11px 13px;
transition:border-color .15s,box-shadow .15s}
.dk-input:focus{outline:none;border-color:var(--dk-accent);box-shadow:0 0 0 3px var(--dk-ring)}
.dk-input:user-invalid{border-color:var(--dk-error)}
.dk-hint{font-size:.8rem;color:var(--dk-muted);margin-top:6px}
/* joined groups: fixed prefix + input, input + eye button */
.dk-group{display:flex;background:var(--dk-field);border:1px solid var(--dk-line);border-radius:10px;transition:border-color .15s,box-shadow .15s}
.dk-group:focus-within{border-color:var(--dk-accent);box-shadow:0 0 0 3px var(--dk-ring)}
.dk-group:has(:user-invalid){border-color:var(--dk-error)}
.dk-group .dk-input,.dk-group .dk-input:focus{flex:1;border:0;box-shadow:none;background:transparent}
.dk-prefix{display:flex;align-items:center;padding:0 0 0 13px;color:var(--dk-muted);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.84rem}
.dk-prefix+.dk-input{padding-left:2px}
.dk-eye{flex:none;width:46px;border:0;background:none;color:var(--dk-muted);cursor:pointer;border-radius:0 10px 10px 0;display:grid;place-items:center}
.dk-eye:hover{color:var(--dk-ink)}
.dk-eye:focus-visible{outline:2px solid var(--dk-accent);outline-offset:-5px;border-radius:8px}
.dk-eye[hidden],.dk-eye[aria-pressed="true"] .dk-show,.dk-eye[aria-pressed="false"] .dk-hide{display:none}
/* plan picker: two radio cards */
.dk-plans{border:0;margin:4px 0 18px;min-width:0}
.dk-plans legend{font-size:.84rem;font-weight:600;margin-bottom:8px}
.dk-plan-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.dk-plan{display:flex;gap:10px;align-items:flex-start;padding:12px;border:1px solid var(--dk-line);border-radius:12px;cursor:pointer;transition:border-color .15s,background-color .15s}
.dk-plan:has(:checked){border-color:var(--dk-accent);background:rgba(163,230,53,.07)}
.dk-plan b{display:block;font-weight:650}
.dk-plan small{font-size:.78rem;color:var(--dk-muted)}
.dk-radio,.dk-box{appearance:none;flex:none;width:18px;height:18px;margin-top:1px;border:1.5px solid var(--dk-line);background:var(--dk-field) center/12px no-repeat;cursor:pointer;
transition:border-color .15s,background-color .15s}
.dk-radio{border-radius:50%}
.dk-radio:checked{border:5px solid var(--dk-accent);background-color:var(--dk-accent-ink)}
.dk-box{border-radius:5px}
.dk-box:checked{background-color:var(--dk-accent);border-color:var(--dk-accent);
background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.5l3 3 6-7' fill='none' stroke='%230b1019' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")}
.dk-radio:focus-visible,.dk-box:focus-visible{outline:2px solid var(--dk-accent);outline-offset:2px}
.dk-check{display:flex;gap:10px;align-items:flex-start;font-size:.86rem;margin:2px 0 18px;cursor:pointer}
.dk-code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.18em;text-transform:uppercase}
.dk-btn{display:block;width:100%;font:inherit;font-weight:700;color:var(--dk-accent-ink);background:var(--dk-accent);border:0;border-radius:10px;padding:12px 16px;cursor:pointer;
box-shadow:0 0 0 1px rgba(255,255,255,.06),0 8px 24px -8px var(--dk-ring);transition:filter .15s,box-shadow .15s}
.dk-btn:hover{filter:brightness(1.08);box-shadow:0 0 0 1px rgba(255,255,255,.08),0 10px 30px -6px var(--dk-ring)}
.dk-btn:focus-visible{outline:2px solid var(--dk-accent);outline-offset:3px}
.dk a{color:var(--dk-accent);text-decoration:underline;text-underline-offset:2px}
.dk a:focus-visible{outline:2px solid var(--dk-accent);outline-offset:2px;border-radius:3px}
.dk-foot{margin-top:16px;text-align:center;color:var(--dk-muted);font-size:.86rem}
@media (max-width:575px){.dk-plan-grid{grid-template-columns:1fr}}
@media (max-width:420px){.dk{padding:26px 20px 22px}}
@media (prefers-reduced-motion:reduce){.dk-input,.dk-group,.dk-plan,.dk-radio,.dk-box,.dk-btn{transition:none}}
JavaScript
// Show/hide password. The button stays hidden without the script; everything else is the browser's own validation.
document.querySelectorAll('[data-pw-toggle]').forEach(function (btn) {
var input = document.getElementById(btn.getAttribute('aria-controls'));
btn.hidden = false;
btn.addEventListener('click', function () {
var show = input.type === 'password';
input.type = show ? 'text' : 'password';
btn.setAttribute('aria-pressed', show ? 'true' : 'false');
});
});
// Show/hide password. The button stays hidden without the script; everything else is the browser's own validation.
document.querySelectorAll('[data-pw-toggle]').forEach(function (btn) {
var input = document.getElementById(btn.getAttribute('aria-controls'));
btn.hidden = false;
btn.addEventListener('click', function () {
var show = input.type === 'password';
input.type = show ? 'text' : 'password';
btn.setAttribute('aria-pressed', show ? 'true' : 'false');
});
});
// Show/hide password. The button stays hidden without the script; everything else is the browser's own validation.
document.querySelectorAll('[data-pw-toggle]').forEach(function (btn) {
var input = document.getElementById(btn.getAttribute('aria-controls'));
btn.hidden = false;
btn.addEventListener('click', function () {
var show = input.type === 'password';
input.type = show ? 'text' : 'password';
btn.setAttribute('aria-pressed', show ? 'true' : 'false');
});
});
About this set
Two registration forms for dark interfaces such as developer tools and members’ communities. Developer sign-up has a lime accent: email, a username field with a fixed relay.dev/ prefix drawn inside the same box and a pattern that allows lowercase letters, numbers and hyphens, a password with a show and hide button, and a plan picker of two radio cards for a free and a paid tier. Invite-only registration has a violet accent and starts with an invite code field in spaced monospace capitals that must match four characters, a hyphen and four more, then a display name, email, password and a member directory checkbox. Use the first for SaaS and developer products, the second for private communities, betas and anything behind an invite. Dark forms fail when borders vanish and grey text sinks, so field borders are lightened to stay at 3:1 against the card, muted text stays above 4.5:1, and the accent is kept for focus rings, checked states and the main button, which carries a soft glow. The Bootstrap version switches the card into Bootstrap’s own dark colour mode with data-bs-theme=”dark”. JavaScript is used only for the show password button.
What’s included
Prefixed username field built as one bordered group
Invite code field with a pattern and monospace letter spacing
Plan picker radio cards highlighted with :has(:checked)
Borders and muted text tuned for contrast on a dark card
Bootstrap version uses data-bs-theme="dark", .input-group-text and .form-check-input
Accessibility
Every field has a visible label and an autocomplete value (email, username, nickname, new-password); the invite code turns autocomplete and spellcheck off. Hints such as the username rules are linked with aria-describedby, and the decorative prefix is aria-hidden because the hint spells it out. The plan choice is a fieldset with a legend, the password toggle uses aria-pressed, focus rings use the accent colour, and transitions switch off under prefers-reduced-motion.
Customise it
Change --dk-accent and --dk-ring on .dk for the accent (.dk--violet is the second palette) and --dk-bg, --dk-field and --dk-line for the surfaces. In Bootstrap the same variables feed --bs-card-bg and --bs-border-color; in Tailwind edit the dk-* theme colours and the [--dk-accent:…] properties.