/* Botões — .btn-ghost e .navbtn são a mesma aparência; .navbtn existe só
   porque é aplicado a <a> (por isso o text-decoration abaixo). */
.btn-solid, .btn-ghost, .navbtn {
  font-family: var(--font);
  font-weight: 600;
  font-size: var(--fs-label);
  height: var(--control-md);
  padding: 0 var(--space-4);
  border-radius: var(--radius);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  white-space: nowrap;
  border: 1px solid transparent;
  /* Sprint 15.2 (I-04): microinteração sutil no hover — antes toda
     mudança de cor/borda era instantânea em todo o produto. */
  transition: border-color .12s ease, color .12s ease, background-color .12s ease, filter .12s ease;
}
.btn-solid { background: var(--accent); color: var(--accent-contrast); border-color: var(--accent); box-shadow: var(--card-shadow, none); }
.btn-solid:hover { filter: brightness(1.05); }
.btn-ghost, .navbtn { background: var(--surface); color: var(--text-primary); border-color: var(--border); }
.btn-ghost:hover, .navbtn:hover { border-color: var(--accent); color: var(--accent); }
.navbtn { text-decoration: none; }
.navbtn-icon { min-width: 40px; justify-content: center; }
/* Filtro rápido selecionado (Sprint 14) — mesmo .navbtn, só o estado
   ativo, no mesmo vocabulário visual do item ativo da sidebar. */
.navbtn-active { border-color: var(--accent); color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--surface)); }
.btn-icon { width: var(--control-md); height: var(--control-md); padding: 0; justify-content: center; background: none; border: 1px solid transparent; border-radius: var(--radius-sm); color: var(--text-secondary); cursor: pointer; display: inline-flex; align-items: center; transition: background-color .12s ease, color .12s ease; }
.btn-icon:hover { background: var(--bg-subtle); color: var(--accent); }

/* Inputs */
input[type=text], input[type=email], input[type=password], input[type=date], input[type=month], select, textarea {
  font-family: var(--font);
  font-size: var(--fs-label);
  color: var(--text-primary);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0 var(--space-3);
  height: var(--control-md);
  transition: border-color .12s ease;
}
textarea { padding: var(--space-2) var(--space-3); min-height: 72px; height: auto; resize: vertical; width: 100%; }
input:focus-visible, select:focus-visible, textarea:focus-visible { border-color: var(--accent); }

/* Sprint 15 (RF11): estado desabilitado no baseline do Design System —
   antes não existia, e um controle desabilitado ficava idêntico a um
   ativo. Vale para botões e campos, sem classe nova. */
button:disabled, input:disabled, select:disabled, textarea:disabled,
.btn-solid:disabled, .btn-ghost:disabled {
  opacity: .5;
  cursor: not-allowed;
  filter: none;
}
button:disabled:hover, .btn-ghost:disabled:hover, .btn-solid:disabled:hover {
  border-color: var(--border);
  color: inherit;
  filter: none;
}

/* Cards / painéis */
.panel, .col, .task, .login-box {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--card-shadow, none);
}
.panel { padding: var(--space-4); margin-bottom: var(--space-4); }
.panel h4 { font-size: var(--fs-lg); margin-bottom: var(--space-3); }

/* Card das telas de autenticação (login, recuperação de senha).
   Sprint 15: .auth-card foi absorvida aqui — eram duas classes com o
   mesmo max-width aplicadas ao mesmo elemento. Formulário e botão são
   responsabilidade de .stacked-form / .btn-block. */
.login-box {
  width: 100%;
  max-width: 400px;
  margin: var(--space-16) auto;
  padding: var(--space-8);
  box-shadow: var(--shadow-md);
}

/* Trocar senha: centraliza .login-box verticalmente no espaço visível
   abaixo do appbar (56px, mesmo cálculo já usado por .sidebar), em vez
   de só ancorado no topo por margin-top fixo — só nesta tela, que fica
   atrás de login (sem appbar). */
.auth-shell {
  min-height: calc(100vh - 56px);
  display: flex;
  align-items: center;
  justify-content: center;
}
.auth-shell .login-box {
  margin: 0;
}

/* Telas de autenticação reprojetadas (Sprint 13): card com wordmark,
   título e formulário com labels explícitos. Reaproveita .login-box
   (card centralizado) e .stacked-form (compartilhado com Alterar senha). */
.auth-brand { margin-bottom: var(--space-6); }
.auth-wordmark { font-weight: 800; font-size: var(--fs-title); color: var(--accent); letter-spacing: -.01em; }
.auth-tagline { font-size: var(--fs-meta); color: var(--text-tertiary); margin-top: 2px; }
.auth-title { font-size: var(--fs-title); font-weight: 700; margin-bottom: var(--space-4); }
.auth-text { margin: var(--space-2) 0 var(--space-4); color: var(--text-secondary); font-size: var(--fs-label); line-height: var(--lh-base); }
.auth-links { margin-top: var(--space-4); text-align: center; font-size: var(--fs-label); }
.auth-welcome { font-size: var(--fs-title); font-weight: 700; margin-bottom: var(--space-1); }
.auth-subtext { font-size: var(--fs-label); color: var(--text-secondary); margin-bottom: var(--space-6); }
.auth-subtext a { font-weight: 600; }

/* Formulário com labels empilhados — reutilizado por login, recuperação
   de senha e Alterar senha. */
.stacked-form { display: flex; flex-direction: column; gap: var(--space-3); }
.stacked-form label { display: flex; flex-direction: column; gap: var(--space-1); font-size: var(--fs-label); font-weight: 600; color: var(--text-secondary); }
.stacked-form input { width: 100%; }

/* Validação client-side (Sprint 17): erro só aparece depois que o campo
   obrigatório é tocado e sai vazio (padrão "touched", igual ClickUp) —
   JS alterna .field-invalid/.field-error-text, sem componente novo. */
.field-error-text { display: none; color: var(--danger); font-size: var(--fs-meta); font-weight: 500; margin-top: -2px; }
.stacked-form label.field-invalid input { border-color: var(--danger); }
.stacked-form label.field-invalid .field-error-text { display: block; }

/* Campo de senha com botão de mostrar/ocultar embutido — reaproveita o
   mesmo input de .stacked-form, só adiciona o botão posicionado dentro. */
.password-field { position: relative; }
.password-field input { padding-right: calc(var(--control-md) - 4px); }
.password-field .btn-icon { position: absolute; right: 2px; top: 2px; }
.password-field .btn-icon .eye-open { display: none; }
.password-field .btn-icon.revealed .eye-open { display: inline-flex; }
.password-field .btn-icon.revealed .eye-closed { display: none; }
.btn-block { width: 100%; justify-content: center; height: var(--control-lg); font-size: var(--fs-lg); }
.form-panel { max-width: 480px; }
.form-actions { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-1); }

/* Login (Sprint 18): duas colunas — institucional à esquerda (fundo
   abstrato + Aurora, sem foto ainda) e o formulário à direita. Cores
   fixas (não var(--bg)/var(--surface)): esta tela roda sob
   base_auth.html com data-theme="light" travado, então usar os tokens
   normais aqui seria reintroduzir a variação de tema que o
   isolamento existe pra evitar.
   --auth-visual-image fica reservada e vazia de propósito — quando
   houver uma foto real, basta declará-la (uma linha, aqui) sem tocar
   em nenhum template. */
.auth-page { display: flex; min-height: 100vh; }

.auth-visual {
  --auth-visual-image: none;
  flex: 0 0 55%;
  position: relative;
  overflow: hidden;
  background-color: #1E1B4B;
  background-image: var(--auth-visual-image);
  background-size: cover;
  background-position: center;
  display: flex;
  align-items: flex-end;
  padding: var(--space-16);
}
/* Base abstrata: 100% CSS, sem imagem — convive atrás de uma foto real
   quando --auth-visual-image for definida. */
.auth-visual::before {
  content: '';
  position: absolute; inset: 0;
  background:
    radial-gradient(60% 50% at 15% 85%, rgba(91,95,239,.55), transparent 70%),
    radial-gradient(50% 45% at 85% 70%, rgba(129,140,248,.35), transparent 70%),
    linear-gradient(160deg, #1E1B4B 0%, #312E81 55%, #1E1B4B 100%);
}
/* Overlay escuro suave, pra manter contraste do texto mesmo se
   --auth-visual-image virar uma foto clara no futuro. */
.auth-visual::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,.1) 0%, rgba(0,0,0,.45) 100%);
}
/* Aurora: brilho elegante e rápido no topo, não um degradê forte —
   3 radiais claros na paleta do produto, sem repetir a cor do ClickUp. */
.auth-aurora {
  position: absolute; inset: 0 0 auto 0; height: 48%;
  background:
    radial-gradient(42% 65% at 18% 0%, rgba(165,180,252,.55), transparent 70%),
    radial-gradient(36% 60% at 55% 0%, rgba(103,232,249,.4), transparent 70%),
    radial-gradient(32% 55% at 88% 0%, rgba(253,186,140,.35), transparent 70%);
  mix-blend-mode: screen;
}
.auth-visual-content { position: relative; z-index: 1; max-width: 30rem; color: #fff; }
.auth-visual-brand { font-size: var(--fs-label); font-weight: 700; letter-spacing: .08em; text-transform: uppercase; opacity: .85; margin-bottom: var(--space-4); }
.auth-visual-title { font-size: 2.25rem; font-weight: 700; line-height: var(--lh-tight); letter-spacing: -.01em; margin-bottom: var(--space-4); }
.auth-visual-text { font-size: var(--fs-lg); line-height: var(--lh-base); color: rgba(255,255,255,.85); max-width: 36ch; }

.auth-panel { flex: 1; display: flex; align-items: center; justify-content: center; padding: var(--space-8); background: #FAFAFA; }
.auth-panel-inner { width: 100%; max-width: 400px; }
/* Mesmo login-box de antes, só sem chrome de card — a coluna já dá o
   contraste de fundo, um segundo cartão por cima ficaria redundante. */
.auth-panel .login-box { max-width: none; margin: 0; padding: 0; border: none; box-shadow: none; background: transparent; }

@media (max-width: 1024px) {
  .auth-visual { flex-basis: 42%; padding: var(--space-8); }
  .auth-visual-title { font-size: 1.75rem; }
}
@media (max-width: 720px) {
  .auth-visual { display: none; }
  .auth-panel { padding: var(--space-6); }
}

/* Breadcrumb (Sprint 13): só onde há hierarquia real de navegação. */
.breadcrumb { display: flex; align-items: center; gap: var(--space-2); font-size: var(--fs-meta); color: var(--text-tertiary); margin-bottom: var(--space-3); flex-wrap: wrap; }
.breadcrumb a { color: var(--text-secondary); text-decoration: none; }
.breadcrumb a:hover { color: var(--accent); }
.breadcrumb-sep { color: var(--text-tertiary); }
.breadcrumb-current { color: var(--text-primary); font-weight: 600; }

/* Home (Sprint 13): reaproveita .panel/.stat-card/.chip/.navbtn; só
   acrescenta o realce de tom dos alertas, o subtítulo e os agrupamentos. */
.page-sub { font-size: var(--fs-label); color: var(--text-secondary); margin-top: var(--space-1); }
a.stat-card { text-decoration: none; color: inherit; display: block; transition: border-color .12s; }
a.stat-card:hover { border-color: var(--accent); }
.stat-danger .stat-num { color: var(--danger); }
.stat-warn .stat-num { color: var(--status-aguardando); }
.stat-ok .stat-num { color: var(--success); }
/* Sprint 15.2 (R-04): tom neutro explícito — antes a Home do dev usava
   stat-neutral sem nenhuma regra correspondente (o card só "acertava"
   por acidente, herdando a cor padrão de .stat-num). */
.stat-neutral .stat-num { color: var(--text-primary); }
.home-list { display: flex; flex-direction: column; }
/* Linha clicável em lista — mesmo destaque de fundo de .data-table
   tr:hover. Sprint 16: .thread-summary-row (Recados) saiu do seletor,
   já que a classe deixou de ser emitida em qualquer template. */
.home-list-row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-3) var(--space-1);
  border-bottom: 1px solid var(--border);
  text-decoration: none; color: var(--text-primary); font-size: var(--fs-label); font-weight: 600;
  transition: background-color .12s ease;
}
.home-list-row:last-child { border-bottom: none; }
.home-list-row:hover { background: var(--bg-subtle); }
/* Índice de Configurações (Sprint 15): reaproveita .home-list-row; só
   nomeia as duas partes da linha (destino + descrição). */
.settings-item { display: inline-flex; align-items: center; gap: var(--space-2); }
.settings-desc { color: var(--text-tertiary); font-weight: 400; font-size: var(--fs-meta); text-align: right; }
.home-integrations { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.home-integration { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--fs-label); font-weight: 600; }
.quick-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }

/* Dashboard (Sprint 14): hierarquia de leitura — problemas críticos com
   mais peso visual; IA subordinada (fundo recuado, título menor), para
   parecer apoio e nunca o foco. Só apresentação: reaproveita
   .panel/.stat-card/.data-table/.navbtn já existentes. */
.panel-critical { border-color: color-mix(in srgb, var(--danger) 35%, var(--border)); }
/* Sprint 22 (auditoria de UX do módulo Análises, item 3): o título da
   seção crítica do Dashboard reforça a mesma urgência já sinalizada pela
   borda — hoje só a borda diferenciava .panel-critical de um painel
   comum, peso visual insuficiente para a seção de maior prioridade. */
.panel-critical h4 { color: var(--danger); }
.panel h4 { display: flex; align-items: center; gap: var(--space-2); }
.section-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-3); }
.table-note { font-size: var(--fs-meta); color: var(--text-tertiary); margin-top: var(--space-2); }
/* Tabela larga rola dentro do próprio painel — a página nunca rola na
   horizontal (a partir de 640px a .data-table já vira cards). */
.table-scroll { overflow-x: auto; }

.panel-ai { background: var(--bg-subtle); }
.panel-ai h4 { font-size: var(--fs-body); color: var(--text-secondary); }
/* Sprint 15.2 (I-03): max-width vinha declarado aqui (70ch) E na regra
   unificada de largura de leitura abaixo (var(--readable), 72ch) — as
   duas com a mesma especificidade, a de baixo sempre vencia, deixando o
   70ch morto e confuso para quem fosse editar. Removido; a largura vem
   só da regra unificada. line-height tokenizado (R-05). */
.panel-note { font-size: var(--fs-meta); color: var(--text-tertiary); margin-bottom: var(--space-3); line-height: var(--lh-base); }
.ai-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); gap: var(--space-3); }
/* Sprint 24 (ideias de consistência de card): raio unificado com
   .panel/.task/.stat-card (var(--radius), 8px) — antes usava
   --radius-sm (6px) sem motivo de design, só deriva. Hover acende a
   borda em --accent, mesmo tratamento de .task:hover. */
.ai-item { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: var(--space-3); transition: border-color .12s; }
.ai-item:hover { border-color: var(--accent); }
.ai-item-title { font-size: var(--fs-label); font-weight: 600; }
.ai-item-text { font-size: var(--fs-label); color: var(--text-secondary); margin-top: var(--space-2); white-space: pre-wrap; line-height: var(--lh-base); }
/* Sprint 23 (T11): estado de carregamento de um painel de IA — mesmo tom
   de .empty (itálico, cor terciária), só pra não parecer um resultado
   final enquanto a geração está em andamento. */
.ai-item-loading { font-size: var(--fs-label); color: var(--text-tertiary); font-style: italic; margin-top: var(--space-2); }
/* Resposta completa no Histórico de IA — mesmo tratamento de texto do
   painel do Dashboard (preserva quebras de linha, mesmo line-height:
   R-05 unificou o que antes eram 1.5 e 1.6 para o mesmo tipo de
   conteúdo), em corpo de leitura. */
.ai-response-text { white-space: pre-wrap; line-height: var(--lh-base); color: var(--text-primary); max-width: var(--readable); }
.btn-sm { height: var(--control-sm); padding: 0 var(--space-2); font-size: var(--fs-meta); }

/* Sprint 15 (RF2): largura confortável de leitura. `.page` vai até
   1280px, então blocos de texto corrido (mural, recados, resposta de IA,
   resumo, timeline) esticavam a linha de ponta a ponta. Utilitário único
   — não é componente novo, só um limite aplicado a texto. */
.readable { max-width: var(--readable); }
.panel-note, .summary-line, .auth-text, .ai-item-text,
.timeline-comment-text { max-width: var(--readable); }
/* Sprint 21: .mural-item-text saiu deste selector — o limite de 72ch
   fazia sentido só na sidebar estreita do Mural do dev (340px, já
   limitada pelo próprio container). No painel full-width do admin isso
   deixava o texto sempre numa coluna estreita cercada de espaço vazio.
   O container (.mural-grid ou .dev-side) já define a largura certa em
   cada contexto, sem precisar do limite aqui. */

/* Chips e badge de status compartilham a mesma forma de "pílula"
   (Sprint 15.2, R-01) — cada um só acrescenta o tom/peso que o distingue
   semanticamente (chip = metadado neutro; status-badge = estado colorido). */
.chip, .status-badge {
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius-pill);
  padding: var(--space-1) var(--space-2);
  font-size: var(--fs-meta);
}
.chip {
  background: var(--bg-subtle);
  color: var(--text-secondary);
  gap: var(--space-1);
}
.chip.overdue { color: var(--danger); background: color-mix(in srgb, var(--danger) 12%, var(--surface)); font-weight: 600; }
/* Prioridade de incidente (Sprint 16) — baixa/média ficam no tom neutro
   padrão do chip (sem classe extra); alta/crítica reaproveitam
   exatamente o mesmo tom de .chip.overdue, com nome próprio para não
   emprestar uma classe pensada para prazo vencido. */
.chip.priority-alta { color: var(--status-aguardando); background: color-mix(in srgb, var(--status-aguardando) 16%, var(--surface)); font-weight: 600; }
.chip.priority-critica { color: var(--danger); background: color-mix(in srgb, var(--danger) 12%, var(--surface)); font-weight: 600; }

/* Badge de status: fundo tingido (identifica o status) + texto sempre em
   --text-primary (contraste AA); o ícone já carrega a cor semântica via
   stroke="var(--status-*)" direto no SVG, então o texto não precisa repetir
   a cor e sacrificar legibilidade. Gap ligeiramente maior que o do chip
   (6px, não é --space-1/--space-2) — ícone+texto pedem mais respiro do
   que o par metadado do chip; valor intencional, não é token faltando. */
.status-badge {
  gap: 6px;
  font-weight: 600;
  color: var(--text-primary);
}
.status-andamento { background: color-mix(in srgb, var(--status-andamento) 14%, var(--surface)); }
.status-aguardando { background: color-mix(in srgb, var(--status-aguardando) 16%, var(--surface)); }
.status-bloqueado { background: color-mix(in srgb, var(--status-bloqueado) 14%, var(--surface)); }
.status-pausado { background: color-mix(in srgb, var(--status-pausado) 16%, var(--surface)); }
.status-concluido { background: color-mix(in srgb, var(--status-concluido) 16%, var(--surface)); }
/* Status de incidente "monitorando" (Sprint 16) — único tom novo; os
   outros 4 status de incidente reaproveitam os tons de status de tarefa
   já existentes (ver STATUS_BADGE_CLASS em domain/incidents.py). */
.incident-monitorando { background: color-mix(in srgb, var(--accent) 14%, var(--surface)); }

/* Tabela densa (visão de mês, Task 6) */
.data-table { width: 100%; border-collapse: collapse; font-size: var(--fs-label); }
.data-table th { text-align: left; color: var(--text-tertiary); font-weight: 600; font-size: var(--fs-meta); text-transform: uppercase; letter-spacing: .04em; padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--border); }
.data-table td { padding: var(--space-3); border-bottom: 1px solid var(--border); color: var(--text-primary); }
.data-table tr td { transition: background-color .12s ease; }
.data-table tr:hover td { background: var(--bg-subtle); }
.data-table tr.task-blocked td:first-child { border-left: 3px solid var(--danger); }
/* PLAN-002: célula de carga futura sinalizada como sobrecarga — mesmo
   padrão de destaque de .chip.overdue, reaproveitando --danger. */
.data-table td.cell-overload { background: color-mix(in srgb, var(--danger) 12%, var(--surface)); color: var(--danger); font-weight: 600; }

@media (max-width: 640px) {
  .data-table thead { display: none; }
  .data-table, .data-table tbody, .data-table tr, .data-table td { display: block; width: 100%; }
  .data-table tr { border: 1px solid var(--border); border-radius: var(--radius); margin-bottom: var(--space-3); padding: var(--space-2); }
  .data-table tr.task-blocked td:first-child { border-left: none; }
  .data-table tr.task-blocked { border-left: 3px solid var(--danger); }
  .data-table td { border: none; padding: var(--space-1) var(--space-2); display: flex; justify-content: space-between; gap: var(--space-4); }
  .data-table td::before { content: attr(data-label); color: var(--text-tertiary); font-size: var(--fs-meta); font-weight: 600; }
}

/* Ícones SVG (Task 2) */
.icon { width: 16px; height: 16px; flex-shrink: 0; display: inline-block; vertical-align: middle; }

/* Indicador de "Salvo" (Task 3) */
.saved-indicator {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-meta); color: var(--status-concluido);
  opacity: 0; transition: opacity .2s;
}
.saved-indicator.show { opacity: 1; }

/* ---------------------------------------------------------------------
   Compatibilidade: classes já usadas pelos templates de tela existentes
   (dev_board.html, admin_board.html, month_view.html, _task.html) que
   não fazem parte do conjunto principal acima. Os templates não mudam
   nesta tarefa, então essas classes precisam de estilo com os novos
   tokens para nada ficar "sem estilo". Serão revisadas/substituídas nas
   Tasks 2-6 conforme o plano.
   --------------------------------------------------------------------- */

/* Cartão de tarefa: layout interno (num + corpo) */
.task { padding: var(--space-3); display: flex; gap: var(--space-3); min-width: 0; }
.task:hover { border-color: var(--accent); }
/* Sprint 24 (ideias de consistência de card): dentro de .col (Board do
   admin), o card da tarefa não precisa de sombra própria — .col já
   carrega a sua. No Board do dev, a tarefa vive em .week-panel (que não
   tem sombra própria), então mantém a sua ali. */
.col .task { box-shadow: none; }
.task-blocked { border-left: 3px solid var(--danger); }
.task-num {
  font-weight: 700; font-size: var(--fs-lg); color: var(--accent); min-width: 28px;
  text-align: right; line-height: 1.25; border: none; background: none;
  font-family: var(--font); padding: 0; cursor: pointer;
}
.task-num:hover { text-decoration: underline; }
.task-body { flex: 1; min-width: 0; }
.task-title-input {
  width: 100%; border: none; background: transparent;
  font-size: var(--fs-body); font-weight: 700; font-family: var(--font);
  color: var(--text-primary); outline: none;
  /* padding/line-height ajustados a este campo específico (alinhar o
     caret com o texto de .task-title-ro ao lado) — não são parte da
     escala de espaçamento/leitura, por isso não usam token (R-07). */
  padding: 1px 0; line-height: 1.35;
}
.task-title-ro { font-size: var(--fs-body); font-weight: 700; line-height: 1.35; color: var(--text-primary); }
.task-meta { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-2); flex-wrap: wrap; }
.task-meta select, .task-meta input[type=date] { font-size: var(--fs-meta); padding: 0 var(--space-2); height: var(--control-sm); min-width: 0; }
.task-meta input[type=date].overdue { color: var(--danger); font-weight: 600; background: color-mix(in srgb, var(--danger) 12%, var(--surface)); border-color: var(--danger); }
.task-meta-readonly { font-size: var(--fs-meta); color: var(--text-secondary); margin-top: var(--space-2); }
.task-actions-row { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-2); flex-wrap: wrap; }
.task-actions-row form { display: inline; }
.btn-star { border: 1px solid transparent; background: none; cursor: pointer; font-size: var(--fs-lg); color: var(--text-tertiary); line-height: 1; }
.btn-star.on { color: var(--accent); }
/* Botão-ícone pequeno (mover, remover). Sprint 15: .mini-x era uma
   segunda classe para o mesmo papel, com aparência diferente — a
   lixeira de Clientes/Modelos/Recorrências não batia com a da tarefa.
   Consolidadas nesta. */
.btn-mini { border: none; background: none; color: var(--text-tertiary); cursor: pointer; padding: var(--space-1); display: inline-flex; align-items: center; flex-shrink: 0; border-radius: var(--radius-sm); }
.btn-mini:hover { color: var(--danger); background: var(--bg-subtle); }
/* Sprint 23 (T7): o hover vermelho de .btn-mini sinaliza perigo — correto
   para excluir, mas os botões de reordenar (mover ↑/↓) não são
   destrutivos e não devem herdar esse sinal. .btn-nudge neutraliza a cor
   (fica no acento), preservando o restante da caixa de .btn-mini. Regra
   depois de .btn-mini:hover para vencer por ordem de origem. */
.btn-nudge:hover { color: var(--accent); }
.add-task-form { display: flex; gap: var(--space-2); padding: var(--space-3) var(--space-3) 0; }
.add-task-form input { flex: 1; border: 1px dashed var(--border); min-width: 0; }
.empty { font-size: var(--fs-label); color: var(--text-tertiary); font-style: italic; padding: var(--space-1) 0 var(--space-2); }
.empty-card {
  display: flex; flex-direction: column; gap: var(--space-1);
  min-height: 92px; justify-content: center;
  background: var(--bg-subtle); border: 1px dashed var(--border);
  border-radius: var(--radius); padding: var(--space-4);
}
.empty-card strong { font-size: var(--fs-lg); color: var(--text-primary); }
.empty-card span { font-size: var(--fs-label); color: var(--text-secondary); }
.empty-card-wide { grid-column: 1 / -1; }

/* Badge numérico (contagem de não lidos). Padding próprio (não a escala
   --space-*) para manter a proporção de pílula bem justa ao redor de 1-2
   dígitos — --space-1 deixaria o badge visivelmente maior (R-07). */
.badge {
  background: var(--accent); color: var(--accent-contrast);
  border-radius: var(--radius-pill); font-size: var(--fs-meta); font-weight: 700;
  padding: 2px 7px; display: inline-flex; align-items: center;
}


/* Aviso de tom neutro/atenção. Forma compartilhada com .flash em
   base.css (Sprint 15.2, I-02) — aqui só o tom.
   .readonly-banner: especificamente para telas em modo somente leitura
   (semana encerrada, visão de mês). .banner-attention: mesmo tom, para
   avisos informativos que não são sobre travamento de edição (ex.:
   "exibindo os primeiros N resultados" na Busca) — reaproveita o mesmo
   visual sem emprestar um nome de classe que sugere a coisa errada. */
.readonly-banner, .banner-attention {
  background: color-mix(in srgb, var(--status-aguardando) 14%, var(--surface));
  border-color: var(--status-aguardando);
  color: var(--text-primary);
}

/* Linhas de cadastro (Equipe, Clientes, Modelos, Recorrências).
   Sprint 15 (N-05): a linha da lista e a linha de "adicionar" viviam com
   dimensionamentos diferentes (lista com input 100%, add-row sem largura),
   o que deixava os campos desalinhados dentro do mesmo painel. Agora
   ambas usam o mesmo esqueleto flexível. */
/* Sprint 24 (ideias de consistência de card): layout "título/meta à
   esquerda, ação à direita" era declarado três vezes de forma idêntica
   (.mgmt-row, .ai-item-head, .mural-item-meta) — unificado aqui; cada
   classe mantém só a tipografia/espaçamento que já era própria dela. */
.mgmt-row, .ai-item-head, .mural-item-meta {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
}
.mgmt-row { margin-bottom: var(--space-2); font-size: var(--fs-label); flex-wrap: wrap; }
/* Só o formulário de edição (o primeiro da linha) ocupa o espaço livre;
   os formulários de ação (ativar, remover) ficam do tamanho do próprio
   botão — sem isso todos dividiam a linha em partes iguais e o campo de
   texto ficava com metade da largura disponível. */
.mgmt-row > form { display: flex; align-items: center; gap: var(--space-2); flex: 0 0 auto; flex-wrap: wrap; }
.mgmt-row > form:first-child { flex: 1 1 auto; min-width: 0; }
.mgmt-row input[type=text], .mgmt-row select { flex: 1; min-width: 140px; }
/* Formulário de "adicionar" — mesmo esqueleto da linha da lista acima,
   para os campos alinharem dentro do painel. */
.add-row { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-3); padding-top: var(--space-3); border-top: 1px solid var(--border); flex-wrap: wrap; }
.add-row input[type=text], .add-row input[type=email], .add-row select { flex: 1; min-width: 140px; }
/* Sprint 18: quando "Adicionar X" fica no seu próprio painel (com título
   h4), a borda/margem de topo da .add-row viram ruído — o painel já
   separa. .add-row-plain reaproveita o layout flex sem o divisor. */
.add-row-plain { border-top: none; margin-top: 0; padding-top: 0; }

/* Sprint 18: agrupa múltiplas ações (formulários independentes) numa
   célula de tabela sem que cada <form> quebre em bloco — usado na tabela
   de Integrações. */
.row-actions { display: inline-flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }

/* Mural de avisos */
.mural-form { margin-bottom: var(--space-3); }
/* Sprint 27 (reposicionamento do Mural): cabeçalho com título à esquerda
   e o botão "Publicar aviso" à direita (mesmo layout de .ai-item-head/
   .mgmt-row). Estado vazio vira uma linha discreta no lugar do
   .empty-card grande, já que o Mural agora fica no topo do board. */
.mural-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-3); }
.mural-head h4 { margin-bottom: 0; }
.mural-empty { font-size: var(--fs-label); color: var(--text-tertiary); margin: 0; }
/* Sprint 24 (ideias de consistência de card): raio unificado (var(--radius),
   igual a .panel/.task/.ai-item/.stat-card) e borda própria — antes só a
   cor de fundo diferenciava o card, "achatado" ao lado dos demais. Hover
   acende a borda em --accent, mesmo tratamento usado em .task/.ai-item. */
.mural-item { background: var(--bg-subtle); border: 1px solid var(--border); border-radius: var(--radius); padding: var(--space-3); margin-bottom: var(--space-2); transition: border-color .12s; }
.mural-item:hover { border-color: var(--accent); }
.mural-item-text { font-size: var(--fs-label); white-space: pre-wrap; margin: 0; }
/* Sprint 23: leitura (parágrafo) e edição (textarea) usam a mesma classe
   de texto — só uma das duas está visível por vez (toggleMuralEdit,
   app.js). .mural-item-edit-form some via o atributo [hidden] nativo. */
.mural-item-edit-form textarea.mural-item-text { margin-bottom: var(--space-2); }
.mural-item-meta { font-size: var(--fs-meta); color: var(--text-tertiary); margin-top: var(--space-2); }
.mural-item-actions { display: flex; align-items: center; gap: var(--space-1); flex-shrink: 0; }
/* Sprint 21 organizou os avisos em grid de colunas (mesma técnica de
   .counters); Sprint 24 reverteu pra lista vertical de largura total —
   um grid de colunas só fica bem com itens suficientes pra preencher a
   linha. Com 1 ou 2 avisos (o caso mais comum), mesmo com teto de
   largura (tentativa anterior desta mesma sprint), sobrava um vazio
   grande ao lado do card. Lista full-width é o padrão de conteúdo
   cronológico (Slack, Notion, mural físico): nunca sobra espaço vazio,
   qualquer que seja a quantidade de avisos. O mural do dev (sidebar
   estreita) já era coluna única, sem nenhuma destas classes. */
.mural-list { display: flex; flex-direction: column; gap: var(--space-2); }
.mural-list .mural-item { margin-bottom: 0; }
/* Aviso mais recente ganha o mesmo destaque de borda já usado em
   .data-table tr.task-blocked — reaproveita --accent, sem badge novo. */
.mural-item-recent { border-left: 3px solid var(--accent); }

/* Formulário de comentário/atualização — compartilhado pela timeline de
   tarefa (_task_detail.html) e pela timeline de incidente
   (incident_detail.html). Sprint 16: classes exclusivas de Recados
   (.chat-thread/.chat-msg/.chat-who/.chat-text/.chat-ts/.side-chat-form/
   .thread-snippet) removidas — Recados saiu de interface e código. */
.chat-form { display: flex; gap: var(--space-2); align-items: flex-start; }
.chat-form .btn-solid { margin-top: 0; flex-shrink: 0; }

/* Filtro (select de dev nas telas de admin) */
.filter-form select { max-width: 100%; }
/* Campo com label acima, em barra de filtro horizontal (Sprint 14). */
.field { display: flex; flex-direction: column; gap: var(--space-1); font-size: var(--fs-meta); font-weight: 600; color: var(--text-secondary); }
/* Tendência (↑ +2) — secundária, não compete com o número. */
.trend { font-size: var(--fs-meta); color: var(--text-tertiary); white-space: nowrap; }
/* Sprint 15.2 (I-03): esta regra redeclarava max-width: 80ch e
   line-height: 1.6, sobrescrevendo silenciosamente a largura de leitura
   unificada (var(--readable), 72ch) e o line-height padrão (R-05) — o
   Resumo do período em Evolução era o único texto do produto fora do
   padrão. Ambas as propriedades removidas; vêm da regra compartilhada. */
.summary-line { font-size: var(--fs-label); color: var(--text-secondary); }

/* Modal de detalhes da tarefa (Sprint 2) */
.modal-overlay {
  position: fixed; inset: 0; background: rgba(0,0,0,.4);
  display: flex; align-items: center; justify-content: center;
  z-index: 50; padding: var(--space-4);
}
.modal-overlay[hidden] { display: none; }
.modal {
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow-md);
  max-width: 640px; width: 100%; max-height: 85vh; overflow-y: auto;
  position: relative; padding: var(--space-4);
}
.modal-close { position: absolute; top: var(--space-3); right: var(--space-3); }
.modal-tabs {
  display: flex; gap: var(--space-2); border-bottom: 1px solid var(--border);
  margin-bottom: var(--space-3); padding-right: var(--space-8);
}
.modal-tab {
  border: none; background: none; border-bottom: 2px solid transparent;
  padding: var(--space-2) var(--space-1); font-size: var(--fs-label);
  font-family: var(--font); color: var(--text-secondary); cursor: pointer;
}
.modal-tab.active { color: var(--text-primary); border-bottom-color: var(--accent); font-weight: 600; }
.task-info-list { display: grid; grid-template-columns: auto 1fr; gap: var(--space-2) var(--space-3); font-size: var(--fs-label); }
.task-info-list dt { color: var(--text-tertiary); font-size: var(--fs-meta); }
.task-info-list dd { margin: 0; }
.timeline-list { display: flex; flex-direction: column; gap: var(--space-2); }
.timeline-item { font-size: var(--fs-label); padding-bottom: var(--space-2); border-bottom: 1px solid var(--border); }
.timeline-time { color: var(--text-tertiary); font-size: var(--fs-meta); margin-right: var(--space-2); }
.timeline-comment-text { white-space: pre-wrap; margin-top: var(--space-1); }
.modal-tab-panel .chat-form { margin-top: var(--space-3); }
.checklist-row .checklist-toggle-form,
.checklist-row .checklist-label { flex: 1; min-width: 0; }
.checklist-label { display: flex; align-items: center; gap: var(--space-2); cursor: pointer; }
.checklist-done-text { color: var(--text-tertiary); text-decoration: line-through; }
.checklist-rename-input { border: none; background: transparent; }
.attachment-info { min-width: 0; }
.attachment-meta { font-size: var(--fs-meta); color: var(--text-tertiary); margin-top: 1px; }
