/* ==========================================================================
   English is Fun Indonesia — design system
   Tokens → base → components → layouts → responsive
   One stylesheet for the whole platform so every area stays consistent.
   ========================================================================== */

:root {
  --indigo: #4f46e5;
  --indigo-dark: #4038c9;
  --violet: #8b5cf6;
  --violet-soft: #ede9fe;
  --sky: #38bdf8;
  --pink: #f472b6;

  --ink: #1f1b3a;
  --ink-soft: #2e2a52;
  --muted: #635f82;
  --muted-2: #8a86a8;

  --bg: #f3f0ff;
  --surface: rgba(255, 255, 255, 0.66);
  --surface-strong: rgba(255, 255, 255, 0.86);
  --surface-solid: #ffffff;
  --line: rgba(31, 27, 58, 0.10);
  --line-soft: rgba(31, 27, 58, 0.06);

  --success: #0f9d63;
  --success-soft: #e3f8ee;
  --warning: #b45309;
  --warning-soft: #fdf1dc;
  --danger: #d64545;
  --danger-soft: #fdeaea;

  --radius-sm: 10px;
  --radius: 14px;
  --radius-lg: 18px;
  --radius-xl: 24px;

  --shadow-sm: 0 2px 8px rgba(31, 27, 58, 0.06);
  --shadow: 0 12px 32px rgba(31, 27, 58, 0.09);
  --shadow-lg: 0 24px 60px rgba(31, 27, 58, 0.13);

  --sidebar-w: 262px;
  --topbar-h: 66px;

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 44px;

  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  min-height: 100vh;
  font-family: var(--font);
  font-size: 15.5px;
  line-height: 1.62;
  color: var(--ink);
  background-color: var(--bg);
  background-image:
    radial-gradient(58rem 40rem at 8% -8%, rgba(99, 102, 241, 0.30), transparent 62%),
    radial-gradient(48rem 34rem at 98% 4%, rgba(244, 114, 182, 0.24), transparent 60%),
    radial-gradient(52rem 40rem at 72% 100%, rgba(139, 92, 246, 0.26), transparent 62%),
    radial-gradient(40rem 30rem at 12% 96%, rgba(56, 189, 248, 0.20), transparent 60%);
  background-attachment: fixed;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0 0 var(--space-3); line-height: 1.25; color: var(--ink); font-weight: 700; letter-spacing: -0.015em; }
h1 { font-size: clamp(1.75rem, 1.15rem + 2.1vw, 2.6rem); }
h2 { font-size: clamp(1.35rem, 1.05rem + 1.1vw, 1.85rem); }
h3 { font-size: 1.14rem; }
h4 { font-size: 1rem; }
p  { margin: 0 0 var(--space-4); }
a  { color: var(--indigo); text-decoration: none; }
a:hover { text-decoration: underline; }
img { max-width: 100%; display: block; }
svg.icon { flex: 0 0 auto; }

.muted     { color: var(--muted); }
.small     { font-size: 0.86rem; }
.mono      { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.85rem; }
.text-center { text-align: center; }
.nowrap    { white-space: nowrap; }

/* ------------------------------------------------------------------ layout */

.container { width: min(1180px, 100% - 40px); margin-inline: auto; }
.container-narrow { width: min(560px, 100% - 40px); margin-inline: auto; }

.section       { padding-block: var(--space-8); }
.section-sm    { padding-block: var(--space-7); }
.stack         { display: flex; flex-direction: column; gap: var(--space-5); }
.stack-sm      { display: flex; flex-direction: column; gap: var(--space-3); }
.row           { display: flex; gap: var(--space-3); flex-wrap: wrap; align-items: center; }
.row-between   { display: flex; gap: var(--space-4); flex-wrap: wrap; align-items: center; justify-content: space-between; }
.spacer        { flex: 1 1 auto; }

.grid { display: grid; gap: var(--space-5); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid-auto { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.grid-auto-lg { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }

/* ------------------------------------------------------------------ cards */

.card,
.glass-card {
  background: var(--surface);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.65);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: var(--space-6);
}

.card-solid { background: var(--surface-solid); }
.card-flush { padding: 0; overflow: hidden; }
.card-header {
  display: flex; flex-wrap: wrap; gap: var(--space-3);
  align-items: center; justify-content: space-between;
  padding: var(--space-5) var(--space-6);
  border-bottom: 1px solid var(--line-soft);
}
.card-header h3 { margin: 0; }
.card-body { padding: var(--space-6); }
.card-footer {
  padding: var(--space-4) var(--space-6);
  border-top: 1px solid var(--line-soft);
  background: rgba(255, 255, 255, 0.35);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}

.stat-card { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-5) var(--space-6); }
.stat-label { font-size: 0.8rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.stat-value { font-size: 2rem; font-weight: 700; line-height: 1.1; color: var(--ink); }
.stat-hint  { font-size: 0.85rem; color: var(--muted); }

.tile-link {
  display: flex; gap: var(--space-4); align-items: flex-start;
  color: inherit; text-decoration: none;
  transition: transform 0.16s ease, box-shadow 0.16s ease;
}
.tile-link:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); text-decoration: none; }
/* A stat card that is ALSO a link carries `tile-link` for the clickable affordance, but that class
   sets a wider gap for the module tiles. This keeps the stat-card metrics identical to every other
   stat card (so a clickable one cannot stretch its neighbours in the same grid row). */
.stat-card.tile-link { gap: var(--space-2); align-items: stretch; }
.tile-icon {
  display: grid; place-items: center;
  width: 42px; height: 42px; flex: 0 0 42px;
  border-radius: 12px;
  background: linear-gradient(135deg, var(--indigo), var(--violet));
  color: #fff;
  box-shadow: 0 8px 20px rgba(79, 70, 229, 0.28);
}
.tile-icon.is-muted { background: rgba(31, 27, 58, 0.08); color: var(--muted); box-shadow: none; }
.tile-body { min-width: 0; }
.tile-title { font-weight: 650; margin-bottom: 2px; }
.tile-desc { font-size: 0.87rem; color: var(--muted); margin: 0; }

/* ---------------------------------------------------------------- buttons */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 18px;
  border-radius: 12px;
  border: 1px solid transparent;
  font: inherit; font-weight: 600; font-size: 0.92rem;
  cursor: pointer;
  background: rgba(255, 255, 255, 0.7);
  color: var(--ink);
  transition: transform 0.14s ease, background 0.14s ease, box-shadow 0.14s ease, border-color 0.14s ease;
  text-decoration: none;
  white-space: nowrap;
}
.btn:hover { transform: translateY(-1px); text-decoration: none; }
.btn:active { transform: translateY(0); }
.btn:focus-visible { outline: 2px solid var(--indigo); outline-offset: 2px; }

.btn-primary {
  background: linear-gradient(135deg, var(--indigo), var(--violet));
  color: #fff;
  box-shadow: 0 10px 24px rgba(79, 70, 229, 0.30);
}
.btn-primary:hover { background: linear-gradient(135deg, var(--indigo-dark), var(--violet)); }
.btn-ghost { background: rgba(255, 255, 255, 0.55); border-color: var(--line); color: var(--ink); }
.btn-ghost:hover { background: #fff; border-color: rgba(79, 70, 229, 0.35); }
.btn-danger { background: var(--danger-soft); color: var(--danger); border-color: rgba(214, 69, 69, 0.25); }
.btn-block { width: 100%; }
.btn-sm { padding: 7px 13px; font-size: 0.85rem; border-radius: 10px; }
.btn-lg { padding: 13px 24px; font-size: 1rem; border-radius: 14px; }
.btn[disabled], .btn.is-disabled { opacity: 0.55; cursor: not-allowed; transform: none; }

/* ------------------------------------------------------------------ forms */

.form-grid { display: grid; gap: var(--space-4); }
.form-row-2 { display: grid; gap: var(--space-4); grid-template-columns: repeat(2, minmax(0, 1fr)); }

.field { display: flex; flex-direction: column; gap: 6px; }
.field label { font-weight: 600; font-size: 0.9rem; }
.field .hint { font-size: 0.82rem; color: var(--muted); }

input[type="text"], input[type="email"], input[type="password"], input[type="number"],
input[type="search"], input[type="tel"], input[type="date"], select, textarea {
  width: 100%;
  padding: 11px 14px;
  font: inherit;
  font-size: 0.95rem;
  color: var(--ink);
  background: rgba(255, 255, 255, 0.82);
  border: 1px solid var(--line);
  border-radius: 12px;
  transition: border-color 0.14s ease, box-shadow 0.14s ease, background 0.14s ease;
}
textarea { min-height: 120px; resize: vertical; }
input:focus, select:focus, textarea:focus {
  outline: none;
  background: #fff;
  border-color: rgba(79, 70, 229, 0.5);
  box-shadow: 0 0 0 4px rgba(79, 70, 229, 0.12);
}
input.is-invalid, select.is-invalid, textarea.is-invalid { border-color: rgba(214, 69, 69, 0.6); }
.field-error { font-size: 0.82rem; color: var(--danger); font-weight: 500; }

.checkline { display: flex; align-items: flex-start; gap: 10px; font-size: 0.9rem; color: var(--muted); }
.checkline input { margin-top: 3px; width: 16px; height: 16px; accent-color: var(--indigo); }

/* ---------------------------------------------------------------- badges */

.badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 0.78rem; font-weight: 650; letter-spacing: 0.01em;
  background: rgba(31, 27, 58, 0.07); color: var(--muted);
  white-space: nowrap;
}
.badge-success { background: var(--success-soft); color: var(--success); }
.badge-warning { background: var(--warning-soft); color: var(--warning); }
.badge-danger  { background: var(--danger-soft);  color: var(--danger); }
.badge-muted   { background: rgba(31, 27, 58, 0.07); color: var(--muted); }
.badge-brand   { background: var(--violet-soft); color: var(--indigo); }
.badge-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

.chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 14px; border-radius: 999px;
  background: rgba(255, 255, 255, 0.7);
  border: 1px solid var(--line);
  font-size: 0.86rem; font-weight: 600;
}
.chip-code {
  font-weight: 700; color: var(--indigo);
  background: var(--violet-soft);
  border-radius: 999px; padding: 1px 9px; font-size: 0.78rem;
}

/* --------------------------------------------------------------- alerts */

.alert {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 13px 16px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--surface-strong);
  font-size: 0.92rem;
  margin-bottom: var(--space-4);
}
.alert:last-child { margin-bottom: 0; }
.alert-icon { flex: 0 0 auto; margin-top: 2px; }
.alert-success { background: var(--success-soft); border-color: rgba(15, 157, 99, 0.22); color: #0b6b45; }
.alert-warning { background: var(--warning-soft); border-color: rgba(180, 83, 9, 0.22); color: #8a4708; }
.alert-danger  { background: var(--danger-soft);  border-color: rgba(214, 69, 69, 0.22); color: #a52f2f; }
.alert-info    { background: rgba(79, 70, 229, 0.08); border-color: rgba(79, 70, 229, 0.20); color: #3730a3; }

.flash-stack { display: flex; flex-direction: column; gap: var(--space-3); margin-bottom: var(--space-6); }
.flash-holder { padding-top: var(--space-6); }
.flash-holder:empty { display: none; }
.soon-tag { margin-left: auto; font-size: 0.68rem; }
.sidebar-link-as-button { width: 100%; border: 0; background: none; cursor: pointer; text-align: left; font: inherit; }
.shell-footer { border: 0; margin: 0; padding-top: var(--space-4); }

/* ======================================================== reading passage */

.passage-card { display: flex; flex-direction: column; gap: var(--space-4); }
.passage-head { display: flex; flex-direction: column; gap: var(--space-3); }
.passage-title { margin: 0; font-size: 1.15rem; }
.passage-body {
  /* Long reading text: comfortable measure, never clipped or scrolled-away. */
  font-size: 1.02rem;
  line-height: 1.78;
  color: var(--ink-soft);
  border-left: 3px solid rgba(79, 70, 229, 0.35);
  padding-left: var(--space-4);
  overflow-wrap: anywhere;
}

/* ======================================================== audio player */

.audio-player { display: flex; flex-direction: column; gap: var(--space-4); }
.audio-controls {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-3);
}
.audio-timeline {
  position: relative; flex: 1 1 180px;
  min-width: 120px; height: 8px; border-radius: 999px;
  background: rgba(31, 27, 58, 0.10);
  cursor: pointer; overflow: hidden;
}
.audio-timeline-fill {
  height: 100%; width: 0;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--indigo), var(--violet));
  transition: width 0.15s linear;
}
.audio-time { font-size: 0.84rem; color: var(--muted); white-space: nowrap; }
.audio-note { margin: 0; }
.audio-player audio { width: 100%; height: 0; visibility: hidden; }

.audio-transcript { border-top: 1px solid var(--line-soft); padding-top: var(--space-3); }
.audio-transcript summary {
  cursor: pointer; font-weight: 650; font-size: 0.9rem; color: var(--indigo);
}
.audio-transcript-body {
  margin-top: var(--space-3);
  font-size: 0.95rem; line-height: 1.75; color: var(--ink-soft);
  white-space: normal;
}

@media (max-width: 560px) {
  /* Mobile: full-width controls on their own rows, nothing overlapping. */
  .audio-controls { gap: var(--space-2); }
  .audio-controls .btn { flex: 1 1 auto; }
  .audio-timeline { flex: 1 1 100%; order: 3; }
  .audio-time { order: 4; }
  .passage-body { padding-left: var(--space-3); font-size: 0.98rem; }
}

/* ================================================ admin assessment reader */

.admin-submission {
  max-height: 420px;
  overflow-y: auto;
  padding: var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: rgba(255, 255, 255, 0.7);
  font-size: 0.96rem;
  line-height: 1.7;
  white-space: normal;
  overflow-wrap: anywhere;
}

/* ================================================ speaking recorder (Phase 5) */

.record-panel { display: flex; flex-direction: column; gap: var(--space-3); }
.record-controls { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-3); }
.record-indicator {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 5px 12px; border-radius: 999px;
  background: var(--danger-soft); color: var(--danger);
  font-size: 0.84rem; font-weight: 650;
}
.record-dot {
  width: 10px; height: 10px; border-radius: 50%; background: var(--danger);
  animation: recordPulse 1.1s ease-in-out infinite;
}
@keyframes recordPulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.35; transform: scale(0.82); } }
.record-clock { font-size: 0.88rem; color: var(--ink-soft); white-space: nowrap; }
.record-wave {
  border-radius: 8px; background: rgba(31, 27, 58, 0.06);
  border: 1px solid var(--line);
}
.record-meter { height: 6px; border-radius: 999px; background: rgba(31, 27, 58, 0.09); overflow: hidden; }
.record-meter-fill {
  height: 100%; width: 0; border-radius: 999px;
  background: linear-gradient(90deg, var(--indigo), var(--danger));
  transition: width 0.1s linear;
}
.record-playback { width: 100%; }

@media (max-width: 560px) {
  .record-controls { gap: var(--space-2); }
  .record-controls .btn { flex: 1 1 auto; }
  .record-wave { width: 100%; }
}

/* ==================================================== test session layout */

.test-layout {
  display: grid;
  grid-template-columns: minmax(0, 2.4fr) minmax(0, 1fr);
  gap: var(--space-5);
  align-items: start;
}
.test-segment { display: flex; flex-direction: column; gap: var(--space-5); }
.test-sidebar {
  display: flex; flex-direction: column; gap: var(--space-5);
  position: sticky; top: calc(var(--topbar-h) + 12px);
}
.question-text { margin: 0 0 var(--space-4); font-size: 1.02rem; }

.option-row {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.6);
  cursor: pointer;
  transition: border-color 0.14s ease, background 0.14s ease;
}
.option-row:hover { border-color: rgba(79, 70, 229, 0.35); background: #fff; }
.option-row.is-selected {
  border-color: rgba(79, 70, 229, 0.5);
  background: rgba(79, 70, 229, 0.07);
}
.option-row input { width: 17px; height: 17px; accent-color: var(--indigo); flex: 0 0 auto; }
.option-label { display: flex; gap: 8px; align-items: baseline; min-width: 0; }

@media (max-width: 900px) {
  /* One column on tablet/mobile: the sidebar panel moves below the questions,
     so the submit button is still reachable without horizontal scrolling. */
  .test-layout { grid-template-columns: minmax(0, 1fr); }
  .test-sidebar { position: static; }
}

/* ------------------------------------------------------------- empty state */

.empty-state {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: var(--space-3);
  padding: var(--space-8) var(--space-6);
  border: 1px dashed rgba(31, 27, 58, 0.18);
  border-radius: var(--radius-lg);
  background: rgba(255, 255, 255, 0.42);
}
.empty-state .empty-icon {
  display: grid; place-items: center;
  width: 54px; height: 54px; border-radius: 16px;
  background: rgba(79, 70, 229, 0.10); color: var(--indigo);
}
.empty-state h3 { margin: 0; }
.empty-state p { margin: 0; max-width: 46ch; color: var(--muted); font-size: 0.92rem; }

/* ---------------------------------------------------------------- tables */

.table-wrap { width: 100%; overflow-x: auto; border-radius: var(--radius); }
table.data { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
table.data th, table.data td { padding: 12px 16px; text-align: left; vertical-align: middle; }
table.data thead th {
  font-size: 0.76rem; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--muted); font-weight: 700;
  background: rgba(255, 255, 255, 0.5);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
table.data tbody tr { border-bottom: 1px solid var(--line-soft); }
table.data tbody tr:last-child { border-bottom: none; }
table.data tbody tr:hover { background: rgba(255, 255, 255, 0.4); }
.table-empty { padding: var(--space-7) var(--space-6); text-align: center; color: var(--muted); font-size: 0.92rem; }

.progress-track { height: 8px; border-radius: 999px; background: rgba(31, 27, 58, 0.09); overflow: hidden; }
.progress-fill { height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--indigo), var(--violet)); }
.progress-fill.is-warning { background: linear-gradient(90deg, #f59e0b, #f97316); }

/* ============================================================ public site */

.public-header {
  position: sticky; top: 0; z-index: 40;
  backdrop-filter: blur(18px) saturate(180%);
  -webkit-backdrop-filter: blur(18px) saturate(180%);
  background: rgba(243, 240, 255, 0.72);
  border-bottom: 1px solid rgba(255, 255, 255, 0.6);
}
.public-header-inner {
  display: flex; align-items: center; gap: var(--space-5);
  min-height: var(--topbar-h);
}

.brand { display: inline-flex; align-items: center; gap: 10px; font-weight: 750; font-size: 1.06rem; color: var(--ink); text-decoration: none; }
.brand:hover { text-decoration: none; }
.brand-mark {
  display: grid; place-items: center;
  width: 34px; height: 34px; flex: 0 0 34px;
  border-radius: 11px;
  background: linear-gradient(135deg, var(--indigo), var(--violet));
  color: #fff; font-size: 0.9rem; font-weight: 800;
  box-shadow: 0 8px 18px rgba(79, 70, 229, 0.30);
}
/* BRAND: LEARNOVA renders as a WORDMARK. `PLATFORM_BRAND_INITIALS` is empty and the landing
   page passes an empty override mark, so the initials badge must not render as a blank tile. */
.brand-mark:empty { display: none; }
.brand-text small { display: block; font-size: 0.68rem; font-weight: 600; color: var(--muted); letter-spacing: 0.05em; text-transform: uppercase; }

/* BRAND LOGO (public header) — the official LEARNOVA artwork.
   Width-only sizing: `height: auto` + `aspect-ratio` make the height resolve from the intrinsic
   2048 x 877 ratio, so the logo can never be stretched, squashed or cropped, and the box is
   reserved before the image decodes (no layout shift) without needing a `height` attribute.
   No background/colour/filter is applied, so the PNG's own transparency keeps working.
   Desktop ~200px; the mobile width is set in the <=900px block below, which is where this header
   already moves its navigation onto its own row. */
.brand-logo {
  display: block;
  width: 200px;
  height: auto;
  aspect-ratio: 2048 / 877;
  max-width: 100%;
}

@media (max-width: 900px) {
  .brand-logo { width: 150px; }
}

.public-nav { display: flex; align-items: center; gap: var(--space-2); margin-left: var(--space-5); }
.public-nav a {
  padding: 8px 13px; border-radius: 10px;
  color: var(--ink-soft); font-weight: 600; font-size: 0.9rem;
}
.public-nav a:hover { background: rgba(255, 255, 255, 0.7); text-decoration: none; }
.public-nav a.is-active { background: #fff; color: var(--indigo); box-shadow: var(--shadow-sm); }
.public-actions { display: flex; align-items: center; gap: var(--space-2); margin-left: auto; }

/* ============================================ language switcher (i18n) */

/* A `<details>`-based control: no JavaScript, works with touch, and cannot affect the header
   layout while closed (the summary occupies one button-sized slot like its neighbours). */
.lang-switch { position: relative; display: inline-block; }
.lang-switch > summary { list-style: none; cursor: pointer; }
.lang-switch > summary::-webkit-details-marker { display: none; }
.lang-switch-toggle {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 11px; border-radius: 10px;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.7);
  color: var(--ink-soft); font-size: 0.86rem; font-weight: 600;
  line-height: 1.2; white-space: nowrap;
}
.lang-switch-toggle:hover { background: #fff; }
.lang-switch[open] > .lang-switch-toggle { background: #fff; border-color: rgba(79, 70, 229, 0.35); color: var(--indigo); }
.lang-switch-caret { font-size: 0.7rem; opacity: 0.65; }

.lang-switch-menu {
  position: absolute; z-index: 60;
  top: calc(100% + 8px); inset-inline-end: 0;
  min-width: 190px; margin: 0; padding: 6px;
  list-style: none;
  background: #fff; border: 1px solid var(--line); border-radius: 12px;
  box-shadow: var(--shadow-lg);
}
.lang-switch-item {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 9px 11px; border-radius: 8px;
  color: var(--ink); font-size: 0.9rem; font-weight: 600; text-decoration: none;
}
.lang-switch-item:hover { background: rgba(79, 70, 229, 0.07); text-decoration: none; }
.lang-switch-item.is-active { background: var(--violet-soft); color: var(--indigo); }
.lang-switch-check { color: var(--indigo); }

/* ------------------------------------------------------------- RTL */

/* Applied only when <html dir="rtl"> (Arabic). Everything is scoped under `[dir="rtl"]`, so no
   other language is affected, and removing `dir` restores LTR exactly. */
[dir="rtl"] body { text-align: right; }
[dir="rtl"] .public-nav { margin-left: 0; margin-right: var(--space-5); }
[dir="rtl"] .public-actions { margin-left: 0; margin-right: auto; }
[dir="rtl"] .lang-switch-menu { inset-inline-end: 0; }
[dir="rtl"] .tile-link,
[dir="rtl"] .sidebar-link,
[dir="rtl"] .level-row { text-align: right; }
[dir="rtl"] .table-wrap table.data th,
[dir="rtl"] .table-wrap table.data td { text-align: right; }
[dir="rtl"] .stack ul, [dir="rtl"] .stack-sm ul { padding-left: 0; padding-right: 20px; }
[dir="rtl"] .faq-item summary::after { margin-inline-start: 0; margin-inline-end: auto; }

@media (max-width: 900px) {
  /* The public header already wraps its nav onto its own row here, so the switcher keeps its slot
     and the menu opens within the viewport instead of overflowing it. */
  .lang-switch-menu { inset-inline-end: auto; inset-inline-start: 0; min-width: 170px; }
  [dir="rtl"] .lang-switch-menu { inset-inline-start: auto; inset-inline-end: 0; }
}
@media (max-width: 560px) {
  /* The current language name is hidden on the smallest screens; the globe + caret stay as the
     touch target so the header cannot overflow with longer names such as "Bahasa Indonesia". */
  .lang-switch-current { display: none; }

  /* A translated call-to-action can be considerably longer than the Indonesian one (measured:
     "S'inscrire gratuitement" is 185px, against 288px of usable width at a 320px viewport). The
     actions row therefore wraps its own children and the label may break inside the button, so the
     header adapts to the LONGEST translation instead of overflowing the viewport. */
  .public-actions { flex-wrap: wrap; justify-content: flex-end; row-gap: 8px; }
  .public-actions .btn { white-space: normal; text-align: center; max-width: 100%; }
}

.nav-toggle { display: none; }

.hero { padding-block: clamp(40px, 7vw, 84px) var(--space-8); }
.hero-grid { display: grid; gap: var(--space-8); grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); align-items: center; }
.hero h1 { margin-bottom: var(--space-4); }
.hero .lead { font-size: clamp(1rem, 0.94rem + 0.35vw, 1.16rem); color: var(--muted); max-width: 60ch; }
.eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 5px 13px; border-radius: 999px;
  background: rgba(255, 255, 255, 0.7);
  border: 1px solid var(--line);
  font-size: 0.78rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--indigo); margin-bottom: var(--space-4);
}

.hero-panel { display: grid; gap: var(--space-4); }
.level-ladder { display: grid; gap: var(--space-2); }
.level-row {
  display: flex; align-items: center; gap: var(--space-3);
  padding: 11px 15px; border-radius: 12px;
  background: rgba(255, 255, 255, 0.62);
  border: 1px solid rgba(255, 255, 255, 0.7);
}
.level-row .level-code { font-weight: 800; color: var(--indigo); width: 32px; }
.level-row .level-name { font-weight: 600; font-size: 0.9rem; }
.level-bar { height: 6px; border-radius: 999px; background: linear-gradient(90deg, var(--indigo), var(--violet)); opacity: 0.85; }

.feature-card { display: flex; flex-direction: column; gap: var(--space-2); }
.feature-card .tile-icon { margin-bottom: var(--space-2); }

.public-footer {
  margin-top: var(--space-8);
  padding-block: var(--space-7);
  border-top: 1px solid rgba(255, 255, 255, 0.6);
  color: var(--muted); font-size: 0.88rem;
}

/* ============================================================= app shell */

.app-shell { display: grid; grid-template-columns: var(--sidebar-w) minmax(0, 1fr); min-height: 100vh; }

.sidebar {
  position: sticky; top: 0; align-self: start;
  height: 100vh;
  display: flex; flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-4);
  background: rgba(255, 255, 255, 0.55);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border-right: 1px solid rgba(255, 255, 255, 0.7);
  overflow-y: auto;
  z-index: 50;
}
.sidebar .brand { margin-bottom: var(--space-2); }
.sidebar-nav { display: flex; flex-direction: column; gap: 3px; }
.sidebar-group-label {
  font-size: 0.7rem; font-weight: 750; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--muted-2); padding: var(--space-4) 10px 6px;
}
.sidebar-link {
  display: flex; align-items: center; gap: 11px;
  padding: 10px 12px; border-radius: 11px;
  color: var(--ink-soft); font-weight: 600; font-size: 0.9rem;
  text-decoration: none;
  transition: background 0.14s ease, color 0.14s ease;
}
.sidebar-link:hover { background: rgba(255, 255, 255, 0.8); text-decoration: none; }
.sidebar-link.is-active {
  background: linear-gradient(135deg, rgba(79, 70, 229, 0.13), rgba(139, 92, 246, 0.13));
  color: var(--indigo);
}
.sidebar-link .icon { color: currentColor; opacity: 0.9; }
.sidebar-foot { margin-top: auto; padding-top: var(--space-4); border-top: 1px solid var(--line-soft); }

.app-main { min-width: 0; display: flex; flex-direction: column; }
.app-topbar {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; gap: var(--space-4);
  padding: 12px clamp(16px, 3vw, 32px);
  min-height: var(--topbar-h);
  background: rgba(243, 240, 255, 0.78);
  backdrop-filter: blur(18px) saturate(180%);
  -webkit-backdrop-filter: blur(18px) saturate(180%);
  border-bottom: 1px solid rgba(255, 255, 255, 0.65);
}
.app-topbar h1 { font-size: 1.16rem; margin: 0; }
.app-topbar .page-sub { font-size: 0.84rem; color: var(--muted); margin: 0; }
.topbar-actions { display: flex; align-items: center; gap: var(--space-2); margin-left: auto; }
.icon-btn {
  display: inline-grid; place-items: center;
  width: 38px; height: 38px; border-radius: 11px;
  background: rgba(255, 255, 255, 0.7); border: 1px solid var(--line);
  color: var(--ink-soft); cursor: pointer;
}
.icon-btn:hover { background: #fff; }
.app-content { padding: clamp(18px, 3vw, 34px); display: flex; flex-direction: column; gap: var(--space-7); }
.app-content > *:last-child { margin-bottom: var(--space-4); }
.page-head { display: flex; flex-wrap: wrap; gap: var(--space-4); align-items: flex-end; justify-content: space-between; }
.page-head h1 { margin: 0 0 4px; font-size: clamp(1.4rem, 1.1rem + 1.1vw, 1.9rem); }
.page-head p { margin: 0; color: var(--muted); font-size: 0.92rem; }

.user-chip {
  display: flex; align-items: center; gap: 10px;
  padding: 5px 12px 5px 5px; border-radius: 999px;
  background: rgba(255, 255, 255, 0.7); border: 1px solid var(--line);
}
.avatar {
  display: grid; place-items: center;
  width: 32px; height: 32px; border-radius: 50%;
  background: linear-gradient(135deg, var(--indigo), var(--violet));
  color: #fff; font-size: 0.78rem; font-weight: 700;
}
.avatar-lg { width: 64px; height: 64px; font-size: 1.3rem; border-radius: 20px; }
.user-chip-meta { display: flex; flex-direction: column; line-height: 1.15; }
.user-chip-meta strong { font-size: 0.86rem; }
.user-chip-meta span { font-size: 0.74rem; color: var(--muted); }

.backdrop {
  display: none;
  position: fixed; inset: 0; z-index: 45;
  background: rgba(31, 27, 58, 0.4);
  backdrop-filter: blur(2px);
}

/* --------------------------------------------------------- auth pages */

.auth-shell {
  min-height: 100vh;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: var(--space-5);
  padding: var(--space-7) var(--space-4);
}
.auth-card { width: min(500px, 100%); }
.auth-card .brand { justify-content: center; margin-bottom: var(--space-5); }
.auth-head { text-align: center; margin-bottom: var(--space-6); }
.auth-head h1 { font-size: 1.5rem; margin-bottom: 6px; }
.auth-head p { margin: 0; color: var(--muted); font-size: 0.92rem; }
.auth-alt { text-align: center; font-size: 0.9rem; color: var(--muted); }
.auth-foot { font-size: 0.82rem; color: var(--muted-2); text-align: center; }

.divider { display: flex; align-items: center; gap: var(--space-3); color: var(--muted-2); font-size: 0.8rem; }
.divider::before, .divider::after { content: ""; height: 1px; flex: 1; background: var(--line); }

/* ----------------------------------------------------------- error page */

.page-error { display: grid; place-items: center; min-height: 100vh; padding: var(--space-5); }
.error-shell { width: min(560px, 100%); }
.error-card { text-align: center; padding: var(--space-8) var(--space-6); }
.error-code {
  display: inline-block; font-size: 3rem; font-weight: 800; line-height: 1;
  background: linear-gradient(135deg, var(--indigo), var(--violet));
  -webkit-background-clip: text; background-clip: text; color: transparent;
  margin-bottom: var(--space-3);
}
.error-actions { display: flex; justify-content: center; gap: var(--space-3); margin-top: var(--space-5); flex-wrap: wrap; }
.error-detail {
  white-space: pre-wrap; word-break: break-word; text-align: left;
  background: rgba(31, 27, 58, 0.06); padding: 14px; border-radius: 12px;
  font-size: 12px; margin-top: var(--space-5); overflow-x: auto;
}

/* ---------------------------------------------------------- responsive */

@media (max-width: 1080px) {
  .hero-grid { grid-template-columns: minmax(0, 1fr); }
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 900px) {
  .app-shell { grid-template-columns: minmax(0, 1fr); }
  .sidebar {
    position: fixed; top: 0; left: 0; height: 100vh;
    /* leaves a comfortable tap-out area on small phones */
    width: min(286px, 78vw);
    transform: translateX(-102%);
    transition: transform 0.22s ease;
    box-shadow: var(--shadow-lg);
    background: rgba(255, 255, 255, 0.94);
  }
  body.nav-open .sidebar { transform: translateX(0); }
  body.nav-open .backdrop { display: block; }
  .nav-toggle { display: inline-grid; }
  /* Public navigation stays reachable on small screens: wraps under the brand
     as a horizontally scrollable row instead of disappearing. */
  .public-header-inner { flex-wrap: wrap; padding-block: 10px; }
  .public-nav {
    order: 3; width: 100%; margin-left: 0;
    overflow-x: auto; padding-bottom: 2px;
    -webkit-overflow-scrolling: touch;
  }
  .public-nav a { white-space: nowrap; }
}

@media (max-width: 720px) {
  .grid-2, .grid-3, .grid-4 { grid-template-columns: minmax(0, 1fr); }
  .form-row-2 { grid-template-columns: minmax(0, 1fr); }
  .container { width: min(1180px, 100% - 32px); }
  .app-topbar { flex-wrap: wrap; }
  .topbar-actions { width: 100%; margin-left: 0; }
  .user-chip-meta { display: none; }
  .card, .glass-card { padding: var(--space-5); border-radius: var(--radius); }
  .card-body { padding: var(--space-5); }
  .card-header, .card-footer { padding: var(--space-4) var(--space-5); }
  table.data th, table.data td { padding: 10px 12px; }
}

@media (max-width: 560px) {
  .public-actions .btn span.hide-sm { display: none; }
  .stat-value { font-size: 1.6rem; }
  h1 { font-size: 1.6rem; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
  html { scroll-behavior: auto; }
}

/* ===================================================== landing page (LEARNOVA) */

/* The landing page shows its brand as a wordmark with a literal-case tagline
   ("Learn. Practice. Master."), where the shared header uppercases taglines. */
.brand-text.is-literal small { text-transform: none; letter-spacing: 0.02em; font-size: 0.74rem; }

/* Section heading used between landing sections. */
.lp-head { max-width: 68ch; margin-bottom: var(--space-6); }
.lp-head h2 { margin-bottom: var(--space-2); }
.lp-head p { margin: 0; color: var(--muted); }

/* Checklists (who it is for, what Lifetime includes). */
.lp-check { display: grid; gap: var(--space-3); }
.lp-check-item {
  display: flex; gap: var(--space-3); align-items: flex-start;
  font-size: 0.94rem; color: var(--ink-soft);
}
.lp-check-item .lp-tick { flex: 0 0 auto; margin-top: 3px; color: var(--success); }

/* Numbered steps (how to use it, how to get Lifetime). */
.lp-step { display: flex; gap: var(--space-4); align-items: flex-start; }
.lp-step-no {
  flex: 0 0 auto;
  display: grid; place-items: center;
  width: 30px; height: 30px;
  border-radius: 10px;
  background: linear-gradient(135deg, var(--indigo), var(--violet));
  color: #fff; font-size: 0.82rem; font-weight: 800;
}
.lp-step-body { min-width: 0; }
.lp-step-title { display: block; font-weight: 700; color: var(--ink); }
.lp-step-desc { display: block; color: var(--muted); font-size: 0.9rem; margin-top: 2px; }

/* Price block on the Lifetime section. */
.lp-price {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-3);
  margin: var(--space-4) 0 var(--space-2);
}
.lp-price .lp-amount { font-size: clamp(1.9rem, 1.5rem + 1.4vw, 2.4rem); font-weight: 800; color: var(--ink); line-height: 1.05; }
.lp-price .lp-per { color: var(--muted); font-size: 0.9rem; font-weight: 600; }

/* FAQ — native <details> so it works without JavaScript. */
.faq-list { display: grid; gap: var(--space-3); }
.faq-item {
  border-radius: var(--radius);
  border: 1px solid rgba(255, 255, 255, 0.7);
  background: rgba(255, 255, 255, 0.62);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  overflow: hidden;
}
.faq-item summary {
  cursor: pointer; list-style: none;
  display: flex; align-items: center; gap: var(--space-3);
  padding: 14px 18px;
  font-weight: 650; font-size: 0.95rem; color: var(--ink);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: '+'; margin-left: auto;
  font-weight: 800; font-size: 1.15rem; line-height: 1; color: var(--indigo);
}
.faq-item[open] summary::after { content: '\2212'; }
.faq-item summary:focus-visible { outline: 2px solid var(--indigo); outline-offset: -2px; }
.faq-item .faq-answer {
  padding: 0 18px 16px;
  color: var(--muted); font-size: 0.92rem;
}
.faq-item .faq-answer p { margin: 0; }

/* A quiet, clearly-marked caveat (e.g. the Placement limitation). */
.lp-note {
  margin-top: var(--space-5);
  border-left: 3px solid var(--indigo);
  padding: var(--space-3) var(--space-4);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: rgba(79, 70, 229, 0.07);
  color: var(--ink-soft); font-size: 0.9rem;
}
.lp-note strong { color: var(--ink); }

@media (max-width: 720px) {
  .lp-head { margin-bottom: var(--space-5); }
}
