/* LUCID'S PARTS KIT — one rule set per part. 15 October 2026.
   =========================================================================
   Matt, 15 Oct: "Yes. I like starting with mail." Every room built its own
   buttons, cards, rows, popups and empty states and restyled them with
   stacked overrides; docs/KIT-INVENTORY.md counts them. This is the one set
   they move onto. It is not wired into any room yet — Mail is first, and
   Matt reviews docs/kit-demo.html before anything is.

   THE LOOK IS MAIL'S. Every value here is the token that Mail and the New
   Message dialog already resolve to today: same faces, same radii, same
   washes, same glows. A cleanup of the spelling, not a redesign.

   THE RULES THIS FILE KEEPS, and tests/test-kit.js holds it to them:
     · Only tokens. Sizes, corners, spacing, type and elevation come from
       app/tokens.css; colour, washes and motion from app.css's own :root,
       restated per theme there. The only literal length is a 1px hairline.
     · No !important. Anything that needs one is fighting an override, and
       the kit exists so there are no overrides to fight.
     · Every class is prefixed k-. Variants are modifiers (k-btn--primary);
       states are attributes (aria-pressed, aria-busy, data-state="failed").
     · Light mode keys off :root[data-mode="light"], like the rest of Lucid.
   ========================================================================= */

/* Three kit aliases, each a token under another name, because the right
   token differs between dark and light and the parts should not care.
   There is no --red: danger is --cat-red-2 on dark, --cat-red on paper,
   exactly as .btn.danger does it today. */
:root{
  --k-danger: var(--cat-red-2);
  --k-knob: var(--neutral-2);
  --k-glow: 0 0 var(--space-4) var(--ring-gap) var(--accent-glow);
  /* Mail's 3px account edge on a row, and the failed state's edge. */
  --k-edge: calc(var(--space-hair) + var(--ring-gap));
}
:root[data-mode="light"]{
  --k-danger: var(--cat-red);
  --k-knob: var(--bg-mid);
  --k-glow: none;
}

/* ---------------------------------------------------------------------------
   BUTTON — k-btn. Mail's .btn, its toolbar .tb-btn, its .chip.
   ------------------------------------------------------------------------ */
.k-btn{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--space-2);
  padding:var(--space-3) var(--space-5);
  border:1px solid var(--glass-border-hi); border-radius:var(--radius-card);
  background:var(--wash-soft); color:var(--text);
  font-family:var(--font-body); font-size:var(--type-body); font-weight:var(--weight-strong);
  line-height:1.2; white-space:nowrap; cursor:pointer;
  transition:background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out),
             border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.k-btn:hover:not(:disabled){ background:var(--wash-hover); }
.k-btn:focus-visible{ outline:var(--ring-width) solid var(--accent); outline-offset:var(--ring-gap); }
.k-btn:disabled{ opacity:.4; cursor:default; }
.k-btn svg{ width:var(--space-4); height:var(--space-4); flex:none; }

.k-btn--sm{ padding:var(--space-1) var(--space-3); border-radius:var(--radius-control); }

/* PRIMARY IS THE TINTED ONE, because that is New Message's Send. */
.k-btn--primary{
  background:color-mix(in srgb, var(--accent) 14%, transparent);
  border-color:color-mix(in srgb, var(--accent) 42%, transparent);
  color:color-mix(in srgb, var(--accent-2, var(--accent)) 58%, var(--text));
  box-shadow:var(--k-glow);
}
.k-btn--primary:hover:not(:disabled){ background:color-mix(in srgb, var(--accent) 22%, transparent); }
:root[data-mode="light"] .k-btn--primary{ color:color-mix(in srgb, var(--accent) 78%, var(--text)); }

/* SOLID — the accent gradient that .btn.primary wears outside Mail, kept so
   those rooms can move over without changing. */
.k-btn--solid{
  background:linear-gradient(135deg, var(--accent), var(--accent-2));
  border-color:transparent; color:var(--ink); box-shadow:var(--k-glow);
}
.k-btn--solid:hover:not(:disabled){ background:linear-gradient(135deg, var(--accent), var(--accent-2)); filter:brightness(1.08); }
:root[data-mode="light"] .k-btn--solid{
  background:linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 82%, var(--bg-mid)));
  color:var(--on-accent, var(--bg-mid));
}

.k-btn--danger{
  color:var(--k-danger);
  border-color:color-mix(in srgb, var(--k-danger) 45%, transparent);
  background:color-mix(in srgb, var(--k-danger) 10%, transparent);
}
.k-btn--danger:hover:not(:disabled){ background:color-mix(in srgb, var(--k-danger) 20%, transparent); border-color:var(--k-danger); }

/* QUIET — no border, no fill until hovered: the toolbar's text buttons. */
.k-btn--quiet{ background:transparent; border-color:transparent; color:var(--text-dim); }
.k-btn--quiet:hover:not(:disabled){ color:var(--text); }

/* ICON-ONLY — Mail's .tb-btn: 34 square, control corners, no border. */
.k-btn--icon{
  width:calc(var(--space-8) + var(--space-hair)); height:calc(var(--space-8) + var(--space-hair));
  padding:0; border-color:transparent; border-radius:var(--radius-control);
  background:transparent; color:var(--text-dim);
}
.k-btn--icon:hover:not(:disabled){ color:var(--text); }

/* CHIP — Mail's .chip. Pressed is aria-pressed, not .active. */
.k-btn--chip{
  padding:var(--space-2) var(--space-4); border-radius:var(--radius-pill);
  border-color:var(--glass-border); background:transparent; color:var(--text-dim);
}
.k-btn--chip[aria-pressed="true"]{ background:var(--wash-hover); color:var(--text); border-color:var(--glass-border-hi); box-shadow:var(--k-glow); }
.k-btn--chip .k-btn__n{ font-family:var(--font-mono); font-size:var(--type-label); color:var(--text-faint); font-weight:var(--weight-medium); }

/* LINK — .mini-link: the action inside an empty or a failed state. */
.k-btn--link{
  padding:0; border:0; background:transparent; border-radius:var(--radius-tight);
  color:var(--blue); font-size:var(--type-label); font-weight:var(--weight-medium);
}
.k-btn--link:hover:not(:disabled){ background:transparent; text-decoration:underline; }

/* BUSY — aria-busy. The label stays (so the button keeps its width and says
   what it is doing) and a ring turns beside it. */
.k-btn[aria-busy="true"]{ cursor:progress; }
.k-btn[aria-busy="true"]::before{
  content:''; width:var(--space-3); height:var(--space-3); flex:none;
  border:var(--ring-width) solid currentColor; border-right-color:transparent; border-radius:var(--radius-round);
  animation:k-turn var(--dur-tick) linear infinite;
}
@keyframes k-turn{ to{ transform:rotate(360deg); } }

/* ---------------------------------------------------------------------------
   CARD — k-card. The .glass surface Mail's panes are cut from.
   ------------------------------------------------------------------------ */
.k-card{
  position:relative; padding:var(--space-4) var(--space-5);
  border:1px solid var(--glass-border); border-radius:var(--radius-card);
  background:var(--glass-sheen), var(--glass-bg); color:var(--text);
  box-shadow:var(--glass-shadow, var(--elev-raised));
  font-family:var(--font-body); font-size:var(--type-body);
}
:root[data-mode="light"] .k-card{ background:var(--glass-sheen), color-mix(in srgb, var(--bg-mid) 96%, transparent); }
.k-card--flat{ box-shadow:var(--elev-flat); background:var(--wash-soft); }
.k-card__eyebrow{ font-size:var(--type-label); font-weight:var(--weight-loud); text-transform:uppercase; letter-spacing:.09em; color:var(--text-dim); margin:0 0 var(--space-2); }
.k-card__title{ font-family:var(--font-display); font-size:var(--type-lead); font-weight:var(--weight-strong); margin:0 0 var(--space-2); }
.k-card__body{ color:var(--text-dim); line-height:1.5; margin:0; }
.k-card__actions{ display:flex; flex-wrap:wrap; gap:var(--space-2); margin-top:var(--space-4); }

/* ---------------------------------------------------------------------------
   LIST ROW — k-row. The mail row is the reference: 3px tone edge, 38 round
   face, bold who, mono time, subject, one line of preview.
   The tone is --k-tone, set inline by kitRow() from one of the six hues.
   ------------------------------------------------------------------------ */
.k-row{
  position:relative; display:flex; align-items:flex-start; gap:var(--space-3);
  padding:var(--space-3); margin-bottom:var(--space-1);
  border-left:var(--k-edge) solid var(--k-tone, transparent); border-radius:var(--radius-card);
  color:var(--text); font-family:var(--font-body); font-size:var(--type-body);
  cursor:pointer; overflow:hidden;
  transition:background var(--dur-fast) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.k-row:hover{ background:var(--wash-hover); }
.k-row:focus-visible{ outline:var(--ring-width) solid var(--accent); outline-offset:calc(var(--ring-gap) * -1); }
.k-row[aria-selected="true"]{
  background:color-mix(in srgb, var(--k-tone, var(--accent)) 16%, transparent);
  box-shadow:0 0 0 1px color-mix(in srgb, var(--k-tone, var(--accent)) 35%, transparent);
}
.k-row__face{
  width:calc(var(--space-10) - var(--space-hair)); height:calc(var(--space-10) - var(--space-hair));
  flex:none; display:flex; align-items:center; justify-content:center;
  border-radius:var(--radius-round); border:1px solid color-mix(in srgb, var(--k-tone, var(--blue)) 40%, var(--glass-border-hi));
  background:linear-gradient(135deg, color-mix(in srgb, var(--k-tone, var(--blue)) 36%, transparent), color-mix(in srgb, var(--k-tone, var(--blue)) 12%, transparent));
  font-size:var(--type-body); font-weight:var(--weight-loud); color:var(--text);
}
:root[data-mode="light"] .k-row__face{
  background:linear-gradient(135deg, color-mix(in srgb, var(--k-tone, var(--blue)) 30%, var(--bg-mid)), color-mix(in srgb, var(--k-tone, var(--blue)) 12%, var(--bg-mid)));
  border-color:color-mix(in srgb, var(--k-tone, var(--blue)) 30%, var(--glass-border-hi));
}
.k-row__main{ flex:1; min-width:0; }
.k-row__top{ display:flex; justify-content:space-between; gap:var(--space-2); }
.k-row__title{ font-weight:var(--weight-loud); min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.k-row__meta{ font-family:var(--font-mono); font-size:var(--type-label); color:var(--text-dim); flex:none; }
.k-row__sub{ margin-top:var(--space-hair); color:var(--text); min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.k-row__preview{ margin-top:var(--space-1); color:color-mix(in srgb, var(--text) 25%, var(--text-dim)); min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.k-row__dot{
  display:inline-block; width:calc(var(--space-1) + var(--space-hair)); height:calc(var(--space-1) + var(--space-hair));
  margin-right:var(--space-2); vertical-align:middle; border-radius:var(--radius-round);
  background:var(--accent); box-shadow:var(--k-glow);
}
.k-row__trail{ flex:none; align-self:center; }
/* The account glow Mail's rows wear on dark (--row-glow is the hue at ~45%). */
:root:not([data-mode="light"]) .k-row{ box-shadow:0 0 var(--space-3) 0 color-mix(in srgb, var(--k-tone, transparent) 45%, transparent); }
:root:not([data-mode="light"]) .k-row:hover{ box-shadow:0 0 var(--space-4) var(--ring-gap) color-mix(in srgb, var(--k-tone, var(--accent)) 45%, transparent); }
:root:not([data-mode="light"]) .k-row[aria-selected="true"]{
  box-shadow:0 0 0 1px color-mix(in srgb, var(--k-tone, var(--accent)) 35%, transparent),
             0 0 var(--space-6) var(--space-1) color-mix(in srgb, var(--k-tone, var(--accent)) 45%, transparent);
}

/* ---------------------------------------------------------------------------
   POPUP — k-scrim + k-modal. New Message is the reference. The right-side
   TRAY is not here: it is pinned by tests/test-lucid-look-is-pinned.js and
   stays .modal-backdrop.as-tray until Matt says otherwise.
   ------------------------------------------------------------------------ */
.k-scrim{
  position:fixed; inset:0; z-index:50; display:flex; align-items:center; justify-content:center;
  padding:var(--space-4); background:color-mix(in srgb, var(--bg-deep) 50%, transparent);
  backdrop-filter:blur(var(--space-1)); -webkit-backdrop-filter:blur(var(--space-1));
}
.k-scrim[hidden]{ display:none; }
.k-modal{
  position:relative; width:100%; max-width:min(54rem, 100%); max-height:88vh; overflow-y:auto;
  padding:var(--space-6); border:1px solid var(--glass-border); border-radius:var(--radius-card);
  background:var(--glass-sheen), linear-gradient(var(--glass-bg), var(--glass-bg)), color-mix(in srgb, var(--bg-base) 96%, transparent);
  box-shadow:var(--elev-floating); color:var(--text); font-family:var(--font-body); font-size:var(--type-body);
}
:root[data-mode="light"] .k-modal{ background:var(--glass-sheen), color-mix(in srgb, var(--bg-mid) 96%, transparent); }
.k-modal--inline{ max-height:none; }
.k-modal__head{ display:flex; align-items:center; justify-content:space-between; gap:var(--space-3); margin-bottom:var(--space-4); }
.k-modal__title{ font-family:var(--font-display); font-size:var(--type-title); font-weight:var(--weight-strong); margin:0; }
.k-modal__foot{ display:flex; flex-wrap:wrap; justify-content:flex-end; gap:var(--space-2); margin-top:var(--space-5); }

/* MENU — k-menu. Mail's ⋯ More (.tb-more-menu / .tb-more-item). */
.k-menu{
  display:flex; flex-direction:column; gap:var(--space-hair); min-width:16.5rem; padding:var(--space-2);
  border:1px solid var(--glass-border); border-radius:var(--radius-card);
  background:var(--glass-sheen), linear-gradient(var(--glass-bg), var(--glass-bg)), var(--bg-base);
  box-shadow:var(--elev-floating); font-family:var(--font-body);
}
:root[data-mode="light"] .k-menu{ background:color-mix(in srgb, var(--bg-mid) 97%, transparent); }
.k-menu[hidden]{ display:none; }
.k-menu__item{
  display:grid; grid-template-columns:var(--space-4) 1fr auto; align-items:center; column-gap:var(--space-3);
  width:100%; padding:var(--space-2) var(--space-3); border:0; border-radius:var(--radius-control);
  background:transparent; color:var(--text); font-family:inherit; font-size:var(--type-body); text-align:left; cursor:pointer;
}
.k-menu__item:hover, .k-menu__item:focus-visible{ background:color-mix(in srgb, var(--accent) 12%, transparent); outline:none; }
.k-menu__item svg{ width:var(--space-4); height:var(--space-4); color:var(--text-dim); }
.k-menu__hint{ grid-column:2 / 4; font-size:var(--type-label); color:var(--text-faint); }
.k-menu__tick{ grid-column:3; grid-row:1; color:var(--accent); visibility:hidden; }
.k-menu__item[aria-checked="true"] .k-menu__tick{ visibility:visible; }
.k-menu__item--danger{ color:var(--k-danger); }
.k-menu__item--danger:hover{ background:color-mix(in srgb, var(--k-danger) 14%, transparent); }
.k-menu__sep{ height:1px; margin:var(--space-1) var(--space-2); background:var(--glass-border); }

/* ---------------------------------------------------------------------------
   TEXT FIELD — k-field. Mail's .field, with its label.
   ------------------------------------------------------------------------ */
.k-field{ display:flex; flex-direction:column; gap:var(--space-2); font-family:var(--font-body); }
.k-field__label{ font-size:var(--type-label); font-weight:var(--weight-loud); text-transform:uppercase; letter-spacing:.09em; color:var(--text-dim); }
.k-field__control{
  width:100%; box-sizing:border-box; padding:var(--space-3) var(--space-4);
  border:1px solid var(--glass-border); border-radius:var(--radius-card);
  background:var(--field-fill, var(--wash-soft)); color:var(--text);
  font-family:var(--font-body); font-size:var(--type-lead);
  transition:border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.k-field__control::placeholder{ color:var(--text-faint); }
.k-field__control:focus{ outline:none; border-color:color-mix(in srgb, var(--accent) 50%, transparent); box-shadow:var(--k-glow); }
textarea.k-field__control{ min-height:7.5rem; resize:vertical; line-height:1.5; }
select.k-field__control{ cursor:pointer; }
.k-field__hint{ font-size:var(--type-label); color:var(--text-faint); }
.k-field__control[aria-invalid="true"]{ border-color:var(--k-danger); }
.k-field__control[aria-invalid="true"] ~ .k-field__hint{ color:var(--k-danger); }

/* ---------------------------------------------------------------------------
   SWITCH — k-switch. New Message's "Include signature": a 34 × 20 capsule,
   a 16 knob, accent when on. The input stays a real checkbox (role=switch).
   ------------------------------------------------------------------------ */
.k-switch{ display:inline-flex; align-items:center; gap:var(--space-2); cursor:pointer; user-select:none; font-family:var(--font-body); font-size:var(--type-body); color:var(--text-dim); }
.k-switch__in{ position:absolute; opacity:0; width:1px; height:1px; pointer-events:none; }
.k-switch__track{
  position:relative; flex:none;
  width:calc(var(--space-8) + var(--space-hair)); height:var(--space-5);
  border-radius:var(--radius-pill); background:var(--glass-border-hi);
  transition:background var(--dur-fast) var(--ease-out);
}
.k-switch__track::after{
  content:''; position:absolute; top:var(--space-hair); left:var(--space-hair);
  width:var(--space-4); height:var(--space-4); border-radius:var(--radius-round);
  background:var(--k-knob); box-shadow:var(--elev-raised);
  transition:transform var(--dur-fast) var(--ease-out);
}
.k-switch__in:checked + .k-switch__track{ background:var(--accent); }
.k-switch__in:checked + .k-switch__track::after{ transform:translateX(calc(var(--space-3) + var(--space-hair))); }
.k-switch__in:checked ~ .k-switch__label{ color:var(--text); }
.k-switch__in:focus-visible + .k-switch__track{ outline:var(--ring-width) solid var(--accent); outline-offset:var(--ring-width); }
.k-switch__in:disabled ~ *{ opacity:.45; cursor:default; }

/* ---------------------------------------------------------------------------
   EMPTY, FAILED, LOADING — three parts, never one. Rule 211: a failed read
   must never render like an empty one. Today Mail draws all three in
   .mail-empty and only the words differ. Here they differ in role, shape,
   colour, mark and words.
   ------------------------------------------------------------------------ */
/* EMPTY — the read worked and there is nothing. Calm, centred, faint. */
.k-empty{
  padding:var(--space-12) var(--space-5); text-align:center;
  color:var(--text-faint); font-family:var(--font-body); font-size:var(--type-body);
}
.k-empty__title{ margin:0 0 var(--space-2); font-size:var(--type-lead); font-weight:var(--weight-strong); color:var(--text-dim); }
.k-empty__sub{ max-width:34rem; margin:0 auto; line-height:1.65; }
.k-empty__act{ margin-top:var(--space-3); }

/* FAILED — the read did not work. Left-aligned, edged, marked, and it says
   so. Never centred and faint, because that is what empty looks like. */
.k-fail{
  display:grid; grid-template-columns:auto 1fr; column-gap:var(--space-3); align-items:start;
  margin:var(--space-3) 0; padding:var(--space-4) var(--space-5);
  border:1px solid color-mix(in srgb, var(--k-danger) 35%, transparent);
  border-left:var(--k-edge) solid var(--k-danger); border-radius:var(--radius-card);
  background:color-mix(in srgb, var(--k-danger) 8%, transparent);
  color:var(--text); font-family:var(--font-body); font-size:var(--type-body); text-align:left;
}
.k-fail__mark{
  width:var(--space-5); height:var(--space-5); grid-row:1 / span 4;
  display:flex; align-items:center; justify-content:center;
  border-radius:var(--radius-round); background:var(--k-danger); color:var(--bg-deep);
  font-size:var(--type-label); font-weight:var(--weight-loud);
}
.k-fail__title{ margin:0; font-size:var(--type-body); font-weight:var(--weight-loud); color:var(--text); }
.k-fail__why{ margin:var(--space-1) 0 0; color:var(--text-dim); line-height:1.5; }
.k-fail__detail{ margin:var(--space-1) 0 0; font-family:var(--font-mono); font-size:var(--type-label); color:var(--text-faint); overflow-wrap:anywhere; }
.k-fail__act{ margin-top:var(--space-3); }

/* LOADING — the read has not come back. Says so in words, and shows lines
   where the rows will be. */
.k-loading{ padding:var(--space-4) var(--space-3); font-family:var(--font-body); font-size:var(--type-body); color:var(--text-dim); }
.k-loading__say{ display:flex; align-items:center; gap:var(--space-2); margin:0 0 var(--space-3); }
.k-loading__say::before{
  content:''; width:calc(var(--space-1) + var(--space-hair)); height:calc(var(--space-1) + var(--space-hair));
  border-radius:var(--radius-round); background:var(--accent); box-shadow:var(--k-glow);
  animation:k-breathe var(--dur-ambient) var(--ease-in-out) infinite alternate;
}
.k-loading__line{
  height:var(--space-3); margin:var(--space-3) 0; border-radius:var(--radius-tight);
  background:linear-gradient(90deg, var(--wash-soft), var(--wash-hover), var(--wash-soft));
  background-size:200% 100%; animation:k-sheen var(--dur-ambient) var(--ease-linear, linear) infinite;
}
.k-loading__line:nth-child(3n){ width:62%; }
.k-loading__line:nth-child(3n+1){ width:88%; }
@keyframes k-breathe{ from{ opacity:.35; } to{ opacity:1; } }
@keyframes k-sheen{ from{ background-position:100% 0; } to{ background-position:-100% 0; } }
@media (prefers-reduced-motion: reduce){
  .k-loading__say::before, .k-loading__line, .k-btn[aria-busy="true"]::before{ animation:none; }
}

/* ---------------------------------------------------------------------------
   TOAST — k-toast. Mail's .toast: glass, a tone dot, an Undo, a close.
   ------------------------------------------------------------------------ */
.k-toast{
  display:flex; align-items:flex-start; gap:var(--space-3); max-width:min(26rem, 100%);
  padding:var(--space-3) var(--space-4); border:1px solid var(--glass-border); border-radius:var(--radius-card);
  background:var(--glass-bg); backdrop-filter:blur(var(--space-4)); -webkit-backdrop-filter:blur(var(--space-4));
  box-shadow:var(--elev-floating); color:var(--text); font-family:var(--font-body); font-size:var(--type-body); line-height:1.45;
}
:root[data-mode="light"] .k-toast{ background:color-mix(in srgb, var(--bg-mid) 96%, transparent); }
.k-toast__dot{ width:var(--space-2); height:var(--space-2); margin-top:var(--space-1); flex:none; border-radius:var(--radius-round); background:var(--text-dim); }
.k-toast[data-tone="ok"] .k-toast__dot{ background:var(--green); box-shadow:0 0 var(--space-2) var(--ring-gap) var(--green-glow); }
.k-toast[data-tone="warn"] .k-toast__dot{ background:var(--orange); box-shadow:0 0 var(--space-2) var(--ring-gap) var(--orange-glow); }
.k-toast[data-tone="failed"] .k-toast__dot{ background:var(--k-danger); box-shadow:0 0 var(--space-2) var(--ring-gap) var(--cat-red-glow); }
.k-toast__say{ flex:1; min-width:0; }
.k-toast__undo{ flex:none; padding:0; border:0; background:none; color:var(--accent); font:inherit; font-weight:var(--weight-strong); text-decoration:underline; text-underline-offset:var(--space-hair); cursor:pointer; }
.k-toast__x{ flex:none; padding:0; border:0; background:none; color:var(--text-faint); font:inherit; cursor:pointer; }
.k-toast__x:hover{ color:var(--text); }
