Open demo

CSS code

HTML
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
  <symbol id="neu-i-search" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="6.5"/><path d="m16 16 4.5 4.5"/></symbol>
  <symbol id="neu-i-chevDown" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></symbol>
  <symbol id="neu-i-alert" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 4 2.8 19.5h18.4z"/><path d="M12 10v4.5M12 17.2h.01"/></symbol>
  <symbol id="neu-i-home" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 10.5 12 4l8 6.5V20h-5.5v-6h-5v6H4z"/></symbol>
  <symbol id="neu-i-mail" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="5.5" width="17" height="13" rx="2"/><path d="m4 7 8 6 8-6"/></symbol>
  <symbol id="neu-i-lock" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="10.5" width="14" height="10" rx="2"/><path d="M8 10.5V7.5a4 4 0 0 1 8 0v3"/></symbol>
  <symbol id="neu-i-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2.5v2M12 19.5v2M4.6 4.6 6 6M18 18l1.4 1.4M2.5 12h2M19.5 12h2M4.6 19.4 6 18M18 6l1.4-1.4"/></symbol>
</svg>
<div class="cols">
<div class="stack">
<section><span class="lbl">Text fields · default, with icon, with an error</span><div class="neu-stack-f"><div class="neu-field"><label class="neu-label" for="f-name">Full name</label><input class="neu-input" id="f-name" type="text" value="Ada Okafor" autocomplete="name"></div>
<div class="neu-field"><label class="neu-label" for="f-search">Find a device</label><div class="neu-control neu-control--icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-search"/></svg><input class="neu-input" id="f-search" type="search" placeholder="Lamp, lock, speaker…" aria-describedby="f-search-help"></div><p class="neu-help" id="f-search-help">14 devices in 5 rooms</p></div>
<div class="neu-field"><label class="neu-label" for="f-email">Email for alerts</label><input class="neu-input" id="f-email" type="email" value="ada@okafor" aria-invalid="true" aria-describedby="f-email-err" autocomplete="email"><p class="neu-help neu-help--error" id="f-email-err"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-alert"/></svg>Enter an address like [email protected]</p></div></div></section>
<section><span class="lbl">Select and range</span><div class="pair"><div class="neu-field"><label class="neu-label" for="f-room">Default room</label><div class="neu-control neu-control--select"><select class="neu-select" id="f-room"><option>Living room</option><option selected>Kitchen</option><option>Bedroom</option><option>Office</option><option>Garden</option></select><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-chevDown"/></svg></div></div>
<div class="neu-field"><div class="neu-range-head"><label class="neu-label" for="rg-bright">Brightness</label><output for="rg-bright">70%</output></div><input class="neu-range" id="rg-bright" type="range" min="0" max="100" value="70" style="--val:70%" data-neu-range><div class="neu-range-ends" aria-hidden="true"><span>Dim</span><span>Bright</span></div></div></div></section>
<section><span class="lbl">Checkboxes and radios</span><div class="pair"><fieldset class="neu-fieldset"><legend class="neu-legend">Notify me about</legend><div class="neu-choices"><label class="neu-check"><input class="neu-sr" type="checkbox" name="notify" checked><span class="neu-check__box" aria-hidden="true"></span>Doors left unlocked</label><label class="neu-check"><input class="neu-sr" type="checkbox" name="notify" checked><span class="neu-check__box" aria-hidden="true"></span>Water leaks</label><label class="neu-check"><input class="neu-sr" type="checkbox" name="notify"><span class="neu-check__box" aria-hidden="true"></span>Daily energy summary</label></div></fieldset>
<fieldset class="neu-fieldset"><legend class="neu-legend">Heating mode</legend><div class="neu-choices"><label class="neu-check"><input class="neu-sr" type="radio" name="mode" value="comfort" checked><span class="neu-check__box neu-check__box--radio" aria-hidden="true"></span>Comfort</label><label class="neu-check"><input class="neu-sr" type="radio" name="mode" value="eco"><span class="neu-check__box neu-check__box--radio" aria-hidden="true"></span>Eco</label><label class="neu-check"><input class="neu-sr" type="radio" name="mode" value="away"><span class="neu-check__box neu-check__box--radio" aria-hidden="true"></span>Away</label></div></fieldset></div></section>
</div>
<section><span class="lbl">Login card</span><form class="neu-card neu-login" action="#" aria-labelledby="login-title">
<span class="neu-login__logo"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-home"/></svg></span>
<h2 class="neu-login__title" id="login-title">Welcome home</h2>
<p class="neu-login__sub">Sign in to Hearth to control your rooms.</p>
<div class="neu-field"><label class="neu-label" for="l-email">Email</label><div class="neu-control neu-control--icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-mail"/></svg><input class="neu-input" id="l-email" type="email" placeholder="[email protected]" autocomplete="email" required></div></div>
<div class="neu-field"><label class="neu-label" for="l-pass">Password</label><div class="neu-control neu-control--icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-lock"/></svg><input class="neu-input" id="l-pass" type="password" autocomplete="current-password" required></div></div>
<div class="neu-login__row"><label class="neu-check"><input class="neu-sr" type="checkbox" name="remember" checked><span class="neu-check__box" aria-hidden="true"></span>Keep me signed in</label><a class="neu-link" href="#">Forgot password?</a></div>
<button class="neu-btn neu-btn--accent neu-btn--block" type="submit">Sign in</button>
<p class="neu-login__foot">New to Hearth? <a class="neu-link" href="#">Create an account</a></p>
</form></section>
</div>
CSS
/* ── Neumorphism UI kit tokens (uiCookies) — identical in every set ──────────────
   Every component is moulded from --neu-bg and lit from the top left. Change a token and
   the whole kit follows; the shadow recipes below are built from these values. */
:root{
  --neu-bg:#e0e5ec;          /* the one surface colour */
  --neu-light:#ffffff;       /* highlight, top left */
  --neu-dark:#a3b1c6;        /* shade, bottom right */
  --neu-distance:6px;        /* how far a shape rises */
  --neu-blur:14px;           /* how soft its shadow is */
  --neu-radius:18px;         /* cards; buttons use .75 of it, fields .6 */
  --neu-accent:#4f46e5;      /* focus ring and on / selected / current states, 4.9:1 on --neu-bg */
  --neu-on-accent:#ffffff;   /* text and marks on accent fills, 6.3:1 */
  --neu-ink:#1f2937;         /* text, 11.6:1 */
  --neu-muted:#4a5568;       /* secondary text, 5.9:1 */
  --neu-edge:#74819a;        /* control boundary (fields, tracks, boxes, buttons), 3.1:1 */
  --neu-line:rgba(255,255,255,.6); /* decorative edge on cards and panels */
  --neu-bw:1px;              /* control border width */
  --neu-success:#126b35;--neu-warning:#8a5300;--neu-danger:#b42318;
}
/* Dark neumorphism: data-neu="dark" on any wrapper, or a checked .neu-theme-input inside a [data-neu] element.
   :is() is a forgiving list, so browsers without :has() still apply data-neu="dark" */
[data-neu]:is([data-neu="dark"],:has(.neu-theme-input:checked)){
  --neu-bg:#262b33;--neu-light:#323944;--neu-dark:#14171c;
  --neu-accent:#8f88ff;--neu-on-accent:#14161b;--neu-ink:#e7ebf2;--neu-muted:#aab4c3;--neu-edge:#717d90;
  --neu-line:rgba(255,255,255,.06);--neu-success:#6fdc9a;--neu-warning:#f3c164;--neu-danger:#ff8f84;color-scheme:dark}
/* More contrast requested: the soft shadows go, every control and panel gets a solid outline */
@media (prefers-contrast:more){:root,[data-neu]:is([data-neu],:has(.neu-theme-input:checked)){
  --neu-light:transparent;--neu-dark:transparent;--neu-edge:var(--neu-ink);--neu-line:var(--neu-ink);--neu-muted:var(--neu-ink);--neu-bw:2px}}
:root,[data-neu]{
  --neu-raised:var(--neu-distance) var(--neu-distance) var(--neu-blur) var(--neu-dark),calc(var(--neu-distance)*-1) calc(var(--neu-distance)*-1) var(--neu-blur) var(--neu-light);
  --neu-raised-sm:calc(var(--neu-distance)*.5) calc(var(--neu-distance)*.5) calc(var(--neu-blur)*.5) var(--neu-dark),calc(var(--neu-distance)*-.5) calc(var(--neu-distance)*-.5) calc(var(--neu-blur)*.5) var(--neu-light);
  --neu-inset:inset calc(var(--neu-distance)*.6) calc(var(--neu-distance)*.6) calc(var(--neu-blur)*.6) var(--neu-dark),inset calc(var(--neu-distance)*-.6) calc(var(--neu-distance)*-.6) calc(var(--neu-blur)*.6) var(--neu-light);
  --neu-inset-sm:inset calc(var(--neu-distance)*.35) calc(var(--neu-distance)*.35) calc(var(--neu-blur)*.35) var(--neu-dark),inset calc(var(--neu-distance)*-.35) calc(var(--neu-distance)*-.35) calc(var(--neu-blur)*.35) var(--neu-light);
}
[data-neu]{background:var(--neu-bg);color:var(--neu-ink)}
/* Components */
:where([class*="neu-"]),:where([class*="neu-"])::before,:where([class*="neu-"])::after{box-sizing:border-box}
.neu-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.neu-ico{width:20px;height:20px;flex:none}
/* Buttons: raised by default, pressed (inset) while held, accent ring on keyboard focus */
.neu-btn{display:inline-flex;align-items:center;justify-content:center;gap:.55rem;min-height:46px;padding:.65rem 1.35rem;
  border:var(--neu-bw) solid var(--neu-edge);border-radius:calc(var(--neu-radius)*.75);background:var(--neu-bg);color:var(--neu-ink);
  font-family:inherit;font-size:.95rem;font-weight:600;line-height:1.2;text-decoration:none;cursor:pointer;
  box-shadow:var(--neu-raised-sm);transition:box-shadow .2s,color .2s,background-color .2s}
.neu-btn:hover{box-shadow:var(--neu-raised)}
.neu-btn:active{box-shadow:var(--neu-inset-sm)}
.neu-btn:focus-visible{outline:3px solid var(--neu-accent);outline-offset:3px}
.neu-btn--accent{background:var(--neu-accent);border-color:var(--neu-accent);color:var(--neu-on-accent)}
.neu-btn--sm{min-height:38px;padding:.45rem 1rem;font-size:.85rem}
.neu-btn--block{width:100%}
.neu-btn--icon{width:50px;height:50px;min-height:0;padding:0;border-radius:50%}
.neu-btn--square{border-radius:calc(var(--neu-radius)*.75)}
.neu-btn--icon-sm{width:42px;height:42px}
.neu-btn--icon-lg{width:64px;height:64px}
.neu-btn--icon .neu-ico{width:22px;height:22px}
/* Card: a raised panel with a faint highlight edge (a solid outline under prefers-contrast: more) */
.neu-card{padding:1.5rem;border:var(--neu-bw) solid var(--neu-line);border-radius:var(--neu-radius);background:var(--neu-bg);color:var(--neu-ink);box-shadow:var(--neu-raised)}
.neu-card h2,.neu-card h3,.neu-card p{margin:0}
/* Fields: pressed-in wells with a 3:1 edge. Focus adds the accent ring; errors add a red edge AND a message with an icon */
.neu-field{display:grid;gap:.45rem;min-width:0}
.neu-label{font-size:.88rem;font-weight:600;color:var(--neu-ink)}
.neu-input,.neu-select{display:block;width:100%;min-height:48px;margin:0;padding:.7rem 1rem;border:var(--neu-bw) solid var(--neu-edge);
  border-radius:calc(var(--neu-radius)*.6);background:var(--neu-bg);color:var(--neu-ink);font-family:inherit;font-size:1rem;line-height:1.4;box-shadow:var(--neu-inset-sm)}
.neu-input::placeholder{color:var(--neu-muted);opacity:1}
.neu-input:focus,.neu-select:focus{outline:3px solid var(--neu-accent);outline-offset:2px}
.neu-input[aria-invalid="true"]{border-color:var(--neu-danger);border-width:2px}
.neu-help{margin:0;font-size:.82rem;color:var(--neu-muted)}
.neu-help--error{display:flex;align-items:center;gap:.4rem;font-weight:600;color:var(--neu-danger)}
.neu-help .neu-ico{width:16px;height:16px}
.neu-control{position:relative}
.neu-control>.neu-ico{position:absolute;top:50%;left:1rem;margin-top:-10px;color:var(--neu-muted);pointer-events:none}
.neu-control--icon .neu-input{padding-left:2.9rem}
.neu-control--select>.neu-ico{left:auto;right:1rem}
.neu-select{appearance:none;padding-right:2.9rem;cursor:pointer}
/* Checkboxes and radios: a pressed-in box that pops out, fills with accent and shows a tick or dot when chosen */
.neu-fieldset{min-width:0;margin:0;padding:0;border:0}
.neu-legend{margin-bottom:.8rem;padding:0;font-size:.88rem;font-weight:600}
.neu-choices{display:grid;gap:.7rem}
.neu-check{position:relative;display:flex;align-items:center;gap:.75rem;min-height:32px;cursor:pointer}
.neu-check__box{position:relative;flex:none;width:24px;height:24px;border:var(--neu-bw) solid var(--neu-edge);border-radius:7px;background:var(--neu-bg);box-shadow:var(--neu-inset-sm);transition:background-color .2s,box-shadow .2s}
.neu-check__box::after{content:"";position:absolute;left:7px;top:3px;width:7px;height:12px;border:solid var(--neu-on-accent);border-width:0 2.5px 2.5px 0;transform:rotate(45deg);opacity:0}
.neu-check__box--radio{border-radius:50%}
.neu-check__box--radio::after{left:50%;top:50%;width:10px;height:10px;margin:-5px 0 0 -5px;border:0;border-radius:50%;background:var(--neu-on-accent);transform:none}
.neu-check input:checked+.neu-check__box{border-color:var(--neu-accent);background:var(--neu-accent);box-shadow:var(--neu-raised-sm)}
.neu-check input:checked+.neu-check__box::after{opacity:1}
.neu-check input:focus-visible+.neu-check__box{outline:3px solid var(--neu-accent);outline-offset:3px}
/* Range: a pressed groove with an accent fill and a raised thumb. Firefox fills natively; WebKit reads --val from the script */
.neu-range-head{display:flex;justify-content:space-between;align-items:baseline}
.neu-range-head output{font-weight:700;font-variant-numeric:tabular-nums;color:var(--neu-accent)}
.neu-range{--val:50%;width:100%;height:30px;margin:0;background:transparent;-webkit-appearance:none;appearance:none;cursor:pointer}
.neu-range::-webkit-slider-runnable-track{box-sizing:border-box;height:14px;border:var(--neu-bw) solid var(--neu-edge);border-radius:999px;box-shadow:var(--neu-inset-sm);
  background:linear-gradient(var(--neu-accent),var(--neu-accent)) 0 0/var(--val) 100% no-repeat,var(--neu-bg)}
.neu-range::-webkit-slider-thumb{box-sizing:border-box;width:28px;height:28px;margin-top:-8px;border:var(--neu-bw) solid var(--neu-edge);border-radius:50%;-webkit-appearance:none;appearance:none;
  background:radial-gradient(circle,var(--neu-accent) 0 4px,var(--neu-bg) 4.5px);box-shadow:var(--neu-raised-sm)}
.neu-range::-moz-range-track{box-sizing:border-box;height:14px;border:var(--neu-bw) solid var(--neu-edge);border-radius:999px;background:var(--neu-bg);box-shadow:var(--neu-inset-sm)}
.neu-range::-moz-range-progress{height:12px;border-radius:999px;background:var(--neu-accent)}
.neu-range::-moz-range-thumb{box-sizing:border-box;width:28px;height:28px;border:var(--neu-bw) solid var(--neu-edge);border-radius:50%;
  background:radial-gradient(circle,var(--neu-accent) 0 4px,var(--neu-bg) 4.5px);box-shadow:var(--neu-raised-sm)}
.neu-range:focus-visible{outline:3px solid var(--neu-accent);outline-offset:4px;border-radius:999px}
.neu-range-ends{display:flex;justify-content:space-between;font-size:.8rem;color:var(--neu-muted)}
/* Login card */
.neu-login{display:grid;gap:1.15rem;padding:2rem}
.neu-login__logo{display:grid;place-items:center;width:64px;height:64px;margin:0 auto .2rem;border-radius:50%;color:var(--neu-accent);box-shadow:var(--neu-inset)}
.neu-login__logo .neu-ico{width:28px;height:28px}
.neu-login__title{margin:0;font-size:1.5rem;line-height:1.25;font-weight:700;letter-spacing:-.01em;text-align:center}
.neu-login__sub{margin:-.6rem 0 .3rem;font-size:.92rem;color:var(--neu-muted);text-align:center}
.neu-login__row{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:.6rem}
.neu-login__foot{margin:0;font-size:.9rem;color:var(--neu-muted);text-align:center}
.neu-link{color:var(--neu-accent);font-weight:600;text-decoration:underline;text-underline-offset:3px;border-radius:4px}
.neu-link:hover{text-decoration-thickness:2px}
.neu-link:focus-visible{outline:3px solid var(--neu-accent);outline-offset:3px}
@media (prefers-reduced-motion:reduce){.neu-btn,.neu-check__box{transition:none}}
JavaScript
// Range: paint the WebKit fill (--val), and keep the visible value and aria-valuetext in step
document.querySelectorAll('[data-neu-range]').forEach(function (r) {
  var out = document.querySelector('output[for="' + r.id + '"]');
  function paint() {
    r.style.setProperty('--val', (r.value - r.min) / (r.max - r.min) * 100 + '%');
    r.setAttribute('aria-valuetext', r.value + ' percent');
    if (out) out.textContent = r.value + '%';
  }
  r.addEventListener('input', paint); paint();
});

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
  <symbol id="neu-i-search" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="6.5"/><path d="m16 16 4.5 4.5"/></symbol>
  <symbol id="neu-i-chevDown" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></symbol>
  <symbol id="neu-i-alert" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 4 2.8 19.5h18.4z"/><path d="M12 10v4.5M12 17.2h.01"/></symbol>
  <symbol id="neu-i-home" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 10.5 12 4l8 6.5V20h-5.5v-6h-5v6H4z"/></symbol>
  <symbol id="neu-i-mail" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="5.5" width="17" height="13" rx="2"/><path d="m4 7 8 6 8-6"/></symbol>
  <symbol id="neu-i-lock" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="10.5" width="14" height="10" rx="2"/><path d="M8 10.5V7.5a4 4 0 0 1 8 0v3"/></symbol>
  <symbol id="neu-i-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2.5v2M12 19.5v2M4.6 4.6 6 6M18 18l1.4 1.4M2.5 12h2M19.5 12h2M4.6 19.4 6 18M18 6l1.4-1.4"/></symbol>
</svg>
<div class="cols neu-form">
<div class="stack">
<section><span class="lbl">Text fields · default, with icon, with an error</span><div class="d-grid gap-4"><div><label class="form-label" for="f-name">Full name</label><input class="form-control" id="f-name" type="text" value="Ada Okafor" autocomplete="name"></div>
<div><label class="form-label" for="f-search">Find a device</label><div class="position-relative"><svg class="neu-ico neu-control-icon" aria-hidden="true" focusable="false"><use href="#neu-i-search"/></svg><input class="form-control ps-neu" id="f-search" type="search" placeholder="Lamp, lock, speaker…" aria-describedby="f-search-help"></div><div class="form-text" id="f-search-help">14 devices in 5 rooms</div></div>
<div><label class="form-label" for="f-email">Email for alerts</label><input class="form-control is-invalid" id="f-email" type="email" value="ada@okafor" aria-invalid="true" aria-describedby="f-email-err" autocomplete="email"><div class="invalid-feedback d-flex" id="f-email-err"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-alert"/></svg>Enter an address like [email protected]</div></div></div></section>
<section><span class="lbl">Select and range</span><div class="row g-4"><div class="col-sm-6"><div><label class="form-label" for="f-room">Default room</label><select class="form-select" id="f-room"><option>Living room</option><option selected>Kitchen</option><option>Bedroom</option><option>Office</option><option>Garden</option></select></div></div><div class="col-sm-6"><div class="d-grid gap-2"><div class="neu-range-head"><label class="form-label mb-0" for="rg-bright">Brightness</label><output for="rg-bright">70%</output></div><input class="form-range neu-range" id="rg-bright" type="range" min="0" max="100" value="70" style="--val:70%" data-neu-range><div class="neu-range-ends" aria-hidden="true"><span>Dim</span><span>Bright</span></div></div></div></div></section>
<section><span class="lbl">Checkboxes and radios</span><div class="row g-4"><div class="col-sm-6"><fieldset><legend>Notify me about</legend><div class="d-grid gap-2"><div class="form-check neu-check"><input class="form-check-input" type="checkbox" name="notify" id="n-doors" checked><label class="form-check-label" for="n-doors">Doors left unlocked</label></div><div class="form-check neu-check"><input class="form-check-input" type="checkbox" name="notify" id="n-leaks" checked><label class="form-check-label" for="n-leaks">Water leaks</label></div><div class="form-check neu-check"><input class="form-check-input" type="checkbox" name="notify" id="n-energy"><label class="form-check-label" for="n-energy">Daily energy summary</label></div></div></fieldset></div><div class="col-sm-6"><fieldset><legend>Heating mode</legend><div class="d-grid gap-2"><div class="form-check neu-check"><input class="form-check-input" type="radio" name="mode" id="m-comfort" value="comfort" checked><label class="form-check-label" for="m-comfort">Comfort</label></div><div class="form-check neu-check"><input class="form-check-input" type="radio" name="mode" id="m-eco" value="eco"><label class="form-check-label" for="m-eco">Eco</label></div><div class="form-check neu-check"><input class="form-check-input" type="radio" name="mode" id="m-away" value="away"><label class="form-check-label" for="m-away">Away</label></div></div></fieldset></div></div></section>
</div>
<section><span class="lbl">Login card</span><form class="card neu-card neu-login" action="#" aria-labelledby="login-title">
<span class="neu-login__logo"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-home"/></svg></span>
<h2 class="neu-login__title" id="login-title">Welcome home</h2>
<p class="neu-login__sub">Sign in to Hearth to control your rooms.</p>
<div><label class="form-label" for="l-email">Email</label><div class="position-relative"><svg class="neu-ico neu-control-icon" aria-hidden="true" focusable="false"><use href="#neu-i-mail"/></svg><input class="form-control ps-neu" id="l-email" type="email" placeholder="[email protected]" autocomplete="email" required></div></div>
<div><label class="form-label" for="l-pass">Password</label><div class="position-relative"><svg class="neu-ico neu-control-icon" aria-hidden="true" focusable="false"><use href="#neu-i-lock"/></svg><input class="form-control ps-neu" id="l-pass" type="password" autocomplete="current-password" required></div></div>
<div class="neu-login__row"><div class="form-check neu-check"><input class="form-check-input" type="checkbox" name="remember" id="l-remember" checked><label class="form-check-label" for="l-remember">Keep me signed in</label></div><a class="neu-link" href="#">Forgot password?</a></div>
<button class="btn btn-neu btn-neu-accent w-100" type="submit">Sign in</button>
<p class="neu-login__foot">New to Hearth? <a class="neu-link" href="#">Create an account</a></p>
</form></section>
</div>
CSS
/* ── Neumorphism UI kit tokens (uiCookies) — identical in every set ──────────────
   Every component is moulded from --neu-bg and lit from the top left. Change a token and
   the whole kit follows; the shadow recipes below are built from these values. */
:root{
  --neu-bg:#e0e5ec;          /* the one surface colour */
  --neu-light:#ffffff;       /* highlight, top left */
  --neu-dark:#a3b1c6;        /* shade, bottom right */
  --neu-distance:6px;        /* how far a shape rises */
  --neu-blur:14px;           /* how soft its shadow is */
  --neu-radius:18px;         /* cards; buttons use .75 of it, fields .6 */
  --neu-accent:#4f46e5;      /* focus ring and on / selected / current states, 4.9:1 on --neu-bg */
  --neu-on-accent:#ffffff;   /* text and marks on accent fills, 6.3:1 */
  --neu-ink:#1f2937;         /* text, 11.6:1 */
  --neu-muted:#4a5568;       /* secondary text, 5.9:1 */
  --neu-edge:#74819a;        /* control boundary (fields, tracks, boxes, buttons), 3.1:1 */
  --neu-line:rgba(255,255,255,.6); /* decorative edge on cards and panels */
  --neu-bw:1px;              /* control border width */
  --neu-success:#126b35;--neu-warning:#8a5300;--neu-danger:#b42318;
}
/* Dark neumorphism: data-neu="dark" on any wrapper, or a checked .neu-theme-input inside a [data-neu] element.
   :is() is a forgiving list, so browsers without :has() still apply data-neu="dark" */
[data-neu]:is([data-neu="dark"],:has(.neu-theme-input:checked)){
  --neu-bg:#262b33;--neu-light:#323944;--neu-dark:#14171c;
  --neu-accent:#8f88ff;--neu-on-accent:#14161b;--neu-ink:#e7ebf2;--neu-muted:#aab4c3;--neu-edge:#717d90;
  --neu-line:rgba(255,255,255,.06);--neu-success:#6fdc9a;--neu-warning:#f3c164;--neu-danger:#ff8f84;color-scheme:dark}
/* More contrast requested: the soft shadows go, every control and panel gets a solid outline */
@media (prefers-contrast:more){:root,[data-neu]:is([data-neu],:has(.neu-theme-input:checked)){
  --neu-light:transparent;--neu-dark:transparent;--neu-edge:var(--neu-ink);--neu-line:var(--neu-ink);--neu-muted:var(--neu-ink);--neu-bw:2px}}
:root,[data-neu]{
  --neu-raised:var(--neu-distance) var(--neu-distance) var(--neu-blur) var(--neu-dark),calc(var(--neu-distance)*-1) calc(var(--neu-distance)*-1) var(--neu-blur) var(--neu-light);
  --neu-raised-sm:calc(var(--neu-distance)*.5) calc(var(--neu-distance)*.5) calc(var(--neu-blur)*.5) var(--neu-dark),calc(var(--neu-distance)*-.5) calc(var(--neu-distance)*-.5) calc(var(--neu-blur)*.5) var(--neu-light);
  --neu-inset:inset calc(var(--neu-distance)*.6) calc(var(--neu-distance)*.6) calc(var(--neu-blur)*.6) var(--neu-dark),inset calc(var(--neu-distance)*-.6) calc(var(--neu-distance)*-.6) calc(var(--neu-blur)*.6) var(--neu-light);
  --neu-inset-sm:inset calc(var(--neu-distance)*.35) calc(var(--neu-distance)*.35) calc(var(--neu-blur)*.35) var(--neu-dark),inset calc(var(--neu-distance)*-.35) calc(var(--neu-distance)*-.35) calc(var(--neu-blur)*.35) var(--neu-light);
}
[data-neu]{background:var(--neu-bg);color:var(--neu-ink)}
/* Bootstrap's own variables mapped onto the kit tokens */
:root,[data-neu]{--bs-body-bg:var(--neu-bg);--bs-body-color:var(--neu-ink);--bs-emphasis-color:var(--neu-ink);
  --bs-heading-color:var(--neu-ink);--bs-secondary-color:var(--neu-muted);--bs-tertiary-color:var(--neu-muted);
  --bs-border-color:var(--neu-edge);--bs-border-width:var(--neu-bw);--bs-border-radius:calc(var(--neu-radius)*.6);
  --bs-border-radius-lg:var(--neu-radius);--bs-focus-ring-color:var(--neu-accent)}
/* Components */
.neu-ico{width:20px;height:20px;flex:none}
/* Buttons: Bootstrap .btn with a .btn-neu variant set through --bs-btn-* variables */
.btn-neu{--bs-btn-padding-x:1.35rem;--bs-btn-padding-y:.65rem;--bs-btn-font-size:.95rem;--bs-btn-font-weight:600;--bs-btn-line-height:1.2;
  --bs-btn-border-width:var(--neu-bw);--bs-btn-border-radius:calc(var(--neu-radius)*.75);
  --bs-btn-bg:var(--neu-bg);--bs-btn-color:var(--neu-ink);--bs-btn-border-color:var(--neu-edge);
  --bs-btn-hover-bg:var(--neu-bg);--bs-btn-hover-color:var(--neu-ink);--bs-btn-hover-border-color:var(--neu-edge);
  --bs-btn-active-bg:var(--neu-bg);--bs-btn-active-color:var(--neu-ink);--bs-btn-active-border-color:var(--neu-edge);
  --neu-btn-shadow:var(--neu-raised-sm);
  display:inline-flex;align-items:center;justify-content:center;gap:.55rem;min-height:46px;
  box-shadow:var(--neu-btn-shadow);transition:box-shadow .2s,color .2s,background-color .2s}
.btn-neu:hover{--neu-btn-shadow:var(--neu-raised)}
.btn-neu:active{--neu-btn-shadow:var(--neu-inset-sm)}
.btn-neu:focus-visible,.btn-check:focus-visible+.btn-neu{box-shadow:var(--neu-btn-shadow);outline:3px solid var(--neu-accent);outline-offset:3px}
.btn-neu-accent{--bs-btn-bg:var(--neu-accent);--bs-btn-color:var(--neu-on-accent);--bs-btn-border-color:var(--neu-accent);
  --bs-btn-hover-bg:var(--neu-accent);--bs-btn-hover-color:var(--neu-on-accent);--bs-btn-hover-border-color:var(--neu-accent);
  --bs-btn-active-bg:var(--neu-accent);--bs-btn-active-color:var(--neu-on-accent);--bs-btn-active-border-color:var(--neu-accent)}
.btn-neu.btn-sm{--bs-btn-padding-x:1rem;--bs-btn-padding-y:.45rem;--bs-btn-font-size:.85rem;min-height:38px}
.btn-neu-icon{--bs-btn-padding-x:0;--bs-btn-padding-y:0;width:50px;height:50px;min-height:0;border-radius:50%}
.btn-neu-icon.btn-neu-square{border-radius:calc(var(--neu-radius)*.75)}
.btn-neu-icon-sm{width:42px;height:42px}
.btn-neu-icon-lg{width:64px;height:64px}
.btn-neu-icon .neu-ico{width:22px;height:22px}
/* Card: Bootstrap .card restyled through --bs-card-* */
.card.neu-card{--bs-card-bg:var(--neu-bg);--bs-card-color:var(--neu-ink);--bs-card-border-color:var(--neu-line);--bs-card-border-width:var(--neu-bw);
  --bs-card-border-radius:var(--neu-radius);--bs-card-inner-border-radius:calc(var(--neu-radius) - var(--neu-bw));--bs-card-spacer-x:1.5rem;--bs-card-spacer-y:1.5rem;box-shadow:var(--neu-raised)}
.neu-card h2,.neu-card h3,.neu-card p{margin:0}
/* Fields: .form-control / .form-select as pressed-in wells with a 3:1 edge and the accent focus ring */
:root,[data-neu]{--bs-form-invalid-color:var(--neu-danger);--bs-form-invalid-border-color:var(--neu-danger)}
.neu-form .form-label{margin-bottom:.45rem;font-size:.88rem;font-weight:600}
.neu-form .form-control,.neu-form .form-select{min-height:48px;padding:.7rem 1rem;border:var(--neu-bw) solid var(--neu-edge);border-radius:calc(var(--neu-radius)*.6);
  background-color:var(--neu-bg);color:var(--neu-ink);line-height:1.4;box-shadow:var(--neu-inset-sm)}
.neu-form .form-select{padding-right:2.9rem;background-position:right 1rem center;cursor:pointer}
.neu-form .form-control::placeholder{color:var(--neu-muted);opacity:1}
.neu-form .form-control:focus,.neu-form .form-select:focus{border-color:var(--neu-edge);background-color:var(--neu-bg);color:var(--neu-ink);box-shadow:var(--neu-inset-sm);outline:3px solid var(--neu-accent);outline-offset:2px}
.neu-form .form-control.is-invalid{border-width:2px;border-color:var(--neu-danger);background-image:none;padding-right:1rem}
.neu-form .form-control.is-invalid:focus{border-color:var(--neu-danger);box-shadow:var(--neu-inset-sm)}
.neu-form .form-text{margin-top:.45rem;font-size:.82rem;color:var(--neu-muted)}
.neu-form .invalid-feedback{align-items:center;gap:.4rem;margin-top:.45rem;font-size:.82rem;font-weight:600}
.neu-form .form-text .neu-ico,.neu-form .invalid-feedback .neu-ico{width:16px;height:16px}
.neu-control-icon{position:absolute;top:50%;left:1rem;margin-top:-10px;color:var(--neu-muted);pointer-events:none}
.neu-form .ps-neu{padding-left:2.9rem}
/* Checkboxes and radios: .form-check-input as a pressed-in box that pops out and fills with accent when chosen */
.neu-form legend{float:none;margin-bottom:.8rem;font-size:.88rem;font-weight:600}
.neu-check{display:flex;align-items:center;gap:.75rem;min-height:32px;margin:0;padding:0}
.neu-check .form-check-label{cursor:pointer}
.neu-check .form-check-input{flex:none;float:none;width:24px;height:24px;margin:0;border:var(--neu-bw) solid var(--neu-edge);background-color:var(--neu-bg);background-size:14px;
  box-shadow:var(--neu-inset-sm);cursor:pointer;transition:background-color .2s,box-shadow .2s}
.neu-check .form-check-input[type=checkbox]{border-radius:7px;background-size:16px}
.neu-check .form-check-input:focus{border-color:var(--neu-edge);box-shadow:var(--neu-inset-sm)}
.neu-check .form-check-input:checked{border-color:var(--neu-accent);background-color:var(--neu-accent);box-shadow:var(--neu-raised-sm)}
.neu-check .form-check-input:focus-visible{outline:3px solid var(--neu-accent);outline-offset:3px}
/* Range: .form-range as a pressed groove with an accent fill and a raised thumb */
.neu-range-head{display:flex;justify-content:space-between;align-items:baseline}
.neu-range-head output{font-weight:700;font-variant-numeric:tabular-nums;color:var(--neu-accent)}
.form-range.neu-range{--val:50%;height:30px}
.form-range.neu-range::-webkit-slider-runnable-track{box-sizing:border-box;height:14px;border:var(--neu-bw) solid var(--neu-edge);border-radius:999px;box-shadow:var(--neu-inset-sm);
  background:linear-gradient(var(--neu-accent),var(--neu-accent)) 0 0/var(--val) 100% no-repeat,var(--neu-bg)}
.form-range.neu-range::-webkit-slider-thumb{box-sizing:border-box;width:28px;height:28px;margin-top:-8px;border:var(--neu-bw) solid var(--neu-edge);
  background:radial-gradient(circle,var(--neu-accent) 0 4px,var(--neu-bg) 4.5px);box-shadow:var(--neu-raised-sm)}
.form-range.neu-range::-moz-range-track{box-sizing:border-box;height:14px;border:var(--neu-bw) solid var(--neu-edge);border-radius:999px;background:var(--neu-bg);box-shadow:var(--neu-inset-sm)}
.form-range.neu-range::-moz-range-progress{height:12px;border-radius:999px;background:var(--neu-accent)}
.form-range.neu-range::-moz-range-thumb{box-sizing:border-box;width:28px;height:28px;border:var(--neu-bw) solid var(--neu-edge);
  background:radial-gradient(circle,var(--neu-accent) 0 4px,var(--neu-bg) 4.5px);box-shadow:var(--neu-raised-sm)}
.form-range.neu-range:focus::-webkit-slider-thumb{box-shadow:var(--neu-raised-sm)}
.form-range.neu-range:focus-visible{outline:3px solid var(--neu-accent);outline-offset:4px;border-radius:999px}
.neu-range-ends{display:flex;justify-content:space-between;font-size:.8rem;color:var(--neu-muted)}
/* Login card */
.neu-login{display:grid;gap:1.15rem;padding:2rem}
.neu-login .form-label{margin-bottom:.45rem}
.neu-login__logo{display:grid;place-items:center;width:64px;height:64px;margin:0 auto .2rem;border-radius:50%;color:var(--neu-accent);box-shadow:var(--neu-inset)}
.neu-login__logo .neu-ico{width:28px;height:28px}
.neu-login__title{margin:0;font-size:1.5rem;line-height:1.25;font-weight:700;letter-spacing:-.01em;text-align:center}
.neu-login__sub{margin:-.6rem 0 .3rem;font-size:.92rem;color:var(--neu-muted);text-align:center}
.neu-login__row{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:.6rem}
.neu-login__foot{margin:0;font-size:.9rem;color:var(--neu-muted);text-align:center}
.neu-link{color:var(--neu-accent);font-weight:600;text-decoration:underline;text-underline-offset:3px;border-radius:4px}
.neu-link:hover{text-decoration-thickness:2px}
.neu-link:focus-visible{outline:3px solid var(--neu-accent);outline-offset:3px}
@media (prefers-reduced-motion:reduce){.btn-neu,.neu-check .form-check-input{transition:none}}
JavaScript
// Range: paint the WebKit fill (--val), and keep the visible value and aria-valuetext in step
document.querySelectorAll('[data-neu-range]').forEach(function (r) {
  var out = document.querySelector('output[for="' + r.id + '"]');
  function paint() {
    r.style.setProperty('--val', (r.value - r.min) / (r.max - r.min) * 100 + '%');
    r.setAttribute('aria-valuetext', r.value + ' percent');
    if (out) out.textContent = r.value + '%';
  }
  r.addEventListener('input', paint); paint();
});

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
  <symbol id="neu-i-search" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="6.5"/><path d="m16 16 4.5 4.5"/></symbol>
  <symbol id="neu-i-chevDown" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></symbol>
  <symbol id="neu-i-alert" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 4 2.8 19.5h18.4z"/><path d="M12 10v4.5M12 17.2h.01"/></symbol>
  <symbol id="neu-i-home" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 10.5 12 4l8 6.5V20h-5.5v-6h-5v6H4z"/></symbol>
  <symbol id="neu-i-mail" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="5.5" width="17" height="13" rx="2"/><path d="m4 7 8 6 8-6"/></symbol>
  <symbol id="neu-i-lock" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="10.5" width="14" height="10" rx="2"/><path d="M8 10.5V7.5a4 4 0 0 1 8 0v3"/></symbol>
  <symbol id="neu-i-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2.5v2M12 19.5v2M4.6 4.6 6 6M18 18l1.4 1.4M2.5 12h2M19.5 12h2M4.6 19.4 6 18M18 6l1.4-1.4"/></symbol>
</svg>
<div class="grid items-start gap-14 min-[861px]:grid-cols-[minmax(0,1.15fr)_minmax(0,.85fr)]">
<div class="grid gap-11">
<section><span class="mb-[18px] block text-[.72rem] font-semibold tracking-[.12em] text-neu-muted uppercase">Text fields · default, with icon, with an error</span><div class="grid gap-6"><div class="grid min-w-0 gap-[.45rem]"><label class="text-[.88rem] font-semibold" for="f-name">Full name</label><input class="block w-full min-h-12 rounded-neu-field border-(length:--neu-bw) border-neu-edge bg-neu-bg px-4 py-[.7rem] text-base leading-[1.4] text-neu-ink shadow-neu-in-sm placeholder:text-neu-muted focus:outline-3 focus:outline-offset-2 focus:outline-neu-accent" id="f-name" type="text" value="Ada Okafor" autocomplete="name"></div>
<div class="grid min-w-0 gap-[.45rem]"><label class="text-[.88rem] font-semibold" for="f-search">Find a device</label><div class="relative"><svg class="pointer-events-none absolute top-1/2 left-4 -mt-2.5 size-5 text-neu-muted" aria-hidden="true" focusable="false"><use href="#neu-i-search"/></svg><input class="block w-full min-h-12 rounded-neu-field border-(length:--neu-bw) border-neu-edge bg-neu-bg px-4 py-[.7rem] text-base leading-[1.4] text-neu-ink shadow-neu-in-sm placeholder:text-neu-muted focus:outline-3 focus:outline-offset-2 focus:outline-neu-accent pl-[2.9rem]" id="f-search" type="search" placeholder="Lamp, lock, speaker…" aria-describedby="f-search-help"></div><p class="text-[.82rem] text-neu-muted" id="f-search-help">14 devices in 5 rooms</p></div>
<div class="grid min-w-0 gap-[.45rem]"><label class="text-[.88rem] font-semibold" for="f-email">Email for alerts</label><input class="block w-full min-h-12 rounded-neu-field  bg-neu-bg px-4 py-[.7rem] text-base leading-[1.4] text-neu-ink shadow-neu-in-sm placeholder:text-neu-muted focus:outline-3 focus:outline-offset-2 focus:outline-neu-accent border-2 border-neu-danger" id="f-email" type="email" value="ada@okafor" aria-invalid="true" aria-describedby="f-email-err" autocomplete="email"><p class="flex items-center gap-[.4rem] text-[.82rem] font-semibold text-neu-danger" id="f-email-err"><svg class="size-4 shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-alert"/></svg>Enter an address like [email protected]</p></div></div></section>
<section><span class="mb-[18px] block text-[.72rem] font-semibold tracking-[.12em] text-neu-muted uppercase">Select and range</span><div class="grid gap-7 min-[561px]:grid-cols-2"><div class="grid min-w-0 gap-[.45rem]"><label class="text-[.88rem] font-semibold" for="f-room">Default room</label><div class="relative"><select class="block w-full min-h-12 rounded-neu-field border-(length:--neu-bw) border-neu-edge bg-neu-bg px-4 py-[.7rem] text-base leading-[1.4] text-neu-ink shadow-neu-in-sm placeholder:text-neu-muted focus:outline-3 focus:outline-offset-2 focus:outline-neu-accent cursor-pointer appearance-none pr-[2.9rem]" id="f-room"><option>Living room</option><option selected>Kitchen</option><option>Bedroom</option><option>Office</option><option>Garden</option></select><svg class="pointer-events-none absolute top-1/2 right-4 -mt-2.5 size-5 text-neu-muted" aria-hidden="true" focusable="false"><use href="#neu-i-chevDown"/></svg></div></div>
<div class="grid gap-[.45rem]"><div class="flex items-baseline justify-between"><label class="text-[.88rem] font-semibold" for="rg-bright">Brightness</label><output class="font-bold text-neu-accent tabular-nums" for="rg-bright">70%</output></div><input class="neu-range" id="rg-bright" type="range" min="0" max="100" value="70" style="--val:70%" data-neu-range><div class="flex justify-between text-[.8rem] text-neu-muted" aria-hidden="true"><span>Dim</span><span>Bright</span></div></div></div></section>
<section><span class="mb-[18px] block text-[.72rem] font-semibold tracking-[.12em] text-neu-muted uppercase">Checkboxes and radios</span><div class="grid gap-7 min-[561px]:grid-cols-2"><fieldset class="m-0 min-w-0 border-0 p-0"><legend class="mb-[.8rem] p-0 text-[.88rem] font-semibold">Notify me about</legend><div class="grid gap-[.7rem]"><label class="relative flex min-h-8 cursor-pointer items-center gap-3"><input class="peer sr-only" type="checkbox" name="notify" checked><span class="relative size-6 flex-none border-(length:--neu-bw) border-neu-edge bg-neu-bg shadow-neu-in-sm transition-[background-color,box-shadow] duration-200 after:opacity-0 peer-checked:border-neu-accent peer-checked:bg-neu-accent peer-checked:shadow-neu-sm peer-checked:after:opacity-100 motion-reduce:transition-none peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-neu-accent rounded-[7px] after:absolute after:top-[3px] after:left-[7px] after:h-3 after:w-[7px] after:rotate-45 after:border-r-[2.5px] after:border-b-[2.5px] after:border-neu-on-accent" aria-hidden="true"></span>Doors left unlocked</label><label class="relative flex min-h-8 cursor-pointer items-center gap-3"><input class="peer sr-only" type="checkbox" name="notify" checked><span class="relative size-6 flex-none border-(length:--neu-bw) border-neu-edge bg-neu-bg shadow-neu-in-sm transition-[background-color,box-shadow] duration-200 after:opacity-0 peer-checked:border-neu-accent peer-checked:bg-neu-accent peer-checked:shadow-neu-sm peer-checked:after:opacity-100 motion-reduce:transition-none peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-neu-accent rounded-[7px] after:absolute after:top-[3px] after:left-[7px] after:h-3 after:w-[7px] after:rotate-45 after:border-r-[2.5px] after:border-b-[2.5px] after:border-neu-on-accent" aria-hidden="true"></span>Water leaks</label><label class="relative flex min-h-8 cursor-pointer items-center gap-3"><input class="peer sr-only" type="checkbox" name="notify"><span class="relative size-6 flex-none border-(length:--neu-bw) border-neu-edge bg-neu-bg shadow-neu-in-sm transition-[background-color,box-shadow] duration-200 after:opacity-0 peer-checked:border-neu-accent peer-checked:bg-neu-accent peer-checked:shadow-neu-sm peer-checked:after:opacity-100 motion-reduce:transition-none peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-neu-accent rounded-[7px] after:absolute after:top-[3px] after:left-[7px] after:h-3 after:w-[7px] after:rotate-45 after:border-r-[2.5px] after:border-b-[2.5px] after:border-neu-on-accent" aria-hidden="true"></span>Daily energy summary</label></div></fieldset>
<fieldset class="m-0 min-w-0 border-0 p-0"><legend class="mb-[.8rem] p-0 text-[.88rem] font-semibold">Heating mode</legend><div class="grid gap-[.7rem]"><label class="relative flex min-h-8 cursor-pointer items-center gap-3"><input class="peer sr-only" type="radio" name="mode" value="comfort" checked><span class="relative size-6 flex-none border-(length:--neu-bw) border-neu-edge bg-neu-bg shadow-neu-in-sm transition-[background-color,box-shadow] duration-200 after:opacity-0 peer-checked:border-neu-accent peer-checked:bg-neu-accent peer-checked:shadow-neu-sm peer-checked:after:opacity-100 motion-reduce:transition-none peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-neu-accent rounded-full after:absolute after:top-1/2 after:left-1/2 after:-mt-[5px] after:-ml-[5px] after:size-2.5 after:rounded-full after:bg-neu-on-accent" aria-hidden="true"></span>Comfort</label><label class="relative flex min-h-8 cursor-pointer items-center gap-3"><input class="peer sr-only" type="radio" name="mode" value="eco"><span class="relative size-6 flex-none border-(length:--neu-bw) border-neu-edge bg-neu-bg shadow-neu-in-sm transition-[background-color,box-shadow] duration-200 after:opacity-0 peer-checked:border-neu-accent peer-checked:bg-neu-accent peer-checked:shadow-neu-sm peer-checked:after:opacity-100 motion-reduce:transition-none peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-neu-accent rounded-full after:absolute after:top-1/2 after:left-1/2 after:-mt-[5px] after:-ml-[5px] after:size-2.5 after:rounded-full after:bg-neu-on-accent" aria-hidden="true"></span>Eco</label><label class="relative flex min-h-8 cursor-pointer items-center gap-3"><input class="peer sr-only" type="radio" name="mode" value="away"><span class="relative size-6 flex-none border-(length:--neu-bw) border-neu-edge bg-neu-bg shadow-neu-in-sm transition-[background-color,box-shadow] duration-200 after:opacity-0 peer-checked:border-neu-accent peer-checked:bg-neu-accent peer-checked:shadow-neu-sm peer-checked:after:opacity-100 motion-reduce:transition-none peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-neu-accent rounded-full after:absolute after:top-1/2 after:left-1/2 after:-mt-[5px] after:-ml-[5px] after:size-2.5 after:rounded-full after:bg-neu-on-accent" aria-hidden="true"></span>Away</label></div></fieldset></div></section>
</div>
<section><span class="mb-[18px] block text-[.72rem] font-semibold tracking-[.12em] text-neu-muted uppercase">Login card</span><form class="rounded-neu border-(length:--neu-bw) border-neu-line bg-neu-bg text-neu-ink shadow-neu grid gap-[1.15rem] p-8" action="#" aria-labelledby="login-title">
<span class="mx-auto mb-[.2rem] grid size-16 place-items-center rounded-full text-neu-accent shadow-neu-in"><svg class="size-7 shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-home"/></svg></span>
<h2 class="text-center text-2xl leading-[1.25] font-bold tracking-[-.01em]" id="login-title">Welcome home</h2>
<p class="-mt-[.6rem] mb-[.3rem] text-center text-[.92rem] text-neu-muted">Sign in to Hearth to control your rooms.</p>
<div class="grid min-w-0 gap-[.45rem]"><label class="text-[.88rem] font-semibold" for="l-email">Email</label><div class="relative"><svg class="pointer-events-none absolute top-1/2 left-4 -mt-2.5 size-5 text-neu-muted" aria-hidden="true" focusable="false"><use href="#neu-i-mail"/></svg><input class="block w-full min-h-12 rounded-neu-field border-(length:--neu-bw) border-neu-edge bg-neu-bg px-4 py-[.7rem] text-base leading-[1.4] text-neu-ink shadow-neu-in-sm placeholder:text-neu-muted focus:outline-3 focus:outline-offset-2 focus:outline-neu-accent pl-[2.9rem]" id="l-email" type="email" placeholder="[email protected]" autocomplete="email" required></div></div>
<div class="grid min-w-0 gap-[.45rem]"><label class="text-[.88rem] font-semibold" for="l-pass">Password</label><div class="relative"><svg class="pointer-events-none absolute top-1/2 left-4 -mt-2.5 size-5 text-neu-muted" aria-hidden="true" focusable="false"><use href="#neu-i-lock"/></svg><input class="block w-full min-h-12 rounded-neu-field border-(length:--neu-bw) border-neu-edge bg-neu-bg px-4 py-[.7rem] text-base leading-[1.4] text-neu-ink shadow-neu-in-sm placeholder:text-neu-muted focus:outline-3 focus:outline-offset-2 focus:outline-neu-accent pl-[2.9rem]" id="l-pass" type="password" autocomplete="current-password" required></div></div>
<div class="flex flex-wrap items-center justify-between gap-[.6rem]"><label class="relative flex min-h-8 cursor-pointer items-center gap-3"><input class="peer sr-only" type="checkbox" name="remember" checked><span class="relative size-6 flex-none border-(length:--neu-bw) border-neu-edge bg-neu-bg shadow-neu-in-sm transition-[background-color,box-shadow] duration-200 after:opacity-0 peer-checked:border-neu-accent peer-checked:bg-neu-accent peer-checked:shadow-neu-sm peer-checked:after:opacity-100 motion-reduce:transition-none peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-neu-accent rounded-[7px] after:absolute after:top-[3px] after:left-[7px] after:h-3 after:w-[7px] after:rotate-45 after:border-r-[2.5px] after:border-b-[2.5px] after:border-neu-on-accent" aria-hidden="true"></span>Keep me signed in</label><a class="rounded font-semibold text-neu-accent underline underline-offset-3 hover:decoration-2 focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-neu-accent" href="#">Forgot password?</a></div>
<button class="inline-flex items-center justify-center gap-[.55rem] border-(length:--neu-bw) font-semibold leading-[1.2] no-underline cursor-pointer shadow-neu-sm transition-[box-shadow,color,background-color] duration-200 hover:shadow-neu active:shadow-neu-in-sm motion-reduce:transition-none focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-neu-accent min-h-[46px] rounded-neu-btn px-[1.35rem] py-[.65rem] text-[.95rem] border-neu-accent bg-neu-accent text-neu-on-accent w-full" type="submit">Sign in</button>
<p class="text-center text-[.9rem] text-neu-muted">New to Hearth? <a class="rounded font-semibold text-neu-accent underline underline-offset-3 hover:decoration-2 focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-neu-accent" href="#">Create an account</a></p>
</form></section>
</div>
CSS
/* ── Neumorphism UI kit tokens (uiCookies) — identical in every set ──────────────
   Every component is moulded from --neu-bg and lit from the top left. Change a token and
   the whole kit follows; the shadow recipes below are built from these values. */
:root{
  --neu-bg:#e0e5ec;          /* the one surface colour */
  --neu-light:#ffffff;       /* highlight, top left */
  --neu-dark:#a3b1c6;        /* shade, bottom right */
  --neu-distance:6px;        /* how far a shape rises */
  --neu-blur:14px;           /* how soft its shadow is */
  --neu-radius:18px;         /* cards; buttons use .75 of it, fields .6 */
  --neu-accent:#4f46e5;      /* focus ring and on / selected / current states, 4.9:1 on --neu-bg */
  --neu-on-accent:#ffffff;   /* text and marks on accent fills, 6.3:1 */
  --neu-ink:#1f2937;         /* text, 11.6:1 */
  --neu-muted:#4a5568;       /* secondary text, 5.9:1 */
  --neu-edge:#74819a;        /* control boundary (fields, tracks, boxes, buttons), 3.1:1 */
  --neu-line:rgba(255,255,255,.6); /* decorative edge on cards and panels */
  --neu-bw:1px;              /* control border width */
  --neu-success:#126b35;--neu-warning:#8a5300;--neu-danger:#b42318;
}
/* Dark neumorphism: data-neu="dark" on any wrapper, or a checked .neu-theme-input inside a [data-neu] element.
   :is() is a forgiving list, so browsers without :has() still apply data-neu="dark" */
[data-neu]:is([data-neu="dark"],:has(.neu-theme-input:checked)){
  --neu-bg:#262b33;--neu-light:#323944;--neu-dark:#14171c;
  --neu-accent:#8f88ff;--neu-on-accent:#14161b;--neu-ink:#e7ebf2;--neu-muted:#aab4c3;--neu-edge:#717d90;
  --neu-line:rgba(255,255,255,.06);--neu-success:#6fdc9a;--neu-warning:#f3c164;--neu-danger:#ff8f84;color-scheme:dark}
/* More contrast requested: the soft shadows go, every control and panel gets a solid outline */
@media (prefers-contrast:more){:root,[data-neu]:is([data-neu],:has(.neu-theme-input:checked)){
  --neu-light:transparent;--neu-dark:transparent;--neu-edge:var(--neu-ink);--neu-line:var(--neu-ink);--neu-muted:var(--neu-ink);--neu-bw:2px}}
:root,[data-neu]{
  --neu-raised:var(--neu-distance) var(--neu-distance) var(--neu-blur) var(--neu-dark),calc(var(--neu-distance)*-1) calc(var(--neu-distance)*-1) var(--neu-blur) var(--neu-light);
  --neu-raised-sm:calc(var(--neu-distance)*.5) calc(var(--neu-distance)*.5) calc(var(--neu-blur)*.5) var(--neu-dark),calc(var(--neu-distance)*-.5) calc(var(--neu-distance)*-.5) calc(var(--neu-blur)*.5) var(--neu-light);
  --neu-inset:inset calc(var(--neu-distance)*.6) calc(var(--neu-distance)*.6) calc(var(--neu-blur)*.6) var(--neu-dark),inset calc(var(--neu-distance)*-.6) calc(var(--neu-distance)*-.6) calc(var(--neu-blur)*.6) var(--neu-light);
  --neu-inset-sm:inset calc(var(--neu-distance)*.35) calc(var(--neu-distance)*.35) calc(var(--neu-blur)*.35) var(--neu-dark),inset calc(var(--neu-distance)*-.35) calc(var(--neu-distance)*-.35) calc(var(--neu-blur)*.35) var(--neu-light);
}
[data-neu]{background:var(--neu-bg);color:var(--neu-ink)}
/* The tokens above, exposed as Tailwind utilities: bg-neu-bg, text-neu-muted, border-neu-edge,
   shadow-neu, shadow-neu-sm, shadow-neu-in, shadow-neu-in-sm, rounded-neu, rounded-neu-btn, rounded-neu-field… */
@theme inline {
  --color-neu-bg: var(--neu-bg); --color-neu-ink: var(--neu-ink); --color-neu-muted: var(--neu-muted);
  --color-neu-edge: var(--neu-edge); --color-neu-line: var(--neu-line);
  --color-neu-accent: var(--neu-accent); --color-neu-on-accent: var(--neu-on-accent);
  --color-neu-success: var(--neu-success); --color-neu-warning: var(--neu-warning); --color-neu-danger: var(--neu-danger);
  --shadow-neu: var(--neu-raised); --shadow-neu-sm: var(--neu-raised-sm);
  --shadow-neu-in: var(--neu-inset); --shadow-neu-in-sm: var(--neu-inset-sm);
  --radius-neu: var(--neu-radius); --radius-neu-btn: calc(var(--neu-radius) * .75); --radius-neu-field: calc(var(--neu-radius) * .6);
}
/* Range thumb and track live here: Tailwind has no utilities for these pseudo-elements */
.neu-range{--val:50%;width:100%;height:30px;margin:0;background:transparent;-webkit-appearance:none;appearance:none;cursor:pointer}
.neu-range::-webkit-slider-runnable-track{box-sizing:border-box;height:14px;border:var(--neu-bw) solid var(--neu-edge);border-radius:999px;box-shadow:var(--neu-inset-sm);
  background:linear-gradient(var(--neu-accent),var(--neu-accent)) 0 0/var(--val) 100% no-repeat,var(--neu-bg)}
.neu-range::-webkit-slider-thumb{box-sizing:border-box;width:28px;height:28px;margin-top:-8px;border:var(--neu-bw) solid var(--neu-edge);border-radius:50%;-webkit-appearance:none;appearance:none;
  background:radial-gradient(circle,var(--neu-accent) 0 4px,var(--neu-bg) 4.5px);box-shadow:var(--neu-raised-sm)}
.neu-range::-moz-range-track{box-sizing:border-box;height:14px;border:var(--neu-bw) solid var(--neu-edge);border-radius:999px;background:var(--neu-bg);box-shadow:var(--neu-inset-sm)}
.neu-range::-moz-range-progress{height:12px;border-radius:999px;background:var(--neu-accent)}
.neu-range::-moz-range-thumb{box-sizing:border-box;width:28px;height:28px;border:var(--neu-bw) solid var(--neu-edge);border-radius:50%;
  background:radial-gradient(circle,var(--neu-accent) 0 4px,var(--neu-bg) 4.5px);box-shadow:var(--neu-raised-sm)}
.neu-range:focus-visible{outline:3px solid var(--neu-accent);outline-offset:4px;border-radius:999px}
JavaScript
// Range: paint the WebKit fill (--val), and keep the visible value and aria-valuetext in step
document.querySelectorAll('[data-neu-range]').forEach(function (r) {
  var out = document.querySelector('output[for="' + r.id + '"]');
  function paint() {
    r.style.setProperty('--val', (r.value - r.min) / (r.max - r.min) * 100 + '%');
    r.setAttribute('aria-valuetext', r.value + ' percent');
    if (out) out.textContent = r.value + '%';
  }
  r.addEventListener('input', paint); paint();
});

About this set

Form controls carved into the surface, and a login card that uses them. Text fields are pressed-in wells with a label above, shown plain, with a search icon and helper text, and in an error state that adds a red edge and an icon with a message tied to the field through aria-describedby. A native select gets a matching chevron, checkboxes and radios pop out of their well and fill with accent when chosen, and a brightness slider shows its value beside the label. The login card puts an email and a password field, a keep-me-signed-in checkbox, a forgotten-password link and a full-width sign-in button inside one raised panel. Use the fields wherever a soft UI needs input, and the card as a sign-in screen for a dashboard or a smart-home app. Every field edge reaches 3:1 against the background, which most neumorphic forms skip, and the accent focus ring is drawn outside the field so it never blends into the shadow. The slider is a native range input; a few lines of script paint its fill in WebKit and keep the value and aria-valuetext current.

What’s included

  • Inset fields with a 3:1 edge, icon, helper and error variants
  • Checkboxes and radios that pop out and fill with accent when chosen
  • Native select and range input styled to match
  • Login card with labelled fields and autocomplete hints
  • Bootstrap version built on .form-control, .form-select, .form-check-input and .form-range

Accessibility

Every field has a visible label, the error is announced through aria-invalid and aria-describedby, and the checkboxes and radios sit in fieldsets with legends. Fields show a 3px accent outline on focus and custom boxes draw it on the visible box. The slider reports its value as a percentage through aria-valuetext. Transitions are removed under prefers-reduced-motion, and prefers-contrast: more replaces the shadows with solid outlines.

Customise it

Edit the --neu-* tokens at the top for colours, depth and radius; the error colour is --neu-danger. Bootstrap reads them through --bs-form-invalid-color and the .neu-form rules, and Tailwind uses border-neu-edge, shadow-neu-in-sm and rounded-neu-field.