/* janqua.css — Janqua Console brand stylesheet
   Colours and typography from brand guidelines v1.1
   ---------------------------------------------------------------- */

@import url('https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,600;1,9..40,400&family=DM+Mono:wght@400;500&display=swap');

/* ── CSS Variables ──────────────────────────────────────────────── */
:root {
  /* Brand colours */
  --blue-deep:    #3A4797;
  --blue-soft:    #5A6F98;
  --blue-light:   #5A6F98;
  --slate-deep:   #2T7464;   /* Deep Slate from brand */
  --slate:        #3A5F6F;
  --grey-muted:   #887488;
  --grey-light:   #A5B6BE;
  --grey-pale:    #EEF1F5;
  --white:        #FFFFFF;

  /* Gradient — the macron arc: blue → green */
  --grad-start:   #3A6BC4;
  --grad-end:     #7EC86A;
  --gradient:     linear-gradient(90deg, var(--grad-start), var(--grad-end));

  /* Portal accent — overridden per portal below; used by the wordmark +
     macron bar so each portal (Coaching/Teaching/School/Console) reads
     distinct at a glance while sharing one layout. */
  --portal-accent: var(--blue-deep);

  /* Semantic */
  --bg:           #F5F7FA;
  --surface:      #FFFFFF;
  --surface2:     #EEF1F5;
  --border:       #DDE3EC;
  --text:         #1A2340;
  --text-muted:   #5A6880;
  --text-dim:     #8A96A8;

  /* Status */
  --status-queued:   #A5B6BE;
  --status-running:  #3A6BC4;
  --status-complete: #4CAF7D;
  --status-failed:   #E05252;

  /* Layout */
  --sidebar-w:    240px;
  --radius:       8px;
  --radius-lg:    12px;
  --shadow:       0 1px 3px rgba(26,35,64,.08), 0 4px 12px rgba(26,35,64,.06);
  --shadow-lg:    0 4px 16px rgba(26,35,64,.12), 0 12px 32px rgba(26,35,64,.08);

  /* Typography */
  --font:         'DM Sans', system-ui, sans-serif;
  --font-mono:    'DM Mono', 'Fira Code', monospace;
}

/* ── Reset & Base ───────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html { font-size: 15px; -webkit-font-smoothing: antialiased; }

body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  line-height: 1.6;
  min-height: 100vh;
  display: flex;
  /* The page must NEVER scroll horizontally: any element wider than the viewport
     (a fixed-width sparkline, a long unbroken string) would otherwise give the
     whole page a horizontal scroll, and the position:fixed bottom tab bar then
     appears to "slide off" as the page shifts sideways. Clip it at the root. */
  overflow-x: hidden;
}

a { color: var(--blue-deep); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ── Layout ─────────────────────────────────────────────────────── */
.sidebar {
  width: var(--sidebar-w);
  background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0; left: 0; bottom: 0;
  z-index: 100;
  transition: transform .2s ease;
}

/* Mobile drawer toggle (hamburger) — hidden on desktop, shown in the topbar
   at narrow widths so the off-canvas sidebar can be opened. Both auth realms
   share this; the learner realm's only nav lives in the sidebar. */
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 40px; height: 40px;
  margin-right: .25rem;
  border: none;
  border-radius: var(--radius);
  background: var(--gradient);
  color: #fff;
  box-shadow: var(--shadow);
  cursor: pointer;
  flex-shrink: 0;
  transition: opacity .15s;
}
.nav-toggle:hover { opacity: .9; }

/* Learner home control — the top-right twin of the top-left hamburger. Same
   brand-gradient icon box, same mobile-only visibility (desktop uses sidebar). */
.topbar-home {
  display: none;
  align-items: center;
  justify-content: center;
  width: 40px; height: 40px;
  margin-left: .25rem;
  border: none;
  border-radius: var(--radius);
  background: var(--gradient);
  color: #fff;
  box-shadow: var(--shadow);
  cursor: pointer;
  flex-shrink: 0;
  text-decoration: none;
  transition: opacity .15s;
}
.topbar-home:hover { opacity: .9; text-decoration: none; }

/* Learner bottom tab bar — the primary nav on mobile (the app-feel upgrade).
   Hidden by default; shown ≤900px for the learner realm only (see media query). */
.tabbar { display: none; }
.tab {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; padding: .5rem 0 .55rem; text-decoration: none;
  color: var(--text-dim); font-size: .64rem; font-weight: 600; letter-spacing: .01em;
}
.tab svg { width: 22px; height: 22px; }
.tab.active { color: var(--blue-deep); }
.tab:hover { text-decoration: none; color: var(--blue-deep); }

.sidebar-backdrop {
  position: fixed;
  inset: 0;
  z-index: 99;
  background: rgba(15,17,21,.45);
}
.sidebar-backdrop[hidden] { display: none; }

/* Admin console = desktop-only. Hidden by default; on narrow screens it covers
   the console with a notice. Only rendered for the staff realm (see base.html),
   so learner pages are never gated and stay fully mobile. */
.desktop-only-gate { display: none; }

.main {
  margin-left: var(--sidebar-w);
  flex: 1;
  /* min-width:0 lets this flex item shrink below its content's intrinsic
     width, so wide tables scroll inside their own .table-wrap instead of
     blowing the whole page out horizontally on narrow screens. */
  min-width: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.topbar {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  padding: 0 2rem;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: sticky;
  top: 0;
  z-index: 50;
}

.page-content {
  padding: 2rem;
  flex: 1;
}

/* ── Sidebar brand ──────────────────────────────────────────────── */
.sidebar-brand {
  padding: 1.5rem 1.25rem 1rem;
  border-bottom: 1px solid var(--border);
}

.sidebar-logo {
  display: flex;
  align-items: center;
  gap: .6rem;
}

.sidebar-logo img {
  height: 28px;
  width: auto;
}

.sidebar-logo-text {
  font-size: 1.2rem;
  font-weight: 600;
  color: var(--blue-deep);
  letter-spacing: -.02em;
}

/* Gradient macron accent bar */
.macron-bar {
  height: 3px;
  width: 48px;
  background: var(--gradient);
  border-radius: 2px;
  margin-top: .4rem;
}

/* ── Per-portal theming ─────────────────────────────────────────────
   base.html stamps <body data-portal="learner|teacher|org_admin|staff">.
   Each portal gets its own accent + a solid macron bar in that accent, so
   which tool you're in is legible before you read a word. The learner
   portal keeps the full brand gradient (it IS the product). */
body[data-portal="learner"]   { --portal-accent: var(--blue-deep); }
body[data-portal="teacher"]   { --portal-accent: #3F7D5A; }   /* teaching green */
body[data-portal="org_admin"] { --portal-accent: #8A5A2B; }   /* school ochre  */
body[data-portal="staff"]     { --portal-accent: #6B7280; }   /* console grey  */

body[data-portal="teacher"]   .macron-bar,
body[data-portal="org_admin"] .macron-bar,
body[data-portal="staff"]     .macron-bar { background: var(--portal-accent); }

.portal-mark { font-weight: 600; }
body .portal-mark { color: var(--portal-accent) !important; }
body[data-portal="teacher"]   .nav-section,
body[data-portal="org_admin"] .nav-section { color: var(--portal-accent); }

/* Brand-gradient text — the macron arc (blue → green) painted along the
   wording itself. fit-content sizes the gradient to the TEXT, not the card,
   so short headings still end on green. Falls back to solid brand blue where
   background-clip:text is unsupported. */
.title-grad {
  color: var(--blue-deep);
  width: fit-content;
  background: var(--gradient);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* ── Sidebar nav ────────────────────────────────────────────────── */
.sidebar-nav {
  flex: 1;
  padding: 1rem 0;
  overflow-y: auto;
}

.nav-section {
  padding: .25rem 1.25rem .1rem;
  font-size: .7rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-top: .75rem;
}

.nav-item {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .5rem 1.25rem;
  font-size: .875rem;
  color: var(--text-muted);
  border-radius: 0;
  transition: background .15s, color .15s;
  cursor: pointer;
}

.nav-item:hover {
  background: var(--grey-pale);
  color: var(--text);
  text-decoration: none;
}

.nav-item.active {
  background: linear-gradient(90deg, rgba(58,71,151,.08), transparent);
  color: var(--blue-deep);
  font-weight: 500;
  border-left: 3px solid var(--blue-deep);
  padding-left: calc(1.25rem - 3px);
}

.nav-icon {
  width: 16px;
  height: 16px;
  opacity: .7;
  flex-shrink: 0;
}

/* ── Cards ──────────────────────────────────────────────────────── */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  overflow: hidden;
}

.card-header {
  padding: 1.1rem 1.5rem;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.card-title {
  font-size: .875rem;
  font-weight: 600;
  color: var(--text);
  letter-spacing: -.01em;
}

.card-body {
  padding: 1.5rem;
}

/* ── Tables ─────────────────────────────────────────────────────── */
.table-wrap { overflow-x: auto; }

table {
  width: 100%;
  border-collapse: collapse;
  font-size: .875rem;
}

thead th {
  padding: .6rem 1rem;
  text-align: left;
  font-size: .7rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-dim);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

tbody tr {
  border-bottom: 1px solid var(--border);
  transition: background .1s;
}

tbody tr:last-child { border-bottom: none; }
tbody tr:hover { background: var(--grey-pale); }

tbody td {
  padding: .75rem 1rem;
  vertical-align: middle;
}

/* ── Status badges ──────────────────────────────────────────────── */
.badge {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  padding: .2rem .6rem;
  border-radius: 20px;
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .02em;
  white-space: nowrap;
}

.badge::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  opacity: .7;
}

.badge-queued   { background: #F0F2F5; color: var(--text-muted); }
.badge-running  { background: #EBF1FB; color: var(--blue-deep);
                  animation: pulse-running 1.5s ease-in-out infinite; }
.badge-complete { background: #EBF7EF; color: #2E7D52; }
.badge-failed   { background: #FDEAEA; color: #C0392B; }

@keyframes pulse-running {
  0%, 100% { opacity: 1; }
  50%       { opacity: .65; }
}

/* ── Buttons ────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .5rem 1.1rem;
  border-radius: var(--radius);
  font-family: var(--font);
  font-size: .875rem;
  font-weight: 500;
  cursor: pointer;
  border: 1px solid transparent;
  transition: all .15s;
  text-decoration: none;
  white-space: nowrap;
}

.btn-primary {
  background: var(--gradient);
  color: white;
  border-color: transparent;
}

.btn-primary:hover {
  opacity: .9;
  text-decoration: none;
  color: white;
}

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

.btn-secondary:hover {
  background: var(--grey-pale);
  text-decoration: none;
}

.btn-sm {
  padding: .3rem .75rem;
  font-size: .8rem;
}

/* ── Forms ──────────────────────────────────────────────────────── */
.form-group {
  margin-bottom: 1.25rem;
}

label {
  display: block;
  font-size: .8rem;
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: .4rem;
  letter-spacing: .02em;
}

input[type=text], input[type=url], select, textarea {
  width: 100%;
  padding: .55rem .85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-family: var(--font);
  font-size: .875rem;
  color: var(--text);
  background: var(--surface);
  transition: border-color .15s, box-shadow .15s;
  appearance: none;
}

input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--blue-soft);
  box-shadow: 0 0 0 3px rgba(58,71,151,.1);
}

textarea {
  resize: vertical;
  min-height: 100px;
  font-family: var(--font-mono);
  font-size: .8rem;
}

.form-hint {
  font-size: .75rem;
  color: var(--text-dim);
  margin-top: .3rem;
}

/* Speaker selector */
.speaker-radio {
  display: grid;
  gap: .5rem;
  max-height: 220px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: .5rem;
}

.speaker-option {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: .5rem .75rem;
  border-radius: 6px;
  cursor: pointer;
  transition: background .1s;
}

.speaker-option:hover { background: var(--grey-pale); }
.speaker-option input[type=radio] { width: auto; accent-color: var(--blue-deep); }

.speaker-option-name {
  font-size: .875rem;
  font-weight: 500;
}

.speaker-option-meta {
  font-size: .75rem;
  color: var(--text-dim);
}

/* ── Log viewer ─────────────────────────────────────────────────── */
.log-viewer {
  background: #0F1521;
  color: #C8D8E8;
  font-family: var(--font-mono);
  font-size: .78rem;
  line-height: 1.7;
  padding: 1.25rem;
  border-radius: var(--radius);
  min-height: 300px;
  max-height: 500px;
  overflow-y: auto;
  white-space: pre-wrap;
  word-break: break-all;
}

.log-viewer .log-stage   { color: #7EC86A; font-weight: 600; }
.log-viewer .log-warning { color: #F5C542; }
.log-viewer .log-error   { color: #E05252; }
.log-viewer .log-info    { color: #5B9BD5; }

/* ── Page header ────────────────────────────────────────────────── */
.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 1.75rem;
  gap: 1rem;
  flex-wrap: wrap;
}

.page-title {
  font-size: 1.4rem;
  font-weight: 600;
  letter-spacing: -.02em;
  color: var(--text);
}

.page-subtitle {
  font-size: .875rem;
  color: var(--text-muted);
  margin-top: .2rem;
}

/* ── Stats row ──────────────────────────────────────────────────── */
.stats-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 1rem;
  margin-bottom: 1.75rem;
}

.stat-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 1.1rem 1.25rem;
  box-shadow: var(--shadow);
}

.stat-label {
  font-size: .72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-dim);
  margin-bottom: .3rem;
}

.stat-value {
  font-size: 1.75rem;
  font-weight: 600;
  letter-spacing: -.03em;
  color: var(--text);
  line-height: 1;
}

.stat-accent {
  height: 3px;
  width: 32px;
  background: var(--gradient);
  border-radius: 2px;
  margin-top: .6rem;
}

/* ── Grid layout ────────────────────────────────────────────────── */
.grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.5rem;
}

@media (max-width: 900px) {
  .grid-2 { grid-template-columns: 1fr; }
  .sidebar { transform: translateX(-100%); box-shadow: var(--shadow-lg); }
  .sidebar.open { transform: translateX(0); }
  .main { margin-left: 0; }
  .nav-toggle { display: inline-flex; }
  .topbar-home { display: inline-flex; }
  .topbar { padding: 0 1rem; }
  .page-content { padding: 1rem; }

  /* Learner realm: show the bottom tab bar and let it carry primary nav. The
     top-right home icon is redundant (Home is a tab), so hide it; the hamburger
     stays as the account/sign-out menu. */
  body.learner-view .tabbar {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 200;
    background: var(--surface); border-top: 1px solid var(--border);
    box-shadow: 0 -2px 12px rgba(26,35,64,.06);
    padding-bottom: env(safe-area-inset-bottom, 0);
  }
  /* Keep the tappable top-right home ICON (house symbol) — learners reach for the
     top to go home, and the breadcrumb "Home" is only a label, not a link. The
     bottom bar's Home tab complements it; both navigate to /app. */
  /* The tab bar carries nav now, so the drawer's nav links are redundant on
     mobile — hide them, leaving the hamburger as a compact account / sign-out
     menu (brand + email + Sign out). Desktop keeps the full sidebar nav. */
  body.learner-view .sidebar-nav { display: none; }
  /* Clear the fixed bar so page content isn't hidden behind it. */
  body.learner-view .page-content { padding-bottom: calc(66px + env(safe-area-inset-bottom, 0)); }

  /* Staff/admin console: replace the desktop UI with a desktop-only notice. */
  .desktop-only-gate {
    display: flex;
    position: fixed;
    inset: 0;
    z-index: 2000;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
    background: var(--bg);
  }
  .desktop-only-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    padding: 2rem 1.75rem;
    max-width: 22rem;
    text-align: center;
  }
}

/* Display scaling (150–225% is common on high-DPI Windows/macOS laptops) makes
   a REAL desktop report ≤900 CSS px, which used to (a) hard-block the admin
   console behind the desktop-only gate and (b) force the learner's phone chrome.
   A precise primary pointer (mouse/trackpad) is the reliable "this is a desktop"
   signal independent of the reported width — so on any such device keep the full
   desktop layout and never show the gate. This block follows the max-width one,
   so it wins on a mouse device whose window also matches ≤900px. */
@media (pointer: fine) {
  .desktop-only-gate { display: none !important; }
  .sidebar { transform: none; box-shadow: none; }
  .main { margin-left: var(--sidebar-w); }
  .nav-toggle { display: none; }
  .topbar-home { display: none; }
  body.learner-view .tabbar { display: none; }
  body.learner-view .sidebar-nav { display: block; }
  body.learner-view .page-content { padding-bottom: 1rem; }
}

/* ── Speaker avatar ─────────────────────────────────────────────── */
.avatar {
  width: 36px; height: 36px;
  border-radius: 50%;
  background: var(--gradient);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-weight: 600;
  font-size: .875rem;
  flex-shrink: 0;
}

/* ── Learner desktop top-bar account controls (Settings gear + avatar menu) ──
   Desktop-only: hidden by default, shown on a fine pointer (mirrors how the
   desktop sidebar layout is gated). The mobile .topbar-home icons are the
   inverse (shown ≤900px, hidden on fine pointer). */
/* Avatar account menu shows on every size (it carries Settings + Sign out, so
   sign-out is reachable in one tap on mobile too). */
.topbar-account { display: flex; align-items: center; gap: .5rem; position: relative; }

/* The standalone gear is desktop-only; on mobile the avatar menu covers Settings. */
.topbar-icon-btn {
  display: none; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: var(--radius);
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text-dim); text-decoration: none; cursor: pointer;
  transition: border-color .15s, color .15s;
}
.topbar-icon-btn:hover { border-color: var(--blue-soft); color: var(--blue-deep); text-decoration: none; }
@media (pointer: fine) { .topbar-icon-btn { display: inline-flex; } }

.avatar-menu { position: relative; }
.topbar-avatar {
  width: 38px; height: 38px; border-radius: 50%; border: none; cursor: pointer;
  background: var(--gradient); color: #fff; font-weight: 700; font-size: .95rem;
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: var(--shadow);
}
.avatar-dropdown {
  position: absolute; right: 0; top: calc(100% + 8px); min-width: 210px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
  padding: .35rem; z-index: 300;
}
.avatar-dropdown[hidden] { display: none; }
.avatar-dd-head { padding: .5rem .6rem; border-bottom: 1px solid var(--border); margin-bottom: .3rem; }
.avatar-dd-name { font-weight: 600; font-size: .9rem; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.avatar-dd-email { font-size: .78rem; color: var(--text-dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.avatar-dd-item {
  display: block; padding: .5rem .6rem; border-radius: calc(var(--radius) - 2px);
  font-size: .9rem; color: var(--text); text-decoration: none;
}
.avatar-dd-item:hover { background: var(--grey-pale); text-decoration: none; }

/* ── Misc ───────────────────────────────────────────────────────── */
.text-muted  { color: var(--text-muted); }
.text-dim    { color: var(--text-dim); }
.text-small  { font-size: .8rem; }
.mono        { font-family: var(--font-mono); font-size: .8rem; font-variant-ligatures: none; }
.mt-1  { margin-top: .5rem; }
.mt-2  { margin-top: 1rem; }
.mt-3  { margin-top: 1.5rem; }
.mb-1  { margin-bottom: .5rem; }
.mb-2  { margin-bottom: 1rem; }
.flex  { display: flex; }
.items-center { align-items: center; }
.gap-1 { gap: .5rem; }
.gap-2 { gap: 1rem; }

.empty-state {
  text-align: center;
  padding: 3rem 1rem;
  color: var(--text-dim);
}

.empty-state-icon {
  font-size: 2.5rem;
  margin-bottom: .75rem;
  opacity: .4;
}

.divider {
  height: 1px;
  background: var(--border);
  margin: 1.5rem 0;
}
