/* KVCoders 2.0 -- Component Primitives
 *
 * One recipe per component (Master Plan Part 7), each harvested from the
 * existing implementation it's built from rather than invented fresh.
 * Requires design-tokens.css to be loaded first.
 *
 * Naming note: the student shell (examiner/includes/student_chrome_header.php)
 * already has a working, live three-tier button system named
 * .cta-primary/-secondary/-subtle, referenced by three already-migrated
 * pages (mcq/universal_test.php, output_test/universal_output.php, SQL
 * Arena's submit button). Renaming those classes now would break three
 * live pages for zero benefit, so the shell keeps its own .cta-* names
 * (now pointed at the canonical --brand-* tokens via the shell's own
 * :root, not this file) and this file's .btn-* is the same recipe under
 * the forward-looking canonical name, for pages built from this point
 * on -- starting with examiner/exams/index.php. See
 * KVCODERS_UI_UX_2_0_PHASE1_FOUNDATION.md for the full rationale. The
 * two are not meant to silently drift apart: any future change to one
 * recipe should be mirrored in the other until the three legacy .cta-*
 * consumers are migrated and .cta-* can be retired.
 */

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  border-radius: 999px;
  font-weight: 700;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  text-decoration: none;
  cursor: pointer;
  border: none;
  transition: transform var(--duration-micro) var(--ease),
              box-shadow var(--duration-micro) var(--ease),
              background var(--duration-micro) var(--ease),
              opacity var(--duration-micro) var(--ease);
}
.btn:disabled, .btn[aria-disabled="true"] {
  cursor: not-allowed;
  opacity: 0.5;
  transform: none !important;
}

.btn-primary {
  background: var(--brand-600);
  color: #fff;
  padding: 14px 28px;
  box-shadow: 0 8px 20px rgba(91,79,232,0.22);
}
.btn-primary:hover:not(:disabled) {
  background: var(--brand-700);
  transform: translateY(-2px);
  box-shadow: 0 12px 26px rgba(91,79,232,0.3);
}

.btn-secondary {
  background: transparent;
  color: var(--brand-600);
  border: 2px solid var(--brand-600);
  padding: 12px 26px;
}
.btn-secondary:hover:not(:disabled) {
  background: var(--brand-100);
  transform: translateY(-2px);
}

.btn-subtle {
  background: var(--brand-100);
  color: var(--brand-600);
  padding: 8px 16px;
  font-size: var(--text-xs);
}
.btn-subtle:hover:not(:disabled) {
  background: #E0DCFC;
}

/* ---------- Cards ---------- */
/* Base recipe generalized from examiner/question-browser/includes/
   qb_shared_head.php's .qb-block-card -- one hue, decreasing opacity for
   authority signal, not a rainbow of borders per card type. */

.card {
  background: var(--surface-card);
  border: 1px solid var(--border-canvas);
  border-left: 3px solid var(--border-canvas);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: var(--space-6);
  transition: transform var(--duration-standard) var(--ease),
              box-shadow var(--duration-standard) var(--ease);
}
.card:hover {
  box-shadow: var(--shadow-md);
}

/* Subject-identity accent -- the left border only. Reserved for content
   genuinely scoped to one subject; never decorative. */
.card-cs { border-left-color: var(--cs-500); }
.card-ip { border-left-color: var(--ip-500); }

/* Content-authority accent -- mirrors qb-block-card's board/sample/
   preboard/practice modifiers exactly (one hue, varying opacity). */
.card-board    { border-left-color: rgba(91,79,232,0.85); }
.card-sample   { border-left-color: rgba(91,79,232,0.5); }
.card-preboard { border-left-color: rgba(91,79,232,0.28); }
.card-practice { border-left-color: var(--border-canvas); }

/* ---------- Badges ---------- */
/* Generalized from qb-badge-easy/-medium/-hard. */

.badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 20px;
  font-size: var(--text-xs);
  font-weight: 700;
  font-family: var(--font-body);
}
.badge-easy   { background: rgba(16,185,129,0.12); color: var(--success-500); }
.badge-medium { background: rgba(249,115,22,0.12); color: var(--warning-500); }
.badge-hard   { background: rgba(239,68,68,0.12);  color: var(--danger-500); }
/* --cs-700/--ip-700, not --cs-500/--ip-500 -- axe-core measured the
   500-shades at 3.48:1/2.31:1 against these exact tint backgrounds,
   below WCAG AA's 4.5:1 for text. Found and fixed via the Phase 2
   public homepage rebuild; see design-tokens.css's own comment on
   --cs-700/--ip-700 for the full contrast math. */
.badge-cs { background: var(--cs-100); color: var(--cs-700); }
.badge-ip { background: var(--ip-100); color: var(--ip-700); }

/* ---------- Forms ---------- */
/* Harvested from examiner/auth/includes/auth_head.php's .field recipe --
   the most internally consistent, accessible subsystem in the codebase.
   auth_head.php itself is NOT modified in this phase (see migration
   doc); this is a parallel recipe for new pages to consume directly. */

.field { margin-bottom: 18px; }
.field label {
  display: block;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--text-sm);
  color: var(--text-canvas-muted);
  margin-bottom: 7px;
}
.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 13px 14px;
  border-radius: var(--radius-sm);
  border: 1.5px solid var(--border-canvas);
  background: var(--surface-alt);
  color: var(--text-canvas);
  font-family: var(--font-body);
  font-size: var(--text-base);
  box-shadow: inset 0 1px 2px rgba(15,23,42,0.05);
  transition: background-color var(--duration-micro) var(--ease),
              border-color var(--duration-micro) var(--ease),
              box-shadow var(--duration-micro) var(--ease);
}
.field input::placeholder,
.field textarea::placeholder { color: var(--text-canvas-muted); opacity: 0.7; }
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  background: var(--surface-card);
  border-color: var(--brand-600);
  box-shadow: 0 0 0 4px var(--brand-100);
}

/* ---------- Tables ---------- */
/* One recipe replaces ~4 different table treatments found in the audit.
   Zebra-free by design -- a bottom border per row is enough separation. */

.table { width: 100%; border-collapse: collapse; font-family: var(--font-body); }
.table th {
  text-align: left;
  text-transform: uppercase;
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.4px;
  color: var(--slate-500);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-canvas);
}
.table td {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-canvas);
  font-size: var(--text-sm);
  color: var(--text-canvas);
}
.table td.numeric, .table th.numeric { font-variant-numeric: tabular-nums; text-align: right; }

/* ---------- Alerts ---------- */
/* Generalized from auth_head.php's .auth-alert-*. */

.alert {
  padding: 13px 16px;
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: 500;
  line-height: 1.5;
  font-family: var(--font-body);
}
.alert-error   { background: rgba(239,68,68,0.1);  color: #B91C1C; border-left: 3px solid var(--danger-500); }
.alert-success { background: rgba(16,185,129,0.1); color: #065F46; border-left: 3px solid var(--success-500); }
.alert-warning { background: rgba(249,115,22,0.1); color: #9A3412; border-left: 3px solid var(--warning-500); }

/* ---------- Progress indicators ---------- */
/* One shape language: pill for inline stats, ring for a single hero
   score -- currently student.php's .stat-pill and SQL Arena's
   .score-circle are unrelated; this is the convergence point. */

.stat-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border-radius: 999px;
  background: var(--surface-alt);
  border: 1px solid var(--border-canvas);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-canvas);
}
.stat-pill i { color: var(--brand-600); }

.score-circle {
  --score-size: 120px;
  --score-ring: 10px;
  position: relative;
  width: var(--score-size);
  height: var(--score-size);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: conic-gradient(var(--brand-600) calc(var(--score-percent, 0) * 1%), var(--border-canvas) 0);
}
.score-circle::before {
  content: '';
  position: absolute;
  inset: var(--score-ring);
  border-radius: 50%;
  background: var(--surface-card);
}
.score-circle span {
  position: relative;
  z-index: 1;
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 700;
  color: var(--text-canvas);
}

/* ---------- Empty / loading / error states ---------- */
/* Genuinely new -- Part 7 flags this as a real gap, not a consolidation
   target. One pattern for "no data yet," reused everywhere a list/card
   grid can legitimately be empty. */

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-3);
  padding: var(--space-12) var(--space-6);
  color: var(--text-canvas-muted);
}
.empty-state i { font-size: 2rem; color: var(--slate-400); }
.empty-state p { margin: 0; font-family: var(--font-body); font-size: var(--text-sm); max-width: 40ch; }

.skeleton {
  background: linear-gradient(90deg, var(--surface-alt) 25%, var(--border-canvas) 37%, var(--surface-alt) 63%);
  background-size: 400% 100%;
  animation: kv-skeleton-pulse 1.4s ease infinite;
  border-radius: var(--radius-sm);
}
@keyframes kv-skeleton-pulse {
  0% { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}
@media (prefers-reduced-motion: reduce) {
  .skeleton { animation: none; }
}

/* ---------- Contained dark stage (KVCoders 3.0) ---------- */
/* A rounded, elevated --ink-950 panel meant to sit INSIDE a light
   section -- a "window into the real product" (a live code console, the
   Learn/Practice/Test/Analyse pipeline), not a full section-background
   swap. This is the one sanctioned way dark appears outside chrome:
   contained, elevated, and always because something genuinely technical
   (code, live data) is being shown -- never as a decorative section
   alternation. Text inside uses --slate-400 for muted content (verified
   7.51:1 against --ink-950 in Phase 1) since --text-canvas-muted is
   calibrated for light backgrounds only. */
.stage-dark {
  background: var(--ink-950);
  color: #fff;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  position: relative;
}
.stage-dark .stage-muted { color: var(--slate-400); }
.stage-dark .stage-border { border-color: rgba(255,255,255,0.09); }

/* ---------- Pipeline diagram (KVCoders 3.0) ---------- */
/* The Learn -> Practice -> Test -> Analyse loop, rendered as connected
   nodes -- built once, used at two information densities: .pipeline
   (compact, icon + label, for a dark stage's header/aside) and
   .pipeline-detailed (icon + title + description, one cell per stage,
   for a dedicated section). Both consume the same node data/order;
   kept as two recipes rather than one collapsing-component because the
   detailed version carries real explanatory copy the compact one has
   no room for -- not a duplicate, a deliberate density variant. */
.pipeline { display: flex; align-items: center; }
.pipeline-node { flex: 1; text-align: center; }
.pipeline-node .node-icon {
  width: 34px; height: 34px; margin: 0 auto var(--space-2);
  border-radius: var(--radius-sm);
  border: 1px solid rgba(255,255,255,0.14);
  background: var(--ink-900);
  display: grid; place-items: center;
  color: var(--slate-400);
}
.pipeline-node.active .node-icon { border-color: var(--brand-600); color: #9B90FF; }
.pipeline-node .node-label { font-family: var(--font-mono); font-size: 9px; color: var(--slate-400); letter-spacing: 0.03em; }
.pipeline-connector { flex: 0 0 auto; width: 26px; height: 1px; background: rgba(255,255,255,0.14); margin-top: -17px; }

.pipeline-detailed {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.pipeline-detailed .stage-cell { background: var(--ink-900); padding: var(--space-6) var(--space-4); }
.pipeline-detailed .stage-num { font-family: var(--font-mono); font-size: 10px; color: var(--slate-400); margin-bottom: var(--space-3); }
.pipeline-detailed .stage-icon {
  width: 34px; height: 34px; border-radius: var(--radius-sm);
  background: var(--ink-800); border: 1px solid rgba(255,255,255,0.12);
  display: grid; place-items: center; margin-bottom: var(--space-4); color: #9B90FF;
}
.pipeline-detailed .stage-title { font-family: var(--font-display); font-weight: 700; font-size: var(--text-lg); color: #fff; margin-bottom: var(--space-2); }
.pipeline-detailed .stage-desc { font-size: var(--text-sm); color: var(--slate-400); line-height: 1.55; }
@media (max-width: 767px) {
  .pipeline-detailed { grid-template-columns: 1fr 1fr; }
}
