    /* Plus Jakarta Sans servida localmente (fonte variável), sem requisição externa. */
    @font-face {
      font-family: 'Plus Jakarta Sans';
      font-style: normal;
      font-weight: 200 500;
      font-display: swap;
      src: url('fonts/plus-jakarta-sans-latin-ext.woff2') format('woff2');
      unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
    }
    @font-face {
      font-family: 'Plus Jakarta Sans';
      font-style: normal;
      font-weight: 200 500;
      font-display: swap;
      src: url('fonts/plus-jakarta-sans-latin.woff2') format('woff2');
      unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
    }

    @font-face {
      font-family: 'Atkinson Hyperlegible Next';
      font-style: normal;
      font-weight: 200;
      font-display: swap;
      src: url('fonts/atkinson-200.woff2') format('woff2');
    }

    @font-face {
      font-family: 'Atkinson Hyperlegible Next';
      font-style: normal;
      font-weight: 300;
      font-display: swap;
      src: url('fonts/atkinson-300.woff2') format('woff2');
    }

    @font-face {
      font-family: 'Atkinson Hyperlegible Next';
      font-style: normal;
      font-weight: 400;
      font-display: swap;
      src: url('fonts/atkinson-400.woff2') format('woff2');
    }

    @font-face {
      font-family: 'Atkinson Hyperlegible Next';
      font-style: normal;
      font-weight: 500;
      font-display: swap;
      src: url('fonts/atkinson-500.woff2') format('woff2');
    }

    @font-face {
      font-family: 'Atkinson Hyperlegible Next';
      font-style: italic;
      font-weight: 300;
      font-display: swap;
      src: url('fonts/atkinson-300-italic.woff2') format('woff2');
    }

    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      font-family: 'Atkinson Hyperlegible Next', 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
    }

    :root {
      color-scheme: dark;
      --bg-color: #2e2d2b;
      --text-main: #f1f5f9;
      --icon-color: #f1f5f9;
      --vignette-color: rgba(0, 0, 0, 0); /* Fundo 100% sólido e uniforme no modo escuro */
      --menu-bg: #262524;
      --menu-border: rgba(255, 255, 255, 0.12);
      --btn-ctrl-bg: rgba(255, 255, 255, 0.05);
      --btn-ctrl-border: rgba(255, 255, 255, 0.15);
      --view-bg: rgba(38, 37, 36, 0.86); /* Fundo das telas de conteúdo (ofuscado) */
      --blur-conteudo: 2.5px; /* Desfoque único do conteúdo (manifesto e janelas) */
      /* Recorte do fundo atrás do painel do menu aberto (mesmo mecanismo dos
         buracos dos ícones). O JS troca estas listas ao abrir/fechar o menu —
         o recorte é estático: rolar a lista não muda os limites do painel.
         --menu-holes usa coordenadas da viewport (para o .view-overlay, fixo);
         --menu-holes-doc usa coordenadas locais do .container, que rola. */
      --menu-holes: linear-gradient(#000 0 0);
      --menu-holes-doc: linear-gradient(#000 0 0);
      --menu-hole-gap: 6px;
      --menu-hole-blur: 5px;
      /* Polegar das barras de rolagem (segue o tema). */
      --scrollbar-thumb: rgba(255, 255, 255, 0.16);
      --scrollbar-thumb-hover: rgba(255, 255, 255, 0.35);
    }

    /* Tema claro concentrado no <html>: as variáveis são herdadas por todo o
       documento e a classe também deixa a barra de rolagem e os controles
       nativos (seta/resize) coerentes com o tema. O JS alterna a classe em
       <html> e <body>, então basta este seletor. */
    html.light-theme {
      color-scheme: light;
      --bg-color: #faf9f6;
      --text-main: #0f172a;
      --icon-color: #0f172a;
      --vignette-color: rgba(230, 229, 221, 0.4);
      --menu-bg: #ffffff;
      --menu-border: rgba(0, 0, 0, 0.12);
      --btn-ctrl-bg: rgba(0, 0, 0, 0.04);
      --btn-ctrl-border: rgba(0, 0, 0, 0.12);
      --view-bg: rgba(250, 249, 246, 0.88);
      --scrollbar-thumb: rgba(0, 0, 0, 0.16);
      --scrollbar-thumb-hover: rgba(0, 0, 0, 0.35);
    }

    /* Barras de rolagem seguem o tema, iguais em todo o site
       (WebKit/Blink usam os pseudo-elementos). */
    *::-webkit-scrollbar {
      width: 10px;
      height: 10px;
    }

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

    /* Sem as setas nativas da caixa de texto: fica igual à barra do site. */
    *::-webkit-scrollbar-button {
      display: none;
      width: 0;
      height: 0;
    }

    *::-webkit-scrollbar-corner {
      background: transparent;
    }

    *::-webkit-scrollbar-thumb {
      background: var(--scrollbar-thumb);
      border: 2px solid transparent;
      border-radius: 999px;
      background-clip: content-box;
    }

    *::-webkit-scrollbar-thumb:hover {
      background: var(--scrollbar-thumb-hover);
      background-clip: content-box;
    }

    /* Firefox: usa as propriedades padrão. O teste por `-moz-appearance` é
       exclusivo do Gecko (Blink/Safari não o reconhecem), ao contrário de
       `selector(::-webkit-scrollbar)`, que alguns motores parseiam sem de fato
       suportar e acabariam ficando com a barra nativa. */
    @supports (-moz-appearance: none) {
      * {
        scrollbar-width: thin;
        scrollbar-color: var(--scrollbar-thumb) transparent;
      }
    }

    body {
      background-color: var(--bg-color);
      color: var(--text-main);
      overflow-x: hidden;
      min-height: 100vh;
      min-height: 100dvh;
      transition: background-color 100ms cubic-bezier(0.333333, 0, 0.666667, 1),
                  color 100ms cubic-bezier(0.333333, 0, 0.666667, 1);
    }

    #bg-canvas, #grain-canvas {
      position: fixed;
      top: 0;
      left: 0;
      width: 100vw;
      height: 100vh;
      height: 100dvh;
      z-index: 0;
      pointer-events: none;
      transition: filter 320ms ease, opacity 320ms ease;
    }

    .vignette {
      position: fixed;
      top: 0;
      left: 0;
      width: 100vw;
      height: 100vh;
      height: 100dvh;
      z-index: 1;
      background: radial-gradient(circle at center, rgba(0,0,0,0) 40%, var(--vignette-color) 100%);
      pointer-events: none;
      transition: background 100ms cubic-bezier(0.333333, 0, 0.666667, 1),
                  opacity 320ms ease;
    }

    header {
      position: fixed;
      top: 48px;
      left: 48px;
      right: 48px;
      z-index: 10;
      display: flex;
      align-items: center;
      justify-content: space-between;
      pointer-events: none;
    }

    .logo-container {
      pointer-events: auto;
      position: relative;
      display: flex;
      align-items: center;
      justify-content: center;
      width: 38px;
      height: 38px;
      text-decoration: none;
      user-select: none;
      -webkit-user-select: none;
      -webkit-tap-highlight-color: transparent;
    }

    /* O logotipo não deve ficar marcado pelo foco do teclado (Tab) nem
       pelo clique do mouse: durante o jogo ele vira a nave e o realce
       atrapalha. */
    .logo-container:focus,
    .logo-container:focus-visible {
      outline: none;
    }

    .logo-svg {
      user-select: none;
      -webkit-user-select: none;
      pointer-events: none;
    }

    /* Tooltip do logotipo (canto superior esquerdo): para cima, como o do
       menu do topo, e centralizada em relação ao ícone. */
    .logo-container[data-tooltip]::after {
      content: attr(data-tooltip);
      position: absolute;
      bottom: calc(100% + 6px);
      left: 50%;
      font-size: 0.68rem;
      letter-spacing: 0.04em;
      color: var(--text-main);
      white-space: nowrap;
      pointer-events: none;
      opacity: 0;
      transform: translate(-50%, 3px);
      transition: opacity 0.3s ease, transform 0.3s ease;
    }

    @media (hover: hover) {
      .logo-container[data-tooltip]:hover::after,
      .logo-container[data-tooltip]:focus-visible::after {
        opacity: 0.6;
        transform: translate(-50%, 0);
      }
    }

    /* Menu aberto: o logotipo fica ofuscado, então o tooltip some junto. */
    body:is(.site-menu-open, .lang-menu-open) .logo-container[data-tooltip]:hover::after {
      opacity: 0;
    }

    .logo-svg {
      width: 19px;
      height: 19px;
      display: block;
      color: var(--icon-color);
      filter: drop-shadow(0 2px 8px rgba(0,0,0,0.2));
      transition: color 100ms cubic-bezier(0.333333, 0, 0.666667, 1);
    }

    .logo-svg path {
      transition: fill 100ms cubic-bezier(0.333333, 0, 0.666667, 1),
                  stroke 100ms cubic-bezier(0.333333, 0, 0.666667, 1);
    }

    .container {
      position: relative;
      z-index: 2;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      min-height: 100vh;
      min-height: 100dvh;
      text-align: center;
      padding: 0 24px;
      transition: filter 100ms ease, opacity 100ms ease;
    }

    h1 {
      font-size: clamp(2.2rem, 4.5vw, 4rem);
      font-weight: 500;
      letter-spacing: -0.02em;
      line-height: 1.25;
      white-space: pre-line;
      max-width: 1000px;
      color: var(--text-main);
      transition: color 100ms cubic-bezier(0.333333, 0, 0.666667, 1);
    }

    .translation {
      margin-top: 18px;
      font-size: clamp(0.85rem, 1.5vw, 1.1rem);
      font-style: italic;
      font-weight: 300;
      letter-spacing: 0.02em;
      line-height: 1.5;
      white-space: pre-line;
      max-width: 600px;
      color: var(--text-main);
      opacity: 0.65;
      transition: color 100ms cubic-bezier(0.333333, 0, 0.666667, 1);
    }

    .translation::before {
      content: "";
      display: block;
      width: 36px;
      height: 1px;
      margin: 0 auto 14px;
      background-color: currentColor;
      opacity: 0.45;
    }

    /* Aviso para quem navega sem JavaScript: só é renderizado nesse caso. */
    .noscript-aviso {
      margin-top: 28px;
      max-width: 560px;
      font-size: clamp(0.85rem, 1.5vw, 1rem);
      line-height: 1.5;
      color: var(--text-main);
      opacity: 0.85;
    }

    .noscript-aviso a {
      color: inherit;
      text-decoration: underline;
      text-underline-offset: 3px;
    }

    /* Telas de conteúdo (Sobre, Projetos, Publicações, Contato): abrem sobre o
       manifesto, sem trocar de página nem de endereço. O fundo animado
       continua no lugar, apenas ofuscado, para o texto ficar legível. */

    /* Fundo das telas de conteúdo: cor + desfoque ficam aqui, separados do
       conteúdo que rola. Como o recorte dos ícones vive no .view-overlay
       (acima), o fundo continua uniforme e não aparecem "buracos". */
    .view-backdrop {
      position: fixed;
      inset: 0;
      z-index: 4;
      pointer-events: none;
      opacity: 0;
      visibility: hidden;
      background: var(--view-bg);
      -webkit-backdrop-filter: blur(18px) saturate(1.05);
      backdrop-filter: blur(18px) saturate(1.05);
      transition: opacity 100ms ease, visibility 0s linear 100ms,
                  background 100ms cubic-bezier(0.333333, 0, 0.666667, 1);
    }

    body.view-open .view-backdrop {
      opacity: 1;
      visibility: visible;
      transition: opacity 100ms ease, visibility 0s,
                  background 100ms cubic-bezier(0.333333, 0, 0.666667, 1);
    }

    /* A moldura fica parada: é ela que carrega a máscara (recorte dos
       ícones). Quem rola é o .view-scroll interno. Se a máscara ficasse no
       próprio elemento que rola, em navegadores móveis ela anda junto com o
       conteúdo e o recorte "descola" dos ícones durante o toque. */
    .view-overlay {
      position: fixed;
      inset: 0;
      z-index: 5;
      overflow: hidden;
      opacity: 0;
      visibility: hidden;
      pointer-events: none;
      transition: opacity 100ms ease, filter 100ms ease,
                  visibility 0s linear 100ms;

      /* Recorte: o texto some por trás dos ícones (início, fechar, menu,
         tema e idioma). Só o conteúdo é recortado, então o fundo (pixels e
         luzes) segue aparecendo normalmente. O recorte é mais largo que o
         ícone, com uma borda suave pra não cortar o texto num círculo seco. */
      --vd-top: 48px;
      --vd-side: 48px;
      --vd-bottom: 48px;
      --hole: 26px;
      --hole-logo-x: calc(var(--vd-side) + 19px);
      --hole-close-x: calc(100% - var(--vd-side) - 69px);
      --hole-menu-x: calc(100% - var(--vd-side) - 19px);
      --hole-lang-x: calc(var(--vd-side) + 19px);
      --hole-top-y: calc(var(--vd-top) + 19px);
      --hole-bottom-y: calc(100% - var(--vd-bottom) - 19px);
      -webkit-mask-image:
        radial-gradient(circle var(--hole) at var(--hole-logo-x) var(--hole-top-y), transparent 0 72%, #000 100%),
        radial-gradient(circle var(--hole) at var(--hole-menu-x) var(--hole-top-y), transparent 0 72%, #000 100%),
        radial-gradient(circle var(--hole) at var(--hole-close-x) var(--hole-top-y), transparent 0 72%, #000 100%),
        radial-gradient(circle var(--hole) at var(--hole-lang-x) var(--hole-bottom-y), transparent 0 72%, #000 100%),
        radial-gradient(circle var(--hole) at var(--hole-menu-x) var(--hole-bottom-y), transparent 0 72%, #000 100%),
        var(--menu-holes);
      mask-image:
        radial-gradient(circle var(--hole) at var(--hole-logo-x) var(--hole-top-y), transparent 0 72%, #000 100%),
        radial-gradient(circle var(--hole) at var(--hole-menu-x) var(--hole-top-y), transparent 0 72%, #000 100%),
        radial-gradient(circle var(--hole) at var(--hole-close-x) var(--hole-top-y), transparent 0 72%, #000 100%),
        radial-gradient(circle var(--hole) at var(--hole-lang-x) var(--hole-bottom-y), transparent 0 72%, #000 100%),
        radial-gradient(circle var(--hole) at var(--hole-menu-x) var(--hole-bottom-y), transparent 0 72%, #000 100%),
        var(--menu-holes);
      -webkit-mask-repeat: no-repeat;
      mask-repeat: no-repeat;
      /* Cada camada é opaca por fora do seu buraco, então a interseção some
         apenas onde qualquer buraco cobre e buracos sobrepostos se somam (o
         xor/exclude antigo os cancelava, reabrindo o fundo atrás do menu). */
      -webkit-mask-composite: source-in;
      mask-composite: intersect;
    }

    /* Área rolável da tela de conteúdo. Fica dentro do .view-overlay para que
       a máscara (recorte dos ícones) permaneça fixa enquanto o texto rola. */
    .view-scroll {
      position: absolute;
      inset: 0;
      display: flex;
      justify-content: center;
      align-items: flex-start;
      padding: 108px 24px 110px;
      overflow-y: auto;
      overscroll-behavior: contain;
    }

    .view-overlay.active {
      opacity: 1;
      visibility: visible;
      pointer-events: auto;
      transition: opacity 100ms ease, filter 100ms ease, visibility 0s;
    }

    .view {
      position: relative;
      width: 100%;
      max-width: 720px;
      transform: translateY(12px);
      transition: transform 100ms cubic-bezier(0.22, 0.61, 0.36, 1);
    }

    .view-overlay.active .view {
      transform: none;
    }

    .view h2 {
      font-size: clamp(1.5rem, 3vw, 2.1rem);
      font-weight: 500;
      letter-spacing: -0.02em;
      line-height: 1.25;
      color: var(--text-main);
      transition: color 100ms cubic-bezier(0.333333, 0, 0.666667, 1);
    }

    /* Mesmo fio curto do manifesto, ligando as telas ao desenho do site. */
    .view h2::after {
      content: "";
      display: block;
      width: 36px;
      height: 1px;
      margin-top: 18px;
      background-color: currentColor;
      opacity: 0.45;
    }

    .view p.view-texto {
      margin-top: 22px;
      font-size: clamp(0.95rem, 1.6vw, 1.05rem);
      font-weight: 300;
      line-height: 1.7;
      max-width: 62ch;
      opacity: 0.85;
      color: var(--text-main);
      transition: color 100ms cubic-bezier(0.333333, 0, 0.666667, 1);
    }

    /* Tela Sobre: a largura da coluna fica no contêiner para que todos os
       parágrafos (inclusive a citação em negrito e a tradução em itálico)
       tenham a mesma largura e compartilhem o mesmo eixo central. */
    #sobre-texto {
      max-width: 62ch;
      font-size: clamp(0.95rem, 1.6vw, 1.05rem);
      font-weight: 300;
    }

    #sobre-texto .view-texto {
      max-width: none;
      text-align: justify;
    }

    #sobre-texto .view-citacao {
      margin-top: 22px;
      text-align: center;
      font-weight: 700;
      font-style: italic;
    }

    #sobre-texto .view-citacao-traducao {
      margin-top: 2px;
      text-align: center;
      font-style: italic;
      opacity: 0.7;
    }

    /* Barra de busca das telas com lista (Projetos, Publicações). */
    .view-search {
      width: 100%;
      margin-top: 28px;
      padding: 10px 34px 10px 14px;
      background: var(--btn-ctrl-bg);
      border: 1px solid var(--btn-ctrl-border);
      border-radius: 10px;
      color: var(--text-main);
      font-size: 0.95rem;
      font-weight: 300;
      transition: background 100ms cubic-bezier(0.333333, 0, 0.666667, 1),
                  border-color 100ms cubic-bezier(0.333333, 0, 0.666667, 1),
                  color 100ms cubic-bezier(0.333333, 0, 0.666667, 1);
    }

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

    /* "X" de limpar: mesmo traço e cor dos ícones do projeto (currentColor),
       sem o azul do controle nativo do navegador. */
    .view-search::-webkit-search-cancel-button {
      -webkit-appearance: none;
      appearance: none;
      width: 14px;
      height: 14px;
      margin-left: 8px;
      background-color: currentColor;
      opacity: 0.45;
      cursor: pointer;
      -webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='2.4'%20stroke-linecap='round'%3E%3Cpath%20d='M6%206l12%2012M18%206L6%2018'/%3E%3C/svg%3E") center / contain no-repeat;
      mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='2.4'%20stroke-linecap='round'%3E%3Cpath%20d='M6%206l12%2012M18%206L6%2018'/%3E%3C/svg%3E") center / contain no-repeat;
      transition: opacity 0.3s ease;
    }

    .view-search::-webkit-search-cancel-button:hover {
      opacity: 0.8;
    }

    .view-search::placeholder {
      color: currentColor;
      opacity: 0.45;
    }

    .view-search:focus-visible {
      outline: 1px solid var(--btn-ctrl-border);
      outline-offset: 2px;
    }

    /* Recado da tela: carregando, vazio, erro ou contagem de itens. */
    .view-status {
      margin-top: 26px;
      font-size: 0.85rem;
      font-weight: 300;
      line-height: 1.6;
      max-width: 62ch;
      opacity: 0.55;
      color: var(--text-main);
      transition: color 100ms cubic-bezier(0.333333, 0, 0.666667, 1);
    }

    .view-lista {
      list-style: none;
      margin-top: 10px;
    }

    .view-item {
      padding: 24px 0;
      border-top: 1px solid var(--menu-border);
    }

    .view-item:last-child {
      border-bottom: 1px solid var(--menu-border);
    }

    /* Contato: o rótulo do canal abre o item, então não leva respiro em cima. */
    .view-item-canal .view-item-meta {
      margin-top: 0;
    }

    .view-item-titulo {
      display: inline-block;
      font-size: clamp(1.05rem, 1.8vw, 1.2rem);
      font-weight: 400;
      line-height: 1.4;
      color: var(--text-main);
      text-decoration: none;
      transition: opacity 0.3s ease, color 100ms cubic-bezier(0.333333, 0, 0.666667, 1);
    }

    a.view-item-titulo:hover {
      opacity: 0.65;
    }

    a.view-item-titulo:focus-visible {
      outline: 1px solid var(--btn-ctrl-border);
      outline-offset: 3px;
    }

    .view-item-meta {
      margin-top: 7px;
      font-size: 0.8rem;
      font-weight: 300;
      letter-spacing: 0.02em;
      opacity: 0.55;
    }

    .view-item-desc {
      margin-top: 11px;
      font-size: 0.95rem;
      font-weight: 300;
      line-height: 1.65;
      max-width: 62ch;
      opacity: 0.8;
      text-align: justify;
    }

    .view-item-site {
      margin-top: 9px;
      font-size: 0.85rem;
      font-weight: 300;
      line-height: 1.5;
    }

    .view-item-site a {
      color: var(--text-main);
      text-decoration: none;
      opacity: 0.65;
      border-bottom: 1px solid var(--menu-border);
      transition: opacity 0.3s ease;
    }

    .view-item-site a:hover {
      opacity: 1;
    }

    .view-item-tags {
      margin-top: 13px;
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
    }

    .view-item-tags span {
      padding: 3px 10px;
      font-size: 0.72rem;
      letter-spacing: 0.04em;
      border: 1px solid var(--menu-border);
      border-radius: 999px;
      opacity: 0.6;
    }

    /* Origem dos dados, quando o JSON informar (ex.: "GitHub: usuário"). */
    .view-fonte {
      margin-top: 20px;
      font-size: 0.75rem;
      font-weight: 300;
      opacity: 0.4;
    }

    /* Formulário de contato: mesmos tokens dos campos de busca e controles. */
    .view-form {
      margin-top: 34px;
      padding-top: 26px;
      border-top: 1px solid var(--menu-border);
      display: flex;
      flex-direction: column;
      gap: 16px;
      max-width: 62ch;
    }

    .view-form-campo {
      display: flex;
      flex-direction: column;
      gap: 7px;
    }

    .view-form-rotulo {
      font-size: 0.75rem;
      font-weight: 300;
      letter-spacing: 0.04em;
      text-transform: uppercase;
      opacity: 0.55;
    }

    .view-form-input {
      width: 100%;
      padding: 10px 14px;
      background: var(--btn-ctrl-bg);
      border: 1px solid var(--btn-ctrl-border);
      border-radius: 10px;
      color: var(--text-main);
      font: inherit;
      font-size: 0.95rem;
      font-weight: 300;
      transition: background 100ms cubic-bezier(0.333333, 0, 0.666667, 1),
                  border-color 100ms cubic-bezier(0.333333, 0, 0.666667, 1),
                  color 100ms cubic-bezier(0.333333, 0, 0.666667, 1);
    }

    .view-form-textarea {
      resize: vertical;
      min-height: 120px;
      line-height: 1.6;
      /* Espaço para o contador sobreposto no canto inferior direito. */
      padding-bottom: 26px;
    }

    /* Contador de caracteres dentro da própria caixa da mensagem. */
    .view-form-mensagem {
      position: relative;
      display: block;
    }

    .view-form-mensagem .view-form-textarea {
      display: block;
    }

    .view-form-contador {
      position: absolute;
      right: 12px;
      bottom: 9px;
      font-size: 0.7rem;
      font-weight: 300;
      letter-spacing: 0.03em;
      opacity: 0.35;
      pointer-events: none;
      user-select: none;
    }

    /* Seletor de assunto: mesma caixa dos demais campos, com seta desenhada
       no tema atual (mesmo traço dos ícones do projeto). */
    .view-form-caixa-select {
      position: relative;
      display: block;
    }

    .view-form-caixa-select::after {
      content: "";
      position: absolute;
      top: 50%;
      right: 15px;
      width: 7px;
      height: 7px;
      margin-top: -5px;
      border-right: 1.2px solid var(--text-main);
      border-bottom: 1.2px solid var(--text-main);
      transform: rotate(45deg);
      opacity: 0.55;
      pointer-events: none;
    }

    .view-form-select {
      appearance: none;
      -webkit-appearance: none;
      padding-right: 38px;
      cursor: pointer;
    }

    .view-form-select option {
      background-color: var(--menu-bg);
      color: var(--text-main);
    }

    .view-form-input:focus-visible {
      outline: 1px solid var(--btn-ctrl-border);
      outline-offset: 2px;
    }

    /* Armadilha para robôs: invisível para quem preenche. */
    .view-form-honey {
      position: absolute;
      left: -9999px;
      width: 1px;
      height: 1px;
      opacity: 0;
      pointer-events: none;
    }

    .view-form-acoes {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 14px;
    }

    .view-form-enviar {
      padding: 10px 22px;
      background: var(--btn-ctrl-bg);
      border: 1px solid var(--btn-ctrl-border);
      border-radius: 10px;
      color: var(--text-main);
      font: inherit;
      font-size: 0.9rem;
      font-weight: 400;
      cursor: pointer;
      transition: opacity 0.3s ease, background 100ms cubic-bezier(0.333333, 0, 0.666667, 1),
                  border-color 100ms cubic-bezier(0.333333, 0, 0.666667, 1),
                  color 100ms cubic-bezier(0.333333, 0, 0.666667, 1);
    }

    .view-form-enviar:hover:not([disabled]) {
      opacity: 0.75;
    }

    .view-form-enviar[disabled] {
      opacity: 0.5;
      cursor: default;
    }

    .view-form-enviar:focus-visible {
      outline: 1px solid var(--btn-ctrl-border);
      outline-offset: 3px;
    }

    .view-form-recado {
      font-size: 0.85rem;
      font-weight: 300;
      opacity: 0.7;
    }

    /* Botão de fechar das telas de conteúdo: fica no topo, à esquerda do menu,
       e só aparece quando uma tela está aberta. */
    .icon-btn.view-close {
      display: none;
    }

    body.view-open .icon-btn.view-close {
      display: flex;
    }

    /* Tela de conteúdo aberta: manifesto e logo ficam ao fundo; os controles
       (menu, idioma e tema) e o próprio conteúdo seguem nítidos. */
    body.view-open {
      overflow: hidden;
    }

    body.view-open .container {
      filter: blur(var(--blur-conteudo));
      opacity: 0.15;
    }

    .controls-footer {
      position: fixed;
      bottom: 48px;
      right: 48px;
      z-index: 10;
      display: flex;
      gap: 12px;
      align-items: center;
    }

    .icon-btn {
      background: transparent;
      border: none;
      width: 38px;
      height: 38px;
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
      padding: 0;
      outline: none;
      position: relative;
      opacity: 1;
    }

    .icon-btn:focus-visible {
      outline: 1px solid var(--btn-ctrl-border);
      outline-offset: 2px;
    }

    .icon-btn svg {
      width: 19px;
      height: 19px;
      fill: none;
      stroke: var(--icon-color);
      stroke-width: 1.2;
      stroke-linecap: round;
      stroke-linejoin: round;
      transition: stroke 100ms cubic-bezier(0.333333, 0, 0.666667, 1), 
                  transform 0.6s ease;
    }

    .icon-btn.rotating svg {
      transform: rotate(180deg) scale(0.85);
      opacity: 0;
    }

    .icon-btn[data-tooltip]::after {
      content: attr(data-tooltip);
      position: absolute;
      bottom: calc(100% + 6px);
      left: 50%;
      font-size: 0.68rem;
      letter-spacing: 0.04em;
      color: var(--text-main);
      white-space: nowrap;
      pointer-events: none;
      opacity: 0;
      transform: translate(-50%, 3px);
      transition: opacity 0.3s ease, transform 0.3s ease;
    }

    @media (hover: hover) {
      .icon-btn[data-tooltip]:hover::after,
      .icon-btn[data-tooltip]:focus-visible::after {
        opacity: 0.6;
        transform: translate(-50%, 0);
      }

      .lang-dropdown.active ~ .icon-btn[data-tooltip]:hover::after {
        opacity: 0;
      }
    }

    /* Menu do topo: mesmo painel/lista/itens do menu de idiomas,
       mas ancorado no botão do canto direito em vez de centralizado. */
    .site-menu-wrapper {
      position: relative;
      pointer-events: auto;
      display: flex;
      align-items: center;
      gap: 12px;
    }

    .lang-dropdown.lang-dropdown-right {
      position: absolute;
      top: calc(100% + 12px);
      right: 0;
      left: auto;
      transform: none;
      background: transparent;
      border-color: transparent;
      box-shadow: none;
    }

    /* Itens do menu do topo alinhados à direita (o menu de idiomas alinha à esquerda) */
    .lang-dropdown-right .lang-menu-list {
      align-items: flex-end;
    }

    /* Contato: separado dos demais itens por um fio sutil */
    .lang-dropdown-right .lang-option-sep {
      padding-bottom: 8px;
      margin-bottom: 6px;
      border-bottom: 1px solid var(--menu-border);
    }

    .lang-dropdown-right .lang-option {
      text-align: right;
    }

    /* Rodapé esquerdo: seletor de idiomas. Mesmo visual do menu do topo,
       mas ancorado no botão do canto esquerdo e abrindo para cima. */
    .lang-footer {
      position: fixed;
      bottom: 48px;
      left: 48px;
      z-index: 10;
      display: flex;
      align-items: center;
    }

    .lang-footer-inner {
      position: relative;
    }

    .lang-dropdown.lang-dropdown-left {
      position: absolute;
      top: auto;
      bottom: calc(100% + 12px);
      left: 0;
      right: auto;
      transform: none;
      background: transparent;
      border-color: transparent;
      box-shadow: none;
    }

    .lang-dropdown-left .lang-menu-list {
      align-items: flex-start;
    }

    .lang-dropdown-left .lang-option {
      text-align: left;
    }

    /* Itens do menu de redes são links, não botões. */
    a.lang-option {
      display: block;
      text-decoration: none;
    }

    /* Qualquer menu aberto (topo ou idioma): ofusca o fundo animado, o texto
       do manifesto e também as janelas de conteúdo abertas (Sobre, Projetos,
       Publicações, Contato). Os controles (logo/início, fechar, menu, idioma e
       tema) continuam nítidos, porque são botões. */
    body:is(.site-menu-open, .lang-menu-open) #bg-canvas,
    body:is(.site-menu-open, .lang-menu-open) #grain-canvas {
      filter: blur(7px) saturate(0.5);
      opacity: 0.14;
    }

    body:is(.site-menu-open, .lang-menu-open) .vignette {
      opacity: 0.45;
    }

    body:is(.site-menu-open, .lang-menu-open) .container,
    body:is(.site-menu-open, .lang-menu-open) .view-overlay {
      filter: blur(var(--blur-conteudo));
      opacity: 0.3;
    }

    /* O manifesto (quando não há tela aberta) também recebe o recorte atrás
       do painel, senão o texto continuaria aparecendo sob o menu. Como o
       .container rola com a página, ele usa a variante em coordenadas locais
       (--menu-holes-doc), recalculada também no scroll. */
    body:is(.site-menu-open, .lang-menu-open) .container {
      -webkit-mask-image: var(--menu-holes-doc);
      mask-image: var(--menu-holes-doc);
      -webkit-mask-repeat: no-repeat;
      mask-repeat: no-repeat;
      -webkit-mask-composite: source-in;
      mask-composite: intersect;
    }

    /* Ao abrir ou fechar um menu, o desfoque do fundo entra e sai na hora
       (sem transição). `menu-snap` é uma classe transitória aplicada apenas
       pelo JS no instante da troca; não deve ser usada estaticamente. */
    body:is(.site-menu-open, .lang-menu-open, .menu-snap) #bg-canvas,
    body:is(.site-menu-open, .lang-menu-open, .menu-snap) #grain-canvas,
    body:is(.site-menu-open, .lang-menu-open, .menu-snap) .vignette,
    body:is(.site-menu-open, .lang-menu-open, .menu-snap) .container,
    body:is(.site-menu-open, .lang-menu-open, .menu-snap) .view-overlay {
      transition: none;
    }

    /* Tela aberta a partir de um menu: o fundo já está ofuscado pelo menu e
       precisa continuar assim até o .view-backdrop cobrir tudo. Sem isso, ao
       fechar o menu o fundo reaparece nítido por um instante antes de a tela
       surgir (o "piscar"). `view-opening` é transitória, só enquanto a tela
       abre; o .view-overlay não entra aqui para poder aparecer suavemente. */
    body.view-opening #bg-canvas,
    body.view-opening #grain-canvas {
      filter: blur(7px) saturate(0.5);
      opacity: 0.14;
    }

    body.view-opening .vignette {
      opacity: 0.45;
    }

    body.view-opening .container {
      filter: blur(var(--blur-conteudo));
      opacity: 0.3;
    }

    .lang-dropdown {
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      display: none;
      flex-direction: column;
      padding: 19px 30px;
      background: var(--menu-bg);
      border: 1px solid var(--menu-border);
      border-radius: 16px;
      box-shadow: 0 20px 55px rgba(0, 0, 0, 0.35);
      transition: background 100ms cubic-bezier(0.333333, 0, 0.666667, 1),
                  border-color 100ms cubic-bezier(0.333333, 0, 0.666667, 1);
    }

    /* Só a lista rola. O respiro do painel fica reservado para as setas,
       então o texto nunca passa por baixo delas. */
    .lang-menu-list {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 6px;
      max-height: 64vh;
      max-height: 64dvh;
      overflow-y: auto;
      overscroll-behavior: contain;
      scrollbar-width: none;
      -ms-overflow-style: none;
    }

    .lang-menu-list::-webkit-scrollbar {
      width: 0;
      height: 0;
    }

    /* Setas discretas (mesmo traço dos ícones do rodapé) que só aparecem
       quando ainda há idiomas para rolar. São botões: clicar rola a lista. */
    .lang-scroll-btn {
      position: absolute;
      left: 50%;
      transform: translateX(-50%);
      width: 48px;
      height: 16px;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 0;
      background: transparent;
      border: none;
      cursor: pointer;
      opacity: 0;
      visibility: hidden;
      transition: opacity 0.3s ease, visibility 0.3s;
    }

    .lang-scroll-btn::before {
      content: "";
      width: 8px;
      height: 8px;
      border-right: 1.2px solid var(--text-main);
      border-bottom: 1.2px solid var(--text-main);
    }

    .lang-scroll-btn:focus-visible {
      outline: 1px solid var(--btn-ctrl-border);
      outline-offset: 2px;
    }

    .lang-scroll-up {
      top: 4px;
    }

    .lang-scroll-up::before {
      transform: rotate(-135deg);
    }

    .lang-scroll-down {
      bottom: 4px;
    }

    .lang-scroll-down::before {
      transform: rotate(45deg);
    }

    .lang-dropdown.can-scroll-up .lang-scroll-up,
    .lang-dropdown.can-scroll-down .lang-scroll-down {
      opacity: 0.55;
      visibility: visible;
    }

    .lang-dropdown.can-scroll-up .lang-scroll-up:hover,
    .lang-dropdown.can-scroll-down .lang-scroll-down:hover {
      opacity: 0.9;
    }

    .lang-dropdown.active {
      display: flex;
    }

    .lang-option {
      padding: 4px 14px;
      background: transparent;
      border: none;
      color: var(--text-main);
      font-size: clamp(0.95rem, 2.2vw, 1.15rem);
      line-height: 1.5;
      white-space: nowrap;
      text-align: center;
      cursor: pointer;
      width: 100%;
      opacity: 0.4;
      transition: opacity 0.3s ease,
                  color 100ms cubic-bezier(0.333333, 0, 0.666667, 1);
    }

    .lang-option:hover {
      opacity: 1;
    }

    @media (max-width: 640px) {
      header {
        top: calc(24px + env(safe-area-inset-top));
        left: 24px;
        right: 24px;
      }

      .container {
        padding: 0 28px;
      }

      h1 {
        font-size: clamp(1.7rem, 7.5vw, 2.4rem);
        line-height: 1.3;
      }

      .translation {
        margin-top: 16px;
        font-size: 0.82rem;
      }

      .translation::before {
        margin-bottom: 12px;
      }

      .controls-footer {
        bottom: calc(24px + env(safe-area-inset-bottom));
        right: 24px;
      }

      .lang-footer {
        bottom: calc(24px + env(safe-area-inset-bottom));
        left: 24px;
      }

      /* No mobile, os dois menus ficam centralizados na tela, em vez de
         ancorados no botão do topo (direita) ou no de idioma (esquerda). */
      .lang-dropdown.lang-dropdown-right,
      .lang-dropdown.lang-dropdown-left {
        position: fixed;
        top: 50%;
        left: 50%;
        right: auto;
        bottom: auto;
        transform: translate(-50%, -50%);
      }

      .lang-dropdown-right .lang-menu-list,
      .lang-dropdown-left .lang-menu-list {
        align-items: center;
      }

      .lang-dropdown-right .lang-option,
      .lang-dropdown-left .lang-option {
        text-align: center;
      }

      .lang-dropdown {
        padding: 17px 22px;
      }

      /* No toque, cada opção precisa de área grande e texto legível. */
      .lang-option {
        display: flex;
        align-items: center;
        justify-content: center;
        min-height: 52px;
        padding: 12px 24px;
        font-size: 1.2rem;
      }

      .lang-menu-list {
        gap: 8px;
        max-height: 70vh;
        max-height: 70dvh;
      }

      .view-overlay {
        --vd-top: calc(24px + env(safe-area-inset-top));
        --vd-side: 24px;
        --vd-bottom: calc(24px + env(safe-area-inset-bottom));
      }

      .view-scroll {
        padding: 92px 24px 96px;
      }
    }

    /* ------------------------------------------------------------------
       Mini jogo: o logotipo do topo esquerdo vira uma nave. Ao ativar, os
       menus e textos somem e sobra o fundo animado; o ponteiro guia a nave e
       o clique atira nos nós da rede.
       ------------------------------------------------------------------ */
    body.game-mode .container,
    body.game-mode .controls-footer,
    body.game-mode .lang-footer,
    body.game-mode .vignette,
    body.game-mode .view-backdrop,
    body.game-mode .view-overlay,
    body.game-mode header .site-menu-wrapper {
      opacity: 0 !important;
      pointer-events: none !important;
    }

    body.game-mode #bg-canvas {
      pointer-events: auto;
      cursor: crosshair;
    }

    body.game-mode .logo-container {
      position: fixed;
      top: 0;
      left: 0;
      width: 38px;
      height: 38px;
      margin: 0;
      z-index: 50;
      pointer-events: auto;
      cursor: crosshair;
      will-change: transform;
    }

    body.game-mode .logo-container[data-tooltip]::after {
      display: none;
    }

    /* HUD do mini jogo (topo central): pausar, pontos e sair. */
    .game-hud {
      position: fixed;
      top: 40px;
      left: 50%;
      transform: translateX(-50%);
      z-index: 30;
      display: flex;
      align-items: center;
      gap: 18px;
      opacity: 0;
      visibility: hidden;
      pointer-events: none;
      transition: opacity 300ms ease, visibility 300ms;
    }

    body.game-mode .game-hud {
      opacity: 1;
      visibility: visible;
      pointer-events: auto;
    }

    .game-hud .score {
      font-variant-numeric: tabular-nums;
      font-size: 1.1rem;
      letter-spacing: 0.06em;
      color: var(--text-main);
      min-width: 2ch;
      text-align: center;
    }

    /* Nave inimiga: mesmo desenho do logotipo, em cor hostil. */
    .nave-inimiga {
      position: fixed;
      top: 0;
      left: 0;
      width: 38px;
      height: 38px;
      display: flex;
      align-items: center;
      justify-content: center;
      z-index: 49;
      pointer-events: none;
      color: #ff453a;
      filter: drop-shadow(0 0 10px rgba(255, 69, 58, 0.55));
      will-change: transform;
      opacity: 0;
      transition: opacity 200ms ease;
    }

    .nave-inimiga svg {
      width: 26px;
      height: 26px;
      display: block;
    }
