Open demo

CSS code

HTML
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
  <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-grid" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="7" height="7" rx="1.5"/><rect x="13" y="4" width="7" height="7" rx="1.5"/><rect x="4" y="13" width="7" height="7" rx="1.5"/><rect x="13" y="13" width="7" height="7" rx="1.5"/></symbol>
  <symbol id="neu-i-sofa" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M5 11V8a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v3"/><path d="M3 12a2 2 0 0 1 4 0v2h10v-2a2 2 0 0 1 4 0v5H3z"/><path d="M5 17v2M19 17v2"/></symbol>
  <symbol id="neu-i-star" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m12 3.5 2.6 5.4 5.9.8-4.3 4.1 1 5.8L12 16.8l-5.2 2.8 1-5.8-4.3-4.1 5.9-.8z"/></symbol>
  <symbol id="neu-i-bolt" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M13 3 5 13.5h6L10 21l8-10.5h-6z"/></symbol>
  <symbol id="neu-i-bell" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6 16v-5a6 6 0 0 1 12 0v5l1.5 2h-15zM10 20.5a2 2 0 0 0 4 0"/></symbol>
  <symbol id="neu-i-sliders" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h10M18 7h2M4 17h4M12 17h8"/><circle cx="16" cy="7" r="2"/><circle cx="10" cy="17" r="2"/></symbol>
  <symbol id="neu-i-logout" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M14 4h4.5a1.5 1.5 0 0 1 1.5 1.5v13a1.5 1.5 0 0 1-1.5 1.5H14M10 16.5 5.5 12 10 7.5M5.5 12H16"/></symbol>
  <symbol id="neu-i-thermo" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M14 14.5V5.5a2 2 0 0 0-4 0v9a4 4 0 1 0 4 0z"/><path d="M12 9.5V16"/></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>
  <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-arrowDown" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M6.5 13.5 12 19l5.5-5.5"/></symbol>
  <symbol id="neu-i-arrowUp" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19V5M6.5 10.5 12 5l5.5 5.5"/></symbol>
  <symbol id="neu-i-drop" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3.5s6 6.6 6 11a6 6 0 0 1-12 0c0-4.4 6-11 6-11z"/></symbol>
  <symbol id="neu-i-minus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/></symbol>
  <symbol id="neu-i-plus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></symbol>
  <symbol id="neu-i-bulb" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9.5 18h5M10.5 21h3M12 3a6 6 0 0 0-3.6 10.8c.6.5 1 1.2 1 2v.2h5.2v-.2c0-.8.4-1.5 1-2A6 6 0 0 0 12 3z"/></symbol>
  <symbol id="neu-i-play" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path fill="currentColor" d="M8 5.2v13.6L19 12z"/></symbol>
  <symbol id="neu-i-pause" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path fill="currentColor" stroke="none" d="M7 5h3.6v14H7zM13.4 5H17v14h-3.6z"/></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-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20 14.5A8 8 0 0 1 9.5 4a8 8 0 1 0 10.5 10.5z"/></symbol>
</svg>
<div class="neu-home" data-neu="light">
<nav class="neu-side neu-home__side" aria-label="Main">
<p class="neu-home__brand"><span class="neu-home__mark"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-home"/></svg></span>Hearth</p>
<h2 class="neu-side__heading" id="hs-0">Home</h2><ul class="neu-side__list" aria-labelledby="hs-0"><li><a class="neu-sidelink" href="#" aria-current="page"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-grid"/></svg>Dashboard</a></li><li><a class="neu-sidelink" href="#"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-sofa"/></svg>Rooms</a></li><li><a class="neu-sidelink" href="#"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-star"/></svg>Scenes</a></li><li><a class="neu-sidelink" href="#"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-bolt"/></svg>Energy</a></li><li><a class="neu-sidelink" href="#"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-bell"/></svg>Alerts<span class="neu-count">1<span class="neu-sr"> new</span></span></a></li></ul>
<h2 class="neu-side__heading" id="hs-1">Account</h2><ul class="neu-side__list" aria-labelledby="hs-1"><li><a class="neu-sidelink" href="#"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-sliders"/></svg>Settings</a></li><li><a class="neu-sidelink" href="#"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-logout"/></svg>Sign out</a></li></ul>
</nav>
<div class="neu-home__main">
<header class="neu-home__head"><div><h1 class="neu-home__title">Good evening, Ada</h1><p class="neu-home__sub">Thursday 16 October · 7 devices on · 21.5 °C inside</p></div>
<label class="neu-switch neu-home__theme"><input class="neu-sr neu-theme-input" type="checkbox" role="switch"><span class="neu-switch__text">Dark mode<small>Soft UI after sunset</small></span><span class="neu-switch__state" aria-hidden="true"></span><span class="neu-switch__track" aria-hidden="true"></span></label></header>
<div class="neu-home__stats">
<article class="neu-stat"><span class="neu-stat__icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-bolt"/></svg></span><p class="neu-stat__label">Energy today</p><p class="neu-stat__value">12.4<small> kWh</small></p><p class="neu-stat__delta neu-stat__delta--good"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-arrowDown"/></svg>8% less than yesterday</p></article>
<article class="neu-stat"><span class="neu-stat__icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-sun"/></svg></span><p class="neu-stat__label">Solar now</p><p class="neu-stat__value">1.2<small> kW</small></p><p class="neu-stat__delta neu-stat__delta--good"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-arrowUp"/></svg>Battery at 82%</p></article>
<article class="neu-stat"><span class="neu-stat__icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-drop"/></svg></span><p class="neu-stat__label">Humidity</p><p class="neu-stat__value">46<small> %</small></p><p class="neu-stat__delta">Comfortable range</p></article>
<article class="neu-stat"><span class="neu-stat__icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-lock"/></svg></span><p class="neu-stat__label">Security</p><p class="neu-stat__value">Locked</p><p class="neu-stat__delta">All 3 doors, since 22:41</p></article>
</div>
<div class="neu-home__grid">
<section class="neu-card neu-home__panel" aria-labelledby="p-climate"><h2 class="neu-home__h" id="p-climate">Climate<small>Heating</small></h2><div class="neu-dial" role="group" aria-label="Hallway thermostat" data-neu-dial data-min="10" data-max="30"><div class="neu-dial__face" style="--p:57.5" data-neu-face><span class="neu-dial__arc"></span><span class="neu-dial__core"><span class="neu-dial__mode">Heating to</span><span class="neu-dial__target" aria-live="polite"><span class="neu-sr">Target </span><span data-neu-value>21.5</span><span aria-hidden="true">°</span><span class="neu-sr"> Celsius</span></span><span class="neu-dial__now">Now 19.8 °C</span></span></div><div class="neu-dial__ctrl"><button class="neu-btn neu-btn--icon neu-btn--icon-sm" type="button" data-step="-0.5" aria-label="Lower target temperature"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-minus"/></svg></button><p class="neu-dial__name">Hallway</p><button class="neu-btn neu-btn--icon neu-btn--icon-sm" type="button" data-step="0.5" aria-label="Raise target temperature"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-plus"/></svg></button></div></div></section>
<section class="neu-card neu-home__panel" aria-labelledby="p-lights"><h2 class="neu-home__h" id="p-lights">Lights<small>2 of 4 on</small></h2><div class="neu-home__lights"><label class="neu-toggle"><input class="neu-sr" type="checkbox" role="switch" checked><span class="neu-toggle__face"><span class="neu-toggle__icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-bulb"/></svg></span><span class="neu-toggle__name">Kitchen<span class="neu-sr">, Pendants, 80%</span></span><span class="neu-toggle__sub" aria-hidden="true">Pendants, 80%</span><span class="neu-toggle__state" aria-hidden="true"></span></span></label><label class="neu-toggle"><input class="neu-sr" type="checkbox" role="switch" checked><span class="neu-toggle__face"><span class="neu-toggle__icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-bulb"/></svg></span><span class="neu-toggle__name">Living room<span class="neu-sr">, Floor lamp</span></span><span class="neu-toggle__sub" aria-hidden="true">Floor lamp</span><span class="neu-toggle__state" aria-hidden="true"></span></span></label><label class="neu-toggle"><input class="neu-sr" type="checkbox" role="switch"><span class="neu-toggle__face"><span class="neu-toggle__icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-bulb"/></svg></span><span class="neu-toggle__name">Hallway<span class="neu-sr">, Off at 23:00</span></span><span class="neu-toggle__sub" aria-hidden="true">Off at 23:00</span><span class="neu-toggle__state" aria-hidden="true"></span></span></label><label class="neu-toggle"><input class="neu-sr" type="checkbox" role="switch"><span class="neu-toggle__face"><span class="neu-toggle__icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-bulb"/></svg></span><span class="neu-toggle__name">Porch<span class="neu-sr">, Motion sensor</span></span><span class="neu-toggle__sub" aria-hidden="true">Motion sensor</span><span class="neu-toggle__state" aria-hidden="true"></span></span></label></div></section>
<section class="neu-card neu-home__panel neu-home__wide" aria-labelledby="p-scene"><h2 class="neu-home__h" id="p-scene">Scene and music</h2><div class="neu-home__row"><fieldset class="neu-seg"><legend class="neu-seg__legend">Active scene</legend><div class="neu-seg__opts"><label class="neu-seg__opt"><input class="neu-sr" type="radio" name="scene" value="morning"><span>Morning</span></label><label class="neu-seg__opt"><input class="neu-sr" type="radio" name="scene" value="away"><span>Away</span></label><label class="neu-seg__opt"><input class="neu-sr" type="radio" name="scene" value="movie" checked><span>Movie</span></label><label class="neu-seg__opt"><input class="neu-sr" type="radio" name="scene" value="sleep"><span>Sleep</span></label></div></fieldset><div class="neu-mini"><span class="neu-mini__art" aria-hidden="true"></span><div class="neu-mini__meta"><p class="neu-mini__title">Low Tide</p><p class="neu-mini__artist">Marla Quinn · Living room</p><div class="neu-mini__bar" style="--p:40%" role="progressbar" aria-label="Track position" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100"></div></div><label class="neu-play"><input class="neu-sr" type="checkbox" aria-label="Play Low Tide"><span class="neu-play__face"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-play"/></svg><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-pause"/></svg></span></label></div><div class="neu-alert neu-alert--warning"><span class="neu-alert__icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-alert"/></svg></span><div><p class="neu-alert__title"><span class="neu-sr">Warning: </span>Bedroom window open</p><p class="neu-alert__text">Heating paused until it is closed.</p></div></div></div></section>
</div>
</div>
</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}
/* Sidebar: current item = pressed in, accent edge and text, and a dot at the end */
.neu-side{display:grid;align-content:start;gap:.2rem;padding:1.1rem;border:var(--neu-bw) solid var(--neu-line);border-radius:var(--neu-radius);background:var(--neu-bg);box-shadow:var(--neu-raised)}
.neu-side__heading{margin:.5rem .8rem .4rem;font-size:.72rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--neu-muted)}
.neu-side__list{display:grid;gap:6px;margin:0;padding:0;list-style:none}
.neu-sidelink{display:flex;align-items:center;gap:.75rem;min-height:44px;padding:.55rem .8rem;border:var(--neu-bw) solid transparent;border-radius:calc(var(--neu-radius)*.6);
  color:var(--neu-muted);font-weight:600;text-decoration:none;transition:box-shadow .2s,color .2s}
.neu-sidelink:hover{color:var(--neu-ink);box-shadow:var(--neu-raised-sm)}
.neu-sidelink[aria-current="page"]{border-color:var(--neu-accent);color:var(--neu-accent);box-shadow:var(--neu-inset-sm)}
.neu-sidelink[aria-current="page"]::after{content:"";width:8px;height:8px;margin-left:auto;border-radius:50%;background:currentColor}
.neu-sidelink:focus-visible{outline:3px solid var(--neu-accent);outline-offset:2px}
.neu-count{margin-left:auto;min-width:24px;padding:.1rem .45rem;border-radius:999px;background:var(--neu-accent);color:var(--neu-on-accent);font-size:.75rem;font-weight:700;text-align:center}
/* Switches: a checkbox with role="switch". On = knob travels right, track fills with accent and the word On appears */
.neu-switch{position:relative;display:flex;align-items:center;gap:.9rem;cursor:pointer}
.neu-switch__text{flex:1;min-width:0;font-weight:600;line-height:1.3}
.neu-switch__text small{display:block;margin-top:.15rem;font-size:.82rem;font-weight:400;color:var(--neu-muted)}
.neu-switch__state{min-width:2.1em;font-size:.75rem;font-weight:700;letter-spacing:.08em;text-align:right;text-transform:uppercase;color:var(--neu-muted)}
.neu-switch__state::after{content:"Off"}
.neu-switch__track{position:relative;flex:none;width:58px;height:32px;border:var(--neu-bw) solid var(--neu-edge);border-radius:999px;
  background:var(--neu-bg);box-shadow:var(--neu-inset-sm);transition:background-color .25s,border-color .25s}
.neu-switch__track::before{content:"";position:absolute;top:50%;left:3px;width:24px;height:24px;margin-top:-12px;border-radius:50%;
  border:var(--neu-bw) solid var(--neu-edge);background:var(--neu-bg);box-shadow:var(--neu-raised-sm);transition:transform .25s,background-color .25s}
.neu-switch input:checked~.neu-switch__track{background:var(--neu-accent);border-color:var(--neu-accent)}
.neu-switch input:checked~.neu-switch__track::before{transform:translateX(calc(28px - 2*var(--neu-bw)));background:var(--neu-on-accent);border-color:var(--neu-on-accent)}
.neu-switch input:checked~.neu-switch__state{color:var(--neu-accent)}
.neu-switch input:checked~.neu-switch__state::after{content:"On"}
.neu-switch input:focus-visible~.neu-switch__track{outline:3px solid var(--neu-accent);outline-offset:3px}
/* Stat tile: icon in a pressed well, label, a big value, and a change line that says which way in words */
.neu-stat{display:grid;gap:.2rem;padding:1.25rem;border:var(--neu-bw) solid var(--neu-line);border-radius:var(--neu-radius);background:var(--neu-bg);box-shadow:var(--neu-raised)}
.neu-stat__icon{display:grid;place-items:center;width:44px;height:44px;margin-bottom:.6rem;border-radius:50%;color:var(--neu-accent);box-shadow:var(--neu-inset-sm)}
.neu-stat__label{margin:0;font-size:.85rem;font-weight:600;color:var(--neu-muted)}
.neu-stat__value{margin:0;font-size:1.9rem;font-weight:700;line-height:1.15;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.neu-stat__value small{font-size:.9rem;font-weight:600;letter-spacing:0;color:var(--neu-muted)}
.neu-stat__delta{display:flex;align-items:center;gap:.3rem;margin:.35rem 0 0;font-size:.82rem;font-weight:600;color:var(--neu-muted)}
.neu-stat__delta .neu-ico{width:16px;height:16px}
.neu-stat__delta--good{color:var(--neu-success)}
.neu-stat__delta--warn{color:var(--neu-warning)}
/* Thermostat: a 270° conic-gradient arc in a pressed groove, a raised core with the target,
   and minus / plus buttons. A few lines of script change the target and the arc (--p, 0–100). */
.neu-dial{display:grid;justify-items:center;gap:1.1rem}
.neu-dial__face{--p:50;position:relative;display:grid;place-items:center;width:216px;aspect-ratio:1;border:var(--neu-bw) solid var(--neu-line);border-radius:50%;background:var(--neu-bg);box-shadow:var(--neu-raised)}
.neu-dial__arc{position:absolute;inset:12px;border-radius:50%;box-shadow:var(--neu-inset-sm);
  background:conic-gradient(from 225deg,var(--neu-accent) calc(var(--p)*.75%),transparent 0);
  -webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 14px),#000 calc(100% - 13.5px));mask:radial-gradient(farthest-side,transparent calc(100% - 14px),#000 calc(100% - 13.5px));transition:background .3s}
.neu-dial__core{position:relative;display:grid;place-items:center;align-content:center;width:142px;aspect-ratio:1;border-radius:50%;box-shadow:var(--neu-raised-sm);text-align:center}
.neu-dial__mode{font-size:.75rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--neu-accent)}
.neu-dial__target{margin:0;font-size:2.6rem;font-weight:700;line-height:1.05;letter-spacing:-.03em;font-variant-numeric:tabular-nums}
.neu-dial__now{font-size:.8rem;color:var(--neu-muted)}
.neu-dial__ctrl{display:flex;align-items:center;gap:1.4rem}
.neu-dial__name{margin:0;font-weight:600}
/* Toggle tiles: a visually hidden checkbox and a face. On = pressed in (inset), accent border,
   accent icon, a filled dot and the word On — never colour alone. */
.neu-toggle{position:relative;display:inline-flex;cursor:pointer}
.neu-toggle__face{display:flex;flex-direction:column;align-items:flex-start;gap:.4rem;width:100%;min-width:132px;padding:1rem 1.1rem;
  border:var(--neu-bw) solid var(--neu-edge);border-radius:var(--neu-radius);background:var(--neu-bg);color:var(--neu-ink);
  box-shadow:var(--neu-raised-sm);transition:box-shadow .25s,border-color .25s}
.neu-toggle__icon{display:grid;place-items:center;width:42px;height:42px;margin-bottom:.35rem;border-radius:50%;color:var(--neu-muted);box-shadow:var(--neu-inset-sm);transition:color .25s,background-color .25s}
.neu-toggle__icon .neu-ico{width:22px;height:22px}
.neu-toggle__name{font-weight:600;line-height:1.25}
.neu-toggle__state{display:flex;align-items:center;gap:.4rem;font-size:.8rem;font-weight:600;color:var(--neu-muted)}
.neu-toggle__state::before{content:"";width:9px;height:9px;border:2px solid currentColor;border-radius:50%}
.neu-toggle__state::after{content:"Off"}
.neu-toggle input:checked+.neu-toggle__face{box-shadow:var(--neu-inset);border-color:var(--neu-accent)}
.neu-toggle input:checked+.neu-toggle__face .neu-toggle__icon{color:var(--neu-on-accent);background:var(--neu-accent)}
.neu-toggle input:checked+.neu-toggle__face .neu-toggle__state{color:var(--neu-accent)}
.neu-toggle input:checked+.neu-toggle__face .neu-toggle__state::before{background:currentColor}
.neu-toggle input:checked+.neu-toggle__face .neu-toggle__state::after{content:"On"}
.neu-toggle input:focus-visible+.neu-toggle__face{outline:3px solid var(--neu-accent);outline-offset:3px}
.neu-toggle__sub{margin-top:-.3rem;font-size:.8rem;color:var(--neu-muted)}
/* Segmented control: radios in a fieldset. The chosen option rises out of the well, turns accent and gains a dot */
.neu-seg{min-width:0;margin:0;padding:0;border:0}
.neu-seg__legend{margin-bottom:.6rem;padding:0;font-size:.88rem;font-weight:600}
.neu-seg__opts{display:flex;flex-wrap:wrap;gap:6px;padding:6px;border:var(--neu-bw) solid var(--neu-edge);border-radius:calc(var(--neu-radius)*.75);box-shadow:var(--neu-inset-sm)}
.neu-seg__opt{position:relative;flex:1 1 auto}
.neu-seg__opt span{display:flex;align-items:center;justify-content:center;gap:.4rem;min-height:40px;padding:.4rem .9rem;border:var(--neu-bw) solid transparent;
  border-radius:calc(var(--neu-radius)*.5);color:var(--neu-muted);font-size:.9rem;font-weight:600;cursor:pointer;transition:box-shadow .2s,color .2s}
.neu-seg__opt input:checked+span{border-color:var(--neu-accent);color:var(--neu-accent);box-shadow:var(--neu-raised-sm)}
.neu-seg__opt input:checked+span::before{content:"";width:7px;height:7px;border-radius:50%;background:currentColor}
.neu-seg__opt input:focus-visible+span{outline:3px solid var(--neu-accent);outline-offset:2px}
/* Mini player: art in a pressed well, title, a progress groove, and a play / pause toggle (checkbox) */
.neu-mini{display:flex;align-items:center;gap:1rem;padding:1rem 1.1rem;border:var(--neu-bw) solid var(--neu-line);border-radius:var(--neu-radius);background:var(--neu-bg);box-shadow:var(--neu-raised)}
.neu-mini__art{flex:none;width:52px;height:52px;border-radius:calc(var(--neu-radius)*.6);box-shadow:var(--neu-inset-sm);
  background:radial-gradient(circle at 30% 30%,#f59e0b 0 18%,transparent 19%),linear-gradient(160deg,#4f46e5,#0e7490)}
.neu-mini__meta{flex:1;min-width:0}
.neu-mini__title{margin:0;font-weight:700;line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.neu-mini__artist{margin:0;font-size:.82rem;color:var(--neu-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.neu-mini__bar{height:8px;margin-top:.55rem;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(--p,40%) 100% no-repeat}
.neu-play{position:relative;flex:none;display:inline-flex}
.neu-play__face{display:grid;place-items:center;width:52px;height:52px;border:var(--neu-bw) solid var(--neu-accent);border-radius:50%;
  background:var(--neu-accent);color:var(--neu-on-accent);box-shadow:var(--neu-raised-sm);cursor:pointer;transition:box-shadow .2s}
.neu-play__face .neu-ico{width:24px;height:24px}
.neu-play__face .neu-ico+.neu-ico,.neu-play input:checked+.neu-play__face .neu-ico:first-child{display:none}
.neu-play input:checked+.neu-play__face .neu-ico+.neu-ico{display:block}
.neu-play input:checked+.neu-play__face{box-shadow:var(--neu-inset-sm)}
.neu-play input:focus-visible+.neu-play__face{outline:3px solid var(--neu-accent);outline-offset:3px}
/* Alerts: the type is carried by an icon, a title and hidden "Warning:" style text, not by colour alone */
.neu-alerts{display:grid;gap:16px}
.neu-alert{--tone:var(--neu-accent);position:relative;display:flex;align-items:flex-start;gap:.9rem;padding:1rem 1.1rem 1rem 1.35rem;border:var(--neu-bw) solid var(--neu-line);
  border-radius:var(--neu-radius);background:var(--neu-bg);box-shadow:var(--neu-raised-sm)}
.neu-alert::before{content:"";position:absolute;left:.55rem;top:1rem;bottom:1rem;width:4px;border-radius:4px;background:var(--tone)}
.neu-alert--success{--tone:var(--neu-success)}.neu-alert--warning{--tone:var(--neu-warning)}.neu-alert--danger{--tone:var(--neu-danger)}
.neu-alert__icon{display:grid;place-items:center;flex:none;width:40px;height:40px;border-radius:50%;color:var(--tone);box-shadow:var(--neu-inset-sm)}
.neu-alert__title{margin:0;font-weight:700;line-height:1.3}
.neu-alert__text{margin:.15rem 0 0;font-size:.9rem;color:var(--neu-muted)}
/* Dashboard shell. The theme switch is a checkbox with class .neu-theme-input: the token block's
   [data-neu]:has(.neu-theme-input:checked) rule swaps every token to dark, so no script is involved */
.neu-home{display:grid;grid-template-columns:250px minmax(0,1fr);gap:32px;min-height:100vh;padding:28px}
.neu-home__side{position:sticky;top:28px;align-self:start}
.neu-home__brand{display:flex;align-items:center;gap:.65rem;margin:0 .4rem .9rem;font-size:1.1rem;font-weight:800}
.neu-home__mark{display:grid;place-items:center;width:40px;height:40px;border-radius:50%;color:var(--neu-accent);box-shadow:var(--neu-inset-sm)}
.neu-home__main{display:grid;grid-template-columns:minmax(0,1fr);align-content:start;gap:28px;min-width:0}
.neu-home__head{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:16px 24px}
.neu-home__title{margin:0;font-size:1.75rem;font-weight:800;line-height:1.2;letter-spacing:-.02em}
.neu-home__sub{margin:.25rem 0 0;color:var(--neu-muted)}
.neu-home__theme{min-width:250px;padding:.7rem 1rem;border:var(--neu-bw) solid var(--neu-line);border-radius:calc(var(--neu-radius)*.75);box-shadow:var(--neu-raised-sm)}
.neu-home__stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,190px),1fr));gap:22px}
.neu-home__grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.25fr);gap:22px;align-items:start}
.neu-home__wide{grid-column:1/-1}
.neu-home__row{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr));gap:22px;align-items:center}
.neu-home__row>:last-child{grid-column:1/-1}
.neu-home__panel{display:grid;grid-template-columns:minmax(0,1fr);gap:1.1rem}
.neu-home__h{display:flex;justify-content:space-between;align-items:baseline;gap:.5rem;margin:0;font-size:1rem;font-weight:700}
.neu-home__h small{font-size:.82rem;font-weight:600;color:var(--neu-muted)}
.neu-home__lights{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}
@media (max-width:1100px){.neu-home__grid{grid-template-columns:minmax(0,1fr)}}
@media (max-width:900px){.neu-home{grid-template-columns:minmax(0,1fr);gap:24px;padding:16px}.neu-home__side{position:static}
  .neu-home .neu-side__list{display:flex;flex-wrap:wrap}.neu-home .neu-side__heading{display:none}}
.neu-home .neu-toggle__face{min-width:0}
@media (prefers-reduced-motion:reduce){.neu-btn,.neu-sidelink,.neu-switch__track,.neu-switch__track::before,.neu-toggle__face,.neu-toggle__icon,.neu-seg__opt span,.neu-play__face,.neu-dial__arc{transition:none}}
JavaScript
// Thermostat: minus / plus move the target in 0.5° steps and redraw the arc (--p is 0–100 of the range)
document.querySelectorAll('[data-neu-dial]').forEach(function (dial) {
  var min = +dial.dataset.min, max = +dial.dataset.max;
  var face = dial.querySelector('[data-neu-face]'), out = dial.querySelector('[data-neu-value]');
  dial.querySelectorAll('[data-step]').forEach(function (b) {
    b.addEventListener('click', function () {
      var t = Math.min(max, Math.max(min, parseFloat(out.textContent) + parseFloat(b.dataset.step)));
      out.textContent = t.toFixed(1);
      face.style.setProperty('--p', ((t - min) / (max - min) * 100).toFixed(1));
    });
  });
});

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-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-grid" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="7" height="7" rx="1.5"/><rect x="13" y="4" width="7" height="7" rx="1.5"/><rect x="4" y="13" width="7" height="7" rx="1.5"/><rect x="13" y="13" width="7" height="7" rx="1.5"/></symbol>
  <symbol id="neu-i-sofa" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M5 11V8a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v3"/><path d="M3 12a2 2 0 0 1 4 0v2h10v-2a2 2 0 0 1 4 0v5H3z"/><path d="M5 17v2M19 17v2"/></symbol>
  <symbol id="neu-i-star" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m12 3.5 2.6 5.4 5.9.8-4.3 4.1 1 5.8L12 16.8l-5.2 2.8 1-5.8-4.3-4.1 5.9-.8z"/></symbol>
  <symbol id="neu-i-bolt" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M13 3 5 13.5h6L10 21l8-10.5h-6z"/></symbol>
  <symbol id="neu-i-bell" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6 16v-5a6 6 0 0 1 12 0v5l1.5 2h-15zM10 20.5a2 2 0 0 0 4 0"/></symbol>
  <symbol id="neu-i-sliders" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h10M18 7h2M4 17h4M12 17h8"/><circle cx="16" cy="7" r="2"/><circle cx="10" cy="17" r="2"/></symbol>
  <symbol id="neu-i-logout" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M14 4h4.5a1.5 1.5 0 0 1 1.5 1.5v13a1.5 1.5 0 0 1-1.5 1.5H14M10 16.5 5.5 12 10 7.5M5.5 12H16"/></symbol>
  <symbol id="neu-i-thermo" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M14 14.5V5.5a2 2 0 0 0-4 0v9a4 4 0 1 0 4 0z"/><path d="M12 9.5V16"/></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>
  <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-arrowDown" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M6.5 13.5 12 19l5.5-5.5"/></symbol>
  <symbol id="neu-i-arrowUp" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19V5M6.5 10.5 12 5l5.5 5.5"/></symbol>
  <symbol id="neu-i-drop" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3.5s6 6.6 6 11a6 6 0 0 1-12 0c0-4.4 6-11 6-11z"/></symbol>
  <symbol id="neu-i-minus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/></symbol>
  <symbol id="neu-i-plus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></symbol>
  <symbol id="neu-i-bulb" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9.5 18h5M10.5 21h3M12 3a6 6 0 0 0-3.6 10.8c.6.5 1 1.2 1 2v.2h5.2v-.2c0-.8.4-1.5 1-2A6 6 0 0 0 12 3z"/></symbol>
  <symbol id="neu-i-play" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path fill="currentColor" d="M8 5.2v13.6L19 12z"/></symbol>
  <symbol id="neu-i-pause" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path fill="currentColor" stroke="none" d="M7 5h3.6v14H7zM13.4 5H17v14h-3.6z"/></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-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20 14.5A8 8 0 0 1 9.5 4a8 8 0 1 0 10.5 10.5z"/></symbol>
</svg>
<div class="neu-home" data-neu="light">
<nav class="card neu-card neu-side neu-home__side" aria-label="Main"><div class="card-body">
<p class="neu-home__brand"><span class="neu-home__mark"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-home"/></svg></span>Hearth</p>
<h2 class="neu-side__heading" id="hs-0">Home</h2><ul class="nav nav-pills flex-column" aria-labelledby="hs-0"><li class="nav-item"><a class="nav-link active" href="#" aria-current="page"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-grid"/></svg>Dashboard</a></li><li class="nav-item"><a class="nav-link" href="#"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-sofa"/></svg>Rooms</a></li><li class="nav-item"><a class="nav-link" href="#"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-star"/></svg>Scenes</a></li><li class="nav-item"><a class="nav-link" href="#"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-bolt"/></svg>Energy</a></li><li class="nav-item"><a class="nav-link" href="#"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-bell"/></svg>Alerts<span class="badge rounded-pill">1<span class="visually-hidden"> new</span></span></a></li></ul>
<h2 class="neu-side__heading" id="hs-1">Account</h2><ul class="nav nav-pills flex-column" aria-labelledby="hs-1"><li class="nav-item"><a class="nav-link" href="#"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-sliders"/></svg>Settings</a></li><li class="nav-item"><a class="nav-link" href="#"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-logout"/></svg>Sign out</a></li></ul>
</div></nav>
<div class="neu-home__main">
<header class="neu-home__head"><div><h1 class="neu-home__title">Good evening, Ada</h1><p class="neu-home__sub">Thursday 16 October · 7 devices on · 21.5 °C inside</p></div>
<div class="form-check form-switch neu-switch neu-home__theme"><input class="form-check-input neu-theme-input" type="checkbox" role="switch" id="theme-dark"><label class="form-check-label" for="theme-dark">Dark mode<small>Soft UI after sunset</small></label><span class="neu-switch-state" aria-hidden="true"></span></div></header>
<div class="neu-home__stats">
<article class="neu-stat"><span class="neu-stat__icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-bolt"/></svg></span><p class="neu-stat__label">Energy today</p><p class="neu-stat__value">12.4<small> kWh</small></p><p class="neu-stat__delta neu-stat__delta--good"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-arrowDown"/></svg>8% less than yesterday</p></article>
<article class="neu-stat"><span class="neu-stat__icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-sun"/></svg></span><p class="neu-stat__label">Solar now</p><p class="neu-stat__value">1.2<small> kW</small></p><p class="neu-stat__delta neu-stat__delta--good"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-arrowUp"/></svg>Battery at 82%</p></article>
<article class="neu-stat"><span class="neu-stat__icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-drop"/></svg></span><p class="neu-stat__label">Humidity</p><p class="neu-stat__value">46<small> %</small></p><p class="neu-stat__delta">Comfortable range</p></article>
<article class="neu-stat"><span class="neu-stat__icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-lock"/></svg></span><p class="neu-stat__label">Security</p><p class="neu-stat__value">Locked</p><p class="neu-stat__delta">All 3 doors, since 22:41</p></article>
</div>
<div class="neu-home__grid">
<section class="card neu-card neu-home__panel" aria-labelledby="p-climate"><div class="card-body"><h2 class="neu-home__h" id="p-climate">Climate<small>Heating</small></h2><div class="neu-dial" role="group" aria-label="Hallway thermostat" data-neu-dial data-min="10" data-max="30"><div class="neu-dial__face" style="--p:57.5" data-neu-face><span class="neu-dial__arc"></span><span class="neu-dial__core"><span class="neu-dial__mode">Heating to</span><span class="neu-dial__target" aria-live="polite"><span class="visually-hidden">Target </span><span data-neu-value>21.5</span><span aria-hidden="true">°</span><span class="visually-hidden"> Celsius</span></span><span class="neu-dial__now">Now 19.8 °C</span></span></div><div class="neu-dial__ctrl"><button class="btn btn-neu btn-neu-icon btn-neu-icon-sm" type="button" data-step="-0.5" aria-label="Lower target temperature"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-minus"/></svg></button><p class="neu-dial__name">Hallway</p><button class="btn btn-neu btn-neu-icon btn-neu-icon-sm" type="button" data-step="0.5" aria-label="Raise target temperature"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-plus"/></svg></button></div></div></div></section>
<section class="card neu-card neu-home__panel" aria-labelledby="p-lights"><div class="card-body"><h2 class="neu-home__h" id="p-lights">Lights<small>2 of 4 on</small></h2><div class="neu-home__lights"><div class="d-grid"><input class="btn-check" type="checkbox" id="h-kitchen" role="switch" checked autocomplete="off"><label class="btn btn-neu btn-neu-tile" for="h-kitchen"><span class="neu-tile-icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-bulb"/></svg></span><span class="neu-tile-name">Kitchen<span class="visually-hidden">, Pendants, 80%</span></span><span class="neu-tile-sub" aria-hidden="true">Pendants, 80%</span><span class="neu-tile-state" aria-hidden="true"></span></label></div><div class="d-grid"><input class="btn-check" type="checkbox" id="h-living" role="switch" checked autocomplete="off"><label class="btn btn-neu btn-neu-tile" for="h-living"><span class="neu-tile-icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-bulb"/></svg></span><span class="neu-tile-name">Living room<span class="visually-hidden">, Floor lamp</span></span><span class="neu-tile-sub" aria-hidden="true">Floor lamp</span><span class="neu-tile-state" aria-hidden="true"></span></label></div><div class="d-grid"><input class="btn-check" type="checkbox" id="h-hall" role="switch" autocomplete="off"><label class="btn btn-neu btn-neu-tile" for="h-hall"><span class="neu-tile-icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-bulb"/></svg></span><span class="neu-tile-name">Hallway<span class="visually-hidden">, Off at 23:00</span></span><span class="neu-tile-sub" aria-hidden="true">Off at 23:00</span><span class="neu-tile-state" aria-hidden="true"></span></label></div><div class="d-grid"><input class="btn-check" type="checkbox" id="h-porch" role="switch" autocomplete="off"><label class="btn btn-neu btn-neu-tile" for="h-porch"><span class="neu-tile-icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-bulb"/></svg></span><span class="neu-tile-name">Porch<span class="visually-hidden">, Motion sensor</span></span><span class="neu-tile-sub" aria-hidden="true">Motion sensor</span><span class="neu-tile-state" aria-hidden="true"></span></label></div></div></div></section>
<section class="card neu-card neu-home__panel neu-home__wide" aria-labelledby="p-scene"><div class="card-body"><h2 class="neu-home__h" id="p-scene">Scene and music</h2><div class="neu-home__row"><fieldset class="neu-seg"><legend class="">Active scene</legend><div class="btn-group"><input class="btn-check" type="radio" name="scene" id="scene-morning" value="morning" autocomplete="off"><label class="btn" for="scene-morning">Morning</label><input class="btn-check" type="radio" name="scene" id="scene-away" value="away" autocomplete="off"><label class="btn" for="scene-away">Away</label><input class="btn-check" type="radio" name="scene" id="scene-movie" value="movie" checked autocomplete="off"><label class="btn" for="scene-movie">Movie</label><input class="btn-check" type="radio" name="scene" id="scene-sleep" value="sleep" autocomplete="off"><label class="btn" for="scene-sleep">Sleep</label></div></fieldset><div class="neu-mini"><span class="neu-mini__art" aria-hidden="true"></span><div class="neu-mini__meta"><p class="neu-mini__title">Low Tide</p><p class="neu-mini__artist">Marla Quinn · Living room</p><div class="neu-mini__bar" style="--p:40%" role="progressbar" aria-label="Track position" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100"></div></div><label class="neu-play"><input class="visually-hidden" type="checkbox" aria-label="Play Low Tide"><span class="neu-play__face"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-play"/></svg><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-pause"/></svg></span></label></div><div class="alert neu-alert neu-alert--warning"><span class="neu-alert__icon"><svg class="neu-ico" aria-hidden="true" focusable="false"><use href="#neu-i-alert"/></svg></span><div><p class="alert-heading"><span class="visually-hidden">Warning: </span>Bedroom window open</p><p class="neu-alert__text">Heating paused until it is closed.</p></div></div></div></div></section>
</div>
</div>
</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}
/* Sidebar: .card holding .nav.nav-pills.flex-column; .active + aria-current = pressed in, accent, a dot */
.neu-side .card-body{display:grid;align-content:start;gap:.2rem;padding:1.1rem}
.neu-side .neu-side__heading{margin:.5rem .8rem .4rem;font-size:.72rem;font-weight:700;line-height:1.5;letter-spacing:.1em;text-transform:uppercase;color:var(--neu-muted)}
.neu-side .nav{--bs-nav-link-padding-x:.8rem;--bs-nav-link-padding-y:.55rem;--bs-nav-link-color:var(--neu-muted);--bs-nav-link-hover-color:var(--neu-ink);--bs-nav-link-font-weight:600;
  --bs-nav-pills-border-radius:calc(var(--neu-radius)*.6);--bs-nav-pills-link-active-bg:var(--neu-bg);--bs-nav-pills-link-active-color:var(--neu-accent);gap:6px}
.neu-side .nav-link{display:flex;align-items:center;gap:.75rem;min-height:44px;border:var(--neu-bw) solid transparent;transition:box-shadow .2s,color .2s}
.neu-side .nav-link:hover{box-shadow:var(--neu-raised-sm)}
.neu-side .nav-link.active{border-color:var(--neu-accent);box-shadow:var(--neu-inset-sm)}
.neu-side .nav-link.active::after{content:"";width:8px;height:8px;margin-left:auto;border-radius:50%;background:currentColor}
.neu-side .nav-link:focus-visible{outline:3px solid var(--neu-accent);outline-offset:2px;box-shadow:none}
.neu-side .badge{--bs-badge-font-size:.75rem;--bs-badge-padding-x:.45rem;--bs-badge-padding-y:.25rem;--bs-badge-color:var(--neu-on-accent);margin-left:auto;min-width:24px;background:var(--neu-accent)}
/* Switches: Bootstrap .form-check.form-switch. The knob is a token-coloured radial gradient so it follows light and dark */
.neu-switch{display:flex;align-items:center;gap:.9rem;min-height:0;margin:0;padding:0}
.neu-switch .form-check-label{flex:1;min-width:0;font-weight:600;line-height:1.3;cursor:pointer}
.neu-switch .form-check-label small{display:block;margin-top:.15rem;font-size:.82rem;font-weight:400;color:var(--neu-muted)}
.neu-switch .neu-switch-state{min-width:2.1em;font-size:.75rem;font-weight:700;letter-spacing:.08em;text-align:right;text-transform:uppercase;color:var(--neu-muted)}
.neu-switch .neu-switch-state::after{content:"Off"}
.neu-switch.form-switch .form-check-input,.neu-switch.form-switch .form-check-input:focus,.neu-switch.form-switch .form-check-input:checked{
  --bs-form-switch-bg:radial-gradient(circle at 50% 50%,var(--neu-knob) 0 10.5px,var(--neu-knob-edge) 11px 12px,transparent 12.5px),radial-gradient(circle at 58% 60%,var(--neu-dark) 0 9px,transparent 14px)}
.neu-switch .form-check-input{--neu-knob:var(--neu-bg);--neu-knob-edge:var(--neu-edge);
  order:3;flex:none;float:none;width:58px;height:32px;margin:0;border:var(--neu-bw) solid var(--neu-edge);border-radius:999px;
  background-color:var(--neu-bg);background-size:30px 30px;background-position:left center;cursor:pointer;
  box-shadow:var(--neu-inset-sm);transition:background-position .25s,background-color .25s,border-color .25s}
.neu-switch .form-check-input:focus{border-color:var(--neu-edge);box-shadow:var(--neu-inset-sm)}
.neu-switch .form-check-input:checked{--neu-knob:var(--neu-on-accent);--neu-knob-edge:var(--neu-on-accent);background-color:var(--neu-accent);border-color:var(--neu-accent);background-position:right center}
.neu-switch .form-check-input:focus-visible{outline:3px solid var(--neu-accent);outline-offset:3px}
.neu-switch .form-check-input:checked~.neu-switch-state{color:var(--neu-accent)}
.neu-switch .form-check-input:checked~.neu-switch-state::after{content:"On"}
/* Stat tile: icon in a pressed well, label, a big value, and a change line that says which way in words */
.neu-stat{display:grid;gap:.2rem;padding:1.25rem;border:var(--neu-bw) solid var(--neu-line);border-radius:var(--neu-radius);background:var(--neu-bg);box-shadow:var(--neu-raised)}
.neu-stat__icon{display:grid;place-items:center;width:44px;height:44px;margin-bottom:.6rem;border-radius:50%;color:var(--neu-accent);box-shadow:var(--neu-inset-sm)}
.neu-stat__label{margin:0;font-size:.85rem;font-weight:600;color:var(--neu-muted)}
.neu-stat__value{margin:0;font-size:1.9rem;font-weight:700;line-height:1.15;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.neu-stat__value small{font-size:.9rem;font-weight:600;letter-spacing:0;color:var(--neu-muted)}
.neu-stat__delta{display:flex;align-items:center;gap:.3rem;margin:.35rem 0 0;font-size:.82rem;font-weight:600;color:var(--neu-muted)}
.neu-stat__delta .neu-ico{width:16px;height:16px}
.neu-stat__delta--good{color:var(--neu-success)}
.neu-stat__delta--warn{color:var(--neu-warning)}
/* Thermostat: a 270° conic-gradient arc in a pressed groove, a raised core with the target,
   and minus / plus buttons. A few lines of script change the target and the arc (--p, 0–100). */
.neu-dial{display:grid;justify-items:center;gap:1.1rem}
.neu-dial__face{--p:50;position:relative;display:grid;place-items:center;width:216px;aspect-ratio:1;border:var(--neu-bw) solid var(--neu-line);border-radius:50%;background:var(--neu-bg);box-shadow:var(--neu-raised)}
.neu-dial__arc{position:absolute;inset:12px;border-radius:50%;box-shadow:var(--neu-inset-sm);
  background:conic-gradient(from 225deg,var(--neu-accent) calc(var(--p)*.75%),transparent 0);
  -webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 14px),#000 calc(100% - 13.5px));mask:radial-gradient(farthest-side,transparent calc(100% - 14px),#000 calc(100% - 13.5px));transition:background .3s}
.neu-dial__core{position:relative;display:grid;place-items:center;align-content:center;width:142px;aspect-ratio:1;border-radius:50%;box-shadow:var(--neu-raised-sm);text-align:center}
.neu-dial__mode{font-size:.75rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--neu-accent)}
.neu-dial__target{margin:0;font-size:2.6rem;font-weight:700;line-height:1.05;letter-spacing:-.03em;font-variant-numeric:tabular-nums}
.neu-dial__now{font-size:.8rem;color:var(--neu-muted)}
.neu-dial__ctrl{display:flex;align-items:center;gap:1.4rem}
.neu-dial__name{margin:0;font-weight:600}
/* Toggle tiles: Bootstrap .btn-check + .btn. On = pressed in, accent border and icon, a filled dot and the word On */
.btn-neu-tile{--bs-btn-padding-x:1.1rem;--bs-btn-padding-y:1rem;--bs-btn-border-radius:var(--neu-radius);--bs-btn-font-weight:400;--bs-btn-line-height:1.5;--bs-btn-font-size:1rem;
  --bs-btn-active-color:var(--neu-ink);--bs-btn-active-border-color:var(--neu-accent);
  flex-direction:column;align-items:flex-start;gap:.4rem;width:100%;min-width:132px;text-align:start;transition:box-shadow .25s,border-color .25s}
.btn-neu-tile:hover{--neu-btn-shadow:var(--neu-raised-sm)}
.btn-check:checked+.btn-neu-tile{--neu-btn-shadow:var(--neu-inset)}
.btn-neu-tile .neu-tile-icon{display:grid;place-items:center;width:42px;height:42px;margin-bottom:.35rem;border-radius:50%;color:var(--neu-muted);box-shadow:var(--neu-inset-sm);transition:color .25s,background-color .25s}
.btn-neu-tile .neu-tile-icon .neu-ico{width:22px;height:22px}
.btn-neu-tile .neu-tile-name{font-weight:600;line-height:1.25}
.btn-neu-tile .neu-tile-state{display:flex;align-items:center;gap:.4rem;font-size:.8rem;font-weight:600;color:var(--neu-muted)}
.btn-neu-tile .neu-tile-state::before{content:"";width:9px;height:9px;border:2px solid currentColor;border-radius:50%}
.btn-neu-tile .neu-tile-state::after{content:"Off"}
.btn-check:checked+.btn-neu-tile .neu-tile-icon{color:var(--neu-on-accent);background:var(--neu-accent)}
.btn-check:checked+.btn-neu-tile .neu-tile-state{color:var(--neu-accent)}
.btn-check:checked+.btn-neu-tile .neu-tile-state::before{background:currentColor}
.btn-check:checked+.btn-neu-tile .neu-tile-state::after{content:"On"}
.btn-neu-tile .neu-tile-sub{margin-top:-.3rem;font-size:.8rem;color:var(--neu-muted)}
/* Segmented control: .btn-group of .btn-check radios. The chosen option rises, turns accent and gains a dot */
.neu-seg{min-width:0;margin:0;padding:0;border:0}
.neu-seg legend{float:none;width:auto;margin-bottom:.6rem;padding:0;font-size:.88rem;font-weight:600}
.neu-seg .btn-group{display:flex;flex-wrap:wrap;gap:6px;width:100%;padding:6px;border:var(--neu-bw) solid var(--neu-edge);border-radius:calc(var(--neu-radius)*.75);box-shadow:var(--neu-inset-sm)}
.neu-seg .btn{--bs-btn-padding-x:.9rem;--bs-btn-padding-y:.4rem;--bs-btn-font-size:.9rem;--bs-btn-font-weight:600;--bs-btn-color:var(--neu-muted);--bs-btn-border-color:transparent;
  --bs-btn-hover-color:var(--neu-ink);--bs-btn-hover-border-color:transparent;--bs-btn-active-color:var(--neu-accent);--bs-btn-active-border-color:var(--neu-accent);--bs-btn-active-bg:transparent;
  flex:1 1 auto;display:flex;align-items:center;justify-content:center;gap:.4rem;min-height:40px;border-radius:calc(var(--neu-radius)*.5)!important;margin:0!important;transition:box-shadow .2s,color .2s}
.neu-seg .btn-check:checked+.btn{box-shadow:var(--neu-raised-sm)}
.neu-seg .btn-check:checked+.btn::before{content:"";width:7px;height:7px;border-radius:50%;background:currentColor}
.neu-seg .btn-check:focus-visible+.btn{outline:3px solid var(--neu-accent);outline-offset:2px;box-shadow:var(--neu-raised-sm)}
/* Mini player: art in a pressed well, title, a progress groove, and a play / pause toggle (checkbox) */
.neu-mini{display:flex;align-items:center;gap:1rem;padding:1rem 1.1rem;border:var(--neu-bw) solid var(--neu-line);border-radius:var(--neu-radius);background:var(--neu-bg);box-shadow:var(--neu-raised)}
.neu-mini__art{flex:none;width:52px;height:52px;border-radius:calc(var(--neu-radius)*.6);box-shadow:var(--neu-inset-sm);
  background:radial-gradient(circle at 30% 30%,#f59e0b 0 18%,transparent 19%),linear-gradient(160deg,#4f46e5,#0e7490)}
.neu-mini__meta{flex:1;min-width:0}
.neu-mini__title{margin:0;font-weight:700;line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.neu-mini__artist{margin:0;font-size:.82rem;color:var(--neu-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.neu-mini__bar{height:8px;margin-top:.55rem;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(--p,40%) 100% no-repeat}
.neu-play{position:relative;flex:none;display:inline-flex}
.neu-play__face{display:grid;place-items:center;width:52px;height:52px;border:var(--neu-bw) solid var(--neu-accent);border-radius:50%;
  background:var(--neu-accent);color:var(--neu-on-accent);box-shadow:var(--neu-raised-sm);cursor:pointer;transition:box-shadow .2s}
.neu-play__face .neu-ico{width:24px;height:24px}
.neu-play__face .neu-ico+.neu-ico,.neu-play input:checked+.neu-play__face .neu-ico:first-child{display:none}
.neu-play input:checked+.neu-play__face .neu-ico+.neu-ico{display:block}
.neu-play input:checked+.neu-play__face{box-shadow:var(--neu-inset-sm)}
.neu-play input:focus-visible+.neu-play__face{outline:3px solid var(--neu-accent);outline-offset:3px}
/* Alerts (.alert with --bs-alert-* set to the kit): the type is carried by an icon, a title and hidden "Warning:" style text, not by colour alone */
.neu-alerts{display:grid;gap:16px}
.alert.neu-alert{--bs-alert-bg:var(--neu-bg);--bs-alert-color:var(--neu-ink);--bs-alert-border-color:var(--neu-line);--bs-alert-margin-bottom:0;--tone:var(--neu-accent);position:relative;display:flex;align-items:flex-start;gap:.9rem;padding:1rem 1.1rem 1rem 1.35rem;border:var(--neu-bw) solid var(--neu-line);
  border-radius:var(--neu-radius);background:var(--neu-bg);box-shadow:var(--neu-raised-sm)}
.neu-alert::before{content:"";position:absolute;left:.55rem;top:1rem;bottom:1rem;width:4px;border-radius:4px;background:var(--tone)}
.alert.neu-alert--success{--tone:var(--neu-success)}.alert.neu-alert--warning{--tone:var(--neu-warning)}.alert.neu-alert--danger{--tone:var(--neu-danger)}
.neu-alert__icon{display:grid;place-items:center;flex:none;width:40px;height:40px;border-radius:50%;color:var(--tone);box-shadow:var(--neu-inset-sm)}
.neu-alert .alert-heading{margin:0;font-size:1rem;color:var(--neu-ink);font-weight:700;line-height:1.3}
.neu-alert__text{margin:.15rem 0 0;font-size:.9rem;color:var(--neu-muted)}
/* Dashboard shell. The theme switch is a checkbox with class .neu-theme-input: the token block's
   [data-neu]:has(.neu-theme-input:checked) rule swaps every token to dark, so no script is involved */
.neu-home{display:grid;grid-template-columns:250px minmax(0,1fr);gap:32px;min-height:100vh;padding:28px}
.neu-home__side{position:sticky;top:28px;align-self:start}
.neu-home__brand{display:flex;align-items:center;gap:.65rem;margin:0 .4rem .9rem;font-size:1.1rem;font-weight:800}
.neu-home__mark{display:grid;place-items:center;width:40px;height:40px;border-radius:50%;color:var(--neu-accent);box-shadow:var(--neu-inset-sm)}
.neu-home__main{display:grid;grid-template-columns:minmax(0,1fr);align-content:start;gap:28px;min-width:0}
.neu-home__head{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:16px 24px}
.neu-home__title{margin:0;font-size:1.75rem;font-weight:800;line-height:1.2;letter-spacing:-.02em}
.neu-home__sub{margin:.25rem 0 0;color:var(--neu-muted)}
.neu-home__theme{min-width:250px;padding:.7rem 1rem;border:var(--neu-bw) solid var(--neu-line);border-radius:calc(var(--neu-radius)*.75);box-shadow:var(--neu-raised-sm)}
.neu-home__stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,190px),1fr));gap:22px}
.neu-home__grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.25fr);gap:22px;align-items:start}
.neu-home__wide{grid-column:1/-1}
.neu-home__row{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr));gap:22px;align-items:center}
.neu-home__row>:last-child{grid-column:1/-1}
.neu-home__panel .card-body{display:grid;grid-template-columns:minmax(0,1fr);gap:1.1rem}
.neu-home__h{display:flex;justify-content:space-between;align-items:baseline;gap:.5rem;margin:0;font-size:1rem;font-weight:700}
.neu-home__h small{font-size:.82rem;font-weight:600;color:var(--neu-muted)}
.neu-home__lights{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}
@media (max-width:1100px){.neu-home__grid{grid-template-columns:minmax(0,1fr)}}
@media (max-width:900px){.neu-home{grid-template-columns:minmax(0,1fr);gap:24px;padding:16px}.neu-home__side{position:static}
  .neu-home .neu-side .nav{flex-direction:row!important;flex-wrap:wrap}.neu-home .neu-side__heading{display:none}}
.neu-home .btn-neu-tile{min-width:0}
.neu-home__theme.form-check{padding:.7rem 1rem}
@media (prefers-reduced-motion:reduce){.btn-neu,.neu-side .nav-link,.neu-switch .form-check-input,.btn-neu-tile .neu-tile-icon,.neu-seg .btn,.neu-play__face,.neu-dial__arc{transition:none}}
JavaScript
// Thermostat: minus / plus move the target in 0.5° steps and redraw the arc (--p is 0–100 of the range)
document.querySelectorAll('[data-neu-dial]').forEach(function (dial) {
  var min = +dial.dataset.min, max = +dial.dataset.max;
  var face = dial.querySelector('[data-neu-face]'), out = dial.querySelector('[data-neu-value]');
  dial.querySelectorAll('[data-step]').forEach(function (b) {
    b.addEventListener('click', function () {
      var t = Math.min(max, Math.max(min, parseFloat(out.textContent) + parseFloat(b.dataset.step)));
      out.textContent = t.toFixed(1);
      face.style.setProperty('--p', ((t - min) / (max - min) * 100).toFixed(1));
    });
  });
});

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-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-grid" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="7" height="7" rx="1.5"/><rect x="13" y="4" width="7" height="7" rx="1.5"/><rect x="4" y="13" width="7" height="7" rx="1.5"/><rect x="13" y="13" width="7" height="7" rx="1.5"/></symbol>
  <symbol id="neu-i-sofa" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M5 11V8a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v3"/><path d="M3 12a2 2 0 0 1 4 0v2h10v-2a2 2 0 0 1 4 0v5H3z"/><path d="M5 17v2M19 17v2"/></symbol>
  <symbol id="neu-i-star" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m12 3.5 2.6 5.4 5.9.8-4.3 4.1 1 5.8L12 16.8l-5.2 2.8 1-5.8-4.3-4.1 5.9-.8z"/></symbol>
  <symbol id="neu-i-bolt" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M13 3 5 13.5h6L10 21l8-10.5h-6z"/></symbol>
  <symbol id="neu-i-bell" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6 16v-5a6 6 0 0 1 12 0v5l1.5 2h-15zM10 20.5a2 2 0 0 0 4 0"/></symbol>
  <symbol id="neu-i-sliders" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h10M18 7h2M4 17h4M12 17h8"/><circle cx="16" cy="7" r="2"/><circle cx="10" cy="17" r="2"/></symbol>
  <symbol id="neu-i-logout" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M14 4h4.5a1.5 1.5 0 0 1 1.5 1.5v13a1.5 1.5 0 0 1-1.5 1.5H14M10 16.5 5.5 12 10 7.5M5.5 12H16"/></symbol>
  <symbol id="neu-i-thermo" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M14 14.5V5.5a2 2 0 0 0-4 0v9a4 4 0 1 0 4 0z"/><path d="M12 9.5V16"/></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>
  <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-arrowDown" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M6.5 13.5 12 19l5.5-5.5"/></symbol>
  <symbol id="neu-i-arrowUp" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19V5M6.5 10.5 12 5l5.5 5.5"/></symbol>
  <symbol id="neu-i-drop" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3.5s6 6.6 6 11a6 6 0 0 1-12 0c0-4.4 6-11 6-11z"/></symbol>
  <symbol id="neu-i-minus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/></symbol>
  <symbol id="neu-i-plus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></symbol>
  <symbol id="neu-i-bulb" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9.5 18h5M10.5 21h3M12 3a6 6 0 0 0-3.6 10.8c.6.5 1 1.2 1 2v.2h5.2v-.2c0-.8.4-1.5 1-2A6 6 0 0 0 12 3z"/></symbol>
  <symbol id="neu-i-play" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path fill="currentColor" d="M8 5.2v13.6L19 12z"/></symbol>
  <symbol id="neu-i-pause" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path fill="currentColor" stroke="none" d="M7 5h3.6v14H7zM13.4 5H17v14h-3.6z"/></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-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20 14.5A8 8 0 0 1 9.5 4a8 8 0 1 0 10.5 10.5z"/></symbol>
</svg>
<div class="grid min-h-screen grid-cols-[minmax(0,1fr)] gap-8 bg-neu-bg p-7 text-neu-ink min-[901px]:grid-cols-[250px_minmax(0,1fr)] max-[900px]:gap-6 max-[900px]:p-4" data-neu="light">
<nav class="grid content-start gap-[.2rem] self-start rounded-neu border-(length:--neu-bw) border-neu-line bg-neu-bg p-[1.1rem] text-neu-ink shadow-neu min-[901px]:sticky min-[901px]:top-7" aria-label="Main">
<p class="mx-[.4rem] mb-[.9rem] flex items-center gap-[.65rem] text-[1.1rem] font-extrabold"><span class="grid size-10 place-items-center rounded-full text-neu-accent shadow-neu-in-sm"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-home"/></svg></span>Hearth</p>
<h2 class="mx-[.8rem] mt-2 mb-[.4rem] text-[.72rem] font-bold tracking-[.1em] text-neu-muted uppercase max-[900px]:hidden" id="hs-0">Home</h2><ul class="m-0 grid list-none gap-1.5 p-0 max-[900px]:flex max-[900px]:flex-wrap" aria-labelledby="hs-0"><li><a class="flex min-h-11 items-center gap-3 rounded-neu-field border-(length:--neu-bw) border-transparent px-[.8rem] py-[.55rem] font-semibold text-neu-muted no-underline transition-[box-shadow,color] duration-200 hover:text-neu-ink hover:shadow-neu-sm aria-[current=page]:border-neu-accent aria-[current=page]:text-neu-accent aria-[current=page]:shadow-neu-in-sm aria-[current=page]:after:ml-auto aria-[current=page]:after:size-2 aria-[current=page]:after:rounded-full aria-[current=page]:after:bg-current motion-reduce:transition-none focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-neu-accent" href="#" aria-current="page"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-grid"/></svg>Dashboard</a></li><li><a class="flex min-h-11 items-center gap-3 rounded-neu-field border-(length:--neu-bw) border-transparent px-[.8rem] py-[.55rem] font-semibold text-neu-muted no-underline transition-[box-shadow,color] duration-200 hover:text-neu-ink hover:shadow-neu-sm aria-[current=page]:border-neu-accent aria-[current=page]:text-neu-accent aria-[current=page]:shadow-neu-in-sm aria-[current=page]:after:ml-auto aria-[current=page]:after:size-2 aria-[current=page]:after:rounded-full aria-[current=page]:after:bg-current motion-reduce:transition-none focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-neu-accent" href="#"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-sofa"/></svg>Rooms</a></li><li><a class="flex min-h-11 items-center gap-3 rounded-neu-field border-(length:--neu-bw) border-transparent px-[.8rem] py-[.55rem] font-semibold text-neu-muted no-underline transition-[box-shadow,color] duration-200 hover:text-neu-ink hover:shadow-neu-sm aria-[current=page]:border-neu-accent aria-[current=page]:text-neu-accent aria-[current=page]:shadow-neu-in-sm aria-[current=page]:after:ml-auto aria-[current=page]:after:size-2 aria-[current=page]:after:rounded-full aria-[current=page]:after:bg-current motion-reduce:transition-none focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-neu-accent" href="#"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-star"/></svg>Scenes</a></li><li><a class="flex min-h-11 items-center gap-3 rounded-neu-field border-(length:--neu-bw) border-transparent px-[.8rem] py-[.55rem] font-semibold text-neu-muted no-underline transition-[box-shadow,color] duration-200 hover:text-neu-ink hover:shadow-neu-sm aria-[current=page]:border-neu-accent aria-[current=page]:text-neu-accent aria-[current=page]:shadow-neu-in-sm aria-[current=page]:after:ml-auto aria-[current=page]:after:size-2 aria-[current=page]:after:rounded-full aria-[current=page]:after:bg-current motion-reduce:transition-none focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-neu-accent" href="#"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-bolt"/></svg>Energy</a></li><li><a class="flex min-h-11 items-center gap-3 rounded-neu-field border-(length:--neu-bw) border-transparent px-[.8rem] py-[.55rem] font-semibold text-neu-muted no-underline transition-[box-shadow,color] duration-200 hover:text-neu-ink hover:shadow-neu-sm aria-[current=page]:border-neu-accent aria-[current=page]:text-neu-accent aria-[current=page]:shadow-neu-in-sm aria-[current=page]:after:ml-auto aria-[current=page]:after:size-2 aria-[current=page]:after:rounded-full aria-[current=page]:after:bg-current motion-reduce:transition-none focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-neu-accent" href="#"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-bell"/></svg>Alerts<span class="ml-auto min-w-6 rounded-full bg-neu-accent px-[.45rem] py-[.1rem] text-center text-[.75rem] font-bold text-neu-on-accent">1<span class="sr-only"> new</span></span></a></li></ul>
<h2 class="mx-[.8rem] mt-2 mb-[.4rem] text-[.72rem] font-bold tracking-[.1em] text-neu-muted uppercase max-[900px]:hidden" id="hs-1">Account</h2><ul class="m-0 grid list-none gap-1.5 p-0 max-[900px]:flex max-[900px]:flex-wrap" aria-labelledby="hs-1"><li><a class="flex min-h-11 items-center gap-3 rounded-neu-field border-(length:--neu-bw) border-transparent px-[.8rem] py-[.55rem] font-semibold text-neu-muted no-underline transition-[box-shadow,color] duration-200 hover:text-neu-ink hover:shadow-neu-sm aria-[current=page]:border-neu-accent aria-[current=page]:text-neu-accent aria-[current=page]:shadow-neu-in-sm aria-[current=page]:after:ml-auto aria-[current=page]:after:size-2 aria-[current=page]:after:rounded-full aria-[current=page]:after:bg-current motion-reduce:transition-none focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-neu-accent" href="#"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-sliders"/></svg>Settings</a></li><li><a class="flex min-h-11 items-center gap-3 rounded-neu-field border-(length:--neu-bw) border-transparent px-[.8rem] py-[.55rem] font-semibold text-neu-muted no-underline transition-[box-shadow,color] duration-200 hover:text-neu-ink hover:shadow-neu-sm aria-[current=page]:border-neu-accent aria-[current=page]:text-neu-accent aria-[current=page]:shadow-neu-in-sm aria-[current=page]:after:ml-auto aria-[current=page]:after:size-2 aria-[current=page]:after:rounded-full aria-[current=page]:after:bg-current motion-reduce:transition-none focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-neu-accent" href="#"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-logout"/></svg>Sign out</a></li></ul>
</nav>
<div class="grid min-w-0 grid-cols-[minmax(0,1fr)] content-start gap-7">
<header class="flex flex-wrap items-center justify-between gap-x-6 gap-y-4"><div><h1 class="text-[1.75rem] leading-[1.2] font-extrabold tracking-[-.02em]">Good evening, Ada</h1><p class="mt-1 text-neu-muted">Thursday 16 October · 7 devices on · 21.5 °C inside</p></div>
<label class="group relative flex min-w-[250px] cursor-pointer items-center gap-[.9rem] rounded-neu-btn border-(length:--neu-bw) border-neu-line px-4 py-[.7rem] shadow-neu-sm"><input class="peer sr-only neu-theme-input" type="checkbox" role="switch"><span class="min-w-0 flex-1 leading-[1.3] font-semibold">Dark mode<small class="mt-[.15rem] block text-[.82rem] font-normal text-neu-muted">Soft UI after sunset</small></span><span class="min-w-[2.1em] text-right text-[.75rem] font-bold tracking-[.08em] text-neu-muted uppercase after:content-['Off'] group-has-checked:text-neu-accent group-has-checked:after:content-['On']" aria-hidden="true"></span><span class="relative h-8 w-[58px] flex-none rounded-full border-(length:--neu-bw) border-neu-edge bg-neu-bg shadow-neu-in-sm transition-colors duration-[250ms] peer-checked:border-neu-accent peer-checked:bg-neu-accent motion-reduce:transition-none peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-neu-accent before:absolute before:top-1/2 before:left-[3px] before:-mt-3 before:size-6 before:rounded-full before:border-(length:--neu-bw) before:border-neu-edge before:bg-neu-bg before:shadow-neu-sm before:transition-[translate,background-color] before:duration-[250ms] peer-checked:before:translate-x-[calc(28px-2*var(--neu-bw))] peer-checked:before:border-neu-on-accent peer-checked:before:bg-neu-on-accent motion-reduce:before:transition-none" aria-hidden="true"></span></label></header>
<div class="grid grid-cols-[repeat(auto-fit,minmax(min(100%,190px),1fr))] gap-[22px]">
<article class="grid gap-[.2rem] rounded-neu border-(length:--neu-bw) border-neu-line bg-neu-bg p-5 shadow-neu"><span class="mb-[.6rem] grid size-11 place-items-center rounded-full text-neu-accent shadow-neu-in-sm"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-bolt"/></svg></span><p class="text-[.85rem] font-semibold text-neu-muted">Energy today</p><p class="text-[1.9rem] leading-[1.15] font-bold tracking-[-.02em] tabular-nums">12.4<small class="text-[.9rem] font-semibold tracking-normal text-neu-muted"> kWh</small></p><p class="mt-[.35rem] flex items-center gap-[.3rem] text-[.82rem] font-semibold text-neu-success"><svg class="size-4 shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-arrowDown"/></svg>8% less than yesterday</p></article>
<article class="grid gap-[.2rem] rounded-neu border-(length:--neu-bw) border-neu-line bg-neu-bg p-5 shadow-neu"><span class="mb-[.6rem] grid size-11 place-items-center rounded-full text-neu-accent shadow-neu-in-sm"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-sun"/></svg></span><p class="text-[.85rem] font-semibold text-neu-muted">Solar now</p><p class="text-[1.9rem] leading-[1.15] font-bold tracking-[-.02em] tabular-nums">1.2<small class="text-[.9rem] font-semibold tracking-normal text-neu-muted"> kW</small></p><p class="mt-[.35rem] flex items-center gap-[.3rem] text-[.82rem] font-semibold text-neu-success"><svg class="size-4 shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-arrowUp"/></svg>Battery at 82%</p></article>
<article class="grid gap-[.2rem] rounded-neu border-(length:--neu-bw) border-neu-line bg-neu-bg p-5 shadow-neu"><span class="mb-[.6rem] grid size-11 place-items-center rounded-full text-neu-accent shadow-neu-in-sm"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-drop"/></svg></span><p class="text-[.85rem] font-semibold text-neu-muted">Humidity</p><p class="text-[1.9rem] leading-[1.15] font-bold tracking-[-.02em] tabular-nums">46<small class="text-[.9rem] font-semibold tracking-normal text-neu-muted"> %</small></p><p class="mt-[.35rem] flex items-center gap-[.3rem] text-[.82rem] font-semibold text-neu-muted">Comfortable range</p></article>
<article class="grid gap-[.2rem] rounded-neu border-(length:--neu-bw) border-neu-line bg-neu-bg p-5 shadow-neu"><span class="mb-[.6rem] grid size-11 place-items-center rounded-full text-neu-accent shadow-neu-in-sm"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-lock"/></svg></span><p class="text-[.85rem] font-semibold text-neu-muted">Security</p><p class="text-[1.9rem] leading-[1.15] font-bold tracking-[-.02em] tabular-nums">Locked</p><p class="mt-[.35rem] flex items-center gap-[.3rem] text-[.82rem] font-semibold text-neu-muted">All 3 doors, since 22:41</p></article>
</div>
<div class="grid items-start gap-[22px] min-[1101px]:grid-cols-[minmax(0,1fr)_minmax(0,1.25fr)]">
<section class="rounded-neu border-(length:--neu-bw) border-neu-line bg-neu-bg text-neu-ink shadow-neu grid grid-cols-[minmax(0,1fr)] gap-[1.1rem] p-6" aria-labelledby="p-climate"><h2 class="flex items-baseline justify-between gap-2 text-base font-bold" id="p-climate">Climate<small class="text-[.82rem] font-semibold text-neu-muted">Heating</small></h2><div class="grid justify-items-center gap-[1.1rem]" role="group" aria-label="Hallway thermostat" data-neu-dial data-min="10" data-max="30"><div class="relative grid aspect-square w-[216px] place-items-center rounded-full border-(length:--neu-bw) border-neu-line bg-neu-bg shadow-neu" style="--p:57.5" data-neu-face><span class="absolute inset-3 rounded-full bg-[conic-gradient(from_225deg,var(--neu-accent)_calc(var(--p)*.75%),transparent_0)] shadow-neu-in-sm transition-[background] duration-300 [mask:radial-gradient(farthest-side,transparent_calc(100%-14px),#000_calc(100%-13.5px))] motion-reduce:transition-none"></span><span class="relative grid aspect-square w-[142px] place-items-center content-center rounded-full text-center shadow-neu-sm"><span class="text-[.75rem] font-bold tracking-[.1em] text-neu-accent uppercase">Heating to</span><span class="text-[2.6rem] leading-[1.05] font-bold tracking-[-.03em] tabular-nums" aria-live="polite"><span class="sr-only">Target </span><span data-neu-value>21.5</span><span aria-hidden="true">°</span><span class="sr-only"> Celsius</span></span><span class="text-[.8rem] text-neu-muted">Now 19.8 °C</span></span></div><div class="flex items-center gap-[1.4rem]"><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 size-[42px] rounded-full border-neu-edge bg-neu-bg text-neu-ink" type="button" data-step="-0.5" aria-label="Lower target temperature"><svg class="size-[22px] shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-minus"/></svg></button><p class="font-semibold">Hallway</p><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 size-[42px] rounded-full border-neu-edge bg-neu-bg text-neu-ink" type="button" data-step="0.5" aria-label="Raise target temperature"><svg class="size-[22px] shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-plus"/></svg></button></div></div></section>
<section class="rounded-neu border-(length:--neu-bw) border-neu-line bg-neu-bg text-neu-ink shadow-neu grid grid-cols-[minmax(0,1fr)] gap-[1.1rem] p-6" aria-labelledby="p-lights"><h2 class="flex items-baseline justify-between gap-2 text-base font-bold" id="p-lights">Lights<small class="text-[.82rem] font-semibold text-neu-muted">2 of 4 on</small></h2><div class="grid grid-cols-2 gap-4"><label class="group relative inline-flex cursor-pointer"><input class="peer sr-only" type="checkbox" role="switch" checked><span class="flex w-full min-w-0 flex-col items-start gap-[.4rem] rounded-neu border-(length:--neu-bw) border-neu-edge bg-neu-bg px-[1.1rem] py-4 text-neu-ink shadow-neu-sm transition-[box-shadow,border-color] duration-[250ms] peer-checked:border-neu-accent peer-checked:shadow-neu-in motion-reduce:transition-none peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-neu-accent"><span class="mb-[.35rem] grid size-[42px] place-items-center rounded-full text-neu-muted shadow-neu-in-sm transition-colors duration-[250ms] group-has-checked:bg-neu-accent group-has-checked:text-neu-on-accent motion-reduce:transition-none"><svg class="size-[22px] shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-bulb"/></svg></span><span class="leading-[1.25] font-semibold">Kitchen<span class="sr-only">, Pendants, 80%</span></span><span class="-mt-[.3rem] text-[.8rem] text-neu-muted" aria-hidden="true">Pendants, 80%</span><span class="flex items-center gap-[.4rem] text-[.8rem] font-semibold text-neu-muted before:size-[9px] before:rounded-full before:border-2 before:border-current after:content-['Off'] group-has-checked:text-neu-accent group-has-checked:before:bg-current group-has-checked:after:content-['On']" aria-hidden="true"></span></span></label><label class="group relative inline-flex cursor-pointer"><input class="peer sr-only" type="checkbox" role="switch" checked><span class="flex w-full min-w-0 flex-col items-start gap-[.4rem] rounded-neu border-(length:--neu-bw) border-neu-edge bg-neu-bg px-[1.1rem] py-4 text-neu-ink shadow-neu-sm transition-[box-shadow,border-color] duration-[250ms] peer-checked:border-neu-accent peer-checked:shadow-neu-in motion-reduce:transition-none peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-neu-accent"><span class="mb-[.35rem] grid size-[42px] place-items-center rounded-full text-neu-muted shadow-neu-in-sm transition-colors duration-[250ms] group-has-checked:bg-neu-accent group-has-checked:text-neu-on-accent motion-reduce:transition-none"><svg class="size-[22px] shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-bulb"/></svg></span><span class="leading-[1.25] font-semibold">Living room<span class="sr-only">, Floor lamp</span></span><span class="-mt-[.3rem] text-[.8rem] text-neu-muted" aria-hidden="true">Floor lamp</span><span class="flex items-center gap-[.4rem] text-[.8rem] font-semibold text-neu-muted before:size-[9px] before:rounded-full before:border-2 before:border-current after:content-['Off'] group-has-checked:text-neu-accent group-has-checked:before:bg-current group-has-checked:after:content-['On']" aria-hidden="true"></span></span></label><label class="group relative inline-flex cursor-pointer"><input class="peer sr-only" type="checkbox" role="switch"><span class="flex w-full min-w-0 flex-col items-start gap-[.4rem] rounded-neu border-(length:--neu-bw) border-neu-edge bg-neu-bg px-[1.1rem] py-4 text-neu-ink shadow-neu-sm transition-[box-shadow,border-color] duration-[250ms] peer-checked:border-neu-accent peer-checked:shadow-neu-in motion-reduce:transition-none peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-neu-accent"><span class="mb-[.35rem] grid size-[42px] place-items-center rounded-full text-neu-muted shadow-neu-in-sm transition-colors duration-[250ms] group-has-checked:bg-neu-accent group-has-checked:text-neu-on-accent motion-reduce:transition-none"><svg class="size-[22px] shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-bulb"/></svg></span><span class="leading-[1.25] font-semibold">Hallway<span class="sr-only">, Off at 23:00</span></span><span class="-mt-[.3rem] text-[.8rem] text-neu-muted" aria-hidden="true">Off at 23:00</span><span class="flex items-center gap-[.4rem] text-[.8rem] font-semibold text-neu-muted before:size-[9px] before:rounded-full before:border-2 before:border-current after:content-['Off'] group-has-checked:text-neu-accent group-has-checked:before:bg-current group-has-checked:after:content-['On']" aria-hidden="true"></span></span></label><label class="group relative inline-flex cursor-pointer"><input class="peer sr-only" type="checkbox" role="switch"><span class="flex w-full min-w-0 flex-col items-start gap-[.4rem] rounded-neu border-(length:--neu-bw) border-neu-edge bg-neu-bg px-[1.1rem] py-4 text-neu-ink shadow-neu-sm transition-[box-shadow,border-color] duration-[250ms] peer-checked:border-neu-accent peer-checked:shadow-neu-in motion-reduce:transition-none peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-neu-accent"><span class="mb-[.35rem] grid size-[42px] place-items-center rounded-full text-neu-muted shadow-neu-in-sm transition-colors duration-[250ms] group-has-checked:bg-neu-accent group-has-checked:text-neu-on-accent motion-reduce:transition-none"><svg class="size-[22px] shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-bulb"/></svg></span><span class="leading-[1.25] font-semibold">Porch<span class="sr-only">, Motion sensor</span></span><span class="-mt-[.3rem] text-[.8rem] text-neu-muted" aria-hidden="true">Motion sensor</span><span class="flex items-center gap-[.4rem] text-[.8rem] font-semibold text-neu-muted before:size-[9px] before:rounded-full before:border-2 before:border-current after:content-['Off'] group-has-checked:text-neu-accent group-has-checked:before:bg-current group-has-checked:after:content-['On']" aria-hidden="true"></span></span></label></div></section>
<section class="rounded-neu border-(length:--neu-bw) border-neu-line bg-neu-bg text-neu-ink shadow-neu grid grid-cols-[minmax(0,1fr)] gap-[1.1rem] p-6 col-span-full" aria-labelledby="p-scene"><h2 class="flex items-baseline justify-between gap-2 text-base font-bold" id="p-scene">Scene and music</h2><div class="grid grid-cols-[repeat(auto-fit,minmax(min(100%,300px),1fr))] items-center gap-[22px] [&>:last-child]:col-span-full"><fieldset class="m-0 min-w-0 border-0 p-0"><legend class="mb-[.6rem] p-0 text-[.88rem] font-semibold">Active scene</legend><div class="flex flex-wrap gap-1.5 rounded-neu-btn border-(length:--neu-bw) border-neu-edge p-1.5 shadow-neu-in-sm"><label class="relative flex-auto"><input class="peer sr-only" type="radio" name="scene" value="morning"><span class="flex min-h-10 cursor-pointer items-center justify-center gap-[.4rem] rounded-[calc(var(--neu-radius)*.5)] border-(length:--neu-bw) border-transparent px-[.9rem] py-[.4rem] text-[.9rem] font-semibold text-neu-muted transition-[box-shadow,color] duration-200 peer-checked:border-neu-accent peer-checked:text-neu-accent peer-checked:shadow-neu-sm peer-checked:before:size-[7px] peer-checked:before:rounded-full peer-checked:before:bg-current peer-focus-visible:outline-3 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-neu-accent motion-reduce:transition-none">Morning</span></label><label class="relative flex-auto"><input class="peer sr-only" type="radio" name="scene" value="away"><span class="flex min-h-10 cursor-pointer items-center justify-center gap-[.4rem] rounded-[calc(var(--neu-radius)*.5)] border-(length:--neu-bw) border-transparent px-[.9rem] py-[.4rem] text-[.9rem] font-semibold text-neu-muted transition-[box-shadow,color] duration-200 peer-checked:border-neu-accent peer-checked:text-neu-accent peer-checked:shadow-neu-sm peer-checked:before:size-[7px] peer-checked:before:rounded-full peer-checked:before:bg-current peer-focus-visible:outline-3 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-neu-accent motion-reduce:transition-none">Away</span></label><label class="relative flex-auto"><input class="peer sr-only" type="radio" name="scene" value="movie" checked><span class="flex min-h-10 cursor-pointer items-center justify-center gap-[.4rem] rounded-[calc(var(--neu-radius)*.5)] border-(length:--neu-bw) border-transparent px-[.9rem] py-[.4rem] text-[.9rem] font-semibold text-neu-muted transition-[box-shadow,color] duration-200 peer-checked:border-neu-accent peer-checked:text-neu-accent peer-checked:shadow-neu-sm peer-checked:before:size-[7px] peer-checked:before:rounded-full peer-checked:before:bg-current peer-focus-visible:outline-3 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-neu-accent motion-reduce:transition-none">Movie</span></label><label class="relative flex-auto"><input class="peer sr-only" type="radio" name="scene" value="sleep"><span class="flex min-h-10 cursor-pointer items-center justify-center gap-[.4rem] rounded-[calc(var(--neu-radius)*.5)] border-(length:--neu-bw) border-transparent px-[.9rem] py-[.4rem] text-[.9rem] font-semibold text-neu-muted transition-[box-shadow,color] duration-200 peer-checked:border-neu-accent peer-checked:text-neu-accent peer-checked:shadow-neu-sm peer-checked:before:size-[7px] peer-checked:before:rounded-full peer-checked:before:bg-current peer-focus-visible:outline-3 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-neu-accent motion-reduce:transition-none">Sleep</span></label></div></fieldset><div class="flex items-center gap-4 rounded-neu border-(length:--neu-bw) border-neu-line bg-neu-bg px-[1.1rem] py-4 shadow-neu"><span class="size-[52px] flex-none rounded-neu-field bg-[radial-gradient(circle_at_30%_30%,#f59e0b_0_18%,transparent_19%),linear-gradient(160deg,#4f46e5,#0e7490)] shadow-neu-in-sm" aria-hidden="true"></span><div class="min-w-0 flex-1"><p class="truncate leading-[1.25] font-bold">Low Tide</p><p class="truncate text-[.82rem] text-neu-muted">Marla Quinn · Living room</p><div class="mt-[.55rem] h-2 rounded-full border-(length:--neu-bw) border-neu-edge bg-[linear-gradient(var(--neu-accent),var(--neu-accent))] bg-no-repeat shadow-neu-in-sm" style="background-size:40% 100%" role="progressbar" aria-label="Track position" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100"></div></div><label class="group relative inline-flex flex-none"><input class="peer sr-only" type="checkbox" aria-label="Play Low Tide"><span class="grid size-[52px] cursor-pointer place-items-center rounded-full border-(length:--neu-bw) border-neu-accent bg-neu-accent text-neu-on-accent shadow-neu-sm transition-shadow duration-200 peer-checked:shadow-neu-in-sm motion-reduce:transition-none peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-neu-accent"><svg class="size-6 shrink-0 group-has-checked:hidden" aria-hidden="true" focusable="false"><use href="#neu-i-play"/></svg><svg class="size-6 shrink-0 hidden group-has-checked:block" aria-hidden="true" focusable="false"><use href="#neu-i-pause"/></svg></span></label></div><div class="relative flex items-start gap-[.9rem] rounded-neu border-(length:--neu-bw) border-neu-line bg-neu-bg py-4 pr-[1.1rem] pl-[1.35rem] shadow-neu-sm before:absolute before:inset-y-4 before:left-[.55rem] before:w-1 before:rounded before:bg-neu-warning"><span class="grid size-10 flex-none place-items-center rounded-full text-neu-warning shadow-neu-in-sm"><svg class="size-5 shrink-0" aria-hidden="true" focusable="false"><use href="#neu-i-alert"/></svg></span><div><p class="leading-[1.3] font-bold"><span class="sr-only">Warning: </span>Bedroom window open</p><p class="mt-[.15rem] text-[.9rem] text-neu-muted">Heating paused until it is closed.</p></div></div></div></section>
</div>
</div>
</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);
}
JavaScript
// Thermostat: minus / plus move the target in 0.5° steps and redraw the arc (--p is 0–100 of the range)
document.querySelectorAll('[data-neu-dial]').forEach(function (dial) {
  var min = +dial.dataset.min, max = +dial.dataset.max;
  var face = dial.querySelector('[data-neu-face]'), out = dial.querySelector('[data-neu-value]');
  dial.querySelectorAll('[data-step]').forEach(function (b) {
    b.addEventListener('click', function () {
      var t = Math.min(max, Math.max(min, parseFloat(out.textContent) + parseFloat(b.dataset.step)));
      out.textContent = t.toFixed(1);
      face.style.setProperty('--p', ((t - min) / (max - min) * 100).toFixed(1));
    });
  });
});

About this set

A full smart-home dashboard assembled from the kit, with a light and dark switch that needs no JavaScript. A sidebar with the brand, grouped links and an unread count sits beside a greeting, four stat tiles for energy, solar, humidity and security, a climate panel with the thermostat dial, a lights panel with four switch tiles, and a scene and music panel with a segmented scene picker, a mini player and a window-open warning. The dark mode switch is a checkbox with the class neu-theme-input; the token block’s [data-neu]:has(.neu-theme-input:checked) rule swaps every token to the dark set, so the whole dashboard changes theme in CSS alone. Use it as a starting point for a home control app, or copy single panels into your own layout. On screens narrower than 900 pixels the sidebar moves above the content and its links wrap into rows, and the panels stack into one column. The thermostat buttons use the same short script as the widgets set; everything else is HTML and CSS.

What’s included

  • Light and dark theme switch built on :has(), no JavaScript
  • Sidebar, stat tiles, thermostat, light switches, scenes, player and alert
  • Uses the same tokens and components as the rest of the kit
  • Stacks to one column with a wrapping nav under 900 pixels
  • Bootstrap version on .card, .nav-pills, .form-switch and .btn-check

Accessibility

The page has a labelled main navigation with aria-current, one h1 and an h2 for each panel, and every panel is a section named by its heading. The theme switch is a native checkbox with role="switch", the scene picker is a radio group with a legend, and the lights are named switches. Focus shows a 3px accent ring in both themes, transitions stop under prefers-reduced-motion, and prefers-contrast: more outlines the dashboard in either theme.

Customise it

Change the --neu-* tokens on :root for the light theme and in the [data-neu] dark rule for the dark one. Panel widths come from .neu-home grid columns; in Tailwind edit the grid-cols-[250px_minmax(0,1fr)] utility on the root.