/* =============================================================================
   blocos.css — a aparência do editor de blocos
   -----------------------------------------------------------------------------
   Os blocos são <div> comuns, não SVG. A escolha foi deliberada: dentro de um
   bloco há <select> e <input> de verdade, e no SVG cada um deles viraria um
   <foreignObject> — pesado, com foco e acessibilidade capengas em vários
   navegadores. Em DOM, o menu de pino é um menu de pino: abre no celular,
   funciona com teclado, e o navegador cuida de tudo.

   O CONTORNO DE CADA PEÇA É UM <svg> ATRÁS DO CONTEÚDO, desenhado pelo
   blocos-ui.js depois de medir o bloco (a geometria mora no
   blocos-formas.js). Era `clip-path`, e o recorte não pinta fora da caixa
   do elemento: a lingueta de dentro do C nunca aparecia, e o primeiro bloco
   de um "se" ficava com um buraco vazado no topo. Com o SVG os blocos ficam
   RENTES — sem margem negativa —, a lingueta pende para fora da caixa e cai
   no dente do de baixo, e o contorno pode ter curva e borda.

   As alturas daqui e as medidas do blocos-formas.js andam juntas: dente de
   8 px, espinha do C de 16, cúpula do chapéu de 16.
   ========================================================================== */

.blocos {
  position: relative;               /* a camada de voo se apoia aqui */
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  min-height: 0;
  background: var(--bg-suave);
}

/* O bloco que está na mão. Por cima da gaveta, da prévia e dos botões:
   a mão nunca perde de vista o que está carregando. */
.blocos__voo {
  position: absolute;
  inset: 0;
  z-index: 60;
  overflow: visible;
  pointer-events: none;
}

.blocos[hidden] { display: none; }


/* =========================================================================
   GAVETA
   ====================================================================== */

/* Duas colunas: a trilha das famílias e as amostras da família aberta.
   A trilha não rola junto com as amostras — saber onde se está não pode
   depender de ter rolado a lista de volta ao topo. */
/* A trilha ocupa a coluna da esquerda inteira; a da direita tem a lista
   de amostras em cima e a dica de apagar no pé.

   280 px e não 230: a 230 o "contar de 0 até 10 pulando 1" quebrava em
   três linhas na gaveta e vinha numa linha só na tela, e a amostra
   deixava de parecer o bloco que ela é. */
.blocos__gaveta {
  position: relative;               /* a lixeira cobre a gaveta inteira */
  display: grid;
  grid-template-columns: auto minmax(210px, 280px);
  grid-template-rows: minmax(0, 1fr) auto;
  min-height: 0;
  border-right: 1px solid var(--borda);
  background: var(--bg-elevado);
}

.blocos__trilha { grid-row: 1 / span 2; }

.blocos__trilha {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-height: 0;
  overflow-y: auto;
  padding: 8px 6px;
  background: var(--bg-suave);
  border-right: 1px solid var(--borda);
}

.blocos__familia {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 7px 10px 7px 8px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--texto-medio);
  font-weight: 600;
  font-size: 12px;
  line-height: 1.2;
  text-align: left;
  cursor: pointer;
  transition: background var(--rapido), color var(--rapido);
}

.blocos__familia-bola {
  flex: none;
  width: 11px; height: 11px;
  border-radius: 50%;
  background: var(--cor);
}

.blocos__familia-nome { white-space: nowrap; }

.blocos__familia:hover { background: color-mix(in srgb, var(--cor) 14%, transparent); }

/* A família aberta se pinta com a própria cor: é a mesma cor dos blocos
   que estão ali do lado, e é assim que os dois se ligam sem legenda. */
.blocos__familia--aberta {
  background: color-mix(in srgb, var(--cor) 20%, transparent);
  color: var(--texto);
  box-shadow: inset 3px 0 0 var(--cor);
}

.blocos__lista {
  min-height: 0;
  overflow-y: auto;
  padding: 6px 12px 16px;
  /* A última amostra não termina num corte reto: some aos poucos no pé da
     lista. Os 18 px cabem no respiro de baixo, então no fim da rolagem a
     última amostra aparece inteira. */
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 18px), transparent);
          mask-image: linear-gradient(to bottom, #000 calc(100% - 18px), transparent);
}

/* Arrastar um bloco de volta para a gaveta é o único jeito de apagar — e
   não havia nada na tela dizendo isso. A dica fica no pé, discreta, e
   acende em vermelho enquanto há um bloco no ar. */
.blocos__lixo {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 9px 12px;
  border-top: 1px dashed var(--borda);
  color: var(--texto-suave);
  font-weight: 500;
  font-size: 11.5px;
  line-height: 1.3;
  transition: color var(--rapido), background var(--rapido);
}

.blocos__lixo-txt { display: grid; gap: 1px; }
.blocos__lixo-txt b { font-weight: 700; }
.blocos__lixo-txt span { opacity: .8; }
.blocos__lixo-ico { flex: none; margin-top: 1px; }
.blocos__lixo-ico svg { width: 15px; height: 15px; display: block; }

/* Com um bloco no ar, quem fala é a lixeira que cobre a gaveta. A faixa
   ficava visível por baixo dela, com o mesmo aviso em outras palavras, e o
   vermelho dela pintava só a caixa do texto: um retângulo tingido no pé,
   com a cor normal embaixo. Dois avisos iguais competem; some a faixa. */
.blocos--arrastando .blocos__lixo,
.blocos--engolindo  .blocos__lixo { visibility: hidden; }

/* ---- A LIXEIRA ----
   Com um bloco no ar, a gaveta inteira vira o alvo de apagar: é a área
   que apaga de verdade, e agora ela se mostra do tamanho que tem. Longe,
   um convite discreto; com o bloco em cima, vermelho cheio e a tampa
   aberta — saber ANTES de soltar é a diferença entre apagar de propósito
   e apagar sem querer. */
.blocos__lixeira {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 16px;
  text-align: center;
  color: var(--coral, #e5484d);
  background: color-mix(in srgb, var(--bg-elevado) 88%, transparent);
  border: 2px dashed color-mix(in srgb, var(--coral, #e5484d) 70%, transparent);
  border-radius: 10px;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 140ms ease, visibility 0s linear 140ms,
              background 140ms ease, border-color 140ms ease;
}

.blocos--arrastando .blocos__lixeira,
.blocos--engolindo  .blocos__lixeira {
  opacity: 1;
  visibility: visible;
  transition: opacity 140ms ease, visibility 0s,
              background 140ms ease, border-color 140ms ease;
}

.blocos__lixeira-lata {
  display: grid;
  place-items: center;
  width: 76px;
  height: 76px;
  border-radius: 50%;
  color: #fff;
  background: var(--coral, #e5484d);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--coral, #e5484d) 35%, transparent);
  transition: transform 160ms cubic-bezier(.2, 0, 0, 1), box-shadow 160ms ease;
}
.blocos__lixeira-lata svg { width: 40px; height: 40px; overflow: visible; }

/* A tampa gira em volta da dobradiça, na ponta direita dela. */
.blocos__lixeira-tampa {
  transform-origin: 39px 14px;
  transition: transform 180ms cubic-bezier(.2, 0, 0, 1.4);
}

.blocos__lixeira-txt { font-size: 13px; font-weight: 700; line-height: 1.3; }
.blocos__lixeira-txt--perto { display: none; }

.blocos--apagando .blocos__lixeira,
.blocos--engolindo .blocos__lixeira {
  background: color-mix(in srgb, var(--coral, #e5484d) 22%, var(--bg-elevado));
  border-color: var(--coral, #e5484d);
  border-style: solid;
}
.blocos--apagando .blocos__lixeira-lata,
.blocos--engolindo .blocos__lixeira-lata {
  transform: scale(1.12);
  box-shadow: 0 0 0 10px color-mix(in srgb, var(--coral, #e5484d) 22%, transparent);
}
.blocos--apagando .blocos__lixeira-tampa,
.blocos--engolindo .blocos__lixeira-tampa { transform: translateY(-2px) rotate(28deg); }
.blocos--apagando .blocos__lixeira-txt--longe { display: none; }
.blocos--apagando .blocos__lixeira-txt--perto { display: block; }

/* O bloco sobre a lixeira encolhe e desbota: é o último aviso. */
.pilha--voando.pilha--apagando {
  opacity: .55;
  filter: grayscale(.6) drop-shadow(0 6px 12px rgba(15, 23, 42, .3));
  transform: rotate(-1.5deg) scale(.82);
  transition: transform 140ms cubic-bezier(.2, 0, 0, 1), opacity 140ms ease;
}

@media (prefers-reduced-motion: reduce) {
  .blocos__lixeira, .blocos__lixeira-lata, .blocos__lixeira-tampa,
  .pilha--voando.pilha--apagando { transition: none; }
  .pilha--voando.pilha--apagando { transform: none; }
}

/* O título gruda no alto enquanto as amostras passam por baixo dele — e
   tem de cobrir TUDO. Ele grudava 6 px abaixo do topo (o respiro de cima
   da lista) e 12 px mais estreito de cada lado (o respiro dos lados): pelas
   frestas as amostras apareciam em volta dele, e o título parecia encavalado
   no bloco. Agora ele vai até as bordas da lista, cola no topo de verdade e
   termina num esmaecido, para a amostra entrar por baixo sem corte seco. */
.blocos__grupo {
  position: sticky;
  top: -6px;
  z-index: 2;
  margin: 12px -12px 6px;
  padding: 8px 12px 6px;
  box-shadow: 0 8px 8px -4px var(--bg-elevado);
  font-weight: 700;
  font-size: 11px;
  line-height: 1.2;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--cor);
  background: var(--bg-elevado);
}

.blocos__amostra {
  margin-bottom: 8px;
  cursor: grab;
}

/* Na gaveta o bloco é só uma amostra: não recebe foco nem abre menu, porque
   o gesto ali é pegar e arrastar, não configurar. */
.blocos__amostra .bl__campo { pointer-events: none; }

/* A BOCA VAZIA ENCOLHE NA GAVETA.

   Um bloco em C mostra a "boca" com a altura de um corpo de verdade, para o
   aluno enxergar que cabe coisa lá dentro. Na gaveta isso não ensina nada —
   não há o que pôr ali — e custa caro: a família Controle tem oito
   amostras, e só três cabiam na lista (810 px de conteúdo em 484 px). A
   trilha lateral existe justamente para a família aberta caber inteira.

   Encolher a boca na amostra é o que o Scratch e o Blockly fazem com o
   bloco da paleta: a forma continua reconhecível, o tamanho não. */
.blocos__amostra .bl__braco,
.blocos__amostra .bl__braco--vazio {
  min-height: 12px;
}

/* Na gaveta a amostra pode quebrar a linha: a coluna tem 280 px, e o bloco
   mais comprido do catálogo passa dos 380. Na tela ele não quebra nunca. */
.blocos__amostra .bl__linha { flex-wrap: wrap; }
.blocos__amostra .bl { max-width: 100%; }


/* =========================================================================
   TELA
   ====================================================================== */

/* A prévia do código fica EMBAIXO em tela estreita e AO LADO em tela
   larga. Embaixo ela custava 38% da altura da tela de montagem, que já
   era o que tinha menos: sobravam 343 px para montar um programa. */
.blocos__area {
  position: relative;
  display: grid;
  grid-template-rows: minmax(0, 1fr) minmax(74px, 34%);
  min-height: 0;
}

@media (min-width: 1100px) {
  .blocos__area {
    grid-template-rows: minmax(0, 1fr);
    grid-template-columns: minmax(0, 1fr) minmax(250px, 30%);
  }
  .blocos__previa { border-top: 0; border-left: 1px solid var(--borda); }
}

.blocos__palco {
  position: relative;
  display: grid;
  min-height: 0;
  min-width: 0;
}

.blocos__tela {
  position: relative;
  overflow: auto;
  min-height: 0;
  touch-action: none;                 /* o arrasto é nosso, não da rolagem */

  background-color: var(--bg-suave);
  background-image: radial-gradient(circle, var(--borda) 1px, transparent 1px);
  background-size: 22px 22px;
}

.blocos__vazio {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 24px;
  text-align: center;
  color: var(--texto-suave);
  font-size: 14px;
  pointer-events: none;
}

.blocos__vazio-sub { font-size: 12.5px; opacity: .8; }

/* A LARGURA DA PILHA É A DO QUE ELA TEM. Uma pilha posicionada encolhe até a
   borda da tela, e a linha do bloco quebrava conforme ONDE a pilha estava:
   "guardar … em volts" vinha em uma linha num canto e em duas no outro, e
   um hexágono quebrado virava um hexágono alto. Hoje a linha não quebra, e
   a tela rola de lado. */
.pilha {
  position: absolute;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: max-content;
  /* A ordem de pintura dos blocos (veja a seleção) fica DENTRO da pilha:
     um bloco de uma pilha nunca passa na frente de outra, nem dos botões
     e selos da tela. */
  isolation: isolate;
}

/* Todo bloco de pilha pinta num degrau acima do escolhido — veja a seleção. */
.pilha .bl { z-index: 1; }

/* ---- PILHA SOLTA ----
   Fora de "quando ligar" e de "repetir sempre", esta pilha não vai rodar.
   A faixa da prévia já dizia isso, mas do outro lado da tela: a marca
   precisa estar NO bloco, senão o aviso fala de uma coisa que o aluno não
   consegue apontar. */
/* Era um retângulo tracejado em volta da caixa da pilha, e a peça não é
   retângulo: sobrava canto vazio ao lado do cabeçalho do "se", e a
   lingueta de baixo ficava para fora. Um `drop-shadow` segue o recorte de
   verdade — o dente, a boca do C, a lingueta —, porque é calculado sobre
   o que foi PINTADO, e não sobre a caixa. Três camadas finas em vez de
   uma larga: a sombra borrada de uma só vira névoa, as finas empilhadas
   fazem um contorno. A etiqueta diz o motivo: só a cor não conta por que
   aquela pilha está marcada. */
/* O CONTORNO É SÓLIDO, e não um brilho. O brilho borrado sumia ao lado dos
   blocos de dentro do C: junto do laranja ele se somava à borda e parecia
   linha, junto do rosa quase não se via — a borda "sumia" no meio da
   pilha. Quatro cópias deslocadas 2 px, sem borrão, dilatam a silhueta
   inteira: um contorno do mesmo peso em volta de qualquer cor, e que entra
   na boca vazia do "senão". O brilho de fora é só o acabamento. A cor não
   é a âmbar dos blocos de Controle, senão o contorno de um "se" solto
   seria o próprio "se" 2 px mais largo. */
.blocos {
  --halo-solta: #d97706;
  --halo-solta-brilho: rgba(217, 119, 6, .35);
  --selecao-cor: #1e293b;          /* branco sumiria no fundo claro */
}

.pilha--solta {
  filter: drop-shadow(2px 0 0 var(--halo-solta)) drop-shadow(-2px 0 0 var(--halo-solta))
          drop-shadow(0 2px 0 var(--halo-solta)) drop-shadow(0 -2px 0 var(--halo-solta))
          drop-shadow(0 0 5px var(--halo-solta-brilho));
}

/* O selo mora na TELA, por cima de toda pilha — veja posicionarAvisos. */
.blocos__solta {
  position: absolute;
  z-index: 20;
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 2px solid var(--bg-suave);
  border-radius: 50%;
  background: var(--halo-solta);
  color: #412402;
  font: inherit;
  font-size: 13px;
  font-weight: 800;
  line-height: 1;
  cursor: help;
  box-shadow: 0 1px 4px rgba(15, 23, 42, .35);
}

/* A frase inteira: embaixo do selo e crescendo para a esquerda, que é
   para onde o bloco está — para a direita ela sairia da pilha. */
.blocos__solta::after {
  content: attr(data-dica);
  position: absolute;
  top: calc(100% + 6px);
  right: -6px;
  width: max-content;
  max-width: 230px;
  padding: 7px 10px;
  border-radius: 8px;
  background: #0b0f15;
  color: #fef3c7;
  border: 1px solid var(--halo-solta);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.35;
  text-align: left;
  white-space: normal;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-3px);
  transition: opacity 120ms ease, transform 120ms ease, visibility 0s linear 120ms;
}
.blocos__solta:hover::after,
.blocos__solta:focus-visible::after,
.blocos__solta--aberto::after {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: opacity 120ms ease, transform 120ms ease, visibility 0s;
}
.blocos__solta:focus-visible { outline: 2px solid var(--halo-solta); outline-offset: 2px; }

/* Com um bloco no ar, o selo e a frase só atrapalham a mira. */
.blocos--arrastando .blocos__solta { visibility: hidden; }

.pilha--voando {
  z-index: 30;
  filter: drop-shadow(0 12px 22px rgba(15, 23, 42, .34));
  opacity: .96;
  pointer-events: none;
  /* Uma inclinação de um grau e meio: o bloco no ar deixa de parecer
     grudado na tela. */
  transform: rotate(-1.5deg) scale(1.03);
}

/* ---- A PRÉVIA: a silhueta da peça, no lugar exato ----
   Não é mais uma cópia desbotada por cima: é uma cópia no PROGRAMA, e a
   montagem abre espaço para ela de verdade — a pilha se afasta, o C estica
   em volta do que vai engolir, o buraco se alarga. É o Scratch 3. Cinza
   médio e translúcido para ler sobre o fundo claro e sobre o escuro. */
.bl--previa > .bl__linha { visibility: hidden; }
.bl--previa > .bl__fundo .bl__corpo { fill: rgba(128, 138, 152, .42); }
.bl--previa > .bl__fundo .bl__borda { stroke: rgba(128, 138, 152, .85); }

/* O valor que vai sair do buraco para dar lugar ao novo */
.bl--sera-trocado { opacity: .3; }

@media (prefers-reduced-motion: reduce) {
  .pilha--voando { transform: none; }
}


/* =========================================================================
   O BLOCO
   ====================================================================== */

.bl {
  position: relative;
  isolation: isolate;          /* o fundo em SVG fica atrás do que é DESTE bloco */
  min-width: 0;
  color: #fff;
  font-weight: 600;
  font-size: 13.5px;
  line-height: 1.35;
  cursor: grab;
  user-select: none;
}

.bl:active { cursor: grabbing; }

.bl__fundo,
.bl__vaga-fundo {
  position: absolute;
  left: 0; top: 0;
  width: 100%; height: 100%;
  overflow: visible;           /* a lingueta pende para fora da caixa */
  z-index: -1;
  pointer-events: none;
}

/* Dois caminhos: o corpo, só cor, e a borda, só o que está à mostra — uma
   emenda, um traço (veja "CORPO E BORDA" no blocos-formas.js). */
.bl__corpo { fill: var(--cor, #5b6470); }
.bl__borda {
  fill: none;
  stroke: var(--borda, none);
  stroke-width: 1;
  stroke-linejoin: round;
}

/* O marco invisível que empurra o fim da rolagem além do último bloco. */
.blocos__margem { position: absolute; width: 1px; height: 1px; pointer-events: none; }

/* 48 px de altura, e o texto um pouco abaixo do meio: o dente de 8 px come
   o alto da faixa da esquerda. */
.bl__linha {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 6px;
  min-height: 48px;
  padding: 7px 12px 4px;
}

.bl__rotulo { white-space: nowrap; }

.bl--controle,
.bl--chapeu { display: flex; flex-direction: column; align-items: stretch; }

/* A cúpula do chapéu sobe 16 px acima da barra. */
.bl--chapeu > .bl__linha:first-child { min-height: 64px; padding-top: 22px; }

.bl__linha--meio { min-height: 32px; padding: 4px 12px; }

/* A BOCA do C. A espinha é desenhada pelo contorno; aqui só se reserva o
   espaço dela à esquerda. Rente em cima e embaixo: o dente de dentro da
   barra cai no buraco do primeiro bloco, e a lingueta do último cai no pé. */
.bl__braco {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-height: 24px;
  min-width: 124px;
  padding-left: 16px;
}

.bl__pe { height: 16px; min-width: 140px; }


/* ---- valor: pílula (número/texto) e hexágono (sim/não) ---- */

.bl--valor { display: inline-flex; align-items: center; }

.bl--valor > .bl__linha { min-height: 28px; padding: 2px 10px; gap: 5px; }

.bl--r-logico > .bl__linha { padding-left: 16px; padding-right: 16px; }

/* COR ALTERNADA. Uma conta dentro de outra conta são dois azuis iguais, e
   as duas viravam uma peça só. Como no Snap!, o valor de dentro clareia e o
   texto dele escurece. */
.bl--zebra { color: var(--texto-zebra, #0f172a); }


/* ---- campos ---- */

.bl__campo {
  font-weight: 600;
  font-size: 13px;
  line-height: 1;

  /* Cores fixas de proposito. O campo e uma ilha branca sobre a cor do
     bloco, em qualquer tema — herdar --texto o deixava branco no branco
     quando o site estava no escuro. */
  color: #0f172a;
  background: #fff;
  border: 0;
  border-radius: 999px;
  padding: 4px 8px;
  max-width: 140px;
}

.bl__campo--menu { padding-right: 4px; cursor: pointer; }

.bl__campo--texto { min-width: 2.2em; }

.bl__campo:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }

/* Os oito pontos de uma linha da matriz. A ilha branca é a mesma dos
   outros campos; cada ponto é um LED da matriz, vermelho aceso e cinza
   apagado — com borda nos dois, para o apagado não sumir no branco. */
.bl__campo--pontos {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 4px 7px;
  max-width: none;
}

.bl__ponto {
  width: 13px;
  height: 13px;
  padding: 0;
  border-radius: 50%;
  border: 1.5px solid #94a3b8;
  background: #e2e8f0;
  cursor: pointer;
}

.bl__ponto[aria-pressed="true"] {
  background: #e5484d;
  border-color: #a51d24;
}

.bl__ponto:focus-visible { outline: 2px solid #0f172a; outline-offset: 1px; }


/* ---- encaixes de valor: o buraco tem a forma do que aceita ---- */

.bl__vaga {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  min-width: 42px;
}

.bl__vaga-fundo path { fill: var(--buraco, rgba(0, 0, 0, .25)); }

.bl__vaga--logico { min-width: 58px; }

.bl__vaga--cheia { min-width: 0; }

.bl__vaga-dica {
  padding: 0 12px;
  font-weight: 500;
  font-size: 11.5px;
  line-height: 1;
  color: rgba(255, 255, 255, .72);
}

/* ACENDE ONDE CABE. Só a forma não impede de tentar o buraco errado — é o
   que os estudos com crianças mostram —, então ao pegar um valor os
   buracos onde ele entra ficam tracejados, e os outros apagam. */
.bl__vaga--cabe { outline: 2px dashed rgba(255, 255, 255, .9); outline-offset: 2px; border-radius: 16px; }
.bl__vaga--nao { opacity: .35; }


/* ---- seleção ---- */

/* A SELEÇÃO CONTORNA A SILHUETA, e não o caminho do bloco.

   Era um traço de 2,5 px no caminho do próprio bloco, e num C isso dava
   errado de três jeitos: o caminho passa POR DENTRO (embaixo da barra de
   cima, em volta da lingueta da boca), e o traço aparecia lá, riscando o
   bloco de dentro; do lado direito, onde o bloco de dentro chega à beira,
   o caminho do C não passa, e a linha sumia; e a lingueta do pé ganhava
   contorno por cima do dente de quem estava pendurado embaixo. O traço
   centrado no caminho ainda ficava meio coberto pelo próprio corpo, e era
   isso que parecia borrado.

   Agora é a mesma dilatação do contorno da pilha solta: quatro cópias
   deslocadas 2 px, sem borrão, em volta de tudo o que o bloco PINTOU — ele e
   o que está dentro dele. E ele clareia um pouco: no meio de uma pilha só os
   lados ganham contorno (as emendas dividem em cima e embaixo), e o brilho é
   o que diz qual dos blocos está escolhido.

   E o escolhido pinta ATRÁS dos vizinhos (z-index 0 contra 1). O contorno
   sai 2 px para fora do bloco, e o de baixo de uma emenda pintava depois do
   de cima: selecionar o "usar" pendurado num "se" punha uma faixa por cima
   do pé laranja e em volta da lingueta dele, e a emenda parecia torta. Atrás
   dos dois vizinhos, o contorno aparece só onde o bloco está à mostra — em
   cima e embaixo quem cobre a emenda é o vizinho, como numa emenda qualquer. */
.pilha .bl--escolhido { z-index: 0; }

/* Do lado de uma emenda com outro bloco da pilha, a seleção não se estende:
   atrás do vizinho ela sumiria de qualquer jeito, mas os 2 px que saem para
   o lado ficavam de fora no canto, um risquinho acima (ou abaixo) da emenda.
   As cópias de lado vêm primeiro, e só depois as de cima e de baixo que
   ainda valem. */
.pilha:not(.pilha--solta) .bl--escolhido.bl--irmao-cima {
  filter: brightness(1.08) drop-shadow(2px 0 0 var(--selecao)) drop-shadow(-2px 0 0 var(--selecao))
          drop-shadow(0 2px 0 var(--selecao));
}
.pilha:not(.pilha--solta) .bl--escolhido.bl--irmao-baixo {
  filter: brightness(1.08) drop-shadow(2px 0 0 var(--selecao)) drop-shadow(-2px 0 0 var(--selecao))
          drop-shadow(0 -2px 0 var(--selecao));
}
.pilha:not(.pilha--solta) .bl--escolhido.bl--irmao-cima.bl--irmao-baixo {
  filter: brightness(1.08) drop-shadow(2px 0 0 var(--selecao)) drop-shadow(-2px 0 0 var(--selecao));
}
.bl--escolhido {
  --selecao: var(--selecao-cor, #fff);
  filter: brightness(1.08) drop-shadow(2px 0 0 var(--selecao)) drop-shadow(-2px 0 0 var(--selecao))
          drop-shadow(0 2px 0 var(--selecao)) drop-shadow(0 -2px 0 var(--selecao));
}

/* NUMA PILHA SOLTA A SELEÇÃO NÃO MEXE NO CONTORNO. O amarelo já cerca a
   pilha inteira: branco por dentro dele eram duas bordas brigando, e
   amarelo em volta só do escolhido engrossava o contorno a partir dele —
   um degrau no canto, como se o bloco estivesse desalinhado da pilha. O
   escolhido ali só clareia: a forma fica exatamente a da pilha. */
.pilha--solta .bl--escolhido { filter: brightness(1.14) saturate(1.05); }

.bl--perdido {
  background: var(--coral);
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 12px;
}

/* ---- DESFAZER E REFAZER DOS BLOCOS ----
   Flutuam no canto da tela de montagem, e não na barra de cima: ali em
   cima já existem um Desfazer e um Refazer, e eles são da BANCADA. Dois
   pares do mesmo par de botões, em barras diferentes, para coisas
   diferentes, é confusão garantida. */
.blocos__acoes {
  position: absolute;
  top: 10px; right: 12px;
  z-index: 5;
  display: flex;
  gap: 4px;
  padding: 3px;
  border-radius: 10px;
  background: color-mix(in srgb, var(--bg-elevado) 88%, transparent);
  border: 1px solid var(--borda);
  backdrop-filter: blur(4px);
}

.blocos__acao {
  display: grid; place-items: center;
  width: 28px; height: 28px;
  border: 0;
  border-radius: 7px;
  background: none;
  color: var(--texto-medio);
  cursor: pointer;
  transition: background var(--rapido), color var(--rapido);
}

.blocos__acao svg { width: 16px; height: 16px; }
.blocos__acao:hover:not(:disabled) { background: var(--bg-suave); color: var(--texto); }
.blocos__acao:disabled { opacity: .32; cursor: default; }


/* =========================================================================
   PRÉVIA DO CÓDIGO
   ---------------------------------------------------------------------
   A faixa embaixo da tela mostrando o texto gerado. É o motivo pedagógico
   do editor inteiro existir, então ela não é escondível por acidente: fica
   sempre à vista, acompanhando cada bloco que entra.
   ====================================================================== */

.blocos__previa {
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr);
  border-top: 1px solid var(--borda);
  background: var(--bg-elevado);
  min-height: 0;
}

.blocos__previa-topo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 12px;
  font-weight: 700;
  font-size: 10.5px;
  line-height: 1;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--texto-suave);
  border-bottom: 1px solid var(--borda);
}

.blocos__previa pre {
  margin: 0;
  padding: 10px 14px;
  overflow: auto;
  font: 400 12px/18px 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  color: var(--texto);
  white-space: pre;
  tab-size: 2;
}

/* TEXTO ESCURO SOBRE O ÂMBAR, e não branco.

   Branco sobre #f59e0b dá 2,15:1 — medido na página —, e a WCAG AA pede
   4,5:1 para texto normal. Não é detalhe de acabamento: esta faixa é o
   ÚNICO canal por onde o editor de blocos fala com o aluno. Passa por aqui
   todo erro do gerador, o bloco solto, o bloco encaixado embaixo do chapéu,
   o chapéu repetido, o laço que nunca termina. Num projetor de sala de aula
   2,15:1 é texto que não se lê. */
.blocos__recado {
  margin: 0;
  padding: 7px 12px;
  font-weight: 600;
  font-size: 12.5px;
  line-height: 1.35;
  text-transform: none;
  letter-spacing: 0;
  color: #422006;
  background: var(--ambar, #f59e0b);
}

.blocos__recado[hidden] { display: none; }


/* =========================================================================
   O BOTÃO QUE TROCA BLOCOS / TEXTO
   ====================================================================== */

.ide__modo {
  display: inline-flex;
  padding: 2px;
  border-radius: 999px;
  background: var(--bg-suave);
  border: 1px solid var(--borda);
}

.ide__modo button {
  font-weight: 600;
  font-size: 11.5px;
  line-height: 1;
  padding: 6px 12px;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--texto-medio);
  cursor: pointer;
}

.ide__modo button[aria-pressed="true"] {
  background: var(--bg-elevado);
  color: var(--texto);
  box-shadow: 0 1px 2px rgba(15, 23, 42, .12);
}


/* =========================================================================
   TELAS ESTREITAS
   ====================================================================== */

@media (max-width: 860px) {
  .blocos { grid-template-columns: 1fr; grid-template-rows: auto minmax(0, 1fr); }

  /* A trilha vira uma fileira que rola na horizontal, e as amostras
     seguem embaixo dela: é o mesmo desenho, deitado. */
  .blocos__gaveta {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto;
    border-right: 0;
    border-bottom: 1px solid var(--borda);
  }
  .blocos__trilha {
    flex-direction: row;
    gap: 4px;
    overflow-x: auto;
    padding: 6px;
    border-right: 0;
    border-bottom: 1px solid var(--borda);
  }
  .blocos__familia { width: auto; border-radius: 999px; }
  .blocos__familia--aberta { box-shadow: none; }

  .blocos__lista { display: flex; gap: 8px; overflow-x: auto; padding: 8px; }
  .blocos__grupo { position: static; align-self: center; margin: 0 4px; }
  .blocos__amostra { margin-bottom: 0; flex: 0 0 auto; }

  /* A PRÉVIA SAI, E A TELA DE MONTAGEM FICA COM O QUE SOBRA.

     Medido a 820 px de largura, antes: gaveta 227 px, tela de montagem
     171 px, prévia 20 px. Os três inúteis ao mesmo tempo — a prévia não
     mostrava uma linha inteira e na montagem não cabia um "repetir" com
     dois comandos dentro.

     Numa tela estreita não dá para ter as duas coisas, e a escolha é fácil:
     a tela de montagem é onde o aluno TRABALHA, a prévia é onde ele
     confere. Quem quiser ver o código tem a aba "Texto" ao lado, que mostra
     o mesmo sketch inteiro. */
  .blocos__previa { display: none; }

  /* A faixa dela também. Esconder o elemento não some com a linha da grade,
     e ela continuava cobrando os 74 px do `minmax` — a tela de montagem
     ficava com 186 px de uma área de 282. */
  .blocos__area { grid-template-rows: minmax(0, 1fr); }

  /* A dica da lixeira numa linha só: numa gaveta deitada as duas linhas
     custam mais do que ensinam, e o que sobra vira tela de montagem. */
  .blocos__lixo-txt { grid-auto-flow: column; gap: 6px; align-items: baseline; }
  .blocos__lixo     { padding: 6px 12px; }

  /* A FILEIRA DE AMOSTRAS TEM TETO, e é isso que dá espaço à montagem.

     A grade já faz a conta: a gaveta é `auto` e a área é `1fr`. Limitar a
     gaveta é o que sobra para a tela de montagem, sem forçar altura nenhuma
     — um `min-height` na montagem estourava o container e cortava 39 px
     dela, sem barra de rolagem que avisasse. A fileira rola na horizontal,
     então esta altura basta para ela se mostrar. */
  .blocos__lista { max-height: 132px; }

  /* Deitada, a fileira rola de lado: quem some aos poucos é a ponta direita. */
  .blocos__lista {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 18px), transparent);
            mask-image: linear-gradient(to right, #000 calc(100% - 18px), transparent);
  }
}


/* =========================================================================
   CONVIVÊNCIA COM O EDITOR DE TEXTO
   ---------------------------------------------------------------------
   As duas vistas são irmãs dentro do .ide__corpo, que é um grid de duas
   faixas: o editor em cima, o monitor serial embaixo. Só uma das irmãs
   fica em cena por vez — e é preciso dizer isso ao CSS, porque o
   `display: flex` do .editor vence o `hidden` do HTML sozinho.
   ====================================================================== */

.editor[hidden] { display: none; }

/* Blocos pedem largura: a trilha, as amostras, a tela e a prévia não cabem
   nos 540 px que bastam para um editor de texto. A IDE cresce ao entrar no
   modo blocos e volta ao sair. */
.ide--blocos { width: var(--larg-gaveta-blocos); }

/* No modo blocos o monitor serial cede espaço: quem está montando precisa
   ver a tela e o código gerado ao mesmo tempo, e a saída do serial só
   interessa depois de apertar Rodar. */
.ide--blocos .ide__corpo { grid-template-rows: minmax(0, 1fr) minmax(72px, 13%); }
