/* CSS custom — sobrescritas pontuais sobre o Tailwind. */

/* Tokens da marca. Fonte da verdade: /design-system. */
:root {
  /* Paleta do Beat — a marca é #8B7CF6, do Nocturne (app/src/theme.ts).
     A escala mantém os mesmos degraus de luminosidade da escala original do boilerplate,
     só girando a matiz: assim todo componente que já usava --brand-N continua
     com o mesmo contraste relativo, sem revisar um por um. */
  /* Escala tonal do roxo. 500 é a cor da marca; 300/400 são as versões
     legíveis sobre fundo escuro (o 500 puro não passa 4.5:1 no dark). */
  --brand-50:  #f0eefb;
  --brand-100: #d9d5f6;
  --brand-200: #aaa0f8;
  --brand-300: #8070f5;
  --brand-400: #5e4af3;
  --brand-500: #8B7CF6;
  --brand-600: #4128f0;
  --brand-700: #260ed2;
  --brand-800: #1e0ba2;
  --brand-900: #160877;

  --color-brand: var(--brand-500);
  --brand-magenta: #5FE3B0;
  /* Gradiente da assinatura — mesmo do símbolo no logo.svg. */
  --brand-gradient: linear-gradient(135deg, #8B7CF6 0%, #5FE3B0 100%);

  /* Superfícies e texto do produto (tema claro). */
  --surface-app: #f7f7f7;
  --surface-card: #ffffff;
  --text-primary: rgb(0 0 0 / 0.87);
  --text-secondary: #60646c;

  /* Superfícies do tema escuro (usadas na página de marca). */
  --ink-900: #0b0a0f;
  --ink-800: #141219;
  --ink-700: #1c1a23;
  --ink-600: #2a2733;
}

/* Campo com label sobreposta à borda (padrão dos formulários do produto).
   A label "corta" a borda usando o fundo do container — quem define a cor é
   --field-bg, para o mesmo componente servir em painel claro ou creme. */
.field-control {
  position: relative;
}
.field-control > label {
  position: absolute;
  top: -0.55rem;
  left: 0.75rem;
  padding: 0 0.375rem;
  background: var(--field-bg, #fff);
  font-size: 0.875rem;
  line-height: 1;
  color: #8217b1;
}
.field input,
.field select,
.field textarea {
  width: 100%;
  min-height: 3.25rem;
  border: 1px solid #d0cfcf;
  border-radius: 0.25rem;
  background: transparent;
  padding: 0.875rem 1rem;
  font-size: 0.9375rem;
  color: var(--text-primary);
}
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--brand-500);
  box-shadow: 0 0 0 3px rgb(129 38 253 / 0.18);
}
.field input::placeholder { color: #8d8d8d; }
.field--error input { border-color: #dc2626; }
.field--error label { color: #dc2626; }
/* Roxo escuro some no fundo escuro — no dark o label flutuante clareia p/ brand-300. */
.dark .field-control > label { color: var(--brand-300); }

/* Campo das telas de entrada, sobre o fundo ink do shell público.

   Não é o `.field` do painel: aquele nasceu com label flutuante cortando a
   borda, que só funciona quando o fundo do campo é o mesmo do container — regra
   que o tema escuro e o card quebravam a cada mudança. Aqui o rótulo fica acima
   do campo, em markup comum, e o input é uma superfície translúcida sobre o
   card. O botão vem de components/button.html (variant gradient). */
.auth-input {
  width: 100%;
  min-height: 3.125rem;
  border: 1px solid rgb(255 255 255 / 0.10);
  border-radius: 0.75rem;
  background: rgb(255 255 255 / 0.04);
  padding: 0.875rem 1rem;
  font-size: 0.9375rem;
  color: #fff;
  transition: border-color .18s, box-shadow .18s, background-color .18s;
}
.auth-input::placeholder { color: rgb(255 255 255 / 0.28); }
.auth-input:hover { border-color: rgb(255 255 255 / 0.18); }
.auth-input:focus {
  outline: none;
  background: rgb(255 255 255 / 0.06);
  border-color: var(--brand-400);
  box-shadow: 0 0 0 4px rgb(129 38 253 / 0.22);
}
.auth-error .auth-input { border-color: #f87171; }
.auth-error .auth-input:focus { box-shadow: 0 0 0 4px rgb(248 113 113 / 0.20); }

/* Autofill do Chrome pinta o campo de azul-claro e apaga o desenho inteiro do
   formulário. O inset repõe a superfície do card sem tirar o preenchimento. */
.auth-input:-webkit-autofill,
.auth-input:-webkit-autofill:hover,
.auth-input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 100px var(--ink-800) inset;
  -webkit-text-fill-color: #fff;
  caret-color: #fff;
}

/* Item do roteiro de playbook — controles com label flutuante consistentes.
   O label corta a borda usando o fundo do card (branco / ink-800). */
.pb-item { --field-bg: #fff; }
.dark .pb-item { --field-bg: var(--ink-800); }
.pb-ctl { position: relative; }
.pb-ctl > label {
  position: absolute;
  top: -0.5rem;
  left: 0.55rem;
  padding: 0 0.35rem;
  background: var(--field-bg, #fff);
  font-size: 0.7rem;
  font-weight: 700;
  line-height: 1;
  color: #8217b1;
  pointer-events: none;
}
.dark .pb-ctl > label { color: var(--brand-300); }
.pb-ctl > .ctl {
  width: 100%;
  min-height: 2.75rem;
  border: 1px solid #d8d8de;
  border-radius: 0.5rem;
  background: transparent;
  padding: 0.5rem 0.7rem;
  font-size: 0.875rem;
  color: var(--text-primary);
}
.pb-ctl > textarea.ctl { resize: vertical; }
.pb-ctl > .ctl:focus {
  outline: none;
  border-color: var(--brand-500);
  box-shadow: 0 0 0 3px rgb(129 38 253 / 0.18);
}
.dark .pb-ctl > .ctl { border-color: rgb(255 255 255 / 0.12); color: #e5e7eb; }
.pb-ctl > .ctl[readonly] { background: #f7f7f7; }
.dark .pb-ctl > .ctl[readonly] { background: rgb(255 255 255 / 0.05); }

.brand-gradient-text {
  background: var(--brand-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Controles de formulário do painel (CRUDs). Estiliza os widgets padrão do
   Django dentro de um wrapper .ds-form — sem depender de classe por campo. */
.ds-form input:not([type="checkbox"]):not([type="radio"]),
.ds-form select,
.ds-form textarea {
  width: 100%;
  border: 1px solid #d8d8de;
  border-radius: 0.5rem;
  background: #fff;
  padding: 0.625rem 0.875rem;
  font-size: 0.875rem;
  color: var(--text-primary);
}
/* O JS do `field.html` ajusta a altura ao conteúdo; `resize: vertical` continua
   valendo para quem quiser esticar mais, e volta a acompanhar ao digitar. */
.ds-form textarea { resize: vertical; }
.ds-form input:focus,
.ds-form select:focus,
.ds-form textarea:focus {
  outline: none;
  border-color: var(--brand-500);
  box-shadow: 0 0 0 3px rgb(129 38 253 / 0.18);
}
.ds-form input::placeholder,
.ds-form textarea::placeholder { color: #9a9aa4; }
.ds-form .has-error input,
.ds-form .has-error select,
.ds-form .has-error textarea { border-color: #dc2626; }
/* Checkboxes de grupos (CheckboxSelectMultiple) e flags. */
.ds-form ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.375rem; }
.ds-form input[type="checkbox"],
.ds-form input[type="radio"] { accent-color: var(--brand-500); width: 1rem; height: 1rem; }
.ds-form label { cursor: pointer; }

.dark .ds-form input:not([type="checkbox"]):not([type="radio"]),
.dark .ds-form select,
.dark .ds-form textarea {
  background: var(--ink-900);
  border-color: rgb(255 255 255 / 0.12);
  color: #e5e7eb;
}
.dark .ds-form input::placeholder,
.dark .ds-form textarea::placeholder { color: #6b7280; }

/* ── Seletor de período (components/date_range.html) ─────────────────────────
   Da lib (vanilla-calendar-pro) vem só o layout.css, sem cor: o tema é nosso,
   para o calendário usar os tokens da marca e seguir o .dark do produto. */
/* Painel ancorado por `date_range.js` (position fixed + coordenadas): fixed
   escapa do overflow de modal/popover, que cortaria um painel absoluto. */
.vc[data-vc-input] {
  /* Sem isto o painel herda a largura do campo e os dois meses empilham. */
  width: max-content !important;
  max-width: 92vw;
}
.vc {
  z-index: 60;
  font-family: inherit;
  font-size: 0.875rem;
  background: #fff;
  color: var(--text-primary);
  border: 1px solid #ececf0;
  box-shadow: 0 16px 40px rgb(0 0 0 / 0.14);
}
.dark .vc {
  background: var(--ink-800);
  color: #e5e7eb;
  border-color: rgb(255 255 255 / 0.1);
  box-shadow: 0 16px 40px rgb(0 0 0 / 0.5);
}
.vc [data-vc=grid] { column-gap: 1.25rem; }
.vc-month, .vc-year {
  border-radius: 0.375rem;
  padding: 0.125rem 0.375rem;
  font-weight: 700;
  color: inherit;
}
.vc-month:hover, .vc-year:hover, .vc-months__month:hover, .vc-years__year:hover {
  background: var(--brand-50);
  color: var(--brand-700);
}
.dark .vc-month:hover, .dark .vc-year:hover,
.dark .vc-months__month:hover, .dark .vc-years__year:hover {
  background: rgb(129 38 253 / 0.18);
  color: var(--brand-300);
}
.vc-months__month, .vc-years__year { border-radius: 0.5rem; }
.vc-months__month[data-vc-months-month-selected],
.vc-years__year[data-vc-years-year-selected] {
  background: var(--brand-500);
  color: #fff;
}
/* Seta = máscara sobre currentColor: acompanha o tema sem duplicar o SVG. */
[data-vc-arrow]:before {
  background: currentColor;
  opacity: 0.55;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>") center / 1rem no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>") center / 1rem no-repeat;
}
[data-vc-arrow]:hover:before { opacity: 1; }
.vc-week__day { font-size: 0.75rem; font-weight: 700; color: #9a9aa4; }
.vc-date__btn { border-radius: 0.5rem; color: inherit; }
.vc-date__btn:hover { background: #f4f4f6; }
.dark .vc-date__btn:hover { background: rgb(255 255 255 / 0.07); }
.vc-date[data-vc-date-today] .vc-date__btn {
  box-shadow: inset 0 0 0 1px var(--brand-400);
  font-weight: 700;
}
/* Pontas do range com a cor cheia da marca; o miolo fica em fundo suave. */
.vc-date[data-vc-date-selected] .vc-date__btn {
  background: var(--brand-500);
  color: #fff;
  font-weight: 700;
  box-shadow: none;
}
.vc-date[data-vc-date-selected=middle] .vc-date__btn {
  background: var(--brand-50);
  color: var(--brand-700);
  font-weight: 400;
}
.dark .vc-date[data-vc-date-selected=middle] .vc-date__btn {
  background: rgb(129 38 253 / 0.2);
  color: var(--brand-200);
}
.vc-date[data-vc-date-hover] .vc-date__btn { background: var(--brand-50); }
.dark .vc-date[data-vc-date-hover] .vc-date__btn { background: rgb(129 38 253 / 0.15); }
.vc-date[data-vc-date-disabled] .vc-date__btn { color: #c9c9d0; }
.dark .vc-date[data-vc-date-disabled] .vc-date__btn { color: #4b5563; }
/* Atalhos + limpar (injetados por date_range.js). */
.vc [data-dr-footer] {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem;
  margin-top: 0.75rem;
  padding-top: 0.75rem;
  border-top: 1px solid #ececf0;
}
.dark .vc [data-dr-footer] { border-color: rgb(255 255 255 / 0.1); }
.vc [data-dr-footer] button {
  cursor: pointer;
  border-radius: 0.375rem;
  padding: 0.25rem 0.5rem;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--brand-600);
}
.vc [data-dr-footer] button:hover { background: var(--brand-50); }
.vc [data-dr-footer] [data-dr-clear] { margin-left: auto; color: var(--text-secondary); }
.vc [data-dr-footer] [data-dr-clear]:hover { background: #f4f4f6; color: var(--text-primary); }
.dark .vc [data-dr-footer] button { color: var(--brand-300); }
.dark .vc [data-dr-footer] button:hover { background: rgb(129 38 253 / 0.18); }
.dark .vc [data-dr-footer] [data-dr-clear] { color: #9ca3af; }
.dark .vc [data-dr-footer] [data-dr-clear]:hover { background: rgb(255 255 255 / 0.07); color: #fff; }

[x-cloak] { display: none !important; }

/* Estilo de markdown renderizado (flatpages, blog, docs). */
.markdown-body { color: rgb(17 24 39); line-height: 1.7; }
.dark .markdown-body { color: rgb(229 231 235); }
.markdown-body h1, .markdown-body h2, .markdown-body h3 { font-weight: 600; margin-top: 1.5em; margin-bottom: 0.5em; color: rgb(17 24 39); }
.dark .markdown-body h1, .dark .markdown-body h2, .dark .markdown-body h3 { color: white; }
.markdown-body h2 { font-size: 1.5rem; }
.markdown-body h3 { font-size: 1.25rem; }
.markdown-body p { margin-bottom: 1em; }
.markdown-body a { color: rgb(79 70 229); text-decoration: underline; }
.dark .markdown-body a { color: rgb(165 180 252); }
.markdown-body ul, .markdown-body ol { padding-left: 1.5em; margin-bottom: 1em; }
.markdown-body ul { list-style: disc; }
.markdown-body ol { list-style: decimal; }
.markdown-body li { margin-bottom: 0.25em; }
.markdown-body code { background: rgb(243 244 246); padding: 0.125em 0.375em; border-radius: 0.25em; font-size: 0.875em; }
.dark .markdown-body code { background: rgb(31 41 55); }
.markdown-body pre { background: rgb(17 24 39); color: rgb(243 244 246); padding: 1em; border-radius: 0.5em; overflow-x: auto; margin-bottom: 1em; }
.markdown-body pre code { background: transparent; padding: 0; }
.markdown-body blockquote { border-left: 4px solid rgb(209 213 219); padding-left: 1em; color: rgb(75 85 99); font-style: italic; margin-bottom: 1em; }
.dark .markdown-body blockquote { border-color: rgb(75 85 99); color: rgb(156 163 175); }
.markdown-body table { width: 100%; border-collapse: collapse; margin-bottom: 1em; }
.markdown-body th, .markdown-body td { border: 1px solid rgb(229 231 235); padding: 0.5em 0.75em; }
.dark .markdown-body th, .dark .markdown-body td { border-color: rgb(55 65 81); }
.markdown-body th { background: rgb(249 250 251); font-weight: 600; }
.dark .markdown-body th { background: rgb(31 41 55); }
.markdown-body img { max-width: 100%; border-radius: 0.5em; margin: 1em 0; }

/* HTMX progress indicator (top loading bar durante boost navigation). */
.htmx-indicator { transform: scaleX(0); transition: transform 0.2s ease-out; }
.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator { transform: scaleX(0.9); }
.htmx-request.htmx-indicator { animation: htmx-progress 1.5s ease-out infinite; }
@keyframes htmx-progress {
  0%   { transform: scaleX(0); }
  50%  { transform: scaleX(0.7); }
  100% { transform: scaleX(0.95); }
}

/* Shimmer de skeleton (listagens): bloco neutro com brilho que atravessa. */
.shimmer { position: relative; overflow: hidden; background: rgb(236 236 240); }
.dark .shimmer { background: rgb(255 255 255 / 0.08); }
.shimmer::after {
  content: ""; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgb(255 255 255 / 0.7), transparent);
  animation: shimmer 1.6s ease-in-out infinite;
}
.dark .shimmer::after { background: linear-gradient(90deg, transparent, rgb(255 255 255 / 0.1), transparent); }
@keyframes shimmer { 100% { transform: translateX(100%); } }

/* Troca conteúdo real ↔ skeleton enquanto o hx-indicator (#listing-rows) está ativo. */
.listing-skeleton { display: none; }
.htmx-request .listing-real { display: none; }
.htmx-request .listing-skeleton { display: block; }

/* Linhas que chegam pela rolagem entram desvanecendo (v1): aparecer de estalo, logo
   abaixo do shimmer que sai, faz a lista parecer que pulou. `htmx-added` é a classe
   que o HTMX põe no conteúdo novo durante o settle. */
/* Entrada das linhas que chegam pela rolagem — padrão de settle do HTMX, não animação.
   `htmx-added` só existe entre o swap e o fim do settle (20ms no default): animação
   presa a essa classe é cortada antes de aparecer. O jeito certo é o inverso — a
   linha declara a transição e nasce deslocada COM a classe; quando o HTMX a remove,
   a transição roda. Por isso o `settle:` no hx-swap: sem ele o navegador não chega a
   pintar o estado inicial e a transição não tem de onde partir. */
#listing-rows [id^="call-row-"],
#analysis-list [id^="call-row-"] {
  transition: opacity 320ms ease-out, transform 320ms cubic-bezier(.16, 1, .3, 1);
}
#listing-rows [id^="call-row-"].htmx-added,
#analysis-list [id^="call-row-"].htmx-added {
  opacity: 0;
  transform: translateY(12px);
}
@media (prefers-reduced-motion: reduce) {
  #listing-rows [id^="call-row-"],
  #analysis-list [id^="call-row-"] { transition: none; }
  #listing-rows [id^="call-row-"].htmx-added,
  #analysis-list [id^="call-row-"].htmx-added { opacity: 1; transform: none; }
}

/* Hero do detalhe de conta — grain SVG + animação de entrada das seções. */
.hero-grain {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.5 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}
@keyframes fade-up { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.anim-in    { animation: fade-up 520ms cubic-bezier(.16, 1, .3, 1) backwards; }
.anim-d-100 { animation-delay:  80ms; }
.anim-d-200 { animation-delay: 160ms; }
.anim-d-300 { animation-delay: 240ms; }

/* Colapso das etapas do processamento. O estado é um atributo do <body> (ver
   app.js) e não classe no card: o card é trocado a cada 4s pelo polling, então
   qualquer estado guardado DENTRO dele é perdido no swap. */
body[data-etapas="fechado"] #call-timeline-steps { display: none; }
body[data-etapas="fechado"] .js-etapas-chevron { transform: rotate(0deg); }
.js-etapas-chevron { transform: rotate(90deg); transition: transform 150ms; }
body:not([data-etapas="fechado"]) .js-etapas-resumo { display: none; }

/* Barra de execução: durante o arraste o trilho e o handle ficam no estado de
   hover, senão eles somem no meio do gesto (o ponteiro sai do elemento). */
.js-scrub.js-arrastando .js-scrub-track,
.js-scrub.js-arrastando .js-scrub-fill { height: 6px; }
.js-scrub.js-arrastando .js-scrub-handle { transform: translate(-50%, -50%) scale(1.1); }

/* Paleta das etapas do playbook (aba "Tópicos da ligação"). Aqui e não no
   template: a cor identifica a etapa e precisa ser a MESMA em toda tela que
   mostrar etapa. Entram por `style` nas faixas, para não brigar com a cor do
   locutor (que é classe). */
:root {
  --etapa-0: #059669; /* emerald-600  */
  --etapa-1: #8126fd; /* roxo da marca */
  --etapa-2: #2563eb; /* blue-600     */
  --etapa-3: #f59e0b; /* amber-500    */
  --etapa-4: #f43f5e; /* rose-500     */
  --etapa-5: #14b8a6; /* teal-500     */
  --etapa-6: #7c3aed; /* violet-600   */
  --etapa-7: #65a30d; /* lime-600     */
  --etapa-outros: #c4c4cc;
}
.dark { --etapa-outros: #52525b; }
