/* ============================================================================
   components.css — every component of DESIGN_SYSTEM.md §7, all states.
   Token variables only (no raw colors/sizes). Logical properties only (§5).
   Layers: tokens.css → base.css → components.css (→ pages/*.css)
   ============================================================================ */

/* ==== 7.1 Buttons ========================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  block-size: 40px;
  padding-inline: var(--space-5);
  border: 0;
  border-radius: var(--radius-md);
  font-size: var(--fs-body);
  font-weight: 500;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease),
              color var(--dur-1) var(--ease),
              border-color var(--dur-1) var(--ease);
}
a.btn:hover { text-decoration: none; }

.btn--sm { block-size: 32px; padding-inline: var(--space-4); font-size: var(--fs-body-sm); }
.btn--lg { block-size: 48px; padding-inline: var(--space-6); font-size: var(--fs-body-lg); }

.btn--primary { background: var(--btn-primary-bg); color: var(--ink-inverse); }
.btn--primary:hover  { background: var(--btn-primary-hover); }
.btn--primary:active { background: var(--btn-primary-active); }

.btn--secondary {
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--border-strong);
}
.btn--secondary:hover  { border-color: var(--ink-3); background: var(--surface-alt); }
.btn--secondary:active { background: var(--border); }

.btn--ghost { background: transparent; color: var(--link); padding-inline: var(--space-3); }
.btn--ghost:hover  { background: var(--primary-tint); }
.btn--ghost:active { background: var(--primary-100); }

.btn--danger { background: var(--danger); color: var(--ink-inverse); }
.btn--danger:hover, .btn--danger:active { background: var(--danger-hover); }

.btn:disabled, .btn.is-disabled {
  opacity: .45;
  cursor: not-allowed;
  pointer-events: none;
}

/* Loading: spinner replaces the icon; label stays; button never shrinks */
.btn.is-loading { pointer-events: none; }
.btn.is-loading .btn__icon { display: none; }
.btn .btn__spinner { display: none; }
.btn.is-loading .btn__spinner { display: inline-flex; }

/* Icon-only button: 40×40, requires aria-label */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 40px;
  block-size: 40px;
  border-radius: var(--radius-md);
  color: var(--ink-2);
  transition: background-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}
.icon-btn:hover { background: var(--surface-alt); color: var(--ink); }

/* Vertical reorder arrows (paragraph ordering — placement, task, exam).
   The shared 'arrow' icon is drawn pointing inline-forward; we rotate it to
   point up / down. Vertical direction does NOT depend on reading direction,
   so RTL keeps the SAME rotation as LTR — and must override the horizontal
   scaleX flip that .icon-directional applies to directional icons in RTL
   (equal specificity, wins by loading after base.css). */
.pl-arrow-up   { transform: rotate(-90deg); }
.pl-arrow-down { transform: rotate(90deg); }
[dir="rtl"] .pl-arrow-up   { transform: rotate(-90deg); }
[dir="rtl"] .pl-arrow-down { transform: rotate(90deg); }

/* ==== 7.2 Fields ============================================================ */

.field { display: flex; flex-direction: column; }
.field + .field { margin-block-start: var(--space-4); }

.field__label {
  font-size: var(--fs-body-sm);
  line-height: var(--lh-body-sm);
  font-weight: 500;
  margin-block-end: 6px;
}

.input {
  inline-size: 100%;
  block-size: 44px;
  padding-inline: var(--space-3);
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  transition: border-color var(--dur-1) var(--ease);
}
textarea.input { block-size: auto; min-block-size: 96px; padding-block: var(--space-2); resize: vertical; }

.input:focus-visible { border-color: var(--primary-500); }
.input:disabled { background: var(--surface-alt); color: var(--ink-3); cursor: not-allowed; }

.field__help {
  font-size: var(--fs-body-sm);
  line-height: var(--lh-body-sm);
  color: var(--ink-3);
  margin-block-start: 6px;
}

/* Error message: revealed only after first blur/submit (JS adds .field--error) */
.field__error {
  display: none;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--fs-body-sm);
  line-height: var(--lh-body-sm);
  color: var(--danger);
  margin-block-start: 6px;
}
.field--error .field__error { display: inline-flex; }
.field--error .input { border-color: var(--danger); }

/* Input with a trailing affix (password eye…) */
.field__wrap { position: relative; }
.field__wrap .input { padding-inline-end: var(--space-12); }
.field__affix {
  position: absolute;
  inset-inline-end: var(--space-1);
  inset-block-start: 50%;
  transform: translateY(-50%);
  inline-size: 36px;
  block-size: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  color: var(--ink-3);
}
.field__affix:hover { color: var(--ink); }
/* password eye: swap icons via .is-visible (ui.js) */
.field__affix .icon-eye-off { display: none; }
.field__affix.is-visible .icon-eye { display: none; }
.field__affix.is-visible .icon-eye-off { display: block; }

/* Custom select: logical chevron */
.select { position: relative; }
.select .input {
  appearance: none;
  padding-inline-end: var(--space-10);
  cursor: pointer;
}
.select .icon-chevron {
  position: absolute;
  inset-inline-end: var(--space-3);
  inset-block-start: 50%;
  transform: translateY(-50%);
  color: var(--ink-3);
  pointer-events: none;
}

/* Custom checkbox / radio — 20px, SVG check (CSS mask), visible focus */
.choice {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  cursor: pointer;
  font-size: var(--fs-body);
}
.choice input {
  appearance: none;
  inline-size: 20px;
  block-size: 20px;
  margin: 0;
  flex-shrink: 0;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--space-1);
  display: grid;
  place-content: center;
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease);
}
.choice input[type="radio"] { border-radius: 50%; }
.choice input:checked { background: var(--btn-primary-bg); border-color: var(--btn-primary-bg); }
.choice input[type="checkbox"]:checked::before {
  content: "";
  inline-size: 12px;
  block-size: 12px;
  background: var(--ink-inverse);
  -webkit-mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 6 9 17l-5-5" fill="none" stroke="black" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/></svg>') center / contain no-repeat;
  mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 6 9 17l-5-5" fill="none" stroke="black" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/></svg>') center / contain no-repeat;
}
.choice input[type="radio"]:checked::before {
  content: "";
  inline-size: 8px;
  block-size: 8px;
  border-radius: 50%;
  background: var(--ink-inverse);
}
.choice input:disabled { background: var(--surface-alt); cursor: not-allowed; }
.choice:has(input:disabled) { color: var(--ink-3); cursor: not-allowed; }

/* ==== 7.3 Card ============================================================== */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: var(--space-6);
}
@media (max-width: 599px) { .card { padding: var(--space-4); } }

.card__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-block-end: var(--space-4);
}

a.card, .card--interactive {
  display: block;
  color: inherit;
  text-decoration: none;
  transition: box-shadow var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease);
}
a.card:hover, .card--interactive:hover {
  box-shadow: var(--shadow-md);
  border-color: var(--border-strong);
  text-decoration: none;
}

/* ==== 7.4 Badge ============================================================= */

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  block-size: 24px;
  padding-inline: 10px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-caption);
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
}
.badge--success { background: var(--success-soft); color: var(--success); }
.badge--warning { background: var(--warning-soft); color: var(--warning-ink); }
.badge--danger  { background: var(--danger-soft);  color: var(--danger); }
.badge--info    { background: var(--info-soft);    color: var(--info); }
.badge--neutral { background: var(--surface-alt);  color: var(--ink-2); }

/* CEFR badge — brand chip, identical in both themes (§7.4) */
.badge--cefr {
  block-size: 32px;
  padding-inline: var(--space-3);
  background: var(--primary-50);
  color: var(--primary-800);
  font-size: var(--fs-body-sm);
  font-weight: 600;
}

/* ==== 7.5 Alert ============================================================= */

.alert {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-4);
  border-radius: var(--radius-md);
  border-inline-start: 3px solid;
}
.alert__icon { flex-shrink: 0; margin-block-start: 2px; }
.alert__title { font-weight: 600; }
.alert__body  { color: var(--ink-2); }
.alert__close { margin-inline-start: auto; align-self: flex-start; color: var(--ink-3); }
.alert__close:hover { color: var(--ink); }

.alert--success { background: var(--success-soft); border-color: var(--success); }
.alert--success .alert__icon { color: var(--success); }
.alert--warning { background: var(--warning-soft); border-color: var(--warning); }
.alert--warning .alert__icon { color: var(--warning); }
.alert--danger  { background: var(--danger-soft);  border-color: var(--danger); }
.alert--danger .alert__icon  { color: var(--danger); }
.alert--info    { background: var(--info-soft);    border-color: var(--info); }
.alert--info .alert__icon    { color: var(--info); }

/* ==== 7.6 Modal ============================================================= */

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: var(--backdrop);
  z-index: var(--z-modal-backdrop);
  display: grid;
  place-items: center;
  padding: var(--space-4);
}
.modal-backdrop[hidden] { display: none; }

.modal {
  inline-size: 100%;
  max-inline-size: 520px;
  background: var(--surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  z-index: var(--z-modal);
  animation: modal-in var(--dur-2) var(--ease);
}
@keyframes modal-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

.modal__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-5) var(--space-6) 0;
}
.modal__body { padding: var(--space-4) var(--space-6); color: var(--ink-2); }
.modal__footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
  padding: 0 var(--space-6) var(--space-5);
}

@media (max-width: 599px) {
  .modal-backdrop { padding: 0; align-items: stretch; }
  .modal {
    max-inline-size: none;
    min-block-size: 100svh;
    border-radius: 0;
    display: flex;
    flex-direction: column;
  }
  .modal__body { flex: 1; overflow-y: auto; }
}

/* ==== 7.7 Stepper =========================================================== */

.stepper { display: flex; align-items: center; }
.stepper__step { display: flex; align-items: center; gap: var(--space-2); }
.stepper__step:not(:first-child) { flex: 1; }
/* connector line before every step except the first */
.stepper__step:not(:first-child)::before {
  content: "";
  flex: 1;
  block-size: 2px;
  background: var(--border-strong);
  margin-inline: var(--space-2);
}
.stepper__step.is-done:not(:first-child)::before,
.stepper__step.is-current:not(:first-child)::before { background: var(--primary-600); }

.stepper__dot {
  inline-size: 28px;
  block-size: 28px;
  border-radius: 50%;
  border: 2px solid var(--border-strong);
  color: var(--ink-3);
  font-size: var(--fs-caption);
  font-weight: 600;
  display: grid;
  place-content: center;
  flex-shrink: 0;
}
.stepper__step.is-current .stepper__dot { border-color: var(--primary-600); color: var(--ink); }
.stepper__step.is-done .stepper__dot {
  background: var(--primary-600);
  border-color: var(--primary-600);
  color: var(--ink-inverse);
}
.stepper__label { font-size: var(--fs-caption); font-weight: 500; color: var(--ink-3); white-space: nowrap; }
.stepper__step.is-current .stepper__label,
.stepper__step.is-done .stepper__label { color: var(--ink); }

/* Compact form under 600px: text line + thin progress bar */
.stepper-compact { display: none; }
@media (max-width: 599px) {
  .stepper { display: none; }
  .stepper-compact { display: block; }
  .stepper-compact__text {
    font-size: var(--fs-body-sm);
    font-weight: 500;
    color: var(--ink-2);
    margin-block-end: var(--space-2);
  }
}

/* ==== 7.8 Tabs ============================================================== */

.tabs {
  position: relative;
  display: flex;
  border-block-end: 1px solid var(--border);
  overflow-x: auto;
  scrollbar-width: none;
}
.tab {
  padding: var(--space-3) var(--space-4);
  font-weight: 500;
  color: var(--ink-2);
  white-space: nowrap;
  transition: color var(--dur-1) var(--ease);
}
.tab:hover { color: var(--ink); }
.tab.is-active { color: var(--link); }
/* Sliding indicator positioned by ui.js; falls back to per-tab underline */
.tabs__indicator {
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 0;
  block-size: 2px;
  inline-size: 0;
  background: var(--primary-600);
  transition: transform var(--dur-2) var(--ease), inline-size var(--dur-2) var(--ease);
}
.tabs:not(:has(.tabs__indicator)) .tab.is-active {
  box-shadow: inset 0 -2px 0 var(--primary-600);
}
.tab-panel[hidden] { display: none; }

/* ==== 7.9 Table ============================================================= */

.table { inline-size: 100%; }
.table th {
  background: var(--surface-alt);
  font-size: var(--fs-caption);
  font-weight: 600;
  color: var(--ink-2);
  text-align: start;
  padding: var(--space-3) var(--space-4);
}
.table td {
  border-block-end: 1px solid var(--border);
  block-size: 48px;
  padding-inline: var(--space-4);
  vertical-align: middle;
}
.table tbody tr { transition: background-color var(--dur-1) var(--ease); }
.table tbody tr:hover { background: var(--primary-tint); }
.table .num { font-variant-numeric: tabular-nums; }

/* Dense admin tables: horizontal scroll with edge hint */
.table-wrap { overflow-x: auto; }

/* Mobile: rows collapse to stacked label/value cards */
@media (max-width: 599px) {
  .table--stack thead { display: none; }
  .table--stack, .table--stack tbody, .table--stack tr, .table--stack td { display: block; }
  .table--stack tr {
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--surface);
    margin-block-end: var(--space-3);
    padding: var(--space-2) var(--space-4);
  }
  .table--stack td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    block-size: auto;
    padding: var(--space-2) 0;
    border-block-end: 1px solid var(--border);
  }
  .table--stack td:last-child { border-block-end: 0; }
  .table--stack td::before {
    content: attr(data-label);
    font-size: var(--fs-caption);
    font-weight: 500;
    color: var(--ink-3);
  }
}

/* ==== 7.10 Empty state ====================================================== */

.empty {
  min-block-size: 240px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--space-3);
  padding: var(--space-8) var(--space-4);
}
.empty__icon {
  inline-size: 80px;
  block-size: 80px;
  border-radius: 50%;
  background: var(--primary-tint);
  color: var(--icon-accent);
  display: grid;
  place-content: center;
}
.empty__text { color: var(--ink-2); max-inline-size: 44ch; }
.empty__action { margin-block-start: var(--space-2); }

/* ==== 7.10b Error pages (404 / 403 / 500) ================================== */

.errorpage {
  min-block-size: 60vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--space-3);
  padding: var(--space-10) var(--space-4);
}
.errorpage__code {
  font-size: clamp(4.5rem, 20vw, 9rem);
  font-weight: 800;
  line-height: 0.9;
  letter-spacing: 0.02em;
  color: var(--primary-200);
  margin-block-end: calc(-1 * var(--space-3));
}
.errorpage__icon {
  inline-size: 72px;
  block-size: 72px;
  border-radius: 50%;
  background: var(--primary-tint);
  color: var(--icon-accent);
  display: grid;
  place-content: center;
}
.errorpage__title { font-size: var(--fs-h2); }
.errorpage__text { color: var(--ink-2); max-inline-size: 46ch; }
.errorpage__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: center;
  margin-block-start: var(--space-3);
}

/* ==== 7.11 Skeleton ========================================================= */

.skeleton {
  position: relative;
  overflow: hidden;
  background: var(--surface-alt);
  border-radius: var(--radius-sm);
}
.skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, var(--skeleton-sheen), transparent);
  animation: skeleton-sheen 1.4s var(--ease) infinite;
}
/* sheen travels with reading direction (§7.11) */
[dir="rtl"] .skeleton::after { animation-direction: reverse; }
@keyframes skeleton-sheen {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}
.skeleton--text  { block-size: 1em; }
.skeleton--title { block-size: 1.4em; inline-size: 40%; }
.skeleton--circle { border-radius: 50%; aspect-ratio: 1; }

/* ==== 7.12 Linear progress ================================================== */

.progress {
  block-size: 8px;
  background: var(--surface-alt);
  border-radius: var(--radius-pill);
  overflow: hidden;
}
.progress__fill {
  block-size: 100%;
  /* dynamic value injected as a CSS variable (the single allowed inline var) */
  inline-size: calc(var(--value, 0) * 1%);
  background: var(--primary-500);
  border-radius: var(--radius-pill);
  transition: inline-size var(--dur-2) var(--ease);
}

/* ==== 7.12 Progress ring ==================================================== */

.ring-box { position: relative; inline-size: 120px; }
.ring { inline-size: 100%; transform: rotate(-90deg); }
.ring__track { fill: none; stroke: var(--surface-alt); }
.ring__fill  { fill: none; stroke: currentColor; stroke-linecap: round; }
.ring-box.is-good { color: var(--value-good); }
.ring-box.is-mid  { color: var(--value-mid); }
.ring-box.is-weak { color: var(--value-weak); }
.ring-box__num {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  font-size: var(--fs-h2);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

/* ==== 7.12 Audio player (custom — never the default <audio controls>) ====== */

.audio {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.audio__btn {
  inline-size: 44px;
  block-size: 44px;
  border-radius: 50%;
  background: var(--btn-primary-bg);
  color: var(--ink-inverse);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: background-color var(--dur-1) var(--ease);
}
.audio__btn:hover { background: var(--btn-primary-hover); }
.audio__track { flex: 1; cursor: pointer; }
.audio__time {
  font-size: var(--fs-body-sm);
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
  flex-shrink: 0;
}
/* limited-play variant (listening section): remaining plays counter */
.audio__plays {
  font-size: var(--fs-caption);
  font-weight: 500;
  color: var(--ink-3);
  flex-shrink: 0;
}

/* ==== 7.12 Recorder ========================================================= */

.recorder {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-5);
}
.recorder__btn {
  inline-size: 56px;
  block-size: 56px;
  border-radius: 50%;
  background: var(--danger);
  color: var(--ink-inverse);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background-color var(--dur-1) var(--ease);
}
.recorder__btn:hover { background: var(--danger-hover); }
/* status pulse — while recording only (functional indicator, not decoration) */
.recorder.is-recording .recorder__btn { animation: rec-pulse 1.2s var(--ease) infinite; }
@keyframes rec-pulse {
  from { box-shadow: 0 0 0 0 var(--danger-soft); }
  to   { box-shadow: 0 0 0 14px transparent; }
}
.recorder__timer {
  font-size: var(--fs-body-sm);
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
}
.recorder__wave { display: flex; align-items: center; gap: 3px; block-size: 24px; }
.recorder__wave span {
  inline-size: 3px;
  block-size: 6px;
  border-radius: var(--radius-pill);
  background: var(--border-strong);
}
.recorder.is-recording .recorder__wave span {
  background: var(--danger);
  animation: wave-bounce 900ms var(--ease) infinite alternate;
}
.recorder.is-recording .recorder__wave span:nth-child(2n)  { animation-delay: 150ms; }
.recorder.is-recording .recorder__wave span:nth-child(3n)  { animation-delay: 300ms; }
@keyframes wave-bounce { from { block-size: 6px; } to { block-size: 22px; } }
.recorder__actions { display: flex; gap: var(--space-3); }

/* ==== 7.12 Toast ============================================================ */

.toast {
  position: fixed;
  inset-block-start: var(--space-4);
  inset-inline: 0;
  margin-inline: auto;
  inline-size: fit-content;
  max-inline-size: min(92vw, 480px);
  z-index: var(--z-toast);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  border-inline-start: 3px solid var(--ink-3);
  animation: toast-in var(--dur-2) var(--ease);
}
.toast[hidden] { display: none; }
@keyframes toast-in {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: none; }
}
.toast--success { border-color: var(--success); }
.toast--success .toast__icon { color: var(--success); }
.toast--danger { border-color: var(--danger); }
.toast--danger .toast__icon { color: var(--danger); }
.toast--info { border-color: var(--info); }
.toast--info .toast__icon { color: var(--info); }
.toast--warning { border-color: var(--warning); }
.toast--warning .toast__icon { color: var(--warning); }

/* ==== 7.12 Notification bell ================================================ */

.bell { position: relative; }
.bell__count {
  position: absolute;
  inset-block-start: 2px;
  inset-inline-end: 2px;
  min-inline-size: 18px;
  block-size: 18px;
  padding-inline: var(--space-1);
  border-radius: var(--radius-pill);
  background: var(--danger);
  color: var(--ink-inverse);
  border: 2px solid var(--bg);
  font-size: var(--fs-caption);
  font-weight: 600;
  line-height: 1;
  display: grid;
  place-content: center;
}
.bell__menu {
  position: absolute;
  inset-block-start: calc(100% + var(--space-2));
  inset-inline-end: 0;
  inline-size: 360px;
  max-inline-size: 92vw;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  z-index: var(--z-dropdown);
}
.bell__menu[hidden] { display: none; }
.bell__item {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-block-end: 1px solid var(--border);
  color: var(--ink);
  text-decoration: none;
}
.bell__item:last-child { border-block-end: 0; }
.bell__item.is-unread { background: var(--primary-tint); }
.bell__item:hover { background: var(--surface-alt); text-decoration: none; }
.bell__item-time { font-size: var(--fs-caption); color: var(--ink-3); white-space: nowrap; }
.bell__item-icon { flex: none; color: var(--primary-600); display: inline-flex; }
.bell__item-body { display: flex; flex-direction: column; gap: 2px; min-inline-size: 0; flex: 1; }
.bell__item-title { font-weight: 600; font-size: var(--fs-body); }
.bell__item-text {
  font-size: var(--fs-caption);
  color: var(--ink-2);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.bell__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-block-end: 1px solid var(--border);
}
.bell__head-title { font-weight: 700; }
.bell__markall {
  background: none;
  border: 0;
  color: var(--primary-600);
  font: inherit;
  font-size: var(--fs-caption);
  cursor: pointer;
  padding: 0;
}
.bell__markall:hover { text-decoration: underline; }
.bell__list { max-block-size: 60vh; overflow-y: auto; }
.bell__all {
  display: block;
  text-align: center;
  padding: var(--space-3);
  border-block-start: 1px solid var(--border);
  color: var(--primary-600);
  font-size: var(--fs-caption);
  font-weight: 600;
}
.bell__all:hover { background: var(--surface-alt); text-decoration: none; }

/* Mobile: the 360px menu anchored to the (left-of-centre in RTL) bell overflows
   the viewport's opposite edge. Pin it inside both edges just below the header
   so it always fits. .bell stays relative so the count badge is unaffected. */
@media (max-width: 480px) {
  .bell__menu {
    position: fixed;
    inset-block-start: 64px;
    inset-inline: var(--space-3);
    inline-size: auto;
    max-inline-size: none;
  }
}

/* ==== 7.12 Chat bubbles ===================================================== */

.bubble {
  max-inline-size: 75%;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-md);
  font-size: var(--fs-body);
}
/* flat "tail" corner on the sender's side, logically (§7.12) */
.bubble--student {
  background: var(--primary-tint);
  border-end-end-radius: var(--space-1);
  margin-inline-start: auto;
}
.bubble--admin {
  background: var(--surface);
  border: 1px solid var(--border);
  border-end-start-radius: var(--space-1);
  margin-inline-end: auto;
}
.bubble__time {
  display: block;
  font-size: var(--fs-caption);
  color: var(--ink-3);
  margin-block-start: var(--space-1);
}

/* ==== Layout: site header / footer ========================================== */

.site-header {
  border-block-end: 1px solid var(--border);
  background: var(--bg);
}
.site-header__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  min-block-size: 64px;
}
.brand {
  font-weight: 700;
  font-size: var(--fs-h3);
  color: var(--ink);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  white-space: nowrap;
}
.brand:hover { text-decoration: none; }
.brand .icon { color: var(--icon-accent); }
.header-actions { display: flex; align-items: center; gap: var(--space-1); }
/* Guest nav buttons breathe a bit more than the icon buttons */
.header-actions .btn { margin-inline-end: var(--space-1); }
/* The logout form is chrome, not content — keep the flex row intact */
.header-logout { display: contents; }
.lang-switch { font-size: var(--fs-body-sm); font-weight: 500; }

/* 360px: keep brand + actions on one row. The ghost login link hides —
   login stays reachable from the hero, the register page and /login. */
@media (max-width: 420px) {
  .site-header__row { gap: var(--space-2); }
  .brand { font-size: var(--fs-body); }
  .header-actions .btn--sm { padding-inline: var(--space-2); }
  .header-login { display: none; }
}

/* theme toggle: show the icon of the mode you would switch TO */
html:not([data-theme="dark"]) .theme-icon--sun { display: none; }
html[data-theme="dark"] .theme-icon--moon { display: none; }

.site-footer {
  border-block-start: 1px solid var(--border);
  margin-block-start: var(--space-16);
  padding-block: var(--space-8);
  color: var(--ink-3);
  font-size: var(--fs-body-sm);
}
.site-footer__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

/* Page scaffolding */
.page-main { padding-block: var(--space-8) var(--space-12); }
