/*
 * Onlenco shared component layer.
 *
 * Phase 3 of the UI unification. Loads AFTER onlenco-tokens.css and
 * BEFORE onlenco.css / app-level CSS, so every component here reads
 * from --primary, --space-3, --radius-md, etc. and stays consistent
 * across Student / Admin / Teacher / AI Tutor surfaces.
 *
 * RULES
 *   - All values reference design tokens. No magic numbers.
 *   - Naming uses class.modifier (.btn.btn-primary, .alert.alert-danger).
 *   - This file is ADDITIVE: it never redefines a class that already
 *     exists in onlenco.css. New variants only.
 *
 * Components shipped in Phase 3:
 *   .btn-primary / .btn-secondary / .btn-danger / .btn-sm
 *   .input-base / .select-base / .textarea-base   (renamed to avoid
 *      collision with the legacy .input class; Phase 4+ migrates
 *      forms to use these.)
 *   .table-base / .table-striped / .table-sortable
 *   .badge-success / .badge-warning / .badge-danger / .badge-info /
 *     .badge-neutral
 *   .alert / .alert-success / .alert-warning / .alert-danger /
 *     .alert-info
 *   .skeleton / .skeleton-text / .skeleton-circle
 *   .spinner
 *   .modal / .modal-backdrop / .modal-dialog / .modal-header /
 *     .modal-body / .modal-footer
 *   .pagination-base
 *   .empty-state
 */


/* ============================================================
 *  Buttons — semantic variants
 *
 *  Onlenco.css already defines .btn, .btn-hero, .btn-outline,
 *  .btn-ghost, .btn-glass, .btn-lg. We add .btn-primary (solid teal),
 *  .btn-secondary (solid amber), .btn-danger (solid red), and a
 *  .btn-sm size. These can stack: <button class="btn btn-primary btn-sm">.
 * ============================================================ */

.btn-primary {
  background: hsl(var(--primary));
  color: hsl(var(--primary-foreground));
  border-color: hsl(var(--primary));
  box-shadow: var(--shadow-sm);
}
.btn-primary:hover {
  background: hsl(var(--brand-teal-700));
  border-color: hsl(var(--brand-teal-700));
  box-shadow: var(--shadow-md);
}
.btn-primary:active {
  background: hsl(var(--brand-teal-800));
  transform: translateY(1px);
  box-shadow: var(--shadow-xs);
}

.btn-secondary {
  background: hsl(var(--secondary));
  color: hsl(var(--secondary-foreground));
  border-color: hsl(var(--secondary));
  box-shadow: var(--shadow-sm);
}
.btn-secondary:hover {
  background: hsl(var(--brand-amber-600));
  border-color: hsl(var(--brand-amber-600));
  box-shadow: var(--shadow-md);
}

.btn-danger {
  background: hsl(var(--destructive));
  color: hsl(var(--destructive-foreground));
  border-color: hsl(var(--destructive));
  box-shadow: var(--shadow-sm);
}
.btn-danger:hover {
  background: hsl(0 75% 42%);
  border-color: hsl(0 75% 42%);
}

.btn-sm {
  height: 2.25rem;
  padding: 0 var(--space-3);
  font-size: var(--text-sm);
  border-radius: var(--radius-sm);
}

/* Accessibility — visible focus ring across all buttons. */
.btn:focus-visible,
.btn-primary:focus-visible,
.btn-secondary:focus-visible,
.btn-danger:focus-visible {
  outline: 2px solid hsl(var(--ring) / 0.6);
  outline-offset: 2px;
}


/* ============================================================
 *  Form fields
 *  *-base suffix avoids stomping on the legacy .input class which
 *  already exists in onlenco.css. New forms should use the base
 *  variants; Phase 4 migrates inline-styled inputs onto them.
 * ============================================================ */

.input-base,
.select-base,
.textarea-base {
  width: 100%;
  border: 1px solid hsl(var(--border));
  background: hsl(var(--card));
  color: hsl(var(--foreground));
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
  font-family: inherit;
  line-height: var(--leading-normal);
  transition:
    border-color var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-fast) var(--ease-out);
}

.input-base:focus,
.select-base:focus,
.textarea-base:focus {
  outline: none;
  border-color: hsl(var(--ring));
  box-shadow: 0 0 0 3px hsl(var(--ring) / 0.15);
}

.input-base:disabled,
.select-base:disabled,
.textarea-base:disabled {
  background: hsl(var(--muted));
  color: hsl(var(--muted-foreground));
  cursor: not-allowed;
}

.input-base[aria-invalid="true"],
.select-base[aria-invalid="true"],
.textarea-base[aria-invalid="true"] {
  border-color: hsl(var(--destructive));
}

.label-base {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: hsl(var(--foreground));
  margin-bottom: var(--space-1);
}

.help-text {
  font-size: var(--text-xs);
  color: hsl(var(--muted-foreground));
  margin-top: var(--space-1);
}

.error-text {
  font-size: var(--text-xs);
  color: hsl(var(--destructive));
  margin-top: var(--space-1);
}


/* ============================================================
 *  Tables
 *  Generic table base — admin/teacher CSS will collapse onto this
 *  in Phases 7-8.
 * ============================================================ */

.table-base {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  color: hsl(var(--foreground));
  background: hsl(var(--card));
}

.table-base th,
.table-base td {
  padding: var(--space-3) var(--space-3);
  border-bottom: 1px solid hsl(var(--border));
  text-align: start;          /* logical = LTR/RTL aware */
  vertical-align: middle;
}

.table-base th {
  font-size: var(--text-xs);
  font-weight: var(--font-semibold);
  color: hsl(var(--muted-foreground));
  background: hsl(var(--muted) / 0.4);
  letter-spacing: 0;
}

.table-base tr:hover td {
  background: hsl(var(--muted) / 0.25);
}

.table-striped tbody tr:nth-child(2n) td {
  background: hsl(var(--muted) / 0.15);
}

/* Sortable column header anchor used in click-to-sort tables. */
.table-sortable .th-sort {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  user-select: none;
}
.table-sortable .th-sort:hover { color: hsl(var(--foreground)); }
.table-sortable .th-sort.sort-active {
  color: hsl(var(--foreground));
  font-weight: var(--font-bold);
}


/* ============================================================
 *  Badges — additional variants on top of legacy
 *  .badge / .badge-secondary / .badge-outline / .badge-popular
 * ============================================================ */

.badge-success {
  background: hsl(var(--status-success-100));
  color: hsl(var(--status-success-500));
  border-color: hsl(var(--status-success-500) / 0.3);
}
.badge-warning {
  background: hsl(var(--status-warning-100));
  color: hsl(var(--status-warning-500));
  border-color: hsl(var(--status-warning-500) / 0.3);
}
.badge-danger {
  background: hsl(var(--status-danger-100));
  color: hsl(var(--status-danger-500));
  border-color: hsl(var(--status-danger-500) / 0.3);
}
.badge-info {
  background: hsl(var(--status-info-100));
  color: hsl(var(--status-info-500));
  border-color: hsl(var(--status-info-500) / 0.3);
}
.badge-neutral {
  background: hsl(var(--muted));
  color: hsl(var(--muted-foreground));
  border-color: hsl(var(--border));
}

/* Map admin/teacher legacy colour names to the new system so the
   existing templates don't need to change yet. Removes ~80 lines
   of duplicate definitions from control.css / teacher.css when
   Phase 7-8 prune. */
.badge-green,
.status-pill.status-published,
.status-pill.status-approved {
  background: hsl(var(--status-success-100));
  color: hsl(var(--status-success-500));
}
.badge-yellow,
.status-pill.status-pending_review,
.status-pill.status-pending,
.status-pill.status-draft {
  background: hsl(var(--status-warning-100));
  color: hsl(var(--status-warning-500));
}
.badge-red,
.status-pill.status-rejected,
.status-pill.status-archived {
  background: hsl(var(--status-danger-100));
  color: hsl(var(--status-danger-500));
}
.badge-blue {
  background: hsl(var(--status-info-100));
  color: hsl(var(--status-info-500));
}


/* ============================================================
 *  Alerts (inline message boxes)
 *  Different from .toast (transient banner). Use .alert for static
 *  messages inside forms / page bodies.
 * ============================================================ */

.alert {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  border-inline-start: 4px solid transparent;
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
}
.alert-success {
  background: hsl(var(--status-success-100));
  color: hsl(var(--status-success-500));
  border-inline-start-color: hsl(var(--status-success-500));
}
.alert-warning {
  background: hsl(var(--status-warning-100));
  color: hsl(var(--status-warning-500));
  border-inline-start-color: hsl(var(--status-warning-500));
}
.alert-danger {
  background: hsl(var(--status-danger-100));
  color: hsl(var(--status-danger-500));
  border-inline-start-color: hsl(var(--status-danger-500));
}
.alert-info {
  background: hsl(var(--status-info-100));
  color: hsl(var(--status-info-500));
  border-inline-start-color: hsl(var(--status-info-500));
}


/* ============================================================
 *  Skeleton & spinner — loading states
 * ============================================================ */

.skeleton {
  background: linear-gradient(
    90deg,
    hsl(var(--muted)) 0%,
    hsl(var(--muted) / 0.5) 50%,
    hsl(var(--muted)) 100%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.4s linear infinite;
  border-radius: var(--radius-sm);
}
@keyframes skeleton-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.skeleton-text   { height: 14px; width: 80%; margin: var(--space-1) 0; }
.skeleton-title  { height: 22px; width: 60%; margin: var(--space-2) 0; }
.skeleton-circle { border-radius: var(--radius-full); width: 40px; height: 40px; }
.skeleton-card   { height: 96px; border-radius: var(--radius-md); }

.spinner {
  width: 1.25rem;
  height: 1.25rem;
  border: 2px solid hsl(var(--muted));
  border-top-color: hsl(var(--primary));
  border-radius: var(--radius-full);
  animation: spinner-rotate 0.8s linear infinite;
  display: inline-block;
}
.spinner-sm { width: 1rem; height: 1rem; border-width: 1.5px; }
.spinner-lg { width: 2.5rem; height: 2.5rem; border-width: 3px; }
@keyframes spinner-rotate { to { transform: rotate(360deg); } }


/* ============================================================
 *  Modal / dialog
 *  Minimal — Phase 6+ will add the trigger pattern (data attrs +
 *  vanilla JS) when daily-learning needs it.
 * ============================================================ */

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: hsl(var(--warm-900) / 0.55);
  z-index: var(--z-modal);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
}
.modal-dialog {
  background: hsl(var(--card));
  color: hsl(var(--foreground));
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
  max-width: 32rem;
  width: 100%;
  max-height: 90vh;
  overflow: auto;
  animation: modal-pop var(--duration-base) var(--ease-out);
}
@keyframes modal-pop {
  from { transform: scale(0.96); opacity: 0; }
  to   { transform: scale(1);    opacity: 1; }
}
.modal-header {
  padding: var(--space-5) var(--space-6);
  border-bottom: 1px solid hsl(var(--border));
  font-weight: var(--font-semibold);
  font-size: var(--text-lg);
}
.modal-body   { padding: var(--space-5) var(--space-6); }
.modal-footer {
  padding: var(--space-4) var(--space-6);
  border-top: 1px solid hsl(var(--border));
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
}


/* ============================================================
 *  Pagination (generic)
 * ============================================================ */

.pagination-base {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  margin: var(--space-6) 0;
}
.pagination-base a,
.pagination-base span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2rem;
  height: 2rem;
  padding: 0 var(--space-2);
  border: 1px solid hsl(var(--border));
  border-radius: var(--radius-sm);
  background: hsl(var(--card));
  color: hsl(var(--foreground));
  font-size: var(--text-sm);
  text-decoration: none;
}
.pagination-base a:hover {
  background: hsl(var(--muted));
  border-color: hsl(var(--ring));
}
.pagination-base .is-current {
  background: hsl(var(--primary));
  color: hsl(var(--primary-foreground));
  border-color: hsl(var(--primary));
}


/* ============================================================
 *  Empty state — used when a list/table has no rows
 * ============================================================ */

.empty-state {
  text-align: center;
  padding: var(--space-12) var(--space-6);
  color: hsl(var(--muted-foreground));
}
.empty-state .empty-icon {
  width: 64px;
  height: 64px;
  margin: 0 auto var(--space-4);
  color: hsl(var(--muted-foreground));
  opacity: 0.5;
}
.empty-state h3 {
  font-size: var(--text-lg);
  font-weight: var(--font-semibold);
  color: hsl(var(--foreground));
  margin: 0 0 var(--space-2);
}
.empty-state p {
  font-size: var(--text-sm);
  margin: 0 auto;
  max-width: 36ch;
}


/* ============================================================
 *  Card variants — onlenco.css already has .card, .card.gradient-hero,
 *  .card.gradient-sunset. Add a few small modifiers.
 * ============================================================ */

.card-bordered { border: 1px solid hsl(var(--border)); }
.card-hover {
  transition:
    transform var(--duration-base) var(--ease-out),
    box-shadow var(--duration-base) var(--ease-out);
}
.card-hover:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
}
.card-flat   { box-shadow: none; }
.card-compact { padding: var(--space-3); }


/* ============================================================
 *  Status dots — small coloured circles next to labels.
 *  Used in difficulty legends, online/offline indicators, etc.
 * ============================================================ */

.dot-easy   { background: hsl(var(--status-success-500)); }
.dot-medium { background: hsl(var(--status-warning-500)); }
.dot-hard   { background: hsl(var(--status-danger-500)); }
.dot-online { background: hsl(var(--status-success-500)); }
.dot-offline { background: hsl(var(--warm-500)); }


/* ============================================================
 *  Status pills — labelled badges with success/warning/danger
 *  semantics used inline-with-text (profile fields, "Verified",
 *  "Pending", "Rejected", "Approved" markers).
 *
 *  Different from .badge-* (which has a bordered, sometimes
 *  uppercase look). These are softer fills, often inline with
 *  body copy, no border.
 * ============================================================ */

.pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 2px var(--space-2);
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: var(--font-medium);
  line-height: 1.4;
}
.pill-success {
  background: hsl(var(--status-success-100));
  color: hsl(var(--status-success-500));
}
.pill-warning {
  background: hsl(var(--status-warning-100));
  color: hsl(var(--status-warning-500));
}
.pill-danger {
  background: hsl(var(--status-danger-100));
  color: hsl(var(--status-danger-500));
}
.pill-info {
  background: hsl(var(--status-info-100));
  color: hsl(var(--status-info-500));
}
.pill-neutral {
  background: hsl(var(--muted));
  color: hsl(var(--muted-foreground));
}


/* ============================================================
 *  Skip-to-content link — visible only when focused via keyboard.
 *  Lives just inside <body> and lets sighted-keyboard / screen
 *  reader users bypass the header nav on every page (WCAG SC 2.4.1).
 * ============================================================ */

.skip-to-content {
  position: absolute;
  inset-inline-start: var(--space-3);
  top: var(--space-3);
  z-index: var(--z-tooltip);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  background: hsl(var(--primary));
  color: hsl(var(--primary-foreground));
  font-weight: var(--font-semibold);
  font-size: var(--text-sm);
  text-decoration: none;
  box-shadow: var(--shadow-lg);
  transform: translateY(-200%);
  transition: transform var(--duration-fast) var(--ease-out);
}
.skip-to-content:focus,
.skip-to-content:focus-visible {
  transform: translateY(0);
  outline: none;
}

/* The skip-target wrapper needs a focusable :target style so screen
   readers + keyboard users see they've landed. Subtle outline, no
   layout shift. */
#main-content:focus,
#main-content:focus-visible {
  outline: 2px solid hsl(var(--ring) / 0.4);
  outline-offset: -2px;
}


/* ============================================================
 *  Universal focus polish — any element receiving keyboard focus
 *  should be visually obvious. Tailwind's default focus ring
 *  doesn't cover non-utility elements (legacy classes, raw HTML).
 * ============================================================ */

:focus-visible {
  outline: 2px solid hsl(var(--ring) / 0.6);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Inputs already have their own focus ring via .input-base. Don't
   double up. */
.input-base:focus-visible,
.select-base:focus-visible,
.textarea-base:focus-visible {
  outline: none;
}


/* ============================================================
 *  Utility: visually hidden (a11y) — for skip links, sr-only labels.
 *  Tailwind already exposes .sr-only; this is for non-Tailwind pages.
 * ============================================================ */

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0,0,0,0);
  white-space: nowrap;
  border: 0;
}


/* ============================================================
 *  Touch targets — minimum 44px on touch devices (WCAG SC 2.5.5).
 *  Phase 10 (mobile/a11y pass) will audit further.
 * ============================================================ */

@media (pointer: coarse) {
  .btn, .btn-sm,
  .pagination-base a, .pagination-base span,
  .input-base, .select-base, .textarea-base {
    min-height: 44px;
  }
}


/* ============================================================
 *  Reduced motion — global safety net.
 *  When the user has prefers-reduced-motion enabled, we kill any
 *  animation or scroll-smoothing that isn't essential to feedback.
 *  Per-component overrides already exist in this file (skeleton,
 *  spinner, modal) and in daily_journey.css; this is the safety
 *  net for anything we missed.
 * ============================================================ */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  /* Carve-outs for animations whose duration carries information
     (loading spinners, audio-driven mouth/orb) — leave them slow
     instead of zero. */
  .spinner { animation-duration: 2s !important; }
  .skeleton { background: hsl(var(--muted)) !important; animation: none !important; }
  .modal-dialog { animation: none !important; }
}
