/* ============================================================================
   UNITDK · Movimento, segunda camada   (ticket 50)
   ----------------------------------------------------------------------------
   Desenhado e aprovado num canvas em 09/10/2026, com códigos que este arquivo
   repete nos títulos (E1…E15 são movimentos, T1…T3 são tonalidades):
   https://claude.ai/artifact/CydZ2JjYBj3jbgJpH1rGSd

   A primeira camada mora em app.css, seção "16. Movimento" (barras que enchem,
   listas que entram em cascata, o clicável que levanta). Ela continua valendo;
   este arquivo vem DEPOIS dela e acrescenta. Os princípios são os mesmos:

   1. Só se move o que é clicável. Cartão que acende e não abre nada promete o que
      não faz.
   2. Curto: 180 a 400 ms. Celebração vai até 1,5 s e acontece uma vez. As únicas
      coisas em laço são o feixe do próximo passo e o "você está aqui".
   3. Menos movimento = nada. O bloco do fim desliga tudo, e nada do que é
      conteúdo depende de animação para aparecer.

   O que precisa de JavaScript (a luz que segue o cursor, o destaque da sidebar,
   os números que contam...) está em public/js/movimento.js, e só liga com a marca
   `html.tdk-mov`, posta pelo layout. Sem ela a página é a de antes.
   ============================================================================ */

:root {
  --tdk-saida: cubic-bezier(0.2, 0.8, 0.2, 1);
  --tdk-mola: cubic-bezier(0.3, 1.55, 0.5, 1);
}

/* Propriedades registradas: é o que permite TRANSICIONAR um número dentro de um
   gradiente (a luz) e girar um ângulo (o feixe). Navegador que não conhece
   @property troca de estado sem transição — feio nunca, só mais seco. */
@property --tdk-luz { syntax: '<number>'; inherits: false; initial-value: 0; }
@property --tdk-giro { syntax: '<angle>'; inherits: false; initial-value: 0deg; }


/* ── E12 · Troca de página ────────────────────────────────────────────────────
   O pedido de transição (`@view-transition`) está no layout com sidebar, e só nele:
   a tela de foco (aula e prova) abre seca, porque quem chega ali quer assistir ou
   responder, não ver a página chegar. Aqui fica o COMO: sidebar e topo parados,
   o conteúdo sai rápido e o novo entra deslizando. */
.tdk-sidebar { view-transition-name: tdk-sidebar; }
.tdk-topbar { view-transition-name: tdk-topo; }

::view-transition-old(tdk-sidebar),
::view-transition-new(tdk-sidebar),
::view-transition-old(tdk-topo),
::view-transition-new(tdk-topo) { animation: none; }

::view-transition-old(root) { animation: 140ms ease-out both tdk-vt-sai; }
::view-transition-new(root) { animation: 300ms var(--tdk-saida) both tdk-vt-entra; }

@keyframes tdk-vt-sai { to { opacity: 0; } }
@keyframes tdk-vt-entra { from { opacity: 0; transform: translateX(14px); } }


/* ── T2 · Superfície com luz de cima ──────────────────────────────────────────
   A do `.tdk-card` está no próprio app.css (é o componente base). Aqui ficam as
   superfícies que não são `.tdk-card` mas são cartão na tela do aluno. */
.tdk-trilha-linha,
.tdk-curso-linha,
.tdk-cert-destaque,
.tdk-boletim-linha,
.tdk-material {
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.025), rgba(255, 255, 255, 0) 46%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
}


/* ── E1 + T1 · Luz que segue o cursor, na cor do setor ────────────────────────
   Tudo num `background` só, em camadas, para não disputar ::before/::after com o
   que cada cartão já usa (a linha do tempo da trilha, o link esticado):

     1. o filete do setor no topo (T1), quando o cartão pede `.tdk-filete`;
     2. o brilho que segue o cursor, por dentro;
     3. a luz de cima (T2);
     4. o fundo;
     5. a borda: a camada de `border-box` aparece pelo 1px transparente da borda,
        mais clara onde o cursor está.

   `--tdk-luz` vai de 0 a 1 no hover, com transição — por isso é registrada. A
   posição vem do movimento.js, em `--mx` e `--my`. `--cor` é a do setor, a mesma
   que o chip de área usa; sem ela, o acento. */
html.tdk-mov .tdk-luz {
  --luz-cor: var(--cor, var(--tdk-accent));
  --luz-fundo: var(--tdk-surface);
  border-color: transparent;
  background:
    var(--luz-filete, none) top / 100% 1px no-repeat padding-box,
    radial-gradient(520px circle at var(--mx, 50%) var(--my, 50%),
      color-mix(in srgb, var(--luz-cor) calc(9% * var(--tdk-luz)), transparent), transparent 42%) padding-box,
    linear-gradient(180deg, rgba(255, 255, 255, 0.025), rgba(255, 255, 255, 0) 46%) padding-box,
    linear-gradient(var(--luz-fundo), var(--luz-fundo)) padding-box,
    radial-gradient(260px circle at var(--mx, 50%) var(--my, 50%),
      color-mix(in srgb, var(--luz-cor) calc(80% * var(--tdk-luz)), var(--tdk-border-hi)),
      color-mix(in srgb, var(--tdk-border-hi) calc(100% * var(--tdk-luz)), var(--tdk-border)) 70%) border-box;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
  transition: --tdk-luz 0.35s ease, transform 0.3s var(--tdk-saida), box-shadow 0.3s ease;
}

/* Levanta junto. A sombra é discreta: no escuro, o que dá relevo é a borda acender. */
html.tdk-mov .tdk-luz:hover {
  --tdk-luz: 1;
  transform: translateY(-3px);
  box-shadow: 0 16px 34px -16px rgba(0, 0, 0, 0.75), inset 0 1px 0 rgba(255, 255, 255, 0.05);
}

html.tdk-mov .tdk-luz:active { transform: translateY(-1px); transition-duration: 0.06s; }

/* T1: o filete do setor no topo do cartão. */
.tdk-filete { --luz-filete: linear-gradient(90deg, color-mix(in srgb, var(--cor, var(--tdk-accent)) 80%, transparent), transparent 55%); }

/* No cartão que não acende (não é link), e em qualquer um sem JavaScript, o filete
   entra por cima do fundo do próprio cartão: ele é tonalidade, não movimento. */
.tdk-filete:not(.tdk-luz),
html:not(.tdk-mov) .tdk-filete {
  background-image:
    var(--luz-filete),
    linear-gradient(180deg, rgba(255, 255, 255, 0.025), rgba(255, 255, 255, 0) 46%);
  background-size: 100% 1px, 100% 100%;
  background-repeat: no-repeat;
}


/* ── O cartão inteiro clica (sacada 2) ────────────────────────────────────────
   Sem aninhar link dentro de link: o ::after do link do título cobre o cartão, e o
   que mais houver de clicável dentro (Entrar na trilha, Sair) sobe acima dele. É a
   mesma solução da linha do curso na página da trilha. */
.tdk-cartao-link { position: relative; }
.tdk-cartao-link .tdk-link-esticado { color: inherit; }
.tdk-cartao-link .tdk-link-esticado::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
}
.tdk-cartao-link .tdk-link-esticado:focus-visible { outline: none; }
.tdk-cartao-link:has(.tdk-link-esticado:focus-visible) { outline: 2px solid var(--tdk-accent); outline-offset: 2px; }
.tdk-cartao-link form,
.tdk-cartao-link .tdk-btn,
.tdk-cartao-link .tdk-sobe { position: relative; z-index: 2; }

/* O chip de setor do catálogo (sacada 1) leva a cor do setor num ponto. */
.tdk-chip-cor {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--cor, var(--tdk-accent));
  box-shadow: 0 0 6px color-mix(in srgb, var(--cor, var(--tdk-accent)) 60%, transparent);
}
.tdk-chip { transition: background var(--tdk-trans), border-color var(--tdk-trans), color var(--tdk-trans), transform 0.16s var(--tdk-saida); }
.tdk-chip:active { transform: scale(0.96); }
[data-catalogo][aria-busy="true"] { cursor: progress; }

/* "Abrir →" no pé do cartão: diz que o cartão inteiro leva a algum lugar. */
.tdk-abrir {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: auto;
  color: var(--tdk-text-3);
  font-size: var(--tdk-fs-sm);
  font-weight: var(--tdk-fw-medium);
  transition: color var(--tdk-trans);
}
.tdk-abrir svg { width: 12px; height: 12px; transition: transform 0.28s var(--tdk-mola); }
.tdk-cartao-link:hover .tdk-abrir { color: var(--tdk-text); }
.tdk-cartao-link:hover .tdk-abrir svg { transform: translateX(3px); }


/* ── E2 · Feixe na borda ──────────────────────────────────────────────────────
   Uma luz que percorre a borda do próximo passo. Um por tela: o feixe diz "é por
   aqui", e dois deixam de dizer qualquer coisa. Gradiente cônico girando, recortado
   por máscara num anel de 1px. */
.tdk-com-feixe {
  position: relative;
  box-shadow: 0 0 0 1px rgba(90, 181, 255, 0.12), 0 18px 50px -24px rgba(90, 181, 255, 0.45);
}

.tdk-feixe-caixa {
  position: relative;
  display: inline-flex;
  border-radius: var(--tdk-radius);
}

.tdk-feixe {
  position: absolute;
  inset: -1px;
  z-index: 3;
  border-radius: inherit;
  padding: 1px;
  pointer-events: none;
  background: conic-gradient(from var(--tdk-giro),
    transparent 0deg 250deg,
    rgba(90, 181, 255, 0.15) 290deg,
    rgba(90, 181, 255, 0.95) 340deg,
    #fff 353deg,
    transparent 360deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
  animation: tdk-feixe 5.5s linear infinite;
}

.tdk-feixe-caixa > .tdk-feixe { inset: -2px; padding: 2px; border-radius: calc(var(--tdk-radius) + 2px); }

@keyframes tdk-feixe { to { --tdk-giro: 360deg; } }


/* ── E3 · Botão que responde ──────────────────────────────────────────────────
   O primário ganha um reflexo que atravessa no hover, um brilho embaixo, e afunda
   no clique. A seta (`<x-botao seta>`) anda para o lado de onde aponta. */
.tdk-btn--primario {
  position: relative;
  overflow: hidden;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35);
  transition:
    background var(--tdk-trans),
    border-color var(--tdk-trans),
    color var(--tdk-trans),
    transform 0.16s var(--tdk-saida),
    box-shadow 0.25s ease;
}

.tdk-btn--primario::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: -70%;
  width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.55), transparent);
  transform: skewX(-20deg);
  pointer-events: none;
}

.tdk-btn--primario:hover {
  box-shadow: 0 10px 26px -10px rgba(90, 181, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.35);
}

.tdk-btn--primario:hover::before { left: 135%; transition: left 0.65s ease; }

.tdk-btn:active { transform: translateY(0) scale(0.965); transition-duration: 0.06s; }

.tdk-seta { display: inline-block; transition: transform 0.28s var(--tdk-mola); }
.tdk-btn:hover .tdk-seta { transform: translateX(3px); }
.tdk-btn:hover .tdk-seta--volta { transform: translateX(-3px); }

/* O ícone de baixar desce, como se baixasse. */
.tdk-btn:hover .tdk-desce { animation: tdk-desce 0.7s var(--tdk-saida); }
@keyframes tdk-desce { 40% { transform: translateY(3px); } }

/* O link "Ver todas →" e parentes: a seta anda, o resto fica. */
.tdk-link-seta { display: inline-flex; align-items: center; gap: 4px; }
.tdk-link-seta:hover .tdk-seta { transform: translateX(3px); }


/* ── E4 · Números que contam ──────────────────────────────────────────────────
   A contagem é do movimento.js, sobre o número que o servidor já escreveu: sem
   JavaScript, ou com menos movimento, o número está lá desde o começo. Aqui só a
   largura fixa dos dígitos, para o número não tremer enquanto conta. */
[data-conta] { font-variant-numeric: tabular-nums; }


/* ── E5 · Barra viva ──────────────────────────────────────────────────────────
   O enchimento já existe (app.css). Entram o brilho na ponta e um reflexo que passa
   uma vez, quando ela termina de encher. */
.tdk-progresso-preenche {
  position: relative;
  overflow: hidden;
  background: linear-gradient(90deg, var(--tdk-accent-hov), var(--tdk-accent));
  box-shadow: 0 0 12px rgba(90, 181, 255, 0.45);
}

.tdk-progresso-preenche.is-completo {
  background: linear-gradient(90deg, #45C9A2, var(--tdk-ok));
  box-shadow: 0 0 12px rgba(111, 227, 192, 0.4);
}

.tdk-progresso-preenche::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.55), transparent);
  transform: translateX(-100%);
  animation: tdk-reflexo 0.9s ease 1.1s both;
}

@keyframes tdk-reflexo { to { transform: translateX(100%); } }


/* ── E6 · Destaque que desliza na sidebar ─────────────────────────────────────
   Um fantasma atrás dos itens acompanha o mouse; o item atual ganha a régua azul.
   Só com a sidebar expandida e acima de 880px — recolhida, quem fala é a dica; no
   celular, a sidebar é a faixa do topo. O fantasma é posto pelo movimento.js; sem
   ele, o hover de antes. */
.tdk-nav { position: relative; isolation: isolate; }

.tdk-nav-fantasma {
  position: absolute;
  left: 0;
  top: 0;
  z-index: -1;
  width: var(--fw, 100%);
  height: var(--fh, 0);
  transform: translate(var(--fx, 0), var(--fy, 0));
  border-radius: var(--tdk-radius);
  background: var(--tdk-surface);
  opacity: 0;
  pointer-events: none;
  transition: transform 0.34s var(--tdk-mola), width 0.25s ease, height 0.25s ease, opacity 0.2s ease;
}

.tdk-nav.is-pairando .tdk-nav-fantasma { opacity: 1; }
.tdk-nav-fantasma.sem-transicao { transition: opacity 0.2s ease; }

@media (min-width: 881px) {
  html.tdk-mov .tdk-shell:not(.is-recolhida) .tdk-nav .tdk-nav-item:not(.is-ativo):hover { background: transparent; }

  .tdk-nav-item.is-ativo { position: relative; }
  .tdk-nav-item.is-ativo::before {
    content: "";
    position: absolute;
    left: -13px;
    top: 9px;
    bottom: 9px;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background: var(--tdk-accent);
    box-shadow: 0 0 10px rgba(90, 181, 255, 0.8);
  }
  .is-recolhida .tdk-nav-item.is-ativo::before { left: -11px; }
  .tdk-nav-sub .tdk-nav-item.is-ativo::before { left: -12px; }
}

@media (max-width: 880px) {
  .tdk-nav-fantasma { display: none; }
}
.is-recolhida .tdk-nav-fantasma { display: none; }

/* O ícone do item dá um pulo de lado no hover. A seta do grupo não: ela já gira
   para dizer aberto ou fechado, e o pulo apagaria esse giro. */
.tdk-nav-item svg:not(.tdk-nav-seta) { transition: transform 0.3s var(--tdk-mola), opacity var(--tdk-trans), color var(--tdk-trans); }
.tdk-nav-item:hover svg:not(.tdk-nav-seta) { transform: scale(1.12) rotate(-6deg); }


/* ── O topo: sino e menu da pessoa ────────────────────────────────────────── */
.tdk-sino svg { transform-origin: 50% 2px; }
.tdk-sino:hover svg { animation: tdk-sino 0.7s ease; }
@keyframes tdk-sino {
  20% { transform: rotate(16deg); }
  40% { transform: rotate(-12deg); }
  60% { transform: rotate(7deg); }
  80% { transform: rotate(-3deg); }
}

/* O contador de avisos entra com um pulo, depois de a página chegar. */
.tdk-sino-ponto { animation: tdk-pulo 0.5s var(--tdk-mola) 0.8s both; }
@keyframes tdk-pulo { from { transform: scale(0); } }

.tdk-pessoal-seta { transition: transform 0.3s var(--tdk-mola); }
.tdk-pessoal-botao:hover .tdk-pessoal-seta,
.tdk-pessoal-botao[aria-expanded="true"] .tdk-pessoal-seta { transform: rotate(180deg); }


/* ── E7 · Texto que se revela ─────────────────────────────────────────────────
   O movimento.js parte o título em palavras; cada uma sobe e desfoca para o nítido.
   Enquanto ele não chega o título fica invisível — e, se ele não chegar nunca, o
   título aparece sozinho em 1,5 s: conteúdo não pode depender de animação. */
@media (prefers-reduced-motion: no-preference) {
  html.tdk-mov [data-revela]:not(.is-revelado) { opacity: 0; animation: tdk-aparece 0s linear 1.5s forwards; }
}
@keyframes tdk-aparece { to { opacity: 1; } }

.tdk-palavra {
  display: inline-block;
  animation: tdk-palavra 0.7s var(--tdk-saida) both;
}
@keyframes tdk-palavra { from { opacity: 0; filter: blur(8px); transform: translateY(0.4em); } }

/* "2 cursos": um sublinhado que se desenha depois da frase. */
.tdk-grifo,
.tdk-saudacao-titulo strong { position: relative; white-space: nowrap; }
.tdk-grifo::after,
.tdk-saudacao-titulo strong::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0.02em;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--tdk-accent), rgba(90, 181, 255, 0.2));
  transform-origin: left;
  transform: scaleX(0);
  animation: tdk-grifo 0.7s var(--tdk-saida) 0.8s forwards;
}
@keyframes tdk-grifo { to { transform: scaleX(1); } }


/* ── E8 · Visto que se desenha ────────────────────────────────────────────────
   O traço do "checado" mede 22,6 — 24 sobra e não deixa ponta à mostra. */
.tdk-visto polyline,
.tdk-visto path { stroke-dasharray: 24; stroke-dashoffset: 24; animation: tdk-traca 0.5s cubic-bezier(0.65, 0, 0.35, 1) 0.35s forwards; }
@keyframes tdk-traca { to { stroke-dashoffset: 0; } }

.tdk-surge { animation: tdk-surge-pulo 0.4s var(--tdk-mola) 0.15s both; }
@keyframes tdk-surge-pulo { from { transform: scale(0.6); opacity: 0; } }


/* ── E9 · Cartão 3D com reflexo (o certificado) ───────────────────────────── */
.tdk-cert-destaque { position: relative; perspective: 1100px; }

[data-inclina] {
  position: relative;
  transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transform-style: preserve-3d;
  transition: transform 0.6s var(--tdk-saida), box-shadow 0.4s ease, border-color 0.4s ease;
}
[data-inclina].is-inclinando { transition: transform 0.08s linear, box-shadow 0.4s ease, border-color 0.4s ease; }
[data-inclina]:hover {
  border-color: rgba(242, 184, 30, 0.45);
  box-shadow: 0 30px 60px -30px rgba(0, 0, 0, 0.9), 0 0 0 1px rgba(242, 184, 30, 0.2);
}

.tdk-mini-cert-brilho {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background:
    radial-gradient(circle at var(--gx, 50%) var(--gy, 50%), rgba(255, 255, 255, 0.16), transparent 38%),
    linear-gradient(115deg, transparent 25%, rgba(242, 184, 30, 0.16) 42%, rgba(90, 181, 255, 0.14) 52%, rgba(199, 161, 255, 0.12) 60%, transparent 75%);
  background-size: 100% 100%, 260% 260%;
  background-position: center, var(--gx, 50%) var(--gy, 50%);
  mix-blend-mode: screen;
  opacity: 0;
  transition: opacity 0.4s ease;
}
[data-inclina]:hover .tdk-mini-cert-brilho { opacity: 0.9; }


/* ── E10 · Confete ────────────────────────────────────────────────────────────
   36 peças postas pelo movimento.js, com a trajetória escolhida por nth-child:
   ciclos de 6, 5, 4, 3 e 7 que não se repetem juntos dão uma chuva que parece
   aleatória sem uma linha de sorteio. */
.tdk-confete { position: absolute; left: 50%; top: 50%; width: 0; height: 0; pointer-events: none; z-index: 6; }
.tdk-confete i {
  position: absolute;
  left: -4px;
  top: -6px;
  width: 8px;
  height: 12px;
  border-radius: 2px;
  background: var(--c, var(--tdk-accent));
  opacity: 0;
  animation: tdk-confete 1.5s cubic-bezier(0.12, 0.7, 0.35, 1) var(--d, 0s) forwards;
}
@keyframes tdk-confete {
  0% { opacity: 1; transform: translate(0, 0) rotate(0) scale(0.6); }
  55% { opacity: 1; transform: translate(calc(var(--cx) * 0.85), var(--cy)) rotate(calc(var(--cr) * 0.6)) scale(1); }
  100% { opacity: 0; transform: translate(var(--cx), calc(var(--cy) + 170px)) rotate(var(--cr)) scale(0.9); }
}
.tdk-confete i:nth-child(6n + 1) { --cx: -230px; } .tdk-confete i:nth-child(6n + 2) { --cx: -140px; }
.tdk-confete i:nth-child(6n + 3) { --cx: -55px; }  .tdk-confete i:nth-child(6n + 4) { --cx: 60px; }
.tdk-confete i:nth-child(6n + 5) { --cx: 150px; }  .tdk-confete i:nth-child(6n) { --cx: 235px; }
.tdk-confete i:nth-child(5n + 1) { --cy: -150px; } .tdk-confete i:nth-child(5n + 2) { --cy: -230px; }
.tdk-confete i:nth-child(5n + 3) { --cy: -110px; } .tdk-confete i:nth-child(5n + 4) { --cy: -260px; }
.tdk-confete i:nth-child(5n) { --cy: -190px; }
.tdk-confete i:nth-child(4n + 1) { --c: var(--tdk-accent); } .tdk-confete i:nth-child(4n + 2) { --c: var(--tdk-ok); }
.tdk-confete i:nth-child(4n + 3) { --c: var(--tdk-gold); }   .tdk-confete i:nth-child(4n) { --c: var(--tdk-area-produto); }
.tdk-confete i:nth-child(3n + 1) { --cr: 260deg; } .tdk-confete i:nth-child(3n + 2) { --cr: -340deg; } .tdk-confete i:nth-child(3n) { --cr: 520deg; }
.tdk-confete i:nth-child(7n + 1) { --d: 0s; }   .tdk-confete i:nth-child(7n + 2) { --d: 0.04s; } .tdk-confete i:nth-child(7n + 3) { --d: 0.08s; }
.tdk-confete i:nth-child(7n + 4) { --d: 0.02s; } .tdk-confete i:nth-child(7n + 5) { --d: 0.1s; }  .tdk-confete i:nth-child(7n + 6) { --d: 0.06s; }
.tdk-confete i:nth-child(7n) { --d: 0.12s; }
.tdk-confete i:nth-child(2n) { width: 7px; height: 7px; border-radius: 50%; }

/* Na nota, o confete espera o anel fechar. */
.tdk-resultado-anel .tdk-confete i { animation-delay: calc(var(--d, 0s) + 1s); }


/* ── E11 · Código que se decifra ──────────────────────────────────────────── */
.tdk-decifrando { color: var(--tdk-accent); }


/* ── E13 · Cadeado que nega ───────────────────────────────────────────────────
   A aula fora da vez não abre — e agora diz por quê, em vez de não fazer nada. */
.tdk-nega { animation: tdk-nega 0.42s cubic-bezier(0.36, 0.07, 0.19, 0.97); }
@keyframes tdk-nega {
  20%, 60% { transform: translateX(-5px); }
  40%, 80% { transform: translateX(5px); }
}

.tdk-dica-trancada {
  display: flex;
  align-items: center;
  gap: var(--tdk-sp-2);
  padding: 2px var(--tdk-sp-3) var(--tdk-sp-2) 48px;
  color: var(--tdk-warn);
  font-family: var(--tdk-font-mono);
  font-size: var(--tdk-fs-xs);
  line-height: 1.4;
  animation: tdk-dica-entra 0.3s var(--tdk-saida) both;
}
.tdk-rail-aulas .tdk-dica-trancada { padding-left: 48px; }
@keyframes tdk-dica-entra { from { opacity: 0; transform: translateY(-4px); } }


/* ── Lista de aulas do curso: o ▶ aparece no hover ────────────────────────── */
.tdk-lista-aulas a { transition: background var(--tdk-trans), color var(--tdk-trans), transform 0.25s var(--tdk-saida); }
.tdk-lista-aulas a:hover { transform: translateX(3px); }
.tdk-lista-aulas-marca { position: relative; }
.tdk-lista-aulas-play {
  position: absolute;
  inset: -1px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--tdk-accent);
  color: var(--tdk-on-accent);
  opacity: 0;
  transform: scale(0.6) rotate(-30deg);
  transition: opacity 0.2s ease, transform 0.3s var(--tdk-mola);
}
.tdk-lista-aulas-play svg { width: 12px; height: 12px; margin-left: 2px; fill: currentColor; }
.tdk-lista-aulas a:hover .tdk-lista-aulas-play { opacity: 1; transform: none; }

.tdk-lista-aulas-acao {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--tdk-accent);
  font-size: var(--tdk-fs-xs);
  font-weight: var(--tdk-fw-medium);
  opacity: 0;
  transform: translateX(-6px);
  transition: opacity 0.2s ease, transform 0.25s var(--tdk-saida);
}
.tdk-lista-aulas-acao svg { width: 12px; height: 12px; }
.tdk-lista-aulas a:hover .tdk-lista-aulas-acao,
.tdk-lista-aulas a:focus-visible .tdk-lista-aulas-acao { opacity: 1; transform: none; }


/* ── E14 · Seleção que pega (a alternativa da prova) ──────────────────────── */
.tdk-alternativa { transition: border-color var(--tdk-trans), background var(--tdk-trans), transform 0.25s var(--tdk-saida), box-shadow 0.3s ease; }
.tdk-alternativa:hover { border-color: var(--tdk-border-hi); transform: translateX(2px); }
.tdk-alternativa-letra { position: relative; }
.tdk-alternativa-letra::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  border: 2px solid var(--tdk-accent);
  opacity: 0;
}
.tdk-alternativa:has(input:checked) {
  background: linear-gradient(rgba(90, 181, 255, 0.07), rgba(90, 181, 255, 0.07)), var(--tdk-surface-2);
  box-shadow: 0 0 0 3px rgba(90, 181, 255, 0.1);
}
.tdk-alternativa:has(input:checked) .tdk-alternativa-letra { animation: tdk-pega 0.38s var(--tdk-mola); }
.tdk-alternativa:has(input:checked) .tdk-alternativa-letra::after { animation: tdk-anel 0.6s ease-out; }
@keyframes tdk-pega { 40% { transform: scale(1.18); } }
@keyframes tdk-anel { from { opacity: 0.8; transform: scale(1); } to { opacity: 0; transform: scale(1.7); } }

/* As teclas, à vista só para quem tem teclado e JavaScript. */
.tdk-prova-teclas { display: none; }
html.tdk-mov .tdk-prova-teclas {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--tdk-sp-2);
  margin-top: var(--tdk-sp-4);
  color: var(--tdk-text-3);
  font-size: var(--tdk-fs-xs);
}
.tdk-prova-teclas kbd {
  padding: 2px var(--tdk-sp-2);
  border: 1px solid var(--tdk-border-hi);
  border-bottom-width: 2px;
  border-radius: 5px;
  color: var(--tdk-text-2);
  font-family: var(--tdk-font-mono);
  font-size: 10.5px;
}
@media (hover: none) {
  html.tdk-mov .tdk-prova-teclas { display: none; }
}

.tdk-prova-passo { transition: border-color var(--tdk-trans), color var(--tdk-trans), transform 0.2s var(--tdk-mola); }
.tdk-prova-passo:hover { transform: translateY(-2px); }


/* ── E15 · Você está aqui ─────────────────────────────────────────────────── */
.tdk-aqui { position: relative; }
.tdk-aqui::after {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: inherit;
  border: 2px solid var(--tdk-accent);
  pointer-events: none;
  animation: tdk-respira 2.2s ease-out infinite;
}
@keyframes tdk-respira { from { opacity: 0.75; transform: scale(0.92); } to { opacity: 0; transform: scale(1.35); } }

/* O único vermelho que se mexe: o prazo vencido. */
.tdk-pulso-vivo {
  position: relative;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}
.tdk-pulso-vivo::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: currentColor;
  animation: tdk-eco 1.8s ease-out infinite;
}
@keyframes tdk-eco { to { transform: scale(3.2); opacity: 0; } }


/* ── T3 · Luz ambiente (só o topo do Início) ─────────────────────────────── */
.tdk-main:has(> .tdk-ambiente) { position: relative; isolation: isolate; }
.tdk-ambiente {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  z-index: -1;
  height: 420px;
  overflow: hidden;
  pointer-events: none;
}
.tdk-ambiente::before {
  content: "";
  position: absolute;
  inset: -40px;
  background:
    radial-gradient(560px 260px at 16% 0%, rgba(90, 181, 255, 0.11), transparent 70%),
    radial-gradient(420px 220px at 62% -10%, rgba(111, 227, 192, 0.05), transparent 70%);
  animation: tdk-deriva 18s ease-in-out infinite alternate;
}
.tdk-ambiente::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(rgba(255, 255, 255, 0.07) 1px, transparent 1.2px);
  background-size: 22px 22px;
  -webkit-mask-image: radial-gradient(ellipse 70% 90% at 20% 0%, #000 10%, transparent 70%);
  mask-image: radial-gradient(ellipse 70% 90% at 20% 0%, #000 10%, transparent 70%);
}
@keyframes tdk-deriva { to { transform: translate(60px, 14px); } }


/* ── Início: as listas do lado direito ────────────────────────────────────── */
.tdk-pendencia-marca { transition: background var(--tdk-trans), color var(--tdk-trans), transform 0.3s var(--tdk-mola); }
.tdk-pendencias > li > a:hover .tdk-pendencia-marca { background: var(--tdk-accent); color: var(--tdk-on-accent); }
.tdk-pendencias > li.is-urgente > a:hover .tdk-pendencia-marca { background: var(--tdk-warn); color: var(--tdk-bg); }

/* A medalha do certificado: dourada, com um brilho que passa no hover. */
.tdk-pendencia-marca--medalha {
  position: relative;
  overflow: hidden;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #FFE08A, var(--tdk-gold) 45%, #B9860B);
  color: #3A2A00;
}
.tdk-pendencia-marca--medalha::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, transparent 30%, rgba(255, 255, 255, 0.75) 50%, transparent 70%);
  transform: translateX(-120%);
}
.tdk-pendencias > li > a:hover .tdk-pendencia-marca--medalha { background: radial-gradient(circle at 35% 30%, #FFE08A, var(--tdk-gold) 45%, #B9860B); color: #3A2A00; }
.tdk-pendencias > li > a:hover .tdk-pendencia-marca--medalha::after { transform: translateX(120%); transition: transform 0.7s ease; }


/* ── Trilha: a linha do tempo (sacada 3) ──────────────────────────────────────
   A marca de cada curso sai do cartão e vai para uma coluna à esquerda, ligada às
   outras por uma linha. Cada linha desenha o SEU trecho, da própria marca até a do
   próximo curso: a marca fica no alto do cartão, e por isso o trecho mede a altura
   do cartão mais o vão — conta que o CSS sabe fazer sem medir nada.

   O trecho já percorrido acende de cima para baixo, até o curso em que a pessoa está.
   Sem cadeado em lugar nenhum: aqui a ordem é sugestão. */
.tdk-cursos--linha-do-tempo { padding-left: 56px; }

.tdk-cursos--linha-do-tempo .tdk-curso-linha { grid-template-columns: minmax(0, 1fr) auto; }

.tdk-cursos--linha-do-tempo .tdk-curso-marca {
  position: absolute;
  left: -57px;
  top: 16px;
  z-index: 1;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1.5px solid var(--tdk-border-hi);
  background: var(--tdk-bg);
  transition: transform 0.3s var(--tdk-mola);
}
.tdk-cursos--linha-do-tempo .tdk-curso-linha:hover .tdk-curso-marca { transform: scale(1.08); }

.tdk-cursos--linha-do-tempo .is-cumprido .tdk-curso-marca {
  border-color: var(--tdk-ok);
  background: var(--tdk-ok);
  color: var(--tdk-on-accent);
}
.tdk-cursos--linha-do-tempo .is-corrente .tdk-curso-marca {
  border-color: var(--tdk-accent);
  background: #0E1A26;
  color: var(--tdk-accent);
  box-shadow: none;
}

/* O trecho de cada linha, cinza; e por cima, o percorrido, que enche. */
.tdk-cursos--linha-do-tempo .tdk-curso-linha:not(:last-child)::before,
.tdk-cursos--linha-do-tempo .tdk-curso-linha.is-percorrido:not(:last-child)::after {
  content: "";
  position: absolute;
  left: -38px;
  top: 36px;
  width: 2px;
  height: calc(100% + var(--tdk-sp-3));
  border-radius: 2px;
  background: #232A35;
  pointer-events: none;
}
.tdk-cursos--linha-do-tempo .tdk-curso-linha.is-percorrido:not(:last-child)::after {
  background: linear-gradient(180deg, var(--tdk-ok), var(--tdk-accent));
  box-shadow: 0 0 10px rgba(90, 181, 255, 0.5);
  transform-origin: top;
  animation: tdk-percorre 0.45s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.tdk-cursos--linha-do-tempo .tdk-curso-linha:nth-child(1)::after { animation-delay: 0.45s; }
.tdk-cursos--linha-do-tempo .tdk-curso-linha:nth-child(2)::after { animation-delay: 0.8s; }
.tdk-cursos--linha-do-tempo .tdk-curso-linha:nth-child(3)::after { animation-delay: 1.15s; }
.tdk-cursos--linha-do-tempo .tdk-curso-linha:nth-child(4)::after { animation-delay: 1.5s; }
.tdk-cursos--linha-do-tempo .tdk-curso-linha:nth-child(n + 5)::after { animation-delay: 1.85s; }
@keyframes tdk-percorre { from { transform: scaleY(0); } }

@media (max-width: 720px) {
  .tdk-cursos--linha-do-tempo { padding-left: 44px; }
  .tdk-cursos--linha-do-tempo .tdk-curso-linha { grid-template-columns: minmax(0, 1fr); }
  .tdk-cursos--linha-do-tempo .tdk-curso-acao { grid-column: 1; }
  .tdk-cursos--linha-do-tempo .tdk-curso-marca { left: -45px; top: 14px; width: 32px; height: 32px; }
  .tdk-cursos--linha-do-tempo .tdk-curso-linha:not(:last-child)::before,
  .tdk-cursos--linha-do-tempo .tdk-curso-linha.is-percorrido:not(:last-child)::after { left: -30px; top: 30px; }
}


/* ── Trilha: o anel do certificado (sacada 4) ─────────────────────────────── */
.tdk-cartao-certificado-topo { display: flex; align-items: center; gap: var(--tdk-sp-4); }
.tdk-cartao-certificado-topo .tdk-card-titulo { margin: 0; }

.tdk-anel { position: relative; flex: none; }
.tdk-anel svg { display: block; transform: rotate(-90deg); }
.tdk-anel circle { fill: none; }
.tdk-anel .tdk-anel-trilho { stroke: rgba(255, 255, 255, 0.07); }
.tdk-anel .tdk-anel-arco { stroke: var(--tdk-accent); stroke-linecap: round; animation: tdk-anel-fecha 1.3s cubic-bezier(0.22, 1, 0.36, 1) 0.3s both; }
.tdk-anel--ouro .tdk-anel-arco { stroke: var(--tdk-gold); }
.tdk-anel--ok .tdk-anel-arco { stroke: var(--tdk-ok); }
.tdk-anel--perigo .tdk-anel-arco { stroke: var(--tdk-danger); }
@keyframes tdk-anel-fecha { from { stroke-dashoffset: 100; } }
.tdk-anel-centro {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  text-align: center;
}
.tdk-anel-numero { display: block; font-size: var(--tdk-fs-xl); font-weight: var(--tdk-fw-semi); letter-spacing: -0.02em; line-height: 1; }
.tdk-anel-numero small { color: var(--tdk-text-3); font-size: var(--tdk-fs-sm); font-weight: 400; }
.tdk-anel-rotulo {
  display: block;
  margin-top: 4px;
  color: var(--tdk-text-3);
  font-family: var(--tdk-font-mono);
  font-size: 9px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}


/* ── Aula: o rail entra, a próxima destranca, e o "A seguir" (sacada 5) ──────
   O rail não desliza a grade (app.css explica: alternar a coluna engasga e
   reescala o deck). Ele só ENTRA quando aparece — animação de quem nasce, sem
   custo para o palco. */
.tdk-aula-rail { animation: tdk-rail-entra 0.35s var(--tdk-saida); }
@keyframes tdk-rail-entra { from { opacity: 0; transform: translateX(16px); } }

.tdk-conclusao.is-concluida [data-conclusao-seguir] { animation: tdk-pulo 0.5s var(--tdk-mola); }

.tdk-rail-aulas > li.is-destrancada .tdk-rail-marca { animation: tdk-surge-pulo 0.45s var(--tdk-mola) 0.25s both; }
.tdk-rail-aulas > li.is-destrancada .tdk-celula-sub { color: var(--tdk-ok); }

.tdk-a-seguir {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 50;
  width: min(340px, calc(100vw - 48px));
  padding: var(--tdk-sp-4) var(--tdk-sp-5);
  border: 1px solid rgba(90, 181, 255, 0.35);
  border-radius: var(--tdk-radius-lg);
  background: rgba(17, 21, 28, 0.94);
  backdrop-filter: blur(12px);
  box-shadow: 0 24px 60px -20px rgba(0, 0, 0, 0.9);
  animation: tdk-a-seguir 0.55s var(--tdk-saida) 0.35s both;
}
.tdk-a-seguir[hidden] { display: none; }
@keyframes tdk-a-seguir { from { opacity: 0; transform: translateY(24px) scale(0.97); } }

@media (min-width: 1101px) {
  html:not(.tdk-rail-recolhido) .tdk-a-seguir { right: calc(340px + 48px); }
}

.tdk-a-seguir-titulo { margin-top: var(--tdk-sp-2); font-size: var(--tdk-fs-md); font-weight: var(--tdk-fw-semi); line-height: 1.3; }
.tdk-a-seguir-sub { margin-top: 2px; color: var(--tdk-text-3); font-family: var(--tdk-font-mono); font-size: var(--tdk-fs-xs); }
.tdk-a-seguir-acoes { display: flex; flex-wrap: wrap; gap: var(--tdk-sp-2); margin-top: var(--tdk-sp-4); }
.tdk-a-seguir-fechar {
  position: absolute;
  top: 10px;
  right: 10px;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--tdk-text-3);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}
.tdk-a-seguir-fechar:hover { background: var(--tdk-surface-2); color: var(--tdk-text); }


/* ── Prova: o relógio perto do fim ────────────────────────────────────────────
   Dois minutos antes, âmbar e a borda respirando devagar. Os DÍGITOS não piscam:
   a regra do ticket 34 continua — número que pisca numa prova é crueldade com quem
   está contando os segundos. No último minuto, o vermelho que já existia. */
.tdk-cronometro { transition: border-color 0.4s ease, background 0.4s ease; }
.tdk-cronometro.is-perto { border-color: var(--tdk-warn); background: var(--tdk-warn-soft); animation: tdk-respira-borda 2.4s ease-in-out infinite; }
.tdk-cronometro.is-perto .tdk-cronometro-valor,
.tdk-cronometro.is-perto .tdk-cronometro-rotulo { color: var(--tdk-warn); }
@keyframes tdk-respira-borda { 50% { box-shadow: 0 0 0 4px rgba(245, 194, 107, 0.14); } }


/* ── Resultado da prova ───────────────────────────────────────────────────── */
.tdk-resultado-anel { position: relative; flex: none; }
/* 30px e não 38: em 38px o "100%" encostava no arco; em 30px ele mede 86px num miolo
   de 114px (medido na tela em 09/10/2026). */
.tdk-resultado-anel .tdk-anel-numero { font-size: var(--tdk-fs-2xl); font-variant-numeric: tabular-nums; }
.tdk-resultado-anel.is-aprovado .tdk-anel-numero { color: var(--tdk-ok); }
.tdk-resultado-anel .tdk-anel-rotulo { font-size: 10.5px; letter-spacing: 0.02em; text-transform: none; }
.tdk-resultado-texto { flex: 1 1 280px; display: flex; flex-direction: column; align-items: flex-start; gap: var(--tdk-sp-3); }
.tdk-resultado-frase { font-size: var(--tdk-fs-lg); font-weight: var(--tdk-fw-semi); }
.tdk-resultado-texto .tdk-selo { animation-delay: 1.05s; }


/* ── Certificados: copiado com o visto ────────────────────────────────────── */
.tdk-btn.is-copiado { background: var(--tdk-success-soft); }
.tdk-btn.is-copiado svg { width: 16px; height: 16px; }


/* ── Cascata nas listas novas ─────────────────────────────────────────────── */
.tdk-questoes > *,
.tdk-chips > * { animation: tdk-entrar 0.38s ease-out both; }
.tdk-questoes > :nth-child(2), .tdk-chips > :nth-child(2) { animation-delay: 40ms; }
.tdk-questoes > :nth-child(3), .tdk-chips > :nth-child(3) { animation-delay: 80ms; }
.tdk-questoes > :nth-child(4), .tdk-chips > :nth-child(4) { animation-delay: 120ms; }
.tdk-questoes > :nth-child(5), .tdk-chips > :nth-child(5) { animation-delay: 160ms; }
.tdk-questoes > :nth-child(6), .tdk-chips > :nth-child(6) { animation-delay: 200ms; }
.tdk-questoes > :nth-child(7), .tdk-chips > :nth-child(7) { animation-delay: 240ms; }
.tdk-questoes > :nth-child(n + 8), .tdk-chips > :nth-child(n + 8) { animation-delay: 280ms; }


/* ── Login (ticket 52) ────────────────────────────────────────────────────────
   O mesmo vocabulário na primeira tela que todo mundo vê, e o que só o login tem:
   o campo que acende (L1), o botão que espera (L4) e a grade do painel sob o
   cursor (L6). O olho da senha, o aviso de Caps Lock e a caixinha estão no app.css:
   são desenho, não movimento. */

/* A coluna do formulário entra em cascata; o título se revela (E7, no movimento.js). */
.tdk-entrada-caixa > * { animation: tdk-entrar 0.5s var(--tdk-saida) both; }
.tdk-entrada-caixa > :nth-child(2) { animation-delay: 50ms; }
.tdk-entrada-caixa > :nth-child(3) { animation-delay: 100ms; }
.tdk-entrada-caixa > :nth-child(4) { animation-delay: 150ms; }
.tdk-entrada-caixa > :nth-child(5) { animation-delay: 200ms; }
.tdk-entrada-caixa > :nth-child(6) { animation-delay: 250ms; }
.tdk-entrada-caixa > :nth-child(n + 7) { animation-delay: 300ms; }

/* E13 · Voltou com erro: o formulário entra e, depois, chacoalha. As duas animações
   na mesma regra, em sequência — numa regra só a última apagava a outra (medido:
   o formulário com erro entrava e não chacoalhava). */
.tdk-entrada-caixa > .tdk-nega {
  animation:
    tdk-entrar 0.5s var(--tdk-saida) 200ms both,
    tdk-nega 0.42s cubic-bezier(0.36, 0.07, 0.19, 0.97) 0.7s;
}

/* L1 · O campo acende ao focar: anel azul e um fio que se desenha embaixo. O fio é
   uma imagem de fundo que cresce — input não tem ::after. */
.tdk-entrada .tdk-campo-label { transition: color var(--tdk-trans); }
.tdk-entrada .tdk-campo:focus-within .tdk-campo-label { color: var(--tdk-accent); }
.tdk-entrada .tdk-campo-controle {
  background-image: linear-gradient(var(--tdk-accent), var(--tdk-accent));
  background-repeat: no-repeat;
  background-position: 12px 100%;
  background-size: 0 2px;
  transition: border-color var(--tdk-trans), box-shadow 0.25s ease, background-size 0.35s var(--tdk-saida);
}
.tdk-entrada .tdk-campo-controle:hover { border-color: var(--tdk-border-hi); }
.tdk-entrada .tdk-campo-controle:focus {
  box-shadow: 0 0 0 3px rgba(90, 181, 255, 0.16);
  background-size: calc(100% - 24px) 2px;
}

/* E8 · O visto da caixinha se desenha ao marcar. */
.tdk-caixinha polyline { stroke-dasharray: 24; stroke-dashoffset: 24; transition: stroke-dashoffset 0.35s cubic-bezier(0.65, 0, 0.35, 1); }
.tdk-entrada-lembrar input:checked + .tdk-caixinha polyline { stroke-dashoffset: 0; }

/* "Esqueci minha senha": um sublinhado que corre da esquerda. */
.tdk-entrada-linha a { position: relative; }
.tdk-entrada-linha a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.3s var(--tdk-saida);
}
.tdk-entrada-linha a:hover::after { transform: scaleX(1); transform-origin: left; }

/* L3 · O aviso de Caps Lock desce, não pisca. */
.tdk-caps { animation: tdk-dica-entra 0.25s var(--tdk-saida) both; }

/* L4 · O botão que espera: o giro no lugar da seta. */
.tdk-gira {
  flex: none;
  width: 16px;
  height: 16px;
  border: 2px solid rgba(11, 13, 16, 0.25);
  border-top-color: currentColor;
  border-radius: 50%;
  animation: tdk-girar 0.7s linear infinite;
}
.tdk-btn[aria-busy="true"] { cursor: progress; }

/* T3 · A luz do painel deriva devagar. */
.tdk-entrada-aurora {
  position: absolute;
  inset: -60px;
  pointer-events: none;
  background:
    radial-gradient(520px 380px at 70% 30%, rgba(90, 181, 255, 0.12), transparent 70%),
    radial-gradient(420px 320px at 25% 80%, rgba(111, 227, 192, 0.05), transparent 70%);
  animation: tdk-deriva 22s ease-in-out infinite alternate;
}

/* L6 · A grade acende sob o cursor: uma segunda grade, azul, vista só por um círculo
   que segue o mouse (`--mx`, `--my`, do movimento.js). */
.tdk-entrada-grade-acesa {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right, rgba(90, 181, 255, 0.55) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(90, 181, 255, 0.55) 1px, transparent 1px);
  background-size: 64px 64px;
  -webkit-mask-image: radial-gradient(220px circle at var(--mx, 60%) var(--my, 40%), #000, transparent 70%);
  mask-image: radial-gradient(220px circle at var(--mx, 60%) var(--my, 40%), #000, transparent 70%);
  opacity: 0;
  transition: opacity 0.4s ease;
}
html.tdk-mov .tdk-entrada-destaque:hover .tdk-entrada-grade-acesa { opacity: 1; }

/* O emblema chega com um pulo curto e um reflexo que passa uma vez. */
.tdk-entrada-emblema { animation: tdk-emblema 0.8s var(--tdk-mola) 0.2s both; }
.tdk-entrada-emblema::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, transparent 30%, rgba(255, 255, 255, 0.22) 50%, transparent 70%);
  transform: translateX(-120%);
  animation: tdk-reflexo-unico 1.1s ease 1.1s forwards;
}
@keyframes tdk-emblema { from { opacity: 0; transform: scale(0.85) translateY(10px); } }
@keyframes tdk-reflexo-unico { to { transform: translateX(120%); } }

.tdk-entrada-fatos > * { animation: tdk-entrar 0.45s var(--tdk-saida) both; }
.tdk-entrada-fatos > :nth-child(1) { animation-delay: 0.9s; }
.tdk-entrada-fatos > :nth-child(2) { animation-delay: 0.98s; }
.tdk-entrada-fatos > :nth-child(3) { animation-delay: 1.06s; }


/* ── Relatórios (ticket 54) ───────────────────────────────────────────────────
   O mesmo vocabulário nas quatro telas de relatório, aprovado no mesmo canvas
   (seção "Relatórios — proposta"); R1…R11 são os códigos de lá. As abas ganham o
   traço que corre, e o resto vale só onde a view pede pela classe. */

/* As abas: um traço que corre da esquerda no hover. A ativa já tem o dela. */
.tdk-aba { position: relative; transition: color var(--tdk-trans); }
.tdk-aba:not(.is-ativa)::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2px;
  height: 2px;
  border-radius: 2px;
  background: var(--tdk-border-hi);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.3s var(--tdk-saida);
}
.tdk-aba:not(.is-ativa):hover::after { transform: scaleX(1); }

/* Cascata com ordem: cada filho sabe a própria posição (`--ordem`), e a barra que
   ele carrega enche depois de a linha chegar — uma depois da outra (E5). Para de
   escalonar no nono: depois disso esperar atrapalha. */
.tdk-cascata > * { animation: tdk-entrar 0.4s var(--tdk-saida) calc(var(--ordem, 0) * 55ms) both; }
.tdk-cascata > :nth-child(2) { --ordem: 1; }
.tdk-cascata > :nth-child(3) { --ordem: 2; }
.tdk-cascata > :nth-child(4) { --ordem: 3; }
.tdk-cascata > :nth-child(5) { --ordem: 4; }
.tdk-cascata > :nth-child(6) { --ordem: 5; }
.tdk-cascata > :nth-child(7) { --ordem: 6; }
.tdk-cascata > :nth-child(8) { --ordem: 7; }
.tdk-cascata > :nth-child(n + 9) { --ordem: 8; }

/* E5 · As barras enchem, e as duas cores do andamento crescem juntas. `backwards` e
   não `both`: terminada a entrada, a largura volta a ser só a do estilo — e quando a
   troca no lugar (R11) muda o número, a barra anda até o novo, pela transição. */
.tdk-res-barra > span,
.tdk-res-pilha > span {
  position: relative;
  overflow: hidden;
  animation: tdk-preencher 0.9s cubic-bezier(0.22, 1, 0.36, 1) calc(200ms + var(--ordem, 0) * 90ms) backwards;
  transition: width 0.6s var(--tdk-saida);
}
.tdk-res-barra > span::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.45), transparent);
  transform: translateX(-100%);
  animation: tdk-reflexo 0.9s ease calc(1.1s + var(--ordem, 0) * 90ms) both;
}

/* O ponto do atraso: o único vermelho que se mexe (E15), aqui também. */
.tdk-res-pulso .tdk-pulso-vivo { flex: none; }

/* R1 · A linha inteira do curso abre o detalhe: a régua azul à esquerda, o nome
   acende e o "Abrir →" aparece. O link do nome se estica sobre a linha. */
.tdk-res-tabela tr.tdk-cartao-link > :first-child { transition: box-shadow 0.25s var(--tdk-saida); }
.tdk-res-tabela tr.tdk-cartao-link:hover > :first-child { box-shadow: inset 2px 0 0 var(--tdk-accent); }
.tdk-res-tabela tr.tdk-cartao-link .tdk-res-curso-nome { transition: color var(--tdk-trans); }
.tdk-res-tabela tr.tdk-cartao-link:hover .tdk-res-curso-nome { color: var(--tdk-accent); }
.tdk-res-abrir-celula .tdk-abrir { opacity: 0; transform: translateX(-6px); transition: opacity 0.2s ease, transform 0.25s var(--tdk-saida), color var(--tdk-trans); }
.tdk-res-tabela tr.tdk-cartao-link:hover .tdk-abrir,
.tdk-res-tabela tr.tdk-cartao-link:focus-within .tdk-abrir { opacity: 1; transform: none; color: var(--tdk-text); }
.tdk-res-tabela tr.tdk-cartao-link:has(.tdk-link-esticado:focus-visible) { outline: none; }
.tdk-res-tabela tr.tdk-cartao-link:has(.tdk-link-esticado:focus-visible) > :first-child { box-shadow: inset 2px 0 0 var(--tdk-accent); }

/* R2 · As pílulas respondem ao toque; a tela troca no lugar enquanto espera. */
.tdk-res-pilula { transition: border-color var(--tdk-trans), color var(--tdk-trans), background var(--tdk-trans), transform 0.16s var(--tdk-saida); }
.tdk-res-pilula:not(.is-inerte):active { transform: scale(0.96); }
.tdk-main[aria-busy="true"] { cursor: progress; }

/* O que mudou na troca no lugar (R11) pisca uma vez no azul, e só ele. */
.tdk-mudou { animation: tdk-mudou 0.7s var(--tdk-saida); }
@keyframes tdk-mudou { from { opacity: 0.15; color: var(--tdk-accent); } }

/* R3 · O convite enviado, no lugar do botão. */
.tdk-chamado {
  display: inline-flex;
  align-items: center;
  gap: var(--tdk-sp-2);
  min-height: 32px;
  padding: 0 var(--tdk-sp-3);
  border: 1px solid rgba(111, 227, 192, 0.45);
  border-radius: var(--tdk-radius);
  background: var(--tdk-success-soft);
  color: var(--tdk-ok);
  font-size: var(--tdk-fs-xs);
  font-weight: var(--tdk-fw-semi);
  white-space: nowrap;
  animation: tdk-pulo 0.45s var(--tdk-mola);
}
.tdk-chamado .tdk-visto { width: 12px; height: 12px; flex: none; }

/* R4 · A planilha: "Gerando planilha…" com o giro, e depois o visto. O giro do
   botão claro é escuro; o do secundário, claro. */
.tdk-btn--secundario .tdk-gira,
.tdk-btn--sutil .tdk-gira { border-color: rgba(232, 236, 242, 0.25); border-top-color: currentColor; }
.tdk-btn.is-gerando { cursor: progress; }
.tdk-btn.is-baixada { color: var(--tdk-ok); border-color: rgba(111, 227, 192, 0.5); background: var(--tdk-success-soft); }
.tdk-btn.is-baixada .tdk-visto { width: 16px; height: 16px; }

/* R5 · A dica da barra: um balão só, posto no <body> pelo movimento.js. */
.tdk-dica-flutua {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 60;
  padding: var(--tdk-sp-1) var(--tdk-sp-2);
  border: 1px solid var(--tdk-border-hi);
  border-radius: 8px;
  background: var(--tdk-surface-2);
  color: var(--tdk-text);
  font-size: 11.5px;
  font-weight: var(--tdk-fw-medium);
  line-height: 18px;
  white-space: nowrap;
  pointer-events: none;
  box-shadow: 0 10px 24px -12px rgba(0, 0, 0, 0.8);
  opacity: 0;
  transform: translate(-50%, calc(-100% - 4px));
  transition: opacity 0.15s ease, transform 0.2s var(--tdk-saida);
}
.tdk-dica-flutua.is-visivel { opacity: 1; transform: translate(-50%, calc(-100% - 8px)); }
.tdk-res-coluna:hover > span { filter: brightness(1.3); }

/* R7 · O histograma sobe de baixo, coluna a coluna, e a linha do mínimo se desenha
   de cima a baixo depois. */
.tdk-res-coluna > span {
  animation: tdk-sobe 0.8s cubic-bezier(0.22, 1, 0.36, 1) calc(150ms + var(--coluna, 0) * 45ms) backwards;
  transition: height 0.6s var(--tdk-saida), filter var(--tdk-trans);
}
.tdk-res-coluna:nth-child(2) { --coluna: 1; }
.tdk-res-coluna:nth-child(3) { --coluna: 2; }
.tdk-res-coluna:nth-child(4) { --coluna: 3; }
.tdk-res-coluna:nth-child(5) { --coluna: 4; }
.tdk-res-coluna:nth-child(6) { --coluna: 5; }
.tdk-res-coluna:nth-child(7) { --coluna: 6; }
.tdk-res-coluna:nth-child(8) { --coluna: 7; }
.tdk-res-coluna:nth-child(9) { --coluna: 8; }
.tdk-res-coluna:nth-child(10) { --coluna: 9; }
@keyframes tdk-sobe { from { height: 0; } }

.tdk-res-minimo { animation: tdk-desenha 0.8s cubic-bezier(0.65, 0, 0.35, 1) 1.1s backwards; }
@keyframes tdk-desenha { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0 0 0 0); } }

/* Aula a aula: a da maior queda ganha o marcador âmbar, que chega depois das barras. */
.tdk-res-aula.is-queda .tdk-res-aula-titulo::before {
  content: "";
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 8px;
  border-radius: 50%;
  background: var(--tdk-warn);
  box-shadow: 0 0 0 3px rgba(245, 194, 107, 0.18);
  vertical-align: 1px;
  animation: tdk-pulo 0.5s var(--tdk-mola) 1.6s both;
}

/* R9 · O cabeçalho gruda no topo ao rolar uma lista longa. Só quando a tabela cabe
   na largura: o `overflow-x` que rola a tabela larga prenderia o cabeçalho na
   caixa dela, e é o movimento.js quem confere se cabe (`.is-gruda`). Aí a caixa
   deixa de cortar, e quem arredonda os cantos é a própria tabela, por `clip-path`.
   `overflow: clip` parecia o caminho curto e não serve: com ele o Chrome deixou de
   pintar as linhas abaixo da dobra (medido em 09/10/2026, Pessoas com 12 linhas:
   da 4ª em diante, vazias). Dentro de cartão o cabeçalho é transparente, e grudado
   ele precisa do fundo do cartão. No celular a barra do topo não gruda, e isto
   também não. */
@media (min-width: 881px) {
  .tdk-res-gruda.is-gruda { overflow: visible; }
  .tdk-res-gruda.is-gruda > table { clip-path: inset(0 round calc(var(--tdk-radius) - 1px)); }
  .tdk-res-gruda.is-gruda thead th {
    position: sticky;
    top: var(--tdk-topo-h, 56px);
    z-index: 3;
    box-shadow: inset 0 -1px 0 var(--tdk-border);
  }
  .tdk-card .tdk-res-gruda.is-gruda thead th { background: var(--tdk-surface); }
}

/* R10 · A barra do seu setor enche e, depois, o traço da média da empresa desce e
   pousa nela, com o rótulo em cima. */
.tdk-emp-media { animation: tdk-pousa 0.55s var(--tdk-mola) 1.35s backwards; transform-origin: bottom; }
@keyframes tdk-pousa { from { opacity: 0; transform: translateY(-16px) scaleY(0.4); } }
.tdk-emp-media-rotulo { animation: tdk-rotulo-pousa 0.4s var(--tdk-saida) 1.7s backwards; }
@keyframes tdk-rotulo-pousa { from { opacity: 0; transform: translate(-50%, 4px); } }


/* ── A sanfona dos capítulos (ticket 56) ──────────────────────────────────────
   O capítulo abre e fecha deslizando, e a seta gira com mola. `::details-content` e
   `interpolate-size` são do Chrome 131 em diante; em navegador sem eles o capítulo só
   abre e fecha, seco — nada some. */
.tdk-capitulos { interpolate-size: allow-keywords; }
.tdk-capitulo::details-content {
  block-size: 0;
  overflow: hidden;
  transition: block-size 0.35s var(--tdk-saida), content-visibility 0.35s allow-discrete;
}
.tdk-capitulo[open]::details-content { block-size: auto; }
.tdk-capitulo-seta { transition: transform 0.3s var(--tdk-mola), color var(--tdk-trans); }

/* O aviso da prova que ainda não abriu (ticket 56) entra subindo, como o dos 70%. */
.tdk-modal[open] .tdk-modal-acoes .tdk-btn--primario { animation: tdk-entrar 0.4s var(--tdk-saida) 0.15s both; }


/* ── Menos movimento: nada se mexe, nada some ─────────────────────────────────
   O mesmo ajuste do Windows ("Efeitos de animação") que já desligava a primeira
   camada. Tudo o que é conteúdo chega pronto: os números já são os do servidor, o
   título já está lá, o visto já está desenhado. O que é só enfeite em laço some. */
@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }

  .tdk-feixe,
  .tdk-confete,
  .tdk-ambiente,
  .tdk-entrada-aurora,
  .tdk-entrada-grade-acesa,
  .tdk-entrada-emblema::after,
  .tdk-nav-fantasma,
  .tdk-btn--primario::before,
  .tdk-progresso-preenche::after,
  .tdk-res-barra > span::after { display: none; }

  .tdk-aqui::after,
  .tdk-pulso-vivo::after,
  .tdk-alternativa-letra::after { animation: none; opacity: 0; }

  .tdk-palavra,
  .tdk-grifo::after,
  .tdk-saudacao-titulo strong::after,
  .tdk-visto polyline,
  .tdk-visto path,
  .tdk-surge,
  .tdk-sino-ponto,
  .tdk-sino:hover svg,
  .tdk-btn:hover .tdk-desce,
  .tdk-nega,
  .tdk-dica-trancada,
  .tdk-alternativa:has(input:checked) .tdk-alternativa-letra,
  .tdk-cronometro.is-perto,
  .tdk-anel .tdk-anel-arco,
  .tdk-aula-rail,
  .tdk-conclusao.is-concluida [data-conclusao-seguir],
  .tdk-rail-aulas > li.is-destrancada .tdk-rail-marca,
  .tdk-a-seguir,
  .tdk-cursos--linha-do-tempo .tdk-curso-linha.is-percorrido::after,
  .tdk-questoes > *,
  .tdk-chips > *,
  .tdk-entrada-caixa > *,
  .tdk-entrada-emblema,
  .tdk-entrada-fatos > *,
  .tdk-caps,
  .tdk-gira,
  .tdk-cascata > *,
  .tdk-res-barra > span,
  .tdk-res-pilha > span,
  .tdk-res-coluna > span,
  .tdk-res-minimo,
  .tdk-res-aula.is-queda .tdk-res-aula-titulo::before,
  .tdk-emp-media,
  .tdk-emp-media-rotulo,
  .tdk-chamado,
  .tdk-mudou,
  .tdk-modal[open] .tdk-modal-acoes .tdk-btn--primario { animation: none; }

  .tdk-capitulo::details-content,
  .tdk-capitulo-seta { transition: none; }

  .tdk-caixinha polyline,
  .tdk-entrada .tdk-campo-controle,
  .tdk-entrada-linha a::after,
  .tdk-aba::after,
  .tdk-res-barra > span,
  .tdk-res-pilha > span,
  .tdk-res-coluna > span,
  .tdk-res-abrir-celula .tdk-abrir,
  .tdk-dica-flutua { transition: none; }

  .tdk-res-pilula:active { transform: none; }

  .tdk-grifo::after,
  .tdk-saudacao-titulo strong::after { transform: scaleX(1); }
  .tdk-visto polyline,
  .tdk-visto path { stroke-dashoffset: 0; }

  html.tdk-mov .tdk-luz:hover,
  html.tdk-mov .tdk-luz:active,
  .tdk-btn:active,
  .tdk-alternativa:hover,
  .tdk-prova-passo:hover,
  .tdk-lista-aulas a:hover,
  .tdk-nav-item:hover svg:not(.tdk-nav-seta),
  .tdk-cursos--linha-do-tempo .tdk-curso-linha:hover .tdk-curso-marca,
  [data-inclina] { transform: none; }

  .tdk-btn:hover .tdk-seta,
  .tdk-link-seta:hover .tdk-seta,
  .tdk-cartao-link:hover .tdk-abrir svg,
  .tdk-pessoal-botao:hover .tdk-pessoal-seta { transform: none; }

  .tdk-lista-aulas-play,
  .tdk-lista-aulas-acao { transition: none; }
}
