/* ── Claymorphism UI kit tokens (uiCookies) — identical in every set ──────────────
Every component is a puffy pastel object floating above --clay-bg: one big soft drop shadow
below it, an inset highlight top left and an inset shade bottom right. Change a token and
the whole kit follows; the shadow recipes below are built from these values. */
:root{
--clay-bg:#f3effa; /* page, a pale lilac white */
--clay-surface:#fffcf8; /* cards, fields and plain objects */
--clay-peach:#ffd2bd; /* object fills: ink text on every fill reaches 11:1 */
--clay-lilac:#dccdff;
--clay-mint:#bdeed6;
--clay-sky:#c2e0ff;
--clay-lemon:#ffe9a3;
--clay-ink:#241a3d; /* text, 14.4:1 on --clay-bg */
--clay-muted:#51476a; /* secondary text, 5.7:1 or more on every fill */
--clay-edge:#7a6e96; /* control boundary, 4.1:1 on --clay-bg, so shadows are never the only edge */
--clay-line:rgba(36,26,61,.12); /* decorative edge on cards and panels */
--clay-accent:#6236e8; /* focus ring and on / selected / current states, 5.8:1 on --clay-bg */
--clay-on-accent:#ffffff; /* text and marks on accent fills, 6.5:1 */
--clay-tint:#e9e1ff; /* light accent wash behind current items */
--clay-drop:rgba(86,56,168,.30); /* colour of the outer drop shadow */
--clay-hi:rgba(255,255,255,.88); /* inset highlight, top left */
--clay-lo:rgba(52,30,112,.20); /* inset shade, bottom right */
--clay-lift:14px; /* how high objects float; every shadow scales from it */
--clay-radius:30px; /* cards; buttons are pills, fields use .55 of it */
--clay-bw:1.5px; /* control border width */
--clay-success:#17663d;--clay-warning:#8a4b00;--clay-danger:#b3261e;
--clay-font:ui-rounded,"SF Pro Rounded","Nunito","Quicksand","Varela Round","Arial Rounded MT Bold",system-ui,sans-serif;
}
/* --clay-fill is set by .clay-peach, .clay-mint… on one object and must not leak into its children */
@property --clay-fill{syntax:"*";inherits:false}
/* Dark clay: data-clay="dark" on any wrapper, or a checked .clay-theme-input inside a [data-clay] element.
:is() is a forgiving list, so browsers without :has() still apply data-clay="dark" */
[data-clay]:is([data-clay="dark"],:has(.clay-theme-input:checked)){
--clay-bg:#1a1530;--clay-surface:#2a2347;
--clay-peach:#6e3f33;--clay-lilac:#4a3a8a;--clay-mint:#215a4a;--clay-sky:#26497c;--clay-lemon:#5f5220;
--clay-ink:#f7f3ff;--clay-muted:#d2c9ea;--clay-edge:#8f83b8;--clay-line:rgba(255,255,255,.1);
--clay-accent:#bba6ff;--clay-on-accent:#1a1530;--clay-tint:#3a2f66;
--clay-drop:rgba(4,2,14,.62);--clay-hi:rgba(255,255,255,.2);--clay-lo:rgba(0,0,0,.34);
--clay-success:#86e3b0;--clay-warning:#ffc76e;--clay-danger:#ffa196;color-scheme:dark}
/* More contrast requested: soft shading stays, but every edge and secondary text turns full ink */
@media (prefers-contrast:more){:root,[data-clay]:is([data-clay],:has(.clay-theme-input:checked)){
--clay-edge:var(--clay-ink);--clay-line:var(--clay-ink);--clay-muted:var(--clay-ink);--clay-bw:2px}}
:root,[data-clay]{
--clay-shadow:0 var(--clay-lift) calc(var(--clay-lift)*2.2) calc(var(--clay-lift)*-.3) var(--clay-drop),
inset calc(var(--clay-lift)*.45) calc(var(--clay-lift)*.5) calc(var(--clay-lift)*.9) var(--clay-hi),
inset calc(var(--clay-lift)*-.45) calc(var(--clay-lift)*-.6) calc(var(--clay-lift)*.9) var(--clay-lo);
--clay-shadow-sm:0 calc(var(--clay-lift)*.55) calc(var(--clay-lift)*1.2) calc(var(--clay-lift)*-.15) var(--clay-drop),
inset calc(var(--clay-lift)*.25) calc(var(--clay-lift)*.3) calc(var(--clay-lift)*.5) var(--clay-hi),
inset calc(var(--clay-lift)*-.25) calc(var(--clay-lift)*-.35) calc(var(--clay-lift)*.5) var(--clay-lo);
--clay-press:0 calc(var(--clay-lift)*.12) calc(var(--clay-lift)*.25) 0 var(--clay-drop),
inset calc(var(--clay-lift)*.2) calc(var(--clay-lift)*.25) calc(var(--clay-lift)*.45) var(--clay-lo),
inset calc(var(--clay-lift)*-.12) calc(var(--clay-lift)*-.12) calc(var(--clay-lift)*.3) var(--clay-hi);
--clay-well:inset calc(var(--clay-lift)*.15) calc(var(--clay-lift)*.22) calc(var(--clay-lift)*.45) var(--clay-lo),
inset calc(var(--clay-lift)*-.12) calc(var(--clay-lift)*-.12) calc(var(--clay-lift)*.3) var(--clay-hi);
}
[data-clay]{background:var(--clay-bg);color:var(--clay-ink)}
/* Components */
:where([class*="clay-"]),:where([class*="clay-"])::before,:where([class*="clay-"])::after{box-sizing:border-box}
.clay-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.clay-ico{width:22px;height:22px;flex:none}
.clay-ico--lg{width:28px;height:28px}
/* Fills: put one on any object; components read --clay-fill */
.clay-peach{--clay-fill:var(--clay-peach)}.clay-lilac{--clay-fill:var(--clay-lilac)}.clay-mint{--clay-fill:var(--clay-mint)}
.clay-sky{--clay-fill:var(--clay-sky)}.clay-lemon{--clay-fill:var(--clay-lemon)}
/* Card: a puffy panel that floats on the big drop shadow */
.clay-card{margin:0;padding:1.6rem;border:var(--clay-bw) solid var(--clay-line);border-radius:var(--clay-radius);
background:var(--clay-fill,var(--clay-surface));color:var(--clay-ink);box-shadow:var(--clay-shadow)}
/* Layout helpers */
.clay-cluster{display:flex;flex-wrap:wrap;align-items:center;gap:18px}
.clay-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:22px}
.clay-stack{display:grid;gap:1.4rem}
/* Buttons: pastel pills that float; hover lifts them, pressing squashes the shadow flat */
.clay-btn{display:inline-flex;align-items:center;justify-content:center;gap:.55rem;min-height:50px;margin:0;padding:.7rem 1.5rem;
border:var(--clay-bw) solid var(--clay-edge);border-radius:999px;background:var(--clay-fill,var(--clay-surface));color:var(--clay-ink);
font-family:inherit;font-size:1rem;font-weight:800;line-height:1.2;text-decoration:none;cursor:pointer;
box-shadow:var(--clay-shadow-sm);transition:transform .18s,box-shadow .18s}
.clay-btn:hover{transform:translateY(-2px);box-shadow:var(--clay-shadow)}
.clay-btn:active{transform:translateY(2px);box-shadow:var(--clay-press)}
.clay-btn:focus-visible{outline:3px solid var(--clay-accent);outline-offset:4px}
.clay-btn--accent{--clay-fill:var(--clay-accent);border-color:var(--clay-accent);color:var(--clay-on-accent)}
.clay-btn--sm{min-height:40px;padding:.45rem 1.05rem;font-size:.88rem}
.clay-btn--block{width:100%}
/* Icon buttons: round (or squircle) clay pebbles with a chunky icon and an aria-label */
.clay-iconbtn{display:inline-grid;place-items:center;width:58px;height:58px;margin:0;padding:0;border:var(--clay-bw) solid var(--clay-edge);border-radius:50%;
background:var(--clay-fill,var(--clay-surface));color:var(--clay-ink);cursor:pointer;box-shadow:var(--clay-shadow-sm);transition:transform .18s,box-shadow .18s}
.clay-iconbtn:hover{transform:translateY(-2px);box-shadow:var(--clay-shadow)}
.clay-iconbtn:active{transform:translateY(2px);box-shadow:var(--clay-press)}
.clay-iconbtn:focus-visible{outline:3px solid var(--clay-accent);outline-offset:4px}
.clay-iconbtn--sq{border-radius:20px}
.clay-iconbtn--sm{width:44px;height:44px}
.clay-iconbtn--lg{width:72px;height:72px}
.clay-iconbtn--accent{--clay-fill:var(--clay-accent);border-color:var(--clay-accent);color:var(--clay-on-accent)}
@media (prefers-reduced-motion:reduce){.clay-btn,.clay-iconbtn{transition:none}.clay-btn:hover,.clay-btn:active,.clay-iconbtn:hover,.clay-iconbtn:active{transform:none}}
/* Blob: a small puffy icon tile that sits on any card */
.clay-blob{display:grid;place-items:center;flex:none;width:52px;height:52px;border:var(--clay-bw) solid var(--clay-line);border-radius:18px;
background:var(--clay-fill,var(--clay-surface));color:var(--clay-ink);box-shadow:var(--clay-shadow-sm)}
.clay-chip{display:inline-flex;align-items:center;gap:.35rem;padding:.3rem .75rem;border:var(--clay-bw) solid var(--clay-line);border-radius:999px;
background:var(--clay-surface);color:var(--clay-ink);font-size:.8rem;font-weight:800;line-height:1.3}
.clay-chip .clay-ico{width:16px;height:16px}
/* Stat cards: coloured clay slabs with a blob icon, a big number and a sentence that explains the change */
.clay-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:24px}
.clay-stat{display:grid;gap:.25rem;align-content:start}
.clay-stat__label{margin:.85rem 0 0;font-size:.9rem;font-weight:800;color:var(--clay-muted)}
.clay-stat__value{margin:0;font-size:2.2rem;font-weight:800;line-height:1.1;letter-spacing:-.01em}
.clay-stat__unit{font-size:1rem;font-weight:700}
.clay-stat__note{margin:0;font-size:.86rem;font-weight:600;color:var(--clay-muted)}
/* Content card: an illustration panel made of clay shapes, a chip, a title and a progress line */
.clay-lesson{display:flex;flex-direction:column;gap:1rem;padding:1rem 1rem 1.4rem}
.clay-art{position:relative;height:170px;overflow:hidden;border-radius:calc(var(--clay-radius)*.75);background:var(--clay-sky);box-shadow:var(--clay-well)}
.clay-art__shape{position:absolute;border-radius:50%;box-shadow:var(--clay-shadow-sm)}
.clay-art__shape--sun{top:22px;right:34px;width:58px;height:58px;background:var(--clay-lemon)}
.clay-art__shape--cloud{top:52px;left:40px;width:140px;height:54px;border-radius:999px;background:var(--clay-surface)}
.clay-art__shape--cloud2{top:30px;left:78px;width:70px;height:60px;background:var(--clay-surface)}
.clay-art__shape--hill{bottom:-70px;left:-20px;width:240px;height:140px;background:var(--clay-mint)}
.clay-art__shape--hill2{bottom:-90px;right:-40px;width:260px;height:150px;background:var(--clay-peach)}
.clay-art__shape--drop{top:116px;width:14px;height:20px;border-radius:50% 50% 50% 50%/60% 60% 40% 40%;background:var(--clay-accent);box-shadow:none}
.clay-lesson__body{display:grid;gap:.55rem;padding:0 .5rem}
.clay-lesson__tag{margin:0}
.clay-lesson__title{margin:0;font-size:1.3rem;font-weight:800;line-height:1.25}
.clay-lesson__text{margin:0;color:var(--clay-muted)}
.clay-lesson__foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:1rem;padding:0 .5rem}
.clay-meter{display:grid;gap:.35rem;flex:1;min-width:140px;font-size:.84rem;font-weight:700;color:var(--clay-muted)}
.clay-meter__bar{height:14px;border:var(--clay-bw) solid var(--clay-edge);border-radius:999px;background:var(--clay-bg);box-shadow:var(--clay-well);overflow:hidden}
.clay-meter__fill{display:block;height:100%;width:var(--clay-pct,50%);border-radius:999px;background:var(--clay-accent)}
/* Profile card */
.clay-profile{display:grid;justify-items:center;gap:.4rem;text-align:center}
.clay-avatar{display:grid;place-items:center;width:96px;height:96px;margin-bottom:.6rem;border:var(--clay-bw) solid var(--clay-line);border-radius:50%;
background:var(--clay-fill,var(--clay-lilac));font-size:2rem;font-weight:800;box-shadow:var(--clay-shadow)}
.clay-profile__name{margin:0;font-size:1.3rem;font-weight:800;line-height:1.25}
.clay-profile__role{margin:0;color:var(--clay-muted)}
.clay-profile__stats{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;width:100%;margin:.9rem 0 1.1rem;padding:0;list-style:none}
.clay-profile__stat{display:grid;padding:.6rem .3rem;border-radius:18px;background:var(--clay-fill,var(--clay-bg));box-shadow:var(--clay-well)}
.clay-profile__num{font-size:1.25rem;font-weight:800;line-height:1.2}
.clay-profile__key{font-size:.78rem;font-weight:700;color:var(--clay-muted)}
.clay-profile__actions{display:flex;flex-wrap:wrap;justify-content:center;gap:12px}
/* Pricing pair */
.clay-plans{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:28px;align-items:start}
.clay-plan{position:relative;display:grid;gap:.9rem}
.clay-plan__badge{position:absolute;top:-14px;right:24px;padding:.3rem .85rem;border:var(--clay-bw) solid var(--clay-accent);border-radius:999px;
background:var(--clay-accent);color:var(--clay-on-accent);font-size:.78rem;font-weight:800;box-shadow:var(--clay-shadow-sm)}
.clay-plan__name{margin:0;font-size:1.15rem;font-weight:800}
.clay-plan__price{margin:0;font-size:2.6rem;font-weight:800;line-height:1}
.clay-plan__per{font-size:1rem;font-weight:700;color:var(--clay-muted)}
.clay-plan__desc{margin:0;color:var(--clay-muted)}
.clay-plan__list{display:grid;gap:.6rem;margin:.2rem 0 .4rem;padding:0;list-style:none}
.clay-plan__item{display:flex;align-items:center;gap:.6rem;font-weight:600}
.clay-plan__tick{display:grid;place-items:center;flex:none;width:26px;height:26px;border-radius:50%;background:var(--clay-fill,var(--clay-surface));box-shadow:var(--clay-shadow-sm)}
.clay-plan__tick .clay-ico{width:16px;height:16px}
.clay-two{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);gap:28px;align-items:start}
@media (max-width:767px){.clay-two{grid-template-columns:1fr}}
.clay-stats--two{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
/* Range: native input. The track is a well, the thumb a puffy pebble; a few lines of script paint the fill */
.clay-range-head{display:flex;justify-content:space-between;align-items:baseline;gap:1rem}
.clay-range-out{font-size:.92rem;font-weight:800;color:var(--clay-accent)}
.clay-range{--clay-val:50%;display:block;width:100%;height:30px;margin:0;background:transparent;appearance:none;cursor:pointer}
.clay-range::-webkit-slider-runnable-track{height:14px;border:var(--clay-bw) solid var(--clay-edge);border-radius:999px;box-shadow:var(--clay-well);
background:linear-gradient(90deg,var(--clay-accent) var(--clay-val),var(--clay-bg) var(--clay-val))}
.clay-range::-moz-range-track{height:14px;border:var(--clay-bw) solid var(--clay-edge);border-radius:999px;background:var(--clay-bg);box-shadow:var(--clay-well)}
.clay-range::-moz-range-progress{height:14px;border-radius:999px;background:var(--clay-accent)}
.clay-range::-webkit-slider-thumb{width:28px;height:28px;margin-top:-8.5px;border:var(--clay-bw) solid var(--clay-edge);border-radius:50%;background:var(--clay-lemon);box-shadow:var(--clay-shadow-sm);appearance:none}
.clay-range::-moz-range-thumb{width:28px;height:28px;border:var(--clay-bw) solid var(--clay-edge);border-radius:50%;background:var(--clay-lemon);box-shadow:var(--clay-shadow-sm)}
.clay-range:focus-visible{outline:3px solid var(--clay-accent);outline-offset:4px;border-radius:999px}
.clay-range-scale{display:flex;justify-content:space-between;margin:0;font-size:.8rem;color:var(--clay-muted)}
.clay-widgets{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,400px),1fr));gap:28px;align-items:start}
.clay-wtitle{margin:0;font-size:1.1rem;font-weight:800;line-height:1.3}
.clay-wsub{margin:0;font-size:.88rem;color:var(--clay-muted)}
/* Music player: a clay cover, a seek range and round controls; Play swaps to Pause and says so */
.clay-player{display:grid;gap:1.1rem}
.clay-player__top{display:flex;align-items:center;gap:1.1rem}
.clay-cover{position:relative;display:grid;place-items:center;flex:none;width:96px;height:96px;border:var(--clay-bw) solid var(--clay-line);border-radius:28px;
background:var(--clay-peach);box-shadow:var(--clay-shadow);overflow:hidden}
.clay-cover::before,.clay-cover::after{content:"";position:absolute;border-radius:50%;box-shadow:var(--clay-shadow-sm)}
.clay-cover::before{right:-14px;bottom:-14px;width:54px;height:54px;background:var(--clay-lemon)}
.clay-cover::after{left:-10px;top:-10px;width:38px;height:38px;background:var(--clay-mint)}
.clay-cover .clay-ico{position:relative;z-index:1;width:36px;height:36px}
.clay-player__meta{min-width:0}
.clay-player__times{display:flex;justify-content:space-between;margin:-.4rem 0 0;font-size:.82rem;font-weight:700;color:var(--clay-muted)}
.clay-player__controls{display:flex;align-items:center;justify-content:center;gap:clamp(6px,2vw,16px)}
.clay-play .clay-play__pause,.clay-play[data-playing="true"] .clay-play__play{display:none}
.clay-play[data-playing="true"] .clay-play__pause{display:block}
/* Weather */
.clay-weather{display:grid;gap:1.1rem}
.clay-weather__now{display:flex;align-items:center;gap:1rem}
.clay-weather__icon{display:grid;place-items:center;flex:none;width:84px;height:84px;border:var(--clay-bw) solid var(--clay-line);border-radius:50%;background:var(--clay-lemon);box-shadow:var(--clay-shadow)}
.clay-weather__icon .clay-ico{width:42px;height:42px}
.clay-weather__temp{margin:0;font-size:3rem;font-weight:800;line-height:1}
.clay-weather__facts{display:flex;flex-wrap:wrap;gap:8px;margin:0;padding:0;list-style:none}
.clay-days{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin:0;padding:0;list-style:none}
.clay-day{display:grid;justify-items:center;gap:.2rem;padding:.7rem .3rem;border:var(--clay-bw) solid var(--clay-line);border-radius:20px;background:var(--clay-surface);box-shadow:var(--clay-shadow-sm);text-align:center}
.clay-day__name{font-size:.82rem;font-weight:800}
.clay-day__temp{font-size:.82rem;font-weight:700;color:var(--clay-muted)}
/* Mini calendar: a real table; today is an accent pebble with aria-current="date", event days get a dot and hidden text */
.clay-cal{display:grid;gap:.9rem}
.clay-cal__head{display:flex;align-items:center;justify-content:space-between;gap:.5rem}
.clay-cal__nav{display:flex;gap:8px}
.clay-cal__table{width:100%;border-collapse:separate;border-spacing:4px;table-layout:fixed;text-align:center}
.clay-cal__th{padding:.2rem 0;font-size:.74rem;font-weight:800;color:var(--clay-muted);text-transform:uppercase}
.clay-cal__th abbr{text-decoration:none;cursor:help}
.clay-cal__td{padding:0;font-size:.9rem;font-weight:700}
.clay-cal__day{position:relative;display:grid;place-items:center;height:36px;border-radius:13px}
.clay-cal__day--event::after{content:"";position:absolute;bottom:3px;left:50%;width:6px;height:6px;margin-left:-3px;border-radius:50%;background:var(--clay-success)}
.clay-cal__day--today{border:var(--clay-bw) solid var(--clay-accent);background:var(--clay-accent);color:var(--clay-on-accent);font-weight:800;box-shadow:var(--clay-shadow-sm)}
.clay-cal__day--today.clay-cal__day--event::after{background:var(--clay-on-accent)}
.clay-cal__list{display:grid;gap:8px;margin:0;padding:0;list-style:none}
.clay-cal__item{display:flex;align-items:center;gap:.7rem;padding:.55rem .7rem;border-radius:16px;background:var(--clay-fill,var(--clay-bg));font-size:.9rem;font-weight:700}
.clay-cal__when{margin-left:auto;font-weight:600;color:var(--clay-muted)}
/* Progress: bars with role="progressbar" and a conic-gradient ring for the weekly goal */
.clay-progress{display:grid;gap:1.1rem}
.clay-progress__row{display:grid;gap:.4rem}
.clay-progress__label{display:flex;justify-content:space-between;margin:0;font-weight:800}
.clay-progress__pct{color:var(--clay-muted)}
.clay-goal{display:flex;align-items:center;gap:1.1rem;padding-top:.3rem}
.clay-ring{--clay-pct:50;position:relative;display:grid;place-items:center;flex:none;width:104px;height:104px;border-radius:50%;
background:conic-gradient(var(--clay-accent) calc(var(--clay-pct)*1%),var(--clay-bg) 0);box-shadow:var(--clay-shadow-sm);border:var(--clay-bw) solid var(--clay-edge)}
.clay-ring::before{content:"";position:absolute;inset:14px;border-radius:50%;background:var(--clay-surface);box-shadow:var(--clay-well)}
.clay-ring__value{position:relative;font-size:1.25rem;font-weight:800}
JavaScript
// Music player: Play / Pause swaps its label and icon; the seek range reads "1:42 of 3:58"
document.querySelectorAll('[data-clay-player]').forEach(function (p) {
var play = p.querySelector('[data-clay-play]'), seek = p.querySelector('[data-clay-seek]'), now = p.querySelector('[data-clay-now]');
function fmt(s) { s = Math.round(s); return Math.floor(s / 60) + ':' + String(s % 60).padStart(2, '0'); }
if (play) play.addEventListener('click', function () {
var on = play.getAttribute("data-playing") !== "true";
play.setAttribute("data-playing", on); play.setAttribute('aria-label', on ? 'Pause' : 'Play');
});
if (seek) {
var paint = function () {
var pct = (seek.value - seek.min) / (seek.max - seek.min) * 100;
seek.style.setProperty('--clay-val', pct + '%');
if (now) now.textContent = fmt(seek.value);
seek.setAttribute('aria-valuetext', fmt(seek.value) + ' of ' + fmt(seek.max));
};
seek.addEventListener('input', paint); paint();
}
});
/* ── Claymorphism UI kit tokens (uiCookies) — identical in every set ──────────────
Every component is a puffy pastel object floating above --clay-bg: one big soft drop shadow
below it, an inset highlight top left and an inset shade bottom right. Change a token and
the whole kit follows; the shadow recipes below are built from these values. */
:root{
--clay-bg:#f3effa; /* page, a pale lilac white */
--clay-surface:#fffcf8; /* cards, fields and plain objects */
--clay-peach:#ffd2bd; /* object fills: ink text on every fill reaches 11:1 */
--clay-lilac:#dccdff;
--clay-mint:#bdeed6;
--clay-sky:#c2e0ff;
--clay-lemon:#ffe9a3;
--clay-ink:#241a3d; /* text, 14.4:1 on --clay-bg */
--clay-muted:#51476a; /* secondary text, 5.7:1 or more on every fill */
--clay-edge:#7a6e96; /* control boundary, 4.1:1 on --clay-bg, so shadows are never the only edge */
--clay-line:rgba(36,26,61,.12); /* decorative edge on cards and panels */
--clay-accent:#6236e8; /* focus ring and on / selected / current states, 5.8:1 on --clay-bg */
--clay-on-accent:#ffffff; /* text and marks on accent fills, 6.5:1 */
--clay-tint:#e9e1ff; /* light accent wash behind current items */
--clay-drop:rgba(86,56,168,.30); /* colour of the outer drop shadow */
--clay-hi:rgba(255,255,255,.88); /* inset highlight, top left */
--clay-lo:rgba(52,30,112,.20); /* inset shade, bottom right */
--clay-lift:14px; /* how high objects float; every shadow scales from it */
--clay-radius:30px; /* cards; buttons are pills, fields use .55 of it */
--clay-bw:1.5px; /* control border width */
--clay-success:#17663d;--clay-warning:#8a4b00;--clay-danger:#b3261e;
--clay-font:ui-rounded,"SF Pro Rounded","Nunito","Quicksand","Varela Round","Arial Rounded MT Bold",system-ui,sans-serif;
}
/* --clay-fill is set by .clay-peach, .clay-mint… on one object and must not leak into its children */
@property --clay-fill{syntax:"*";inherits:false}
/* Dark clay: data-clay="dark" on any wrapper, or a checked .clay-theme-input inside a [data-clay] element.
:is() is a forgiving list, so browsers without :has() still apply data-clay="dark" */
[data-clay]:is([data-clay="dark"],:has(.clay-theme-input:checked)){
--clay-bg:#1a1530;--clay-surface:#2a2347;
--clay-peach:#6e3f33;--clay-lilac:#4a3a8a;--clay-mint:#215a4a;--clay-sky:#26497c;--clay-lemon:#5f5220;
--clay-ink:#f7f3ff;--clay-muted:#d2c9ea;--clay-edge:#8f83b8;--clay-line:rgba(255,255,255,.1);
--clay-accent:#bba6ff;--clay-on-accent:#1a1530;--clay-tint:#3a2f66;
--clay-drop:rgba(4,2,14,.62);--clay-hi:rgba(255,255,255,.2);--clay-lo:rgba(0,0,0,.34);
--clay-success:#86e3b0;--clay-warning:#ffc76e;--clay-danger:#ffa196;color-scheme:dark}
/* More contrast requested: soft shading stays, but every edge and secondary text turns full ink */
@media (prefers-contrast:more){:root,[data-clay]:is([data-clay],:has(.clay-theme-input:checked)){
--clay-edge:var(--clay-ink);--clay-line:var(--clay-ink);--clay-muted:var(--clay-ink);--clay-bw:2px}}
:root,[data-clay]{
--clay-shadow:0 var(--clay-lift) calc(var(--clay-lift)*2.2) calc(var(--clay-lift)*-.3) var(--clay-drop),
inset calc(var(--clay-lift)*.45) calc(var(--clay-lift)*.5) calc(var(--clay-lift)*.9) var(--clay-hi),
inset calc(var(--clay-lift)*-.45) calc(var(--clay-lift)*-.6) calc(var(--clay-lift)*.9) var(--clay-lo);
--clay-shadow-sm:0 calc(var(--clay-lift)*.55) calc(var(--clay-lift)*1.2) calc(var(--clay-lift)*-.15) var(--clay-drop),
inset calc(var(--clay-lift)*.25) calc(var(--clay-lift)*.3) calc(var(--clay-lift)*.5) var(--clay-hi),
inset calc(var(--clay-lift)*-.25) calc(var(--clay-lift)*-.35) calc(var(--clay-lift)*.5) var(--clay-lo);
--clay-press:0 calc(var(--clay-lift)*.12) calc(var(--clay-lift)*.25) 0 var(--clay-drop),
inset calc(var(--clay-lift)*.2) calc(var(--clay-lift)*.25) calc(var(--clay-lift)*.45) var(--clay-lo),
inset calc(var(--clay-lift)*-.12) calc(var(--clay-lift)*-.12) calc(var(--clay-lift)*.3) var(--clay-hi);
--clay-well:inset calc(var(--clay-lift)*.15) calc(var(--clay-lift)*.22) calc(var(--clay-lift)*.45) var(--clay-lo),
inset calc(var(--clay-lift)*-.12) calc(var(--clay-lift)*-.12) calc(var(--clay-lift)*.3) var(--clay-hi);
}
[data-clay]{background:var(--clay-bg);color:var(--clay-ink)}
/* Bootstrap's own variables mapped onto the kit tokens */
:root,[data-clay]{--bs-body-bg:var(--clay-bg);--bs-body-color:var(--clay-ink);--bs-body-font-family:var(--clay-font);
--bs-emphasis-color:var(--clay-ink);--bs-heading-color:var(--clay-ink);--bs-secondary-color:var(--clay-muted);--bs-tertiary-color:var(--clay-muted);
--bs-border-color:var(--clay-edge);--bs-border-width:var(--clay-bw);--bs-border-radius:calc(var(--clay-radius)*.55);
--bs-border-radius-lg:var(--clay-radius);--bs-border-radius-pill:999px;--bs-focus-ring-color:var(--clay-accent);
--bs-link-color:var(--clay-accent);--bs-link-color-rgb:98,54,232;--bs-link-hover-color:var(--clay-ink);--bs-link-hover-color-rgb:36,26,61}
/* Components */
:where([class*="clay-"]),:where([class*="clay-"])::before,:where([class*="clay-"])::after{box-sizing:border-box}
.clay-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.clay-ico{width:22px;height:22px;flex:none}
.clay-ico--lg{width:28px;height:28px}
/* Fills: put one on any object; components read --clay-fill */
.clay-peach{--clay-fill:var(--clay-peach)}.clay-lilac{--clay-fill:var(--clay-lilac)}.clay-mint{--clay-fill:var(--clay-mint)}
.clay-sky{--clay-fill:var(--clay-sky)}.clay-lemon{--clay-fill:var(--clay-lemon)}
/* Card: a puffy panel that floats on the big drop shadow */
.clay-card{margin:0;padding:1.6rem;border:var(--clay-bw) solid var(--clay-line);border-radius:var(--clay-radius);
background:var(--clay-fill,var(--clay-surface));color:var(--clay-ink);box-shadow:var(--clay-shadow)}
/* Layout helpers */
.clay-cluster{display:flex;flex-wrap:wrap;align-items:center;gap:18px}
.clay-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:22px}
.clay-stack{display:grid;gap:1.4rem}
/* Cards: Bootstrap .card through its --bs-card-* variables */
.card.clay-card{--bs-card-bg:var(--clay-fill,var(--clay-surface));--bs-card-color:var(--clay-ink);--bs-card-border-color:var(--clay-line);
--bs-card-border-width:var(--clay-bw);--bs-card-border-radius:var(--clay-radius);--bs-card-inner-border-radius:var(--clay-radius);
--bs-card-spacer-x:1.6rem;--bs-card-spacer-y:1.6rem;padding:0}
/* Buttons: Bootstrap .btn with a .btn-clay variant set through --bs-btn-* variables.
Hover lifts the pill, pressing squashes the shadow flat */
.btn-clay{--bs-btn-padding-x:1.5rem;--bs-btn-padding-y:.7rem;--bs-btn-font-family:inherit;--bs-btn-font-size:1rem;--bs-btn-font-weight:800;--bs-btn-line-height:1.2;
--bs-btn-border-width:var(--clay-bw);--bs-btn-border-radius:999px;
--bs-btn-bg:var(--clay-fill,var(--clay-surface));--bs-btn-color:var(--clay-ink);--bs-btn-border-color:var(--clay-edge);
--bs-btn-hover-bg:var(--bs-btn-bg);--bs-btn-hover-color:var(--bs-btn-color);--bs-btn-hover-border-color:var(--bs-btn-border-color);
--bs-btn-active-bg:var(--bs-btn-bg);--bs-btn-active-color:var(--bs-btn-color);--bs-btn-active-border-color:var(--bs-btn-border-color);
--clay-btn-shadow:var(--clay-shadow-sm);
display:inline-flex;align-items:center;justify-content:center;gap:.55rem;min-height:50px;
box-shadow:var(--clay-btn-shadow);transition:transform .18s,box-shadow .18s}
.btn-clay:hover{--clay-btn-shadow:var(--clay-shadow);transform:translateY(-2px)}
.btn-clay:active,.btn-clay:first-child:active{--clay-btn-shadow:var(--clay-press);transform:translateY(2px)}
.btn-clay:focus-visible,.btn-check:focus-visible+.btn-clay{box-shadow:var(--clay-btn-shadow);outline:3px solid var(--clay-accent);outline-offset:4px}
.btn-clay-accent{--clay-fill:var(--clay-accent);--bs-btn-color:var(--clay-on-accent);--bs-btn-border-color:var(--clay-accent)}
.btn-clay.btn-sm{--bs-btn-padding-x:1.05rem;--bs-btn-padding-y:.45rem;--bs-btn-font-size:.88rem;min-height:40px}
/* Icon buttons: a round or squircle .btn-clay with an aria-label */
.btn-clay-icon{--bs-btn-padding-x:0;--bs-btn-padding-y:0;width:58px;height:58px;min-height:0;border-radius:50%}
.btn-clay-icon.btn-clay-sq{border-radius:20px}
.btn-clay-icon.btn-clay-sm{width:44px;height:44px}
.btn-clay-icon.btn-clay-lg{width:72px;height:72px}
@media (prefers-reduced-motion:reduce){.btn-clay{transition:none}.btn-clay:hover,.btn-clay:active,.btn-clay:first-child:active{transform:none}}
/* Blob: a small puffy icon tile that sits on any card */
.clay-blob{display:grid;place-items:center;flex:none;width:52px;height:52px;border:var(--clay-bw) solid var(--clay-line);border-radius:18px;
background:var(--clay-fill,var(--clay-surface));color:var(--clay-ink);box-shadow:var(--clay-shadow-sm)}
.clay-chip{display:inline-flex;align-items:center;gap:.35rem;padding:.3rem .75rem;border:var(--clay-bw) solid var(--clay-line);border-radius:999px;
background:var(--clay-surface);color:var(--clay-ink);font-size:.8rem;font-weight:800;line-height:1.3}
.clay-chip .clay-ico{width:16px;height:16px}
/* Stat cards: coloured clay slabs with a blob icon, a big number and a sentence that explains the change */
.clay-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:24px}
.clay-stat{display:grid;gap:.25rem;align-content:start}
.clay-stat__label{margin:.85rem 0 0;font-size:.9rem;font-weight:800;color:var(--clay-muted)}
.clay-stat__value{margin:0;font-size:2.2rem;font-weight:800;line-height:1.1;letter-spacing:-.01em}
.clay-stat__unit{font-size:1rem;font-weight:700}
.clay-stat__note{margin:0;font-size:.86rem;font-weight:600;color:var(--clay-muted)}
/* Content card: an illustration panel made of clay shapes, a chip, a title and a progress line */
.clay-lesson{display:flex;flex-direction:column;gap:1rem;padding:1rem 1rem 1.4rem}
.clay-art{position:relative;height:170px;overflow:hidden;border-radius:calc(var(--clay-radius)*.75);background:var(--clay-sky);box-shadow:var(--clay-well)}
.clay-art__shape{position:absolute;border-radius:50%;box-shadow:var(--clay-shadow-sm)}
.clay-art__shape--sun{top:22px;right:34px;width:58px;height:58px;background:var(--clay-lemon)}
.clay-art__shape--cloud{top:52px;left:40px;width:140px;height:54px;border-radius:999px;background:var(--clay-surface)}
.clay-art__shape--cloud2{top:30px;left:78px;width:70px;height:60px;background:var(--clay-surface)}
.clay-art__shape--hill{bottom:-70px;left:-20px;width:240px;height:140px;background:var(--clay-mint)}
.clay-art__shape--hill2{bottom:-90px;right:-40px;width:260px;height:150px;background:var(--clay-peach)}
.clay-art__shape--drop{top:116px;width:14px;height:20px;border-radius:50% 50% 50% 50%/60% 60% 40% 40%;background:var(--clay-accent);box-shadow:none}
.clay-lesson__body{display:grid;gap:.55rem;padding:0 .5rem}
.clay-lesson__tag{margin:0}
.clay-lesson__title{margin:0;font-size:1.3rem;font-weight:800;line-height:1.25}
.clay-lesson__text{margin:0;color:var(--clay-muted)}
.clay-lesson__foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:1rem;padding:0 .5rem}
.clay-meter{display:grid;gap:.35rem;flex:1;min-width:140px;font-size:.84rem;font-weight:700;color:var(--clay-muted)}
.clay-meter__bar{height:14px;border:var(--clay-bw) solid var(--clay-edge);border-radius:999px;background:var(--clay-bg);box-shadow:var(--clay-well);overflow:hidden}
.clay-meter__fill{display:block;height:100%;width:var(--clay-pct,50%);border-radius:999px;background:var(--clay-accent)}
/* Profile card */
.clay-profile{display:grid;justify-items:center;gap:.4rem;text-align:center}
.clay-avatar{display:grid;place-items:center;width:96px;height:96px;margin-bottom:.6rem;border:var(--clay-bw) solid var(--clay-line);border-radius:50%;
background:var(--clay-fill,var(--clay-lilac));font-size:2rem;font-weight:800;box-shadow:var(--clay-shadow)}
.clay-profile__name{margin:0;font-size:1.3rem;font-weight:800;line-height:1.25}
.clay-profile__role{margin:0;color:var(--clay-muted)}
.clay-profile__stats{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;width:100%;margin:.9rem 0 1.1rem;padding:0;list-style:none}
.clay-profile__stat{display:grid;padding:.6rem .3rem;border-radius:18px;background:var(--clay-fill,var(--clay-bg));box-shadow:var(--clay-well)}
.clay-profile__num{font-size:1.25rem;font-weight:800;line-height:1.2}
.clay-profile__key{font-size:.78rem;font-weight:700;color:var(--clay-muted)}
.clay-profile__actions{display:flex;flex-wrap:wrap;justify-content:center;gap:12px}
/* Pricing pair */
.clay-plans{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:28px;align-items:start}
.clay-plan{position:relative;display:grid;gap:.9rem}
.clay-plan__badge{position:absolute;top:-14px;right:24px;padding:.3rem .85rem;border:var(--clay-bw) solid var(--clay-accent);border-radius:999px;
background:var(--clay-accent);color:var(--clay-on-accent);font-size:.78rem;font-weight:800;box-shadow:var(--clay-shadow-sm)}
.clay-plan__name{margin:0;font-size:1.15rem;font-weight:800}
.clay-plan__price{margin:0;font-size:2.6rem;font-weight:800;line-height:1}
.clay-plan__per{font-size:1rem;font-weight:700;color:var(--clay-muted)}
.clay-plan__desc{margin:0;color:var(--clay-muted)}
.clay-plan__list{display:grid;gap:.6rem;margin:.2rem 0 .4rem;padding:0;list-style:none}
.clay-plan__item{display:flex;align-items:center;gap:.6rem;font-weight:600}
.clay-plan__tick{display:grid;place-items:center;flex:none;width:26px;height:26px;border-radius:50%;background:var(--clay-fill,var(--clay-surface));box-shadow:var(--clay-shadow-sm)}
.clay-plan__tick .clay-ico{width:16px;height:16px}
.clay-two{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);gap:28px;align-items:start}
@media (max-width:767px){.clay-two{grid-template-columns:1fr}}
.clay-stats--two{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
.clay-widgets{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,400px),1fr));gap:28px;align-items:start}
.clay-wtitle{margin:0;font-size:1.1rem;font-weight:800;line-height:1.3}
.clay-wsub{margin:0;font-size:.88rem;color:var(--clay-muted)}
/* Music player: a clay cover, a seek range and round controls; Play swaps to Pause and says so */
.clay-player{display:grid;gap:1.1rem}
.clay-player__top{display:flex;align-items:center;gap:1.1rem}
.clay-cover{position:relative;display:grid;place-items:center;flex:none;width:96px;height:96px;border:var(--clay-bw) solid var(--clay-line);border-radius:28px;
background:var(--clay-peach);box-shadow:var(--clay-shadow);overflow:hidden}
.clay-cover::before,.clay-cover::after{content:"";position:absolute;border-radius:50%;box-shadow:var(--clay-shadow-sm)}
.clay-cover::before{right:-14px;bottom:-14px;width:54px;height:54px;background:var(--clay-lemon)}
.clay-cover::after{left:-10px;top:-10px;width:38px;height:38px;background:var(--clay-mint)}
.clay-cover .clay-ico{position:relative;z-index:1;width:36px;height:36px}
.clay-player__meta{min-width:0}
.clay-player__times{display:flex;justify-content:space-between;margin:-.4rem 0 0;font-size:.82rem;font-weight:700;color:var(--clay-muted)}
.clay-player__controls{display:flex;align-items:center;justify-content:center;gap:clamp(6px,2vw,16px)}
.clay-play .clay-play__pause,.clay-play[data-playing="true"] .clay-play__play{display:none}
.clay-play[data-playing="true"] .clay-play__pause{display:block}
/* Weather */
.clay-weather{display:grid;gap:1.1rem}
.clay-weather__now{display:flex;align-items:center;gap:1rem}
.clay-weather__icon{display:grid;place-items:center;flex:none;width:84px;height:84px;border:var(--clay-bw) solid var(--clay-line);border-radius:50%;background:var(--clay-lemon);box-shadow:var(--clay-shadow)}
.clay-weather__icon .clay-ico{width:42px;height:42px}
.clay-weather__temp{margin:0;font-size:3rem;font-weight:800;line-height:1}
.clay-weather__facts{display:flex;flex-wrap:wrap;gap:8px;margin:0;padding:0;list-style:none}
.clay-days{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin:0;padding:0;list-style:none}
.clay-day{display:grid;justify-items:center;gap:.2rem;padding:.7rem .3rem;border:var(--clay-bw) solid var(--clay-line);border-radius:20px;background:var(--clay-surface);box-shadow:var(--clay-shadow-sm);text-align:center}
.clay-day__name{font-size:.82rem;font-weight:800}
.clay-day__temp{font-size:.82rem;font-weight:700;color:var(--clay-muted)}
/* Mini calendar: a real table; today is an accent pebble with aria-current="date", event days get a dot and hidden text */
.clay-cal{display:grid;gap:.9rem}
.clay-cal__head{display:flex;align-items:center;justify-content:space-between;gap:.5rem}
.clay-cal__nav{display:flex;gap:8px}
.clay-cal__table{width:100%;border-collapse:separate;border-spacing:4px;table-layout:fixed;text-align:center}
.clay-cal__th{padding:.2rem 0;font-size:.74rem;font-weight:800;color:var(--clay-muted);text-transform:uppercase}
.clay-cal__th abbr{text-decoration:none;cursor:help}
.clay-cal__td{padding:0;font-size:.9rem;font-weight:700}
.clay-cal__day{position:relative;display:grid;place-items:center;height:36px;border-radius:13px}
.clay-cal__day--event::after{content:"";position:absolute;bottom:3px;left:50%;width:6px;height:6px;margin-left:-3px;border-radius:50%;background:var(--clay-success)}
.clay-cal__day--today{border:var(--clay-bw) solid var(--clay-accent);background:var(--clay-accent);color:var(--clay-on-accent);font-weight:800;box-shadow:var(--clay-shadow-sm)}
.clay-cal__day--today.clay-cal__day--event::after{background:var(--clay-on-accent)}
.clay-cal__list{display:grid;gap:8px;margin:0;padding:0;list-style:none}
.clay-cal__item{display:flex;align-items:center;gap:.7rem;padding:.55rem .7rem;border-radius:16px;background:var(--clay-fill,var(--clay-bg));font-size:.9rem;font-weight:700}
.clay-cal__when{margin-left:auto;font-weight:600;color:var(--clay-muted)}
/* Progress: bars with role="progressbar" and a conic-gradient ring for the weekly goal */
.clay-progress{display:grid;gap:1.1rem}
.clay-progress__row{display:grid;gap:.4rem}
.clay-progress__label{display:flex;justify-content:space-between;margin:0;font-weight:800}
.clay-progress__pct{color:var(--clay-muted)}
.clay-goal{display:flex;align-items:center;gap:1.1rem;padding-top:.3rem}
.clay-ring{--clay-pct:50;position:relative;display:grid;place-items:center;flex:none;width:104px;height:104px;border-radius:50%;
background:conic-gradient(var(--clay-accent) calc(var(--clay-pct)*1%),var(--clay-bg) 0);box-shadow:var(--clay-shadow-sm);border:var(--clay-bw) solid var(--clay-edge)}
.clay-ring::before{content:"";position:absolute;inset:14px;border-radius:50%;background:var(--clay-surface);box-shadow:var(--clay-well)}
.clay-ring__value{position:relative;font-size:1.25rem;font-weight:800}
/* Seek bar: Bootstrap .form-range with a well track, a puffy thumb and a painted fill */
.form-range.clay-bseek{--clay-val:50%;height:30px}
.clay-bseek::-webkit-slider-runnable-track{height:14px;border:var(--clay-bw) solid var(--clay-edge);border-radius:999px;box-shadow:var(--clay-well);
background:linear-gradient(90deg,var(--clay-accent) var(--clay-val),var(--clay-bg) var(--clay-val))}
.clay-bseek::-moz-range-track{height:14px;border:var(--clay-bw) solid var(--clay-edge);border-radius:999px;background:var(--clay-bg);box-shadow:var(--clay-well)}
.clay-bseek::-moz-range-progress{height:14px;border-radius:999px;background:var(--clay-accent)}
.clay-bseek::-webkit-slider-thumb{width:28px;height:28px;margin-top:-8.5px;border:var(--clay-bw) solid var(--clay-edge);border-radius:50%;background:var(--clay-lemon);box-shadow:var(--clay-shadow-sm)}
.clay-bseek::-moz-range-thumb{width:28px;height:28px;border:var(--clay-bw) solid var(--clay-edge);border-radius:50%;background:var(--clay-lemon);box-shadow:var(--clay-shadow-sm)}
.clay-bseek:focus::-webkit-slider-thumb,.clay-bseek:focus::-moz-range-thumb{box-shadow:var(--clay-shadow-sm)}
.clay-bseek:focus-visible{outline:3px solid var(--clay-accent);outline-offset:4px;border-radius:999px}
/* Progress bars: Bootstrap .progress through --bs-progress-* */
.progress.clay-progress-bar{--bs-progress-height:14px;--bs-progress-bg:var(--clay-bg);--bs-progress-border-radius:999px;--bs-progress-bar-bg:var(--clay-accent);
border:var(--clay-bw) solid var(--clay-edge);box-shadow:var(--clay-well)}
.clay-progress-bar .progress-bar{border-radius:999px}
JavaScript
// Music player: Play / Pause swaps its label and icon; the seek range reads "1:42 of 3:58"
document.querySelectorAll('[data-clay-player]').forEach(function (p) {
var play = p.querySelector('[data-clay-play]'), seek = p.querySelector('[data-clay-seek]'), now = p.querySelector('[data-clay-now]');
function fmt(s) { s = Math.round(s); return Math.floor(s / 60) + ':' + String(s % 60).padStart(2, '0'); }
if (play) play.addEventListener('click', function () {
var on = play.getAttribute("data-playing") !== "true";
play.setAttribute("data-playing", on); play.setAttribute('aria-label', on ? 'Pause' : 'Play');
});
if (seek) {
var paint = function () {
var pct = (seek.value - seek.min) / (seek.max - seek.min) * 100;
seek.style.setProperty('--clay-val', pct + '%');
if (now) now.textContent = fmt(seek.value);
seek.setAttribute('aria-valuetext', fmt(seek.value) + ' of ' + fmt(seek.max));
};
seek.addEventListener('input', paint); paint();
}
});
/* ── Claymorphism UI kit tokens (uiCookies) — identical in every set ──────────────
Every component is a puffy pastel object floating above --clay-bg: one big soft drop shadow
below it, an inset highlight top left and an inset shade bottom right. Change a token and
the whole kit follows; the shadow recipes below are built from these values. */
:root{
--clay-bg:#f3effa; /* page, a pale lilac white */
--clay-surface:#fffcf8; /* cards, fields and plain objects */
--clay-peach:#ffd2bd; /* object fills: ink text on every fill reaches 11:1 */
--clay-lilac:#dccdff;
--clay-mint:#bdeed6;
--clay-sky:#c2e0ff;
--clay-lemon:#ffe9a3;
--clay-ink:#241a3d; /* text, 14.4:1 on --clay-bg */
--clay-muted:#51476a; /* secondary text, 5.7:1 or more on every fill */
--clay-edge:#7a6e96; /* control boundary, 4.1:1 on --clay-bg, so shadows are never the only edge */
--clay-line:rgba(36,26,61,.12); /* decorative edge on cards and panels */
--clay-accent:#6236e8; /* focus ring and on / selected / current states, 5.8:1 on --clay-bg */
--clay-on-accent:#ffffff; /* text and marks on accent fills, 6.5:1 */
--clay-tint:#e9e1ff; /* light accent wash behind current items */
--clay-drop:rgba(86,56,168,.30); /* colour of the outer drop shadow */
--clay-hi:rgba(255,255,255,.88); /* inset highlight, top left */
--clay-lo:rgba(52,30,112,.20); /* inset shade, bottom right */
--clay-lift:14px; /* how high objects float; every shadow scales from it */
--clay-radius:30px; /* cards; buttons are pills, fields use .55 of it */
--clay-bw:1.5px; /* control border width */
--clay-success:#17663d;--clay-warning:#8a4b00;--clay-danger:#b3261e;
--clay-font:ui-rounded,"SF Pro Rounded","Nunito","Quicksand","Varela Round","Arial Rounded MT Bold",system-ui,sans-serif;
}
/* --clay-fill is set by .clay-peach, .clay-mint… on one object and must not leak into its children */
@property --clay-fill{syntax:"*";inherits:false}
/* Dark clay: data-clay="dark" on any wrapper, or a checked .clay-theme-input inside a [data-clay] element.
:is() is a forgiving list, so browsers without :has() still apply data-clay="dark" */
[data-clay]:is([data-clay="dark"],:has(.clay-theme-input:checked)){
--clay-bg:#1a1530;--clay-surface:#2a2347;
--clay-peach:#6e3f33;--clay-lilac:#4a3a8a;--clay-mint:#215a4a;--clay-sky:#26497c;--clay-lemon:#5f5220;
--clay-ink:#f7f3ff;--clay-muted:#d2c9ea;--clay-edge:#8f83b8;--clay-line:rgba(255,255,255,.1);
--clay-accent:#bba6ff;--clay-on-accent:#1a1530;--clay-tint:#3a2f66;
--clay-drop:rgba(4,2,14,.62);--clay-hi:rgba(255,255,255,.2);--clay-lo:rgba(0,0,0,.34);
--clay-success:#86e3b0;--clay-warning:#ffc76e;--clay-danger:#ffa196;color-scheme:dark}
/* More contrast requested: soft shading stays, but every edge and secondary text turns full ink */
@media (prefers-contrast:more){:root,[data-clay]:is([data-clay],:has(.clay-theme-input:checked)){
--clay-edge:var(--clay-ink);--clay-line:var(--clay-ink);--clay-muted:var(--clay-ink);--clay-bw:2px}}
:root,[data-clay]{
--clay-shadow:0 var(--clay-lift) calc(var(--clay-lift)*2.2) calc(var(--clay-lift)*-.3) var(--clay-drop),
inset calc(var(--clay-lift)*.45) calc(var(--clay-lift)*.5) calc(var(--clay-lift)*.9) var(--clay-hi),
inset calc(var(--clay-lift)*-.45) calc(var(--clay-lift)*-.6) calc(var(--clay-lift)*.9) var(--clay-lo);
--clay-shadow-sm:0 calc(var(--clay-lift)*.55) calc(var(--clay-lift)*1.2) calc(var(--clay-lift)*-.15) var(--clay-drop),
inset calc(var(--clay-lift)*.25) calc(var(--clay-lift)*.3) calc(var(--clay-lift)*.5) var(--clay-hi),
inset calc(var(--clay-lift)*-.25) calc(var(--clay-lift)*-.35) calc(var(--clay-lift)*.5) var(--clay-lo);
--clay-press:0 calc(var(--clay-lift)*.12) calc(var(--clay-lift)*.25) 0 var(--clay-drop),
inset calc(var(--clay-lift)*.2) calc(var(--clay-lift)*.25) calc(var(--clay-lift)*.45) var(--clay-lo),
inset calc(var(--clay-lift)*-.12) calc(var(--clay-lift)*-.12) calc(var(--clay-lift)*.3) var(--clay-hi);
--clay-well:inset calc(var(--clay-lift)*.15) calc(var(--clay-lift)*.22) calc(var(--clay-lift)*.45) var(--clay-lo),
inset calc(var(--clay-lift)*-.12) calc(var(--clay-lift)*-.12) calc(var(--clay-lift)*.3) var(--clay-hi);
}
[data-clay]{background:var(--clay-bg);color:var(--clay-ink)}
/* The tokens above, exposed as Tailwind utilities: bg-clay-peach, text-clay-muted, border-clay-edge,
shadow-clay, shadow-clay-sm, shadow-clay-press, shadow-clay-well, rounded-clay, rounded-clay-field, font-clay… */
@theme inline {
--color-clay-bg: var(--clay-bg); --color-clay-surface: var(--clay-surface);
--color-clay-peach: var(--clay-peach); --color-clay-lilac: var(--clay-lilac); --color-clay-mint: var(--clay-mint);
--color-clay-sky: var(--clay-sky); --color-clay-lemon: var(--clay-lemon);
--color-clay-ink: var(--clay-ink); --color-clay-muted: var(--clay-muted); --color-clay-edge: var(--clay-edge); --color-clay-line: var(--clay-line);
--color-clay-accent: var(--clay-accent); --color-clay-on-accent: var(--clay-on-accent); --color-clay-tint: var(--clay-tint);
--color-clay-success: var(--clay-success); --color-clay-warning: var(--clay-warning); --color-clay-danger: var(--clay-danger);
--shadow-clay: var(--clay-shadow); --shadow-clay-sm: var(--clay-shadow-sm); --shadow-clay-press: var(--clay-press); --shadow-clay-well: var(--clay-well);
--radius-clay: var(--clay-radius); --radius-clay-field: calc(var(--clay-radius) * .55); --radius-clay-sm: calc(var(--clay-radius) * .4);
--font-clay: var(--clay-font);
}
JavaScript
// Music player: Play / Pause swaps its label and icon; the seek range reads "1:42 of 3:58"
document.querySelectorAll('[data-clay-player]').forEach(function (p) {
var play = p.querySelector('[data-clay-play]'), seek = p.querySelector('[data-clay-seek]'), now = p.querySelector('[data-clay-now]');
function fmt(s) { s = Math.round(s); return Math.floor(s / 60) + ':' + String(s % 60).padStart(2, '0'); }
if (play) play.addEventListener('click', function () {
var on = play.getAttribute("data-playing") !== "true";
play.setAttribute("data-playing", on); play.setAttribute('aria-label', on ? 'Pause' : 'Play');
});
if (seek) {
var paint = function () {
var pct = (seek.value - seek.min) / (seek.max - seek.min) * 100;
seek.style.setProperty('--clay-val', pct + '%');
if (now) now.textContent = fmt(seek.value);
seek.setAttribute('aria-valuetext', fmt(seek.value) + ' of ' + fmt(seek.max));
};
seek.addEventListener('input', paint); paint();
}
});
About this set
Four widgets for a playful dashboard. The music player is a lilac card with a clay album cover, a song title and artist, a seek bar, elapsed and total time and round shuffle, previous, play, next and repeat buttons; Play swaps to a Pause icon and label when pressed. The weather card shows the current temperature beside a sun and cloud blob, wind, rain and UV chips and a four-day forecast of small pebbles. The mini calendar is a real table for October 2026 with weekday abbreviations, today as an accent pebble with aria-current=”date”, green dots and hidden text on event days, and two upcoming events below. The progress card has three labelled bars for reading, maths and art and a conic-gradient ring for a weekly goal of 86 of 100 minutes. Use them in a learning app, a family planner or a home screen. The seek bar is a native range input whose aria-valuetext reads, for example, 1:42 of 3:58, and the bars and ring carry progressbar semantics with labels and values. A short script handles the play button and the seek time.
What’s included
Music player with a native range seek bar and a Play and Pause button
Weather card with fact chips and a four-day forecast
Mini calendar as a real table with aria-current="date" on today
Progress bars and a conic-gradient goal ring with progressbar semantics
Bootstrap version built on .card, .form-range and .progress
Accessibility
Icon-only player buttons have aria-labels, and the play button changes its label between Play and Pause. The calendar uses th scope="col" headers with abbr titles, marks today with aria-current and spells out events in hidden text. Weather icons are paired with hidden condition words, and every interactive element shows a 3px accent focus ring.
Customise it
Change the fill classes on each card and --clay-accent for the seek fill, bars and ring. The ring reads its value from --clay-pct. Bootstrap maps the bars to --bs-progress-* variables, and Tailwind builds the ring with a conic-gradient arbitrary value.