/* ==========================================================================
   edcetera Components — canonical UI primitives
   Spec: docs/ui-design-system.md §8. Built ONLY on semantic tokens
   (public/css/tokens.css). Load AFTER tokens.css and style.css.

   This file is additive: legacy classes (.tbtn, .iconBtn, .dash-tools button,
   .primary, …) keep working until each surface is migrated onto these.
   ========================================================================== */

/* ==========================================================================
   Button — .btn
   Variants: primary | secondary | ghost | accent | danger | link
   Sizes:    sm | (md default) | lg   ·  Modifiers: block | icon
   ========================================================================== */
.btn{
  display:inline-flex; align-items:center; justify-content:center;
  gap:var(--space-2);
  font-family:var(--font-sans);
  font-size:var(--text-sm); font-weight:var(--weight-semibold);
  line-height:1.2; white-space:nowrap; text-decoration:none; user-select:none;
  padding:var(--space-2) var(--space-4);          /* md: 8/16 */
  border:1px solid transparent; border-radius:var(--radius-md);
  background:var(--surface-sunken); color:var(--text-primary);
  cursor:pointer;
  transition:background var(--duration-fast) var(--ease-standard),
             border-color var(--duration-fast) var(--ease-standard),
             color var(--duration-fast) var(--ease-standard),
             box-shadow var(--duration-fast) var(--ease-standard);
}
.btn svg.lucide{ width:16px; height:16px; flex:0 0 auto; }
.btn:focus-visible{ box-shadow:var(--shadow-focus); }
.btn[disabled], .btn.is-disabled{ opacity:.55; cursor:not-allowed; box-shadow:none; }

/* ---- Sizes ---- */
.btn--sm{ padding:6px var(--space-3); font-size:var(--text-xs); border-radius:var(--radius-sm); }
.btn--lg{ padding:var(--space-3) var(--space-5); font-size:var(--text-base); }

/* ---- Modifiers ---- */
.btn--block{ width:100%; }
.btn--icon{ padding:var(--space-2); width:36px; height:36px; }
.btn--icon.btn--sm{ width:30px; height:30px; padding:6px; }

/* ---- Variants ---- */
.btn--primary{ background:var(--primary); color:var(--on-primary); }
.btn--primary:hover{ background:var(--primary-hover); }
.btn--primary:active{ background:var(--primary-active); }

.btn--secondary{ background:var(--surface); border-color:var(--border-strong); color:var(--text-primary); }
.btn--secondary:hover{ background:var(--surface-sunken); }

.btn--ghost{ background:transparent; color:var(--text-secondary); }
.btn--ghost:hover{ background:var(--surface-sunken); color:var(--text-primary); }

.btn--accent{ background:var(--accent); color:var(--on-accent); }
.btn--accent:hover{ background:var(--accent-hover); }
.btn--accent:active{ background:var(--accent-active); }

.btn--danger{ background:var(--danger-solid); color:var(--text-inverse); }
.btn--danger:hover{ filter:brightness(.94); }

/* Soft/low-emphasis destructive action (e.g. inline "Archive" in dense grids). */
.btn--danger-soft{ background:var(--danger-surface); color:var(--danger-text); }
.btn--danger-soft:hover{ filter:brightness(.97); }

.btn--link{ background:transparent; border-color:transparent; color:var(--link);
  padding:0; border-radius:0; font-weight:var(--weight-semibold); }
.btn--link:hover{ color:var(--link-hover); text-decoration:underline; }

/* ==========================================================================
   Badge — .badge  (status pills, counts, flags)
   Variants: success | warning | danger | info | neutral | highlight
   ========================================================================== */
.badge{
  display:inline-flex; align-items:center; gap:4px;
  font-size:var(--text-xs); font-weight:var(--weight-semibold); line-height:1.5;
  padding:2px var(--space-2); border-radius:var(--radius-pill);
  background:var(--surface-sunken); color:var(--text-secondary);
  white-space:nowrap;
}
.badge--success{  background:var(--success-surface);      color:var(--success-text); }
.badge--warning{  background:var(--warning-surface);      color:var(--warning-text); }
.badge--danger{   background:var(--danger-surface);       color:var(--danger-text); }
.badge--info{     background:var(--info-surface);         color:var(--info-text); }
.badge--neutral{  background:var(--neutral-surface);      color:var(--neutral-status-text); }
.badge--highlight{background:var(--highlight-bg);         color:var(--orange-600); }

/* ==========================================================================
   Field — .field  (input / select / textarea) + .field-group / .field-label
   ========================================================================== */
.field-group{ display:grid; gap:var(--space-1); }
.field-label{
  font-size:var(--text-xs); font-weight:var(--weight-semibold);
  text-transform:uppercase; letter-spacing:var(--tracking-eyebrow);
  color:var(--text-secondary);
}
.field{
  width:100%; font-family:var(--font-sans); font-size:var(--text-base); line-height:1.4;
  color:var(--text-primary); background:var(--surface);
  border:1px solid var(--border); border-radius:var(--radius-sm);
  padding:var(--space-2) var(--space-3);
  transition:border-color var(--duration-fast) var(--ease-standard),
             box-shadow var(--duration-fast) var(--ease-standard);
}
.field::placeholder{ color:var(--text-disabled); }
.field:focus, .field:focus-visible{ outline:none; border-color:var(--accent); box-shadow:var(--shadow-focus); }
.field:disabled{ background:var(--surface-sunken); color:var(--text-disabled); cursor:not-allowed; }
.field.is-invalid{ border-color:var(--danger-solid); }
textarea.field{ min-height:86px; resize:vertical; }
select.field{ cursor:pointer; }
.field-hint{ font-size:var(--text-xs); color:var(--text-tertiary); }
.field-error{ font-size:var(--text-xs); color:var(--danger-text); }

/* Inline form-level error (docs/ui-fundamentals.md §3) — injected by
   formError(). Spans full width inside grid forms. */
.form-error{
  grid-column:1/-1;
  font-size:var(--text-sm); color:var(--danger-text);
  background:var(--danger-surface); border:1px solid var(--danger-solid);
  border-radius:var(--radius-sm);
  padding:var(--space-2) var(--space-3); margin-top:var(--space-2);
}
/* Invalid marking for legacy (non-.field) inputs — loads after style.css, so
   this wins equal-specificity border rules. */
input.is-invalid, select.is-invalid, textarea.is-invalid{ border-color:var(--danger-solid); }

/* ==========================================================================
   Card — .card  (+ __eyebrow / __head / __title, --interactive / --flush)
   ========================================================================== */
.card{
  background:var(--surface); border:1px solid var(--border);
  border-radius:var(--radius-lg); box-shadow:var(--shadow-sm);
  padding:var(--space-5);
}
.card--flush{ padding:0; overflow:hidden; }
.card--interactive{ cursor:pointer;
  transition:box-shadow var(--duration-base) var(--ease-standard),
             transform var(--duration-fast) var(--ease-standard); }
.card--interactive:hover{ box-shadow:var(--shadow-md); transform:translateY(-1px); }
.card__head{ display:flex; align-items:flex-start; justify-content:space-between;
  gap:var(--space-3); margin-bottom:var(--space-4); }
.card__eyebrow{ font-size:var(--text-xs); font-weight:var(--weight-semibold);
  text-transform:uppercase; letter-spacing:var(--tracking-eyebrow);
  color:var(--accent); margin-bottom:var(--space-1); }
.card__title{ font-size:var(--text-lg); font-weight:var(--weight-semibold); color:var(--text-primary); }
.card__sub{ font-size:var(--text-sm); color:var(--text-secondary); margin-top:2px; }

/* ==========================================================================
   Modal — .modal-backdrop > .modal (__head / __title / __body / __foot)
   Sizes: --sm | (md default) | --lg
   ========================================================================== */
.modal-backdrop{
  position:fixed; inset:0; z-index:100;
  background:rgba(15,23,42,.5);
  display:flex; align-items:center; justify-content:center; padding:var(--space-4);
}
.modal{
  width:100%; max-width:var(--modal-md); max-height:calc(100dvh - 2*var(--space-4));
  background:var(--surface); border-radius:var(--radius-xl); box-shadow:var(--shadow-lg);
  display:flex; flex-direction:column; overflow:hidden;
}
.modal--sm{ max-width:var(--modal-sm); }
.modal--lg{ max-width:var(--modal-lg); }
.modal__head{ display:flex; align-items:flex-start; justify-content:space-between;
  gap:var(--space-4); padding:var(--space-6); border-bottom:1px solid var(--border); }
.modal__title{ font-size:var(--text-2xl); font-weight:var(--weight-bold);
  color:var(--text-primary); letter-spacing:var(--tracking-tight); }
.modal__sub{ font-size:var(--text-sm); color:var(--text-secondary); margin-top:var(--space-1); }
.modal__body{ padding:var(--space-6); overflow:auto; }
.modal__foot{ display:flex; align-items:center; justify-content:flex-end; gap:var(--space-3);
  padding:var(--space-4) var(--space-6); border-top:1px solid var(--border); }

/* ==========================================================================
   Table — .table inside .table-wrap  (spec: docs/ui-design-system.md §8,
   usage rules: docs/dashboard-ui.md §4)
   Modifiers: --zebra. Numeric cells: .num (right-aligned tabular figures).
   Sorting: put aria-sort on the <th> — the affordance renders from the attr.
   Clickable rows: role="button" tabindex="0" on the <tr> (global key handler
   activates Enter/Space).
   ========================================================================== */
.table-wrap{ overflow-x:auto; }
.table{
  width:100%; border-collapse:collapse;
  font-size:var(--text-sm); color:var(--text-primary); background:var(--surface);
  text-align:left;
}
.table th{
  background:var(--surface-sunken); color:var(--text-secondary);
  font-size:var(--text-xs); font-weight:var(--weight-semibold);
  text-transform:uppercase; letter-spacing:var(--tracking-eyebrow);
  padding:var(--space-2) var(--space-3);
  position:sticky; top:0; z-index:1;
}
.table td{ padding:var(--space-2) var(--space-3); border-top:1px solid var(--border-subtle); vertical-align:top; }
.table--zebra tbody tr:nth-child(even) td{ background:var(--surface-sunken); }
.table .num{ text-align:right; font-variant-numeric:tabular-nums; }
.table tr.risk td{ background:color-mix(in srgb, var(--danger-surface) 45%, var(--surface)); }
.table tr[role="button"]{ cursor:pointer; }
.table tr[role="button"]:hover td, .table tr[role="button"]:focus-visible td{ background:var(--info-surface); }
.table--wide{ min-width:860px; }
/* Secondary line under a cell's main value (e.g. cohort under a name). */
.table .table__sub{ display:block; color:var(--text-tertiary); font-size:var(--text-xs); font-weight:var(--weight-regular); margin-top:2px; }
.table th[aria-sort]{ cursor:pointer; user-select:none; }
.table th[aria-sort]::after{ content:'↕'; opacity:.45; margin-left:4px; }
.table th[aria-sort="ascending"]::after{ content:'↑'; opacity:1; }
.table th[aria-sort="descending"]::after{ content:'↓'; opacity:1; }

/* ==========================================================================
   Drawer — .drawer (--left / --right, --sm | --md | --lg) with .is-open
   ========================================================================== */
.drawer{
  position:fixed; top:0; bottom:0; z-index:95;
  width:var(--drawer-md); max-width:calc(100vw - 2*var(--space-4));
  background:var(--surface); box-shadow:var(--shadow-lg);
  display:flex; flex-direction:column;
  transition:transform var(--duration-base) var(--ease-standard);
}
.drawer--sm{ width:var(--drawer-sm); }
.drawer--lg{ width:var(--drawer-lg); }
.drawer--right{ right:0; transform:translateX(100%); }
.drawer--left{ left:0;  transform:translateX(-100%); }
.drawer.is-open{ transform:none; }
.drawer__head{ display:flex; align-items:center; justify-content:space-between;
  gap:var(--space-3); padding:var(--space-4); border-bottom:1px solid var(--border); }
.drawer__title{ font-size:var(--text-lg); font-weight:var(--weight-semibold); color:var(--text-primary); }
.drawer__body{ flex:1; overflow:auto; padding:var(--space-4); }
