/* =========================================================================
   Banco de Questões — Design System
   CSS artesanal com variáveis (sem build Node). Mobile-first.
   Todo o CSS usa apenas tokens semânticos (var(--c-*)); as cores literais
   vivem exclusivamente nos blocos de tema abaixo.
   ========================================================================= */

/* ---------- Tokens de marca — Bela Concurseira (Serene Academic Floral) ----
   Marca única (paleta floral clara). Ver docs/design-system.md.
   Regra: nunca preto puro — cinzas quentes p/ texto; ações em #b57f72.
   -------------------------------------------------------------------------- */

:root {
  color-scheme: light;
  --c-bg: #faf7f8;               /* neutro off-pink (base) */
  --c-surface: #ffffff;          /* cards e menus */
  --c-surface-2: #f6f3f4;        /* hover / seção aninhada */
  --c-text: #1b1b1c;             /* on-surface (cinza quase-preto quente) */
  --c-text-muted: #786a70;       /* cinza-malva */
  --c-border: #d6c1c6;           /* outline-variant (borda rosada suave) */
  --c-primary: #ac627e;          /* deep rose/burgundy — CTAs, ativo, marca */
  --c-primary-hover: #955268;
  --c-primary-contrast: #ffffff;
  --c-primary-text: #874560;     /* texto pequeno sobre --c-primary-soft (AA: 5,1:1; o primary dá 3,3) */
  --c-primary-soft: #f4d7e0;     /* rosa pálida — chips / ativo / aninhado */
  --c-marked: #f6e9d9;           /* creme — a alternativa que o aluno MARCOU (e segue assim depois de corrigida) */
  --c-secondary: #e8b4c3;        /* dusty rose (tertiary) — borda de input, hover, 2ário */
  --c-success: #7a9b6e;          /* acerto = verde sálvia — preenchimentos, barras, bordas */
  --c-success-text: #4f6b45;     /* texto/ícone de acerto (o verde puro não atinge 4.5:1) */
  --c-success-soft: #e4ece0;     /* fundo suave de acerto */
  --c-danger: #ba1a1a;           /* error */
  --c-danger-contrast: #ffffff;  /* texto sobre --c-danger */
  --c-warning: #c99a3f;          /* "pendentes" nos gráficos (fora do DESIGN.md) */
  --c-warning-soft: #f6ecd6;     /* fundo suave de "pendentes" nos gráficos */
  /* Paleta de DESTAQUE do texto de produto (as únicas cores que o admin aplica
     a uma palavra — ver HtmlSanitizer::PRODUCT_CLASSES). Tokens próprios, e não
     reuso de --c-primary-text/--c-success-text, para mexer no chip amanhã não
     mudar, em silêncio, o texto vendido na loja. */
  --c-dest-rosa: #874560;
  --c-dest-verde: #4f6b45;
  --c-dest-ambar: #7d5a10;       /* o --c-warning puro dá 2,4:1 sobre o fundo */
  --c-dest-grifo: #f6ecd6;       /* fundo do grifo (o texto segue em --c-text) */
  --c-shadow: rgba(172, 98, 126, 0.10);  /* sombra tingida de primary */
  --c-img-frame: #ffffff;        /* moldura de 8px da imagem de questão — BRANCA nos três temas, de propósito */
  --c-img-veil: #faf7f81a;       /* o próprio --c-bg com 10% de véu (0x1a = 26/255) sobre a imagem e a moldura */
  --radius-card: 24px;
  --radius-control: 20px;        /* Shapes: standard elements 20px */
  /* Caret do <select> nativo (cor literal: data-URI não lê var()) */
  --select-caret: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23786a70' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* ---------- Tema escuro (plum quente, derivado da paleta floral) ------------
   Preferência ternária (ver App\Support\Theme): claro = :root acima (sem
   bloco próprio) · escuro = bloco abaixo · auto = mesmo bloco, mas só quando
   o aparelho está em dark mode (@media prefers-color-scheme).
   ATENÇÃO: os DOIS blocos são idênticos de propósito — sem preprocessador não
   dá para agrupar seletores através da fronteira do @media. Toda alteração de
   token escuro precisa ser feita NOS DOIS. --------------------------------- */

:root[data-theme="escuro"] {
  color-scheme: dark;
  --c-bg: #211a1e;               /* plum quase-preto quente (irmão do #faf7f8) */
  --c-surface: #2a2227;          /* cards e menus */
  --c-surface-2: #342b31;        /* hover / seção aninhada */
  --c-text: #f0e7eb;             /* off-white rosado */
  --c-text-muted: #b5a4ad;       /* malva claro */
  --c-border: #55454d;
  --c-primary: #dfa1b8;          /* rosa da marca clareado/dessaturado */
  --c-primary-hover: #eab7ca;
  --c-primary-contrast: #43202f; /* plum profundo — texto sobre primary */
  --c-primary-text: #dfa1b8;     /* no escuro o próprio primary já passa (5,7:1 sobre o soft) */
  --c-primary-soft: #4a2d3a;
  --c-marked: #46382a;           /* creme → castanho quente */
  --c-secondary: #8f6273;
  --c-success: #93b586;
  --c-success-text: #b9d5ac;
  --c-success-soft: #2c372a;
  --c-danger: #f2988f;
  --c-danger-contrast: #3d0f0c;
  --c-warning: #e0b25c;
  --c-warning-soft: #423622;
  --c-dest-rosa: #dfa1b8;
  --c-dest-verde: #b9d5ac;
  --c-dest-ambar: #e8c887;
  --c-dest-grifo: #423622;
  --c-shadow: rgba(0, 0, 0, 0.35);  /* sombra tingida sumiria no escuro */
  --c-img-veil: #211a1e40;       /* o próprio --c-bg escuro com 25% de véu (0x40 = 64/255) — mais que o claro, é onde o branco pesa */
  --logo-filter: brightness(1.5);   /* clareia o traço vinho do PNG da marca */
  --select-caret: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23b5a4ad' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

@media (prefers-color-scheme: dark) {
  /* ATENÇÃO: cópia exata do bloco acima — alterar os DOIS. */
  :root[data-theme="auto"] {
    color-scheme: dark;
    --c-bg: #211a1e;
    --c-surface: #2a2227;
    --c-surface-2: #342b31;
    --c-text: #f0e7eb;
    --c-text-muted: #b5a4ad;
    --c-border: #55454d;
    --c-primary: #dfa1b8;
    --c-primary-hover: #eab7ca;
    --c-primary-contrast: #43202f;
    --c-primary-text: #dfa1b8;
    --c-primary-soft: #4a2d3a;
    --c-marked: #46382a;
    --c-secondary: #8f6273;
    --c-success: #93b586;
    --c-success-text: #b9d5ac;
    --c-success-soft: #2c372a;
    --c-danger: #f2988f;
    --c-danger-contrast: #3d0f0c;
    --c-warning: #e0b25c;
    --c-warning-soft: #423622;
    --c-dest-rosa: #dfa1b8;
    --c-dest-verde: #b9d5ac;
    --c-dest-ambar: #e8c887;
    --c-dest-grifo: #423622;
    --c-shadow: rgba(0, 0, 0, 0.35);
    --c-img-veil: #211a1e40;       /* o próprio --c-bg escuro com 25% de véu (0x40 = 64/255) — mais que o claro, é onde o branco pesa */
    --logo-filter: brightness(1.5);
    --select-caret: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23b5a4ad' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  }
}

/* ---------- Reset / base -------------------------------------------------- */

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

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

body {
  font-family: "Quicksand", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  background-color: var(--c-bg);
  color: var(--c-text);
  line-height: 1.6;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  transition: background-color 0.2s ease, color 0.2s ease;
}

a {
  color: var(--c-primary);
  text-decoration: none;
}
a:hover { text-decoration: underline; }

img { max-width: 100%; height: auto; display: block; }

h1, h2, h3, h4 { line-height: 1.25; font-weight: 700; color: var(--c-text); }
h1 { font-size: 1.75rem; }
h2 { font-size: 1.4rem; }
h3 { font-size: 1.15rem; }

@media (min-width: 768px) {
  h1 { font-size: 2.25rem; }
  h2 { font-size: 1.7rem; }
}

/* ---------- Layout -------------------------------------------------------- */

.container {
  width: 100%;
  max-width: 1080px;
  margin: 0 auto;
  padding: 0 1rem;
}

.main {
  flex: 1 0 auto;
  padding: 1.5rem 0;
}

.stack > * + * { margin-top: 1rem; }

.grid { display: grid; gap: 1rem; }
/* Itens de grid encolhem abaixo do conteúdo (min-width padrão = auto travaria
   a coluna na largura intrínseca do canvas dos gráficos → transbordo ao
   estreitar a largura do conteúdo). Sem isto, a coluna do Chart.js não recua. */
.grid > * { min-width: 0; }
@media (min-width: 768px) {
  .grid-2 { grid-template-columns: repeat(2, 1fr); }
  .grid-3 { grid-template-columns: repeat(3, 1fr); }
}

.text-center { text-align: center; }
.text-muted { color: var(--c-text-muted); }
.mt-1 { margin-top: 0.5rem; }
.mt-2 { margin-top: 1rem; }
.mt-3 { margin-top: 1.5rem; }
.mb-2 { margin-bottom: 1rem; }

/* ---------- Navbar (responsiva) ------------------------------------------ */

.navbar {
  background-color: var(--c-surface);
  border-bottom: 1px solid var(--c-border);
  position: sticky;
  top: 0;
  z-index: 50;
}

.navbar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 60px;
}

.navbar__brand {
  font-weight: 800;
  font-size: 1.15rem;
  color: var(--c-text);
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.navbar__brand:hover { text-decoration: none; }
.navbar__brand .dot {
  width: 12px; height: 12px; border-radius: 50%;
  background-color: var(--c-primary);
}

.navbar__toggle {
  display: inline-flex;
  background: none;
  border: 1px solid var(--c-border);
  border-radius: 8px;
  padding: 0.4rem 0.6rem;
  color: var(--c-text);
  cursor: pointer;
  font-size: 1.2rem;
  line-height: 1;
}

.navbar__menu {
  display: none;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0.5rem 0 1rem;
}
.navbar__menu.is-open { display: flex; }

.navbar__menu a,
.navbar__menu .navlink {
  color: var(--c-text);
  padding: 0.6rem 0.5rem;
  border-radius: 8px;
  font-weight: 500;
}
.navbar__menu a:hover,
.navbar__menu .navlink:hover {
  background-color: var(--c-surface-2);
  text-decoration: none;
}

.navbar__actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* No celular o menu ☰ é uma coluna: sem o wrap ele fica na MESMA linha da marca
   e do botão (o .navbar__inner é flex), começa no meio da tela e vaza para fora
   — links cortados e o painel do popover de fonte/tema metade fora do viewport.
   Com o wrap ele desce para a linha de baixo e ocupa a largura inteira. */
@media (max-width: 767px) {
  .navbar__inner { flex-wrap: wrap; }
  .navbar__menu { width: 100%; }
}

@media (min-width: 768px) {
  .navbar__toggle { display: none; }
  .navbar__menu {
    display: flex !important;
    flex-direction: row;
    align-items: center;
    gap: 0.25rem;
    padding: 0;
  }
}

/* ---------- Botões -------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1;
  padding: 0.65rem 1.2rem;
  border-radius: var(--radius-control);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, opacity 0.15s ease;
  text-decoration: none;
}
.btn:hover { text-decoration: none; }
.btn:disabled { opacity: 0.6; cursor: not-allowed; }

.btn--primary {
  background-color: var(--c-primary);
  color: var(--c-primary-contrast);
}
.btn--primary:hover { background-color: var(--c-primary-hover); }

.btn--outline {
  background-color: transparent;
  border-color: var(--c-border);
  color: var(--c-text);
}
.btn--outline:hover { background-color: var(--c-surface-2); }

.btn--ghost {
  background-color: transparent;
  color: var(--c-text);
}
.btn--ghost:hover { background-color: var(--c-surface-2); }

.btn--block { width: 100%; }
.btn--sm { padding: 0.45rem 0.8rem; font-size: 0.85rem; }

/* ---------- Cards --------------------------------------------------------- */

.card {
  background-color: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-card);
  padding: 1.5rem;
  box-shadow: 0 4px 20px var(--c-shadow);
}
.card__title { margin-bottom: 0.5rem; }

/* ---------- Formulários --------------------------------------------------- */

.form { max-width: 420px; margin: 0 auto; }
.form-group { margin-bottom: 1rem; }

.label {
  display: block;
  font-size: 0.9rem;
  font-weight: 600;
  margin-bottom: 0.35rem;
  color: var(--c-text);
}

.input,
.select,
.textarea {
  width: 100%;
  padding: 0.65rem 0.85rem;
  font-size: 1rem;
  color: var(--c-text);
  background-color: var(--c-bg);
  border: 1px solid var(--c-secondary);
  border-radius: var(--radius-control);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.input:focus,
.select:focus,
.textarea:focus {
  outline: none;
  border-color: var(--c-primary);
  box-shadow: inset 0 0 0 1px var(--c-primary);  /* borda "2px" sem deslocar layout */
}
.textarea { min-height: 120px; resize: vertical; }

.checkbox-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.9rem;
}
.checkbox-row input { width: 1rem; height: 1rem; }

.field-error {
  color: var(--c-danger);
  font-size: 0.85rem;
  margin-top: 0.3rem;
}

/* ---------- Alertas ------------------------------------------------------- */

.alert {
  border-radius: 10px;
  padding: 0.75rem 1rem;
  font-size: 0.92rem;
  border: 1px solid transparent;
  margin-bottom: 1rem;
}
.alert--success {
  background-color: var(--c-success-soft);
  border-color: var(--c-success);
  color: var(--c-text);
}
.alert--error {
  background-color: var(--c-primary-soft);
  border-color: var(--c-danger);
  color: var(--c-text);
}

.error-list { list-style: none; }
.error-list li { color: var(--c-danger); font-size: 0.88rem; }

/* ---------- Badges -------------------------------------------------------- */

.badge {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 700;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  background-color: var(--c-primary-soft);
  color: var(--c-primary-text);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

/* ---------- Hero / seções ------------------------------------------------- */

.hero {
  text-align: center;
  padding: 2.5rem 0 1.5rem;
}
.hero p.lead {
  font-size: 1.1rem;
  color: var(--c-text-muted);
  max-width: 640px;
  margin: 1rem auto 0;
}
.hero__cta { margin-top: 1.5rem; display: flex; gap: 0.75rem; justify-content: center; flex-wrap: wrap; }

.section { padding: 2rem 0; }
.section__title { text-align: center; margin-bottom: 1.5rem; }

.feature { text-align: center; }
.feature__icon {
  font-size: 1.8rem;
  display: inline-flex;
  width: 56px; height: 56px;
  align-items: center; justify-content: center;
  border-radius: 14px;
  background-color: var(--c-primary-soft);
  margin-bottom: 0.75rem;
}

/* ---------- Planos (pricing) --------------------------------------------- */

.plan-card {
  display: flex;
  flex-direction: column;
  text-align: center;
}
.plan-card.is-featured { border-color: var(--c-primary); border-width: 2px; }
.plan-card__price { font-size: 2rem; font-weight: 800; margin: 0.5rem 0; }
.plan-card__price small { font-size: 0.9rem; font-weight: 500; color: var(--c-text-muted); }
.plan-card ul { list-style: none; text-align: left; margin: 1rem 0; }
.plan-card li { padding: 0.35rem 0; padding-left: 1.5rem; position: relative; }
.plan-card li::before {
  content: "✓";
  position: absolute; left: 0;
  color: var(--c-success-text); font-weight: 700;
}
.plan-card .btn { margin-top: auto; }

/* ---------- Auth ---------------------------------------------------------- */

.auth-wrap {
  min-height: calc(100vh - 60px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem 1rem;
}
.auth-card {
  width: 100%;
  max-width: 420px;
}

/* Cabeçalho de marca das telas de auth: logo + nome + frase da tela
   (auth/partials/_brand.blade.php). */
.auth-brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  margin-bottom: 2rem;
}
.auth-brand__logo {
  width: 96px;
  height: 96px;
  object-fit: contain;
  border-radius: var(--radius-card);
  background-color: var(--c-surface-2);
  margin-bottom: 1rem;
}
/* Fallback sem arquivo de logo: o ícone da marca no mesmo quadrado. */
.auth-brand__logo--icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 3rem;
  color: var(--c-primary);
}
.auth-brand__title {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--c-primary);
  margin: 0;
}
.auth-brand__subtitle {
  font-size: 1rem;
  color: var(--c-text-muted);
  margin-top: 0.5rem;
}

/* ---------- Footer -------------------------------------------------------- */

.footer {
  flex-shrink: 0;
  background-color: var(--c-surface);
  border-top: 1px solid var(--c-border);
  padding: 1.5rem 0;
  color: var(--c-text-muted);
  font-size: 0.88rem;
}
.footer__inner {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  align-items: center;
  text-align: center;
}
.footer__links { display: flex; gap: 1rem; flex-wrap: wrap; justify-content: center; }
.footer__links a { color: var(--c-text-muted); }

@media (min-width: 768px) {
  .footer__inner { flex-direction: row; justify-content: space-between; }
}

/* ---------- Acessibilidade ------------------------------------------------ */

:focus-visible { outline: 2px solid var(--c-primary); outline-offset: 2px; }

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

/* =========================================================================
   Administração (Fase 3)
   ========================================================================= */

/* Cabeçalho de página com ações à direita */
.page-head {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin-bottom: 1.25rem;
}
.page-head__actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }
@media (min-width: 640px) {
  .page-head { flex-direction: row; align-items: center; justify-content: space-between; }
}

/* Subnavegação da área admin (chips que quebram em quantas linhas couberem) */
.subnav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 0.25rem;
  border-bottom: 1px solid var(--c-border);
  margin-bottom: 1.5rem;
  padding-bottom: 0.5rem;
}
.subnav a {
  white-space: nowrap;
  padding: 0.5rem 0.9rem;
  border-radius: 999px;
  color: var(--c-text-muted);
  font-weight: 600;
  font-size: 0.92rem;
}
.subnav a:hover { background-color: var(--c-surface-2); text-decoration: none; }
.subnav a.is-active { color: var(--c-primary-text); background-color: var(--c-primary-soft); }

/* Só o menu admin recolhe no mobile — a barra de filtros continua sempre visível */
.subnav--menu { display: none; }
.subnav--menu.is-open { display: flex; }
.subnav__toggle {
  display: block;
  width: 100%;
  margin-bottom: 1rem;
  padding: 0.6rem 0.9rem;
  border: 1px solid var(--c-border);
  border-radius: 10px;
  background-color: var(--c-surface);
  color: var(--c-text);
  font-family: inherit;
  font-size: 0.95rem;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}
.subnav__toggle:hover { background-color: var(--c-surface-2); }
@media (min-width: 768px) {
  .subnav__toggle { display: none; }
  .subnav--menu { display: flex; }
}

/* Tabela responsiva */
.table-wrap { overflow-x: auto; border: 1px solid var(--c-border); border-radius: 12px; }
.table {
  width: 100%;
  border-collapse: collapse;
  background-color: var(--c-surface);
  font-size: 0.93rem;
}
.table th, .table td {
  padding: 0.7rem 0.85rem;
  text-align: left;
  border-bottom: 1px solid var(--c-border);
  vertical-align: middle;
}
.table th {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--c-text-muted);
  background-color: var(--c-surface-2);
}
.table tr:last-child td { border-bottom: none; }
.table tbody tr:hover { background-color: var(--c-surface-2); }
.table .actions { display: flex; gap: 0.4rem; white-space: nowrap; }
.table__empty { text-align: center; color: var(--c-text-muted); padding: 2rem; }

/* Botão de perigo */
.btn--danger {
  background-color: transparent;
  border-color: var(--c-danger);
  color: var(--c-danger);
}
.btn--danger:hover { background-color: var(--c-danger); color: var(--c-danger-contrast); }

/* Grid de formulário (2 colunas no desktop) */
.form-grid { display: grid; gap: 1rem; }
@media (min-width: 640px) {
  .form-grid--2 { grid-template-columns: repeat(2, 1fr); }
  .form-grid--3 { grid-template-columns: repeat(2, 1fr); }
  .form-grid--4 { grid-template-columns: repeat(2, 1fr); }
  .form-grid .col-span-2 { grid-column: span 2; }
}
@media (min-width: 900px) {
  .form-grid--3 { grid-template-columns: repeat(3, 1fr); }
  .form-grid--4 { grid-template-columns: repeat(4, 1fr); }
}
.form--wide { max-width: 820px; margin: 0 auto; }

/* Alternativas de múltipla escolha */
.option-row {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.6rem;
  border: 1px solid var(--c-border);
  border-radius: 10px;
  margin-bottom: 0.6rem;
  background-color: var(--c-surface);
}
.option-row__letter {
  font-weight: 700;
  width: 1.8rem;
  height: 1.8rem;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background-color: var(--c-primary-soft);
  color: var(--c-primary-text);
  text-transform: uppercase;
}
.option-row textarea { min-height: 48px; }
.option-row__correct { display: flex; align-items: center; gap: 0.35rem; white-space: nowrap; font-size: 0.85rem; }

/* Miniaturas de imagem */
.img-grid { display: flex; flex-wrap: wrap; gap: 0.75rem; }
.img-thumb {
  position: relative;
  width: 120px;
  border: 1px solid var(--c-border);
  border-radius: 10px;
  overflow: hidden;
  background-color: var(--c-surface-2);
}
.img-thumb img { width: 100%; height: 90px; object-fit: cover; }
.img-thumb__cap { font-size: 0.72rem; padding: 0.3rem; color: var(--c-text-muted); text-align: center; }

/* Estatística compacta no dashboard admin */
.stat {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}
.stat__value { font-size: 1.8rem; font-weight: 800; color: var(--c-primary); }
.stat__label { color: var(--c-text-muted); font-size: 0.9rem; }

/* Paginação */
.pagination-wrap { margin-top: 1.25rem; }
.pagination-wrap nav { display: flex; gap: 0.3rem; flex-wrap: wrap; justify-content: center; }
.pagination-wrap a, .pagination-wrap span {
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--c-border);
  border-radius: 8px;
  color: var(--c-text);
  font-size: 0.88rem;
}
.pagination-wrap a:hover { background-color: var(--c-surface-2); text-decoration: none; }

/* Pílula de status */
.pill {
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 700;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
}
.pill--on { background-color: var(--c-success-soft); color: var(--c-success-text); }
.pill--off { background-color: var(--c-surface-2); color: var(--c-text-muted); }
.pill--new { background-color: var(--c-primary-soft); color: var(--c-primary-text); }
/* Questão retida: entrou incompleta e não pode ir ao ar sem um editor olhar.
   Fundo derivado do token de aviso — sem cor literal, como manda a folha. */
.pill--warn {
  background-color: color-mix(in srgb, var(--c-warning) 18%, var(--c-surface));
  color: color-mix(in srgb, var(--c-warning) 75%, var(--c-text));
}

/* =========================================================================
   Fase 5 — Experiência do cliente (estudo)
   ========================================================================= */

/* Variantes utilitárias */
.badge--soft {
  background-color: var(--c-surface-2);
  color: var(--c-text-muted);
  text-transform: none;
  letter-spacing: 0;
}
.filters__actions { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.25rem; }

/* ---------- Listagem de questões ---------- */
.q-item {
  display: block;
  background-color: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: 12px;
  padding: 1rem 1.1rem;
  box-shadow: 0 1px 2px var(--c-shadow);
  color: inherit;
  transition: border-color 0.15s ease, transform 0.05s ease;
}
.q-item:hover { text-decoration: none; border-color: var(--c-primary); }
.q-item__badges { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-bottom: 0.6rem; }
.q-item__statement { color: var(--c-text); margin-bottom: 0.75rem; }
.q-item__foot { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; flex-wrap: wrap; }
.q-item__go { color: var(--c-primary); font-weight: 600; font-size: 0.9rem; }

/* ---------- Resolução ---------- */
.q-solve { margin-bottom: 1rem; }
.q-prose { white-space: normal; word-wrap: break-word; }
.q-prose p { margin-bottom: 0.6rem; }
.q-statement { margin-top: 0.75rem; font-size: 1.02rem; }

.q-reference {
  border-left: 3px solid var(--c-border);
  background-color: var(--c-surface-2);
  padding: 0.9rem 1rem;
  border-radius: 8px;
  margin-bottom: 1rem;
}
.q-reference h3 { margin-bottom: 0.4rem; }
.q-reference__source { font-size: 0.82rem; font-style: italic; margin-top: 0.4rem; }
.q-reference--images .q-figure { margin: 0; }
.q-reference--images .q-figure + .q-figure { margin-top: 0.75rem; }
.q-nav { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }

.q-figure { margin: 0.9rem 0; }
.q-figure img { border: 1px solid var(--c-border); border-radius: 8px; }
.q-figure figcaption { font-size: 0.8rem; margin-top: 0.3rem; text-align: center; }

/* Formulário de resposta */
.q-answer { margin-bottom: 1rem; }
.q-tf { display: flex; gap: 0.75rem; flex-wrap: wrap; }
/* A borda saiu do item (múltipla escolha e certo/errado): quem separa uma
   alternativa da outra é o espaço, e quem marca estado é o fundo. O `1px solid
   transparent` fica no lugar do `1px solid var(--c-border)` de propósito — sem
   ele a caixa encolheria 2px e todo o alinhamento com a tesoura se deslocaria. */
.q-tf__opt {
  /* Largura pelo conteúdo (com um mínimo): esticar até metade do card jogava
     "Certo" e "Errado" para as pontas opostas, como se não fossem um par. */
  flex: 0 1 auto;
  min-width: 9rem;
  display: flex; align-items: center; justify-content: center; gap: 0.5rem;
  padding: 0.8rem 1rem;
  border: 1px solid transparent;
  border-radius: 10px;
  cursor: pointer;
  font-weight: 600;
  transition: background-color 0.15s ease;
}
.q-tf__opt:hover { background-color: var(--c-surface-2); }
.q-tf__opt:has(input:checked) { background-color: var(--c-marked); }

.q-options { display: flex; flex-direction: column; gap: 0.55rem; }
.q-option {
  display: flex; align-items: flex-start; gap: 0.7rem;
  padding: 0.7rem 0.85rem;
  border: 1px solid transparent;
  border-radius: 10px;
  cursor: pointer;
  transition: background-color 0.15s ease;
}
.q-option:hover { background-color: var(--c-surface-2); }
.q-option:has(input:checked) { background-color: var(--c-marked); }
.q-option__letter {
  flex-shrink: 0;
  width: 1.6rem; height: 1.6rem;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background-color: var(--c-surface-2);
  font-weight: 700; font-size: 0.85rem;
}
.q-option__text { flex: 1; }
.q-option input[type="radio"] { margin-top: 0.35rem; }

/* Alternativas no resultado (gabarito). A cor da LETRA é o sinal — as pílulas
   "gabarito"/"sua resposta" saíram, e o ícone ✓/✗ do bloco no fim do arquivo
   completa o recado.

   O `.q-options--result` na frente NÃO é decoração: `:has()` assume a
   especificidade do argumento, então `.q-option:has(input:checked)` (acima) vale
   (0,2,1) e ganharia de um `.q-option.is-correct` solto, que vale (0,2,0). Quem
   ACERTA marca a própria alternativa do gabarito — a mesma linha é `is-correct` e
   `:checked` —, e ela sairia com a cor de marcada em vez do verde. Com o
   container na frente são (0,3,0), e a contagem de classes decide antes dos
   elementos. O `.is-wrong` vem junto por disciplina: hoje ele repete de propósito
   o `--c-marked` da seleção — marcada e marcada-errada são a MESMA informação, e
   o box não pode trocar de cor ao apertar Responder —, mas quem separar as duas
   cores amanhã precisa que esta regra já esteja ganhando por mérito. */
.q-options--result .q-option { cursor: default; }
.q-options--result .q-option.is-correct { background-color: var(--c-success-soft); }
.q-options--result .q-option.is-correct .q-option__letter { background-color: var(--c-surface); color: var(--c-success-text); }
.q-options--result .q-option.is-wrong { background-color: var(--c-marked); }
.q-options--result .q-option.is-wrong .q-option__letter { background-color: var(--c-surface); color: var(--c-danger); }

/* Resultado */
.q-result { margin-bottom: 1rem; }
.q-verdict {
  font-weight: 800; font-size: 1.1rem;
  padding: 0.7rem 1rem; border-radius: 10px; margin-bottom: 1rem;
}
/* Sobrou só a pendente: objetivas não têm mais tarja de veredito. */
.q-verdict--pending { background-color: var(--c-surface-2); color: var(--c-text-muted); font-size: 1rem; font-weight: 600; }

.q-essay-box {
  background-color: var(--c-surface-2);
  border-radius: 8px; padding: 0.8rem 1rem; margin-top: 0.4rem;
}
.q-selfeval { margin-top: 1rem; padding-top: 1rem; border-top: 1px dashed var(--c-border); }
.q-selfeval__actions { display: flex; gap: 0.6rem; flex-wrap: wrap; }
.q-selfeval__actions form { display: inline; }

.q-explanation { margin-top: 1.2rem; padding-top: 1rem; border-top: 1px solid var(--c-border); }
.q-explanation h4 { margin-bottom: 0.4rem; }

.q-stats {
  display: flex; gap: 1.5rem; flex-wrap: wrap;
  margin-top: 1.2rem; padding-top: 1rem; border-top: 1px solid var(--c-border);
}
/* Como bloco de abertura de um card (resumo do simulado) — sem a linha e a faixa
   vazia que existem para separá-lo do conteúdo acima no card de questão. */
.q-stats--lead { margin-top: 0; padding-top: 0; border-top: 0; }


/* ---------- Comentários ---------- */
.q-comments { margin-top: 1.5rem; padding-top: 1.2rem; border-top: 1px solid var(--c-border); }
.q-comments h2 { margin-bottom: 1rem; font-size: 1.15rem; }
.comment {
  background-color: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: 12px;
  padding: 0.9rem 1rem;
}
.comment--reply {
  border-radius: 10px;
  background-color: var(--c-surface-2);
  margin-top: 0.6rem;
}
.comment__replies { margin-top: 0.6rem; padding-left: 1rem; border-left: 2px solid var(--c-border); }
.comment__head { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 0.35rem; }
.comment__author { font-size: 0.95rem; }
.comment__time { font-size: 0.8rem; }
.comment__body { margin-bottom: 0.5rem; }
.comment__actions { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.comment__actions form { display: inline; }
.comment__reply-btn, .comment__mod {
  background: none; border: none; cursor: pointer;
  color: var(--c-text-muted); font-size: 0.85rem; font-weight: 600;
  padding: 0.2rem 0;
}
.comment__reply-btn:hover, .comment__mod:hover { color: var(--c-primary); }
.comment__reply-form { margin-top: 0.6rem; }

.votes { display: flex; gap: 0.4rem; }
.votes form { display: inline; }
.vote {
  display: inline-flex; align-items: center; gap: 0.3rem;
  background-color: var(--c-surface-2);
  border: 1px solid transparent;
  border-radius: 999px;
  padding: 0.2rem 0.6rem;
  cursor: pointer;
  font-size: 0.85rem;
  color: var(--c-text);
}
.vote:hover { border-color: var(--c-border); }
.vote.is-active { border-color: var(--c-primary); color: var(--c-primary-text); background-color: var(--c-primary-soft); }
.vote.is-active--down { border-color: var(--c-danger); color: var(--c-danger); }
.vote__count { font-weight: 700; }

/* ---------- Admin: reports ---------- */
.report__head { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 0.5rem; }
.report__statement { margin-bottom: 0.5rem; }
.report__comment {
  border-left: 3px solid var(--c-border);
  padding: 0.3rem 0.8rem; margin: 0.5rem 0;
  color: var(--c-text-muted); font-style: italic;
}
.report__notes { margin: 0.4rem 0; font-size: 0.9rem; }
.report__form { margin-top: 0.75rem; padding-top: 0.75rem; border-top: 1px solid var(--c-border); }
.report__form-row { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.report__form-row .input { flex: 1 1 200px; }
.report__form-row .select { flex: 0 0 auto; }

/* =========================================================================
   Fase 6 — Dashboard de desempenho (gráficos Chart.js)
   ========================================================================= */

/* Linha de KPIs: 1 col (mobile) -> 2 -> 4 */
@media (min-width: 560px) { .grid-4 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px) { .grid-4 { grid-template-columns: repeat(4, 1fr); } }

/* Container com altura fixa para o gráfico responsivo do Chart.js */
.chart-box { position: relative; height: 260px; margin-top: 0.5rem; }
.chart-card .card__title { margin-bottom: 0.25rem; }

.dash-empty { text-align: center; padding: 2rem 1rem; }
.dash-empty .card__title { margin-bottom: 0.4rem; }

/* ---------- Assinatura (Fase 7) ------------------------------------------- */

.alert--info {
  background-color: var(--c-primary-soft);
  border-color: var(--c-primary);
  color: var(--c-text);
}

.sub-status { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.sub-meta { color: var(--c-text-muted); font-size: 0.9rem; margin-top: 0.35rem; }
.sub-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 1rem; }

.plan-card__pay { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 0.75rem; }

/* ---------- Cadernos: ações na questão (Fase 9) -------------------------- */

.q-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem; }
.q-actions__form { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.q-actions__form .label { margin: 0; }
.q-actions__form .select { width: auto; min-width: 180px; }
.inline-form { display: inline; }
.pill__x {
  background: none; border: none; cursor: pointer; color: var(--c-text-muted);
  font-size: 1rem; line-height: 1; padding: 0 0 0 0.25rem;
}
.pill__x:hover { color: var(--c-danger); }

/* ---------- Distribuição de respostas por alternativa (Fase 9) ----------- */

.answer-dist { margin-top: 1rem; }
.answer-dist__title { font-size: 0.85rem; color: var(--c-text-muted); margin-bottom: 0.4rem; }
.answer-dist__row { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.35rem; }
.answer-dist__label { width: 3.5rem; font-size: 0.85rem; font-weight: 600; }
.answer-dist__bar {
  flex: 1; height: 10px; background: var(--c-surface-2, rgba(127,127,127,.15));
  border-radius: 6px; overflow: hidden;
}
.answer-dist__bar > span { display: block; height: 100%; background: var(--c-primary); border-radius: 6px; }
.answer-dist__bar.is-correct > span { background: var(--c-success); }
.answer-dist__pct { width: 3rem; text-align: right; font-size: 0.82rem; color: var(--c-text-muted); }

/* ---------- Modo estudo × prova (Fase 9) --------------------------------- */

.q-topbar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-bottom: 0.5rem; }
.study-mode { display: inline-flex; align-items: center; gap: 0.35rem; }
.study-mode__label { font-size: 0.85rem; color: var(--c-text-muted); }

/* ---------- Meta diária (Fase 9) ---------------------------------------- */

.goal-card__head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-bottom: 0.5rem; }
.goal-bar { height: 12px; background: var(--c-surface-2, rgba(127,127,127,.15)); border-radius: 8px; overflow: hidden; }
.goal-bar > span { display: block; height: 100%; background: var(--c-primary); border-radius: 8px; transition: width .3s; }
.goal-form { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }

/* ---------- Notificações in-app (Fase 9) -------------------------------- */

.badge--count { background: var(--c-danger); color: var(--c-danger-contrast); border-radius: 100px; margin-left: .15rem; }
.notif { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.notif--unread { border-left: 3px solid var(--c-primary); }
.notif__body { flex: 1; }

/* ---------- Camada de movimento (GSAP) --------------------------------- */
/* Estado inicial das animações de entrada. Gated por `html.anim-pending`,
   que o script inline do <head> adiciona ANTES do 1º paint só quando há
   animação (não em reduced-motion). Se o JS/CDN do GSAP falhar, o failsafe
   remove a classe e o conteúdo aparece — nunca fica preso invisível. */
html.anim-pending [data-anim="reveal"],
html.anim-pending [data-anim="stagger"] > * { opacity: 0; }

/* ---------- Login social (divisor "ou") -------------------------------- */
.auth-divider { display: flex; align-items: center; gap: .75rem; margin: 1.25rem 0; color: var(--c-text-muted); font-size: .8rem; text-transform: uppercase; letter-spacing: .04em; }
.auth-divider::before, .auth-divider::after { content: ""; flex: 1; border-top: 1px solid var(--c-border); }

/* ---------- Tamanho da fonte -------------------------------------------- */
/* Escala o font-size da raiz; como toda a UI usa rem, tudo cresce/encolhe
   proporcionalmente. Nível 2 = padrão do navegador (100%). */
:root[data-font-scale="1"] { font-size: 90%; }
:root[data-font-scale="2"] { font-size: 100%; }
:root[data-font-scale="3"] { font-size: 112%; }
:root[data-font-scale="4"] { font-size: 125%; }

/* A figura da questão acompanha o nível de leitura. A coluna é em px e o
   tamanho da imagem também, então sem isto quem aumenta a fonte fica com o
   texto grande e a figura do mesmo tamanho de sempre — em prova escaneada,
   justo onde a letra é miúda. Nível 1 = original; quem consome é o bloco da
   moldura, no fim do arquivo. */
:root[data-font-scale="1"] { --img-zoom: 1; }
:root[data-font-scale="2"] { --img-zoom: 1.1; }
:root[data-font-scale="3"] { --img-zoom: 1.25; }
:root[data-font-scale="4"] { --img-zoom: 1.4; }

.fontscale { position: relative; display: inline-flex; }
.fontscale > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.15rem; height: 2.15rem; border-radius: 10px;
  border: 1px solid var(--c-border); background: var(--c-surface);
}
.fontscale > summary::-webkit-details-marker { display: none; }
.fontscale > summary:hover,
.fontscale[open] > summary { border-color: var(--c-primary); }
.fontscale__glyph { font-weight: 800; line-height: 1; letter-spacing: -.02em; }
.fontscale__glyph span { font-size: .68em; font-weight: 700; }
.fontscale__panel {
  margin-top: .5rem; width: 260px; padding: .9rem;
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,.18);
}
@media (min-width: 768px) {
  .fontscale__panel { position: absolute; right: 0; top: 100%; margin-top: .4rem; z-index: 50; }
}
.fontscale__control { display: flex; flex-direction: column; gap: .55rem; }
.fontscale__meta { display: flex; justify-content: space-between; align-items: baseline; font-size: .9rem; color: var(--c-text-muted); }
.fontscale__meta strong { color: var(--c-text); }
.fontscale__hint { margin: 0; font-size: .78rem; color: var(--c-text-muted); }

/* Botões discretos (1–4): um clique aplica o nível — sem arrastar (o slider
   antigo refluía a página sob o cursor). O "A" cresce por nível como pista. */
.fontscale__btns { display: flex; gap: .4rem; }
.fontscale__btn {
  flex: 1; display: inline-flex; align-items: center; justify-content: center;
  height: 2.4rem; padding: 0; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--c-border); background: var(--c-surface);
  color: var(--c-text); font-weight: 800; line-height: 1;
  transition: border-color .12s ease, background-color .12s ease;
}
.fontscale__btn:hover { border-color: var(--c-primary); }
.fontscale__btn.is-active { border-color: var(--c-primary); background: var(--c-primary-soft); }
.fontscale__btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--c-primary-soft); }
.fontscale__btn[data-fontscale-value="1"] { font-size: .8rem; }
.fontscale__btn[data-fontscale-value="2"] { font-size: 1rem; }
.fontscale__btn[data-fontscale-value="3"] { font-size: 1.2rem; }
.fontscale__btn[data-fontscale-value="4"] { font-size: 1.45rem; }

/* ---------- Largura do conteúdo / espaçamento lateral ------------------- */
/* Muda o max-width do .container (navbar + main). Nível 2 = padrão (1080px);
   níveis maiores alargam o conteúdo e reduzem as faixas laterais. */
:root[data-content-width="1"] .container { max-width: 960px; }
:root[data-content-width="2"] .container { max-width: 1080px; }
:root[data-content-width="3"] .container { max-width: 1240px; }
:root[data-content-width="4"] .container { max-width: 1440px; }
:root[data-content-width="5"] .container { max-width: 1680px; }
:root[data-content-width="6"] .container { max-width: none; }

.cwidth { position: relative; display: inline-flex; }
.cwidth > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.15rem; height: 2.15rem; border-radius: 10px; font-size: 1.1rem;
  border: 1px solid var(--c-border); background: var(--c-surface);
}
.cwidth > summary::-webkit-details-marker { display: none; }
.cwidth > summary:hover,
.cwidth[open] > summary { border-color: var(--c-primary); }
.cwidth__glyph { font-weight: 800; line-height: 1; }
.cwidth__panel {
  margin-top: .5rem; width: 260px; padding: .9rem;
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,.18);
}
@media (min-width: 768px) {
  .cwidth__panel { position: absolute; right: 0; top: 100%; margin-top: .4rem; z-index: 50; }
}
.cwidth__control { display: flex; flex-direction: column; gap: .55rem; }
.cwidth__meta { display: flex; justify-content: space-between; align-items: baseline; font-size: .9rem; color: var(--c-text-muted); }
.cwidth__meta strong { color: var(--c-text); }
.cwidth__hint { margin: 0; font-size: .78rem; color: var(--c-text-muted); }
.cwidth__btns { display: flex; gap: .35rem; }
.cwidth__btn {
  flex: 1; display: inline-flex; align-items: center; justify-content: center;
  height: 2.4rem; padding: 0; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--c-border); background: var(--c-surface);
  color: var(--c-text-muted); transition: border-color .12s ease, background-color .12s ease, color .12s ease;
}
.cwidth__btn:hover { border-color: var(--c-primary); }
.cwidth__btn.is-active { border-color: var(--c-primary); background: var(--c-primary-soft); color: var(--c-primary-text); }
.cwidth__btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--c-primary-soft); }
.cwidth__bar { display: block; height: 3px; border-radius: 2px; background: currentColor; }
.cwidth__btn[data-cwidth-value="1"] .cwidth__bar { width: 8px; }
.cwidth__btn[data-cwidth-value="2"] .cwidth__bar { width: 11px; }
.cwidth__btn[data-cwidth-value="3"] .cwidth__bar { width: 14px; }
.cwidth__btn[data-cwidth-value="4"] .cwidth__bar { width: 17px; }
.cwidth__btn[data-cwidth-value="5"] .cwidth__bar { width: 20px; }
.cwidth__btn[data-cwidth-value="6"] .cwidth__bar { width: 23px; }

/* ---------- Navbar: teto de escala de fonte (aceita só níveis 1 e 2) ----- */
/* Regra do produto: a barra superior (navbar) acompanha os níveis de fonte 1
   e 2, mas nunca cresce além do nível 2 — nos níveis 3 e 4 permanece no
   tamanho do nível 2, mantendo a barra compacta enquanto o conteúdo aumenta.
   Como: a navbar ancora a própria fonte em rem (segue os níveis 1–2) e, nos
   níveis 3–4, compensa a escala da raiz (112% e 125%) para travar no nível 2.
   Os tamanhos internos passam a ser em, acompanhando este teto. */
.navbar { font-size: 1rem; }
:root[data-font-scale="3"] .navbar { font-size: 0.893rem; } /* 1 / 1.12 */
:root[data-font-scale="4"] .navbar { font-size: 0.800rem; } /* 1 / 1.25 */

/* Medidas internas da navbar em em (relativas ao teto acima). */
.navbar__brand   { font-size: 1.15em; gap: 0.5em; }
.navbar__toggle  { font-size: 1.2em; padding: 0.4em 0.6em; }
.navbar__menu    { gap: 0.25em; padding: 0.5em 0 1em; }
.navbar__menu a,
.navbar__menu .navlink { padding: 0.6em 0.5em; }
.navbar__actions { gap: 0.5em; }
.navbar__actions .btn      { font-size: 0.95em; padding: 0.65em 1.1em; gap: 0.4em; }
.navbar__actions .btn--sm  { padding: 0.45em 0.8em; font-size: 0.85em; }
.navbar .badge--count { font-size: 0.7em; padding: 0 .4em; }
.navbar .fontscale > summary { width: 2.15em; height: 2.15em; }
/* cwidth tem glifo em font-size: 1.1rem — travar a fonte em em e compensar a
   largura (1.955 × 1.1 = 2.15) mantém o botão no tamanho do nível 2. */
.navbar .cwidth > summary { width: 1.955em; height: 1.955em; font-size: 1.1em; }

@media (min-width: 768px) {
  .navbar__menu { gap: 0.25em; padding: 0; }
}

/* --- Banner promocional da home ---------------------------------------- */
.home-banner { margin: 0 0 1.5rem; }
.home-banner img { width: 100%; border-radius: 14px; } /* height:auto global mantém a proporção */
.home-banner a { display: block; }

/* =========================================================================
   Filtro multi-seleção (dropdown com busca + badge de contagem)
   Usado na lista de questões (client/questions/_multiselect.blade.php).
   ========================================================================= */
.msel { position: relative; }

/* Botão que abre o dropdown: herda a moldura de .select e alinha rótulo,
   badge e caret numa linha. */
.msel__toggle {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  text-align: left;
}
.msel__label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msel__caret { color: var(--c-text-muted); font-size: 0.8rem; flex-shrink: 0; }

/* Badge com a quantidade selecionada (azul da marca, não o vermelho de
   notificação de .badge--count). */
.msel__count {
  flex-shrink: 0;
  min-width: 1.25rem;
  padding: 0.05rem 0.4rem;
  border-radius: 999px;
  background-color: var(--c-primary);
  color: var(--c-primary-contrast);
  font-size: 0.75rem;
  font-weight: 700;
  text-align: center;
  line-height: 1.2;
}
.msel__count[hidden] { display: none; }

/* Painel flutuante */
.msel__panel {
  position: absolute;
  z-index: 30;
  top: calc(100% + 4px);
  left: 0;
  width: 100%;
  min-width: 220px;
  padding: 0.5rem;
  background-color: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: 10px;
  box-shadow: 0 6px 20px var(--c-shadow);
}
.msel__panel[hidden] { display: none; }
.msel__search { margin-bottom: 0.4rem; }
.msel__list { list-style: none; margin: 0; padding: 0; max-height: 260px; overflow-y: auto; }
.msel__item[hidden] { display: none; }

.msel__opt {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.5rem;
  border-radius: 8px;
  cursor: pointer;
}
.msel__opt:hover { background-color: var(--c-surface-2); }
.msel__opt.is-selected {
  background-color: var(--c-primary-soft);
  color: var(--c-primary-text);
  font-weight: 700;
}

/* Chips dos itens marcados, sob o botão do dropdown (montados pelo JS).
   O × desmarca o checkbox; a submissão continua manual. */
.msel__chips {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin: 0.4rem 0 0;
  padding: 0;
}
.msel__chips[hidden] { display: none; }
.msel__chip {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
  max-width: 100%;
  padding: 0.15rem 0.35rem 0.15rem 0.6rem;
  border-radius: 999px;
  background-color: var(--c-primary-soft);
  color: var(--c-primary-text);
  font-size: 0.78rem;
  font-weight: 600;
  line-height: 1.5;
}
.msel__chip-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msel__chip-x {
  background: none; border: none; cursor: pointer; color: inherit;
  font-size: 1rem; line-height: 1; padding: 0 0.15rem; opacity: 0.7;
}
.msel__chip-x:hover { opacity: 1; color: var(--c-primary-hover); }

/* =========================================================================
   Shell da área do cliente (app.) — menu lateral (desktop) + bottom-nav (mobile)
   Bela Concurseira · ver docs/design-system.md
   ========================================================================= */
.app-body { display: block; background-color: var(--c-bg); }
.app-shell { display: flex; min-height: 100vh; }

.sidenav {
  position: sticky; top: 0; align-self: flex-start;
  width: 256px; flex: 0 0 256px; height: 100vh;
  background-color: var(--c-surface); border-right: 1px solid var(--c-border);
  display: flex; flex-direction: column; gap: 0.25rem; padding: 1.1rem 0.8rem;
  overflow-y: auto;
}
.sidenav__close { display: none; }
/* Sem padding próprio: o respiro em volta da marca já vem do padding do
   .sidenav e da linha do .sidenav__nav logo abaixo. */
.sidenav__brand { display: flex; align-items: center; gap: 0.6rem; color: var(--c-text); }
.sidenav__brand:hover { text-decoration: none; }
.sidenav__logo { color: var(--c-primary); font-size: 1.8rem; }
.sidenav__brand-text { display: flex; flex-direction: column; line-height: 1.15; }
.sidenav__brand-text strong { font-size: 1.05rem; color: var(--c-primary); }
.sidenav__brand-text small { font-size: 0.72rem; color: var(--c-text-muted); }

/* A linha acima do 1º item separa a marca da navegação — mesmos valores da que
   já existe acima do rodapé do menu (.sidenav__foot), para as duas serem iguais. */
.sidenav__nav { display: flex; flex-direction: column; gap: 0.2rem; padding-top: 0.6rem; border-top: 1px solid var(--c-border); }
.sidenav__link {
  display: flex; align-items: center; gap: 0.7rem;
  padding: 0.62rem 0.7rem; border-radius: 14px;
  color: var(--c-text); font-weight: 600; font-size: 0.95rem; font-family: inherit;
  background: none; border: none; width: 100%; text-align: left; cursor: pointer;
}
.sidenav__link .material-symbols-outlined { font-size: 1.35rem; color: var(--c-text-muted); flex-shrink: 0; }
.sidenav__link:hover { background-color: var(--c-surface-2); text-decoration: none; }
.sidenav__link.is-active { background-color: var(--c-primary-soft); color: var(--c-primary-text); }
.sidenav__link.is-active .material-symbols-outlined { color: var(--c-primary-text); }
.sidenav__link.is-soon { color: var(--c-text-muted); cursor: default; }
.sidenav__cta { margin: 0.7rem 0; }
.sidenav__foot { margin-top: auto; display: flex; flex-direction: column; gap: 0.2rem; padding-top: 0.6rem; border-top: 1px solid var(--c-border); }
.sidenav__logout { margin: 0; }
.pill--soon { margin-left: auto; background-color: var(--c-surface-2); color: var(--c-text-muted); font-size: 0.62rem; text-transform: none; letter-spacing: 0; }
.sidenav-backdrop { display: none; }

.app-main { flex: 1 1 auto; min-width: 0; width: 100%; max-width: 1200px; padding: 1.6rem 2rem; }
.app-topbar { display: none; }
.bottomnav { display: none; }

@media (max-width: 899px) {
  .app-shell { display: block; }

  .sidenav {
    /* `bottom: 0` fica como fallback: em navegador móvel ele resolve pela LARGE
       viewport (a altura com as barras escondidas), então o fim da rolagem cai
       atrás da barra inferior do navegador e os últimos itens do menu nunca
       aparecem — foi o corte relatado no celular. `height: 100dvh` usa a altura
       VISÍVEL e vence o `bottom` quando os três coexistem; quem não entende
       `dvh` continua como antes. */
    position: fixed; left: 0; top: 0; bottom: 0;
    height: 100dvh;
    overflow-y: auto; overscroll-behavior: contain;
    width: 280px; z-index: 100;
    transform: translateX(-100%);
    transition: transform 0.3s ease;
    box-shadow: 4px 0 20px var(--c-shadow);
    display: flex; /* override desktop none */
  }
  .sidenav.is-open { transform: translateX(0); }
  .sidenav__close {
    display: flex; align-items: center; justify-content: center;
    position: absolute; top: 0.6rem; right: 0.6rem;
    width: 2rem; height: 2rem; border-radius: 999px;
    background: none; border: none; color: var(--c-text-muted); cursor: pointer;
    font-size: 1.3rem;
  }
  .sidenav__close:hover { background-color: var(--c-surface-2); color: var(--c-text); }
  .sidenav-backdrop {
    display: block;
    position: fixed; inset: 0; z-index: 99;
    background: rgba(0,0,0,0.5);
    opacity: 0; pointer-events: none;
    transition: opacity 0.3s ease;
  }
  .sidenav-backdrop.is-open {
    opacity: 1; pointer-events: auto;
  }

  .app-topbar {
    display: flex; align-items: center; justify-content: space-between;
    position: sticky; top: 0; z-index: 40;
    padding: 0.7rem 1rem; background-color: var(--c-surface); border-bottom: 1px solid var(--c-border);
  }
  .app-topbar__brand { display: flex; align-items: center; gap: 0.4rem; color: var(--c-primary); font-weight: 700; }
  .app-topbar__brand:hover { text-decoration: none; }
  .app-topbar__account { position: relative; color: var(--c-text); display: inline-flex; }
  .app-main { padding: 1rem 1rem calc(72px + 1rem); }
  .bottomnav {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
    background-color: var(--c-surface); border-top: 1px solid var(--c-border);
    box-shadow: 0 -2px 12px var(--c-shadow);
  }
  .bottomnav__item {
    flex: 1; display: flex; flex-direction: column; align-items: center; gap: 0.1rem;
    padding: 0.5rem 0; color: var(--c-text-muted); font-size: 0.68rem; font-weight: 600;
  }
  .bottomnav__item:hover { text-decoration: none; }
  .bottomnav__item .material-symbols-outlined { font-size: 1.4rem; }
  .bottomnav__item.is-active { color: var(--c-primary); }
  .bottomnav__toggle {
    background: none; border: none; cursor: pointer; font-family: inherit;
  }
}

/* =========================================================================
   Landing / shell público (Bela Concurseira) — Fase 2
   ========================================================================= */
.public-main { flex: 1 0 auto; padding: 1.5rem 0 2rem; }

/* Navbar de marketing */
.pubnav { position: sticky; top: 0; z-index: 50; background-color: var(--c-surface); border-bottom: 1px solid var(--c-border); }
.pubnav__inner { display: flex; align-items: center; justify-content: space-between; min-height: 64px; gap: 1rem; flex-wrap: wrap; }
.pubnav__brand { display: flex; align-items: center; gap: 0.5rem; color: var(--c-primary); font-weight: 800; font-size: 1.1rem; }
.pubnav__brand:hover { text-decoration: none; }
.pubnav__brand .material-symbols-outlined { font-size: 1.6rem; }
.pubnav__toggle { display: inline-flex; background: none; border: 1px solid var(--c-border); border-radius: 10px; padding: 0.3rem 0.5rem; color: var(--c-text); cursor: pointer; }
.pubnav__menu { display: none; flex-direction: column; gap: 0.5rem; width: 100%; padding-bottom: 1rem; }
.pubnav__menu.is-open { display: flex; }
.pubnav__link { color: var(--c-text); font-weight: 600; padding: 0.4rem 0.2rem; }
.pubnav__link:hover { color: var(--c-primary); text-decoration: none; }
@media (min-width: 768px) {
  .pubnav__toggle { display: none; }
  .pubnav__menu { display: flex !important; flex-direction: row; align-items: center; gap: 1.1rem; width: auto; padding: 0; }
}

/* Hero em duas colunas */
.hero--split { text-align: left; padding: 2rem 0 1rem; }
.hero--split .lead { margin: 1rem 0 0; max-width: 560px; }
.hero--split .hero__cta { justify-content: flex-start; }
@media (min-width: 900px) {
  .hero--split { display: grid; grid-template-columns: 1.05fr 0.95fr; gap: 3rem; align-items: center; }
}
.hero__badge { display: inline-flex; align-items: center; gap: 0.4rem; background-color: var(--c-primary-soft); color: var(--c-primary-text); font-weight: 700; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em; padding: 0.35rem 0.8rem; border-radius: 999px; }
.hero__badge .material-symbols-outlined { font-size: 1.05rem; }
.hero__title { font-size: 2.1rem; line-height: 1.15; margin: 1rem 0; }
.hero__title em { color: var(--c-primary); font-style: italic; }
@media (min-width: 900px) { .hero__title { font-size: 2.8rem; } }

.hero__art { position: relative; border-radius: 28px; min-height: 300px; background-size: cover; background-position: center; border: 1px solid var(--c-border); display: flex; align-items: center; justify-content: center; overflow: hidden; }
.hero__art-icon { font-size: 6rem; color: var(--c-secondary); }
.hero__floating { position: absolute; bottom: 1.2rem; left: 1.2rem; display: flex; align-items: center; gap: 0.6rem; background-color: var(--c-surface); border: 1px solid var(--c-border); border-radius: 16px; padding: 0.7rem 0.9rem; box-shadow: 0 6px 20px var(--c-shadow); }
.hero__floating-icon { color: var(--c-success); font-size: 1.6rem; }
.hero__floating-text { display: flex; flex-direction: column; line-height: 1.1; }
.hero__floating-text strong { font-size: 0.9rem; }
.hero__floating-text small { color: var(--c-text-muted); font-size: 0.78rem; }
@media (max-width: 899px) { .hero__art { min-height: 200px; margin-top: 1.5rem; } }

/* Seções (features / pricing) */
.section__lead { text-align: center; color: var(--c-text-muted); max-width: 640px; margin: -0.5rem auto 2rem; }
@media (min-width: 640px) { .grid-4 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 992px) { .grid-4 { grid-template-columns: repeat(4, 1fr); } }

.feature-grid .feature { text-align: left; background-color: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--radius-card); padding: 1.5rem; box-shadow: 0 4px 20px var(--c-shadow); }
.feature-grid .feature__icon { color: var(--c-primary); margin-bottom: 0.9rem; }
.feature-grid .feature h3 { font-size: 1.05rem; margin-bottom: 0.4rem; }

/* Pricing — card em destaque preenchido */
.plan-card { position: relative; }
.pricing-grid { max-width: 760px; margin: 0 auto; align-items: stretch; }
.pricing-grid .plan-card { text-align: left; }
.plan-card__sub { color: var(--c-text-muted); font-size: 0.9rem; margin-bottom: 0.5rem; }
.plan-card__flag { position: absolute; top: 1rem; right: 1rem; background-color: color-mix(in srgb, var(--c-primary-contrast) 92%, transparent); color: var(--c-primary-text); }
.plan-card.is-featured { background-color: var(--c-primary); border-color: var(--c-primary); color: var(--c-primary-contrast); }
.plan-card.is-featured h3, .plan-card.is-featured .plan-card__price { color: var(--c-primary-contrast); }
.plan-card.is-featured .plan-card__price small, .plan-card.is-featured .plan-card__sub { color: color-mix(in srgb, var(--c-primary-contrast) 85%, transparent); }
.plan-card.is-featured li { color: color-mix(in srgb, var(--c-primary-contrast) 95%, transparent); }
.plan-card.is-featured li::before { color: var(--c-primary-contrast); }
.btn--on-primary { background-color: var(--c-primary-contrast); color: var(--c-primary); }
.btn--on-primary:hover { background-color: color-mix(in srgb, var(--c-primary-contrast) 90%, transparent); }

/* Rodapé de marketing */
.pubfooter { flex-shrink: 0; background-color: var(--c-surface); border-top: 1px solid var(--c-border); padding: 2rem 0; margin-top: 2rem; }
.pubfooter__inner { display: flex; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap; }
.pubfooter__brand { max-width: 440px; }
.pubfooter__brand p { color: var(--c-text-muted); font-size: 0.9rem; margin: 0.6rem 0; }
.pubfooter__brand small { color: var(--c-text-muted); font-size: 0.8rem; }
.pubfooter__links { display: flex; flex-direction: column; gap: 0.5rem; }
.pubfooter__links a { color: var(--c-text-muted); }

/* =========================================================================
   Fase 3 — polimento das telas do cliente (KPI tiles + gabarito comentado)
   ========================================================================= */
.kpi { display: flex; align-items: center; gap: 1rem; }
.kpi__icon {
  width: 48px; height: 48px; border-radius: 14px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center; font-size: 1.6rem;
  background-color: var(--c-primary-soft); color: var(--c-primary);
}
.kpi__icon--warm { background-color: var(--c-marked); color: color-mix(in srgb, var(--c-warning) 70%, var(--c-text)); }
.kpi__label { display: block; color: var(--c-text-muted); font-size: 0.82rem; line-height: 1.2; margin-bottom: 0.15rem; }
.kpi__value { display: block; font-size: 1.9rem; font-weight: 800; color: var(--c-text); line-height: 1.05; }

/* Gabarito comentado como caixa de destaque (estilo "insight" dos mockups) */
.q-explanation {
  margin-top: 1.2rem; padding: 1rem 1.1rem;
  background-color: var(--c-primary-soft);
  border: 1px solid var(--c-border); border-radius: 16px;
}
.q-explanation h4 { display: flex; align-items: center; gap: 0.4rem; margin-bottom: 0.5rem; color: var(--c-primary); }
.q-explanation h4 .material-symbols-outlined { font-size: 1.25rem; }

/* =========================================================================
   Ganhos rápidos — seletor "por página" + filtros salvos (Banco de Questões)
   ========================================================================= */
/* Seletor compacto de questões por página, no cabeçalho da lista */
.per-page { display: inline-flex; align-items: center; gap: 0.4rem; }
.per-page__label { color: var(--c-text-muted); font-size: 0.85rem; white-space: nowrap; }
.select--sm {
  width: auto;
  padding: 0.35rem 2rem 0.35rem 0.6rem;
  font-size: 0.85rem;
  border-radius: 999px;
}

/* Card de filtros salvos */
.saved-filters__head {
  display: flex; align-items: center; gap: 0.4rem;
  color: var(--c-primary); font-weight: 600; margin-bottom: 0.6rem;
}
.saved-filters__head .material-symbols-outlined { font-size: 1.2rem; }
.saved-filters__empty { font-size: 0.9rem; margin: 0; }
.saved-filters__list { display: flex; flex-wrap: wrap; gap: 0.5rem; }

/* Chip de um filtro salvo: nome (aplica) + × (remove) num pill floral */
.saved-filter {
  display: inline-flex; align-items: center;
  background-color: var(--c-primary-soft);
  border-radius: 999px;
  overflow: hidden;
}
.saved-filter__apply {
  padding: 0.3rem 0.75rem;
  color: var(--c-primary); font-size: 0.85rem; font-weight: 600; text-decoration: none;
}
.saved-filter__apply:hover { text-decoration: underline; }
.saved-filter form { display: inline-flex; margin: 0; }
.saved-filter__remove {
  border: none; background: transparent; cursor: pointer;
  padding: 0.3rem 0.6rem 0.3rem 0.2rem;
  color: var(--c-primary); font-size: 1.05rem; line-height: 1;
}
.saved-filter__remove:hover { color: var(--c-danger); }

/* Formulário "salvar filtro atual" (nome + botão), abaixo dos chips */
.saved-filters__save {
  display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center;
  margin-top: 0.85rem; padding-top: 0.85rem;
  border-top: 1px solid var(--c-border);
}
.saved-filters__save .input { flex: 1 1 240px; width: auto; }

/* =========================================================================
   Loja — pacotes de questões (catálogo + meus pacotes)
   ========================================================================= */
.card-grid { display: grid; gap: 1rem; grid-template-columns: 1fr; }
@media (min-width: 640px) { .card-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 992px) { .card-grid { grid-template-columns: repeat(3, 1fr); } }

.pkg-price { font-size: 1.5rem; font-weight: 800; color: var(--c-primary); }

.pkg-row { display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap; }
.pkg-row__actions { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }

/* Campo opcional de cupom nos cartões de compra da loja */
.coupon-field { text-align: left; }
.coupon-field summary {
  cursor: pointer; color: var(--c-primary); font-size: 0.85rem; font-weight: 600;
  list-style: none; user-select: none;
}
.coupon-field summary::-webkit-details-marker { display: none; }
.coupon-field summary::before { content: "🏷️ "; }
.coupon-field input { margin-top: 0.4rem; }
/* ---------- Card de Questão (Design System / docs/references/questoes-formato.png) ---------- */
.q-card {
  background-color: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-card, 24px);
  padding: 1.5rem;
  box-shadow: 0 4px 20px var(--c-shadow);
  margin-bottom: 1.5rem;
}

.q-card__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.25rem;
  flex-wrap: wrap;
}

.q-card__meta-left {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.4rem;
  flex: 1;
}

.q-card__qid {
  display: inline-flex;
  align-items: center;
  padding: 0.3rem 0.75rem;
  border-radius: 999px;
  background-color: var(--c-primary-soft);
  color: var(--c-primary-text);
  font-weight: 700;
  font-size: 0.85rem;
  border: 1px solid var(--c-secondary);
}

.q-card__actions-right {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.q-card__icon-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--c-text-muted);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.2rem;
  height: 2.2rem;
  border-radius: 50%;
  transition: color 0.15s, background-color 0.15s;
}
.q-card__icon-btn:hover {
  color: var(--c-primary);
  background-color: var(--c-surface-2);
}
.q-card__icon-btn.is-active {
  color: var(--c-primary);
}

.q-card__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 1.5rem;
  padding-top: 1rem;
  border-top: 1px solid var(--c-border);
  flex-wrap: wrap;
}

.q-card__footer-left {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  flex-wrap: wrap;
}

.q-card__footer-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--c-text-muted);
  font-weight: 600;
  font-size: 0.9rem;
  background: none;
  border: none;
  cursor: pointer;
  text-decoration: none;
}
.q-card__footer-link:hover {
  color: var(--c-primary);
  text-decoration: none;
}

/* Ajustes de raio para alternativas (20px conforme Design System) */
.q-tf__opt {
  border-radius: var(--radius-control, 20px);
}
.q-option {
  border-radius: var(--radius-control, 20px);
}

/* ---------- Listagem resolvível: a questão é respondida no próprio card ---------- */
.q-list {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}
.q-list > .q-card {
  margin-bottom: 0;
}
/* A âncora #q{id} (volta após responder sem JS) não deve colar o card no topo */
.q-card {
  scroll-margin-top: 1rem;
}

a.q-card__qid {
  text-decoration: none;
}
a.q-card__qid:hover {
  background-color: var(--c-secondary);
  text-decoration: none;
}

/* Popovers do header: reportar erro e salvar em caderno */
.q-card__pop {
  position: relative;
}
.q-card__pop > summary {
  list-style: none;
  cursor: pointer;
}
.q-card__pop > summary::-webkit-details-marker {
  display: none;
}
.q-card__pop-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 0.35rem);
  z-index: 20;
  min-width: 16rem;
  padding: 0.9rem;
  text-align: left;
  background-color: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-card, 24px);
  box-shadow: 0 8px 28px var(--c-shadow);
}
.q-card__pop-panel .select,
.q-card__pop-panel .textarea {
  width: 100%;
}

/* Texto de apoio longo entra recolhido para o card não estourar na lista */
.q-reference--toggle > summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--c-primary);
}

/* Comentários sob demanda. O :target cobre o fluxo sem JS: chegando pela
   âncora do rodapé, a seção se revela sozinha. */
.q-comments[hidden] {
  display: none;
}
.q-comments[hidden]:target {
  display: block;
}
.q-comments__loading {
  padding: 0.5rem 0;
  color: var(--c-text-muted);
  font-size: 0.9rem;
}

/* Card aguardando resposta do servidor */
.q-card.is-busy {
  opacity: 0.6;
  pointer-events: none;
  transition: opacity 0.15s ease;
}

.q-figure img {
  max-width: 100%;
  height: auto;
}

.q-card__pop > summary.q-card__icon-btn {
  color: var(--c-text-muted);
  font-weight: 400;
}
.q-card__pop > summary.q-card__icon-btn:hover,
.q-card__pop[open] > summary.q-card__icon-btn,
.q-card__pop > summary.q-card__icon-btn.is-active {
  color: var(--c-primary);
}

/* ---------- Painéis do rodapé: comentários, gabarito comentado, dica da IA ----
   Chegam vazios do servidor (o conteúdo vem sob demanda) e só um fica aberto por
   vez — com JS quem garante é o app.js; sem JS, o servidor só renderiza o painel
   pedido em ?painel=. */
.q-panel[hidden] {
  display: none;
}
.q-panel__loading {
  padding: 0.5rem 0;
  color: var(--c-text-muted);
  font-size: 0.9rem;
}
/* O atalho aberto fica marcado */
.q-card__footer-link[aria-expanded="true"] {
  color: var(--c-primary);
}

/* Dica da Bela IA: mesma caixa do gabarito comentado, em tom neutro para os dois
   não competirem quando o usuário alterna entre eles. */
.q-explanation--ai {
  background-color: var(--c-surface-2);
}
.q-explanation--ai h4 {
  color: var(--c-text);
}

/* ---------- Admin › perfis de acesso agrupados ---------------------------- */
/* Equipe, cliente e influenciador têm áreas (e subdomínios) distintos; o
   agrupamento deixa isso explícito para quem edita o usuário. */
.role-group {
  border: 1px solid var(--c-border);
  border-radius: var(--radius-control);
  padding: 0.5rem 0.9rem 0.75rem;
  margin-top: 0.6rem;
}
.role-group__legend {
  padding: 0 0.4rem;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--c-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.role-option {
  align-items: flex-start; /* a descrição faz a linha ter duas alturas */
  padding: 0.35rem 0;
}
.role-option input { margin-top: 0.15rem; }
.role-option__hint {
  display: block;
  font-size: 0.8rem;
  line-height: 1.35;
}
.role-option__extra {
  margin: 0.25rem 0 0.5rem 1.5rem;
  padding-left: 0.75rem;
  border-left: 2px solid var(--c-primary-soft);
}
.role-option__extra[hidden] { display: none; }
.role-option__extra small {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.8rem;
  line-height: 1.35;
}
.role-option__number { max-width: 8rem; }

/* Pré-visualização do PDF na moderação (admin) */
.pdf-preview {
  display: block;
  width: 100%;
  height: 75vh;
  min-height: 420px;
  border: 1px solid var(--c-border);
  border-radius: 12px;
  background: var(--c-surface-2);
}
@media (max-width: 640px) {
  .pdf-preview { height: 60vh; min-height: 320px; }
}

/* Lightbox de imagem ("ver em tamanho real") — <dialog> nativo, ver app.js */
.zoomable { display: inline-block; cursor: zoom-in; }
.lightbox {
  max-width: 92vw;
  padding: 0.75rem;
  border: 1px solid var(--c-border);
  border-radius: var(--radius-card);
  background-color: var(--c-surface);
  box-shadow: 0 8px 28px var(--c-shadow);
}
.lightbox::backdrop { background: rgba(0, 0, 0, 0.65); }
.lightbox__img {
  display: block;
  max-width: 100%;
  max-height: 80vh;
  border-radius: 12px;
}
.lightbox__close { margin-top: 0.6rem; }

/* =========================================================================
   Novo simulado — bento: conteúdo + quantidade | tempo + Modo Prova + CTA
   client/mock-exams/create.blade.php · ver docs/design-system.md
   ========================================================================= */

.exam-builder { display: grid; gap: 1.25rem; align-items: start; }
@media (min-width: 900px) {
  /* Proporção do protótipo: ~8/12 + ~4/12 */
  .exam-builder { grid-template-columns: 2fr 1fr; }
}
.exam-builder__main > * + * { margin-top: 1.25rem; }
.exam-builder__side { display: flex; flex-direction: column; gap: 1.25rem; }
.exam-builder__side .card > * + * { margin-top: 1.25rem; }
.exam-builder__rule {
  border: 0;
  border-top: 1px solid var(--c-border);
  opacity: 0.6;
  margin: 1.25rem 0;
}
.exam-builder__cta {
  display: flex; align-items: center; justify-content: center; gap: 0.5rem;
  padding: 0.95rem 1rem;
  font-size: 1.02rem;
}
.exam-builder__cta .material-symbols-outlined { font-size: 1.35rem; }
/* Tempo esmaecido enquanto o Modo Prova está desligado (estado posto por JS) */
.exam-builder__time.is-disabled { opacity: 0.5; }

/* Cabeçalho de seção: ícone da marca + título, com dica opcional */
.sec-head {
  display: flex; align-items: center; gap: 0.5rem;
  font-size: 1rem; font-weight: 700;
  color: var(--c-text);
  margin-bottom: 0.4rem;
}
.sec-head .material-symbols-outlined { font-size: 1.25rem; color: var(--c-primary); }
.sec-head__hint { font-size: 0.8rem; color: var(--c-text-muted); margin-top: 0.5rem; }

/* Atalhos de quantidade (radios) + campo "Outro" */
.qty { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.6rem; }
@media (min-width: 640px) { .qty { grid-template-columns: repeat(4, 1fr); } }
.qty__opt {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  padding: 0.7rem 1rem;
  border: 1px solid var(--c-border);
  border-radius: var(--radius-control);
  background-color: var(--c-surface);
  color: var(--c-text-muted);
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.15s ease, color 0.15s ease;
}
.qty__opt input { position: absolute; opacity: 0; width: 0; height: 0; }
.qty__opt:hover { border-color: var(--c-primary); }
.qty__opt:has(input:checked) {
  border-color: var(--c-primary);
  background-color: var(--c-primary-soft);
  color: var(--c-primary);
}
.qty__opt:has(input:focus-visible) { box-shadow: 0 0 0 3px var(--c-primary-soft); }
.qty__custom { text-align: center; }

/* Toggle switch (Modo Prova) — trilho 44×24, knob 20 */
.switch-row { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.switch-row__text { display: flex; flex-direction: column; }
.switch-row__title { display: flex; align-items: center; gap: 0.5rem; font-weight: 700; }
.switch-row__title .material-symbols-outlined { font-size: 1.25rem; color: var(--c-primary); }
.switch-row__hint { font-size: 0.78rem; color: var(--c-text-muted); margin-top: 0.25rem; }

.switch { position: relative; flex-shrink: 0; width: 44px; height: 24px; display: inline-block; }
/* `~` e não `+`: há um <input type="hidden"> antes do checkbox. */
.switch input[type="checkbox"] {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; margin: 0; cursor: pointer; z-index: 1;
}
.switch__track {
  position: absolute; inset: 0;
  border-radius: 999px;
  background-color: var(--c-border);
  transition: background-color 0.2s ease;
}
.switch__track::after {
  content: "";
  position: absolute; top: 2px; left: 2px;
  width: 20px; height: 20px;
  border-radius: 50%;
  background-color: var(--c-primary-contrast);
  box-shadow: 0 2px 4px var(--c-shadow);
  transition: transform 0.2s ease;
}
.switch input:checked ~ .switch__track { background-color: var(--c-primary); }
.switch input:checked ~ .switch__track::after { transform: translateX(20px); }
.switch input:focus-visible ~ .switch__track { box-shadow: 0 0 0 3px var(--c-primary-soft); }

/* =========================================================================
   Campo com ícone à esquerda e/ou olho de senha à direita
   resources/views/partials/_field.blade.php
   ========================================================================= */

/* Envolve UM .input. Os paddings extras vivem em modificadores do wrapper,
   nunca no .input cru — há dezenas de usos de .input no sistema e nenhum deve
   mudar. O anel de foco continua sendo o box-shadow inset do .input: o wrapper
   não desenha borda, e ícone/botão são absolutos (pintam acima do input
   estático, sem precisar de z-index). Nada de overflow:hidden aqui, senão o
   outline do :focus-visible do botão seria recortado. */
.field { position: relative; display: block; }

.field__icon {
  position: absolute;
  left: 0.9rem;
  top: 50%;
  transform: translateY(-50%);
  font-size: 1.25rem;
  line-height: 1;
  color: var(--c-text-muted);
  pointer-events: none; /* o clique atravessa e cai no input */
}
.field--icon .input { padding-left: 2.8rem; }

.field__toggle {
  position: absolute;
  right: 0.4rem;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  color: var(--c-text-muted);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.2rem;
  height: 2.2rem;
  border-radius: 50%;
  transition: color 0.15s ease, background-color 0.15s ease;
}
.field__toggle:hover { color: var(--c-primary); background-color: var(--c-surface-2); }
.field__toggle .material-symbols-outlined { font-size: 1.25rem; }
/* O botão nasce escondido no Blade e o JS o revela. Sem esta regra o display
   de autor venceria o [hidden] do navegador e ele apareceria inerte. */
.field__toggle[hidden] { display: none; }

.field--toggle .input { padding-right: 3rem; }
/* Edge desenha um "olho" nativo em type=password — ficariam dois. */
.field--toggle .input::-ms-reveal,
.field--toggle .input::-ms-clear { display: none; }

/* Placeholder no cinza-malva da marca (o Firefox aplica opacity .54 sozinho). */
.input::placeholder { color: var(--c-text-muted); opacity: 1; }

/* ---------- Prosa de questão em HTML (importador de JSON) -----------------
   Conteúdo vindo do importador chega em HTML (tabelas, fórmulas, imagens
   inline) e é renderizado sem escape por App\Support\QuestionHtml. As regras
   abaixo só valem dentro de .q-prose — o resto do CSS não muda, e questões
   antigas (texto puro) não são afetadas porque não têm essas tags.
   O overflow vive no container: o HTML vem do importador, então a view não
   tem onde pendurar um .table-wrap. Só rola quando de fato transborda.
   -------------------------------------------------------------------------- */
.q-prose { overflow-x: auto; }

.q-prose img { max-width: 100%; height: auto; }

.q-prose table,
.q-prose .quill-better-table {
  border-collapse: collapse;
  margin: 0.75rem 0;
  font-size: 0.95rem;
  background-color: var(--c-surface);
}
.q-prose th,
.q-prose td {
  border: 1px solid var(--c-border);
  padding: 0.45rem 0.6rem;
  text-align: left;
  vertical-align: top;
  word-break: break-word;
}
.q-prose th { background-color: var(--c-surface-2); font-weight: 600; }

/* O reset zera as listas; dentro da prosa os marcadores voltam. */
.q-prose ul,
.q-prose ol { list-style: revert; padding-left: 1.5rem; margin-bottom: 0.6rem; }
.q-prose li { margin-bottom: 0.2rem; }

.q-prose blockquote {
  border-left: 3px solid var(--c-border);
  padding-left: 0.8rem;
  margin: 0.6rem 0;
  color: var(--c-text-muted);
}

/* Fórmulas: o importador marca TeX como <code class="tex">. */
.q-prose code,
.q-prose code.tex {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.92em;
  background-color: var(--c-surface-2);
  border: 1px solid var(--c-border);
  border-radius: 6px;
  padding: 0.05rem 0.3rem;
}
.q-prose pre {
  background-color: var(--c-surface-2);
  border: 1px solid var(--c-border);
  border-radius: 8px;
  padding: 0.7rem 0.85rem;
  overflow-x: auto;
  margin: 0.6rem 0;
}
.q-prose pre code { background: none; border: none; padding: 0; }

/* ---------------------------------------------------------------------------
   Modo visual × HTML no admin (Issue #16)
   O conteúdo da questão vem em HTML do importador; ver o código cru na textarea
   torna a revisão difícil. Cada campo tem os dois modos no DOM e o
   data-view-mode do formulário (ou do wrapper, na página de leitura) decide qual
   aparece — sem flash, como o data-theme.
   --------------------------------------------------------------------------- */
.view-mode { display: inline-flex; align-items: center; gap: 0.35rem; }
.view-mode__label { font-size: 0.85rem; color: var(--c-text-muted); }

.rich-field { flex: 1; min-width: 0; }
.option-row .rich-field { align-self: stretch; }

.rich-field__visual {
  width: 100%;
  min-height: 3rem;
  padding: 0.65rem 0.85rem;
  color: var(--c-text);
  background-color: var(--c-bg);
  border: 1px solid var(--c-secondary);
  border-radius: var(--radius-control);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.rich-field__visual:focus {
  outline: none;
  border-color: var(--c-primary);
  box-shadow: inset 0 0 0 1px var(--c-primary);
}
/* Campo vazio não pode virar uma faixa sem sentido: mostra o mesmo placeholder. */
.rich-field__visual:empty::before {
  content: attr(data-placeholder);
  color: var(--c-text-muted);
}
/* Página de leitura: sem moldura de campo — ali é texto, não formulário. */
.rich-field__visual--static {
  background-color: transparent;
  border-color: transparent;
  padding-left: 0;
  padding-right: 0;
}

.rich-view__source {
  white-space: pre-wrap;
  word-break: break-word;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.85rem;
  background-color: var(--c-surface-2);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-control);
  padding: 0.65rem 0.85rem;
  margin: 0;
  overflow-x: auto;
}
.rich-view__meta { display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: center; }
.option-row--correct { border-color: var(--c-success); }

/* A troca de modo: um dos dois lados some. */
[data-view-mode='visual'] [data-rich-source] { display: none; }
[data-view-mode='html'] [data-rich-preview],
[data-view-mode='html'] .rich-field__visual { display: none; }

/* O identificador da questão (Q158) nos simulados divide a linha com os badges
   (.q-item__badges). Ali ele acompanha o tamanho deles — no card da área de
   estudo, onde é o título do bloco, continua maior. */
.q-item__badges .q-card__qid {
  font-size: 0.72rem;
  padding: 0.15rem 0.55rem;
  letter-spacing: 0.03em;
}

/* ---------- Cupom nos cartões da loja: aplicar / remover ------------------ */

.coupon-field__row {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.4rem;
}
.coupon-field__row .input { flex: 1; min-width: 0; }

/* Estado "cupom aplicado": some o <details>, entra a linha com o código. */
.coupon-field--on {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  flex-wrap: wrap;
  font-size: 0.85rem;
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--c-border);
  border-radius: 12px;
  background: var(--c-surface-2);
}
.coupon-field--on strong { color: var(--c-primary); }

/* Três planos (mensal/semestral/anual) precisam de mais largura que dois. */
.pricing-grid.grid-3 { max-width: 980px; }

/* ---------- Nº da questão nas tabelas do admin ---------------------------- */
/* Mesmo chip do card do cliente, na densidade de tabela (como no simulado). */
.table .q-card__qid {
  font-size: 0.72rem;
  padding: 0.15rem 0.55rem;
  white-space: nowrap;
}
/* `width: 1%` = encolhe ao conteúdo: a coluna do número não tira largura do
   enunciado, que é o que se lê para reconhecer a questão. */
.table .cell-num {
  width: 1%;
  white-space: nowrap;
}

/* =========================================================================
   Protótipo de front-end (/front-end) — telas para aprovação do cliente
   -------------------------------------------------------------------------
   Bloco isolado, só tokens existentes, para poder ser removido inteiro quando
   a loja de verdade for implementada.
   ========================================================================= */


/* Topo: logo da marca, carrinho e menu */
/* O PNG tem margem interna generosa; 52px deixa a rosa no mesmo peso óptico
   do wordmark ao lado. */
.pubnav__logo { width: 52px; height: 52px; object-fit: contain; flex-shrink: 0; margin: -6px 0; }
.pubnav__quick { display: flex; align-items: center; gap: 0.4rem; }
.pubnav__cart {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.4rem; height: 2.4rem; border-radius: 999px;
  border: 1px solid var(--c-border); color: var(--c-primary);
}
.pubnav__cart:hover { background-color: var(--c-primary-soft); text-decoration: none; }
.pubnav__cart .badge--count {
  position: absolute; top: -0.3rem; right: -0.3rem; margin: 0;
  font-size: 0.65rem; padding: 0.05rem 0.35rem;
}
/* `display: inline-block` do .badge vence o atributo hidden — sem isto o
   carrinho vazio mostraria um "0" vermelho. */
.badge--count[hidden] { display: none; }
.pubnav__link.is-active { color: var(--c-primary); }
@media (min-width: 768px) {
  .pubnav__menu { order: 2; }
  .pubnav__quick { order: 3; }
}

/* Cabeçalho da loja */
.store-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; margin: 0.5rem 0 1.5rem;
}
.store-head__title { margin: 0 0 0.35rem; font-size: 2rem; }
.store-head__lead { margin: 0; color: var(--c-text-muted); max-width: 620px; }
.store-head__cart { flex-shrink: 0; }

/* Busca + abas de tipo */
.store-filters { display: flex; flex-direction: column; gap: 0.9rem; margin-bottom: 1rem; }
.store-searchbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
/* O position:relative é a âncora do painel de sugestões — não trocar por static. */
.store-search { position: relative; flex: 1 1 15rem; max-width: 420px; }
/* A lupa tem classe própria de propósito: o seletor genérico por ícone pegava
   também o ícone de cada sugestão (que vive dentro de .store-search) e o
   pregava, absoluto, sobre o primeiro item da lista (issue #22). */
.store-search__icon {
  position: absolute; left: 0.8rem; top: 50%; transform: translateY(-50%);
  color: var(--c-text-muted); font-size: 1.2rem; pointer-events: none;
}
.store-search .input { padding-left: 2.5rem; }
.store-tabs { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.store-tab {
  border: 1px solid var(--c-border); background-color: var(--c-surface);
  color: var(--c-text-muted); cursor: pointer; font-family: inherit;
  padding: 0.4rem 0.9rem; font-size: 0.82rem;
}
.store-tab:hover { border-color: var(--c-primary); color: var(--c-primary); }
.store-tab.is-active {
  background-color: var(--c-primary-soft); border-color: var(--c-primary); color: var(--c-primary-text);
}
.store-count { margin: 0 0 0.9rem; font-size: 0.85rem; }

/* Cartão de produto
   Coluna flex (em vez das margens do .stack) para o preço e os botões
   descerem ao rodapé do cartão — assim a linha inteira fica alinhada mesmo
   com resumos de tamanhos diferentes. */
.store-card { display: flex; flex-direction: column; gap: 0.7rem; }
.store-card > * + * { margin-top: 0; }
/* O display do cartão venceria o atributo hidden usado pelo filtro. */
.store-card[hidden] { display: none; }
.store-card__top { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.store-card__icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.4rem; height: 2.4rem; border-radius: 14px;
  background-color: var(--c-primary-soft); color: var(--c-primary); font-size: 1.35rem;
}
.store-card__flag { background-color: var(--c-success-soft); color: var(--c-success-text); }
.store-card__title { margin: 0; font-size: 1.12rem; line-height: 1.3; }
.store-card__resumo { margin: 0; font-size: 0.9rem; }
.store-card__meta { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.3rem; }
.store-card__meta li {
  display: flex; align-items: center; gap: 0.4rem;
  font-size: 0.82rem; color: var(--c-text-muted);
}
.store-card__meta .material-symbols-outlined { font-size: 1rem; color: var(--c-success); }
.store-card__price { display: flex; align-items: baseline; gap: 0.5rem; margin-top: auto; }
.store-card__was { color: var(--c-text-muted); font-size: 0.9rem; }
.store-card__actions { display: grid; gap: 0.45rem; }
.store-card__actions .btn { gap: 0.4rem; }
.store-empty { padding: 2.5rem 1rem; }



/* ---------- Protótipo: página de produto --------------------------------- */

.crumbs {
  display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap;
  font-size: 0.85rem; color: var(--c-text-muted); margin: 0.25rem 0 1.2rem;
}
.crumbs a { color: var(--c-text-muted); }
.crumbs a:hover { color: var(--c-primary); }
.crumbs strong { color: var(--c-text); font-weight: 700; }

.prod-layout { display: grid; gap: 1.5rem; align-items: start; }
/* Sem isto, uma tabela larga (a grade do cronograma) estica a coluna e a
   página inteira ganha rolagem horizontal no celular. */
.prod-layout > * { min-width: 0; }
@media (min-width: 900px) {
  .prod-layout { grid-template-columns: minmax(0, 1fr) 340px; gap: 2rem; }
  .prod-buy { position: sticky; top: 84px; }
}
@media (max-width: 899px) {
  /* No celular o cartão de compra vem antes do texto longo. */
  .prod-buy { order: -1; }
}

.prod-head { display: flex; align-items: flex-start; gap: 0.9rem; }
.prod-head .store-card__icon { width: 3rem; height: 3rem; font-size: 1.7rem; }
.prod-title { margin: 0.5rem 0 0; font-size: 1.9rem; line-height: 1.2; }
.prod-autor { margin: 0.3rem 0 0; font-size: 0.9rem; }
.prod-resumo { margin: 1rem 0; }
.prod-tags { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 1.2rem; }
.prod-tag { background-color: var(--c-surface-2); color: var(--c-text-muted); font-weight: 600; }
.prod-texto { margin: 0 0 1rem; line-height: 1.65; }

.prod-bloco { margin: 2rem 0; }
.prod-bloco__titulo { font-size: 1.15rem; margin: 0 0 0.9rem; }

.prod-itens { display: grid; gap: 0.6rem; }
.prod-item {
  display: flex; align-items: center; gap: 0.8rem;
  padding: 0.8rem 1rem; border: 1px solid var(--c-border); border-radius: var(--radius-control);
  background-color: var(--c-surface); color: var(--c-text);
}
.prod-item:hover { border-color: var(--c-primary); text-decoration: none; }
.prod-item__texto { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.prod-item__texto small { font-size: 0.8rem; }
.prod-item__seta { margin-left: auto; color: var(--c-text-muted); }

.prod-inclui { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
.prod-inclui li { display: flex; align-items: flex-start; gap: 0.5rem; line-height: 1.5; }
.prod-inclui .material-symbols-outlined { color: var(--c-success); font-size: 1.15rem; margin-top: 0.1rem; }

.prod-amostra { background-color: var(--c-surface-2); }
.prod-amostra__fonte { font-size: 0.8rem; color: var(--c-text-muted); margin: 0 0 0.6rem; text-transform: uppercase; letter-spacing: 0.03em; }
.prod-amostra__enunciado { margin: 0 0 1rem; line-height: 1.6; font-weight: 500; }
.prod-amostra__alts { display: grid; gap: 0.5rem; }
.prod-amostra__alt { background-color: var(--c-surface); cursor: default; }
.prod-amostra__nota { display: flex; align-items: center; gap: 0.35rem; font-size: 0.85rem; margin: 1rem 0 0; }
.prod-amostra__nota .material-symbols-outlined { font-size: 1rem; }
.prod-amostra__grade td:first-child { font-weight: 700; white-space: nowrap; }
.prod-sumario { margin: 0; padding-left: 1.2rem; display: grid; gap: 0.45rem; color: var(--c-text); }

.prod-buy__card { position: relative; }
.prod-buy__price { display: flex; align-items: baseline; gap: 0.5rem; }
.prod-buy__price .pkg-price { font-size: 1.9rem; }
.prod-buy__parcela { margin: 0.2rem 0 0; font-size: 0.85rem; }
.prod-buy__card .btn { gap: 0.4rem; }
.prod-selos { list-style: none; margin: 0.4rem 0 0; padding: 0.9rem 0 0; display: grid; gap: 0.55rem; border-top: 1px solid var(--c-border); }
.prod-selos li { display: flex; align-items: flex-start; gap: 0.5rem; font-size: 0.83rem; color: var(--c-text-muted); line-height: 1.4; }
.prod-selos .material-symbols-outlined { font-size: 1.1rem; color: var(--c-primary); }

.prod-sugestoes { margin-top: 3rem; }
.prod-sugestoes .section__title { text-align: left; }

/* ---------- Protótipo: trilha de etapas da compra ------------------------- */

.passos { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; margin: 0.25rem 0 1.5rem; }
.passos__item { display: flex; align-items: center; gap: 0.45rem; color: var(--c-text-muted); font-size: 0.85rem; font-weight: 600; }
.passos__item:hover { text-decoration: none; color: var(--c-primary); }
.passos__item + .passos__item::before {
  content: ""; width: 1.5rem; height: 1px; background-color: var(--c-border); margin-right: 0.4rem;
}
.passos__num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.6rem; height: 1.6rem; border-radius: 999px;
  border: 1px solid var(--c-border); background-color: var(--c-surface);
  font-size: 0.78rem; font-weight: 700;
}
.passos__num .material-symbols-outlined { font-size: 1rem; }
.passos__item.is-done { color: var(--c-success-text); }
.passos__item.is-done .passos__num { background-color: var(--c-success-soft); border-color: var(--c-success); color: var(--c-success-text); }
.passos__item.is-current { color: var(--c-primary); }
.passos__item.is-current .passos__num { background-color: var(--c-primary); border-color: var(--c-primary); color: var(--c-primary-contrast); }
@media (max-width: 520px) {
  .passos__rotulo { display: none; }
  .passos__item.is-current .passos__rotulo { display: inline; }
}

/* ---------- Protótipo: carrinho ------------------------------------------ */

.cart-title { margin: 0 0 1.2rem; font-size: 1.8rem; }
.cart-layout { display: grid; gap: 1.5rem; align-items: start; }
.cart-layout > * { min-width: 0; }
@media (min-width: 900px) {
  .cart-layout { grid-template-columns: minmax(0, 1fr) 340px; gap: 2rem; }
  .cart-side { position: sticky; top: 84px; }
}

.cart-list { display: grid; gap: 0.8rem; }
.cart-item { display: flex; align-items: center; gap: 0.9rem; padding: 1rem 1.1rem; }
.cart-item__texto { display: flex; flex-direction: column; align-items: flex-start; gap: 0.3rem; min-width: 0; flex: 1; }
.cart-item__nome { font-size: 1rem; line-height: 1.35; }
.cart-item__dir { display: flex; flex-direction: column; align-items: flex-end; gap: 0.35rem; flex-shrink: 0; }
.cart-item__preco { font-weight: 800; color: var(--c-primary); white-space: nowrap; }
.cart-item__remover {
  display: inline-flex; align-items: center; gap: 0.2rem;
  background: none; border: none; cursor: pointer; font-family: inherit;
  color: var(--c-text-muted); font-size: 0.8rem; font-weight: 600; padding: 0;
}
.cart-item__remover:hover { color: var(--c-danger); }
.cart-item__remover .material-symbols-outlined { font-size: 1.05rem; }
@media (max-width: 520px) {
  .cart-item { align-items: flex-start; flex-wrap: wrap; }
  .cart-item__dir { flex-direction: row; align-items: center; gap: 0.9rem; width: 100%; justify-content: space-between; }
}

.cart-layout.is-empty { grid-template-columns: 1fr; }
.cart-empty { align-items: center; gap: 0.7rem; padding: 2.5rem 1.5rem; max-width: 620px; margin: 0 auto; }
.cart-empty__icon { font-size: 3rem; color: var(--c-primary); }
.cart-empty__title { margin: 0; font-size: 1.25rem; }
.cart-empty__actions { display: flex; gap: 0.6rem; flex-wrap: wrap; justify-content: center; }

.cart-resumo__titulo { margin: 0; font-size: 1.1rem; }
.cart-cupom .label { margin-bottom: 0.3rem; }
.cart-cupom__row { display: flex; gap: 0.5rem; }
.cart-cupom__row .btn { flex-shrink: 0; }
.cart-cupom__msg { margin: 0.45rem 0 0; font-size: 0.82rem; }
.cart-cupom__msg.is-ok { color: var(--c-success-text); }
.cart-cupom__msg.is-erro { color: var(--c-danger); }

.cart-totais { margin: 0; display: grid; gap: 0.5rem; padding-top: 0.9rem; border-top: 1px solid var(--c-border); }
.cart-totais > div { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.cart-totais dt { color: var(--c-text-muted); font-size: 0.9rem; }
.cart-totais dd { margin: 0; font-weight: 700; }
.cart-totais__desconto dd { color: var(--c-success-text); }
.cart-totais__total { padding-top: 0.5rem; border-top: 1px dashed var(--c-border); }
.cart-totais__total dt { color: var(--c-text); font-weight: 700; font-size: 1rem; }
.cart-totais__total dd { font-size: 1.4rem; color: var(--c-primary); font-weight: 800; }
.cart-resumo__parcela { margin: -0.4rem 0 0; font-size: 0.82rem; }

.cart-aviso {
  display: flex; align-items: flex-start; gap: 0.5rem; margin: 0;
  padding: 0.7rem 0.85rem; border-radius: var(--radius-control);
  background-color: var(--c-primary-soft); color: var(--c-text);
  font-size: 0.82rem; line-height: 1.45;
}
.cart-aviso .material-symbols-outlined { font-size: 1.15rem; color: var(--c-primary); flex-shrink: 0; }
.cart-continuar { display: block; text-align: center; font-size: 0.87rem; font-weight: 600; }
.cart-sugestoes { margin-top: 3rem; }
.cart-sugestoes .section__title { text-align: left; }

/* Cupons aplicados no carrinho (um por tipo de produto) */
.cart-cupons { list-style: none; margin: 0.6rem 0 0; padding: 0; display: grid; gap: 0.4rem; }
.cart-cupons__item {
  display: flex; align-items: center; gap: 0.4rem;
  padding: 0.45rem 0.65rem; border-radius: var(--radius-control);
  background-color: var(--c-success-soft); color: var(--c-success-text);
  font-size: 0.78rem; line-height: 1.35;
}
.cart-cupons__item strong { font-weight: 800; }
.cart-cupons__item .pill__x { margin-left: auto; color: var(--c-success-text); font-size: 1.1rem; }
.cart-cupom__ajuda { margin: 0.6rem 0 0; font-size: 0.78rem; line-height: 1.4; }
.cart-cupom__demo {
  margin: 0.4rem 0 0; font-size: 0.75rem; line-height: 1.5;
  padding: 0.45rem 0.6rem; border-radius: 12px;
  background-color: var(--c-surface-2); border: 1px dashed var(--c-border);
}
.cart-item__cupom {
  display: inline-flex; align-items: center; gap: 0.25rem;
  font-size: 0.74rem; font-weight: 700; color: var(--c-success-text);
}
.cart-item__cupom .material-symbols-outlined { font-size: 0.95rem; }
.cart-item__cheio { color: var(--c-text-muted); font-size: 0.8rem; }
/* Rótulo do cupom é longo; o valor nunca deve quebrar em duas linhas. */
.cart-totais dd { white-space: nowrap; }
.cart-totais__desconto dt { font-size: 0.8rem; line-height: 1.35; }
.cart-totais__desconto dd { font-size: 0.9rem; }

/* ---------- Protótipo: identificação ------------------------------------- */

.ident-lead { margin: -0.6rem 0 1.4rem; max-width: 640px; }
.ident-card { padding: 1.2rem; }
.ident-abas { display: flex; gap: 0.35rem; padding: 0.3rem; margin-bottom: 1.2rem;
  background-color: var(--c-surface-2); border-radius: var(--radius-control); }
.ident-aba {
  flex: 1; padding: 0.6rem 0.8rem; border: none; border-radius: 16px;
  background: none; cursor: pointer; font-family: inherit;
  font-size: 0.9rem; font-weight: 700; color: var(--c-text-muted);
}
.ident-aba.is-active { background-color: var(--c-surface); color: var(--c-primary); box-shadow: 0 2px 8px var(--c-shadow); }
.ident-painel { display: grid; gap: 0.2rem; }
/* o display:grid acima venceria o [hidden] do user-agent (ver .field__toggle) */
.ident-painel[hidden] { display: none; }
.ident-painel .btn { margin-top: 0.6rem; }
.ident-termos { align-items: flex-start; font-size: 0.85rem; line-height: 1.45; margin-top: 0.3rem; }
.ident-linha { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.ident-esqueci { font-size: 0.85rem; font-weight: 600; }
.ident-seguro {
  display: flex; align-items: flex-start; gap: 0.5rem;
  margin: 1rem 0 0; font-size: 0.8rem; line-height: 1.45;
}
.ident-seguro .material-symbols-outlined { font-size: 1.1rem; color: var(--c-success); }

/* Resumo do pedido em modo leitura */
.resumo-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.resumo-editar { font-size: 0.83rem; font-weight: 700; }
.resumo-itens { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.65rem; }
.resumo-item { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.8rem; }
.resumo-item__nome { font-size: 0.88rem; font-weight: 600; line-height: 1.35; }
.resumo-item__nome small { font-weight: 500; color: var(--c-text-muted); font-size: 0.76rem; }
.resumo-item__valor { font-weight: 700; white-space: nowrap; }
.resumo-itens { padding-top: 0.3rem; }

/* ---------- Protótipo: pagamento ----------------------------------------- */

.pagar-opcoes { display: grid; gap: 0.6rem; margin-bottom: 1rem; }
@media (min-width: 640px) { .pagar-opcoes { grid-template-columns: repeat(3, 1fr); } }
.pagar-opcao {
  display: flex; align-items: center; gap: 0.6rem; cursor: pointer;
  padding: 0.8rem 0.9rem; border: 1px solid var(--c-border);
  border-radius: var(--radius-control); background-color: var(--c-surface);
}
.pagar-opcao:hover { border-color: var(--c-primary); }
.pagar-opcao.is-active { border-color: var(--c-primary); background-color: var(--c-primary-soft); }
.pagar-opcao input { accent-color: var(--c-primary); flex-shrink: 0; }
.pagar-opcao__icone { color: var(--c-primary); font-size: 1.5rem; }
.pagar-opcao__texto { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.pagar-opcao__texto strong { font-size: 0.92rem; }
.pagar-opcao__texto small { color: var(--c-text-muted); font-size: 0.75rem; }

.pagar-painel__titulo { font-size: 1.05rem; margin: 0 0 0.9rem; }
.pagar-painel .form-grid { margin-top: 0.8rem; }
.pagar-aviso {
  display: flex; align-items: flex-start; gap: 0.5rem; margin: 1rem 0 0;
  padding: 0.7rem 0.85rem; border-radius: var(--radius-control);
  background-color: var(--c-surface-2); font-size: 0.82rem; line-height: 1.45;
}
.pagar-aviso .material-symbols-outlined { font-size: 1.1rem; color: var(--c-warning); flex-shrink: 0; }

.pix-grid { display: grid; gap: 1.2rem; }
@media (min-width: 640px) { .pix-grid { grid-template-columns: 180px minmax(0, 1fr); align-items: start; } }
.pix-qr {
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 1; border-radius: var(--radius-control);
  border: 1px dashed var(--c-border); background-color: var(--c-surface-2);
}
.pix-qr .material-symbols-outlined { font-size: 6rem; color: var(--c-primary); }
.pix-passos { margin: 0 0 1rem; padding-left: 1.1rem; display: grid; gap: 0.35rem; font-size: 0.9rem; line-height: 1.45; }
.pix-copia { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.pix-copia .input { flex: 1; min-width: 200px; font-size: 0.78rem; font-family: monospace; }
.pix-copia .btn { flex-shrink: 0; }
.pix-validade { margin: 0.5rem 0 0; font-size: 0.8rem; }

.pagar-acao { margin-top: 1.2rem; display: grid; gap: 0.2rem; }
.pagar-botao { gap: 0.45rem; font-size: 1.02rem; }
.pagar-acao .cart-continuar { margin-top: 0.4rem; }

/* ---------- Protótipo: pedido confirmado --------------------------------- */

.feito { max-width: 760px; margin: 0 auto; }
.feito-topo { text-align: center; padding: 2.2rem 1.5rem; }
.feito-icone { font-size: 3.4rem; color: var(--c-success); }
.feito-topo--espera .feito-icone { color: var(--c-warning); }
.feito-titulo { margin: 0.5rem 0 0.4rem; font-size: 1.7rem; }
.feito-lead { margin: 0 auto; max-width: 520px; line-height: 1.55; }
.feito-boleto { margin-top: 1.2rem; justify-content: center; }

.feito-dados {
  display: grid; gap: 0.9rem; margin-top: 1rem; padding: 1.1rem 1.3rem;
}
@media (min-width: 640px) { .feito-dados { grid-template-columns: repeat(4, 1fr); } }
.feito-dado { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.feito-dado__rotulo { font-size: 0.75rem; color: var(--c-text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.feito-dado strong { font-size: 0.95rem; }
.feito-dado__total { color: var(--c-primary); font-size: 1.15rem !important; }

.feito-bloco { margin-top: 2rem; }
.feito-itens { display: grid; gap: 0.7rem; }
.feito-item { display: flex; align-items: center; gap: 0.9rem; padding: 0.9rem 1.1rem; }
.feito-item__texto { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; flex: 1; }
.feito-item__texto small { font-size: 0.8rem; }
.feito-item__acao { flex-shrink: 0; }
.feito-item__acao.is-espera { opacity: 0.65; pointer-events: none; }
@media (max-width: 520px) {
  .feito-item { flex-wrap: wrap; }
  .feito-item__acao { width: 100%; }
}

.feito-passos .feito-passo {
  display: flex; flex-direction: column; gap: 0.35rem; color: var(--c-text);
}
.feito-passo:hover { border-color: var(--c-primary); text-decoration: none; }
.feito-passo small { line-height: 1.4; }
.feito-nota { justify-content: center; margin-top: 2rem; }
.feito-nota .material-symbols-outlined { color: var(--c-primary); }

/* ---------- Protótipo: casca do app e Minhas Compras --------------------- */

.sidenav__logo-img { width: 40px; height: 40px; object-fit: contain; flex-shrink: 0; }
.app-topbar__brand .sidenav__logo-img { width: 32px; height: 32px; }
/* A casca do app fica CENTRALIZADA na mesma faixa da landing: quem carrega o
   max-width é o .app-shell (menu + conteúdo), com os mesmos valores do
   .container (ver app.css:982-990), então as margens laterais batem com as da
   landing em todos os 6 níveis. Só no desktop — abaixo de 900px o menu vira
   gaveta e a tela é fluida. */
.app-main { padding-bottom: 4rem; }
@media (min-width: 900px) {
  .app-shell { width: 100%; max-width: 1080px; margin: 0 auto; padding: 0 1rem; }
  /* Quem limita a largura agora é a casca; o teto próprio do .app-main
     estreitaria o conteúdo de novo, dentro de uma faixa já limitada.
     O padding-top é curto porque quem abre o conteúdo é a .app-toolbar: com
     1.6rem sobrava uma faixa de branco no topo de toda tela do app. */
  .app-main { max-width: none; padding: 0.8rem 0 4rem 2rem; }

  :root[data-content-width="1"] .app-shell { max-width: 960px; }
  :root[data-content-width="2"] .app-shell { max-width: 1080px; }
  :root[data-content-width="3"] .app-shell { max-width: 1240px; }
  :root[data-content-width="4"] .app-shell { max-width: 1440px; }
  :root[data-content-width="5"] .app-shell { max-width: 1680px; }
  :root[data-content-width="6"] .app-shell { max-width: none; }
}

.mc-titulo { margin: 0; font-size: 1.6rem; }
.mc-lead { margin: 0.2rem 0 0; }
.mc-abas { display: flex; gap: 0.4rem; flex-wrap: wrap; margin: 0.4rem 0 1.4rem; }
.mc-aba {
  display: inline-flex; align-items: center; gap: 0.35rem;
  padding: 0.5rem 0.9rem; border-radius: 999px; cursor: pointer; font-family: inherit;
  border: 1px solid var(--c-border); background-color: var(--c-surface);
  color: var(--c-text-muted); font-size: 0.85rem; font-weight: 700;
}
.mc-aba:hover { border-color: var(--c-primary); color: var(--c-primary); }
.mc-aba.is-active { background-color: var(--c-primary-soft); border-color: var(--c-primary); color: var(--c-primary-text); }
.mc-aba .material-symbols-outlined { font-size: 1.1rem; }

.mc-plano { display: grid; gap: 1rem; align-items: start; }
@media (min-width: 900px) { .mc-plano { grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); } }
.mc-plano__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; }
.mc-plano__flag { background-color: var(--c-success-soft); color: var(--c-success-text); }
.mc-plano__nome { margin: 0.5rem 0 0.2rem; font-size: 1.35rem; }
.mc-plano__icone { font-size: 2.4rem; color: var(--c-primary); }
.mc-plano__dados { display: grid; gap: 0.8rem; margin: 1.2rem 0; padding: 1rem 0; border-top: 1px solid var(--c-border); border-bottom: 1px solid var(--c-border); }
@media (min-width: 640px) { .mc-plano__dados { grid-template-columns: repeat(3, 1fr); } }
.mc-plano__dados > div { display: flex; flex-direction: column; gap: 0.15rem; }
.mc-plano__dados strong { font-size: 0.92rem; }
.mc-plano__acoes { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.mc-cancelar { color: var(--c-danger); }
.mc-liberado__titulo { display: flex; align-items: center; gap: 0.4rem; margin: 0 0 0.8rem; font-size: 1rem; }
.mc-liberado__titulo .material-symbols-outlined { color: var(--c-primary); }
.mc-sub { margin: 2rem 0 0.8rem; font-size: 1.05rem; }
.mc-recibo { display: inline-flex; align-items: center; gap: 0.25rem; font-size: 0.85rem; font-weight: 600; }
.mc-recibo .material-symbols-outlined { font-size: 1.05rem; }

.mc-lista { display: grid; gap: 0.8rem; }
/* O cartão virou bloco para o painel de detalhes caber embaixo; a linha do
   resumo (ícone + texto + botões) é que continua sendo a faixa flex. */
.mc-item { display: block; padding: 1rem 1.1rem; }
.mc-item__linha { display: flex; align-items: center; gap: 0.9rem; }
.mc-item--novo { border-color: var(--c-primary); }
.mc-item__texto { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; flex: 1; }
.mc-item__texto small { font-size: 0.8rem; }
.mc-item__acao, .mc-item__botoes { flex-shrink: 0; }
/* align-items: sem ele o .pill (inline-block) estica à altura do botão ao lado
   e o border-radius de 999px o transforma numa bolha com o texto no topo. */
.mc-item__botoes { display: flex; gap: 0.4rem; flex-wrap: wrap; align-items: center; }
.mc-novo { background-color: var(--c-primary); color: var(--c-primary-contrast); flex-shrink: 0; }
.mc-progresso { height: 8px; border-radius: 6px; background-color: var(--c-surface-2); overflow: hidden; margin-top: 0.35rem; }
.mc-progresso > span { display: block; height: 100%; background-color: var(--c-primary); border-radius: 6px; }
@media (max-width: 520px) {
  .mc-item__linha { flex-wrap: wrap; }
  .mc-item__acao, .mc-item__botoes { width: 100%; }
  .mc-item__acao { text-align: center; }
}

.mc-pdf { gap: 0.7rem; }
.mc-pdf__capa {
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 3 / 2; border-radius: 16px;
  background-color: var(--c-primary-soft); color: var(--c-primary);
}
.mc-pdf__capa .material-symbols-outlined { font-size: 3rem; }
.mc-pdf__titulo { display: block; line-height: 1.3; }
.mc-pdf small { display: block; margin-top: 0.2rem; font-size: 0.8rem; }
.mc-pdf { position: relative; }
.mc-novo--capa { position: absolute; top: 0.8rem; right: 0.8rem; z-index: 1; }

/* ---------- Protótipo: assinaturas --------------------------------------- */

.planos-topo { text-align: center; margin: 0.5rem 0 2rem; }
.planos-titulo { margin: 0.8rem 0 0.6rem; font-size: 2.1rem; }
.planos-titulo em { color: var(--c-primary); font-style: italic; }
.planos-grade { align-items: start; }
.planos-mes { margin: 0.2rem 0 0; font-size: 0.85rem; color: var(--c-text-muted); }
.planos-de { margin: 0.15rem 0 0; font-size: 0.8rem; color: var(--c-text-muted); }
.planos-itens { list-style: none; margin: 1.1rem 0; padding: 0; display: grid; gap: 0.45rem; text-align: left; }
.planos-itens li { display: flex; align-items: flex-start; gap: 0.45rem; font-size: 0.87rem; line-height: 1.4; }
.planos-itens .material-symbols-outlined { font-size: 1.1rem; color: var(--c-success); flex-shrink: 0; }
.planos-itens li.is-off { opacity: 0.5; }
.planos-itens li.is-off .material-symbols-outlined { color: var(--c-text-muted); }
.is-featured .planos-itens .material-symbols-outlined { color: inherit; }
.planos-nota { margin: 0.6rem 0 0; font-size: 0.78rem; text-align: center; opacity: 0.8; }

.planos-regras .feito-passo { display: flex; flex-direction: column; gap: 0.35rem; }
.planos-faq { max-width: 760px; margin-left: auto; margin-right: auto; }
.faq-item {
  border: 1px solid var(--c-border); border-radius: var(--radius-control);
  background-color: var(--c-surface); padding: 0.9rem 1.1rem; margin-bottom: 0.6rem;
}
.faq-item > summary {
  cursor: pointer; font-weight: 700; font-size: 0.95rem; list-style: none;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
}
.faq-item > summary::-webkit-details-marker { display: none; }
.faq-item > summary::after { content: "+"; color: var(--c-primary); font-size: 1.3rem; line-height: 1; }
.faq-item[open] > summary::after { content: "−"; }
.faq-item > p { margin: 0.7rem 0 0; color: var(--c-text-muted); line-height: 1.6; font-size: 0.9rem; }

.planos-avulso {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1.2rem; flex-wrap: wrap; margin-top: 2rem;
}
.planos-avulso__titulo { margin: 0 0 0.3rem; font-size: 1.2rem; }
.planos-avulso p { margin: 0; max-width: 520px; }
/* O .plan-card já desenha um "✓" por ::before; aqui o ícone é o Material
   Symbols (que também marca o que NÃO vem no plano), então o pseudo sai. */
.planos-itens li { padding-left: 0; }
.planos-itens li::before { content: none; }
/* No cartão em destaque (fundo primário) os textos de apoio herdam o branco. */
.is-featured .planos-mes,
.is-featured .planos-de,
.is-featured .plan-card__price small { color: inherit; opacity: 0.85; }
.is-featured .plan-card__flag { color: var(--c-primary-text); background-color: var(--c-primary-contrast); }
.planos-grade .is-featured h2 { padding-right: 6rem; }
/* Marca em imagem (logo nova) no lugar do ícone local_florist. */
.brand-logo { width: 44px; height: 44px; object-fit: contain; flex-shrink: 0; margin: -6px 0; filter: var(--logo-filter, none); }
.pubfooter__brand .brand-logo { width: 40px; height: 40px; }
.home-cta { margin-top: 2.5rem; }
.home-cta__acoes { display: flex; gap: 0.6rem; flex-wrap: wrap; }

/* ---------- Loja: ajustes pedidos na revisão do cliente ------------------- */

/* Contador do carrinho no rosa escuro da marca (mesmo do botão "Adicionar ao
   carrinho"). Escopado ao carrinho: o badge de notificações continua vermelho. */
.pubnav__cart .badge--count,
.sidenav__link .badge--count.badge--cart,
.app-topbar__quick a[aria-label="Ver carrinho"] .badge--count { background-color: var(--c-primary); }

/* Landing: títulos um degrau abaixo na escala do projeto
   (app.css:70-78). Escopado porque .hero__title e .section__title também são
   usados nas telas de produto, carrinho e assinaturas. */
.public-body .hero__title { font-size: 1.75rem; }
@media (min-width: 900px) { .public-body .hero__title { font-size: 2.25rem; } }
.public-body .section__title { font-size: 1.25rem; }
@media (min-width: 768px) { .public-body .section__title { font-size: 1.4rem; } }

/* ---------- Protótipo: landing acompanhando a Largura do Conteúdo --------- */

/* Texto de apoio das seções: 70% da faixa, 15% de cada lado (o padrão trava em
   640px e espreme a frase em duas linhas). No celular segue em largura total. */
@media (min-width: 768px) {
  .public-body .section__lead { width: 70%; max-width: none; margin-inline: auto; }
}

/* Foto do topo: a moldura ganha a proporção exata do arquivo (1280×714), então
   o background-size: cover deixa de cortar topo e base ao alargar a coluna.
   Cresce até 500px de altura (= 896px de largura) e para; daí em diante o
   espaço extra da faixa vai para a coluna de texto, por conta do fit-content. */
.public-body .hero__art { aspect-ratio: 1280 / 714; min-height: 0; }
@media (min-width: 900px) {
  /* Flex em vez de grade de frações: a moldura pede 47% da faixa e cresce junto
     com ela (largura E altura, pela aspect-ratio), até bater no teto de 896px
     = 500px de altura. Daí em diante ela para e o texto, que é o item flexível,
     fica com todo o espaço restante.
     `min()` porque um fit-content/fr com largura fixa não encolhe: a moldura
     ficava em 896px mesmo na faixa de 1080 e vazava para fora da página. */
  .public-body .hero--split { display: flex; align-items: center; gap: 3rem; }
  .public-body .hero__text { flex: 1 1 auto; min-width: 0; }
  .public-body .hero__art { flex: 0 0 auto; width: min(47%, 896px); }
  /* Sem o teto de 560px o parágrafo acompanha a coluna, mas com limite de
     leitura para não virar linha quilométrica no nível 6. */
  .public-body .hero--split .lead { max-width: 70ch; }
}

/* Grades que ficavam paradas enquanto o resto da página alargava. */
.public-body .pricing-grid,
.public-body .pricing-grid.grid-3 { max-width: none; }
/* As grades de produto seguem com as 3 colunas do padrão (.card-grid), que já
   acompanham a faixa: com auto-fit/auto-fill o Chrome calcula o número de
   trilhas pelo tamanho MÁXIMO, e o nível 2 caía para 2 colunas. */

/* ---------- Feedback pós-resposta: certo/errado com os destaques da múltipla escolha ---------- */
/* O certo/errado leva o mesmo par de sinais da múltipla escolha — ✓ no gabarito,
   ✗ no que foi marcado errado — só que sem a coluna de 2rem da tesoura, que ali
   nunca existiu e cresceria a altura do bloco (ver o ajuste no fim do arquivo).
   O radio continua na tela, apenas desabilitado: some o clique, não o toggle. */
.q-tf--result .q-tf__opt {
  cursor: default;
  justify-content: center;
  gap: 0.5rem;
}
/* O bloco não é mais clicável: o hover do formulário não deve tingir o fundo.
   O :not() é o que impede este seletor (mais específico) de apagar o realce. */
.q-tf--result .q-tf__opt:not(.is-correct):not(.is-wrong):hover { background-color: transparent; }
/* O `.q-tf--result` na frente é o mesmo desempate da múltipla escolha: sem ele,
   `.q-tf__opt:has(input:checked)` (0,2,1) ganha de `.q-tf__opt.is-correct`
   (0,2,0) e quem ACERTA vê a cor de marcada onde devia ver o verde do gabarito. */
.q-tf--result .q-tf__opt.is-correct {
  background-color: var(--c-success-soft);
  color: var(--c-success-text);
}
/* Marcada e errada: mesmo fundo da seleção (o creme) com o rótulo vermelho — é o
   "foi isto que você marcou" continuando visível depois da correção, sem que o
   box mude de cor no caminho. */
.q-tf--result .q-tf__opt.is-wrong { background-color: var(--c-marked); color: var(--c-danger); }

/* Selos da lista de correção do simulado: as mesmas cores do item corrigido. */
.pill--ok {
  border: 1px solid var(--c-success);
  background-color: var(--c-success-soft);
  color: var(--c-success-text);
}
.pill--err {
  border: 1px solid var(--c-danger);
  background-color: var(--c-marked);
  color: var(--c-danger);
}

/* Alvo de foco após a resposta via XHR: sem contorno de teclado indesejado. */
[data-result-anchor]:focus { outline: none; }

/* ===========================================================================
   LOJA — menu recolhível, vitrine, carrinho e pedido
   ===========================================================================
   As classes da loja (.store-*, .cart-*, .passos*, .prod-*) já nasceram aqui
   com o protótipo aprovado; abaixo ficam só os ajustes que a versão real
   trouxe. Tokens `var(--c-*)` sempre — nada de cor literal fora dos blocos
   [data-theme] do topo.
--------------------------------------------------------------------------- */

/* Botão de ocultar/exibir o menu — só faz sentido no desktop; no celular o
   "Ver mais" da barra inferior já abre a gaveta. */
.menu-toggle { display: none; }
@media (min-width: 900px) {
  .menu-toggle {
    display: inline-flex; align-items: center; gap: 0.35rem;
    margin-bottom: 1rem; padding: 0.4rem 0.8rem;
    border: 1px solid var(--c-border); border-radius: 999px;
    background-color: var(--c-surface); color: var(--c-text-muted);
    font-family: inherit; font-size: 0.8rem; font-weight: 600; cursor: pointer;
  }
  .menu-toggle:hover { border-color: var(--c-primary); color: var(--c-primary); }
  .menu-toggle .material-symbols-outlined { font-size: 1.15rem; }

  /* Menu recolhido: o conteúdo assume a faixa inteira. */
  :root[data-sidenav="off"] .app-shell .sidenav { display: none; }
  :root[data-sidenav="off"] .app-shell .app-main { padding-left: 0; }
}

/* Carrinho e conta lado a lado na barra superior do celular. */
.app-topbar__quick { display: inline-flex; align-items: center; gap: 0.9rem; }

/* ---------- Barra de controles no topo do conteúdo (app / influenciador) --- */

/* "Ocultar menu" + "Largura do conteúdo" na mesma linha, acima do conteúdo.
   Escondida abaixo de 900px pelo mesmo motivo do .menu-toggle: no celular o
   menu é gaveta e a faixa é fluida, então nenhum dos dois muda o que se vê. */
.app-toolbar { display: none; }
@media (min-width: 900px) {
  .app-toolbar { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.5rem; }
  /* A margem agora é da barra; no botão ela desalinharia os dois controles. */
  .app-toolbar .menu-toggle { margin-bottom: 0; }
}

/* O popover ancora à direita (app.css:1009) porque na navbar o gatilho fica na
   borda direita da tela. Na barra de conteúdo e na nav pública ele fica à
   esquerda, e manter o `right: 0` jogaria o painel para fora da página. */
@media (min-width: 768px) {
  .cwidth--inline .cwidth__panel { left: 0; right: auto; }
  .fontscale--inline .fontscale__panel { left: 0; right: auto; }
}

/* Fonte e tema na nav da landing: antes do carrinho, e ocultos no celular — ali
   eles vivem abertos dentro do menu ☰ (.pubnav__reading, no fim deste arquivo).
   O breakpoint é o MESMO do menu (768px, app.css ~1362): abaixo dele o menu
   recolhe e leva os controles; a partir dele o menu vira linha e os popovers
   voltam. Um só limiar, sem faixa órfã em que nenhum dos dois aparece.
   A LARGURA não entra neste par: ela tem régua própria (960px, no fim deste
   arquivo), porque abaixo disso nenhum nível dela muda um pixel. */
.pubnav__quick .fontscale { display: none; }
@media (min-width: 768px) {
  .pubnav__quick .fontscale { display: inline-flex; }
}

/* A marca das telas de autenticação virou link para a landing: o <a> passa a
   ser o item flex do .auth-brand, então repete a coluna centralizada e não
   herda sublinhado nem a cor de link. */
.auth-brand__link {
  display: flex; flex-direction: column; align-items: center;
  color: inherit; text-decoration: none;
}
.auth-brand__link:hover { text-decoration: none; }
.auth-brand__link:hover .auth-brand__title { color: var(--c-primary-strong, var(--c-primary)); }

/* Com a casca centralizada, a faixa do app inclui o menu (256px) — então no
   nível 1 sobram ~670px de conteúdo mesmo numa janela larga, e as media
   queries de VIEWPORT do .grid-4 (app.css:848-849) ainda pediriam 4 colunas,
   espremendo os KPIs até cortar o texto. Dentro da casca o grid passa a
   responder à largura que realmente tem. */
.app-body .grid-4 { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }

/* ---------- Carrinho: grupos de cobrança e cupons aplicados ---------------- */

/* A coluna do resumo passou a ter mais de um cartão (um por grupo de cobrança,
   mais o bloco de cupom), então ela mesma vira uma pilha espaçada. */
.cart-side { display: flex; flex-direction: column; gap: 1rem; }

/* Título do grupo na lista de itens; só aparece no carrinho misto. */
.cart-grupo__titulo { margin: 0.4rem 0 0; font-size: 1.05rem; }
.cart-main > .cart-grupo__titulo:first-child { margin-top: 0; }

/* Cupom aplicado: código, efeito e um botão "Remover" com rótulo em texto —
   trocar um cupom pelo outro é uma tarefa comum e um "×" não a anunciava.
   A lista inclui o cupom que não está descontando (o geral que perdeu para um
   cupom de tipo), justamente para poder ser removido. */
.cart-cupons { list-style: none; margin: 0.7rem 0 0; padding: 0; display: grid; gap: 0.5rem; }
.cart-cupom-item {
  display: flex; align-items: flex-start; gap: 0.6rem;
  padding: 0.55rem 0.7rem; border-radius: var(--radius-control);
  background-color: var(--c-surface-2); border: 1px solid var(--c-border);
}
.cart-cupom-item__texto { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; flex: 1; }
.cart-cupom-item__texto strong { font-size: 0.85rem; font-weight: 800; }
.cart-cupom-item__texto small { font-size: 0.75rem; line-height: 1.35; }
.cart-cupom-item__valor { color: var(--c-success-text); font-weight: 700; }
.cart-cupom-item form { margin: 0; flex-shrink: 0; }

/* Os dois modos de cobrança da assinatura, na vitrine e na página do plano. */
.sub-buttons { display: grid; gap: 0.5rem; }

/* ---------- Minha assinatura: lista e painel de detalhes ------------------- */

.sub-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.sub-head h1 { margin: 0; }
.sub-head__acoes { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.sub-head__acoes .material-symbols-outlined { font-size: 1.05rem; }

.sub-list { display: grid; gap: 0.9rem; }
.sub-item { display: block; }

/* Painel de detalhes, usado pela assinatura e por Minhas Compras (compras e
   pedidos): abre embaixo do cartão, separado por um filete, e chega VAZIO do
   servidor — o conteúdo só é buscado quando o cliente clica em "Detalhes".
   A seta acompanha o estado, único sinal de "aberto" no botão. */
[data-panel-toggle] .material-symbols-outlined { transition: transform .15s ease; }
[data-panel-toggle][aria-expanded="true"] .material-symbols-outlined { transform: rotate(180deg); }

.detalhe-painel { margin-top: 1rem; padding-top: 0.9rem; border-top: 1px solid var(--c-border); }
.detalhe-painel[hidden] { display: none; }
.detalhe-titulo { margin: 0 0 0.6rem; font-size: 0.95rem; }
.detalhe-titulo + .table { margin-top: 0; }

.detalhe-grid {
  margin: 0 0 1.1rem; display: grid; gap: 0.7rem 1.4rem;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.detalhe-grid dt { color: var(--c-text-muted); font-size: 0.78rem; }
.detalhe-grid dd { margin: 0.1rem 0 0; font-weight: 700; font-size: 0.92rem; }
.detalhe-painel .cart-aviso { margin-bottom: 1.1rem; }
.detalhe-acoes { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; }

/* =========================================================================
   Três modos de estudo + ordenação da listagem de questões
   ========================================================================= */

/* Respiro entre os botões de modo e o seletor "Por página" — sem ele os dois
   grupos leem como um controle só. A partir de 640px, que é onde o cabeçalho
   deixa de quebrar em linhas. */
@media (min-width: 640px) {
  .page-head__actions .per-page { margin-left: 1rem; }
}

/* Linha de ações do filtro: botões à esquerda, contagem de questões à direita. */
.filters__actions { justify-content: space-between; align-items: center; }
.filters__buttons { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.filters__count { font-size: 0.85rem; white-space: nowrap; }

/* "3x" — quantas vezes o aluno já respondeu a questão, antes do favoritar. */
.q-card__attempts {
  align-self: center;
  font-variant-numeric: tabular-nums;
}

/* =========================================================================
   Acabamento: "Meus filtros" numa linha, título de página e casca do app
   ========================================================================= */

/* Rótulo + chips na mesma linha. A margem inferior sai porque o formulário
   "salvar filtro atual" já traz a sua (e sem ele o cabeçalho é a única linha
   do cartão, onde a folga viraria espaço morto). */
.saved-filters__head { flex-wrap: wrap; margin-bottom: 0; }
.saved-filters__head .saved-filters__list { min-width: 0; }

/* Título de página um nível abaixo do h1 base — os mesmos valores do h2, para
   a escala continuar sendo a mesma. Vale para as telas com .page-head (app,
   influenciador e admin); a landing e a autenticação não têm esse cabeçalho. */
.page-head h1 { font-size: 1.4rem; }
@media (min-width: 768px) {
  .page-head h1 { font-size: 1.7rem; }
}

/* Separador dentro da navegação do menu (mesma linha do .sidenav__nav e do
   .sidenav__foot). Com o gap 0.2rem do nav, a folga de cada lado dá 0.6rem —
   a mesma dos outros dois. */
.sidenav__sep { margin: 0.4rem 0; border: 0; border-top: 1px solid var(--c-border); }

/* ---------- Painel: linha atividade + rosca, disciplinas rolável ----------
   O Chart.js roda com maintainAspectRatio: false, então a altura vem sempre do
   .chart-box. Aqui ela passa a ser variável (mantendo os 260px como padrão),
   para o gráfico por disciplina crescer conforme o número de barras. */
.chart-box { height: var(--chart-h, 260px); }

/* Flex (não grid) de propósito: a quebra precisa responder à largura do
   container, não à do viewport — o painel vive dentro da casca .app-shell, com
   menu lateral de ~256px, onde as media queries do .grid-2 quebram mal. */
.dash-row { display: flex; flex-wrap: wrap; gap: 1rem; align-items: flex-start; }
/* Só o gráfico de atividade cresce; a rosca fica na largura fixa de 234px
   (= 90% dos 260px de altura do gráfico de atividade). O min-width: 0 é o mesmo
   caso do .grid > * — sem ele o canvas trava na largura intrínseca e transborda. */
.dash-row__grow { flex: 1 1 320px; min-width: 0; }
.dash-row__fixed { flex: 0 0 auto; }
.chart-box--donut { width: 234px; max-width: 100%; margin-inline: auto; }

/* Disciplinas: cresce com o número de barras (--chart-h vem do Blade) até 660px,
   e a partir daí rola por dentro do card. */
.chart-scroll { max-height: 660px; overflow-y: auto; }

/* ---------- Diálogo de confirmação (substitui o confirm() do navegador) ----
   Mesmo cartão em desktop e mobile; o <dialog> nativo cuida de centralizar,
   do backdrop, do ESC e do foco (ver o bloco em app.js). */
.confirm {
  width: min(26rem, calc(100vw - 2rem));
  /* O reset do topo (`* { margin: 0 }`) mata o `margin: auto` que o navegador dá
     ao <dialog> modal — sem esta linha ele encosta no canto superior esquerdo. */
  margin: auto;
  padding: 1.35rem;
  border: 1px solid var(--c-border);
  border-radius: var(--radius-card);
  background: var(--c-surface);
  color: var(--c-text);
  box-shadow: 0 8px 28px var(--c-shadow);
}
.confirm::backdrop { background: rgba(0, 0, 0, 0.55); }
.confirm__titulo { margin: 0 0 0.4rem; }
.confirm__msg { margin: 0; color: var(--c-text-muted); }
.confirm__acoes { display: flex; gap: 0.5rem; justify-content: flex-end; margin-top: 1.2rem; }
/* No celular os botões empilham e ocupam a largura toda. column-reverse deixa o
   "Voltar" por último — mais perto do polegar, como nas folhas de ação do celular:
   o toque distraído cai no cancelar, não no destrutivo. A ordem do DOM (e portanto
   a do foco/teclado) continua sendo "Voltar" primeiro. */
@media (max-width: 480px) {
  .confirm__acoes { flex-direction: column-reverse; }
  .confirm__acoes .btn { width: 100%; justify-content: center; }
}

/* ---------- Aviso de e-mail não confirmado + campos travados --------------- */

/* Variante "atenção" dos alertas (Minha conta: e-mail ainda não confirmado).
   color-mix a partir da superfície do tema para funcionar nos cinco. */
.alert--warning {
  background-color: color-mix(in srgb, var(--c-warning) 15%, var(--c-surface));
  border-color: var(--c-warning);
  color: var(--c-text);
}

/* Campo travado pelo AdminGuard (perfil admin / conta ativa do último admin):
   o motivo aparece no <small> ao lado — aqui só o sinal visual. */
.checkbox-row input:disabled + label,
.role-option input:disabled + span {
  opacity: 0.6;
  cursor: not-allowed;
}

/* ---------- Diálogo em modo aviso (um botão só) --------------------------- */

/* O mesmo <dialog class="confirm"> serve de aviso — o teto diário da Bela IA é o
   primeiro caso. O "Voltar" some porque não há o que cancelar, e a regra precisa
   ser explícita: o `display: inline-flex` de .btn é de autor e venceria o
   [hidden] do navegador, deixando o botão visível e inerte (mesma armadilha
   anotada em .field__toggle). */
.confirm__acoes .btn[hidden] { display: none; }

/* ---------- Tesoura: descartar alternativa -------------------------------- */

/* O aluno risca a alternativa que já eliminou. O estado é do navegador
   (localStorage `bc_cortes`, ver public/js/app.js) e nunca chega ao servidor.
   Todos os seletores daqui são guardados por :has(.q-option__hit) ou .is-cut:
   as alternativas já corrigidas (_result-options) não têm nem um nem outro e
   seguem exatamente como estavam. */

/* Com a tesoura, .q-option deixou de ser o <label> e virou a caixa; o <label>
   interno é a área clicável. O padding desce para ele para o alvo de toque
   continuar sendo a linha inteira — sem isso, a borda de 0.85rem deixaria de
   marcar o radio. O gap zera: quem afasta o botão é a margem dele. */
.q-option:has(.q-option__hit) { padding: 0; gap: 0; cursor: default; }
.q-option__hit {
  flex: 1;
  min-width: 0;
  display: flex; align-items: flex-start; gap: 0.7rem;
  padding: 0.7rem 0.85rem;
  border-radius: inherit;
  cursor: pointer;
}

/* Sempre visível, nunca só no :hover — no toque não existe hover, e uma tesoura
   escondida seria invisível para a maioria dos alunos (mobile-first). Discreta
   na cor de apoio para não competir com a letra da alternativa. Abre a linha,
   antes do radio: descartar vem antes de escolher. */
.q-option__cut {
  flex-shrink: 0;
  align-self: flex-start;
  margin: 0.5rem 0 0 0.5rem;
  width: 2rem; height: 2rem;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: none; border-radius: 50%;
  color: var(--c-text-muted);
  cursor: pointer;
  transition: color 0.15s ease, background-color 0.15s ease;
}
.q-option__cut:hover { color: var(--c-primary); background-color: var(--c-surface-2); }
.q-option__cut:focus-visible { outline: 2px solid var(--c-primary); outline-offset: 2px; }
.q-option__cut .material-symbols-outlined { font-size: 1.15rem; }

/* Descartada: texto tachado e esmaecido, letra esmaecida junto. O
   :not(:has(input:checked)) é o desempate com a regra de seleção
   (.q-option:has(input:checked)): marcar SEMPRE vence o risco, mesmo que o JS
   falhe em limpar a classe. E como este bloco vem depois no arquivo, ele ganha
   do .q-option:hover — daí precisar reafirmar o hover abaixo. Desde que a borda
   saiu do item, o que se reafirma é o FUNDO: reafirmar `border-color` aqui
   desenharia uma borda que mais nenhuma alternativa tem. */
.q-option.is-cut:not(:has(input:checked)) { background-color: transparent; }
.q-option.is-cut:not(:has(input:checked)):hover { background-color: transparent; }
.q-option.is-cut:not(:has(input:checked)) .q-option__text {
  color: var(--c-text-muted);
  text-decoration: line-through;
  text-decoration-thickness: 2px;
}
.q-option.is-cut:not(:has(input:checked)) .q-option__letter {
  background-color: var(--c-surface-2);
  color: var(--c-text-muted);
  text-decoration: line-through;
}
/* Riscada, o botão vira o "desfazer" e passa a ser o único ponto aceso da
   linha — é o convite para reverter. */
.q-option.is-cut .q-option__cut { color: var(--c-primary); }

/* ---------- FAQ público (/perguntas-frequentes) ----------
   O accordion .faq-item já existia (bloco dos planos, ~l.2574) e é reusado aqui.
   A resposta é HTML do admin — pode ter vários <p>, listas e tabelas —, então o
   que a regra `.faq-item > p` fazia para o parágrafo único passa a valer para o
   invólucro e seus filhos. */
.faq-secao__titulo {
  font-size: 1.05rem; margin: 1.6rem 0 0.8rem;
  padding-bottom: 0.4rem; border-bottom: 1px solid var(--c-border);
}
.faq-item__resposta {
  margin-top: 0.7rem; color: var(--c-text-muted);
  line-height: 1.6; font-size: 0.9rem;
}
.faq-item__resposta > :first-child { margin-top: 0; }
.faq-item__resposta > :last-child { margin-bottom: 0; }
.faq-item__resposta ul, .faq-item__resposta ol { padding-left: 1.2rem; }

/* Link do PDF no meio do texto: sublinhado, para não se perder na prosa. */
.faq-pdf-link { color: var(--c-primary); text-decoration: underline; }
.faq-pdf-link:hover { text-decoration: none; }

/* Botão de download quando a resposta não referencia o PDF no texto. */
.faq-anexo { margin: 0.9rem 0 0; }
.faq-anexo .btn { display: inline-flex; align-items: center; gap: 0.35rem; }
.faq-anexo .material-symbols-outlined { font-size: 1.1rem; }

/* ---------- Hubs do admin (/admin/taxonomia, /admin/loja) ----------
   Cards de altura igual na grade, com os botões alinhados no rodapé de cada um
   (daí o margin-top:auto): sem isso a linha de botões dança conforme o tamanho
   da descrição. */
.hub-card { display: flex; flex-direction: column; }
.hub-card .card__title { display: flex; align-items: center; gap: 0.4rem; }
.hub-card .card__title .material-symbols-outlined { color: var(--c-primary); font-size: 1.25rem; }
.hub-card__total { margin: 0 0 0.35rem; font-size: 0.9rem; color: var(--c-text-muted); }
.hub-card__total strong { color: var(--c-text); font-size: 1.15rem; }
.hub-card__desc { margin: 0 0 0.9rem; font-size: 0.85rem; line-height: 1.5; }
.hub-card .page-head__actions { margin-top: auto; }
.hub-origens { margin: 0.5rem 0 0.9rem; padding-left: 1.1rem; font-size: 0.87rem; line-height: 1.6; }
.hub-origens li { margin-bottom: 0.35rem; }

/* ---------- Reuso de material de apoio no cadastro de questões ----------
   Dois seletores (texto e figura já usados em questões anteriores) e a caixa do
   texto vinculado. Tudo dentro do <form> da questão — ver form.blade.php. */
.picker-panel {
  border: 1px solid var(--c-border);
  border-radius: 10px;
  padding: 0.75rem;
  background-color: var(--c-surface-2);
  max-height: 340px;
  overflow-y: auto;
}
.picker__busca { display: flex; gap: 0.5rem; margin-bottom: 0.6rem; }
.picker__busca .input { flex: 1; }
.picker__item {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--c-border);
}
.picker__item:last-child { border-bottom: 0; }
.picker__item .btn { flex-shrink: 0; }

/* Texto de apoio vinculado: leitura, porque ele serve a outras questões. */
.ref-linked {
  border: 1px solid var(--c-border);
  border-left: 3px solid var(--c-primary);
  border-radius: 10px;
  padding: 0.75rem;
  margin-top: 0.75rem;
  background-color: var(--c-surface-2);
}
.ref-linked__titulo { display: flex; align-items: center; gap: 0.5rem; margin: 0 0 0.35rem; }
.ref-linked__trecho { font-size: 0.85rem; line-height: 1.5; margin: 0 0 0.5rem; }

/* "Usar a última": um <label> com a miniatura dentro do próprio botão. */
.ref-last-img { display: inline-flex; align-items: center; gap: 0.4rem; cursor: pointer; }
.ref-last-img img { width: 34px; height: 26px; object-fit: cover; border-radius: 4px; }

/* ---------- Botão "Escrever com a Bela IA" no formulário de questão ---------- */
.ai-draft { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin-bottom: 0.5rem; }
.ai-draft .btn { display: inline-flex; align-items: center; gap: 0.35rem; }
.ai-draft .material-symbols-outlined { font-size: 1.05rem; }
.ai-draft__status { margin: 0; font-size: 0.82rem; }

/* Veredito da IA: dificuldade sugerida e divergência de gabarito. Texto — o
   <select> Dificuldade continua sendo escolha do humano. */
.ai-verdict {
  border: 1px solid var(--c-border);
  border-left: 3px solid var(--c-primary);
  border-radius: 10px;
  padding: 0.7rem 0.85rem;
  background-color: var(--c-surface-2);
}
.ai-verdict__linha { display: flex; align-items: flex-start; gap: 0.45rem; margin: 0; font-size: 0.87rem; line-height: 1.5; }
.ai-verdict__linha + .ai-verdict__linha { margin-top: 0.5rem; }
.ai-verdict .material-symbols-outlined { font-size: 1.1rem; color: var(--c-primary); }
.ai-verdict__linha--alerta .material-symbols-outlined { color: var(--c-warning); }

/* ---------- Correção da alternativa: ícone no lugar da tesoura ---------------
   Ao responder, a tesoura de cada alternativa dá lugar a um ícone: ✓ verde no
   gabarito, ✗ vermelho no que o aluno marcou errado, e nada nas demais. A caixa
   é EXATAMENTE a da .q-option__cut (2rem + a mesma margem) porque o span vazio
   das outras alternativas é o que impede o texto de saltar para a esquerda — o
   card não pode se reorganizar entre responder e ver o resultado.

   O mesmo par de sinais vale no certo/errado, mas lá a caixa de 2rem não serve:
   o bloco é uma linha só, centrada, e ela o faria crescer de altura. Ali o ícone
   acompanha o rótulo, sem a margem que aqui alinha com a tesoura. */
.q-option__mark {
  flex-shrink: 0;
  align-self: flex-start;
  margin: 0.5rem 0 0 0.5rem;
  width: 2rem; height: 2rem;
  display: inline-flex; align-items: center; justify-content: center;
}
.q-tf--result .q-option__mark {
  align-self: center;
  margin: 0;
  width: 1.4rem; height: 1.4rem;
}
/* O tique precisa ler como o "V" de marcação, e não como um traço fino. A fonte
   de ícones é variável (eixo wght 100..700, ver layouts/partials/head.blade.php),
   então engrossar é uma linha — sem trocar o glifo e sem mexer na caixa. */
.q-option__mark .material-symbols-outlined {
  font-size: 1.25rem;
  font-variation-settings: 'wght' 600;
}
.q-option.is-correct .q-option__mark,
.q-tf__opt.is-correct .q-option__mark { color: var(--c-success-text); }
.q-option.is-wrong .q-option__mark,
.q-tf__opt.is-wrong .q-option__mark { color: var(--c-danger); }

/* O bloco corrigido reusa a estrutura do respondível (.q-option__hit), então
   herda o padding-zero da regra da tesoura — mas nada ali é clicável: o <span>
   substitui o <label> e o radio vai desabilitado, visível e sem cursor de mão. */
   O hover: corrigida não é clicável, então a regra genérica abaixo anula o realce
   cinza do modo responder — e as duas reafirmações trazem de volta o que a
   alternativa tinha. Elas não são redundância: sem cada uma, passar o mouse por
   cima APAGA o fundo do gabarito ou o da marcada (a genérica é (0,3,0) e vem
   depois das regras de estado, também (0,3,0), no topo do arquivo). No
   certo/errado não há par equivalente e nem precisa: lá as regras de estado são
   `.q-tf--result .q-tf__opt.is-*` (0,3,0) contra um `.q-tf__opt:hover` (0,2,0). */
.q-options--result .q-option__hit { cursor: default; }
.q-options--result .q-option:hover { background-color: transparent; }
.q-options--result .q-option.is-correct:hover { background-color: var(--c-success-soft); }
.q-options--result .q-option.is-wrong:hover { background-color: var(--c-marked); }
.q-option input[type="radio"]:disabled,
.q-tf__opt input[type="radio"]:disabled { cursor: default; }

/* ---------- Linha de ação da questão -----------------------------------------
   Botão primeiro, depois o veredito, o link da comunidade e o percentual — tudo
   numa linha só. As barras abrem logo abaixo dela (o painel é irmão desta linha,
   não do rodapé), e é por isso que este bloco existe em vez de a linha morar no
   .q-card__footer. */
.q-actionbar { margin-top: 1.25rem; }
.q-actionbar__line {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 0.5rem 0.85rem;
}
.q-verdict-inline { font-weight: 800; font-size: 1.05rem; }
.q-verdict-inline.is-ok { color: var(--c-success-text); }
.q-verdict-inline.is-err { color: var(--c-danger); }
.q-actionbar__link {
  color: var(--c-text-muted); font-weight: 600; font-size: 0.9rem;
}
.q-actionbar__link:hover { color: var(--c-primary); text-decoration: none; }
.q-actionbar__link[aria-expanded="true"] { color: var(--c-primary); }
.q-actionbar__rate { color: var(--c-text-muted); font-size: 0.9rem; }
/* O painel chega renderizado e apenas oculto — sem o [hidden] explícito, o
   display:flex/block das regras internas o traria visível. */
.q-actionbar .answer-dist[hidden] { display: none; }

/* Pílula de alerta na fila de moderação: resposta que foi digitada à mão por
   quem cadastrou, porque o gabarito não pôde ser lido. É o item da fila que mais
   merece um segundo olhar, e o `.badge` comum (azul, de informação) não diria
   isso. Reusa o token de aviso do resto do sistema. */
.badge--warning {
  background-color: color-mix(in srgb, var(--c-warning) 20%, var(--c-surface));
  color: var(--c-text);
}

/* Rodapé do sidenav no celular: o drawer vai de top:0 a bottom:0 e o "Sair"
   encostava na borda inferior — atrás da barra do navegador/gestos do
   aparelho, inacessível. Folga da altura de um item do menu (~2.6rem =
   2×0.62rem de padding + a linha do ícone) somada à safe area (0 onde não
   existe). Vale para as cascas de cliente, influenciadora e admin, que
   compartilham o .sidenav; no desktop nada muda. */
@media (max-width: 899px) {
  /* :last-child porque nas cascas de cliente e influenciadora o rodapé deixou de
     ser o fim da gaveta — depois dele vem a seção "Leitura", que leva a folga
     (ver .sidenav__reading no fim deste arquivo). Sem isso seriam duas. */
  .sidenav__foot:last-child { padding-bottom: calc(2.6rem + env(safe-area-inset-bottom)); }
}

/* ---------- Loja: autocomplete da busca + scroll infinito ---------- */
/* Painel de sugestões da busca, ancorado no .store-search (já é
   position:relative por causa do ícone). Mesma receita visual do
   .msel__panel — superfície, borda, sombra e raio idênticos. */
.store-suggest {
  position: absolute;
  z-index: 30;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  background-color: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: 10px;
  box-shadow: 0 6px 20px var(--c-shadow);
  max-height: 320px;
  overflow-y: auto;
}
.store-suggest[hidden] { display: none; }
.store-suggest__item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 0.9rem;
  color: var(--c-text);
  text-decoration: none;
}
.store-suggest__item:hover { background-color: var(--c-surface-2); text-decoration: none; }
.store-suggest__item .material-symbols-outlined { font-size: 1.1rem; color: var(--c-primary); }
.store-suggest__name { font-weight: 600; }
.store-suggest__meta { margin-left: auto; font-size: 0.85rem; white-space: nowrap; }

/* Sentinela do scroll infinito: precisa de área para o IntersectionObserver
   ter o que observar; visualmente não existe. */
.store-sentinel { height: 1px; }

/* --- Item do carrinho vira link para a página do produto ---------------- */
/* O `a` global pinta com --c-primary e sublinha no hover; aqui o link herda
   a cor do card e só o nome sublinha, para o bloco não virar um borrão. */
a.cart-item__texto { color: inherit; }
a.cart-item__texto:hover { text-decoration: none; }
a.cart-item__texto:hover .cart-item__nome { text-decoration: underline; }

/* ---------------------------------------------------------------------------
   Aviso de cookies (LGPD) — layouts/partials/cookie-banner.blade.php.
   Barra fixa no rodapé, não bloqueante. z-index 120: acima da .bottomnav (50)
   e da .sidenav (100); os <dialog> nativos seguem por cima (top layer).
--------------------------------------------------------------------------- */
.cookie-banner {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 120;
  background: var(--c-surface);
  border-top: 1px solid var(--c-border);
  box-shadow: 0 -8px 24px var(--c-shadow);
  padding: 1rem;
}

.cookie-banner__inner {
  max-width: 60rem;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.cookie-banner__texto p {
  margin: 0.25rem 0 0;
  font-size: 0.9rem;
  color: var(--c-text-muted);
}

/* Rola dentro de si quando o painel aberto não cabe (celular deitado). */
.cookie-banner__painel {
  display: grid;
  gap: 0.75rem;
  border-top: 1px solid var(--c-border);
  padding-top: 0.75rem;
  max-height: 45vh;
  overflow-y: auto;
}

/* Mesmo caso do .field__toggle: o `display: grid` acima é regra de autor e
   venceria o [hidden] do navegador — sem esta linha o painel "Personalizar"
   nasce ABERTO para todo visitante (era o que fazia o aviso tomar a tela
   inteira no celular) e o botão de alternar não consegue fechá-lo. */
.cookie-banner__painel[hidden] { display: none; }

.cookie-cat__cabeca {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.cookie-cat__cabeca input { width: 1rem; height: 1rem; }

.cookie-cat p {
  margin: 0.25rem 0 0 1.5rem;
  font-size: 0.85rem;
}

.cookie-banner__acoes {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* Desktop: texto e botões lado a lado; o painel, quando aberto, ocupa a
   linha de baixo inteira (order empurra para depois das ações). */
@media (min-width: 48rem) {
  .cookie-banner__inner {
    flex-flow: row wrap;
    align-items: center;
    justify-content: space-between;
  }
  .cookie-banner__texto { flex: 1 1 30rem; }
  .cookie-banner__painel { flex-basis: 100%; order: 3; }
}

/* ---------- Seletor de tema (claro / escuro / automático) ----------------- */
/* A casca (gatilho + painel + ancoragem --inline + ocultação no celular da
   nav pública) reusa .fontscale de propósito — ver theme-popover.blade.php.
   Aqui só a anatomia dos três botões, que têm ícone + rótulo. */
.themesel__btn {
  flex: 1; display: inline-flex; flex-direction: column; align-items: center;
  justify-content: center; gap: .15rem; padding: .45rem .2rem;
  border-radius: 8px; cursor: pointer;
  border: 1px solid var(--c-border); background: var(--c-surface);
  color: var(--c-text); font-size: .72rem; font-weight: 600; line-height: 1.1;
  transition: border-color .12s ease, background-color .12s ease;
}
.themesel__btn .material-symbols-outlined { font-size: 1.25rem; color: var(--c-text-muted); }
.themesel__btn:hover { border-color: var(--c-primary); }
.themesel__btn.is-active { border-color: var(--c-primary); background: var(--c-primary-soft); }
.themesel__btn.is-active .material-symbols-outlined { color: var(--c-primary); }
.themesel__btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--c-primary-soft); }
.themesel__summary-glyph { font-size: 1.15rem; line-height: 1; color: var(--c-text); }

/* =========================================================================
   Central de Logs
   Só tokens, como manda a folha: nenhuma cor literal daqui para baixo.
   ========================================================================= */

/* Crítico — o único vermelho da Central. Usa o token de perigo derivado,
   não o sólido, para a tabela não virar um bloco de alarme. */
.pill--danger {
  background-color: color-mix(in srgb, var(--c-danger) 18%, var(--c-surface));
  color: color-mix(in srgb, var(--c-danger) 78%, var(--c-text));
}

/* Barra de busca por pessoa: a porta de entrada da Central. */
.log-busca__linha { display: flex; gap: 0.5rem; align-items: center; }
.log-busca__linha .input { flex: 1 1 auto; }
.log-busca__ajuda { font-size: 0.8125rem; margin: 0.5rem 0 0; }

/* Colunas técnicas (data, IP, rota, evento) em monoespaçada: alinham a
   leitura vertical de uma tabela que se lê varrendo, não lendo. */
.log-mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.8125rem;
  white-space: nowrap;
}

/* Estorno entra negativo no valor — precisa saltar aos olhos numa coluna
   em que todo o resto é entrada de dinheiro. */
.log-valor--negativo { color: var(--c-danger); font-weight: 700; }

.log-diff-resumo { font-size: 0.8125rem; color: var(--c-text-muted); }

/* Diff "antes → depois" da tela de detalhe. */
.diff__old { text-decoration: line-through; color: var(--c-text-muted); }
.diff__new { font-weight: 600; }

/* Contexto e trace: bloco técnico, rolagem própria para nunca empurrar a
   página na horizontal. */
.log-trace {
  background-color: var(--c-surface-2);
  color: var(--c-text);
  padding: 0.75rem 1rem;
  border-radius: 8px;
  overflow-x: auto;
  font-size: 0.8125rem;
  line-height: 1.5;
  max-height: 28rem;
}

/* Selo de alertas críticos no item "Logs" do menu admin. */
.subnav__badge {
  display: inline-block;
  margin-left: 0.35rem;
  min-width: 1.25rem;
  padding: 0 0.3rem;
  border-radius: 999px;
  background-color: var(--c-danger);
  color: var(--c-danger-contrast);
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: 1.25rem;
  text-align: center;
}

/* Instrução do alerta: texto de apoio, não protagonista da linha. */
.log-primeiro-socorro { font-size: 0.8125rem; color: var(--c-text-muted); max-width: 32rem; }

/* ---------- Ajuda de campo: a bolha do "?" ------------------------------ */
/* Genérico de propósito: qualquer campo que precise explicar uma regra ganha
   o mesmo par (input + <details>). O gatilho é <summary> e não <button>
   porque dentro de um <form> botão sem type="button" é submit — e porque o
   <details> abre/fecha sozinho, sem uma linha de JS (mesmo padrão dos
   popovers de fonte/largura/tema da navbar). A bolha copia os valores de
   .msel__panel para ler como parte da mesma linha de filtros. */
.field-help { position: relative; display: flex; align-items: center; gap: 0.4rem; }
/* min-width: 0 — sem ele o input se recusa a encolher e estoura a célula da grade. */
.field-help > .input { flex: 1; min-width: 0; }

.field-help__btn {
  list-style: none;
  cursor: pointer;
  user-select: none;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 999px;
  border: 1px solid var(--c-border);
  background-color: var(--c-surface);
  color: var(--c-text-muted);
  font-size: 0.8rem;
  font-weight: 700;
  line-height: 1;
}
.field-help__btn::-webkit-details-marker { display: none; }
.field-help__btn:hover,
.field-help__pop[open] .field-help__btn { border-color: var(--c-primary); color: var(--c-primary); }

.field-help__panel {
  position: absolute;
  z-index: 30;
  top: calc(100% + 4px);
  left: 0;
  /* Mais larga que a célula da grade (é absoluta, pode): com 100% da coluna o
     texto virava uma coluna estreita e alta. O max-width segura no celular. */
  width: 21rem;
  max-width: calc(100vw - 2rem);
  margin: 0;
  padding: 0.6rem 0.7rem;
  background-color: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: 10px;
  box-shadow: 0 6px 20px var(--c-shadow);
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--c-text);
}
/* A bolha tem dois parágrafos (a regra e a nota); o espaço entre eles vem daqui
   para o painel não depender das margens padrão do <p>. */
.field-help__panel p { margin: 0; }
.field-help__panel p + p { margin-top: 0.45rem; }
.field-help__note { color: var(--c-text-muted); }

/* ---------------------------------------------------------------------------
   Skip-link (WCAG 2.4.1) — primeiro focável dos 4 layouts.
   Fora da tela até receber foco: quem usa teclado/leitor pula a navegação
   inteira (a sidenav do cliente é longa) e cai direto no <main id="conteudo">.
   z-index 130: acima do aviso de cookies (120), senão o link apareceria por
   baixo do banner justamente na primeira visita.
--------------------------------------------------------------------------- */
.skip-link {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 130;
  transform: translateY(-120%);
  background: var(--c-surface);
  color: var(--c-primary);
  border: 1px solid var(--c-border);
  border-radius: 0 0 var(--radius-control) 0;
  box-shadow: 0 4px 16px var(--c-shadow);
  padding: 0.6rem 1rem;
  font-weight: 600;
  text-decoration: none;
}

.skip-link:focus {
  transform: translateY(0);
}

/* ---------------------------------------------------------------------------
   Aviso de cookies no celular: teto de altura.
   Com o texto completo (que é compromisso de LGPD e não se corta), o banner
   chegava a ocupar a tela inteira em 390x844 — a página sumia atrás dele na
   primeira visita.

   Quem ganha teto e rolagem é o TEXTO, não o banner inteiro: as ações
   ("Aceitar todos", "Apenas essenciais", "Personalizar") são os últimos filhos
   do markup, então clampar o pai as empurraria para fora da dobra interna e o
   visitante teria de rolar dentro do aviso para conseguir aceitá-lo.
--------------------------------------------------------------------------- */
@media (max-width: 47.99rem) {
  .cookie-banner__texto {
    max-height: 30vh;
    overflow-y: auto;
  }

  .cookie-banner__painel {
    max-height: 35vh;
  }
}

/* ---------- Economia do kit (vitrine, produto e home) --------------------- */
/* Irmã de .store-card__was: o riscado diz o preço cheio, esta diz o ganho.
   Usa --c-success-text (e não --c-success) porque é texto: o verde puro não
   atinge 4.5:1 sobre o fundo do card. */
.kit-economia {
  color: var(--c-success-text);
  font-size: 0.85rem;
  font-weight: 600;
  white-space: nowrap;
}

/* ---------- Pedidos aguardando pagamento (/assinatura) -------------------- */
/* Reusa o accordion .faq-item (bloco dos planos). O corpo aqui não é prosa do
   admin como no FAQ, e sim o aviso + os cartões dos pedidos — daí o invólucro
   próprio em vez de .faq-item__resposta. */
.sub-pendentes__corpo { margin-top: 0.8rem; display: grid; gap: 0.8rem; }
.sub-pendentes__corpo > p { margin: 0; font-size: 0.9rem; line-height: 1.6; }
.sub-pendentes .sub-list { display: grid; gap: 0.7rem; }

/* ---------------------------------------------------------------------------
   Editor de conteúdo da landing (/admin/site/conteudo)

   Reusa a bolha "?" da busca de questões (.field-help*, acima). Duas variantes
   novas: --label, para pendurar a bolha no rótulo dos campos altos (o painel é
   absoluto em relação ao .field-help, e ao lado de um repetidor inteiro ele
   apareceria a meio metro do "?" clicado), e o crescimento dos controles que
   não são <input class="input">.
--------------------------------------------------------------------------- */
.field-help > .textarea,
.field-help > select.input,
.field-help > .icon-picker { flex: 1; min-width: 0; }

.field-help--label { align-items: center; }
.field-help--label .label { margin: 0; }

.site-content__indice { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.75rem; }
.site-content__indice .pill { display: inline-flex; align-items: center; gap: 0.3rem; text-decoration: none; }
.site-content__indice .pill .material-symbols-outlined { font-size: 1rem; }

/* Miniatura da imagem atual do campo. object-fit para a proporção real não
   distorcer — o hero é largo, o favicon é quadrado. */
.site-thumb {
  max-width: 280px;
  max-height: 150px;
  border-radius: 10px;
  border: 1px solid var(--c-border);
  background-color: var(--c-surface-2);
  object-fit: contain;
}

.icon-picker { display: flex; align-items: center; gap: 0.5rem; }
.icon-picker .input { flex: 1; min-width: 0; }
.icon-picker__preview {
  flex-shrink: 0;
  width: 2.2rem;
  text-align: center;
  font-size: 1.6rem;
  color: var(--c-primary);
}

/* Repetidor (lista de itens que o admin monta). */
.repeater__rows { display: flex; flex-direction: column; gap: 0.75rem; }
.repeater__row {
  border: 1px solid var(--c-border);
  border-radius: 12px;
  padding: 0.75rem;
  background-color: var(--c-surface-2);
}
/* `display:` de autor vence o [hidden] do navegador — sem esta linha a linha
   escondida nasceria aberta (a armadilha que já mordeu .field__toggle e o
   painel do aviso de cookies). Vale também para o aviso de lista vazia. */
.repeater__row[hidden] { display: none; }
.repeater__vazio[hidden] { display: none; }
.repeater__vazio { font-size: 0.85rem; margin: 0.5rem 0; }
.repeater__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-bottom: 0.6rem;
}
.repeater__acoes { display: flex; gap: 0.3rem; }
.repeater__acoes .btn { padding: 0.35rem 0.5rem; }
.repeater__acoes .material-symbols-outlined { font-size: 1.1rem; }
.repeater > [data-repeater-add] { margin-top: 0.75rem; }

/* O admin decide, em Marca, se o logo precisa clarear no tema escuro. O token
   nasce com brightness(1.5) porque o PNG original tem traço vinho e some no
   escuro; um logo já claro ficaria lavado, e é isso que esta chave desliga.
   Sem preprocessador, condicionar dentro do @media exigiria o atributo — que é
   o que o head.blade.php emite. */
:root[data-logo-filter="0"] { --logo-filter: none; }

/* Canais de contato do rodapé: só aparecem os que o admin preencheu. */
.pubfooter__social { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: 0.6rem; }
.pubfooter__social a {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.85rem;
  text-decoration: none;
}
.pubfooter__social .material-symbols-outlined { font-size: 1.1rem; }

/* Atalhos do rodapé do card: ocupado (conteúdo a caminho) e travado
   (gabarito comentado antes de a tela mostrar a correção). Sem mexer em
   display:, então a armadilha do [hidden] não se aplica. */
.q-card__footer-link[aria-busy="true"] {
  opacity: 0.55;
  cursor: progress;
}
.q-card__footer-link--locked {
  color: var(--c-text-muted);
  opacity: 0.5;
  cursor: not-allowed;
}
.q-card__footer-link--locked:hover {
  color: var(--c-text-muted);
}

/* ---------- Histórico de prompts (cadastrar gabarito comentado) ------------ */
/* Rótulo, seletor e botão numa linha só; empilha no celular. O <select> cresce
   porque o rótulo de um prompt é um trecho de frase, não uma palavra. */
.prompt-history {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}
.prompt-history > label {
  color: var(--c-text-muted);
  font-size: 0.9rem;
}
.prompt-history > .input {
  flex: 1;
  min-width: 12rem;
}

/* ---------- Bloco de campos técnicos (configuração da Bela IA) ------------- */
/* Mesmo desenho do .role-group (agrupar campos que se leem juntos), mas com
   nome próprio: aquele é dos perfis do usuário e reusá-lo aqui esconderia que
   são duas telas sem relação. */
.fieldset-tecnico {
  border: 1px solid var(--c-border);
  border-radius: var(--radius-control);
  padding: 0.75rem 0.9rem 0.9rem;
  margin: 0;
}
.fieldset-tecnico > legend {
  padding: 0 0.4rem;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--c-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

/* Barra da prova (simulado em andamento): cronômetro, progresso e navegador
   sempre à vista. Sticky top:0 no desktop (o layout do cliente não tem barra no
   topo); no mobile fica logo abaixo da .app-topbar — o calc espelha a altura
   real dela (logo de 32px + 2 × 0.7rem de padding; mudar a topbar exige rever
   isto). Errar para baixo é seguro: a barra entra 1px SOB a topbar (z 30 < 40);
   errar para cima abriria fresta. */
.exam-bar {
  position: sticky;
  top: 0;
  z-index: 30;
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: 12px;
  box-shadow: 0 2px 8px var(--c-shadow);
  padding: 0.6rem 0.9rem;
  margin-bottom: 1rem;
}
.exam-bar__row {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex-wrap: wrap;
}
.exam-bar__progress {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--c-text-muted);
}
.exam-bar__submit { margin-left: auto; }
.exam-nav {
  display: flex;
  gap: 0.35rem;
  margin-top: 0.55rem;
  overflow-x: auto;          /* simulado pode ter 100 questões: linha rolável */
  padding-bottom: 0.15rem;   /* respiro para a barra de rolagem não colar */
}
.exam-nav__item {
  flex: 0 0 auto;
  min-width: 2rem;
  height: 2rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--c-border);
  border-radius: 8px;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--c-text-muted);
  text-decoration: none;
  padding: 0 0.35rem;
}
.exam-nav__item:hover {
  color: var(--c-primary);
  border-color: var(--c-primary);
  text-decoration: none;
}
.exam-nav__item.is-answered {
  background: var(--c-primary);
  border-color: var(--c-primary);
  color: var(--c-primary-contrast);
}
/* A âncora #item-N não pode parar embaixo da barra; a folga absorve o
   fontscale ampliado (sobra vira respiro, falta esconderia o topo do card). */
.q-solve { scroll-margin-top: 8rem; }
@media (min-width: 900px) {
  .exam-nav { flex-wrap: wrap; overflow: visible; }
}
@media (max-width: 899px) {
  .exam-bar { top: calc(32px + 1.4rem); }
  .q-solve { scroll-margin-top: calc(32px + 1.4rem + 8rem); }
}

/* ---------- Popovers do card da questão: camada e largura ---------------- */
/* z-index 35: acima dos dropdowns de filtro, da sugestão da loja, da barra do
   simulado e da bolha de ajuda (30) e abaixo do topbar sticky do celular (40)
   — em 40, um card rolado para debaixo do cabeçalho pintaria o painel por cima
   dele. A largura é fixa e cabe na tela: o ícone fica a ~2.5rem da borda
   direita (padding do .app-main + do .q-card), daí o 3rem de folga. */
.q-card__pop-panel {
  z-index: 35;
  width: min(20rem, calc(100vw - 3rem));
}
/* O card com popover aberto vence o irmão seguinte mesmo com um transform
   residual da animação de entrada (o motion.js limpa, isto é o cinto). */
.q-list > .q-card:has(.q-card__pop[open]) {
  position: relative;
  z-index: 1;
}
/* Bloco "Novo caderno" recolhido dentro do popover (alternado pelo app.js). */
.q-notebook-new[hidden] {
  display: none;
}

/* Primeiro título de seção da aba Pedidos: sem o respiro de 2rem do .mc-sub,
   que existe para separar uma seção da anterior. */
.mc-sub--primeiro { margin-top: 0.5rem; }

/* ---------- Ajustes de leitura no menu ☰ da nav pública (celular) --------- */
/* Abaixo de 768px os popovers do .pubnav__quick somem e os três controles
   (tema, fonte, largura) entram ABERTOS no fim do menu — os mesmos partials
   dos cards de Minha conta, que o app.js já sincroniza entre as cópias. A
   partir de 768px o menu vira linha, os popovers voltam e este bloco some. */
.pubnav__reading {
  display: flex; flex-direction: column; gap: 1rem;
  width: 100%; margin-top: 0.25rem; padding-top: 0.75rem;
  border-top: 1px solid var(--c-border);
}
.pubnav__reading-title,
.sidenav__reading-title {
  margin: 0; font-size: 0.8rem; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--c-text-muted);
}
@media (min-width: 768px) { .pubnav__reading { display: none; } }

/* ---------- Reportar erro: painel em fluxo abaixo do card (issue #31) --------
   O popover absoluto abria sobre o enunciado, escondendo o trecho a citar. O
   formulário agora é um painel irmão dos de comentários/gabarito; o ícone de
   bandeira do header é o toggle (é um <a>, daí o text-decoration). */
a.q-card__icon-btn { text-decoration: none; }
a.q-card__icon-btn:hover { text-decoration: none; }
.q-card__icon-btn[aria-expanded="true"] { color: var(--c-primary); }
.q-panel--report { padding-top: 1rem; border-top: 1px solid var(--c-border); }
.q-report-form { max-width: 34rem; }
.q-report-form__title {
  display: flex; align-items: center; gap: 0.4rem;
  margin: 0 0 0.75rem; font-size: 1rem;
}
.q-report-form__title .material-symbols-outlined { font-size: 1.2rem; color: var(--c-primary); }

/* ---------- Select nativo com a mesma cara do dropdown customizado (#23) ----
   O msel__toggle é um <button class="select">; o <select> de verdade ("Situação",
   "Ordenar por", "Por página") saía com a seta do navegador. appearance:none +
   caret próprio (token --select-caret, data-URI com a cor literal por tema). */
select.select {
  appearance: none;
  -webkit-appearance: none;
  background-image: var(--select-caret);
  background-repeat: no-repeat;
  background-position: right 0.85rem center;
  padding-right: 2.2rem;
  cursor: pointer;
}
select.select--sm { background-position: right 0.7rem center; padding-right: 1.9rem; }

/* Só para leitor de tela (título de região, rótulo de campo com placeholder) */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0);
  white-space: nowrap; border: 0;
}

/* Barra de ações dos filtros: Filtrar/Limpar · Ordenar por · contador (#24) */
.filters__order { display: inline-flex; align-items: center; gap: 0.4rem; }
.filters__order-label { color: var(--c-text-muted); font-size: 0.85rem; white-space: nowrap; }
.filters__order .select--sm { max-width: 16rem; }

/* ---------- Resultado do simulado: quebra por disciplina (#28) ---------- */
.mock-result__sub { margin: 1.2rem 0 0.6rem; font-size: 1rem; }
.mock-result__table td { vertical-align: middle; }
.mock-result__bar {
  display: inline-block; vertical-align: middle; width: 6rem; height: 0.5rem;
  margin-right: 0.5rem; border-radius: 999px; background-color: var(--c-surface-2);
  overflow: hidden;
}
.mock-result__bar > span { display: block; height: 100%; background-color: var(--c-success); border-radius: 999px; }

/* ---------- Validação no cliente: medidor de força e mensagem de sucesso (#32, #34) */
.pw-meter { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.4rem; font-size: 0.8rem; color: var(--c-text-muted); }
.pw-meter[hidden] { display: none; }
.pw-meter__bar { flex: 1; height: 0.35rem; border-radius: 999px; background-color: var(--c-surface-2); overflow: hidden; }
.pw-meter__bar > span { display: block; height: 100%; width: 0; border-radius: 999px; background-color: var(--c-danger); transition: width 0.2s ease, background-color 0.2s ease; }
.pw-meter[data-level="2"] .pw-meter__bar > span { background-color: var(--c-warning); }
.pw-meter[data-level="3"] .pw-meter__bar > span,
.pw-meter[data-level="4"] .pw-meter__bar > span { background-color: var(--c-success); }
.pw-meter__txt { white-space: nowrap; }
.input[aria-invalid="true"] { border-color: var(--c-danger); }
.field-ok { color: var(--c-success-text); font-size: 0.85rem; margin-top: 0.3rem; }
.cart-cupom .field-error, .cart-cupom .field-ok { margin: 0.4rem 0 0; }

/* ---------- FAQ: bloco de canais de atendimento (#37) ---------- */
.contato-canais { margin-top: 2rem; padding-top: 1.25rem; border-top: 1px solid var(--c-border); }
.contato-canais__titulo { font-size: 1.1rem; margin: 0 0 0.75rem; }
.contato-canais__lista { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.contato-canais__lista .btn { display: inline-flex; align-items: center; gap: 0.35rem; }

/* ---------- Painel de parceria: código do cupom em destaque (#46) ---------- */
.cupom-codigo {
  display: inline-block; padding: 0.1rem 0.5rem; border-radius: 6px;
  background-color: var(--c-primary-soft); color: var(--c-primary-text);
  font-weight: 700; letter-spacing: 0.04em; font-family: inherit;
}

/* ---------- Tooltip genérico: [data-tip] ----------------------------------
   `title` nativo não aparece no toque e demora no mouse — no teste cego ninguém
   entendeu o "2x" do card. Esta bolha aparece no hover E no foco (toque em
   elemento com tabindex="0" foca; Esc/tocar fora desfoca). CSS puro, como os
   popovers de fonte/tema. Nunca use junto de title=, senão são duas bolhas.
   Ancorada à direita: quem a usa vive no canto direito do card, e ancorar à
   esquerda vazaria da tela no celular. z-index 35 = camada dos popovers do card. */
[data-tip] { position: relative; }
[data-tip]::after {
  content: attr(data-tip);
  position: absolute; top: calc(100% + 0.35rem); right: 0; z-index: 35;
  width: max-content; max-width: min(18rem, calc(100vw - 3rem));
  padding: 0.45rem 0.65rem; border-radius: 8px;
  background-color: var(--c-text); color: var(--c-bg);
  font-size: 0.8rem; font-weight: 400; line-height: 1.4;
  white-space: normal; text-align: left;
  box-shadow: 0 6px 20px var(--c-shadow);
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity 0.12s ease;
}
[data-tip]:hover::after, [data-tip]:focus::after { opacity: 1; visibility: visible; }
[data-tip]:focus-visible { outline: 2px solid var(--c-primary); outline-offset: 2px; }
/* O badge "2x" ganha ícone para deixar de ser um número mudo (.badge é
   inline-block; aqui vira flex só para alinhar o ícone ao número). */
.q-card__attempts { display: inline-flex; align-items: center; gap: 0.2rem; }
.q-card__attempts .material-symbols-outlined { font-size: 1rem; }

/* ---------- Modo foco (uma questão por tela — App\Support\FocusMode) ---------
   O atributo só existe na página da questão (head.blade.php + $focusPage), por
   isso as regras podem esconder a casca inteira sem :has(). A barra de atalhos
   vive DENTRO do card (topo do rodapé), abaixo da linha do Responder. */
:root[data-focus-mode="on"] .sidenav,
:root[data-focus-mode="on"] .sidenav-backdrop,
:root[data-focus-mode="on"] .app-topbar,
:root[data-focus-mode="on"] .app-toolbar,
:root[data-focus-mode="on"] .bottomnav,
:root[data-focus-mode="on"] .q-topbar { display: none; }
:root[data-focus-mode="on"] .app-main { padding: 1rem 1rem 2rem; }
@media (min-width: 900px) {
  :root[data-focus-mode="on"] .app-main { max-width: 920px; margin: 0 auto; padding: 1.5rem 0 2rem; }
}
.q-topbar__prefs { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.focus-mode { display: inline-flex; align-items: center; gap: 0.35rem; }
.focus-mode .material-symbols-outlined { font-size: 1.05rem; }
.q-focus-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 0.5rem 1rem; flex-wrap: wrap;
  margin: 0.75rem 0; padding: 0.5rem 0.75rem; background-color: var(--c-bg);
  border: 1px solid var(--c-border); border-radius: 8px; font-size: 0.8rem; color: var(--c-text-muted);
}
.q-focus-bar__keys { display: flex; flex-wrap: wrap; gap: 0.35rem 1rem; margin: 0; padding: 0; list-style: none; }
.q-focus-bar__keys li { display: inline-flex; align-items: center; gap: 0.25rem; }
.q-focus-bar kbd {
  display: inline-block; min-width: 1.4em; padding: 0.05rem 0.35rem; text-align: center;
  font-family: inherit; font-size: 0.75rem; font-weight: 700; color: var(--c-text);
  background-color: var(--c-surface); border: 1px solid var(--c-border); border-bottom-width: 2px; border-radius: 4px;
}
.q-focus-bar__actions { display: inline-flex; align-items: center; gap: 0.75rem; margin-left: auto; }
.q-focus-bar .material-symbols-outlined { font-size: 1.05rem; }
/* Sem teclado a lista de atalhos é ruído, e no celular são cinco linhas antes do
   que importa: o caminho de saída. A régua é a LARGURA — (hover: none) sozinho
   não vale em aparelho com caneta (o S Pen reporta hover: hover), e foi por isso
   que os atalhos continuaram na tela do celular embora sumissem no Chrome da
   máquina em tamanho de celular. */
@media (hover: none), (max-width: 899px) { .q-focus-bar__keys { display: none; } }

/* Celular, e só no modo foco: o Anterior/Próxima sobe para ACIMA da linha do
   rodapé (ali é ele que a aluna usa; os atalhos de conteúdo são o secundário).
   A linha separadora acompanha — ela passa a pertencer ao bloco de Comentários/
   Dica, e não ao rodapé inteiro. É reordenação de flex de propósito: o par de
   botões continua sendo UM nó só; duplicá-lo para o celular deixaria dois
   [data-next-link] na página e a tecla → clicaria no primeiro que achasse. */
@media (max-width: 899px) {
  .q-focus-bar__actions { width: 100%; margin-left: 0; justify-content: center; }

  :root[data-focus-mode="on"] .q-card__footer {
    border-top: 0; padding-top: 0; margin-top: 0.75rem; gap: 0.75rem 1rem;
  }
  :root[data-focus-mode="on"] .q-card__footer-left {
    width: 100%; border-top: 1px solid var(--c-border); padding-top: 1rem;
  }
  :root[data-focus-mode="on"] .q-nav {
    order: -1; width: 100%; margin-left: 0; justify-content: space-between;
  }
}

/* Anterior/Próxima com seta (rodapé do card na página da questão). */
.q-nav { margin-left: auto; }
.q-nav__btn { display: inline-flex; align-items: center; gap: 0.25rem; }
.q-nav__btn .material-symbols-outlined { font-size: 1.15rem; }
.q-nav__btn.is-disabled { opacity: 0.45; pointer-events: none; cursor: default; }

/* ---------- "Carregando imagem…" no lugar da figura (data-img-slot) ----------
   O envelope reserva a altura mínima e escreve a mensagem até a imagem chegar;
   o app.js marca is-loaded/is-error. Só com JS (html.js): sem ele a imagem
   aparece normal, sem placeholder. */
html.js [data-img-slot] { position: relative; display: block; }
html.js [data-img-slot]:not(.is-loaded) { min-height: 7rem; background-color: var(--c-bg); border-radius: 8px; }
html.js [data-img-slot]:not(.is-loaded)::before {
  content: "Carregando imagem…"; position: absolute; inset: 0; display: grid; place-items: center;
  color: var(--c-text-muted); font-size: 0.85rem; pointer-events: none;
}
html.js [data-img-slot].is-error::before { content: "Imagem indisponível"; }
html.js [data-img-slot]:not(.is-loaded) img { opacity: 0; }

/* ---------- Caderno de erros: revisão espaçada (ADR 072) ----------
   As abas reusam .mc-abas/.mc-aba (Minhas Compras); o texto "Por que revisar?"
   reusa o accordion .faq-item. Só o cabeçalho de dia da agenda é novo. */
.agenda__dia { display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; margin: 1rem 0 0.25rem; font-size: 1.05rem; }
.agenda__dia .text-muted { font-size: 0.85rem; font-weight: 400; }
.revisao-porque { margin-top: 0.5rem; }
.revisao-porque > summary { font-weight: 700; }

/* ---------- Avaliação 👍/👎 do gabarito comentado e da dica ----------
   Reusa .votes/.vote (dos joinhas de comentário). A caixa é discreta de
   propósito: fica no fim de um conteúdo que a aluna acabou de ler, e competir
   com ele por atenção seria ruído. Sem contagem — ver App\Support\ContentFeedback. */
.content-feedback {
  display: flex; flex-direction: column; gap: 0.5rem;
  margin-top: 0.9rem; padding-top: 0.7rem; border-top: 1px dashed var(--c-border);
}
/* display: de autor vence o [hidden] do navegador (regra da casa). */
.content-feedback[hidden] { display: none; }
.content-feedback.is-busy { opacity: 0.6; pointer-events: none; }
.content-feedback__vote { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.content-feedback__label { color: var(--c-text-muted); font-size: 0.85rem; font-weight: 600; }
.content-feedback__thanks { color: var(--c-primary-text); font-size: 0.85rem; font-weight: 600; }
.vote__text { font-size: 0.85rem; }
.content-feedback__reason { display: flex; flex-direction: column; gap: 0.5rem; align-items: flex-start; }
.content-feedback__ask { margin: 0; font-size: 0.85rem; font-weight: 600; }
.content-feedback__reasons { display: flex; flex-wrap: wrap; gap: 0.4rem 1rem; }
.content-feedback__radio { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.85rem; cursor: pointer; }
.content-feedback__reason .textarea { min-height: 3.5rem; width: 100%; }

/* ---------- Ajustes de leitura no fim da gaveta (cascas de app, celular) ----
   Abaixo de 900px a .app-toolbar some inteira (o "Ocultar menu" não faz sentido
   com o menu em gaveta) e levava tema e fonte junto: no celular ninguém trocava
   nada sem passar por Minha conta. Mesmo desenho do .pubnav__reading da landing
   — os controles vivem ABERTOS no fim do menu, com os mesmos partials, que o
   app.js já sincroniza entre as cópias. O limiar é o MESMO da gaveta e o mesmo
   da .app-toolbar (900px): um só, sem faixa órfã em que nenhum dos dois aparece.
   A folga inferior é a que era do .sidenav__foot (barra de gestos do aparelho);
   ela acompanha quem for o último bloco da gaveta. */
.sidenav__reading {
  display: flex; flex-direction: column; gap: 0.75rem;
  padding-top: 0.75rem; border-top: 1px solid var(--c-border);
  padding-bottom: calc(4rem + env(safe-area-inset-bottom));
}
/* Os dois textos de ajuda (o do tema também usa .fontscale__hint) saem SÓ aqui:
   a gaveta já é longa e eram ~85px de rolagem a mais para chegar aos botões de
   fonte. A explicação continua nos popovers e nos cards de Minha conta. */
.sidenav__reading .fontscale__hint { display: none; }
@media (min-width: 900px) { .sidenav__reading { display: none; } }

/* ---------- A largura do conteúdo só aparece onde ela muda alguma coisa -----
   O nível mais estreito limita o conteúdo em 960px (:root[data-content-width]
   lá em cima), então abaixo dessa largura de viewport nenhum nível move um
   pixel — em casca nenhuma. Controle inerte não vai para a tela: some o popover
   (navbar do admin, .app-toolbar, .pubnav__quick) e some o card de Minha conta.
   Note que 900px NÃO serviria: um celular grande deitado (~932px) já traz a
   .app-toolbar de volta, e ali a largura ainda não faz nada. */
@media (max-width: 959px) {
  .cwidth,
  .cwidth-card { display: none; }
}

/* ---------- Barra superior do celular: tema/fonte e os selos de contagem ----
   Os dois popovers entraram na .app-topbar (caminho de um toque, sem abrir o
   menu e sem rolar até o fim da gaveta). O gatilho encolhe como já encolhe na
   navbar do admin, e os contadores saem do fluxo: eram "1" soltos ao lado do
   ícone e agora ocupam o canto superior direito dele — a mesma receita do
   carrinho da nav pública (.pubnav__cart .badge--count). A borda na cor da
   barra é o que separa o selo do desenho do ícone. */
@media (max-width: 899px) {
  .app-topbar__quick .fontscale > summary { width: 2.15em; height: 2.15em; }
  /* Abaixo de 768px o .fontscale__panel é EM FLUXO (ele nasceu para viver aberto
     dentro do menu ☰, onde isso é o certo). Aqui ele empurrava a barra e a
     página inteira ficava 260px mais larga que a tela. Ancorar no gatilho não
     resolve — o de tema é o ícone mais à esquerda do grupo e o painel sairia
     pela borda esquerda. Então o .fontscale volta a `static` e quem serve de
     âncora é a própria .app-topbar (sticky = já é bloco de contenção): o painel
     desce colado à barra, alinhado à direita pelo mesmo 1rem do padding dela. */
  .app-topbar__quick .fontscale { position: static; }
  .app-topbar__quick .fontscale__panel {
    position: absolute; top: 100%; right: 1rem; margin-top: 0.4rem; z-index: 50;
  }
  .app-topbar__quick .badge--count {
    position: absolute; top: -0.3rem; right: -0.35rem; margin: 0;
    font-size: 0.65rem; padding: 0.05rem 0.35rem;
    border: 2px solid var(--c-surface);
  }
}

/* ---------- Celular: as quatro ações do card viram um menu ☰ --------------
   O <details class="q-card__menu"> não tem painel próprio: quem ele revela é o
   IRMÃO seguinte (.q-card__actions-items), pelo combinador `[open] ~`. É o que
   permite os mesmos quatro controles servirem à barra de ícones do desktop e ao
   menu do celular sem uma segunda cópia no DOM — dentro de um <details> fechado
   eles sumiriam também no desktop, e não existe CSS que "abra" um <details>. */
.q-card__menu { display: none; }        /* o ☰ só existe no celular */
.q-card__act-label { display: none; }   /* fora do menu, os controles são só ícone */
/* No desktop o bloco é transparente: os quatro controles seguem numa linha, como
   quando eram filhos diretos da .q-card__actions-right (um <div> block os
   empilharia). */
.q-card__actions-items { display: flex; align-items: center; gap: 0.5rem; }

@media (max-width: 899px) {
  /* O tipo (múltipla escolha / certo-errado / discursiva) ocupa o selo mais
     largo da fila e não informa nada que a questão já não mostre. */
  .q-card__type { display: none; }

  .q-card__menu { display: block; }
  .q-card__actions-right { position: relative; }
  .q-card__actions-items {
    display: none;
    position: absolute;
    right: 0;
    top: calc(100% + 0.35rem);
    z-index: 35;
    width: min(20rem, calc(100vw - 3rem));
    flex-direction: column;
    align-items: stretch;
    gap: 0.15rem;
    padding: 0.4rem;
    text-align: left;
    background-color: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-card, 24px);
    box-shadow: 0 8px 28px var(--c-shadow);
  }
  .q-card__menu[open] ~ .q-card__actions-items { display: flex; }
  /* Abrir o caderno FECHA o ☰ — a regra "um popover por vez" do app.js não sabe
     que um revela o outro. Enquanto qualquer popover das ações estiver aberto, o
     menu continua na tela. Reforço, não a regra principal: em navegador sem
     :has() o que degrada é só o caderno. */
  .q-card__actions-right:has(.q-card__pop[open]) .q-card__actions-items { display: flex; }

  .q-card__actions-items .q-card__icon-btn,
  .q-card__actions-items .q-card__attempts {
    width: 100%;
    height: auto;
    justify-content: flex-start;
    gap: 0.6rem;
    padding: 0.55rem 0.7rem;
    border-radius: 12px;
    font-size: 0.9rem;
  }
  /* No menu a linha é texto, não ícone solto: o muted que serve ao ícone deixa o
     rótulo apagado ao lado do vizinho que é <button>. */
  .q-card__actions-items .q-card__icon-btn,
  /* o do caderno é <summary>, e a regra dele lá em cima é mais específica */
  .q-card__actions-items .q-card__pop > summary.q-card__icon-btn { color: var(--c-text); }
  .q-card__actions-items .q-card__act-label { display: inline; }
  .q-card__actions-items .q-card__attempts-n { display: none; }
  .q-card__actions-items [data-tip]::after { display: none; }  /* o rótulo já diz */
  .q-card__actions-items .inline-form,
  .q-card__actions-items .q-card__pop { display: block; }
  /* O caderno abre DENTRO do menu, em fluxo: o painel flutuante sairia da caixa
     e cobriria o enunciado. */
  .q-card__actions-items .q-card__pop-panel {
    position: static;
    width: auto;
    min-width: 0;
    padding: 0.5rem 0.2rem 0.2rem;
    border: 0;
    box-shadow: none;
    background: none;
  }
}

/* --- Copiar / divulgação do cupom da parceria (/influ/divulgacao) ---------- */

/* Sem JS não existe área de transferência: o botão some e sobra o campo
   readonly, que a pessoa seleciona à mão. */
html:not(.js) [data-copy],
html:not(.js) [data-copy-target] { display: none; }

/* `display:` de autor vence o [hidden] do navegador — a linha que este projeto
   já esqueceu duas vezes. */
[data-copy][hidden],
[data-copy-target][hidden] { display: none; }

[data-copy].is-copied,
[data-copy-target].is-copied {
    border-color: var(--c-success);
    color: var(--c-success);
}

.share-row {
    display: flex;
    gap: .5rem;
    align-items: center;
    flex-wrap: wrap;
}

.share-row .input { flex: 1 1 16rem; min-width: 0; }

.share-label {
    display: block;
    font-size: .8rem;
    font-weight: 600;
    color: var(--c-text-muted);
    margin-bottom: .25rem;
}

/* O QR é preto sobre branco SEMPRE: no tema escuro um QR que herdasse o fundo
   da página não seria lido por câmera nenhuma. */
.qr-box {
    background: #fff;
    padding: .5rem;
    border-radius: var(--radius-control);
    width: 10rem;
    max-width: 100%;
    line-height: 0;
}

.qr-box svg { width: 100%; height: auto; display: block; }

.share-grid {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 1rem;
    align-items: start;
}

@media (max-width: 640px) {
    .share-grid { grid-template-columns: 1fr; }
    .qr-box { margin-inline: auto; }
}

.share-caption { min-height: 4.5rem; resize: vertical; }

/* Os 4 números do funil moram DENTRO de um card, onde o .grid-4 global
   (minmax 240px) só cabe três e joga "Conversão" sozinha na linha de baixo. */
.share-kpis { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }

/* Escudos da sequência de estudos (ADR 076): uma terceira linha dentro do KPI,
   abaixo do número. Fica em `inline-flex` para o ícone alinhar com o texto sem
   herdar o line-height apertado do .kpi__value. */
.kpi__shields { display: block; margin-top: 0.3rem; font-size: 0.8rem; color: var(--c-text-muted); }
.kpi__shield {
  display: inline-flex; align-items: center; gap: 0.2rem;
  color: color-mix(in srgb, var(--c-warning) 70%, var(--c-text)); font-weight: 600;
}
.kpi__shield .material-symbols-outlined { font-size: 1rem; }
.alert--info .material-symbols-outlined { font-size: 1.05rem; vertical-align: -0.18em; }

/* ---------------------------------------------------------------------------
   Celular: os doze filtros da lista de questões viram um bottom sheet
   (client/questions/index.blade.php)

   O problema era medido: em uma coluna os doze campos empilham ~600px e a
   concurseira rolava a tela inteira antes de ver a primeira questão. De 900px
   para cima NADA muda — as regras soltas aqui embaixo são o "isto não existe no
   desktop", e todo o resto vive dentro do @media (max-width: 899px). O limiar é
   o mesmo da gaveta, da .bottomnav e do menu ☰ do card: um só, sem faixa órfã.

   O gatilho é um <details> SEM painel próprio: quem ele revela é o IRMÃO
   seguinte, pelo `[open] ~`. É a mesma receita do .q-card__menu — os mesmos doze
   campos servem à grade de 4 colunas do desktop e ao sheet do celular sem uma
   segunda cópia no DOM, e sem JS a coisa abre e fecha sozinha. Ele NÃO entra no
   POPOVER_SEL do app.js de propósito: nesse padrão o painel não é descendente do
   <details>, e o "clique fora" dos popovers fecharia o sheet no primeiro toque
   num campo dentro dele.

   Escondido, o painel continua submetendo: `display:none`/`visibility:hidden`
   não desabilitam campo. É isso que faz o GET continuar sendo um só — e é por
   isso que nenhum campo daqui pode virar `required`: dentro de um contêiner
   escondido o Chrome aborta com "invalid form control is not focusable" e o
   botão Filtrar deixa de fazer qualquer coisa, sem erro na tela.
--------------------------------------------------------------------------- */

/* No desktop o gatilho e o fundo não existem; o painel é um <div> transparente
   e os campos seguem na grade do .card, exatamente como antes. */
.filters__sheet,
.filters__backdrop,
.filters__panel-head { display: none; }
/* `display:` de autor vence o [hidden] do navegador — a linha que este projeto
   já esqueceu duas vezes. */
.filters__sheet[hidden],
.filters__backdrop[hidden],
.filters__panel[hidden] { display: none; }

@media (max-width: 899px) {
  /* Fechado, o que sobra do <form class="card"> é um botão só: a moldura de
     cartão em volta de um botão seria uma caixa vazia. */
  .filters { padding: 0; border: 0; background: none; box-shadow: none; }

  .filters__sheet { display: block; }
  .filters__sheet-btn {
    list-style: none;                 /* mata o triângulo do <summary> */
    display: flex; align-items: center; gap: 0.4rem;
    padding: 0.6rem 0.9rem;
    cursor: pointer; user-select: none; font-weight: 600;
    background-color: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-control);
  }
  .filters__sheet-btn::-webkit-details-marker { display: none; }
  .filters__sheet[open] .filters__sheet-btn {
    border-color: var(--c-primary);
    color: var(--c-primary-text);
  }
  /* Azul da marca, e não o vermelho de .badge--count: aqui o número conta
     escolhas do aluno, não notificação pendente (mesma razão do .msel__count). */
  .filters__sheet-count {
    min-width: 1.25rem; padding: 0.05rem 0.4rem; border-radius: 999px;
    background-color: var(--c-primary); color: var(--c-primary-contrast);
    font-size: 0.75rem; font-weight: 700; text-align: center; line-height: 1.2;
  }

  /* Fundo escuro: elemento REAL, não ::backdrop — quem abre é um <details>, não
     um <dialog>. Mesma mecânica (e os mesmos valores) da .sidenav-backdrop, com
     opacidade em vez de display para poder transicionar. z 55 fica ACIMA da
     .bottomnav (50): com o sheet aberto a barra de baixo deixa de ser alvo de
     toque; e ABAIXO da .sidenav (100), que continua vencendo. */
  .filters__backdrop {
    display: block;
    position: fixed; inset: 0; z-index: 55;
    background: rgba(0, 0, 0, 0.5);
    opacity: 0; pointer-events: none;
    transition: opacity 0.3s ease;
  }
  .filters__sheet[open] ~ .filters__backdrop { opacity: 1; pointer-events: auto; }

  /* O painel. `position: fixed` só funciona porque NENHUM ancestral tem
     transform/filter/contain hoje (o data-anim do GSAP está na .q-list, que é
     IRMÃ). Pôr data-anim NESTE formulário quebraria o sheet: o transform de
     entrada viraria o bloco de contenção e o "fixo" passaria a ser relativo ao
     cartão. O motion.js limpa o transform no fim, mas não durante.
     `visibility` (e não display) para o slide poder acontecer; escondido assim
     ele sai da árvore de acessibilidade e do Tab, e mesmo assim submete. */
  .filters__panel {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
    display: flex; flex-direction: column;
    max-height: 85vh;
    max-height: 85dvh;                /* dvh = altura VISÍVEL; vh é o fallback */
    overflow-y: auto;                 /* atenção: overflow-x vira `auto` junto */
    overscroll-behavior: contain;     /* o fim do sheet não vira rolagem da lista */
    padding: 0.9rem 1rem;
    padding-bottom: max(0.9rem, env(safe-area-inset-bottom));
    background-color: var(--c-surface);
    border-top: 1px solid var(--c-border);
    border-radius: var(--radius-card) var(--radius-card) 0 0;
    box-shadow: 0 -8px 28px var(--c-shadow);
    transform: translateY(100%);
    visibility: hidden;
    transition: transform 0.3s ease, visibility 0s linear 0.3s;
  }
  .filters__sheet[open] ~ .filters__panel {
    transform: translateY(0);
    visibility: visible;
    transition: transform 0.3s ease, visibility 0s;
  }

  .filters__panel-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 0.5rem; margin-bottom: 0.8rem;
  }
  .filters__panel-title { font-weight: 700; font-size: 1.05rem; }
  .filters__close {
    display: flex; align-items: center; justify-content: center;
    width: 2rem; height: 2rem; border-radius: 999px;
    background: none; border: 0; cursor: pointer; color: var(--c-text-muted);
  }
  .filters__close:hover { background-color: var(--c-surface-2); color: var(--c-text); }

  /* Rodapé do sheet. `sticky`, não `fixed`: a linha tem flex-wrap e quebra em
     duas ou três num aparelho estreito — um rodapé fixo exigiria reservar uma
     altura que ninguém sabe. Sticky se mede sozinho, dentro do mesmo scroller.
     O fundo é obrigatório: sem ele o conteúdo passa por baixo. */
  .filters__panel .filters__actions {
    position: sticky; bottom: 0;
    margin-top: 0.8rem; padding: 0.7rem 0 0;
    background-color: var(--c-surface);
    border-top: 1px solid var(--c-border);
  }

  /* Dentro do sheet, o dropdown do multi-seleção abre EM FLUXO. Absoluto ele não
     flutuaria: o bloco de contenção (.msel) está DENTRO do scroller, então abrir
     "Assunto" acrescentaria 260px de rolagem ao sheet e o painel ainda sumiria
     atrás do rodapé sticky. É a mesma correção do caderno dentro do menu ☰ do
     card. O escopo em .filters__panel deixa os forms do admin — e o desktop —
     intocados.
     A bolha "?" (.field-help__panel) segue absoluta de propósito: .field-help é
     um flex row, e estático o painel viraria um item ao lado do input. */
  .filters__panel .msel__panel {
    position: static; width: auto; min-width: 0;
    margin-top: 0.35rem; box-shadow: none;
  }
  .filters__panel .msel__list { max-height: 40vh; }
}

@media (prefers-reduced-motion: reduce) {
  .filters__panel, .filters__backdrop { transition: none; }
}

/* ---------- Renovação cancelada: o aviso que ninguém via ------------------
   O cancelamento da renovação automática só aparecia como uma linha cinza no
   meio do `.sub-meta`, e passava batido justamente para quem precisava vê-lo
   (o teste de 26/08/2026: "quase não vi na interface"). Agora o estado ganha
   selo próprio, ao lado do "Assinatura ativa", e a data ganha destaque.

   Os tokens são os mesmos do `.pill--danger` — a mistura com a superfície é o
   que mantém o contraste AA nos três blocos de tema sem cor literal nova. */
.badge--danger {
  background-color: color-mix(in srgb, var(--c-danger) 18%, var(--c-surface));
  color: color-mix(in srgb, var(--c-danger) 78%, var(--c-text));
}

/* Linha de aviso dentro de um card: barra lateral em vez de caixa cheia, que
   dentro do `.sub-item` competiria com o próprio conteúdo. Vale para o texto
   do cancelamento em /assinatura. */
.aviso-cancelamento {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.6rem;
  padding: 0.5rem 0.7rem;
  border-left: 3px solid var(--c-danger);
  background-color: color-mix(in srgb, var(--c-danger) 8%, var(--c-surface));
  border-radius: 0 var(--radius, 6px) var(--radius, 6px) 0;
  color: color-mix(in srgb, var(--c-danger) 78%, var(--c-text));
  font-size: 0.9rem;
}

.aviso-cancelamento .material-symbols-outlined { font-size: 1.1rem; }

/* ---------- Arrependimento (art. 49 do CDC) em Minhas Compras -------------
   A linha que informa o prazo para cancelar e o que o encerra. Fica ABAIXO da
   linha do item (não entre os botões) porque é frase, não ação — o botão de
   cancelar vem junto dela, deliberadamente discreto: quem chegou aqui já
   comprou, e a saída não deve competir com "Baixar". */
.mc-item__arrependimento {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin: 0.75rem 0 0;
  padding-top: 0.75rem;
  border-top: 1px solid var(--c-border);
  color: var(--c-text-muted);
  font-size: 0.9rem;
}

.mc-item__arrependimento .material-symbols-outlined { font-size: 1.1rem; }

/* O form existe só para carregar o botão: não pode ganhar linha própria. */
.mc-item__arrependimento form { margin: 0 0 0 auto; }

/* ---------- Arrependimento (art. 49 do CDC) em /assinatura ----------------
   Irmã de `.aviso-cancelamento`, com a mesma forma de barra lateral e cor
   diferente de propósito: aquela relata um cancelamento já feito (danger),
   esta OFERECE um direito ainda vivo — pintá-la de vermelho faria o prazo
   legal parecer um problema. Texto pequeno sobre `--c-primary-soft` usa
   `--c-primary-text` (ADR 068), nunca `--c-primary`. */
.aviso-arrependimento {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.6rem;
  padding: 0.5rem 0.7rem;
  border-left: 3px solid var(--c-primary);
  background-color: var(--c-primary-soft);
  border-radius: 0 var(--radius, 6px) var(--radius, 6px) 0;
  color: var(--c-primary-text);
  font-size: 0.9rem;
}

.aviso-arrependimento .material-symbols-outlined { font-size: 1.1rem; }

/* O número do pedido/assinatura: é para ser LIDO em voz alta e digitado numa
   busca, então monoespaçado — em fonte proporcional o 0 e o O se confundem. */
.pill--codigo {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: 0.02em;
}

/* ---------- Ação de estorno na fila de reembolsos ------------------------
   O par valor + botão fica na MESMA linha do pagamento a que se refere: numa
   linha com dois pagamentos, um bloco solto embaixo não diria qual dos dois vai
   ser estornado — e aqui errar o alvo é devolver o dinheiro da venda errada. */
.refund-acao {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-left: 0.5rem;
}

/* Largura de campo de dinheiro, não de formulário: cabe "1.234,56" e nada mais. */
.refund-acao__valor { width: 7.5rem; padding: 0.35rem 0.5rem; font-size: 0.9rem; }

@media (max-width: 640px) {
  .refund-acao { display: flex; margin: 0.5rem 0 0; }
}

/* ---------- Campo "motivo" do cancelamento (art. 49 do CDC) --------------
   O `.textarea` global tem `min-height: 120px`, pensado para caixa de redação;
   aqui o campo é opcional e de uma ou duas frases — 120px de área vazia acima do
   botão de cancelar fazem a caixa parecer obrigatória. Mesma receita de
   `.content-feedback__reason .textarea`. */
.motivo-campo .textarea { min-height: 4.5rem; }

.motivo-campo__ajuda {
  margin: 0.35rem 0 0;
  font-size: 0.82rem;
  color: var(--c-text-muted);
}

/* A regra de placeholder existente cobre só `.input` — sem esta, o texto de
   dica de qualquer textarea sai na cor do texto normal e parece conteúdo já
   digitado. */
.textarea::placeholder { color: var(--c-text-muted); opacity: 1; }

/* --- CEP → endereço (card fiscal de Minha conta) --------------------------
   Aviso abaixo do CEP ("Buscando…", "não encontrado…"). O `[hidden]` explícito
   é a regra da casa: `display:` de autor vence o hidden do navegador. */
.cep-status { font-size: .875rem; margin: .25rem 0 0; }
.cep-status[hidden] { display: none; }
[data-cep-fields][hidden] { display: none; }

/* --- Dados fiscais no checkout (ADR 089) ----------------------------------
   Inscrição Estadual só para PJ: o bloco nasce escondido e o JS o alterna.
   `[hidden]` explícito porque `display:` de autor vence o do navegador. */
[data-fiscal-pj][hidden] { display: none; }
.field-hint { font-size: .875rem; margin: .25rem 0 0; }
.pagar-nota { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; font-size: .9rem; margin: 0; }
.pagar-nota .material-symbols-outlined { font-size: 1.1rem; }

/* --- Verificação em duas etapas (ADR 090) ---------------------------------
   O QR nasce com fundo branco próprio (o <rect> injetado no SVG), então a
   moldura só precisa dar respiro e limitar a largura em telas grandes. */
.qr-box { display: inline-block; padding: .75rem; background: #fff; border-radius: var(--radius); max-width: 260px; }
.qr-box svg { display: block; width: 100%; height: auto; }
.recovery-codes { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: .5rem; list-style: none; padding: 0; margin: 0; }
.recovery-codes code { font-size: 1.05rem; letter-spacing: .05em; }

/* ---------- Corrente da taxonomia: Disciplina › Assunto › Tópico ------------
   Os campos filhos nascem TRANCADOS e cada nível destrava o seguinte. O estado
   vem do servidor (App\Support\TaxonomyCascade::locked), então funciona sem JS;
   o app.js só o move quando a escolha muda sem recarregar.

   O cadeado é `disabled` no <button> — e um botão desabilitado não responde a
   hover na maioria dos navegadores, por isso o porquê é TEXTO na tela
   (.msel__hint) e não tooltip. */
.msel--locked .msel__toggle {
  opacity: 0.55;
  cursor: not-allowed;
  background-color: var(--c-surface-2);
}
.msel__hint {
  margin: 0.25rem 0 0;
  color: var(--c-text-muted);
  font-size: 0.78rem;
  line-height: 1.3;
}
.msel__hint[hidden] { display: none; }

/* Opção com caminho (Assunto e Tópico). A lista pode chegar sem nenhum pai
   marcado — e aí "Princípios" aparece uma dúzia de vezes, uma por assunto. O
   caminho desfaz a ambiguidade numa 2ª linha apagada, DENTRO do painel, onde há
   altura de sobra.

   No chip ele não entra (data-chip no checkbox, ver _multiselect.blade.php): o
   chip tem uma linha só e o ellipsis corta pelo FIM, então o caminho comeria
   justamente o nome do item — que é o que a aluna precisa ler.

   `min-width: 0` é o que deixa o ellipsis funcionar dentro do flex do
   .msel__opt. Selecionado, o texto pequeno vai para --c-primary-text:
   --c-text-muted sobre --c-primary-soft é o par que a régua de contraste da
   casa proíbe. */
.msel__opt-text { display: flex; flex-direction: column; min-width: 0; }
.msel__opt-path {
  color: var(--c-text-muted);
  font-size: 0.72rem;
  font-weight: 400;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.msel__opt.is-selected .msel__opt-path { color: var(--c-primary-text); }

/* Aviso de lista vazia dentro de um multi-seleção (_multiselect.blade.php).
   Cobre a busca interna sem resultado e o pai que não tem nenhum filho — nos
   dois casos o painel ficava em branco e mudo, indistinguível de componente
   quebrado. A linha do [hidden] é a regra de sempre: `display:` de autor vence
   o atributo do navegador, e sem ela o aviso nasceria aberto. */
.msel__empty {
  display: block;
  margin: 0;
  padding: 0.5rem 0.4rem;
  color: var(--c-text-muted);
  font-size: 0.85rem;
  text-align: center;
}
.msel__empty[hidden] { display: none; }

/* Caixa "registros semelhantes" dos formulários de taxonomia
   (admin/partials/_name-with-similar + _semelhantes).

   Mesma receita do .picker-panel — borda, raio 10px, superfície 2, teto com
   rolagem —, e EM FLUXO abaixo do campo, não flutuando como o .store-suggest:
   ali é uma lista para escolher, aqui é um aviso para ler antes de salvar. A
   linha do [hidden] é a regra de sempre: `display:` de autor vence o atributo
   do navegador, e sem ela a caixa nasceria aberta e vazia. */
.similar {
  display: block;
  margin-top: 0.6rem;
  border: 1px solid var(--c-border);
  border-radius: 10px;
  padding: 0.6rem 0.75rem;
  background-color: var(--c-surface-2);
  max-height: 320px;
  overflow-y: auto;
}
.similar[hidden] { display: none; }
.similar__head { margin: 0 0 0.4rem; font-size: 0.85rem; font-weight: 600; }
.similar__list { list-style: none; margin: 0; padding: 0; }
.similar__item {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.4rem 0;
  border-top: 1px solid var(--c-border);
}
.similar__item:first-child { border-top: 0; }
.similar__item .msel__opt-text { flex: 1; min-width: 0; }
.similar__meta { font-size: 0.8rem; white-space: nowrap; }
/* O nome idêntico é o caso que a caixa existe para evitar: a linha inteira
   ganha a cor do aviso, para não depender só da pílula. */
.similar__item.is-same { background-color: var(--c-primary-soft); border-radius: 6px; padding-inline: 0.4rem; }
/* Sobre --c-primary-soft o --c-text-muted é o par que a régua de contraste da
   casa proíbe (ADR 068) — vale para o caminho E para a contagem. */
.similar__item.is-same .msel__opt-path,
.similar__item.is-same .similar__meta { color: var(--c-primary-text); }

/* Cabeçalho de coluna ordenável das listagens do admin
   (admin/partials/_th-ordenavel). É um <a> dentro do <th> — e não o <th>
   inteiro clicável — porque link de verdade é o que faz a ordenação funcionar
   sem JavaScript, com "abrir em nova aba" e tudo o mais. */
.th-sort {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  color: inherit;
  text-decoration: none;
}
.th-sort:hover { color: var(--c-primary-text); }
/* A seta some no repouso e volta no hover: com ela sempre visível em todas as
   colunas, o cabeçalho vira uma fileira de símbolos e ninguém acha a coluna
   que está ordenando de verdade. */
.th-sort__seta { font-size: 0.7rem; opacity: 0; transition: opacity 0.12s; }
.th-sort:hover .th-sort__seta,
.th-sort:focus-visible .th-sort__seta { opacity: 0.55; }
.th-sort.is-active { color: var(--c-primary-text); }
.th-sort.is-active .th-sort__seta { opacity: 1; }

/* Aviso "você está dentro deste edital" no topo do banco de questões
   (client/questions/index.blade.php). Um recorte sem explicação é
   indistinguível de um acervo pequeno, e o texto é o único lugar de onde se
   sai dele. Tokens de sempre — nada de cor literal aqui. */
.edital-aviso {
  border-left: 3px solid var(--c-primary);
  background: var(--c-primary-soft);
}
.edital-aviso p:first-child {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  /* Sobre --c-primary-soft, o texto pequeno usa --c-primary-text (ADR 068). */
  color: var(--c-primary-text);
}
.edital-aviso .material-symbols-outlined { font-size: 1.15rem; }

/* ---------------------------------------------------------------------------
   Árvore inline das listagens de taxonomia (/admin/disciplinas e
   /admin/assuntos): a lista de filhos que a IIFE [data-tree-toggle] injeta
   num <tr> irmão da linha clicada. Dois níveis de indentação (assuntos e,
   dentro deles, tópicos). Nada aqui leva `display:` de autor — é o [hidden]
   do navegador que fecha o painel (regra da casa que já mordeu duas vezes). */
.tax-tree { list-style: none; margin: 0; padding: 0; }
.tax-tree__item { padding: 0.3rem 0 0.3rem 1.75rem; }
.tax-tree .tax-tree .tax-tree__item { padding-left: 1.75rem; }
.tax-tree__meta { font-size: 0.85em; color: var(--c-text-muted); margin-left: 0.5rem; }
.tax-tree--filhos { border-left: 2px solid var(--c-border); margin-left: 0.4rem; margin-top: 0.15rem; }
.tax-tree__loading { margin: 0.3rem 0; }
/* O painel não é linha de dado: sem o hover de linha da .table, e com um
   fundo levemente recuado para ler como "conteúdo da linha de cima". */
.table tbody tr.tax-tree-row:hover { background-color: transparent; }
.tax-tree-row > td { background-color: var(--c-surface-2); }

/* ---------------------------------------------------------------------------
   Trilha dos três níveis no topo das listagens de taxonomia
   (partial `admin/partials/_taxonomy-niveis`): Disciplinas · Assuntos ·
   Tópicos, sempre nessa ordem, com o nível aberto como <h1> e os outros dois
   como links do MESMO tamanho.

   Os dois valores de tamanho ficam num lugar só — aqui, no contêiner: o <h1>
   herda com `inherit` e o <a> herda de graça (âncora não tem font-size de
   agente de usuário). Este bloco precisa ficar DEPOIS de `.page-head h1`
   (mesma especificidade, vence quem vem por último) — mais uma razão para o
   CSS novo entrar sempre no fim do arquivo. */
.tax-niveis {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.15rem 0.9rem;
  line-height: 1.25;
  font-size: 1.4rem;
}
@media (min-width: 768px) {
  .tax-niveis { font-size: 1.7rem; }
}
.tax-niveis h1 { font-size: inherit; }
/* O nível aberto herda a cor e o peso 700 do h1 global; os links ficam um
   passo atrás, que é o que faz o título ser o título. */
.tax-niveis a { color: var(--c-text-muted); font-weight: 600; }
.tax-niveis a:hover { color: var(--c-primary); }

/* ==========================================================================
   Questão compartilhada por link temporário (ADR 100)
   Só tokens, e só o que a casca enxuta não herda das classes reusadas.
   ========================================================================== */
.shared-q { max-width: 52rem; margin: 1.5rem auto; }
.shared-q__note {
  margin: 1.25rem 0 0;
  padding-top: 0.9rem;
  border-top: 1px solid var(--c-border);
  font-size: 0.82rem;
}

/* A página de "este link não abre mais". Centralizada porque é a página
   inteira, não um aviso dentro de outra coisa. */
.shared-gone { max-width: 34rem; margin: 2.5rem auto; text-align: center; }
.shared-gone__icon { font-size: 3rem; color: var(--c-text-muted); }
.shared-gone h1 { font-size: 1.4rem; margin: 0.5rem 0; }
.shared-gone p { margin: 0; }

/* O convite embaixo das duas páginas. */
.shared-cta { max-width: 52rem; margin: 2rem auto 3rem; text-align: center; }
.shared-cta__title { font-size: 1.3rem; margin: 0 0 0.35rem; }
.shared-cta__lead { color: var(--c-text-muted); margin: 0 0 1.5rem; }
.shared-cta__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 1rem;
  list-style: none;
  padding: 0;
  margin: 0 0 1.75rem;
  text-align: left;
}
.shared-cta__item { display: flex; gap: 0.6rem; align-items: flex-start; }
.shared-cta__item .material-symbols-outlined { color: var(--c-primary); }
.shared-cta__item strong { display: block; font-size: 0.95rem; }
.shared-cta__item span.text-muted { font-size: 0.82rem; line-height: 1.35; }

/* ---------- A casca da questão compartilhada: popovers em TODAS as larguras --
   Na nav da landing, abaixo de 768px os popovers de fonte e tema somem e os
   controles vivem ABERTOS dentro do menu ☰ (.pubnav__reading) — ali isso é o
   certo, porque o menu é recolhido. A casca compartilhada não tem menu nenhum
   para recolhê-los: deixados abertos, os dois blocos ocupavam um terço da tela
   do celular antes de a questão começar. Aqui, portanto, eles continuam sendo
   popovers em qualquer largura.

   Isso traz junto a armadilha já documentada na .app-topbar: abaixo de 768px o
   .fontscale__panel é EM FLUXO (ele nasceu para viver aberto dentro do ☰), e
   assim ele empurraria a barra, deixando a página 260px mais larga que a tela.
   A receita é a mesma de lá — o .fontscale volta a `static` e quem ancora é a
   própria .pubnav (sticky = já é bloco de contenção): o painel desce colado à
   barra, alinhado à direita pelo mesmo 1rem do padding dela.

   A LARGURA não entra: a regra de 960px acima já a esconde, e abaixo disso ela
   não move um pixel. */
.pubnav--shared .pubnav__quick .fontscale { display: inline-flex; }
@media (max-width: 767px) {
  .pubnav--shared .pubnav__quick .fontscale { position: static; }
  .pubnav--shared .pubnav__quick .fontscale__panel {
    position: absolute; top: 100%; right: 1rem; margin-top: 0.4rem; z-index: 50;
  }
}

/* Painel de compartilhar do card (ADR 100). A caixa vem do .q-panel; aqui só o
   espaçamento do miolo. */
.q-share__hint { font-size: 0.82rem; margin: 0.5rem 0 0; }
.q-share-form .share-row { margin-top: 0.75rem; }

/* ---------- Moldura e véu das imagens de questão (área da aluna) -----------
   O escaneamento é um retângulo branco e o branco cru cansa a vista de quem
   estuda. São duas camadas: (1) a moldura BRANCA de 8px, que é a borda da
   própria <img>; (2) um véu na cor de fundo do body — 10% no tema claro e 25%
   nos escuros, que é o par de dígitos no fim do hex do token — cobrindo a
   imagem INTEIRA e a moldura junto. A dose é maior no escuro porque é lá que o
   retângulo branco do escaneamento pesa na vista; no claro o véu quase não
   mexe no branco e só serve para tirar o contraste duro do traço.
   O véu é um ::after com inset: 0, e por isso mora no envelope [data-img-slot]
   e não na <figure>: a figura também contém a legenda, e ali o inset: 0
   velaria o texto. O envelope precisa encolher à largura da imagem
   (width: fit-content), senão o véu se espalha pela largura do card — e o
   `display: block` fica AQUI, não herdado do html.js [data-img-slot], porque
   sem JS o <span> seria inline e `width` não se aplica a caixa inline.
   Enquanto a figura não chega, o envelope volta a ser o placeholder
   "Carregando imagem…": largura toda e sem véu (ver o bloco data-img-slot
   mais acima).
   Consequência assumida: com a imagem toda velada, moldura branca velada e
   fundo branco velado dão a MESMA cor — sobre escaneamento branco a moldura
   vira uma margem de 8px, e só se vê como moldura em figura escura ou foto.
   Escopo: casca da aluna (.app-body) e da questão compartilhada (.public-body).
   O admin usa layouts.app, cujo <body> não tem classe — lá continua valendo a
   borda de 1px de `.q-figure img` lá em cima. ------------------------------ */
.app-body .q-img,
.public-body .q-img {
  position: relative;
  display: block;
  width: fit-content;
  max-width: 100%;
  zoom: var(--img-zoom, 1);
}
.app-body .q-img img,
.public-body .q-img img {
  border: 8px solid var(--c-img-frame);
  border-radius: 8px;
}
.app-body .q-img::after,
.public-body .q-img::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 8px;
  background-color: var(--c-img-veil);
  pointer-events: none;
}
html.js .app-body .q-img:not(.is-loaded),
html.js .public-body .q-img:not(.is-loaded) { width: auto; }
html.js .app-body .q-img:not(.is-loaded)::after,
html.js .public-body .q-img:not(.is-loaded)::after { display: none; }

/* ---------- Histórico do texto do prompt da Bela IA (ADR 104) ----------
   Lista, e não tabela: o painel "Ler" (.detalhe-painel) nasce vazio logo
   abaixo do item. Os textos quebram linha como no textarea de onde vieram. */
.prompt-versions { list-style: none; margin: 0; padding: 0; }
.prompt-version { padding: 0.75rem 0; border-top: 1px solid var(--c-border); }
.prompt-version:first-child { border-top: 0; padding-top: 0; }
.prompt-version__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
}
.prompt-version__info {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.25rem 0.6rem;
  min-width: 0;
}
.prompt-version__changed { flex-basis: 100%; font-size: 0.82rem; color: var(--c-text-muted); }
.prompt-version__block + .prompt-version__block { margin-top: 0.6rem; }
.prompt-version__block > summary { cursor: pointer; font-weight: 700; font-size: 0.9rem; }
.prompt-version__block > summary .pill { margin-left: 0.4rem; font-weight: 400; }
.prompt-version__note { font-size: 0.82rem; margin: 0.35rem 0 0; }
.prompt-version__text {
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 22rem;
  overflow: auto;
  margin: 0.4rem 0 0;
}
.prompt-version__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  margin-top: 1rem;
  font-size: 0.85rem;
}

/* ---------- Questão compartilhada: responder e corrigir (ADR 104) ----------
   A linha do veredito é a mesma do card (.q-actionbar + .q-verdict-inline);
   aqui só o que é da página pública: o gabarito ao lado do veredito e o bloco
   apagado enquanto o "Corrigir" vai ao servidor. */
.shared-answer.is-busy { opacity: 0.6; pointer-events: none; }
.shared-answer__key { color: var(--c-text-muted); }
.shared-answer__key strong { color: var(--c-text); }

/* ---------- Minhas Compras: o que vem dentro do kit ----------
   O card do kit é o único que lista filhos: a compra é do kit (ADR 018), então
   é daqui que se estuda e se baixa. Reusa .mc-item por fora; o que muda é só a
   lista, separada do cabeçalho por uma linha. */
.mc-kit-itens {
  list-style: none;
  margin: 0.9rem 0 0;
  padding: 0.9rem 0 0;
  border-top: 1px solid var(--c-border);
  display: grid;
  gap: 0.6rem;
}
.mc-kit-item { display: flex; align-items: center; gap: 0.6rem; min-width: 0; }
.mc-kit-item > .material-symbols-outlined { font-size: 1.15rem; color: var(--c-text-muted); flex-shrink: 0; }
.mc-kit-item__nome { flex: 1; min-width: 0; }
.mc-kit-item__acoes { display: flex; gap: 0.4rem; flex-wrap: wrap; flex-shrink: 0; }

@media (max-width: 560px) {
  /* O nome sozinho na primeira linha; os botões abaixo, largos o bastante para
     o toque — a mesma quebra que .mc-item__botoes já faz no cartão. */
  .mc-kit-item { flex-wrap: wrap; }
  .mc-kit-item__acoes { width: 100%; }
}

/* ---------------------------------------------------------------------------
   Paleta de DESTAQUE do texto longo dos produtos (a descrição completa que a
   aluna lê na página do produto).

   São as ÚNICAS classes que o sanitizador aceita num <span>
   (HtmlSanitizer::PRODUCT_CLASSES), e é por isso que a cor sai de uma paleta e
   não de um seletor livre: `style=` nunca passa pelo sanitizador, e um hex
   escolhido no tema claro ficaria ilegível no escuro.

   O peso 600 não é enfeite: matiz sozinha não é distinção acessível (WCAG
   1.4.1) — quem não separa as cores continua vendo o destaque.
--------------------------------------------------------------------------- */
.dest-rosa { color: var(--c-dest-rosa); font-weight: 600; }
.dest-verde { color: var(--c-dest-verde); font-weight: 600; }
.dest-ambar { color: var(--c-dest-ambar); font-weight: 600; }
.dest-grifo {
  background-color: var(--c-dest-grifo);
  border-radius: 4px;
  padding: 0 0.2rem;
}

/* ---------------------------------------------------------------------------
   Editor da descrição longa do produto (_rich-product).

   Sem JavaScript aparece a TEXTAREA (o campo realmente enviado) e nenhum botão;
   o app.js marca `is-js` no bloco e inverte: o bloco editável aparece, a
   textarea some. O botão "HTML" da barra liga `is-html`, que devolve a textarea
   para quem precisa mexer na marcação na mão.
--------------------------------------------------------------------------- */
.rich-product__visual { display: none; }

.rich-product.is-js .rich-product__visual {
  display: block;
  min-height: 8rem;
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--c-secondary);
  border-radius: var(--radius-control);
  background-color: var(--c-surface);
}
.rich-product.is-js .rich-product__source { display: none; }
.rich-product.is-js.is-html .rich-product__visual { display: none; }
.rich-product.is-js.is-html .rich-product__source { display: block; }

.rich-product__visual:focus {
  outline: 2px solid var(--c-primary);
  outline-offset: 1px;
}
.rich-product__visual:empty::before {
  content: attr(data-placeholder);
  color: var(--c-text-muted);
}

.rich-product__toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem;
  margin-bottom: 0.45rem;
}
/* `display:` de autor vence o [hidden] do navegador — sem esta linha a barra
   nasceria aberta mesmo sem JS (a armadilha que já mordeu .field__toggle). */
.rich-product__toolbar[hidden] { display: none; }

.rich-product__btn {
  min-width: 2rem;
  padding: 0.25rem 0.5rem;
  border: 1px solid var(--c-border);
  border-radius: 8px;
  background-color: var(--c-surface);
  font-size: 0.9rem;
  line-height: 1.4;
  cursor: pointer;
}
.rich-product__btn:hover { border-color: var(--c-primary); }
.rich-product__btn--fonte[aria-pressed="true"] {
  background-color: var(--c-primary-soft);
  border-color: var(--c-primary);
  color: var(--c-primary-text);
}
.rich-product__sep {
  width: 1px;
  height: 1.2rem;
  background-color: var(--c-border);
}

/* O que vem dentro do kit, na página do produto: cada item é um bloco aberto
   (não mais um link para a página dele), com a descrição logo abaixo do nome.
   O item cresce em altura, então o alinhamento vertical vai para o topo. */
.prod-item { align-items: flex-start; }
.prod-item__resumo {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--c-text-muted);
}

/* Imagem do produto (só na página do produto). Sem aspect-ratio fixo: o admin
   decide só o TETO de largura e altura, então cortar aqui contrariaria a
   escolha dele — a imagem entra inteira, limitada pela coluna. */
.prod-capa {
  display: block;
  width: 100%;
  max-width: 100%;
  height: auto;
  margin-bottom: 1rem;
  border-radius: var(--radius-card);
  border: 1px solid var(--c-border);
  background-color: var(--c-surface-2);
}

/* ---------- Cupom de teste (_NN): a promessa dos dias no carrinho -----------
   Mora dentro do .cart-cupom-item, entre o código do cupom e o valor do
   desconto. Cor de AVISO e não de sucesso (que é a do valor descontado, logo
   abaixo): o desconto é certo, os dias de teste são promessa condicionada —
   plano mensal, total zero e quem ainda não tem acesso (App\Support\CouponTrial).
   O color-mix é o MESMO da .pill--warn de propósito: aquele par já é aprovado
   pelo ThemeContrastTest nos três temas. `align-self` porque o contêiner é uma
   coluna flex e o bloco esticaria de ponta a ponta. */
.cart-cupom-item__teste {
  display: flex;
  align-items: flex-start;
  gap: 0.3rem;
  align-self: flex-start;
  margin-top: 0.15rem;
  padding: 0.3rem 0.5rem;
  border-radius: var(--radius-control);
  background-color: color-mix(in srgb, var(--c-warning) 18%, var(--c-surface));
  color: color-mix(in srgb, var(--c-warning) 75%, var(--c-text));
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1.35;
}
.cart-cupom-item__teste .material-symbols-outlined { font-size: 0.95rem; flex-shrink: 0; }
/* O impedimento é informação, não promessa: sai do amarelo de destaque. */
.cart-cupom-item__teste--nao {
  background-color: var(--c-surface);
  border: 1px dashed var(--c-border);
  color: var(--c-text-muted);
  font-weight: 600;
}

/* ---------------------------------------------------------------------------
   Painel de detalhes embaixo da linha (/admin/assinaturas e /admin/pedidos)

   O painel é o mesmo `.detalhe-painel` de /assinatura e de Minhas Compras, mas
   aqui ele mora numa <tr> extra que existe SEMPRE, com um <td colspan> de altura
   zero enquanto está fechada. Ele precisa ser um <div> DENTRO do <td>, e não a
   própria <tr>: o app.js só busca conteúdo de painel sem filho elemento, e uma
   <tr> já nasce com o <td> dentro (é o mesmo motivo pelo qual o histórico do
   prompt virou lista em vez de tabela).

   A BORDA DE SEPARAÇÃO muda de dono: sai da linha de dado e vai para o rodapé
   da linha do painel. Com a linha fechada medindo zero, o fio cai no mesmo pixel
   de antes — e a regra `.table tr:last-child td` que já existe continua apagando
   o último. Sem isso, a última linha de dado deixaria de ser :last-child e a
   tabela terminaria com dois traços colados.

   Todo seletor usa `>` de propósito: o painel CONTÉM tabelas `.table` (cobranças,
   comissões, linha do tempo), e uma regra por descendente apagaria as bordas
   delas junto. */
.table--detalhes > tbody > tr > td { border-bottom: none; }
.table--detalhes > tbody > tr.detalhe-row > td { padding: 0; border-bottom: 1px solid var(--c-border); }
.table--detalhes > tbody > tr.detalhe-row:last-child > td { border-bottom: none; }

/* O painel não é linha de dado: não acende no hover da tabela. */
.table--detalhes > tbody > tr.detalhe-row:hover { background-color: transparent; }

/* O pequeno deslocamento para a direita, com o trilho do idioma "aninhado" já
   usado em .tax-tree--filhos. SEM fundo próprio: --c-surface-2 aqui apagaria a
   .pill--off, que é exatamente dessa cor — e o painel imprime "Cancelada",
   "Expirada" e "Pendente" nela. O border-top herdado do .detalhe-painel sai: a
   separação já é feita pela borda de rodapé do par. */
.detalhe-row .detalhe-painel {
  margin: 0 0 0 1rem;
  padding: 0.85rem 1rem 0.35rem;
  border-top: none;
  border-left: 3px solid var(--c-primary-soft);
}
@media (min-width: 768px) {
  .detalhe-row .detalhe-painel { margin-left: 2.25rem; }
}

/* Os painéis do admin empilham até oito blocos; no do cliente eles são dois e
   ficavam separados pela margem do que vinha antes. Aqui um <h4> cai logo
   depois de uma tabela ou de um <p style="margin:0">, e sem isto o título do
   bloco seguinte encosta no anterior. A regra é geral de propósito: o MESMO
   partial é impresso dentro do painel e dentro do card da página do pedido. */
.detalhe-titulo { margin-top: 1.3rem; }
.detalhe-painel > .detalhe-titulo:first-child,
.card > .detalhe-titulo:first-child { margin-top: 0; }

/* Valor longo e SEM espaço — o id de preferência do Mercado Pago tem 40+
   caracteres corridos — estourava a célula do .detalhe-grid e pintava por cima
   do valor da coluna seguinte (visto no painel de /admin/pedidos). Vale para
   todos os painéis de detalhe: e-mail comprido faz o mesmo. */
.detalhe-grid dd { overflow-wrap: anywhere; }
/* E a .log-mono nasceu para célula de TABELA da Central de Logs, onde `nowrap`
   é o certo; dentro do grid de detalhes ela é quem impedia a quebra. */
.detalhe-grid dd.log-mono { white-space: normal; }
