/*
 * Hang in There · Sitewide visual contract
 *
 * This file is intentionally loaded last on every HTML route. Legacy route
 * styles remain responsible for exercise-specific layout and behavior; this
 * layer owns shared type, spacing, surfaces, controls, focus and state
 * language so the site reads as one product.
 */

:root {
  --ui-bg: #f7f8fc;
  --ui-bg-subtle: #f1f3fa;
  --ui-surface: #ffffff;
  --ui-surface-subtle: #f8f8ff;
  --ui-ink: #17233d;
  --ui-muted: #667085;
  --ui-muted-strong: #526079;
  --ui-line: #e1e2ed;
  --ui-line-strong: #cfd5e3;
  --ui-accent: #6464c8;
  --ui-accent-dark: #4f4fa9;
  --ui-accent-soft: #eeeeff;
  /* Semantic states use a restrained, non-neon palette.  The foregrounds
     meet WCAG AA on their matching soft surfaces and on white controls;
     borders stay visible without relying on hue alone. */
  --ui-success: #356b56;
  --ui-success-soft: #e5f1eb;
  --ui-success-border: #b9d8c7;
  --ui-warning: #7f5a24;
  --ui-warning-soft: #f8efdd;
  --ui-warning-border: #e2cfa3;
  --ui-danger: #9f4f4c;
  --ui-danger-soft: #f6e8e6;
  --ui-danger-border: #e3c4c0;
  /* Explicit aliases make the state vocabulary easy to use in route CSS. */
  --ui-alert: var(--ui-warning);
  --ui-alert-soft: var(--ui-warning-soft);
  --ui-alert-border: var(--ui-warning-border);
  --ui-radius-sm: 10px;
  --ui-radius-md: 14px;
  --ui-radius-lg: 18px;
  --ui-radius-xl: 26px;
  --ui-control-height: 42px;
  --ui-content-width: 1180px;
  --ui-shell-gutter: 20px;
  --ui-shadow-card: 0 3px 12px rgba(40, 42, 77, .045);
  --ui-shadow-raised: 0 14px 34px rgba(55, 57, 105, .08);
  --ui-focus: 0 0 0 3px rgba(119, 119, 217, .24);
  --ui-ease: cubic-bezier(.23, 1, .32, 1);

  /* Legacy aliases keep route-specific CSS data-compatible. */
  --bg: var(--ui-bg);
  --bg2: #eef4fb;
  --panel: var(--ui-surface);
  --text: var(--ui-ink);
  --muted: var(--ui-muted);
  --line: var(--ui-line);
  --primary: var(--ui-accent);
  --primary-dark: var(--ui-accent-dark);
  --primary-soft: var(--ui-accent-soft);
  --lavender: var(--ui-accent);
  --lavender-soft: var(--ui-accent-soft);
  --success: var(--ui-success);
  --error: var(--ui-danger);
  --warning: var(--ui-warning);
  --mock-success: var(--ui-success);
  --mock-error: var(--ui-danger);
}

html,
body {
  min-width: 0;
}

body {
  background: var(--ui-bg) !important;
  color: var(--ui-ink) !important;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif !important;
  line-height: 1.5;
}

body :is(h1, h2, h3, h4) {
  color: var(--ui-ink);
  text-wrap: balance;
}

body :is(p, li) {
  text-wrap: pretty;
}

body :is(input, select, textarea) {
  font-family: inherit;
}

body :is(
  .navbar button,
  .auth-nav button,
  .home-actions button,
  .exam-actions button,
  .controls button,
  .practice-bottom-actions button,
  .email-practice-actions button,
  .email-toolbar-buttons button,
  .email-bottom-actions button,
  .mock-exam-actions button,
  .mock-setup-actions button,
  .mock-listening-controls button,
  .mock-speaking-top-actions button,
  .mock-speaking-recording button,
  .mock-speaking-nav button,
  .section-actions button,
  .finish-actions button,
  .control-row button,
  .analytics-actions button,
  .payment-review-actions button,
  .memberships-admin-actions button,
  .auth-switches button
) {
  font-family: inherit;
}

/* Page shells and the outer surfaces establish the same visual frame. */
body :is(.page-shell, .container, .page, .set-shell, .mock-shell, .mock-practice-shell, .mock-report-shell, .analytics-shell, .payments-admin-shell):not(:has(.listening-main)) {
  width: min(var(--ui-content-width), 100%);
  box-sizing: border-box;
  margin-left: auto;
  margin-right: auto;
}

body :is(.page-shell, .container, .page, .set-shell, .mock-shell, .mock-practice-shell, .mock-report-shell):not(:has(.listening-main)) {
  padding-inline: var(--ui-shell-gutter);
}

/* Shared auth.js measures the fixed navbar after each fragment mounts. Keep
   legacy route shells clear of every measured row, including standalone
   exercise documents that predate `.page-shell`. */
@media (max-width: 900px) {
  body :is(.container, .page, .set-shell, .reading-shell, .mock-work-shell) {
    padding-top: calc(var(--hang-nav-height, 66px) + 24px);
  }
}

/* Keep the legacy library aliases on the same contrast-safe accent pair. */
body :is(.reading-hub, .listening-hub, .speaking-hub, .writing-hub, .mock-hub) {
  --library-accent: var(--ui-accent);
  --library-accent-dark: var(--ui-accent-dark);
  --library-accent-soft: var(--ui-accent-soft);
  --writing-teal: var(--ui-accent);
  --writing-teal-soft: var(--ui-accent-soft);
}

body :is(.reading-hub, .listening-hub, .speaking-hub, .writing-hub, .discussion-page, .email-page, .mock-hub, .test-shell, .type-shell, .exam-card, .set-hero, .interview-hero) {
  border: 1px solid var(--ui-line);
  border-radius: var(--ui-radius-xl);
  background: var(--ui-surface);
  box-shadow: var(--ui-shadow-raised);
}

body :is(.reading-hub, .listening-hub, .speaking-hub, .writing-hub, .discussion-page, .email-page, .mock-hub) {
  overflow: hidden;
}

body :is(.reading-hub-header, .listening-hub-header, .speaking-hub-header, .writing-hub-header, .mock-hub-header, .discussion-header, .email-page-header) {
  color: var(--ui-ink);
}

body :is(.reading-hub-header, .listening-hub-header, .speaking-hub-header, .writing-hub-header, .mock-hub-header) {
  padding: 34px 40px 26px;
  border-bottom-color: var(--ui-line);
  background: radial-gradient(circle at 88% 18%, rgba(119, 119, 217, .12), transparent 23%), linear-gradient(135deg, #f8f8ff, #fff);
}

body :is(.reading-hub-header, .listening-hub-header, .speaking-hub-header, .writing-hub-header, .mock-hub-header) h1,
body :is(.discussion-header, .email-page-header) h1 {
  margin-top: 0;
  color: var(--ui-ink);
  font-size: clamp(34px, 4vw, 40px);
  line-height: 1.12;
  letter-spacing: -.035em;
}

body :is(.reading-hub-header, .listening-hub-header, .speaking-hub-header, .writing-hub-header, .mock-hub-header, .discussion-header, .email-page-header) p {
  color: var(--ui-muted);
}

body :is(.reading-panel, .listening-panel, .speaking-panel, .writing-panel, .mock-panel) {
  padding: 22px 40px 40px;
}

body :is(.reading-panel-head, .listening-panel-head, .speaking-panel-head, .writing-panel-head, .mock-panel-head) {
  margin-bottom: 18px;
}

body :is(.reading-panel-head, .listening-panel-head, .speaking-panel-head, .writing-panel-head, .mock-panel-head) h2 {
  margin: 0;
  color: var(--ui-ink);
  font-size: 25px;
  line-height: 1.25;
  letter-spacing: -.025em;
}

body :is(.reading-panel-head, .listening-panel-head, .speaking-panel-head, .writing-panel-head, .mock-panel-head) p {
  color: var(--ui-muted);
}

/* Card contract: same border, radius, shadow and title/meta rhythm. */
body :is(
  .card,
  .section-item,
  .module-tile,
  .record-row,
  .reading-card,
  .listening-list-grid .listening-card,
  .speaking-card,
  .writing-card,
  .email-card,
  .discussion-card,
  .discussion-single-card,
  .email-prompt-card,
  .email-compose-card,
  .question-card,
  .result-card,
  .review-item,
  .passage-card,
  .topic-card,
  .exam-card,
  .stage-panel,
  .score-panel,
  .lr-score-panel,
  .lr-overall-score,
  .lr-sentence-score-card,
  .mock-table-card,
  .mock-set-card,
  .mock-report-card,
  .mock-report-section,
  .mock-analysis-row,
  .analytics-stat,
  .analytics-panel,
  .payment-review-card,
  .history-card,
  .memberships-admin-toolbar
) {
  border-color: var(--ui-line);
  border-radius: var(--ui-radius-lg);
  box-shadow: var(--ui-shadow-card);
}

body :is(.reading-card, .listening-list-grid .listening-card, .speaking-card, .writing-card, .email-card, .discussion-card, .module-tile, .topic-card):hover {
  border-color: var(--ui-line-strong);
  box-shadow: var(--ui-shadow-raised);
}

body :is(.reading-card-title, .listening-list-grid .listening-card-title, .speaking-card-title, .writing-card-cn-title, .email-card-title, .writing-card-title, .discussion-card-title, .module-tile strong, .topic-card h3) {
  max-width: 100%;
  min-width: 0;
  color: var(--ui-ink);
  font-size: clamp(18px, 1.25vw, 20px);
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: -.012em;
  overflow-wrap: anywhere;
}

@media (max-width: 700px) {
  body :is(.reading-card-title, .listening-list-grid .listening-card-title, .speaking-card-title, .writing-card-cn-title, .email-card-title, .writing-card-title, .discussion-card-title) {
    font-size: 17px;
  }
}

body .reading-list-grid .reading-card {
  min-height: 154px;
}

@media (max-width: 700px) {
  body .reading-list-grid .reading-card {
    min-height: 138px;
  }
}

body :is(.reading-card-meta, .listening-list-grid .listening-card-meta, .speaking-card-meta, .writing-card-meta, .discussion-card-meta, .email-card-foot, .writing-card-foot, .topic-meta, .module-tile small) {
  color: var(--ui-muted);
  font-size: 12px;
}

body :is(.reading-card-foot, .listening-list-grid .listening-card-foot, .speaking-card-foot, .writing-card-foot, .email-card-foot) {
  border-top-color: var(--ui-line);
}

/* Kicker and note text are small, so keep them on the darker text role. */
body :is(.home-kicker, .panel-label, .library-hub-eyebrow, .analytics-kicker, .analytics-toolbar-label) {
  color: var(--ui-accent-dark);
}

body .analytics-panel-note {
  color: var(--ui-muted-strong);
}

body .mock-report-empty-badge {
  color: var(--ui-accent-dark);
}

body :is(.reading-type-tab, .listening-type-tab, .speaking-type-tab, .writing-type-tab):not(.active) :is(.library-tab-index, .writing-tab-index, strong, small) {
  color: var(--ui-muted-strong);
}

body :is(.reading-type-tab, .listening-type-tab, .speaking-type-tab, .writing-type-tab) small {
  color: var(--ui-muted-strong);
}

/* Buttons, tabs and form controls. */
body :is(.primary-btn, .secondary-btn, .primary-action, .secondary-action, .primary-action-link, .secondary-action-link, .practice-btn, .start-btn, .finish-action, .lr-score-btn, .email-nav-btn, .email-tool-btn, .home-primary-action, .home-secondary-action, .home-refresh, .mock-primary, .mock-secondary, .mock-full-start, .mock-section-start, .mock-report-start, .mock-reset, .mock-hero-link, .listening-next-btn, .listening-start-btn, .small-btn, .btn-main, .btn-next, .btn-retry, .btn-exit, .nav-btn, .analytics-range, .analytics-refresh, .payments-admin-refresh, .memberships-admin-search-button,
  .navbar button,
  .auth-nav button,
  .home-actions button,
  .exam-actions button,
  .controls button,
  .practice-bottom-actions button,
  .email-practice-actions button,
  .email-toolbar-buttons button,
  .email-bottom-actions button,
  .mock-exam-actions button,
  .mock-setup-actions button,
  .mock-listening-controls button,
  .mock-speaking-top-actions button,
  .mock-speaking-recording button,
  .mock-speaking-nav button,
  .section-actions button,
  .finish-actions button,
  .control-row button,
  .analytics-actions button,
  .payment-review-actions button,
  .memberships-admin-actions button,
  .auth-switches button) {
  min-height: var(--ui-control-height);
  border-radius: var(--ui-radius-md);
  border-width: 1px;
  font-size: 14px;
  font-weight: 800;
  line-height: 1.2;
  transition: transform 160ms var(--ui-ease), background-color 180ms ease, border-color 180ms ease, color 180ms ease, box-shadow 180ms var(--ui-ease), opacity 180ms ease;
}

body :is(
  .navbar button,
  .auth-nav button,
  .home-actions button,
  .exam-actions button,
  .controls button,
  .practice-bottom-actions button,
  .email-practice-actions button,
  .email-toolbar-buttons button,
  .email-bottom-actions button,
  .mock-exam-actions button,
  .mock-setup-actions button,
  .mock-listening-controls button,
  .mock-speaking-top-actions button,
  .mock-speaking-recording button,
  .mock-speaking-nav button,
  .section-actions button,
  .finish-actions button,
  .control-row button,
  .analytics-actions button,
  .payment-review-actions button,
  .memberships-admin-actions button,
  .auth-switches button,
  [role="tab"],
  .nav-links a,
  .top-link,
  .back-link,
  .back,
  .mock-report-tab,
  .mock-section-tabs a,
  .mock-mode-tab
):focus-visible,
body :is(input, textarea, select):focus-visible,
body [role="tab"]:focus-visible {
  outline: 0;
  box-shadow: var(--ui-focus);
}

body :is(
  .navbar button,
  .auth-nav button,
  .home-actions button,
  .exam-actions button,
  .controls button,
  .practice-bottom-actions button,
  .email-practice-actions button,
  .email-toolbar-buttons button,
  .email-bottom-actions button,
  .mock-exam-actions button,
  .mock-setup-actions button,
  .mock-listening-controls button,
  .mock-speaking-top-actions button,
  .mock-speaking-recording button,
  .mock-speaking-nav button,
  .section-actions button,
  .finish-actions button,
  .control-row button,
  .analytics-actions button,
  .payment-review-actions button,
  .memberships-admin-actions button,
  .auth-switches button,
  .nav-links a,
  .auth-nav button,
  .top-link,
  .back-link,
  .back,
  .mock-report-tab,
  .mock-section-tabs a,
  .mock-mode-tab
):active {
  transform: scale(.98);
}

body :is(input, textarea, select) {
  border: 1px solid var(--ui-line-strong);
  border-radius: var(--ui-radius-sm);
  color: var(--ui-ink);
  background: var(--ui-surface);
}

body :is(input, textarea, select):focus {
  border-color: var(--ui-accent);
  outline: 0;
  box-shadow: var(--ui-focus);
}

body :is(.primary-btn, .primary-action, .primary-action-link, .practice-btn, .start-btn, .finish-action, .lr-score-btn, .email-nav-btn.primary, .email-tool-btn.primary, .home-primary-action, .mock-primary, .mock-full-start, .listening-next-btn, .listening-start-btn, .btn-main, .btn-next, .primary-btn) {
  border-color: var(--ui-accent);
  background: var(--ui-accent);
  color: #fff;
  box-shadow: 0 8px 18px rgba(119, 119, 217, .18);
}

body :is(.secondary-btn, .secondary-action, .secondary-action-link, .home-secondary-action, .home-refresh, .mock-secondary, .mock-reset, .mock-hero-link, .light-btn, .email-nav-btn.secondary, .email-tool-btn.light, .btn-exit, .small-btn, .analytics-refresh) {
  border-color: var(--ui-line);
  background: var(--ui-bg-subtle);
  color: var(--ui-muted-strong);
  box-shadow: none;
}

body :is(.danger-btn, .mock-analysis-row.wrong button, .payment-review-reject, .membership-admin-revoke) {
  border-color: var(--ui-danger);
  background: var(--ui-danger);
  color: #fff;
}

body :is(.auth-submit, .payment-submit, .payments-admin-refresh, .memberships-admin-search-button) {
  border: 1px solid var(--ui-accent);
  background: var(--ui-accent);
  color: #fff;
}

/* Status and score language. */
body :is(.email-card-tag, .email-card-status, .question-number, .progress-pill, .score-pill, .lr-score-pill, .mock-report-empty-badge, .mock-analysis-head span, .membership-status, .listening-soft-pill, .badge) {
  border-radius: 999px;
}

body :is(.email-card-status.draft, .membership-status.active, .mock-analysis-row.correct .mock-analysis-head span) {
  background: var(--ui-success-soft);
  color: var(--ui-success);
}

body :is(.email-card-status.empty, .membership-status.none, .mock-report-section.disabled, .mock-report-tab.disabled, .mock-report-start.unavailable) {
  background: var(--ui-bg-subtle);
  color: var(--ui-muted);
}

body :is(.membership-status.expired, .mock-analysis-explanation-state--pending) {
  background: var(--ui-warning-soft);
  color: var(--ui-warning);
}

body :is(.membership-status.revoked, .mock-analysis-row.wrong .mock-analysis-head span, .analytics-status.error, .payments-admin-status.error) {
  background: var(--ui-danger-soft);
  color: var(--ui-danger);
}

body :is(.result-card, .result-box, .final-result, .review-card, .ai-score-box, .mock-report-overall-status, .mock-analysis-score) {
  background: var(--ui-surface-subtle);
  border: 1px solid var(--ui-line);
  border-radius: var(--ui-radius-lg);
  color: var(--ui-ink);
}

body :is(.result-score, .final-score, .band-score, .lr-band, .mock-analysis-score, .mock-report-section-score, .week-total) {
  color: var(--ui-accent-dark);
  font-variant-numeric: tabular-nums;
}

body :is(.locked, .access-blocked, .unavailable) {
  border-color: var(--ui-line-strong);
}

/* Paid cards keep their learning state visible while using a restrained
   membership signal. The badge is intentionally small so scores, drafts,
   and completion states remain the visual priority. */
body :is(.reading-card.access-blocked,
  .listening-list-grid .listening-card.access-blocked,
  .lr-set.access-blocked,
  .speaking-card.access-blocked,
  .writing-card.access-blocked,
  .email-card.access-blocked,
  .bs-set-row.access-blocked,
  .discussion-card.access-blocked) {
  border-color: #d9bd7d;
  background: linear-gradient(145deg, #fffdf7 0%, #fffaf0 100%);
}

body :is(.reading-card.access-blocked,
  .listening-list-grid .listening-card.access-blocked,
  .speaking-card.access-blocked,
  .writing-card.access-blocked,
  .email-card.access-blocked):hover {
  border-color: #c9a85d;
  box-shadow: 0 12px 28px rgba(151, 111, 36, .12);
}

@media (prefers-reduced-motion: reduce) {
  body :is(.reading-card.access-blocked,
    .listening-list-grid .listening-card.access-blocked,
    .speaking-card.access-blocked,
    .writing-card.access-blocked,
    .email-card.access-blocked):hover {
    transform: none;
  }
}

/* Admin surfaces are the same product, not a second visual language. */
body :is(.analytics-shell, .payments-admin-shell) {
  padding-top: calc(var(--hang-nav-height, 66px) + 30px);
  padding-bottom: 72px;
}

body :is(.analytics-hero, .payments-admin-hero) {
  border-color: var(--ui-line);
  border-radius: var(--ui-radius-xl);
  background: linear-gradient(135deg, #fff 0%, var(--ui-surface-subtle) 100%);
  box-shadow: var(--ui-shadow-raised);
}

body :is(.analytics-kicker, .analytics-toolbar-label, .analytics-hero .analytics-kicker) {
  color: var(--ui-accent-dark);
}

body :is(.analytics-status, .payments-admin-status, .memberships-admin-status) {
  border-radius: var(--ui-radius-md);
  color: var(--ui-muted);
}

body :is(.analytics-actions, .memberships-admin-toolbar, .payments-admin-guide) {
  border-color: var(--ui-line);
  border-radius: var(--ui-radius-md);
  background: var(--ui-bg-subtle);
}

body :is(.analytics-panel h2, .analytics-membership-header h2, .payments-admin-hero h1, .history-head h1) {
  color: var(--ui-ink);
  letter-spacing: -.025em;
}

/* Exercise chrome stays coherent while content keeps its domain-specific size. */
body :is(.exam-topbar, .email-practice-topbar, .mock-exam-toolbar, .mock-work-head, .listening-exam-topbar, .toolbar, .history-head) {
  color: var(--ui-ink);
}

body :is(.timer, .email-timer, .listening-timer, .mock-listening-timer, .mock-writing-timer, .reading-timer, .progress-pill, .timer-pill) {
  min-height: 38px;
  border: 1px solid var(--ui-line);
  border-radius: 999px;
  background: var(--ui-accent-soft);
  color: var(--ui-accent-dark);
  font-variant-numeric: tabular-nums;
}

body :is(.review-item.correct, .option.correct, .option-row.correct, .mock-analysis-row.correct) {
  border-color: #b7e4c7;
  background: var(--ui-success-soft);
}

body :is(.review-item.wrong, .option.incorrect, .option-row.wrong, .mock-analysis-row.wrong) {
  border-color: #f3c2cc;
  background: var(--ui-danger-soft);
}

/* Shared one-question-at-a-time review contract. The index stays a compact
   horizontal control on narrow screens; only the selected explanation is in
   the document flow so long answer lists do not become scroll traps. */
body .review-index-heading {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin: 0 0 10px;
  color: var(--ui-ink);
  font-size: 15px;
}

/* Keep the compact index available while a selected explanation grows below.
   The solid surface is the reduced-transparency fallback; the blended surface
   keeps the sticky chrome quiet without letting text show through it. */
body .review-index-header {
  position: sticky;
  top: calc(var(--hang-nav-height, 64px) + 8px);
  z-index: 5;
  margin: -8px -2px 0;
  padding: 8px 2px 2px;
  border-bottom: 1px solid var(--ui-line);
  background: var(--ui-surface);
  background: color-mix(in srgb, var(--ui-surface) 94%, transparent);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

body .review-index-root {
  scroll-margin-top: calc(var(--hang-nav-height, 64px) + 12px);
}

body .review-index-host {
  overflow: visible;
}

body .review-index-label {
  font-weight: 900;
}

body .review-index-nav {
  min-width: 0;
}

body .review-index-scroll {
  display: flex;
  gap: 8px;
  max-width: 100%;
  min-width: 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  padding: 4px 3px 9px;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}

body .review-index-btn {
  flex: 0 0 auto;
  min-width: 43px;
  height: 36px;
  padding: 0 10px;
  border: 1px solid #bbf7d0;
  border-radius: 11px;
  background: #f0fdf4;
  color: #15803d;
  cursor: pointer;
  font: inherit;
  font-size: 13px;
  font-weight: 900;
  line-height: 1;
  transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease, box-shadow 120ms ease, transform 120ms ease-out;
}

body .review-index-btn.is-wrong {
  border-color: #fecaca;
  background: #fef2f2;
  color: #b91c1c;
}

body .review-index-btn.is-unanswered {
  border-color: #cbd5e1;
  background: #f8fafc;
  color: #64748b;
}

body .review-index-btn.is-pending {
  border-color: #fde68a;
  background: #fffbeb;
  color: #b45309;
}

body .review-index-btn.is-neutral {
  border-color: #c7d2fe;
  background: #eef2ff;
  color: #4338ca;
}

body .review-index-btn[aria-current="true"] {
  border-color: var(--ui-accent-dark);
  box-shadow: var(--ui-focus);
}

body .review-index-btn:focus-visible {
  outline: 3px solid rgba(119, 119, 217, .35);
  outline-offset: 2px;
}

body .review-index-btn:active {
  transform: scale(.97);
}

body .review-question-panel {
  margin-top: 18px;
  min-width: 0;
  scroll-margin-top: calc(var(--hang-nav-height, 64px) + 76px);
}

/* Reading review contract: keep the original stem and every choice in the
   result flow. Selection/correctness uses labels plus borders/surfaces so a
   muted palette never makes state depend on color alone. */
body .review-options {
  display: grid;
  gap: 8px;
  margin: 14px 0 16px;
}

body .review-option {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
  padding: 10px 12px;
  border: 1px solid var(--ui-line);
  border-radius: 10px;
  background: var(--ui-surface);
  color: var(--ui-ink);
  line-height: 1.55;
}

body .review-option.is-selected {
  border-color: var(--ui-accent);
  box-shadow: inset 3px 0 0 var(--ui-accent);
}

body .review-option.is-correct {
  border-color: var(--ui-success-border);
  background: var(--ui-success-soft);
  box-shadow: inset 3px 0 0 var(--ui-success);
}

body .review-option.is-wrong {
  border-color: var(--ui-danger-border);
  background: var(--ui-danger-soft);
  box-shadow: inset 3px 0 0 var(--ui-danger);
}

body .review-option-letter {
  font-weight: 900;
  color: var(--ui-ink-muted);
}

body .review-option-text {
  min-width: 0;
  overflow-wrap: anywhere;
}

body .review-option-state {
  color: var(--ui-ink-muted);
  font-size: 12px;
  font-weight: 900;
  white-space: nowrap;
}

body .review-vocabulary {
  margin: 14px 0;
  padding: 12px 14px;
  border: 1px solid var(--ui-line);
  border-radius: 12px;
  background: var(--ui-surface-soft, #f8fafc);
  color: var(--ui-ink);
  line-height: 1.6;
}

body .review-vocabulary-options {
  margin-top: 8px;
  display: grid;
  gap: 4px;
}

body .review-result-toolbar {
  justify-content: flex-end;
  margin-top: 0;
}

@media (max-width: 600px) {
  body .review-option {
    grid-template-columns: 24px minmax(0, 1fr);
  }

  body .review-option-state {
    grid-column: 2;
    white-space: normal;
  }

  body .review-result-toolbar {
    justify-content: stretch;
  }

  body .review-result-toolbar > a {
    flex: 1 1 100%;
  }
}

body .review-question-heading {
  display: inline-flex;
  margin-bottom: 10px;
  padding: 6px 10px;
  border-radius: 999px;
  background: var(--ui-accent-soft);
  color: var(--ui-accent-dark);
  font-size: 13px;
  font-weight: 900;
}

body .review-status {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--ui-success-soft);
  color: var(--ui-success);
  font-size: 13px;
  font-weight: 900;
}

body .review-status.is-wrong {
  background: var(--ui-danger-soft);
  color: var(--ui-danger);
}

body .review-status.is-pending {
  background: var(--ui-warning-soft);
  color: var(--ui-warning);
}

body .review-status.is-unanswered {
  background: #f8fafc;
  color: #64748b;
}

body .review-status.is-neutral {
  background: var(--ui-accent-soft);
  color: var(--ui-accent-dark);
}

/* Semantic state contract -------------------------------------------------
 *
 * Route styles predate the shared layer and use several different reds and
 * greens.  Keep the state names and interactions intact, but make their
 * visual language consistent.  A result state always has at least two cues
 * (surface + border, and where useful a dark label or status mark), so color
 * is never the only signal.
 */

/* Correct / success: muted forest + pale mint. */
body :is(
  .review-item.correct,
  .option.correct,
  .option-row.correct,
  .mock-analysis-row.correct,
  .review-option.correct,
  .choice.correct,
  .answer-btn.correct,
  .mock-answer-btn.correct,
  .mock-listening-options li.correct,
  .mock-listening-option.correct,
  .bs-item.correct,
  .lr-item.correct,
  .char-input.correct,
  .mock-writing-task.correct,
  .review-index-btn:not(.is-wrong):not(.is-unanswered):not(.is-pending):not(.is-neutral)
) {
  border-color: var(--ui-success-border);
  background: var(--ui-success-soft);
}

body :is(.review-item.correct, .mock-analysis-row.correct, .mock-writing-task.correct) {
  border-left-color: var(--ui-success);
}

body :is(
  .review-index-btn:not(.is-wrong):not(.is-unanswered):not(.is-pending):not(.is-neutral),
  .review-status,
  .review-status.ok,
  .answer-btn.correct,
  .mock-answer-btn.correct,
  .bs-item.correct,
  .lr-item.correct,
  .correct-text,
  .auth-message.success,
  .feedback-message.success,
  .feedback-admin-edit-status.success,
  .payment-status.success,
  .feedback-admin-summary-reply.is-replied,
  .status-resolved,
  .membership-status.active,
  .mock-writing-task.correct .mock-writing-result,
  .mock-scoring-status[data-status="scored"]
) {
  color: var(--ui-success);
}

body :is(
  .auth-notice:not(.error),
  .payments-admin-status.success,
  .membership-status.active,
  .status-resolved,
  .mock-scoring-status[data-status="scored"],
  .mock-speaking-complete
) {
  border-color: var(--ui-success-border);
  background: var(--ui-success-soft);
}

body :is(.char-input.filled.correct) {
  border-bottom-color: transparent;
  box-shadow: inset 0 -1px var(--ui-success);
  color: var(--ui-success);
}

body :is(
  .mock-analysis-row.correct .mock-analysis-head span,
  .mock-listening-options li.correct
) {
  background: var(--ui-success-soft);
  color: var(--ui-success);
}

body .mock-listening-option.correct .letter {
  border-color: var(--ui-success);
  background: var(--ui-success);
  color: #fff;
}

/* Wrong / error / destructive: muted brick + pale rose-gray. */
body :is(
  .review-item.wrong,
  .option.incorrect,
  .option.wrong,
  .option-row.wrong,
  .mock-analysis-row.wrong,
  .review-option.wrong,
  .review-option.user-wrong,
  .choice.wrong,
  .answer-btn.wrong,
  .mock-answer-btn.wrong,
  .mock-listening-options li.wrong,
  .mock-listening-option.wrong,
  .bs-item.wrong,
  .lr-item.wrong,
  .char-input.wrong,
  .mock-writing-task.wrong,
  .review-index-btn.is-wrong,
  .review-status.is-wrong,
  .review-status.no,
  .mock-scoring-status[data-status="failed"],
  .mock-speaking-error,
  .result.wrong
) {
  border-color: var(--ui-danger-border);
  background: var(--ui-danger-soft);
}

body :is(.review-item.wrong, .mock-analysis-row.wrong, .mock-writing-task.wrong) {
  border-left-color: var(--ui-danger);
}

body :is(
  .review-index-btn.is-wrong,
  .review-status.is-wrong,
  .review-status.no,
  .answer-btn.wrong,
  .mock-answer-btn.wrong,
  .bs-item.wrong,
  .lr-item.wrong,
  .auth-message.error,
  .auth-notice.error,
  .feedback-message.error,
  .feedback-error-text,
  .feedback-admin-status.error,
  .feedback-admin-edit-status.error,
  .payment-status.error,
  .payment-intro.error,
  .payments-admin-status.error,
  .analytics-status.error,
  .membership-status.revoked,
  .mock-writing-task.wrong .mock-writing-result,
  .mock-speaking-status.error,
  .mock-scoring-status[data-status="failed"],
  .mock-speaking-error,
  .result.wrong
) {
  color: var(--ui-danger);
}

body :is(.auth-notice.error, .payments-admin-status.error, .mock-scoring-status[data-status="failed"], .mock-speaking-error) {
  border-color: var(--ui-danger-border);
  background: var(--ui-danger-soft);
}

body :is(.char-input.filled.wrong) {
  border-bottom-color: transparent;
  box-shadow: inset 0 -1px var(--ui-danger);
  color: var(--ui-danger);
}

body :is(.mock-analysis-row.wrong .mock-analysis-head span, .mock-listening-options li.wrong) {
  background: var(--ui-danger-soft);
  color: var(--ui-danger);
}

body .mock-listening-option.wrong .letter {
  border-color: var(--ui-danger);
  background: var(--ui-danger);
  color: #fff;
}

/* Alert / pending: muted amber + pale parchment. */
body :is(
  .option.pending,
  .review-index-btn.is-pending,
  .review-status.is-pending,
  .membership-status.expired,
  .status-in_progress,
  .mock-analysis-explanation-state--pending,
  .mock-scoring-status[data-status="pending"],
  .mock-scoring-status[data-status="processing"]
) {
  border-color: var(--ui-alert-border);
  background: var(--ui-alert-soft);
  color: var(--ui-alert);
}

body :is(.feedback-message.warning, .analytics-status.loading, .feedback-admin-status.loading) {
  color: var(--ui-alert);
}

body .analytics-status.loading::before,
body .feedback-admin-status.loading::before {
  background: var(--ui-alert);
  box-shadow: 0 0 0 4px var(--ui-alert-soft);
}

body .analytics-status.error::before,
body .feedback-admin-status.error::before {
  background: var(--ui-danger);
  box-shadow: 0 0 0 4px var(--ui-danger-soft);
}

body .analytics-status.success::before,
body .feedback-admin-status.success::before {
  background: var(--ui-success);
  box-shadow: 0 0 0 4px var(--ui-success-soft);
}

body .review-detail-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 18px;
}

body .review-detail-actions a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  padding: 8px 14px;
  border: 1px solid var(--ui-line);
  border-radius: 999px;
  background: var(--ui-surface);
  color: var(--ui-accent-dark);
  font-size: 14px;
  font-weight: 900;
  text-decoration: none;
}

body .review-detail-actions a.primary {
  border-color: var(--ui-accent);
  background: var(--ui-accent);
  color: #fff;
}

@media (max-width: 600px) {
  body .review-index-heading {
    align-items: flex-start;
    flex-direction: column;
    gap: 4px;
  }
}

@media (prefers-reduced-transparency: reduce) {
  body .review-index-header {
    background: var(--ui-surface);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

/* Deliberate exception: audio / recording / reading content can remain roomy. */
body :is(audio, .listening-audio, .mock-analysis-audio, .mock-audio, .audio-dock) {
  max-width: 100%;
}

body :is(.email-textarea, .essay-input, textarea) {
  max-width: 100%;
  box-sizing: border-box;
}

@media (max-width: 900px) {
  body :is(.reading-panel, .listening-panel, .speaking-panel, .writing-panel, .mock-panel) {
    padding-left: 24px;
    padding-right: 24px;
  }

  body :is(.reading-hub-header, .listening-hub-header, .speaking-hub-header, .writing-hub-header, .mock-hub-header) {
    padding-left: 24px;
    padding-right: 24px;
  }
}

@media (max-width: 700px) {
  body :is(.reading-hub, .listening-hub, .speaking-hub, .writing-hub, .discussion-page, .email-page, .mock-hub, .exam-card, .set-hero, .interview-hero) {
    border-radius: 22px;
  }

  body :is(.reading-hub-header, .listening-hub-header, .speaking-hub-header, .writing-hub-header, .mock-hub-header) {
    padding: 26px 20px 20px;
  }

  body :is(.reading-panel, .listening-panel, .speaking-panel, .writing-panel, .mock-panel) {
    padding: 18px 20px 26px;
  }

  body :is(.reading-hub-header, .listening-hub-header, .speaking-hub-header, .writing-hub-header, .mock-hub-header, .discussion-header, .email-page-header) h1 {
    font-size: 34px;
  }

  body :is(.analytics-shell, .payments-admin-shell) {
    padding: 82px var(--ui-shell-gutter) 56px;
  }

  body :is(.analytics-hero, .payments-admin-hero) {
    border-radius: 22px;
  }

  body :is(.analytics-panel, .analytics-stat, .payment-review-card, .history-card, .memberships-admin-toolbar) {
    border-radius: var(--ui-radius-lg);
  }

  body :is(.analytics-actions, .memberships-admin-toolbar, .payments-admin-guide) {
    width: 100%;
  }
}

@media (prefers-reduced-motion: reduce) {
  body :is(
    .navbar button,
    .auth-nav button,
    .home-actions button,
    .exam-actions button,
    .controls button,
    .practice-bottom-actions button,
    .email-practice-actions button,
    .email-toolbar-buttons button,
    .email-bottom-actions button,
    .mock-exam-actions button,
    .mock-setup-actions button,
    .mock-listening-controls button,
    .mock-speaking-top-actions button,
    .mock-speaking-recording button,
    .mock-speaking-nav button,
    .section-actions button,
    .finish-actions button,
    .control-row button,
    .analytics-actions button,
    .payment-review-actions button,
    .memberships-admin-actions button,
    .auth-switches button,
    .nav-links a,
    .top-link,
    .back-link,
    .back,
    .mock-report-tab,
    .mock-section-tabs a,
    .mock-mode-tab,
    .card,
    .reading-card,
    .listening-card,
    .speaking-card,
    .writing-card,
    .email-card,
    .discussion-card,
    .module-tile,
    .record-row,
    .review-index-btn,
    .review-detail-actions a
  ) {
    transition-duration: 1ms !important;
  }
}
