/* ============================================================
   PSICOLOGIA PRETA — DESIGN SYSTEM · base.css
   ------------------------------------------------------------
   Reset, tipografia base, primitivas de layout, o campo de luz
   (#lightfield/#glcanvas/vinheta), e as regras de movimento
   (arrive/breathe + reduced-motion). Comum aos 4 tipos de página.
   Todas as cores vêm de tokens.css (nenhuma cor hard-coded aqui).

   ORDEM DE @layer (declarada uma vez, aqui): tokens vem de
   tokens.css; este arquivo cobre base, light, motion, layout.
   components.css cobre components. Cada template pode acrescentar
   sua própria camada de página DEPOIS de components no cascade.
   ============================================================ */
@layer tokens, base, light, motion, layout, components, page, util;

@layer base {
  *,*::before,*::after{box-sizing:border-box;margin:0;padding:0;}
  html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;}
  body{
    background:var(--bg);
    color:var(--ink);
    font-family:var(--f-sans);
    font-size:var(--fs-body); line-height:1.62; font-weight:380;
    font-optical-sizing:auto;
    -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
    overflow-x:hidden;
    /* transição de tema: cor do chão E da tinta trocam suaves no toggle */
    transition:background-color .9s linear, color .6s linear;
  }
  /* CORREÇÃO DE OVERFLOW MOBILE: toda fala quebra, nada estoura à direita */
  p,h1,h2,h3,h4,li,span,a,label,legend,blockquote,figcaption{
    overflow-wrap:break-word;word-break:normal;hyphens:none;}
  a{color:inherit;text-decoration:none;}
  button,input,select,textarea{font:inherit;color:inherit;}
  button{background:none;border:none;cursor:pointer;}
  img{max-width:100%;display:block;}
  ::selection{background:var(--honey-wash);color:var(--ink);}
  :focus-visible{outline:2.5px solid var(--honey);outline-offset:3px;border-radius:3px;}

  /* títulos: a MESMA grotesca, só peso/largura/óptico mudam (sem itálico-serif de acento) */
  h1,h2,h3{font-family:var(--f-sans);font-weight:600;line-height:1.03;letter-spacing:-.02em;
    font-stretch:88%;}

  /* a voz baixa do registro — metadado/coordenada em mono, instrumental */
  .coord{font-family:var(--f-mono);font-size:var(--fs-mono);letter-spacing:.16em;
    text-transform:uppercase;color:var(--ink-dim);font-weight:400;overflow-wrap:anywhere;}
  .coord b{color:var(--honey);font-weight:500;}
  @media(min-width:560px){.coord{letter-spacing:.22em;}}

  /* skip-link a11y — primeiro tabbable, salta para o conteúdo */
  .skip{position:absolute;left:-9999px;top:0;background:var(--honey);color:var(--skip-ink);
    padding:13px 18px;z-index:999;font-family:var(--f-mono);font-weight:500;border-radius:0 0 6px 0;}
  .skip:focus{left:0;top:0;}
}

@layer light {
  /* O CAMPO DE LUZ: canvas WebGL atrás de tudo (lightfield.js), lâmpada
     quente que floresce na terra. Se WebGL falhar, o gradiente do
     #lightfield cobre a MESMA terra — nunca fica plano nem frio. */
  #lightfield{position:fixed;inset:0;z-index:-2;pointer-events:none;
    background:
      radial-gradient(120% 95% at 50% -8%, var(--bg-warm), transparent 58%),
      radial-gradient(85% 70% at 78% 4%, var(--honey-wash), transparent 52%),
      var(--bg);
    opacity:1;transition:opacity 1s ease;}
  #glcanvas{position:fixed;inset:0;z-index:-1;width:100%;height:100%;
    pointer-events:none;display:block;opacity:0;transition:opacity 1.4s ease;mix-blend-mode:screen;}
  #glcanvas.on{opacity:1;}
  /* véu: vinheta que segura o cômodo nas bordas, sem grão sintético.
     No night escurece de leve (multiply); no day clareia de leve (normal). */
  body::after{content:'';position:fixed;inset:0;z-index:-1;pointer-events:none;
    background:radial-gradient(135% 115% at 50% 6%, transparent 52%, var(--vignette));}
  [data-theme="night"] body::after{mix-blend-mode:multiply;}
  [data-theme="day"] body::after{mix-blend-mode:normal;
    background:radial-gradient(135% 115% at 50% 4%, transparent 58%, var(--vignette));}
  /* No DAY o shader fica MUITO sutil (glow leve), nunca um efeito pesado sob o texto */
  [data-theme="day"] #glcanvas{opacity:0 !important;}
  [data-theme="day"] #glcanvas.on{opacity:.32 !important;mix-blend-mode:multiply;}
}

@layer motion {
  /* a fala que CHEGA — linha por linha, gentil.
     AT-REST VISÍVEL: sem JS/sem scroll, .ln > span fica legível (opacity:1).
     Só quando JS confirma capacidade de animar (html.js-anim) a fala parte de baixo. */
  .arrive .ln{display:block;overflow:hidden;}
  .arrive .ln > span{display:block;}
  html.js-anim .arrive .ln > span{transform:translateY(112%);opacity:0;
    transition:transform .92s var(--ease-soft), opacity .92s var(--ease);}
  html.js-anim .arrive.is-in .ln > span{transform:none;opacity:1;}
  html.js-anim .arrive.is-in .ln:nth-child(2) > span{transition-delay:.10s;}
  html.js-anim .arrive.is-in .ln:nth-child(3) > span{transition-delay:.20s;}
  html.js-anim .arrive.is-in .ln:nth-child(4) > span{transition-delay:.30s;}
  html.js-anim .arrive.is-in .ln:nth-child(5) > span{transition-delay:.40s;}

  /* subir suave — AT-REST VISÍVEL: só esconde quando JS pode revelar */
  html.js-anim .breathe{opacity:0;transform:translateY(22px);
    transition:opacity .9s var(--ease), transform .9s var(--ease-soft);}
  html.js-anim .breathe.is-in{opacity:1;transform:none;}
  .d1{transition-delay:.08s;}.d2{transition-delay:.16s;}.d3{transition-delay:.24s;}
  .d4{transition-delay:.32s;}.d5{transition-delay:.40s;}

  @keyframes emberPulse{0%,100%{opacity:.55;}50%{opacity:1;}}
  @keyframes softDrop{0%{transform:translateY(-90%);}60%,100%{transform:translateY(120%);}}

  /* a11y: reduced-motion desliga TUDO, mas nada some — o estático segura o calor */
  @media(prefers-reduced-motion:reduce){
    *,*::before,*::after{animation:none!important;transition:none!important;scroll-behavior:auto!important;}
    html.js-anim .arrive .ln > span,html.js-anim .breathe{opacity:1!important;transform:none!important;}
    #glcanvas{display:none!important;}
    #lightfield{opacity:1!important;}
    .scroll-cue{display:none!important;}
    body{transition:none!important;}
  }
}

@layer layout {
  .wrap{max-width:var(--wrap);margin:0 auto;padding:0 var(--pad);width:100%;}
  .section{padding:var(--section-py) 0;position:relative;}
}

@layer util{
  [hidden]{display:none!important;}
  .vh{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;}
}

/* ============================================================
   LUZ QUE AQUECE NO SCROLL — CSS scroll-driven nativo.
   @property --warm anima de 0 -> 1 conforme a página desce.
   Onde houver suporte, é nativo (sem JS). theme.js traz o
   fallback em JS p/ navegadores sem animation-timeline.
   (Fora de @layer de propósito: regra de animação global.)
   ------------------------------------------------------------
   O animation-range varia por densidade de página: a home/artigo
   (12vw section-py) aquece em 0%..78%; o app (form curto) em
   0%..60%. O template pode redeclarar este bloco se quiser outro
   range; o default abaixo (78%) serve home/categoria/artigo.
   ============================================================ */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    @keyframes warming { to { --warm: 1; } }
    html{
      animation: warming linear both;
      animation-timeline: scroll(root block);
      animation-range: 0% 78%;
    }
  }
}
