:root {
  --primary: #6c5ce7;
  --primary-dark: #5a4bd1;
  --danger: #e17055;
  --success: #00b894;
  --warning: #b7791f;
  --bg: #f5f6fa;
  --card-bg: #ffffff;
  --text: #2d3436;
  --text-muted: #636e72;
  --border: #e0e3e8;
  --primary-tint: #6c5ce71a;
  --danger-tint: #e1705522;
  --success-tint: #00b89422;
  --warning-tint: #f1c40f26;
  --overlay-bg: rgba(0, 0, 0, 0.4);
  --modal-shadow: none;
  --radius: 10px;
  color-scheme: light;
}

html[data-theme='dark'] {
  color-scheme: dark;
  --primary: #8b7cf6;
  --primary-dark: #a599f8;
  --danger: #ff8a75;
  --success: #35d0a4;
  --warning: #f0c95c;
  --bg: #15161d;
  --card-bg: #1e2029;
  --text: #eae8f2;
  --text-muted: #9b97ab;
  --border: #2b2d3a;
  --primary-tint: #8b7cf62e;
  --danger-tint: #ff8a752e;
  --success-tint: #35d0a42e;
  --warning-tint: #f0c95c2e;
  --overlay-bg: rgba(0, 0, 0, 0.6);
  --modal-shadow: 0 20px 60px -15px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.05);
}

* {
  box-sizing: border-box;
}

/* Garante que o atributo hidden sempre esconda o elemento, mesmo quando
   uma regra mais específica (ex: a.btn-secondary) tenta definir display. */
[hidden] {
  display: none !important;
}

body {
  margin: 0;
  font-family: 'Segoe UI', Roboto, Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
}

body,
.sidebar,
.toolbar-right,
.period-tabs,
.view-toggle,
.task-row,
.board-column,
.board-card,
.board-cards,
.modal,
.modal-overlay,
.tag,
.badge,
button,
input,
select {
  transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 999px;
}

* {
  scrollbar-width: thin;
  scrollbar-color: var(--border) transparent;
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
.project-item:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

button {
  font: inherit;
  cursor: pointer;
}

.app {
  display: grid;
  grid-template-columns: 260px 1fr;
  min-height: 100vh;
}

/* Sidebar recolhida (desktop/tablet): esconde a coluna via o botão
   "sidebarToggleBtn" no toolbar. */
.app.sidebar-collapsed {
  grid-template-columns: 1fr;
}

.app.sidebar-collapsed .sidebar {
  display: none;
}

.sidebar-toggle-btn {
  margin-right: 4px;
  flex-shrink: 0;
}

/* Sidebar */
.sidebar {
  background: var(--card-bg);
  border-right: 1px solid var(--border);
  padding: 20px 16px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.project-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* Desktop/tablet (tudo acima de 480px — ver comentário no breakpoint
   mobile mais abaixo): a sidebar fica travada em 100vh e só as listas de
   projetos/etiquetas rolam internamente, preenchendo o espaço restante da
   coluna. Perfil, atalhos, botões e o cabeçalho "Meus projetos" continuam
   sempre visíveis. Escopo isolado num media query próprio (em vez de
   depender da ordem das regras) pra garantir que nada aqui vaze pro
   drawer mobile de ≤480px, que já resolve seu próprio scroll de forma
   diferente (sidebar inteira rolando como painel de tela cheia). */
@media (min-width: 481px) {
  .sidebar {
    position: sticky;
    top: 0;
    height: 100vh;
    overflow: hidden;
  }

  #projectList,
  #tagList {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
  }
}

.project-item {
  display: flex;
  align-items: center;
  gap: 8px;
  background: none;
  border: none;
  border-radius: var(--radius);
  padding: 8px 10px;
  text-align: left;
  color: var(--text);
  position: relative;
}

.project-item:hover {
  background: var(--bg);
}

.project-item.active {
  background: var(--primary-tint);
  color: var(--primary);
  font-weight: 600;
}

.project-item .dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}

.project-name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.badge {
  background: var(--border);
  color: var(--text-muted);
  font-size: 0.75rem;
  padding: 1px 7px;
  border-radius: 999px;
}

.edit-project {
  display: none;
  font-size: 0.8rem;
}

.project-item:hover .edit-project {
  display: inline;
}

.fav-toggle {
  display: none;
  font-size: 0.8rem;
}

.project-item:hover .fav-toggle,
.fav-toggle.is-favorite {
  display: inline;
}

/* Em touch (celular/tablet) não existe :hover de verdade — sem isso, o
   lápis de editar e a estrela de favoritar ficavam praticamente
   impossíveis de tocar (por isso editar projeto/etiqueta "não funcionava"
   no celular). Em dispositivos com mouse/trackpad, continua só no hover. */
@media (hover: none) {
  .edit-project,
  .fav-toggle {
    display: inline;
  }
}

/* Alça de arrastar-para-reordenar (projetos na sidebar, sessões no modal
   de projeto, cards do Painel, linhas da Lista). touch-action:none fica só
   aqui, numa alça pequena — nunca no container/linha inteira, senão o
   toque de rolar a lista quebraria (mesmo tipo de bug do drawer mobile já
   corrigido, evitado por escopo cirúrgico). Em .project-item some/aparece
   no hover igual fav-toggle/edit-project; em .session-editor-row/.board-
   card/.task-row (não é botão, não tem esse jogo de hover) fica sempre
   visível. .task-drag-handle é uma classe própria (não .drag-handle) só
   pra diferenciar o seletor de alça no enableReorderDrag de cards/linhas
   do seletor de alça de coluna do Painel — como um card fica aninhado
   dentro de uma .board-column, as duas alças precisam de seletores que
   não se sobreponham (ver js/app.js, handleSelector). */
.drag-handle,
.task-drag-handle {
  cursor: grab;
  color: var(--text-muted);
  font-size: 0.9rem;
  flex-shrink: 0;
  touch-action: none;
}

.project-item .drag-handle {
  display: none;
}

.project-item:hover .drag-handle {
  display: inline;
}

@media (hover: none) {
  .project-item .drag-handle {
    display: inline;
  }
}

.dragging {
  opacity: 0.4;
}

.drop-above {
  box-shadow: inset 0 2px 0 0 var(--primary);
}

.drop-below {
  box-shadow: inset 0 -2px 0 0 var(--primary);
}

/* Indicador de soltar pro eixo horizontal (colunas do Painel) — mesma
   ideia de .drop-above/.drop-below, só virado de lado. */
.drop-left {
  box-shadow: inset 2px 0 0 0 var(--primary);
}

.drop-right {
  box-shadow: inset -2px 0 0 0 var(--primary);
}

/* Linha de conta (avatar + nome + engrenagem) e rótulo "Meus projetos":
   mesmo padrão em qualquer tamanho de tela. */
.sidebar-account-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.sidebar-section-label {
  display: block;
  font-size: 0.8rem;
  color: var(--text-muted);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin: 4px 0 0;
}

/* Cabeçalho de seção com um "+" contextual ao lado (ex: Etiquetas) — reduz
   poluição visual movendo a ação de criar da lista de botões do topo da
   sidebar pra perto de onde o item vai efetivamente aparecer. */
.sidebar-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 4px 0 0;
}

.sidebar-section-header .sidebar-section-label {
  margin: 0;
}

.sidebar-section-add-btn {
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: none;
  color: var(--text-muted);
  font-size: 1rem;
  line-height: 1;
  border-radius: 6px;
  padding: 0;
  flex-shrink: 0;
}

.sidebar-section-add-btn:hover {
  background: var(--bg);
  color: var(--text);
}

.sidebar-account-info {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.sidebar-avatar {
  width: 36px;
  height: 36px;
  flex-shrink: 0;
  border-radius: 50%;
  border: none;
  padding: 0;
  background: var(--primary);
  background-size: cover;
  background-position: center;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 0.95rem;
  cursor: pointer;
}

/* Modal "Minha conta": preview grande do avatar com badge de trocar foto */
.account-avatar-edit {
  display: flex;
  justify-content: center;
  margin-bottom: 4px;
}

.account-avatar-preview {
  position: relative;
  width: 84px;
  height: 84px;
  border-radius: 50%;
  border: none;
  padding: 0;
  background: var(--primary);
  background-size: cover;
  background-position: center;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 1.8rem;
  cursor: pointer;
}

.account-avatar-edit-badge {
  position: absolute;
  right: -2px;
  bottom: -2px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--card-bg);
  border: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.9rem;
}

.sidebar-account-name {
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.btn-link {
  border: none;
  background: none;
  color: var(--primary);
  font-weight: 600;
  padding: 0;
  cursor: pointer;
  font-size: 0.85rem;
}

.btn-link:hover {
  text-decoration: underline;
}

/* Autenticação: tela de carregamento de sessão */
.auth-loading {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  background: var(--bg);
  color: var(--text-muted);
  z-index: 250;
}

.auth-loading[hidden] {
  display: none;
}

.auth-loading-spinner {
  width: 32px;
  height: 32px;
  border: 3px solid var(--border);
  border-top-color: var(--primary);
  border-radius: 50%;
  animation: auth-spin 0.8s linear infinite;
}

@keyframes auth-spin {
  to {
    transform: rotate(360deg);
  }
}

/* Autenticação: tela de login/cadastro */
.auth-screen {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--bg) 0%, var(--primary-tint) 100%);
  z-index: 150;
  padding: 20px;
}

.auth-screen[hidden] {
  display: none;
}

.auth-card {
  width: 100%;
  max-width: 860px;
  min-height: 520px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  background: var(--card-bg);
  border-radius: 20px;
  box-shadow: 0 30px 80px -25px rgba(60, 50, 120, 0.35), var(--modal-shadow);
  overflow: hidden;
  animation: auth-card-in 0.5s ease both;
}

@keyframes auth-card-in {
  from {
    opacity: 0;
    transform: translateY(16px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

.auth-panel {
  padding: 40px 36px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.auth-panel-form {
  gap: 4px;
}

.auth-logo {
  width: 56px;
  height: 56px;
  margin-bottom: 16px;
  animation: auth-logo-pop 0.6s ease 0.15s both;
}

@keyframes auth-logo-pop {
  from {
    opacity: 0;
    transform: scale(0.6) rotate(-8deg);
  }
  to {
    opacity: 1;
    transform: scale(1) rotate(0deg);
  }
}

.auth-title {
  margin: 0 0 4px;
  font-size: 1.5rem;
}

.auth-subtitle {
  margin: 0 0 20px;
  color: var(--text-muted);
  font-size: 0.9rem;
}

.auth-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.auth-form label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 0.85rem;
  color: var(--text-muted);
}

.auth-form input[type='email'],
.auth-form input[type='password'] {
  font: inherit;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  background: var(--bg);
}

.auth-error {
  background: var(--danger-tint);
  color: var(--danger);
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 0.85rem;
  margin: 0;
}

.auth-error[hidden] {
  display: none;
}

.auth-error.info {
  background: var(--success-tint);
  color: var(--success);
}

.auth-switch {
  text-align: center;
  font-size: 0.85rem;
  color: var(--text-muted);
  margin: 20px 0 0;
}

/* Painel visual/decorativo ao lado do formulário de login */
.auth-panel-visual {
  position: relative;
  align-items: center;
  text-align: center;
  gap: 18px;
  background: linear-gradient(160deg, var(--primary) 0%, var(--primary-dark) 100%);
  color: #fff;
  overflow: hidden;
}

.auth-blob {
  position: absolute;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  filter: blur(2px);
  animation: auth-blob-float 8s ease-in-out infinite;
}

.auth-blob-1 {
  width: 180px;
  height: 180px;
  top: -60px;
  left: -50px;
}

.auth-blob-2 {
  width: 140px;
  height: 140px;
  bottom: -40px;
  right: -30px;
  animation-delay: -3s;
}

@keyframes auth-blob-float {
  0%,
  100% {
    transform: translate(0, 0) scale(1);
  }
  50% {
    transform: translate(10px, -14px) scale(1.08);
  }
}

.auth-visual-logo {
  width: 140px;
  height: 140px;
  position: relative;
  z-index: 1;
  filter: drop-shadow(0 12px 24px rgba(0, 0, 0, 0.2));
  animation: auth-logo-float 4s ease-in-out infinite;
}

@keyframes auth-logo-float {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-12px);
  }
}

.auth-visual-caption {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 0;
}

.auth-visual-caption strong {
  font-size: 1.15rem;
}

.auth-visual-caption span {
  font-size: 0.9rem;
  opacity: 0.9;
}

@media (max-width: 760px) {
  .auth-card {
    grid-template-columns: 1fr;
    min-height: 0;
  }

  .auth-panel-visual {
    display: none;
  }

  .auth-panel-form {
    padding: 32px 24px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .auth-card,
  .auth-logo,
  .auth-blob,
  .auth-visual-logo {
    animation: none;
  }
}

/* Painel super admin: cards de métricas (compartilhado com admin.css) */
.admin-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
}

.admin-stat-card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
  text-align: center;
}

.admin-stat-value {
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--primary);
}

.admin-stat-label {
  font-size: 0.8rem;
  color: var(--text-muted);
  margin-top: 4px;
}

/* Main */
.main {
  padding: 20px 28px;
  display: flex;
  flex-direction: column;
  gap: 18px;
  min-width: 0;
}

.toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
}

.toolbar-right {
  display: flex;
  align-items: center;
  gap: 12px;
}

.period-tabs,
.view-toggle {
  display: flex;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px;
  gap: 2px;
}

.period-tabs button,
.view-toggle button {
  border: none;
  background: none;
  padding: 6px 14px;
  border-radius: 999px;
  color: var(--text-muted);
  font-size: 0.9rem;
}

.period-tabs button.active,
.view-toggle button.active {
  background: var(--primary);
  color: #fff;
}

.btn-primary,
.btn-secondary,
.btn-danger {
  border: none;
  border-radius: var(--radius);
  padding: 9px 16px;
  font-size: 0.9rem;
}

/* Permite usar essas classes também em <a>, mantendo a aparência de botão */
a.btn-primary,
a.btn-secondary,
a.btn-danger {
  display: inline-block;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}

.btn-primary {
  background: var(--primary);
  color: #fff;
}

.btn-primary:hover {
  background: var(--primary-dark);
}

.btn-secondary {
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
}

/* Toggles "Agrupar por projeto" / "Mostrar concluídas" (toolbar e menu ⋮) */
.toggle-btn.active {
  background: var(--primary-tint);
  color: var(--primary);
  border-color: var(--primary);
}

.btn-danger {
  background: var(--card-bg);
  color: var(--danger);
  border: 1px solid var(--danger);
  margin-right: auto;
}

.btn-block {
  width: 100%;
}

/* Lista */
.list-view {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.list-view[hidden],
.board-view[hidden] {
  display: none;
}

/* Lista agrupada por projeto */
.list-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.list-section + .list-section {
  margin-top: 12px;
}

/* Isola as linhas de CADA sessão dentro de um projeto filtrado — sem este
   wrapper, o gap de 8px de .list-section (acima) ficaria só ENTRE
   título/linhas de sessões diferentes, sem nenhum espaço dedicado dentro
   de uma mesma sessão. Também é o que dá ao drag-and-drop de reordenar
   tarefas (js/app.js, scopeSelector) um container pra distinguir "solto
   dentro da mesma sessão" de "solto numa sessão vizinha". */
.list-session-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.list-section-title {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.task-row {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
}

.task-row.done .task-title {
  text-decoration: line-through;
  color: var(--text-muted);
}

.task-check {
  width: 18px;
  height: 18px;
  accent-color: var(--primary);
  flex-shrink: 0;
}

.task-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.task-title {
  font-weight: 500;
}

/* Prévia da descrição no card/linha (Lista e Painel) — truncada em até 2
   linhas com reticências, estilo Todoist. Só existe quando a tarefa tem
   descrição (ver taskDescriptionPreviewHtml em render.js). */
.task-description-preview {
  font-size: 0.85rem;
  color: var(--text-muted);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

.task-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.tag {
  font-size: 0.75rem;
  background: var(--bg);
  color: var(--text-muted);
  padding: 2px 8px;
  border-radius: 999px;
}

.tag-recurring {
  background: var(--success-tint);
  color: var(--success);
}

.tag-overdue {
  background: var(--danger-tint);
  color: var(--danger);
  font-weight: 600;
}

.empty-state {
  text-align: center;
  color: var(--text-muted);
  padding: 40px 0;
}

/* Menu "⋯" da tarefa (Editar/Data/Excluir), na Lista e no Painel. Mesma
   lógica de posicionamento do .period-menu (menu do rodapé mobile). */
.task-menu-wrap {
  position: relative;
  flex-shrink: 0;
}

.task-menu-btn {
  border: none;
  background: none;
  font-size: 1.1rem;
  line-height: 1;
  padding: 4px 6px;
  border-radius: 6px;
}

.task-menu-btn:hover {
  background: var(--bg);
}

.task-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--modal-shadow), 0 10px 30px -10px rgba(0, 0, 0, 0.25);
  display: flex;
  flex-direction: column;
  min-width: 180px;
  white-space: nowrap;
  z-index: 160;
  overflow: hidden;
}

.task-menu[hidden] {
  display: none;
}

.task-menu button {
  border: none;
  background: none;
  text-align: left;
  padding: 10px 14px;
  color: var(--text);
  font-size: 0.9rem;
  display: block;
  width: 100%;
}

.task-menu button:hover {
  background: var(--bg);
}

.task-menu button.danger {
  color: var(--danger);
}

.task-menu-date-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  font-size: 0.9rem;
  color: var(--text);
  cursor: pointer;
}

.task-menu-date-row:hover {
  background: var(--bg);
}

.task-menu-date-row input[type='date'] {
  flex: 1;
  font: inherit;
  font-size: 0.85rem;
  border: none;
  background: none;
  color: var(--text);
  padding: 0;
}

/* Subtarefas: setinha de expandir/recolher, tag de progresso e o
   checklist que abre dentro da própria Lista/Painel. */
.subtask-toggle-btn {
  border: none;
  background: none;
  color: var(--text-muted);
  font-size: 0.8rem;
  padding: 4px;
  border-radius: 6px;
  flex-shrink: 0;
  cursor: pointer;
}

.subtask-toggle-btn:hover {
  background: var(--bg);
}

.subtask-progress-tag {
  white-space: nowrap;
}

.subtask-panel {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
  padding: 10px 10px 10px 30px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

/* Descrição completa da tarefa, revelada dentro do mesmo painel expansível
   das subtarefas (ver subtaskPanelHtml) — pre-wrap preserva as quebras de
   linha digitadas no textarea do modal. */
.task-description-view {
  white-space: pre-wrap;
  font-size: 0.9rem;
  color: var(--text);
}

.subtask-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.subtask-row.done .subtask-title {
  text-decoration: line-through;
  color: var(--text-muted);
}

.subtask-title {
  flex: 1;
  min-width: 0;
  font-size: 0.9rem;
}

.subtask-delete {
  border: none;
  background: none;
  font-size: 0.85rem;
  padding: 2px 4px;
  border-radius: 6px;
  flex-shrink: 0;
}

.subtask-delete:hover {
  background: var(--card-bg);
}

.subtask-add-form {
  display: flex;
  gap: 8px;
  margin-top: 2px;
}

.subtask-add-form input {
  flex: 1;
  min-width: 0;
  font: inherit;
  font-size: 0.85rem;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--card-bg);
  color: var(--text);
}

/* Lista: o wrap junta a linha da tarefa e o painel de subtarefas para que
   a setinha de expandir/recolher fique associada visualmente aos dois. */
.task-row-wrap {
  display: flex;
  flex-direction: column;
}

/* Painel (colunas por projeto): uma linha só, com rolagem horizontal
   quando não couberem todas as colunas — nunca quebra para baixo.
   touch-action: pan-y deixa a rolagem vertical da página passar normal,
   mas devolve o eixo horizontal pro nosso JS de "arrastar pra rolar"
   (evita rolagem nativa concorrendo com o drag-to-scroll no toque). */
.board-view {
  display: flex;
  flex: 1;
  min-height: 0;
  gap: 16px;
  align-items: start;
  overflow-x: auto;
  padding-bottom: 6px;
  touch-action: pan-y;
  cursor: grab;
  user-select: none;
}

.board-view.dragging {
  cursor: grabbing;
}

.board-column {
  flex: 0 0 320px;
  min-width: 0;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px;
  min-height: 200px;
}

/* Alça de arrastar (⠿) aqui não tem a regra de esconder/mostrar no hover
   que .project-item tem (escopada só a .project-item .drag-handle) —
   coluna do Painel não tem o mesmo conceito de "hover de linha", então
   fica visível sempre, de propósito. */
.board-column h2 {
  font-size: 0.95rem;
  margin: 0 0 12px;
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text-muted);
}

.board-column h2 .count {
  background: var(--bg);
  border-radius: 999px;
  padding: 0 8px;
  font-size: 0.75rem;
}

/* Bolinha colorida numa coluna de sessão, ligando ela visualmente à cor
   do projeto dono (o nome do projeto não repete em cada coluna). */
.board-column h2 .dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}

.board-cards {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-height: 60px;
  min-width: 0;
  border-radius: var(--radius);
}

.board-add-task-btn {
  display: block;
  width: 100%;
  margin-top: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 9px 16px;
  font-size: 0.9rem;
  background: var(--bg);
  color: var(--text);
}

.board-add-task-btn:hover {
  background: var(--border);
}

/* Bolinhas indicadoras do carrossel do Painel — só existem visualmente
   no mobile (ver @media 600px); no desktop ficam escondidas. */
.board-dots {
  display: none;
  justify-content: center;
  gap: 6px;
  padding-top: 4px;
}

.board-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--border);
}

.board-dot.active {
  background: var(--primary);
}

.board-card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.board-card.done .task-title {
  text-decoration: line-through;
  color: var(--text-muted);
}

.board-card-header {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.board-card-header .task-title {
  flex: 1;
  min-width: 0;
  overflow-wrap: break-word;
}

/* Modal */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: var(--overlay-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
}

.modal-overlay[hidden] {
  display: none;
}

.modal {
  background: var(--card-bg);
  border-radius: var(--radius);
  padding: 24px;
  width: 100%;
  max-width: 380px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  box-shadow: var(--modal-shadow);
}

.modal h2 {
  margin: 0;
  font-size: 1.1rem;
}

.modal label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 0.85rem;
  color: var(--text-muted);
}

.modal input[type='text'],
.modal input[type='date'],
.modal select,
.modal textarea {
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
}

.modal textarea {
  resize: vertical;
  min-height: 60px;
}

.description-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: 0.85rem;
  color: var(--text-muted);
  cursor: pointer;
  text-align: left;
}

.description-toggle:hover {
  color: var(--text);
}

.checkbox-row {
  flex-direction: row !important;
  align-items: center;
  gap: 8px !important;
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 6px;
}

/* Editor de subtarefas dentro do modal de tarefa (criar e editar) */
.subtask-editor {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.subtask-editor-label {
  font-size: 0.85rem;
  color: var(--text-muted);
}

.subtask-editor-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.subtask-editor-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.subtask-editor-row.done .subtask-editor-title {
  text-decoration: line-through;
  color: var(--text-muted);
}

.subtask-editor-title {
  flex: 1;
  min-width: 0;
  font-size: 0.9rem;
}

.subtask-editor-row button {
  border: none;
  background: none;
  font-size: 0.85rem;
  padding: 2px 4px;
  border-radius: 6px;
  flex-shrink: 0;
}

.subtask-editor-row button:hover {
  background: var(--bg);
}

.subtask-add-row {
  display: flex;
  gap: 8px;
}

.subtask-add-row input {
  flex: 1;
  min-width: 0;
}

/* Comentários no modal de tarefa — mesmo contêiner de .subtask-editor, mas
   cada item tem duas linhas (data+excluir, depois o texto). */
.comment-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
}

.comment-row:last-child {
  border-bottom: none;
}

.comment-row-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.comment-row-date {
  font-size: 0.78rem;
  color: var(--text-muted);
}

.comment-row-header button {
  border: none;
  background: none;
  font-size: 0.85rem;
  padding: 2px 4px;
  border-radius: 6px;
  flex-shrink: 0;
}

.comment-row-header button:hover {
  background: var(--bg);
}

/* Editor de sessões dentro do modal "Editar projeto" — mesmo molde do
   editor de subtarefas, com o nome já editável direto no campo. */
.session-editor {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.session-editor-label {
  font-size: 0.85rem;
  color: var(--text-muted);
}

.session-editor-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* Modal de projeto: trava a altura total (mesmo problema do modal de
   tarefa antes do redesenho — a lista de sessões existentes cresce sem
   limite e corta os botões fora da viewport). Só a lista de sessões
   (.project-session-list-scroll) rola, com uns 4-5 itens visíveis por
   vez; nome, cor, o form de adicionar sessão nova e a barra de botões
   ficam fixos, sem scroll. Seletor composto (.modal.project-modal) de
   propósito, mesma razão do .modal.task-modal: especificidade real
   sobre o bottom-sheet genérico de ≤480px, independente da ordem no
   arquivo. */
.modal.project-modal {
  max-height: 85vh;
  overflow: hidden;
}

.project-session-list-scroll {
  max-height: 280px;
  overflow-y: auto;
  padding-right: 4px;
}

.session-editor-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.session-editor-name-input {
  flex: 1;
  min-width: 0;
  font: inherit;
  font-size: 0.9rem;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
  color: var(--text);
}

.session-editor-row button {
  border: none;
  background: none;
  font-size: 0.85rem;
  padding: 2px 4px;
  border-radius: 6px;
  flex-shrink: 0;
}

.session-editor-row button:hover {
  background: var(--bg);
}

.session-add-row {
  display: flex;
  gap: 8px;
}

/* Campo de Data de vencimento (modal de tarefa) + botão "x" pra limpar com
   1 clique, sem precisar abrir o date picker nativo e apagar na mão —
   útil tanto quando o campo começa vazio (tarefa nova) quanto quando vem
   pré-preenchido pela coluna de data do Painel ("+ Adicionar tarefa"). */
.due-date-field {
  display: flex;
  gap: 4px;
  align-items: center;
}

.due-date-field input {
  flex: 1;
  min-width: 0;
}

.due-date-clear-btn {
  flex-shrink: 0;
  border: none;
  background: none;
  color: var(--text-muted);
  font-size: 0.85rem;
  padding: 4px 6px;
  border-radius: 6px;
  cursor: pointer;
}

.due-date-clear-btn:hover {
  background: var(--bg);
}

.session-add-row input,
.session-add-row select,
.session-add-row label {
  flex: 1;
  min-width: 0;
}

/* Seletor de dias da semana da recorrência personalizada (modal de tarefa) */
.weekday-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.weekday-picker label {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 0.85rem;
}

/* Modal de tarefa: layout de duas colunas (estilo Todoist). Seletor
   composto (.modal.task-modal) de propósito — .task-modal sozinha teria a
   MESMA especificidade que .modal sozinha, e quem venceria seria só a
   ordem no arquivo; o composto garante vitória real sobre a regra
   genérica do bottom-sheet de ≤480px em qualquer ordem. */
.modal.task-modal {
  max-width: 860px;
  width: 90vw;
  max-height: 85vh;
  padding: 0;
  overflow: hidden; /* só .task-modal-body rola */
}

.modal.task-modal > h2 {
  padding: 24px 24px 0;
}

.task-modal-body {
  flex: 1 1 auto;
  min-height: 0; /* essencial pro overflow-y funcionar dentro do flex column do .modal */
  overflow-y: auto;
  display: grid;
  grid-template-columns: minmax(480px, 1fr) 280px;
  grid-template-areas: 'a b' 'c b';
  gap: 20px 24px;
  align-content: start;
  padding: 20px 24px;
}

.task-modal-area-a {
  grid-area: a;
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
}

.task-modal-area-b {
  grid-area: b;
  display: flex;
  flex-direction: column;
  gap: 14px;
  background: var(--bg);
  border-radius: var(--radius);
  padding: 16px;
}

.task-modal-area-c {
  grid-area: c;
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
}

/* Data de vencimento + Horário lado a lado ficam apertados em 280px —
   empilha só essa linha (não a nested dentro de #taskRepeatCustom). */
.task-modal-area-b > .session-add-row {
  flex-direction: column;
}

.modal.task-modal > .modal-actions {
  flex-shrink: 0;
  padding: 16px 24px 20px;
  margin-top: 0;
  border-top: 1px solid var(--border);
}

.modal-overlay.task-modal-overlay {
  align-items: center;
}

/* Intermediário: janela centralizada, 1 coluna — evita a faixa ~721-940px
   onde as duas colunas de fato não caberiam (minmax(480px,1fr) + 280px +
   gaps exige ~836px de conteúdo mínimo). */
@media (max-width: 940px) {
  .modal.task-modal {
    max-width: 600px;
    width: 90vw;
    max-height: 85vh;
  }
  .task-modal-body {
    grid-template-columns: 1fr;
    grid-template-areas: 'a' 'b' 'c';
  }
}

/* Mobile: tela cheia. */
@media (max-width: 720px) {
  .modal.task-modal {
    width: 100vw;
    height: 100dvh;
    max-width: none;
    max-height: none;
    border-radius: 0;
  }
}

/* Modal de preview do import do Todoist — mais largo que o padrão (380px)
   pra caber a árvore de seções/tarefas/subtarefas sem quebrar demais, e
   com altura travada (mesmo princípio já usado nos modais de tarefa e
   projeto): só .import-preview-body rola, cabeçalho/nome do projeto e a
   barra de botões ficam sempre visíveis. Seletor composto
   (.modal.modal-wide) de propósito — .modal-wide sozinha teria a MESMA
   especificidade do .modal genérico do bottom-sheet de ≤480px. */
.modal.modal-wide {
  width: 90vw;
  max-width: 900px;
  max-height: 85vh;
  overflow: hidden;
}

.import-preview-body {
  flex: 1 1 auto;
  min-height: 0; /* essencial pro overflow-y funcionar dentro do flex column do .modal */
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.import-warnings {
  background: var(--warning-tint);
  color: var(--warning);
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 0.85rem;
}

.import-warnings[hidden] {
  display: none;
}

.import-warnings ul {
  margin: 4px 0 0;
  padding-left: 18px;
}

.import-tree {
  /* Sem max-height/overflow próprio de propósito — o scroll agora é do
     wrapper .import-preview-body, pra não ter duas barras de rolagem
     aninhadas (uma pros avisos+árvore+etiquetas juntos). */
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.9rem;
}

.import-tree-section {
  font-weight: 600;
  margin-top: 8px;
}

.import-tree-section:first-child {
  margin-top: 0;
}

.import-tree-task {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  padding: 2px 0;
}

.import-tree-task.import-tree-subtask {
  padding-left: 20px;
  color: var(--text-muted);
}

.import-tree-task-meta {
  flex-shrink: 0;
  color: var(--text-muted);
  font-size: 0.8rem;
}

.import-tags-section {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

.import-tags-section[hidden] {
  display: none;
}

.import-tags-heading {
  font-weight: 600;
  font-size: 0.9rem;
}

/* #tasksScreen reproduz o layout que .main tinha antes de virar um wrapper
   com dois filhos (tasksScreen/campaignsView) — só um dos dois é visível
   por vez, alternado por state.ui.screen. */
#tasksScreen {
  display: flex;
  flex-direction: column;
  gap: 18px;
  min-width: 0;
}

.campaigns-view {
  display: flex;
  flex-direction: column;
  gap: 18px;
  min-width: 0;
}

.campaigns-view[hidden] {
  display: none;
}

.campaigns-view-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.campaigns-view-header h2 {
  margin: 0;
  font-size: 1.4rem;
}

.campaigns-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.campaign-row {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.campaign-row-name {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
}

.campaign-row-meta {
  color: var(--text-muted);
  font-size: 0.85rem;
}

.campaign-status-badge {
  font-size: 0.75rem;
  padding: 1px 8px;
  border-radius: 999px;
  font-weight: 500;
  background: var(--border);
  color: var(--text-muted);
}

.campaign-status-ativa {
  background: var(--success-tint);
  color: var(--success);
}

.campaign-status-encerrada {
  background: var(--border);
  color: var(--text-muted);
}

/* Seletor composto (.modal.modal-wide) já garante a mesma vitória de
   especificidade usada pelo import do Todoist — reaproveitado aqui. */
.campaign-create-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  display: grid;
  grid-template-columns: minmax(260px, 360px) 1fr;
  gap: 20px;
}

.campaign-create-fields {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.campaign-create-fields textarea {
  min-height: 60px;
  resize: vertical;
}

.campaign-create-preview {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.campaign-import-filename {
  color: var(--text-muted);
  font-size: 0.85rem;
}

.campaign-import-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}

.campaign-import-table[hidden] {
  display: none;
}

.campaign-import-table th,
.campaign-import-table td {
  text-align: left;
  padding: 6px 8px;
  border-bottom: 1px solid var(--border);
}

@media (max-width: 940px) {
  .campaign-create-body {
    grid-template-columns: 1fr;
  }
}

.campaigns-view-header-actions {
  display: flex;
  align-items: center;
  gap: 14px;
}

.campaigns-show-ended-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.85rem;
  color: var(--text-muted);
  cursor: pointer;
}

.campaign-row {
  cursor: pointer;
}

.campaign-row:hover {
  border-color: var(--primary);
}

/* Tela de detalhe da campanha — conteúdo normal de fluxo (sem
   position:fixed/z-index), igual .campaigns-view, pra não conflitar com o
   drawer mobile (.sidebar.mobile-open, z-index 130) nem o bottom nav
   (z-index 140). */
.campaign-detail-view {
  display: flex;
  flex-direction: column;
  gap: 18px;
  min-width: 0;
}

.campaign-detail-view[hidden] {
  display: none;
}

/* Tela "Minhas estatísticas" — mesmo padrão de fluxo normal das telas
   acima (sem position:fixed/z-index). */
.stats-view {
  display: flex;
  flex-direction: column;
  gap: 18px;
  min-width: 0;
}

.stats-view[hidden] {
  display: none;
}

.stats-view-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.stats-view-header h2 {
  margin: 0;
  font-size: 1.4rem;
}

#statsBody {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.stats-karma-card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  display: flex;
  align-items: center;
  gap: 16px;
}

.stats-karma-emoji {
  font-size: 2.4rem;
  line-height: 1;
}

.stats-karma-info {
  flex: 1;
  min-width: 0;
}

.stats-karma-level {
  font-weight: 700;
  font-size: 1.1rem;
}

.stats-karma-total {
  color: var(--text-muted);
  font-size: 0.85rem;
  margin: 4px 0 8px;
}

.stats-karma-progress {
  height: 8px;
  border-radius: 999px;
  background: var(--border);
  overflow: hidden;
}

.stats-karma-progress-fill {
  height: 100%;
  background: var(--primary);
  border-radius: 999px;
}

.stats-charts-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 18px;
}

/* Altura fixa no card (não no <canvas> diretamente) + flex com min-height:0
   no filho: é o jeito confiável de dar altura fixa/largura fluida pro
   Chart.js com responsive:true — deixar o canvas "adivinhar" a própria
   altura (ou forçar height nele via CSS) briga com o resize interno da
   biblioteca. */
.stats-chart-card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
  min-width: 0;
  height: 280px;
  display: flex;
  flex-direction: column;
}

.stats-chart-card h3 {
  margin: 0 0 10px;
  font-size: 0.95rem;
  color: var(--text-muted);
  flex: none;
}

.stats-chart-card canvas {
  flex: 1;
  min-height: 0;
  width: 100%;
}

@media (max-width: 900px) {
  .stats-charts-grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 480px) {
  .stats-chart-card {
    height: 220px;
  }
}

.campaign-detail-header {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
}

.campaign-detail-name {
  margin: 0;
  font-size: 1.3rem;
}

.campaign-detail-header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

.campaign-detail-header-actions .btn-danger {
  margin-right: 0;
}

.campaign-alert-days-field {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.85rem;
  color: var(--text-muted);
}

.campaign-alert-days-field input {
  width: 60px;
}

.campaign-detail-metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 10px;
}

.campaign-metric-tile {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.campaign-metric-value {
  font-size: 1.3rem;
  font-weight: 700;
}

.campaign-metric-label {
  font-size: 0.8rem;
  color: var(--text-muted);
}

.campaign-outcome-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
}

.campaign-outcome-header h3 {
  margin: 0;
  font-size: 0.95rem;
}

.renewal-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  font-size: 0.75rem;
  color: var(--text-muted);
}

.renewal-undo {
  margin-left: 4px;
  font-size: 0.85rem;
}

.campaign-detail-project {
  margin: 0;
  color: var(--text-muted);
  font-size: 0.85rem;
}

.campaign-detail-messages {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px;
}

.campaign-detail-message {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.campaign-detail-message label {
  font-size: 0.8rem;
  color: var(--text-muted);
}

.campaign-detail-message textarea {
  min-height: 70px;
  resize: vertical;
}

.campaign-clients-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.campaign-detail-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.campaign-detail-filter button {
  border: 1px solid var(--border);
  background: var(--card-bg);
  color: var(--text);
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 0.85rem;
  cursor: pointer;
}

.campaign-detail-filter button.active {
  background: var(--primary-tint);
  color: var(--primary);
  border-color: var(--primary);
}

.campaign-client-search {
  flex: 1 1 200px;
  max-width: 280px;
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--card-bg);
  color: var(--text);
  font-size: 0.85rem;
}

/* Único container de scroll da tabela (nunca aninhar dois) — mesma
   filosofia do .board-view: scroll horizontal deliberado, sem esconder
   coluna, funciona igual em qualquer largura. */
.campaign-clients-table-wrap {
  overflow-x: auto;
}

.campaign-clients-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

.campaign-clients-table th,
.campaign-clients-table td {
  text-align: left;
  padding: 6px 8px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.campaign-clients-table textarea {
  min-height: 32px;
  min-width: 140px;
  resize: vertical;
  white-space: normal;
}

.campaign-clients-table input[type='number'] {
  width: 90px;
}

/* Tela "Vouchers" — bloco modelado 1:1 em cima do de Campanhas acima
   (mesmo formato lista + detalhe), com prefixo próprio: o código não tem
   classes de componente genéricas reaproveitáveis entre features, cada
   tela de "lista + detalhe" já duplica o próprio CSS (ver .campaigns-view
   acima), então segue o mesmo padrão em vez de introduzir uma abstração
   nova. .modal-wide/.import-warnings/.campaign-import-table/
   .campaign-import-filename continuam reaproveitados (já são genéricos,
   usados também pelo import do Todoist).*/
.voucher-batches-view {
  display: flex;
  flex-direction: column;
  gap: 18px;
  min-width: 0;
}

.voucher-batches-view[hidden] {
  display: none;
}

.voucher-batches-view-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.voucher-batches-view-header h2 {
  margin: 0;
  font-size: 1.4rem;
}

.voucher-batches-view-header-actions {
  display: flex;
  align-items: center;
  gap: 14px;
}

.voucher-batches-show-ended-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.85rem;
  color: var(--text-muted);
  cursor: pointer;
}

.voucher-batches-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.voucher-batch-row {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  cursor: pointer;
}

.voucher-batch-row:hover {
  border-color: var(--primary);
}

.voucher-batch-row-name {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
}

.voucher-batch-row-meta {
  color: var(--text-muted);
  font-size: 0.85rem;
}

.voucher-batch-row-progress {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 2px;
}

.voucher-batch-progress-bar {
  flex: 1 1 auto;
  height: 6px;
  border-radius: 999px;
  background: var(--border);
  overflow: hidden;
}

.voucher-batch-progress-fill {
  height: 100%;
  background: var(--primary);
  border-radius: 999px;
}

.voucher-batch-progress-remaining {
  flex-shrink: 0;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--primary);
}

.voucher-batch-status-badge {
  font-size: 0.75rem;
  padding: 1px 8px;
  border-radius: 999px;
  font-weight: 500;
  background: var(--border);
  color: var(--text-muted);
}

.voucher-batch-status-ativo {
  background: var(--success-tint);
  color: var(--success);
}

.voucher-batch-status-encerrado {
  background: var(--border);
  color: var(--text-muted);
}

.voucher-batch-create-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  display: grid;
  grid-template-columns: minmax(260px, 360px) 1fr;
  gap: 20px;
}

.voucher-batch-create-fields {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.voucher-batch-create-fields textarea {
  min-height: 60px;
  resize: vertical;
}

.voucher-batch-create-preview {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

@media (max-width: 940px) {
  .voucher-batch-create-body {
    grid-template-columns: 1fr;
  }
}

/* Mesmo motivo de .campaign-detail-view: conteúdo normal de fluxo (sem
   position:fixed/z-index), pra não conflitar com o drawer mobile nem o
   bottom nav. */
.voucher-batch-detail-view {
  display: flex;
  flex-direction: column;
  gap: 18px;
  min-width: 0;
}

.voucher-batch-detail-view[hidden] {
  display: none;
}

.voucher-batch-detail-header {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
}

.voucher-batch-detail-name {
  margin: 0;
  font-size: 1.3rem;
}

.voucher-batch-detail-header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

.voucher-batch-detail-header-actions .btn-danger {
  margin-right: 0;
}

.voucher-batch-detail-metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 10px;
}

.voucher-batch-metric-tile {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.voucher-batch-metric-value {
  font-size: 1.3rem;
  font-weight: 700;
}

.voucher-batch-metric-label {
  font-size: 0.8rem;
  color: var(--text-muted);
}

.voucher-batch-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

/* Mesmo formato de .campaign-client-search — campo de busca genérico das
   telas de detalhe "lista + toolbar + tabela". */
.voucher-code-search {
  flex: 1 1 200px;
  max-width: 280px;
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--card-bg);
  color: var(--text);
  font-size: 0.85rem;
}

.voucher-batch-detail-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.voucher-batch-detail-filter button {
  border: 1px solid var(--border);
  background: var(--card-bg);
  color: var(--text);
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 0.85rem;
  cursor: pointer;
}

.voucher-batch-detail-filter button.active {
  background: var(--primary-tint);
  color: var(--primary);
  border-color: var(--primary);
}

/* Único container de scroll da tabela (nunca aninhar dois) — mesma
   filosofia de .campaign-clients-table-wrap. */
.voucher-batch-table-wrap {
  overflow-x: auto;
}

.voucher-batch-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

.voucher-batch-table th,
.voucher-batch-table td {
  text-align: left;
  padding: 6px 8px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.voucher-batch-table input[type='number'] {
  width: 100px;
}

.voucher-batch-table input[type='text'] {
  min-width: 140px;
}

.import-tags-label {
  font-size: 0.8rem;
  color: var(--text-muted);
  margin: 4px 0 0;
}

.import-tag-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.import-tag-name {
  font-size: 0.85rem;
  flex-shrink: 0;
}

.import-tag-select {
  flex: 1;
  max-width: 220px;
  font: inherit;
  font-size: 0.85rem;
  padding: 4px 6px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
  color: var(--text);
}

.api-token-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.api-token-info small {
  color: var(--text-muted);
  font-size: 0.75rem;
}

/* Sub-cabeçalho de sessão dentro de uma seção de projeto na Lista */
.list-session-title {
  margin: 4px 0 0;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-muted);
}

/* Etiquetas dentro do modal de tarefa: chips das já vinculadas + menu de
   sugestão "@" ancorado embaixo do campo de título inteiro. */
.task-title-label {
  position: relative;
}

.tag-editor {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.tag-editor-label {
  font-size: 0.85rem;
  color: var(--text-muted);
}

.tag-editor-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 0.8rem;
  padding: 3px 6px 3px 10px;
  border-radius: 999px;
}

.tag-chip button {
  border: none;
  background: none;
  color: inherit;
  font-size: 1rem;
  line-height: 1;
  padding: 0 2px;
}

.tag-suggest-menu {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  margin-top: 4px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--modal-shadow), 0 10px 30px -10px rgba(0, 0, 0, 0.25);
  display: flex;
  flex-direction: column;
  max-height: 200px;
  overflow-y: auto;
  z-index: 160;
}

.tag-suggest-menu[hidden] {
  display: none;
}

.tag-suggest-menu button {
  display: flex;
  align-items: center;
  gap: 8px;
  border: none;
  background: none;
  text-align: left;
  padding: 8px 12px;
  color: var(--text);
  font-size: 0.9rem;
}

.tag-suggest-menu button:hover {
  background: var(--bg);
}

.tag-suggest-menu .dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}

/* Chip de sugestão de data/recorrência (App.nlDate) abaixo do título, e a
   nota que aparece na área de repetição quando a regra sugerida não cabe
   nos campos granulares (byMonthDay/byNthWeekday). */
.nldate-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  align-self: flex-start;
  font-size: 0.8rem;
  padding: 4px 6px 4px 10px;
  border-radius: 999px;
  background: var(--primary-tint);
  color: var(--primary);
}

.nldate-chip[hidden] {
  display: none;
}

.nldate-chip.nldate-chip-warning {
  background: var(--warning-tint);
  color: var(--warning);
}

.nldate-chip-dismiss {
  border: none;
  background: none;
  color: inherit;
  font-size: 1rem;
  line-height: 1;
  padding: 0 2px;
}

.nldate-repeat-note {
  font-size: 0.8rem;
  color: var(--primary);
  background: var(--primary-tint);
  padding: 6px 10px;
  border-radius: 8px;
  margin: -6px 0 0;
}

.nldate-repeat-note[hidden] {
  display: none;
}

/* Busca: barra com campo de texto, tanto no ícone de lupa do desktop
   quanto na aba "Buscar" do rodapé mobile. */
.search-bar {
  display: flex;
  align-items: center;
  gap: 8px;
}

.search-bar input {
  flex: 1;
  font: inherit;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--card-bg);
  color: var(--text);
}

.search-bar[hidden] {
  display: none;
}

/* Navegação mobile (rodapé, cabeçalho compacto): escondida por padrão,
   só aparece em telas de celular (ver @media 600px). */
.mobile-title-bar,
.mobile-bottom-nav {
  display: none;
}

.mobile-title-text h2 {
  margin: 0;
  font-size: 1.3rem;
}

/* Título do projeto/período atual no canto superior esquerdo do conteúdo
   (desktop/tablet) — some no modo celular, onde o .mobile-title-bar
   assume esse mesmo papel. */
.page-title {
  margin: 0 0 4px;
  font-size: 1.4rem;
}

.mobile-task-count {
  font-size: 0.85rem;
  color: var(--text-muted);
}

.mobile-title-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.mobile-icon-btn {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--card-bg);
  color: var(--text);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
}

.period-menu-wrap {
  position: relative;
}

.period-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--modal-shadow), 0 10px 30px -10px rgba(0, 0, 0, 0.25);
  display: flex;
  flex-direction: column;
  min-width: 180px;
  white-space: nowrap;
  z-index: 160;
  overflow: hidden;
}

.period-menu[hidden] {
  display: none;
}

.period-menu button,
.period-menu a {
  border: none;
  background: none;
  text-align: left;
  padding: 10px 14px;
  color: var(--text);
  font-size: 0.9rem;
  text-decoration: none;
  display: block;
}

.period-menu button:hover,
.period-menu a:hover {
  background: var(--bg);
}

.mobile-nav-btn {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  border: none;
  background: none;
  color: var(--text-muted);
  font-size: 0.7rem;
  padding: 6px 2px;
  border-radius: 10px;
}

.mobile-nav-btn span:first-child {
  font-size: 1.15rem;
}

.mobile-nav-btn.active {
  color: var(--primary);
}

/* Responsivo: tablets */
@media (max-width: 900px) {
  .task-menu-btn,
  .edit-project {
    min-width: 40px;
    min-height: 40px;
  }

  .task-menu-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}

/* Responsivo: celulares. Só essa faixa (bem estreita, cobre até os
   maiores celulares em pé) vira layout "de celular" — barra lateral em
   tela cheia, menu inferior, carrossel do Painel. Qualquer coisa acima
   disso (incluindo tablets em pé) usa sempre o grid de desktop (barra
   lateral fixa ao lado do conteúdo, nunca empilhada). Antes disso aqui
   existiam dois breakpoints (760px e 600px) que deixavam a faixa
   581-760px num meio-termo estranho (sidebar empilhada por cima do
   conteúdo) — unificado num só valor mais baixo. */
@media (max-width: 480px) {
  .app {
    grid-template-columns: 1fr;
  }

  .main {
    padding: 14px 16px calc(132px + env(safe-area-inset-bottom, 0px));
  }

  .page-title {
    display: none;
  }

  .task-row {
    flex-wrap: wrap;
  }

  .task-menu-wrap {
    margin-left: auto;
  }

  /* Painel em modo carrossel: uma coluna por vez, ocupando a tela toda.
     O encaixe (snap) é feito só pelo JS (enableDragScroll/onDragEnd em
     app.js) — usar também o scroll-snap do CSS aqui fazia os dois
     mecanismos brigarem pelo controle do scrollLeft ao mesmo tempo,
     deixando a rolagem travada/instável. */
  .board-view {
    gap: 0;
  }

  .board-column {
    flex: 0 0 100%;
  }

  .board-dots {
    display: flex;
  }

  .modal-overlay {
    align-items: flex-end;
  }

  .modal {
    max-width: calc(100% - 32px);
    max-height: calc(100vh - 32px);
    overflow-y: auto;
    padding: 18px;
  }

  /* Esconde os controles de desktop (period-tabs, view-toggle, botão de
     recolher sidebar, lupa de busca — a busca no mobile já tem seu
     próprio caminho pela aba "Buscar" do rodapé); #newTaskBtn (fixo,
     vira FAB) e o container do toolbar continuam no DOM normalmente,
     só ficam vazios/invisíveis visualmente. */
  #periodTabs,
  #viewToggle,
  #groupByProjectToggleBtn,
  #showCompletedToggleBtn,
  #searchToggleBtn,
  #desktopSearchBar,
  .sidebar-toggle-btn {
    display: none;
  }

  .toolbar {
    margin: 0;
  }

  #newTaskBtn {
    position: fixed;
    left: auto;
    right: 16px;
    bottom: calc(64px + env(safe-area-inset-bottom, 0px));
    z-index: 140;
    width: 56px;
    height: 56px;
    padding: 0;
    border-radius: 50%;
    font-size: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 10px 24px -8px rgba(0, 0, 0, 0.35);
  }

  #newTaskBtn::after {
    content: '+';
    font-size: 1.8rem;
    line-height: 1;
    color: #fff;
  }

  .mobile-title-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
  }

  /* Sidebar vira o painel "Navegar": uma aba de tela cheia (não um modal),
     escondida por padrão e mostrada só com a classe .mobile-open. O rodapé
     de navegação e o FAB continuam visíveis por cima (ver z-index deles). */
  .sidebar {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 130;
    max-height: none;
    overflow-y: auto;
    border: none;
    padding: 16px 16px calc(96px + env(safe-area-inset-bottom, 0px));
  }

  .sidebar.mobile-open {
    display: flex;
  }

  .mobile-bottom-nav {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 140;
    background: var(--card-bg);
    border-top: 1px solid var(--border);
    padding: 6px 4px calc(6px + env(safe-area-inset-bottom, 0px));
  }
}

/* ---------------------------------------------------------------------
   Seleção múltipla de tarefas (modo seleção + lote Concluir/Agendar).
   Tudo depende de body.selection-mode: fora do modo nada muda.
   --------------------------------------------------------------------- */
.task-select-check {
  display: none;
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  margin: 0;
  accent-color: var(--primary);
  pointer-events: none; /* decorativo: quem alterna a seleção é o clique no card */
}

body.selection-mode .task-select-check {
  display: inline-block;
}

/* Checkbox de CONCLUIR fica inerte no modo (nunca dois significados pro clique) */
body.selection-mode .task-check {
  visibility: hidden;
  pointer-events: none;
}

/* Controles que não fazem sentido em seleção: somem */
body.selection-mode .task-drag-handle,
body.selection-mode .task-menu-wrap,
body.selection-mode .subtask-toggle-btn,
body.selection-mode .subtask-panel,
body.selection-mode .board-add-task-btn {
  display: none;
}

body.selection-mode .task-row,
body.selection-mode .board-card {
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

.task-row.selected,
.board-card.selected {
  box-shadow: inset 0 0 0 2px var(--primary);
  background: var(--primary-tint);
}

/* "Selecionar todas" de um grupo: escondido fora do modo */
.group-select {
  display: none;
  align-items: center;
  gap: 6px;
  margin-left: auto;
  font-size: 0.8rem;
  font-weight: 500;
  cursor: pointer;
  color: var(--text-muted);
}

body.selection-mode .group-select {
  display: inline-flex;
}

.group-select-check {
  width: 16px;
  height: 16px;
  margin: 0;
  accent-color: var(--primary);
}

body.selection-mode .group-select-bar {
  margin-bottom: 8px;
}

/* Barra de ações no rodapé */
.selection-bar {
  position: fixed;
  left: 50%;
  bottom: 16px;
  transform: translateX(-50%);
  z-index: 145; /* acima da nav mobile e do FAB (140), abaixo dos modais (200) */
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  justify-content: center;
  max-width: calc(100vw - 32px);
  padding: 10px 14px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
}

.selection-bar[hidden] {
  display: none;
}

.selection-count {
  font-weight: 600;
}

.selection-actions {
  display: flex;
  gap: 8px;
}

.batch-schedule-preview {
  font-size: 0.85rem;
  color: var(--text-muted);
}

/* Toast de resultado de lote (topo, para não brigar com a barra de ações) */
.toast {
  position: fixed;
  top: 16px;
  left: 50%;
  z-index: 220;
  max-width: calc(100vw - 32px);
  padding: 10px 16px;
  background: var(--text);
  color: var(--card-bg);
  border-radius: var(--radius);
  font-size: 0.9rem;
  text-align: center;
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, -12px);
  transition: opacity 0.2s, transform 0.2s;
}

.toast.show {
  opacity: 1;
  transform: translate(-50%, 0);
}

@media (max-width: 480px) {
  #selectModeToggleBtn {
    display: none;
  }

  /* No modo, o FAB "+ Nova tarefa" sai pra não competir com a barra */
  body.selection-mode #newTaskBtn {
    display: none;
  }

  /* Acima da bottom nav (≈ 60px + safe-area). Medir no aparelho se mudar a nav. */
  .selection-bar {
    bottom: calc(72px + env(safe-area-inset-bottom, 0px));
    width: calc(100vw - 24px);
    justify-content: space-between;
  }

  /* Espaço extra pra última linha não ficar atrás da barra */
  body.selection-mode .main {
    padding-bottom: calc(180px + env(safe-area-inset-bottom, 0px));
  }
}
