/* xCast App Multi-Plataforma — camada de ESTADOS e micro-interacoes.
 * Usada pelos modelos 10, 23, 24, 25 (plantas novas) e 26, 27, 28.
 *
 * CONTRATO GENERICO (adotado pelas plantas de 2026-08-02): em vez de repetir
 * seletor por skin (.e6-play, .o7-play, .p8-play...), a skin nova marca o papel
 * do elemento com uma classe ax-*:
 *   .ax-play     botao de play que fica NO FLUXO  -> spinner ao conectar + halo tocando
 *   .ax-play-abs botao de play POSICIONADO (absolute/translate) -> so spinner, sem
 *                mexer em position (foi o que tirou o losango do 28 do lugar)
 *   .ax-navic    item de barra/menu -> neutro em repouso, accent quando e a aba aberta
 *   .ax-bar      barra que hospeda a pilula deslizante  (.ax-scroll se rolar)
 *   .ax-stagger  container cujos filhos sobem em escalonamento na abertura
 * Assim uma planta nova nasce com todos os estados sem tocar neste arquivo.
 *
 * O motor (p2/xc-core.js) ja publica os estados na raiz [data-xc-player]:
 *   .xc-loading  conectando/buffer   .xc-playing  tocando   .xc-paused  parado
 *   .xc-active   reacao votada       .xc-pop      reacao acabou de ser tocada
 * ...e escreve "Conectando... / No ar / Parado" em [data-xc-status].
 * Ate aqui as skins so liam .xc-playing. Este arquivo da FORMA VISUAL a cada estado.
 *
 * Regras seguidas: sem `transition: all`; saida ~75% da entrada; nada anima acima de
 * 400ms; tudo em transform/opacity (GPU); prefers-reduced-motion honrado no fim.
 */

:root{
  --ux-rapido:120ms; --ux-medio:220ms; --ux-lento:300ms;
  --ux-saida:165ms;               /* ~75% de --ux-medio */
  --ux-ease:cubic-bezier(.22,.61,.36,1);
}

/* ---------------------------------------------- 0. COR DO TEXTO (tema claro)
   🚨 O xc-core.css declara `color` no PROPRIO [data-xc-player]. Como a raiz da skin
   tem esse atributo, ela vence o `body` e o texto continuava BRANCO mesmo com o
   tema claro resolvido (--xt-texto ja era escuro). Era esta a causa do titulo
   ilegivel em fundo claro. Mesmo gotcha ja documentado no modelo 8 "Claro".
   Este arquivo carrega DEPOIS do xc-core.css, entao a declaracao abaixo ganha. */
[data-xc-player]{ color:var(--xt-texto, #fff); }

/* --------------------------------------------- 0b. O PLAY NUNCA PODE ENCOLHER
   🚨 O play e um item flex com largura/altura fixas, mas sem `flex:none` ele cede
   largura antes de todo mundo quando a linha aperta: a altura fica, a largura cai e
   o circulo VIRA ELIPSE. Aconteceu nos layouts 07 e 09 a 300-320px (49x70 e 49x72).
   Uma linha aqui protege todas as skins que carregam este arquivo — inclusive as
   futuras. Nas skins antigas que nao o carregam, o `flex:none` foi para o proprio CSS. */
[data-xc-player] [data-xc-play]{ flex:none; }

/* ------------------------------------------------------------------ 1. TOQUE
   Feedback imediato: o dedo cobre o alvo, entao a resposta precisa ser rapida. */
[data-xc-player] button,
[data-xc-player] a{ transition:transform var(--ux-rapido) var(--ux-ease),
                               background-color var(--ux-rapido) linear,
                               border-color var(--ux-rapido) linear,
                               opacity var(--ux-rapido) linear; }
[data-xc-player] button:active,
[data-xc-player] a:active{ transform:scale(.94); }
/* o play tem transform proprio (centralizacao/rotacao) — cada skin trata o :active */
[data-xc-player] .p8-play:active,
[data-xc-player] .o7-play:active,
[data-xc-player] .e6-play:active{ transform:none; }
.e6-play:active{ transform:scale(.93) !important; }
.o7-play:active{ transform:translate(-50%,-50%) scale(.93) !important; }
.p8-play:active{ transform:translateX(-50%) rotate(45deg) scale(.93) !important; }
/* plantas novas: o play no fluxo encolhe; o posicionado guarda o proprio transform
   na variavel --ax-tf, entao o :active nao apaga a centralizacao dele */
[data-xc-player] .ax-play:active{ transform:scale(.93) !important; }
[data-xc-player] .ax-play-abs:active{ transform:var(--ax-tf, none) scale(.93) !important; }

/* ------------------------------------------------- 2. CONECTANDO (.xc-loading)
   O estado que faltava: entre apertar play e o som sair existe um vazio de 1-4s.
   Anel girando ao redor do proprio botao — o feedback nasce de onde veio o toque. */
/* 🚨 SO os plays que ficam no FLUXO recebem position:relative (para os pseudo-elementos
   de spinner/halo ancorarem neles). O .o7-play e o .p8-play ja sao position:absolute
   com left/top/bottom proprios — sobrescrever a posicao deles os TIRA DO LUGAR
   (o losango do modelo 28 caiu em cima do "Tocando agora"). */
.e6-play, .p8-barplay, .ax-play{ position:relative; }
.xc-loading .e6-play::after,
.xc-loading .o7-play::after,
.xc-loading .ax-play::after,
.xc-loading .ax-play-abs::after,
.xc-loading .p8-barplay::after{
  content:''; position:absolute; inset:-5px; border-radius:50%;
  border:2px solid transparent; border-top-color:currentColor; opacity:.9;
  animation:ux-spin .75s linear infinite; pointer-events:none;
}
.xc-loading .p8-play::after{
  content:''; position:absolute; inset:-5px; border-radius:20px;
  border:2px solid transparent; border-top-color:var(--ac); opacity:.9;
  animation:ux-spin .75s linear infinite; pointer-events:none;
}
@keyframes ux-spin{ to{ transform:rotate(360deg); } }
/* enquanto conecta, o icone respira de leve: diz "estamos indo", nao "travou" */
.xc-loading [data-xc-play] svg{ animation:ux-respira 1.4s ease-in-out infinite; }
@keyframes ux-respira{ 0%,100%{ opacity:1 } 50%{ opacity:.45 } }

/* --------------------------------------------- 3. TOCANDO: halo vivo no play
   Pulso lento (2.6s) — presenca sem competir com o conteudo. */
.xc-playing .e6-play::before,
.xc-playing .o7-play::before,
.xc-playing .ax-play::before,
.xc-playing .ax-play-abs::before{
  content:''; position:absolute; inset:0; border-radius:50%;
  box-shadow:0 0 0 0 color-mix(in srgb, var(--ac) 55%, transparent);
  animation:ux-halo 2.6s ease-out infinite; pointer-events:none;
}
/* play quadrado (planta "Trio"): spinner e halo acompanham a forma, nao o circulo */
.ax-play.ax-quadrado::after, .ax-play.ax-quadrado::before,
.ax-play-abs.ax-quadrado::after, .ax-play-abs.ax-quadrado::before{ border-radius:var(--ax-raio-play, 22px) !important; }
@keyframes ux-halo{
  0%  { box-shadow:0 0 0 0 color-mix(in srgb, var(--ac) 50%, transparent); }
  70% { box-shadow:0 0 0 16px transparent; }
  100%{ box-shadow:0 0 0 0 transparent; }
}
/* o play do "Palco" e um losango: o halo acompanha a forma, com o mesmo ritmo */
.xc-playing .p8-play::before{
  content:''; position:absolute; inset:0; border-radius:18px;
  box-shadow:0 0 0 0 rgba(255,255,255,.5);
  animation:ux-halo-losango 2.6s ease-out infinite; pointer-events:none;
}
@keyframes ux-halo-losango{
  0%  { box-shadow:0 0 0 0 rgba(255,255,255,.45); }
  70% { box-shadow:0 0 0 14px transparent; }
  100%{ box-shadow:0 0 0 0 transparent; }
}

/* ------------------------------------- 4. SELO "NO AR" = equalizer de 3 barras
   Detalhe caracteristico das 3 skins: em vez do ponto pulsante generico, o selo
   VIRA audio. Parado = 3 barras baixas e imoveis; tocando = elas dancam.
   Sem tocar no HTML: o proprio .dot e a barra do meio, ::before/::after as laterais. */
[data-xc-player] .dot{
  position:relative; width:3px !important; height:11px !important;
  border-radius:2px !important; animation:none !important;
  /* as barras laterais moram em ::before/::after, FORA da caixa de 3px —
     a margem reserva o espaco delas para nao encostarem no texto ao lado */
  margin:0 6px !important; flex:none;
  transition:height var(--ux-medio) var(--ux-ease); transform-origin:center bottom;
}
[data-xc-player] .dot::before,
[data-xc-player] .dot::after{
  content:''; position:absolute; bottom:0; width:3px; height:6px;
  border-radius:2px; background:currentColor; opacity:.85;
}
[data-xc-player] .dot::before{ left:-5px; }
[data-xc-player] .dot::after { left:5px; }
.xc-playing .dot            { animation:ux-eq1 .9s ease-in-out infinite !important; }
.xc-playing .dot::before    { animation:ux-eq2 .7s ease-in-out infinite; }
.xc-playing .dot::after     { animation:ux-eq3 1.1s ease-in-out infinite; }
@keyframes ux-eq1{ 0%,100%{ height:11px } 50%{ height:4px } }
@keyframes ux-eq2{ 0%,100%{ height:5px }  50%{ height:12px } }
@keyframes ux-eq3{ 0%,100%{ height:9px }  50%{ height:3px } }

/* ---------------------------------------------- 5. TROCA DE FAIXA (crossfade)
   Sem isso o titulo "salta" de uma musica para outra. app-ux.js poe .ux-troca
   quando o texto muda; a saida e mais curta que a entrada. */
[data-xc-title], [data-xc-artist]{
  transition:opacity var(--ux-medio) var(--ux-ease), transform var(--ux-medio) var(--ux-ease);
}
.ux-troca [data-xc-title], .ux-troca [data-xc-artist]{
  opacity:0; transform:translateY(6px); transition-duration:var(--ux-saida);
}
[data-xc-cover]{ transition:opacity var(--ux-lento) var(--ux-ease); }
.ux-capa-trocando [data-xc-cover]{ opacity:.25; transition-duration:var(--ux-saida); }
/* capa ainda carregando: brilho passando, em vez de retangulo morto */
[data-xc-cover].ux-carregando{
  background-image:linear-gradient(100deg, rgba(255,255,255,.04) 30%, rgba(255,255,255,.14) 50%, rgba(255,255,255,.04) 70%);
  background-size:220% 100%; animation:ux-brilho 1.4s linear infinite;
}
@keyframes ux-brilho{ to{ background-position:-220% 0; } }

/* --------------------------------------------------- 6. TROCA DE PAGINA (aba)
   240ms: acima do limiar de "instantaneo", abaixo do de "lento". */
.a6-page.on{ animation:ux-pagina var(--ux-medio) var(--ux-ease); }
@keyframes ux-pagina{ from{ opacity:0; transform:translateY(10px); } to{ opacity:1; transform:none; } }
.ax-back{ transition:opacity var(--ux-rapido) linear, transform var(--ux-rapido) var(--ux-ease); }
body.ax-interna .ax-back{ animation:ux-pagina var(--ux-medio) var(--ux-ease); }

/* ------------------------------------------- 7. ENTRADA DOS ATALHOS (one-time)
   Acontece uma vez por abertura — pode ser um pouco mais expressivo. */
.e6-grade > *, .o7-extra > *, .p8-scroll > *, .ax-stagger > *{
  animation:ux-sobe 380ms var(--ux-ease) backwards;
}
.o7-orb .o7-ic{ animation:ux-orbita 460ms var(--ux-ease) backwards; }
@keyframes ux-sobe  { from{ opacity:0; transform:translateY(10px); } }
@keyframes ux-orbita{ from{ opacity:0; } }
/* escalonamento curto: passa dos 10 itens vira espera, nao charme */
.e6-grade > *:nth-child(1),.o7-extra > *:nth-child(1),.p8-scroll > *:nth-child(1),.ax-stagger > *:nth-child(1),.o7-orb .o7-ic:nth-of-type(1){ animation-delay:30ms }
.e6-grade > *:nth-child(2),.o7-extra > *:nth-child(2),.p8-scroll > *:nth-child(2),.ax-stagger > *:nth-child(2),.o7-orb .o7-ic:nth-of-type(2){ animation-delay:60ms }
.e6-grade > *:nth-child(3),.o7-extra > *:nth-child(3),.p8-scroll > *:nth-child(3),.ax-stagger > *:nth-child(3),.o7-orb .o7-ic:nth-of-type(3){ animation-delay:90ms }
.e6-grade > *:nth-child(4),.o7-extra > *:nth-child(4),.p8-scroll > *:nth-child(4),.ax-stagger > *:nth-child(4),.o7-orb .o7-ic:nth-of-type(4){ animation-delay:120ms }
.e6-grade > *:nth-child(5),.o7-extra > *:nth-child(5),.p8-scroll > *:nth-child(5),.ax-stagger > *:nth-child(5),.o7-orb .o7-ic:nth-of-type(5){ animation-delay:150ms }
.e6-grade > *:nth-child(6),.o7-extra > *:nth-child(6),.p8-scroll > *:nth-child(6),.ax-stagger > *:nth-child(6),.o7-orb .o7-ic:nth-of-type(6){ animation-delay:180ms }
.e6-grade > *:nth-child(n+7),.o7-extra > *:nth-child(n+7),.p8-scroll > *:nth-child(n+7),.ax-stagger > *:nth-child(n+7),.o7-orb .o7-ic:nth-of-type(n+7){ animation-delay:210ms }

/* ------------------------------------------------------------- 8. REACOES
   O motor ja poe .xc-pop no clique e .xc-active quando o voto esta registrado. */
[data-xc-player] [data-xc-like],
[data-xc-player] [data-xc-dislike],
[data-xc-player] [data-xc-reaction]{ transition:transform var(--ux-rapido) var(--ux-ease),
                                                background-color var(--ux-rapido) linear,
                                                border-color var(--ux-rapido) linear; }
[data-xc-player] .xc-pop{ animation:ux-pop 420ms var(--ux-ease); }
@keyframes ux-pop{ 0%{ transform:scale(1) } 35%{ transform:scale(1.18) } 100%{ transform:scale(1) } }
[data-xc-player] [data-xc-count]{ display:inline-block; transition:transform var(--ux-rapido) var(--ux-ease); }
[data-xc-player] .xc-pop [data-xc-count]{ transform:translateY(-2px); }

/* ------------------------------------------- 8b. "VOCE ESTA AQUI" (item ativo)
   Sem isto, abrir uma aba nao muda nada no menu — o app nao dizia onde voce esta.
   Regra de hierarquia: os itens em repouso ficam NEUTROS e so o ativo usa o accent.
   (Antes todos eram accent, entao nenhum se destacava.) */
.p8-ic, .ax-navic{ color:#8b93a4 !important; position:relative;
        transition:color var(--ux-medio) var(--ux-ease), transform var(--ux-rapido) var(--ux-ease); }
.p8-ic.ax-ativo, .ax-navic.ax-ativo{ color:var(--ac) !important; }
.p8-ic.ax-ativo .ax-ic, .ax-navic.ax-ativo .ax-ic{ transform:translateY(-1px); }

/* a pilula desliza ate o item aberto — o movimento e o que liga um menu ao outro */
.p8-bar, .ax-bar{ position:relative; }
.p8-ind{
  position:absolute; top:6px; left:0; height:44px; width:44px; border-radius:14px;
  background:color-mix(in srgb, var(--ac) 14%, transparent);
  border-bottom:3px solid var(--ac);
  transform:translateX(var(--ind-x, 0px)); opacity:0; pointer-events:none; z-index:0;
  transition:transform 300ms var(--ux-ease), width 300ms var(--ux-ease), opacity var(--ux-saida) linear;
}
.p8-bar.tem-ativo .p8-ind, .ax-bar.tem-ativo .p8-ind{ opacity:1; }
.p8-ic .ax-ic, .ax-navic .ax-ic{ position:relative; z-index:1; }

/* nas skins sem barra: o proprio icone marca que aquela aba esta aberta */
.e6-ic.ax-ativo, .o7-ic.ax-ativo, .ax-ativo.ax-anel{ box-shadow:0 0 0 3px color-mix(in srgb, var(--ac) 45%, transparent); }
.e6-sec.ax-ativo{ color:#fff !important; background:var(--ac) !important; }

/* -------------------------------------------------- 9. ACESSIBILIDADE (piso)
   Foco visivel para quem navega por teclado (TV, Windows, leitor de tela) e
   alvo de toque nunca menor que 44px — mesmo nas telas estreitas. */
[data-xc-player] button:focus-visible,
[data-xc-player] a:focus-visible,
.ax-back:focus-visible{
  outline:2px solid var(--ac); outline-offset:3px; border-radius:14px;
}
[data-xc-player] .e6-ic, [data-xc-player] .e6-sec,
[data-xc-player] .o7-ic, [data-xc-player] .p8-ic,
[data-xc-player] .ax-navic, [data-xc-player] .ax-alvo{ min-width:44px; min-height:44px; }
/* as reacoes sao alvo de toque como qualquer outro: o pill era ~30px de altura */
[data-xc-player] .e6-react button,
[data-xc-player] .o7-react button,
[data-xc-player] .p8-react button,
[data-xc-player] .ax-react button{ min-height:44px; padding-top:0; padding-bottom:0; }
[data-xc-player] .ax-wa:focus-visible{ outline:2px solid #fff; outline-offset:-3px; }

/* ------------------------------------------- 10. MOVIMENTO REDUZIDO (respeito)
   Quem pediu menos movimento continua recebendo TODA a informacao de estado —
   o equalizer para em barras estaticas, o spinner vira pulso de opacidade. */
@media (prefers-reduced-motion: reduce){
  [data-xc-player] *,
  [data-xc-player] *::before,
  [data-xc-player] *::after{
    animation-duration:.01ms !important; animation-iteration-count:1 !important;
    transition-duration:.01ms !important; scroll-behavior:auto !important;
  }
  .xc-loading .e6-play::after, .xc-loading .o7-play::after,
  .xc-loading .p8-play::after, .xc-loading .p8-barplay::after,
  .xc-loading .ax-play::after, .xc-loading .ax-play-abs::after{ display:none; }
  .xc-loading [data-xc-play] svg{ opacity:.55; }
  .xc-playing .dot, .xc-playing .dot::before, .xc-playing .dot::after{ animation:none !important; }
  .xc-playing .dot{ height:11px !important; }
}
