/* ==========================================================================
   NEXUS theme-final / sections/cases.css
   Secao "cases" (evidencia): 3 destaques (Projeto MEL, FireDash, JX-AI — eram
   4 ate o CEB IPes ser desativado em content.js, 06/08/2026) em layout zebra,
   midia e texto estruturado em rotulos mono alternando de lado. Cada bloco tem
   um gatilho "Saber mais" que abre o MESMO modal do portfolio (06/08/2026,
   pedido do dono — ver a nota grande no fim de partials/cases.js). Territorio
   exclusivo deste agente, junto de partials/cases.js.

   So consome tokens de 01-tokens.css e reaproveita os primitivos de
   03-ui.css (.badge, .link) e o transversal de 04-sections.css/02-base.css
   (.section, .section__head, .eyebrow, .media-frame, .cluster). Nenhum hex,
   nenhum px de raio, nenhuma familia de fonte literal. Motion: so transform
   e opacity animam. O reveal generico cobre a entrada de cada .case-block;
   desde a rodada "evidência com artes rotativas" (06/08/2026) a moldura de
   mídia também anima por padrão em repouso — o crossfade contínuo da
   galeria de 4 artes (bloco 3, `.case-block__shot`, opacity + um leve
   scale de 1,02→1, "esmaecer moderno" pedido do dono), navegável na mão
   por seta/teclado/arrasto e sinalizada por um indicador estilo stories
   (`.case-block__progresso`), com o comportamento (Fisher-Yates + timer +
   pausa de cortesia pós-interação) em partials/cases.js. Convive com o
   efeito global 'scroll-paralaxe' (core/fx.js, dono de `transform` em
   todo `.media-frame img` do site) pelo MESMO trade-off já aceito em
   produção por sections/portfolio.css — ver a nota grande do bloco 3.
   Desde a mesma rodada, cada `.case-block` também é um CARTÃO com
   superfície própria (bloco 2, `--card` + borda + raio) — antes só
   09-skin-cult.css/10-skin-smooth.css davam essa leitura; glass/surface/
   index-sem-pele ganharam o mesmo piso na camada compartilhada.

   Indice:
   1. Lista de cases (ritmo vertical entre cartões)
   2. Bloco de case: grade zebra imagem/texto, cartão com fundo próprio
   3. Midia (moldura + galeria em crossfade + setas + arrasto + indicador)
   4. Corpo: meta, titulo, resumo
   5. Fatos estruturados (problema, restricao, arquitetura, alternativa)
   6. Stack — removida (dado morto em content.js, UI não renderiza mais)
   7. Numeros (regua de prova pontual do case)
   8. Nota — removida (idem) — e acoes (link externo / case privado)
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Lista de cases
   -------------------------------------------------------------------------- */

.cases__list {
  display: grid;
  gap: clamp(var(--space-10), 6vw, var(--space-12));
}

/* --------------------------------------------------------------------------
   2. Bloco de case: grade zebra, cartão com fundo próprio

   auto-fit decide sozinho quando colunas cabem (nunca contagem fixa); a
   inversao de lado e so um ajuste de ordem, aplicado a partir de uma largura
   em que duas colunas de leitura confortavel (min 420px cada) ja cabem.

   FUNDO/DIVISÃO NA CAMADA BASE (06/08/2026, pedido do dono: "no tema
   escuro os cases estão sem cor no fundo, sem divisão"). Até esta rodada
   `.case-block` não tinha superfície própria nenhuma — só a grade zebra
   sobre o fundo da seção, com um hairline `border-block-start` dividindo
   um case do seguinte. Em tema escuro isso lê como "tudo grudado", porque
   caso e fundo de página são a MESMA cor: o divisor de 1px é a única
   pista, e ela é sutil por design (--border, não pensado para carregar
   sozinho a separação de blocos inteiros).

   A correção dá a cada case a MESMA leitura de cartão que 09-skin-cult.css
   e 10-skin-smooth.css já davam (cada um com a própria identidade, cult em
   chapa rebitada, smooth em painel liso) — só que agora na folha
   COMPARTILHADA, então glass/surface/index-sem-pele (que não tinham
   tratamento próprio nenhum) ganham o mesmo piso. `--card`, não
   `--surface-2`: é o token de SUPERFÍCIE DE CONTEÚDO elevado (o mesmo que
   `.card` genérico usa, 03-ui.css), com o contraste já calibrado contra
   `--background` nos dois temas — não um valor novo. cult/smooth
   continuam intactos: os seletores deles (`:is([data-skin=...]) .case-block`)
   pesam mais que este por causa do atributo, então vencem sem depender de
   ordem de arquivo.

   O DIVISOR ANTIGO (`.case-block + .case-block { border-block-start }`)
   SAIU: virou redundante — dois cartões com borda própria em TODOS os
   lados, um embaixo do outro, já têm separação visual pelo próprio
   contorno + o gap da lista (`.cases__list`, reduzido de
   clamp(--space-12,...,--space-16) para clamp(--space-10,...,--space-12)
   porque agora o respiro é ENTRE CARTÕES, não entre um hairline e o
   próximo bloco de texto — o vão didático antigo, pensado para uma lista
   sem cartão, ficaria exagerado ao lado de bordas que já demarcam cada
   item). */
.case-block {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 26rem), 1fr));
  gap: var(--space-8);
  align-items: center;
  padding: var(--space-6);
  border-radius: var(--radius-lg);
  border: var(--hairline) solid hsl(var(--border));
  background-color: hsl(var(--card));
}

@media (min-width: 60rem) {
  .case-block {
    gap: var(--space-12);
  }

  .case-block--flip .case-block__media {
    order: 2;
  }

  .case-block--flip .case-block__body {
    order: 1;
  }
}

/* --------------------------------------------------------------------------
   3. Midia
   -------------------------------------------------------------------------- */

.case-block__frame {
  /* 2/1 = proporção real das artes conceituais (assets/img/arte/*.webp,
     1600×800, ver GALERIA_DIMS em partials/cases.js) — a mesma proporção de
     .portfolio__card-media em sections/portfolio.css, porque é o MESMO
     gerador de arte para os dois usos.

     Era 3/2 (06/08/2026: mudou de 4/3 para 3/2 quando os mockups de case
     entraram, ver histórico abaixo) até a rodada "evidência com artes
     rotativas" trocar o conteúdo da moldura de mockup fotográfico
     (item.imagem, 1200×800, 3/2) para a galeria de 4 artes conceituais
     (item.galeria, 1600×800, 2/1) — moldura e asset continuam um contrato
     só, e o valor acompanhou a troca de asset.

     HISTÓRICO (3/2, quando a moldura mostrava item.imagem): "Era 4/3, e o
     cover recortava ~11% da largura das três imagens (reclamação do dono,
     05/08/2026: 'tá cortado')." */
  --media-ratio: 2 / 1;
}

/* Case privado: nenhuma alteracao dinamica, so um tratamento visual estatico
   (nao anima) para diferenciar do case com link publico.

   SÓ `filter`, NÃO `opacity` (06/08/2026, rodada "evidência com artes
   rotativas"). Até a rodada anterior a moldura tinha uma única <img>
   estática e `opacity: 0.86` aqui era inofensivo. Agora há 4 camadas
   empilhadas (`.case-block__shot`, bloco 3 abaixo) cujo crossfade TAMBÉM
   escreve `opacity` (0 ou 1, por `[data-ativo]`) — e a regra de aqui,
   por ter 2 classes + 1 tipo (0,2,1), pesa mais que `.case-block__shot`
   (0,1,0) e mais até que `.case-block__shot[data-ativo]` (0,2,0), então
   venceria a briga de especificidade e travaria as 4 camadas em 0,86 de
   opacidade simultânea — nenhuma escondida, nenhum crossfade visível. A
   correção é a mesma disciplina de core/fx.js (scroll-paralaxe) e
   sections/portfolio.css (crossfade) convivendo em CAMADAS/PROPRIEDADES
   diferentes: aqui o tratamento "case privado" fica só em `filter`
   (grayscale + um leve escurecimento em brightness, no lugar da opacidade
   fixa), e `opacity` continua propriedade exclusiva do crossfade. */
.case-block--private .case-block__frame img {
  filter: grayscale(35%) brightness(0.94);
}

/* GALERIA EM CROSSFADE, 4 ARTES (06/08/2026, rodada "evidência com artes
   rotativas"; transição atualizada na mesma data, rodada "esmaecer
   moderno"). As 4 camadas já saem empilhadas de 04-sections.css
   (`.media-frame img { position: absolute; inset: 0 }`, compartilhado — não
   redeclarado aqui). Esta regra decide só qual está pintada, com que
   transição e com que leve escala — MESMO padrão de `.portfolio__shot`/
   `.portfolio__shot[data-ativo]` (sections/portfolio.css §10.2), inclusive
   o `transform: scale(...)`, que a primeira versão desta regra tinha
   deixado de fora de propósito (ver histórico abaixo). Sem `--shot-zoom`
   de hover (cases não tem essa interação), só o par de escalas do
   crossfade: 1,02 na camada que ainda não é a ativa, 1 na ativa — "um leve
   esmaecer com scale de 1,02→1", pedido literal do dono, discreto o
   bastante para "não chamar muita atenção".

   HISTÓRICO (por que a primeira versão não tinha `transform`, e por que
   voltou): `transform` em `.media-frame img` é também o alvo do efeito
   global 'scroll-paralaxe' (core/fx.js, ligado por padrão em TODO
   `.media-frame img` do site, inclusive estas 4 camadas). A versão
   original desta regra evitava a propriedade inteira para as duas nunca
   competirem. O pedido do scale tornou essa fuga insustentável — e não
   precisa ser sustentada, porque `.portfolio__shot` JÁ convive com o mesmo
   paralaxe fazendo a MESMA coisa (scale + crossfade) em produção, todos os
   dias, nos 15 cartões do portfólio: durante a transição da troca, a
   regra de classe (`transition-property` cobrindo opacity E transform)
   vence por CSS Cascading §4.1 ("transition declarations" têm prioridade
   sobre qualquer declaração normal, inclusive inline); fora da janela de
   transição, o paralaxe pode reescrever `transform` por cima — o mesmo
   trade-off aceito, replicado aqui em vez de reinventado. Ele é inofensivo
   na prática porque as 4 camadas ocupam a MESMA caixa (mesmo
   getBoundingClientRect), então o paralaxe desloca as 4 igual — nunca
   desalinha a pilha, só sobrepõe um deslocamento vertical sutil ao scale
   do crossfade.

   MESMA técnica de "sem dip" do portfólio: a imagem que ENTRA sobe de
   camada (`z-index: 1`) e começa a aparecer no mesmo instante
   (`transition-delay: 0s`); a que SAI só começa a desaparecer depois de
   `--dur-slow` (quando já está inteiramente coberta pela que entrou), então
   nunca há um instante em que a soma das opacidades seja menor que 1 — sem
   isso, a meio caminho de cada troca apareceria um piscar de `--muted` (o
   fundo da moldura) por baixo das duas imagens semitransparentes. */
/* `border-radius: inherit` SAIU daqui em 06/08/2026 (item 1 da rodada
   seguinte, "borda vazando, de novo"): o mesmo defeito documentado abaixo
   (camada composta do `transform` clipando ao retângulo, não ao raio do
   pai) voltou a aparecer em OUTRAS molduras que nunca passaram por este
   arquivo — cartão a cartão não escala. A correção subiu para a CAMADA
   COMPARTILHADA (`.media-frame img/video/picture/canvas`, 04-sections.css),
   que já dá `border-radius: inherit` a TODA imagem/vídeo dentro de
   `.media-frame`, `.case-block__shot` incluído — repetir a declaração aqui
   seria política local sem propósito, então saiu (regra de altitude: quem
   corrige na camada de baixo remove a exceção de cima).

   HISTÓRICO (por que a causa é essa, mantido porque a explicação continua
   valendo): `.case-block__frame` clipa com `overflow: hidden` +
   `border-radius: var(--radius-lg)` (herdado de `.media-frame`,
   04-sections.css) — mas `transform` (o scale de 1,02→1 deste bloco)
   promove o elemento a uma CAMADA DE COMPOSIÇÃO própria (GPU), e alguns
   motores de renderização (Safari/WebKit em especial) clipam essa camada
   composta ao RETÂNGULO do pai, não à forma arredondada — o filete é
   literalmente o canto QUADRADO da camada composta assomando por trás do
   canto ARREDONDADO que o overflow do pai deveria estar recortando. Não
   acontecia em `.portfolio__shot` (sections/portfolio.css, mesmo mecanismo
   de scale) porque `.portfolio__card-media` é `border-radius: 0` — reto,
   sem canto arredondado para vazar (e `inherit`, agora vindo da camada
   compartilhada, acompanha esse `0` sem precisar de exceção nenhuma). */
.case-block__shot {
  opacity: 0;
  z-index: 0;
  transform: scale(1.02);
  transition-property: opacity, transform;
  transition-duration: calc(var(--dur-slow) * var(--motion));
  transition-timing-function: var(--ease-io), var(--ease-out);
  transition-delay: calc(var(--dur-slow) * var(--motion)), 0s;
}

.case-block__shot[data-ativo] {
  opacity: 1;
  z-index: 1;
  transform: scale(1);
  transition-delay: 0s, 0s;
}

/* SETAS MANUAIS (06/08/2026, pedido do dono: "setas prev/next discretas
   para passar as artes na mão"). Botão real, focável (partials/cases.js,
   setasHTML()) — ao contrário do mostruário de verticais do portfólio, que
   virou decorativo por pedido explícito do dono, este É clique de verdade,
   então a moldura carrega a afordância certa. "Discretas": baixa opacidade
   em repouso, cheia sob hover/foco — nunca escondida por completo (uma
   seta invisível até o hover falha para quem navega por teclado ou toque,
   que não têm ":hover"). z-index acima das 4 camadas de arte (`1`) e do
   véu de legibilidade de `.media-frame::after` (04-sections.css, sem
   z-index próprio, então qualquer valor positivo aqui já fica por cima). */
.case-block__seta {
  position: absolute;
  inset-block: 0;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: clamp(2.5rem, 4vw + 1rem, 3rem);
  border: 0;
  background: linear-gradient(90deg, hsl(var(--scrim) / 0.3), hsl(var(--scrim) / 0));
  color: hsl(0 0% 100%);
  opacity: 0.55;
  cursor: pointer;
  transition:
    opacity calc(var(--dur-fast) * var(--motion)) var(--ease-out),
    background-color calc(var(--dur-fast) * var(--motion)) var(--ease-out);
}

.case-block__seta--prev {
  inset-inline-start: 0;
}

.case-block__seta--prev .nx-icon {
  transform: rotate(180deg);
}

.case-block__seta--next {
  inset-inline-end: 0;
  background-image: linear-gradient(270deg, hsl(var(--scrim) / 0.3), hsl(var(--scrim) / 0));
}

.case-block__frame:hover .case-block__seta,
.case-block__seta:hover,
.case-block__seta:focus-visible {
  opacity: 1;
}

.case-block__seta:hover {
  background-color: hsl(var(--scrim) / 0.22);
}

.case-block__seta:focus-visible {
  outline: 2px solid hsl(var(--ring));
  outline-offset: -2px;
}

/* ARRASTO/SWIPE (06/08/2026, pedido do dono: "por que não dá pra trocar
   arrastando"). `cursor: grab` avisa a afordância antes do primeiro
   toque — mesmo padrão do carrossel do modal de portfólio
   (`.portfolio-modal__track`, sections/portfolio.css §13.2), sem o
   `grabbing`/`is-dragging` de lá porque aqui o gesto não arrasta um
   track visualmente (a galeria é crossfade, não posição): o cursor muda
   de intenção, o resultado só aparece na troca de arte no fim do gesto
   (partials/cases.js, pointerup). `touch-action: pan-y` deixa o toque
   vertical (rolar a página) atravessar livre — só o eixo horizontal é
   capturado pelo JS. */
.case-block__frame {
  cursor: grab;
  touch-action: pan-y;
}

/* INDICADOR DE PROGRESSO, ESTILO STORIES (06/08/2026, pedido do dono:
   "bolinhas/tracinho embaixo mostrando quantos tem e vai andando").
   `case-block__progresso` é IRMÃO de `.media-frame` (não filho — ver
   midiaHTML(), partials/cases.js): "sob a moldura" é pedido literal, a
   barra fica ABAIXO da mídia, nunca sobreposta a ela.

   Cada `.case-block__dash` é um botão real, clicável (pula direto pra
   arte daquele índice, partials/cases.js). A trilha (`::before`, cinza
   fixo em --border) é o traço "vazio"; `.case-block__dash-fill` é a
   camada que preenche por cima, animada via `transform: scaleX()`
   (`transform-origin: left`, cresce da esquerda pra direita) escrito
   inline pelo comportamento — só `transform` anima, nunca `width`
   (§6: só transform/opacity em efeito contínuo). SEM ANIMAÇÃO SOB
   `--motion: 0`/reduced-motion: o JS (atualizarDashes(), partials/
   cases.js) já checa `movimentoLigado()` antes de escrever a
   `transition` inline — sob motion 0 o traço ativo salta direto pra
   cheio, sem transição nenhuma, só o ESTADO (pedido literal do dono:
   "sem animação de preenchimento, só estado"). */
.case-block__progresso {
  display: flex;
  gap: var(--space-2);
  margin-block-start: var(--space-3);
  padding-inline: var(--space-1);
}

/* AS "BOLINHAS ENORMES" DO CELULAR MORAVAM AQUI (06/08/2026, terceiro
   relato do dono no mesmo ponto: "no celular as bolinhas do carrossel
   aparecem enormes; já foi mexido uma vez e não resolveu").

   O QUE ELE VIA, medido em 390×844 com ponteiro grosso REAL
   (`Emulation.setDeviceMetricsOverride` mais `setTouchEmulationEnabled`,
   nas cinco páginas): cada traço deste indicador renderizava **44×44px**,
   com `border-radius: var(--radius-full)` — quatro BOLAS cheias, com o
   preenchimento em `--primary` na ativa, sob a moldura de cada case. Não
   era o ponto do modal de produto: aquele já media 6,0×6,0px e estava
   correto desde a rodada anterior, que é exatamente por que "mexer" não
   resolveu — o conserto tinha sido feito no componente errado.

   A CAUSA, e ela é a armadilha que o §7.5 avisa: `02-base.css` §4 impõe
   `min-block-size`/`min-inline-size: var(--tap-min)` a TODO `button` sob
   `(pointer: coarse)`. Esta regra declarava `block-size: 0.125rem` (na
   faixa de celular, bloco mais abaixo) mas NENHUM `min-block-size` — e
   `min-*` sempre vence `block-size` quando é maior. O traço de 2px de
   altura virava 44px de altura. A largura vinha do mesmo lugar (o bloco
   `(pointer: coarse)` no fim desta folha subia `inline-size` para 2,75rem
   PARA VALER O ALVO DE TOQUE, ou seja, engordando o elemento VISUAL em vez
   de só a área tocável), e o raio `--radius-full` fechava o círculo.

   A CORREÇÃO tem duas metades, e as duas são regra de casa:
     1. o piso do elemento passa a ser declarado aqui, do tamanho do traço,
        anulando o mínimo genérico de botão sem `!important` (0,1,0 de
        classe contra 0,0,1 de tipo);
     2. os 44px do §7.5 continuam existindo, e existem onde sempre
        deveriam: no pseudo-elemento invisível, agora nos DOIS eixos (ele
        já cobria o vertical). O bloco `(pointer: coarse)` do fim da folha
        deixa de esticar o traço e passa a abrir o `gap` do grupo, para as
        áreas de 44px ladrilharem sem se sobrepor.

   `appearance: none` continua logo abaixo, pelo motivo do Safari já
   registrado — os dois problemas são primos, mas são independentes. */
.case-block__dash {
  position: relative;
  /* Acima da arte ativa, e é a caixa de TOQUE que precisa disso, não o
     traço. `.case-block__shot[data-ativo]` sobe para `z-index: 1` (bloco do
     crossfade, acima) e, sem `z-index` próprio aqui, o `::before` de 46px
     do traço ficava POR BAIXO dela na faixa em que os dois se cruzam:
     medido com `elementFromPoint`, o ponto a 22px acima do centro do traço
     resolvia para `.case-block__shot`, ou seja, o alvo existia e não era
     alcançável. O custo é uma tira de ~13px na base da imagem, sobre a
     largura dos traços, onde o arrasto de troca de arte não começa (quem
     recebe o ponteiro ali é o traço). Aceito: é a base da moldura, o gesto
     de arrastar tem a imagem inteira acima dela, e a alternativa seria
     engordar o traço de novo. */
  z-index: 2;
  flex: 1 1 0;
  block-size: 0.1875rem;
  min-block-size: 0.1875rem;
  min-inline-size: 1.25rem;
  border: 0;
  border-radius: var(--radius-full);
  background-color: hsl(var(--border));
  cursor: pointer;
  padding: 0;
}

/* Alvo de toque do §7.5 sem esticar a barra visual: a área clicável real
   cresce por um pseudo-elemento invisível, não pelo `block-size` do
   traço (que ficaria grosso demais).

   `overflow: hidden` SAIU DAQUI, e a remoção é o que faz este alvo existir
   de verdade (06/08/2026). Ele estava no traço para o preenchimento não
   vazar da cápsula arredondada — só que recorte de overflow vale também
   para o TESTE DE ACERTO: o `::before` de coordenadas negativas era
   desenhado fora da caixa do pai e, portanto, cortado junto, o que
   significa que a área estendida nunca chegou ao dedo. Quem arredonda o
   preenchimento agora é o raio do próprio preenchimento (`border-radius:
   inherit`, abaixo), sem clipe nenhum no caminho. */
.case-block__dash::before {
  content: "";
  position: absolute;
  /* A caixa de toque é `--tap-min` mais 2px, e os 2px não são enfeite: o
     harness de auditoria (`scripts/shots.mjs`, areaDeToqueOk()) testa os
     quatro pontos cardeais a EXATAMENTE 22px do centro. Com a caixa em
     44px cravados, esses pontos caem na fronteira e o `elementFromPoint`
     resolve para o vizinho ou para o que está atrás, por arredondamento —
     o alvo existe e mesmo assim o teste reprova. Com 46px, os 22px ficam
     dentro por 1px de cada lado.
     A porcentagem resolve contra a caixa do próprio traço (altura no eixo
     de bloco, largura no eixo em linha), então a mesma conta serve para os
     dois eixos, com o traço estreito do celular ou com o largo do
     desktop. */
  --alvo-toque: calc(var(--tap-min) + 0.125rem);
  inset-block: calc((var(--alvo-toque) - 100%) / -2);
  inset-inline: 0;
}

.case-block__dash-fill {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  transform-origin: left;
  transform: scaleX(0);
  background-color: hsl(var(--primary));
}

.case-block__dash:focus-visible {
  outline: 2px solid hsl(var(--ring));
  outline-offset: 2px;
}

/* Correção de motor (06/08/2026, print do dono no Safari): tracinhos e
   setas são <button> e o Safari mantém o cromo nativo (pílula com altura
   mínima e padding próprio) enquanto `appearance` não for zerado — no
   Chrome o estilo autoral já derrubava o nativo e os 3px de projeto
   valiam. Zerar appearance garante a mesma régua em qualquer motor. */
.case-block__seta,
.case-block__dash {
  appearance: none;
  -webkit-appearance: none;
  padding: 0;
}

/* Pedido do dono (06/08/2026): no celular o conjunto de navegação pesava
   ("tem que ficar sutil e menorzinho"). Setas mais estreitas e discretas;
   os traços param de esticar a linha inteira e viram um grupo curto,
   centralizado e mais fino. A área de toque continua garantida pelo
   ::before de --tap-min acima, que não muda com a régua visual. */
@media (max-width: 639.98px) {
  .case-block__seta {
    inline-size: 2rem;
    opacity: 0.4;
  }

  .case-block__progresso {
    justify-content: center;
    gap: var(--space-1);
    margin-block-start: var(--space-2);
  }

  .case-block__dash {
    flex: 0 0 auto;
    inline-size: 1.5rem;
    block-size: 0.125rem;
    /* Acompanha o `block-size`: sem isto, o piso de 0,1875rem declarado no
       bloco 3 venceria e o traço ficaria mais grosso no celular do que no
       desktop, o oposto do pedido "sutil e menorzinho". */
    min-block-size: 0.125rem;
  }
}

/* DEDO, não largura de tela (§7.5 do contrato: o teste de alvo de toque é
   `pointer: coarse`, não viewport estreita).

   ESTE BLOCO ERA A CAUSA DAS "BOLINHAS ENORMES" (06/08/2026 — o diagnóstico
   completo está no bloco 3, em `.case-block__dash`). Ele subia o
   `inline-size` do traço para 2,75rem, ou seja, engordava o ELEMENTO
   VISUAL para satisfazer o alvo de toque; junto com o `min-block-size` de
   44px que `02-base.css` impõe a todo `button` sob ponteiro grosso, e com
   o raio `--radius-full` da cápsula, o resultado renderizado era uma BOLA
   de 44×44px por arte. Medido, quatro delas sob a moldura de cada case, em
   todas as cinco peles.

   A régua visual agora é a mesma do olho (1,5rem × 2px, bloco acima) e os
   44px vão inteiros para o pseudo-elemento, nos dois eixos: o `::before`
   passa a se estender para os lados até fechar `--tap-min`, e o `gap` do
   grupo abre o suficiente para que as áreas de dois traços vizinhos NÃO se
   sobreponham (sem isso o alvo existe mas pertence ao vizinho, porque em
   sobreposição quem ganha o toque é o último do documento). Passo entre
   traços = 1,5rem de traço + gap = `--tap-min`, exatamente.

   As setas continuam com 2,75rem de largura porque nelas o alvo É a caixa:
   são controles com área própria, não um ponto de 2px. */
@media (pointer: coarse) {
  .case-block__dash::before {
    inset-inline: calc((var(--alvo-toque) - 100%) / -2);
  }

  .case-block__seta {
    inline-size: 2.75rem;
  }
}

/* O `gap` alargado só onde o traço é estreito (celular). Em tablet ou
   notebook de toque o traço já é `flex: 1 1 0` e mede muito mais que
   `--tap-min` sozinho, então abrir o vão ali seria mexer no ritmo visual
   sem nenhum ganho de alvo. */
@media (pointer: coarse) and (max-width: 639.98px) {
  .case-block__progresso {
    gap: calc(var(--tap-min) + 0.125rem - 1.5rem);
  }
}

/* --------------------------------------------------------------------------
   4. Corpo: meta, titulo, resumo
   -------------------------------------------------------------------------- */

.case-block__body {
  display: grid;
  gap: var(--space-5);
  align-content: start;
}

.case-block__meta {
  gap: var(--space-4);
}

/* Pedido do dono (06/08/2026): nos cases espelhados a vertical ("Segurança
   Pública", "Energia") morria no MEIO do cartão — a linha de meta vive na
   coluna de texto, e com a coluna à esquerda o fim da linha é a borda
   interna, não o canto do cartão. Espelha-se a linha junto com o layout:
   no flip a vertical vai para o canto EXTERNO (esquerdo) e o índice para a
   borda interna — o mesmo desenho dos cases não-espelhados, refletido.
   row-reverse mexe só na apresentação; a ordem de leitura (índice →
   vertical) continua a do DOM. */
.case-block--flip .case-block__meta {
  flex-direction: row-reverse;
}

.case-block__index {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  letter-spacing: var(--tracking-mono);
  color: hsl(var(--muted-foreground));
  font-variant-numeric: tabular-nums;
}

.case-block__vertical {
  color: hsl(var(--primary));
}

.case-block__title {
  font-size: var(--fs-h2);
  line-height: var(--lh-display);
}

.case-block__resumo {
  max-width: var(--measure);
  font-size: var(--fs-lead);
  line-height: 1.55;
  color: hsl(var(--muted-foreground));
}

/* --------------------------------------------------------------------------
   5. Fatos estruturados
   -------------------------------------------------------------------------- */

.case-block__facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: var(--space-5) var(--space-6);
  padding-block: var(--space-5);
  margin: 0;
  border-block: var(--hairline) solid hsl(var(--border));
}

.case-block__fact {
  display: grid;
  gap: var(--space-2);
  margin: 0;
}

.case-block__fact-label {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  letter-spacing: var(--tracking-mono);
  text-transform: uppercase;
  color: hsl(var(--muted-foreground));
}

.case-block__fact-value {
  margin: 0;
  font-size: var(--fs-sm);
  line-height: var(--lh-body);
  color: hsl(var(--foreground));
}

/* --------------------------------------------------------------------------
   6. Stack — REMOVIDA (06/08/2026, pedido do dono: "remover o bloco Stack
   de TODOS os cases — a UI não renderiza mais"). `.case-block__stack`,
   `.case-block__stack-label` e `.case-block__stack-item` perderam o alvo
   (partials/cases.js parou de escrever `stackBadges()`, ver a nota lá) e
   saíram daqui junto. `item.stack` continua em content.js como dado
   (documentado lá). ÓRFÃO FORA DESTE TERRITÓRIO: `.case-block__stack-item`
   ainda aparece em seletores de pele (06/08/09/10-skin-*.css, junto de
   outros crachás como `.badge--outline`/`.govtech-chip`) — não é
   território deste agente mexer lá, e um seletor de pele sem elemento
   correspondente não gera erro, só fica sem alvo, mesma tolerância já
   documentada para `.portfolio__note` em sections/portfolio.css.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   7. Numeros
   Reaproveita .stat de 04-sections.css, so compactado para caber ao lado do
   corpo de texto em vez de ocupar uma regua inteira de largura de secao.
   -------------------------------------------------------------------------- */

.case-block__numbers {
  gap: var(--space-8);
  padding-block-start: var(--space-1);
}

.case-block__stat {
  gap: var(--space-1);
}

.case-block__stat .stat__value {
  font-size: var(--fs-h3);
}

.case-block__stat-note {
  font-size: var(--fs-xs);
  color: hsl(var(--muted-foreground));
}

/* --------------------------------------------------------------------------
   8. Nota (REMOVIDA, mesmo pedido e mesma rodada do bloco 6 — "remover a
   nota de rodapé dos cases... UI não renderiza") e acoes

   `.case-block__nota` perdeu o alvo (caseBlock() parou de escrever o
   parágrafo, partials/cases.js) e saiu. `item.nota` continua em content.js
   como dado (documentado lá) — exceto no FireDash, onde o dono reprovou o
   TEXTO da nota, não só a renderização: o campo virou `null` na fonte.
   -------------------------------------------------------------------------- */

.case-block__actions {
  align-items: center;
  gap: var(--space-4);
  padding-block-start: var(--space-2);
}

.case-block__status {
  background-color: hsl(var(--surface-2));
  color: hsl(var(--foreground));
  border-color: hsl(var(--border));
}

/* Crachá de acesso (06/08/2026, reforma editorial, itens B e I da spec do
   dono). Irmão do de maturidade, não substituto: são dois eixos, e a linha de
   ação passa a mostrar os dois lado a lado. Sem fundo, só contorno, para o
   par não virar duas manchas iguais e o olho ler primeiro a maturidade.
   `data-tone="privado"` afina a tinta, o mesmo recurso (não a mesma regra)
   que .portfolio__badge[data-tone] já usa: nenhuma cor nova entra, só o par
   --muted-foreground/--border que a paleta neutra já publica. */
.case-block__acesso {
  background-color: transparent;
  color: hsl(var(--foreground));
  border-color: hsl(var(--border));
}

.case-block__acesso[data-tone="privado"] {
  color: hsl(var(--muted-foreground));
}

.case-block__link {
  font-size: var(--fs-sm);
}

/* "SABER MAIS" (06/08/2026, pedido do dono: o case abre o MESMO modal do
   portfólio). Mesmo porte e mesma tinta do link que existia aqui — é o
   primitivo `.link` de 03-ui.css nos dois casos, e o gatilho do cartão de
   produto (`.portfolio__link`) usa exatamente a mesma régua, para os dois
   "Saber mais" da página lerem como o mesmo controle. `margin-inline-start:
   auto` empurra o botão para a ponta oposta aos crachás na mesma linha,
   que é a leitura que a linha de ação já tinha quando havia link externo.
   A seta acompanha o hover do bloco, como no portfólio. */
.case-block__saber {
  font-size: var(--fs-sm);
  margin-inline-start: auto;
}

.case-block__saber svg {
  transition: transform calc(var(--dur-fast) * var(--motion)) var(--ease-out);
}

.case-block:hover .case-block__saber svg,
.case-block__saber:hover svg,
.case-block__saber:focus-visible svg {
  transform: translate3d(0.15em, 0, 0);
}
