/* =========================================================
   GNN   componentes só desta página

   Camada 3 de 3: styles.css → llm.css → didatica.css → aqui.
   O mapa do grafo, as linhas de vetor, as curvas de treino e
   as tabelas de peso por vizinho.
   ========================================================= */

/* =========================
   Mapa do grafo
   ========================= */
.gnn-map {
  margin-top: var(--md);
  aspect-ratio: 1.55;
  max-height: 340px;
  border: 1px solid var(--hair-soft);
  border-radius: 10px;
  background: rgba(14, 16, 22, .015);
  overflow: hidden;
}

.gnn-map svg {
  display: block;
  width: 100%;
  height: 100%;
}

.gnn-edge {
  stroke: rgba(14, 16, 22, .16);
  stroke-width: .35;
  vector-effect: non-scaling-stroke;
  transition: stroke .25s ease, opacity .25s ease;
}

.gnn-edge.is-dim { opacity: .22; }

.gnn-edge.is-hot {
  stroke: var(--c-purple);
  stroke-width: 1;
}

.gnn-node circle {
  fill: var(--c);
  stroke: #fff;
  stroke-width: .5;
  vector-effect: non-scaling-stroke;
  cursor: pointer;
  transition: opacity .25s ease;
}

.gnn-node.is-dim { opacity: .25; }

/* o nó com rótulo tem anel: é a informação que decide o treino */
.gnn-node.is-labeled circle {
  stroke: var(--bg);
  stroke-width: 1.1;
}

.gnn-node.is-sel circle {
  stroke: var(--bg);
  stroke-width: 1.4;
}

/* previsão errada: cruz vermelha por cima, sem depender só de cor */
.gnn-node.is-wrong circle {
  stroke: var(--c-pink);
  stroke-width: 1.2;
  stroke-dasharray: 1.2 .8;
}

/* =========================
   Linhas de vetor
   ========================= */
.gnn-vec {
  display: flex;
  align-items: flex-end;
  gap: 1px;
  flex: 1;
  height: 26px;
  padding: 2px;
  border-radius: 5px;
  background: rgba(14, 16, 22, .03);
}

.gnn-vec i {
  flex: 1;
  min-width: 2px;
  border-radius: 1px;
  background: var(--c);
}

.gnn-terms {
  display: flex;
  flex-wrap: wrap;
  gap: calc(var(--sm) / 2);
  margin-top: var(--sm);
}

.gnn-truth { margin-top: var(--sm); }

/* uma linha por nó na etapa de propagação */
.gnn-prows {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-top: var(--md);
  max-height: 300px;
  overflow-y: auto;
}

.gnn-prow {
  display: flex;
  align-items: center;
  gap: var(--sm);
  padding: 2px calc(var(--sm) / 1.6);
  border-radius: 6px;
  cursor: pointer;
  transition: background .2s ease;
}

.gnn-prow:hover { background: rgba(14, 16, 22, .04); }
.gnn-prow.is-sel { background: rgba(14, 16, 22, .06); }

.gnn-prow__n {
  flex: none;
  width: 24px;
  font-size: calc(var(--sm) / 1.1);
  text-align: right;
  color: var(--c);
  font-weight: 700;
}

/* =========================
   Vizinhos
   ========================= */
.gnn-neighs {
  display: flex;
  flex-wrap: wrap;
  gap: calc(var(--sm) / 1.6);
  margin-top: var(--sm);
}

.gnn-neigh {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: calc(var(--sm) / 1.8) calc(var(--sm) / 1.2);
  border: 1px solid var(--hair);
  border-radius: 8px;
  background: #fff;
  transition: border-color .2s ease, transform .2s ease;
}

.gnn-neigh:hover {
  border-color: var(--c);
  transform: translateY(-2px);
}

.gnn-neigh__n {
  font-size: var(--md);
  font-weight: 700;
  color: var(--c);
}

.gnn-neigh__cls {
  font-size: calc(var(--sm) / 1.2);
  color: var(--ink-45);
}

/* o vizinho da mesma classe é o que ajuda: marca discreta */
.gnn-neigh.is-same { background: color-mix(in srgb, var(--c) 8%, #fff); }

/* =========================
   Estatísticas e veredito
   ========================= */
.gnn-stats {
  display: flex;
  flex-wrap: wrap;
  gap: calc(var(--sm) / 1.4);
  margin-top: var(--md);
}

.gnn-verdict {
  margin-top: var(--md);
  font-size: calc(var(--md) / 1.02);
  line-height: 1.5;
  color: var(--ink-80);
}

.gnn-verdict.is-bad { color: var(--c-pink); }

/* =========================
   Curvas
   ========================= */
.gnn-curve {
  margin-top: var(--md);
  height: 130px;
  border: 1px solid var(--hair-soft);
  border-radius: 9px;
  background: rgba(14, 16, 22, .02);
  overflow: hidden;
}

.gnn-curve--tall { height: 200px; }

.gnn-curve svg {
  display: block;
  width: 100%;
  height: 100%;
}

.gnn-curve polyline {
  fill: none;
  stroke: var(--c-blue);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
}

/* precisam do seletor descendente: `.gnn-curve polyline` acima já tem
   especificidade 0-1-1, e uma classe sozinha perderia dele */
.gnn-curve polyline.gnn-curve__loss { stroke: var(--c-pink); }
.gnn-curve polyline.gnn-curve__acc { stroke: var(--c-green); }
.gnn-curve polyline.gnn-curve__mlp { stroke: var(--c-amber); }
.gnn-curve polyline.gnn-curve__gcn { stroke: var(--c-purple); }

.gnn-curve__now {
  stroke: var(--ink-45);
  stroke-width: 1;
  stroke-dasharray: 3 3;
  vector-effect: non-scaling-stroke;
}

/* a linha do acaso na curva de AUC */
.gnn-curve__base {
  stroke: var(--hair);
  stroke-width: 1;
  stroke-dasharray: 2 3;
  vector-effect: non-scaling-stroke;
}

/* =========================
   Confronto MLP × GCN
   ========================= */
.gnn-versus {
  display: flex;
  flex-direction: column;
  gap: var(--sm);
  margin-top: var(--md);
}

.gnn-vs {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 2.2fr auto;
  align-items: center;
  gap: var(--sm);
}

.gnn-vs__name {
  font-size: calc(var(--md) / 1.06);
  color: var(--ink-80);
}

.gnn-vs__track {
  height: 18px;
  border-radius: 6px;
  background: rgba(14, 16, 22, .06);
  overflow: hidden;
}

.gnn-vs__track i {
  display: block;
  height: 100%;
  border-radius: 6px;
  background: var(--c);
  transition: width .35s ease;
}

.gnn-vs__v {
  min-width: 56px;
  text-align: right;
  font-weight: 700;
}

/* =========================
   Arquiteturas e pesos
   ========================= */
.gnn-archs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sm);
}

.gnn-arch {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 160px;
  padding: var(--sm);
  border: 1px solid var(--hair);
  border-radius: 10px;
  background: #fff;
  text-align: left;
  transition: border-color .2s ease, background .2s ease;
}

.gnn-arch:hover { border-color: var(--ink-45); }

.gnn-arch.is-on {
  border-color: var(--c);
  background: color-mix(in srgb, var(--c) 8%, #fff);
}

.gnn-arch__name {
  font-size: var(--md);
  font-weight: 700;
}

.gnn-arch__tag {
  font-size: calc(var(--sm) / 1.1);
  color: var(--ink-45);
}

.gnn-wrows {
  display: flex;
  flex-direction: column;
  gap: calc(var(--sm) / 2.2);
  margin-top: var(--md);
  max-height: 300px;
  overflow-y: auto;
}

.gnn-wrow {
  display: grid;
  grid-template-columns: 28px minmax(0, 88px) 1fr 52px;
  align-items: center;
  gap: calc(var(--sm) / 1.4);
}

.gnn-wrow__n {
  font-size: calc(var(--sm) / 1.06);
  font-weight: 700;
  text-align: right;
  color: var(--c);
}

.gnn-wrow__tag {
  font-size: calc(var(--sm) / 1.15);
  color: var(--ink-45);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.gnn-wrow__bar {
  height: 10px;
  border-radius: 4px;
  background: rgba(14, 16, 22, .06);
  overflow: hidden;
}

.gnn-wrow__bar i {
  display: block;
  height: 100%;
  border-radius: 4px;
  background: var(--c);
}

.gnn-wrow__v {
  font-size: calc(var(--sm) / 1.06);
  text-align: right;
  color: var(--ink-60);
}

/* =========================
   Responsivo
   ========================= */
@media (max-width: 900px) {
  .gnn-map { aspect-ratio: 1.25; }
  .gnn-curve--tall { height: 160px; }
}

@media (max-width: 640px) {
  .gnn-map { aspect-ratio: 1; }
  .gnn-vs { grid-template-columns: 1fr auto; }
  .gnn-vs__track { grid-column: 1 / -1; }
  .gnn-wrow { grid-template-columns: 24px 1fr 44px; }
  .gnn-wrow__tag { display: none; }
  .gnn-prows, .gnn-wrows { max-height: 240px; }
}
