/* ============================================================================
   Página /dessem/mapa-intercambio — mapa vivo do SIN.

   Duas regras, e este arquivo inteiro sai delas:

   1. **Só tokens.** Nenhuma cor de tema hardcoded: tudo sai de `--theme-*` e
      `--comerc-green`. O modo escuro NÃO mora aqui — quem troca os tokens é
      `zz_theme_dark.css` via `html[data-theme="dark"]`. As poucas exceções são
      a paleta Okabe-Ito (cega-friendly) das secções e dos estados de limite,
      que não existem no design system, e por isso viram tokens locais em
      `.mi-page` — declarados uma vez, usados por nome daqui para baixo.
   2. **Prefixo `mi-`.** Nada colide com outra página, então este arquivo pode
      carregar em qualquer ordem sem precisar de `!important` (o único aparece
      no bloco de `prefers-reduced-motion`, que precisa vencer a animação).

   O SVG do diagrama é desenhado por `assets/mapa_sin.js`, que não pinta nada em
   linha: toda cor de fio, seta, caixa e barra é resolvida por classe aqui. É o
   que permite o toggle claro/escuro funcionar sem redesenhar o mapa.
   ============================================================================ */

/* ---------------------------------------------------------------- tokens */
/* Paleta Okabe-Ito: as três secções e os estados de carregamento precisam ser
   distinguíveis por quem não separa vermelho de verde — o alarme nunca é só
   "ficou vermelho", vem sempre com borda mais grossa e barra cheia junto. */
.mi-page {
  --mi-ok: var(--comerc-green);
  --mi-bad: #D55E00;
  --mi-warn: #E69F00;
  /* Okabe-Ito. ⚠️ --mi-cut1 NÃO pode repetir --mi-warn (#E69F00): a barra de
     carga em atenção e o arco da secção EXP_NE dividiam o mesmo diagrama com a
     mesma cor. O azul abaixo estava livre desde que o sistema de status saiu. */
  --mi-cut1: #0072B2;
  --mi-cut2: #CC79A7;
  --mi-cut3: #009E73;
  --mi-wire: var(--theme-dim);
  padding-bottom: 40px;
}

/* No fundo escuro o laranja e o azul do Okabe-Ito ficam abafados; as versões
   claras da mesma família mantêm a distinção e ganham contraste. */
html[data-theme="dark"] .mi-page {
  --mi-bad: #FF8442;
  --mi-cut1: #56B4E9;
}

/* ------------------------------------------------------------- estrutura */
/* O diagrama tem largura mínima real: abaixo de ~620 px as caixas se
   sobrepõem e os inputs deixam de caber. Em vez de encolher até virar sopa, a
   página rola na horizontal. */
.mi-scroll { overflow-x: auto; }

/* Wrapper do diagrama. A razão (aspect-ratio) vem inline do Python
   (`aspect_ratio_css()`), da MESMA fonte que o viewBox do SVG — é o que
   garante que os inputs, posicionados em % daqui, caiam dentro das caixas.
   `container-type: inline-size` existe para os inputs medirem a fonte em
   `cqi`: eles precisam encolher com o diagrama, não com a janela. */
.mi-wrap {
  position: relative;
  width: 100%;
  max-width: 900px;
  min-width: 620px;
  margin: 0 auto;
  container-type: inline-size;
}
.mi-host { position: absolute; inset: 0; }
.mi-svg { width: 100%; height: 100%; display: block; }

/* ------------------------------------------------------- fios e fluxo */
.mi-wire {
  fill: none; stroke: var(--mi-wire); stroke-width: 3;
  stroke-linecap: round; stroke-linejoin: round;
}

/* Tracejado que corre no sentido real do fluxo. É a única informação da tela
   que não depende de ler número nenhum. */
.mi-flow {
  fill: none; stroke: var(--mi-ok); stroke-width: 3.2;
  stroke-linecap: round; stroke-dasharray: 7 12;
  opacity: .95; pointer-events: none;
}
.mi-flow.fwd { animation: mi-flowF 1.05s linear infinite; }
.mi-flow.rev { animation: mi-flowR 1.05s linear infinite; }
.mi-flow.off { display: none; }
.mi-flow.is-bad { stroke: var(--mi-bad); }
@keyframes mi-flowF { to { stroke-dashoffset: -38; } }
@keyframes mi-flowR { to { stroke-dashoffset: 38; } }

.mi-arrow { fill: var(--mi-ok); stroke: none; }
.mi-arrow.is-bad { fill: var(--mi-bad); }

/* ------------------------------------------------------------------ nós */
.mi-node { fill: var(--theme-panel2); stroke: var(--mi-wire); stroke-width: 1.6; }
.mi-node-name {
  font-size: 27px; font-weight: 700; fill: var(--theme-ink); text-anchor: middle;
}
.mi-node-cmo {
  font-size: 18px; font-weight: 600; fill: var(--mi-ok); text-anchor: middle;
  font-variant-numeric: tabular-nums;
}
.mi-node-unit {
  font-size: 10px; font-weight: 600; letter-spacing: .08em;
  fill: var(--theme-mut); text-anchor: middle;
}
.mi-dot { fill: var(--theme-ink); }
.mi-dot-label { font-size: 14px; font-weight: 600; fill: var(--theme-mut); }
.mi-hz { font-size: 13px; font-weight: 600; fill: var(--theme-ink); }
.mi-conv-linha { stroke: var(--mi-wire); stroke-width: 1.4; stroke-dasharray: 5 5; }

/* --------------------------------------------------------------- caixas */
.mi-box-bg { fill: var(--theme-panel); stroke: var(--theme-line); stroke-width: 1.2; }
.mi-box-lbl {
  font-size: 12.5px; font-weight: 600; letter-spacing: .05em;
  fill: var(--theme-ink);
}
.mi-box-unit {
  font-size: 10px; font-weight: 600; letter-spacing: .06em; fill: var(--theme-dim);
}
.mi-box-note { font-size: 9px; font-weight: 500; fill: var(--theme-mut); }

/* Caixa compacta (fluxo sem limite, como Itaipu): o rótulo tem a largura toda
   para si, mas são só 80 px úteis — "ITAIPU 50 HZ" a 12,5 px não cabe. A
   unidade divide a faixa de baixo com a borda da caixa; 9 px é o que cabe
   entre o pé do input e o fundo. */
.mi-box-simples .mi-box-lbl { font-size: 10.5px; }
.mi-box-simples .mi-box-unit { font-size: 9px; }

/* Barra de carregamento |fluxo| / |limite|. */
.mi-track { fill: var(--theme-line); }
.mi-bar { fill: var(--mi-ok); }
.mi-bar.warn { fill: var(--mi-warn); }
.mi-bar.bad { fill: var(--mi-bad); }

/* -------------------------------------------------------------- secções */
.mi-cut-arc {
  fill: none; stroke-width: 2.4; stroke-linecap: round;
  /* stroke-dasharray vem do spec (`traco`): cada secção tem o seu, para que
     dois arcos que se cruzam continuem separáveis em preto e branco. */
}
.mi-cut .mi-box-bg { stroke-dasharray: 6 4; stroke-width: 1.4; }
.mi-cut-1 .mi-cut-arc, .mi-cut-1 .mi-box-bg { stroke: var(--mi-cut1); }
.mi-cut-2 .mi-cut-arc, .mi-cut-2 .mi-box-bg { stroke: var(--mi-cut2); }
.mi-cut-3 .mi-cut-arc, .mi-cut-3 .mi-box-bg { stroke: var(--mi-cut3); }
/* Numa secção, a cor do arco manda no rótulo — é ela que amarra a caixa ao
   traço lá no diagrama. */
.mi-cut-1 .mi-box-lbl { fill: var(--mi-cut1); }
.mi-cut-2 .mi-box-lbl { fill: var(--mi-cut2); }
.mi-cut-3 .mi-box-lbl { fill: var(--mi-cut3); }

/* Alarme de limite por último: vence a cor da secção, porque é o estado mais
   urgente da caixa. */
.at-lim .mi-box-bg { stroke: var(--mi-bad); stroke-width: 1.8; stroke-dasharray: none; }

/* Toggle das secções: o Python devolve `mi-hide-<id>` no className do wrapper
   e uma classe só apaga o arco, a caixa e os dois inputs da secção. */
.mi-hide-exp_ne .mi-cut[data-sec="exp_ne"],
.mi-hide-exp_ne .mi-in[data-sec="exp_ne"],
.mi-hide-fns_fnese .mi-cut[data-sec="fns_fnese"],
.mi-hide-fns_fnese .mi-in[data-sec="fns_fnese"],
.mi-hide-imp_seco .mi-cut[data-sec="imp_seco"],
.mi-hide-imp_seco .mi-in[data-sec="imp_seco"] { display: none; }

/* ------------------------------------------------------ inputs por cima */
/* Os números das caixas são `dcc.Input` HTML posicionados em % sobre o SVG
   (Python: `posicao_input_pct`), e não texto SVG: é o que mantém a edição
   what-if com teclado, foco e acessibilidade nativos. */
.mi-in {
  position: absolute;
  margin: 0;
  padding: 0;
  display: block;
}
.mi-in input {
  width: 100%;
  height: 100%;
  display: block;
}
/* (Dash 4 embrulhava o input em `div.dash-input-container`; o app roda Dash 3.2,
   que devolve o `<input>` direto — os blocos do wrapper foram removidos como
   código morto. Se o Dash subir para 4.x, restaurar do histórico do git.) */
.mi-in input {
  box-sizing: border-box;
  min-width: 0;
  padding: 0 3px;
  border: 1px solid var(--theme-line);
  border-radius: 5px;
  background: var(--theme-panel);
  color: var(--theme-ink);
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               "Liberation Mono", monospace;
  font-weight: 600;
  text-align: center;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  /* Fallback para navegador sem container queries; a linha seguinte manda onde
     `cqi` existe, para a fonte acompanhar o diagrama e não a janela. */
  font-size: clamp(10px, 1.7vw, 16px);
  font-size: clamp(10px, 1.9cqi, 16px);
}
.mi-in input:hover { border-color: var(--theme-mut); }
.mi-in input:focus,
.mi-in input:focus-visible {
  outline: none;
  border-color: var(--comerc-green);
  box-shadow: 0 0 0 2px var(--comerc-green-lighter);
}
/* Limite: menor e apagado — é teto, não medição. */
.mi-in-lim input {
  color: var(--theme-mut);
  font-weight: 500;
  font-size: clamp(9px, 1.3vw, 11px);
  font-size: clamp(9px, 1.4cqi, 11px);
}
/* Campo manual: mesmo preenchimento da caixa tracejada do SVG que ele cobre —
   um relance basta para ver que ali não há dado de rodada por trás. */
.mi-in-manual input { background: var(--theme-panel2); }

/* |fluxo| ≥ |limite|: os dois inputs do par acendem juntos, junto com a borda
   da caixa e a barra cheia — três sinais, nenhum deles só cor. */
.mi-in.is-bad input {
  color: var(--mi-bad);
  border-color: var(--mi-bad);
}
/* Valor que não é mais o da rodada. Tracejado sutil, sem cor: "editado" não é
   erro, é cenário. */
.mi-in.is-editado input { border-style: dashed; }

/* Rótulo acessível de cada input (o leitor de tela precisa saber qual caixa é;
   na tela, quem diz isso é o rótulo desenhado no SVG). Fica escopado à página
   porque o projeto ainda não tem um utilitário global equivalente. */
.mi-page .visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------- transporte do tempo (IPER) */
.mi-tempo { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.mi-tempo .mi-slider { flex: 1 1 140px; min-width: 110px; }
.mi-transp {
  width: 32px; height: 32px; border-radius: 8px; flex: none;
  border: 1px solid var(--theme-line); background: var(--theme-panel2);
  color: var(--theme-ink); cursor: pointer;
  display: flex; align-items: center; justify-content: center; font-size: 13px;
}
.mi-transp:hover { background: var(--theme-line); }
.mi-transp.is-on {
  background: var(--comerc-green); color: #0c130f; border-color: var(--comerc-green);
}
.mi-relogio {
  font-size: 15px; font-weight: 700; color: var(--theme-ink);
  min-width: 118px; text-align: center; font-variant-numeric: tabular-nums;
}

.mi-page .mi-slider .rc-slider-rail { background: var(--theme-line); }
.mi-page .mi-slider .rc-slider-track { background: var(--comerc-green); }
.mi-page .mi-slider .rc-slider-handle {
  border-color: var(--comerc-green);
  background: var(--comerc-green);
  opacity: 1;
}
.mi-page .mi-slider .rc-slider-dot-active { border-color: var(--comerc-green); }
.mi-page .mi-slider .rc-slider-mark-text {
  color: var(--theme-mut); font-size: 0.68rem;
}
.mi-page .mi-slider .rc-slider-mark-text-active { color: var(--theme-ink); }

/* Bootstrap zera a margem de `figure`, mas a página não deve depender disso:
   o diagrama é o herói e não pode ganhar recuo de 40 px se a folha mudar. */
.mi-figure { margin: 0; }

/* A coluna "Sub" é a chave de leitura das duas tabelas largas — sem peso ela
   some no meio dos números. */
.mi-td-sist { font-weight: 600; }

/* ------------------------------------------------------ card de secções */
/* ⚠️ Cada `.mi-sec-row` é o ÚNICO filho do seu próprio `<label>` — o
   dcc.Checklist embrulha opção por opção. Logo `:last-child` casava com as
   três e o separador nunca aparecia; e como item flex a linha encolhia para o
   conteúdo (255/270/336 px num label de 570 px), deixando os valores
   desalinhados. O `width: 100%` resolve o alinhamento e o separador passa a
   ser borda de topo, aplicada a partir da segunda opção. */
.mi-sec-row {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 7px 0;
}
.mi-sec-list > label + label .mi-sec-row { border-top: 1px solid var(--theme-line); }
.mi-sec-nome { flex: 1; font-size: 12.5px; font-weight: 600; letter-spacing: .03em; }
.mi-sec-valor {
  font-size: 12px; font-weight: 600; color: var(--theme-mut);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.mi-sec-list > label { display: block; }
.mi-sec-check { accent-color: var(--comerc-green); }

.mi-sw { width: 10px; height: 10px; border-radius: 3px; flex: none; display: inline-block; }
.mi-sw-1 { background: var(--mi-cut1); }
.mi-sw-2 { background: var(--mi-cut2); }
.mi-sw-3 { background: var(--mi-cut3); }

/* ------------------------------------------------------------- legenda */
.mi-legend {
  display: flex; flex-wrap: wrap; gap: 6px 18px;
  padding: 10px 6px 4px; color: var(--theme-mut); font-size: 11.5px;
}
.mi-legend span { display: inline-flex; align-items: center; gap: 6px; }
.mi-legend .mi-sw-bad { background: var(--mi-bad); }

/* -------------------------------------------- contraste no tema claro */
/* O verde da marca (#94D600) é claro demais para texto fino sobre painel
   branco — não passa 4.5:1. A variante escura mantém a identidade e a leitura.
   Só o texto muda: preenchimentos sólidos (seta, barra) seguem no verde. */
html:not([data-theme="dark"]) .mi-node-cmo { fill: #6BA800; }

/* ------------------------------------------------------------ respostas */
@media (prefers-reduced-motion: reduce) {
  /* Sem a corrida do tracejado o sentido continua legível pela seta; a opacidade
     menor evita que a linha estática compita com o fio de baixo. */
  .mi-flow { animation: none !important; opacity: .45; }
}


/* --------------------------------------------------------------- fita do dia */
/* As 48 meias-horas de cada elemento com limite, lado a lado. O diagrama diz
   ONDE; a fita diz QUANDO. Duas leituras da mesma verdade, do mesmo store.

   Dois canais de propósito: a ALTURA da barra é |fluxo| ÷ |limite| (contínua,
   legível em preto e branco) e a COR marca as faixas. Quem não separa vermelho
   de laranja continua lendo a fita pela altura. */
.mi-fita-wrap { overflow-x: auto; padding: 2px 0 6px; }
.mi-fita-wrap:focus-visible {
  outline: 2px solid var(--comerc-green);
  outline-offset: 2px;
}
.mi-fita {
  width: 100%; min-width: 620px;
  table-layout: fixed; border-collapse: collapse;
}
.mi-fita-rot {
  width: 116px; text-align: right; padding-right: 8px;
  font-size: 11px; font-weight: 600; color: var(--theme-mut);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
/* Título de submercado: separa os blocos sem virar linha de dado — não tem
   célula, então o JS (que varre `[data-dono]`) passa reto por ela. */
.mi-fita-grupo {
  text-align: left; padding: 7px 0 2px;
  font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--theme-dim); border-bottom: 1px solid var(--theme-line);
}
.mi-fita-grupo-tr:first-child .mi-fita-grupo { padding-top: 2px; }
.mi-fita-hora {
  height: 14px; font-size: 9.5px; font-weight: 600; color: var(--theme-dim);
  text-align: left; padding: 0; font-variant-numeric: tabular-nums;
}
.mi-fita-cel {
  height: 15px; padding: 0;
  border-left: 1px solid var(--theme-panel);
  /* A barra cresce de baixo para cima; --f vem do JS, entre 0 e 1. */
  background:
    linear-gradient(to top, currentColor calc(var(--f, 0) * 100%), transparent 0)
    no-repeat;
  color: var(--theme-line);
  cursor: pointer;
}
.mi-fita-cel.aten  { color: var(--mi-warn); }
.mi-fita-cel.perto { color: #E8730C; }
/* No limite ganha contorno além da cor: é o único estado que exige ação, e não
   pode depender de o leitor distinguir dois tons de laranja. */
.mi-fita-cel.at-lim {
  color: var(--mi-bad);
  box-shadow: inset 0 0 0 1px var(--mi-bad);
}
.mi-fita-cel.sem-dado {
  background: repeating-linear-gradient(45deg, transparent 0 3px, var(--theme-line) 3px 4px);
  cursor: default;
}
/* A meia-hora que o diagrama está mostrando. */
.mi-fita-cel.is-agora { border-left-color: var(--comerc-green); }
.mi-fita tbody tr:hover .mi-fita-cel { background-color: var(--theme-panel2); }

.mi-fita-legenda { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; }
.mi-fita-legenda span { display: inline-flex; align-items: center; gap: 5px; }
.mi-fita-sw {
  width: 9px; height: 11px; flex: none; display: inline-block; border-radius: 2px;
}
.mi-fita-sw.aten   { background: var(--mi-warn); }
.mi-fita-sw.perto  { background: #E8730C; }
.mi-fita-sw.at-lim { background: var(--mi-bad); box-shadow: inset 0 0 0 1px var(--mi-bad); }

@media (prefers-reduced-motion: reduce) {
  .mi-fita tbody tr:hover .mi-fita-cel { background-color: transparent; }
}

/* ═══════════════════════════════════════════ camada "por que o limite é esse"

   Prefixo `mx-` (a camada é de outro arquivo Python: `_mapa_explicacao.py`), e
   as mesmas duas regras do topo: só tokens de tema, nada de cor hardcoded fora
   da Okabe-Ito já declarada em `.mi-page`.

   O elemento memorável desta camada é UM: a memória de cálculo (`.mx-ledger`),
   que é lida como um livro-razão — coluna de contribuição alinhada, régua antes
   do total, o total confrontado com o que o DESSEM gravou. Todo o resto
   (gráficos, tabelas de definição) é deliberadamente quieto, senão a conta
   deixa de ser o centro.                                                      */

/* Caixa do diagrama que tem restrição explicável: só o cursor muda, porque a
   caixa já carrega cor demais (secção, limite, carregamento). */
.mi-box-explica { cursor: pointer; }
.mi-box-explica:hover .mi-box-bg { stroke-width: 2; }
.mi-box.is-foco .mi-box-bg {
  stroke: var(--comerc-green); stroke-width: 2.4; stroke-dasharray: none;
}

/* ------------------------------------------------------------ a barra/gate */
.mx-painel { padding: 0; overflow: hidden; }
.mx-bar {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  width: 100%; padding: 14px 18px; border: 0; background: transparent;
  color: var(--theme-ink); text-align: left; cursor: pointer;
}
.mx-bar:hover { background: var(--theme-panel2); }
.mx-bar:focus-visible { outline: 2px solid var(--comerc-green); outline-offset: -2px; }
.mx-bar-titulo { font-family: var(--theme-serif); font-size: 19px; }
.mx-bar-sub { color: var(--theme-mut); font-size: 12.5px; }
.mx-seta { color: var(--comerc-green); transition: transform .18s ease; }
.mx-bar.is-aberta .mx-seta { transform: rotate(180deg); }

/* ------------------------------------------------------------ os 11 chips */
.mx-chips-wrap { padding: 0 18px 10px; border-top: 1px solid var(--theme-line); padding-top: 12px; }
.mx-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }
.mx-chip {
  display: inline-flex; align-items: baseline; gap: 6px;
  padding: 5px 11px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--theme-line); background: var(--theme-panel);
  color: var(--theme-mut); font-size: 12.5px; line-height: 1.2;
}
.mx-chip:hover { border-color: var(--comerc-green); color: var(--theme-ink); }
.mx-chip:focus-visible { outline: 2px solid var(--comerc-green); outline-offset: 2px; }
.mx-chip-nome { font-weight: 600; letter-spacing: .01em; }
.mx-chip-re { font-variant-numeric: tabular-nums; opacity: .8; }
.mx-chip.is-foco {
  border-color: var(--comerc-green); color: var(--theme-ink);
  background: rgba(148, 214, 0, .12); font-weight: 600;
}
/* Fonte do limite: um traço à esquerda, porque "de onde vem o limite" é a
   primeira coisa que muda a leitura — e três das onze não têm fórmula. */
.mx-chip[data-mx-fonte="RSTTAB"] { border-left: 3px solid var(--mi-cut2); }
.mx-chip[data-mx-fonte="FIXO"]   { border-left: 3px solid var(--theme-dim); }

/* --------------------------------------------------------------- o corpo */
.mx-corpo-in { padding: 4px 18px 18px; }
.mx-foco { margin-bottom: 10px; }
.mx-foco-tit { margin-bottom: 2px; }
.mx-foco-tit small { font-family: inherit; font-size: 13px; color: var(--theme-mut); }
.mx-foco-nota { color: var(--theme-mut); font-size: 13px; max-width: 74ch; margin: 0; }
.mx-aviso {
  border-left: 3px solid var(--mi-warn); background: var(--theme-panel2);
  padding: 8px 12px; border-radius: 0 6px 6px 0; font-size: 13px; margin: 8px 0;
}
.mx-topo { margin: 12px 0 4px; }
.mx-kpi-estado .v { font-size: 20px; }
.mx-linha { margin-left: 0; margin-right: 0; }
.mx-graf { width: 100%; }

/* ------------------------------------------------- o livro-razão da conta */
.mx-bloco {
  border: 1px solid var(--theme-line); border-radius: 10px;
  padding: 12px 14px; background: var(--theme-panel);
}
.mx-bloco + .mx-bloco { margin-top: 12px; }
/* Quem manda na meia-hora ganha a régua verde à esquerda. Numa RE com duas
   LPPs as duas contas ficam na tela — o que vale é a de MENOR limite, e ver a
   perdedora ao lado é o que torna a regra do mínimo visível. */
.mx-bloco.is-manda { border-color: var(--comerc-green); }
.mx-bloco:not(.is-manda) { opacity: .62; }
.mx-bloco-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.mx-bloco-tit { font-size: 15px; margin: 0; }
.mx-bloco-tit small { font-family: inherit; color: var(--theme-mut); font-size: 12.5px; }
.mx-manda {
  display: none; font-size: 11px; letter-spacing: .03em;
  color: var(--comerc-green); border: 1px solid currentColor;
  border-radius: 999px; padding: 1px 8px;
}
.mx-bloco.is-manda .mx-manda { display: inline-block; }
.mx-eq { font-size: 14px; margin: 8px 0 2px; }
.mx-eq-resto { color: var(--theme-mut); }
.mx-coeflin { font-size: 15px; font-weight: 600; }
.mx-curva { font-size: 12.5px; color: var(--theme-mut); margin-bottom: 8px; }
.mx-eq-nota { display: block; font-size: 11.5px; }
.mx-chipnum {
  background: var(--theme-panel2); border-radius: 4px; padding: 0 6px;
  color: var(--theme-ink);
}
.mx-val { font-variant-numeric: tabular-nums; }
.mx-ledger table { font-size: 13px; }
.mx-ledger td, .mx-ledger tfoot th { text-align: right; }
.mx-ledger tbody th, .mx-ledger thead th:first-child { text-align: left; }
.mx-ledger thead th:not(:first-child) { text-align: right; }
.mx-ledger tfoot th { text-align: left; }
.mx-tr-total th, .mx-tr-total td { border-top: 2px solid var(--theme-ink); }
.mx-total { font-size: 15px; font-weight: 700; }
.mx-delta { color: var(--theme-mut); margin-left: 10px; }
.mx-vazio { color: var(--theme-mut); text-align: left; font-style: italic; }

/* ------------------------------------------------------- blocos fechados */
.mx-det {
  border: 1px solid var(--theme-line); border-radius: 10px;
  margin-top: 14px; background: var(--theme-panel);
}
.mx-det > summary {
  padding: 11px 14px; cursor: pointer; font-weight: 600;
  list-style-position: inside;
}
.mx-det > summary:focus-visible { outline: 2px solid var(--comerc-green); outline-offset: -2px; }
.mx-sum-sub { font-weight: 400; color: var(--theme-mut); }
.mx-det-corpo { padding: 0 14px 14px; }
.mx-def-bloco + .mx-def-bloco { margin-top: 16px; }
.mx-def-tit { font-size: 14px; margin: 10px 0 4px; }
.mx-def-tit small { font-family: inherit; color: var(--theme-mut); font-weight: 400; }
.mx-det table { font-size: 12.5px; }
.mx-criterios .mx-num { text-align: right; font-variant-numeric: tabular-nums; }
/* A coluna do critério primário é a que se lê primeiro; a do preço-sombra fica
   ao lado como diagnóstico, não como segunda verdade. */
.mx-criterios .mx-primario { font-weight: 700; }
.mx-rodape { margin-top: 12px; }

@media (max-width: 720px) {
  .mx-corpo-in { padding: 4px 12px 14px; }
  .mx-chips-wrap { padding-left: 12px; padding-right: 12px; }
  .mx-bar { padding: 12px; }
}
@media (prefers-reduced-motion: reduce) {
  .mx-seta { transition: none !important; }
}

/* A frase derivada do deck, logo abaixo da nota fixa da restrição. Fica mais
   discreta de propósito: a nota diz o que a restrição É, esta diz o que ESTE
   caso faz — e os números dela mudam de deck para deck. */
.mx-foco-deck {
  margin: 2px 0 0; font-size: 12px; color: var(--theme-mut);
  font-variant-numeric: tabular-nums;
}

/* ============================================================================
   Modos do painel: cenário e período — prefixo `mz-`.

   Três perguntas sobre o MESMO sujeito (a restrição escolhida nos chips `mx-`),
   e por isso abas e não secções novas: ver `paginas/dessem/_mapa_modos.py`. A
   troca de aba é só classe — os três corpos ficam no DOM, então voltar não
   redesenha figura nenhuma.
   ============================================================================ */

/* ------------------------------------------------------------------- abas */
.mz-abas {
  display: flex; flex-wrap: wrap; gap: 4px;
  padding: 0 18px; border-bottom: 1px solid var(--theme-line);
}
.mz-aba {
  display: flex; flex-direction: column; gap: 1px;
  padding: 9px 14px 8px; border: 0; border-bottom: 2px solid transparent;
  background: transparent; color: var(--theme-mut); cursor: pointer;
  text-align: left; border-radius: 8px 8px 0 0;
}
.mz-aba:hover { background: var(--theme-panel2); color: var(--theme-ink); }
.mz-aba:focus-visible { outline: 2px solid var(--comerc-green); outline-offset: -2px; }
.mz-aba.is-on {
  color: var(--theme-ink); border-bottom-color: var(--comerc-green);
  background: var(--theme-panel2);
}
.mz-aba-tit { font-weight: 600; font-size: 14px; }
.mz-aba-sub { font-size: 11.5px; color: var(--theme-mut); }

/* Corpo de cada modo. `display:none` e não `visibility`: um Plotly escondido
   por visibilidade continua medindo largura errada ao reaparecer, e a figura
   sairia estreita até alguém mexer na janela. */
.mz-modo { display: none; }
.mz-modo.is-on { display: block; }
.mz-linha { margin: 0; padding: 14px 6px 4px; }
.mz-corpo { padding: 0 12px 14px; }

/* -------------------------------------------------------------- controles */
.mz-controles { padding: 4px 12px 8px; }
.mz-campo { margin-bottom: 14px; }
.mz-radio { display: flex; flex-direction: column; gap: 6px; font-size: 13px; }
.mz-radio label { display: flex; align-items: flex-start; gap: 7px; cursor: pointer; }
.mz-radio-in { margin-top: 3px; accent-color: var(--comerc-green); }

/* --------------------------------------------------- formulário do cenário */
.mz-form { list-style: none; padding: 0; margin: 0 0 8px; }
.mz-ch-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 0 8px 10px; border-top: 1px solid var(--theme-line);
}
.mz-ch { display: flex; flex-direction: column; gap: 0; min-width: 0; }
.mz-ch-nome { font-weight: 600; font-size: 13px; font-variant-numeric: tabular-nums; }
.mz-ch-papel { color: var(--theme-mut); font-size: 11px; }
.mz-ch-faixa { color: var(--theme-mut); font-size: 11px; font-variant-numeric: tabular-nums; }
.mz-ch-in { display: flex; align-items: baseline; gap: 5px; flex: 0 0 auto; }
/* (Dash 4: o wrapper `div.dash-input-container` pedia largura própria aqui; no Dash 3.2
   o `<input>` vem direto — regra removida como código morto.) */
.mz-ch-in input {
  width: 100%; padding: 5px 8px; text-align: right;
  font-variant-numeric: tabular-nums; font-size: 13px;
  border: 1px solid var(--theme-line); border-radius: 7px;
  background: var(--theme-panel); color: var(--theme-ink);
}
.mz-ch-in input:focus { outline: 2px solid var(--comerc-green); outline-offset: 1px; }
.mz-ch-un { color: var(--theme-mut); font-size: 11px; white-space: nowrap; }
/* A linha de PARAM é a que troca a curva — é o efeito que o modo existe para
   mostrar, e por isso ela se destaca das linhas de controlador. */
.mz-ch-row.is-param { border-left: 3px solid var(--mi-cut2); padding-left: 7px; }

/* ------------------------------------------------- o recorte da meia-hora */
.mz-agora-wrap {
  border: 1px solid var(--theme-line); border-radius: 12px;
  padding: 10px 12px 4px; margin: 12px 0 4px; background: var(--theme-panel);
}
.mz-agora { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.mz-agora-rot { color: var(--theme-mut); font-size: 12px; }
.mz-agora-h { font-size: 17px; font-weight: 700; font-variant-numeric: tabular-nums; }
.mz-agora-pat, .mz-agora-est {
  font-size: 11.5px; padding: 1px 8px; border-radius: 999px;
  border: 1px solid var(--theme-line); color: var(--theme-mut);
}
.mz-agora-est[data-mz-estado="trava"] { border-color: var(--mi-cut1); color: var(--mi-cut1); }
.mz-agora-est[data-mz-estado="ja_travado"] { border-color: var(--mi-bad); color: var(--mi-bad); }
.mz-agora-est[data-mz-estado="suspeito"] { border-color: var(--mi-warn); color: var(--mi-warn); }
.mz-kpis, .mz-kpis-dia { margin-top: 6px; }
.mz-val { font-variant-numeric: tabular-nums; }
.mz-val.is-cen { color: var(--mi-cut2); }
/* O mesmo âmbar da caixa que acende no diagrama: é o que liga o nome ao mapa. */
.mz-quem { font-size: 16px; display: inline-flex; align-items: center; gap: 6px; }
.mz-quem::before {
  content: ""; width: 9px; height: 9px; border-radius: 50%;
  background: var(--mi-warn); flex: 0 0 auto;
}
.mz-num { text-align: right; font-variant-numeric: tabular-nums; }
.mz-sub { font-size: 14px; margin: 0 0 6px; }

/* ------------------------------------------------------- tags do cenário */
.mz-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.mz-tag {
  display: inline-flex; gap: 6px; align-items: baseline;
  padding: 2px 9px; border-radius: 999px; font-size: 12px;
  border: 1px solid var(--mi-cut2); color: var(--mi-cut2);
}
.mz-tag.is-vazio { border-color: var(--theme-line); color: var(--theme-mut); }
.mz-tag-k { font-weight: 600; }
.mz-tag-v { font-variant-numeric: tabular-nums; }

/* ------------------------------------------------- veredito e estados */
/* A única peça "alta" dos dois modos: é a resposta, e tudo em volta é o que a
   sustenta. Serifada como o título da barra, para ler como frase e não como KPI. */
.mz-veredito {
  font-family: var(--theme-serif); font-size: 19px; line-height: 1.45;
  margin: 10px 0 8px; padding-left: 12px; max-width: 70ch;
  border-left: 3px solid var(--theme-line);
}
.mz-veredito.mz-est-trava { border-left-color: var(--mi-cut1); }
.mz-veredito.mz-est-ja_travado { border-left-color: var(--mi-bad); }
.mz-veredito.mz-est-suspeito { border-left-color: var(--mi-warn); }
.mz-veredito.mz-est-nao_trava_ate_teto { border-left-color: var(--mi-cut3); }

.mz-estados { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; padding: 0; margin: 0 0 6px; }
.mz-est {
  display: inline-flex; align-items: baseline; gap: 6px;
  padding: 3px 10px; border-radius: 999px; font-size: 12px;
  border: 1px solid var(--theme-line); background: var(--theme-panel);
}
.mz-est-n { font-weight: 700; font-variant-numeric: tabular-nums; }
.mz-est-de { color: var(--theme-mut); }
.mz-est.is-zero { opacity: .45; }
/* Estado não é legível só pela cor: o nome vai sempre junto. A cor é o segundo
   canal, e a borda esquerda o terceiro. */
.mz-est.mz-est-trava { border-color: var(--mi-cut1); }
.mz-est.mz-est-ja_travado { border-color: var(--mi-bad); }
.mz-est.mz-est-suspeito { border-color: var(--mi-warn); }
.mz-est.mz-est-nao_trava_ate_teto { border-color: var(--mi-cut3); }
/* "Não aperta neste sentido" fica com a borda neutra de propósito: é o único
   estado que não diz nada sobre aperto, e a mesma cor cinza o representa na
   figura (`estresse_view._COR_ESTADO`). */
.mz-est.mz-est-nao_amarra_neste_sentido { border-color: var(--theme-line); }

.mz-cobertura td:first-child, .mz-cobertura th { text-align: left; }
/* O nome do estado é o PRIMEIRO canal do chip (a cor é o segundo, a borda o
   terceiro — comentário acima): sem peso ele lia depois do número. A classe já
   era emitida por `_chip_estado` e estava sem regra nenhuma. */
.mz-est-nome { font-weight: 600; }
/* "Quem trava, e quantas vezes". Mesma armadilha de `.mz-cobertura` e
   `.mz-diff`: `.theme-table tbody td` (0,1,2) centraliza tudo e deixa `.mz-num`
   (0,1,0) inerte. Aqui a coluna que se compara é a contagem de meias-horas —
   número contra número —, e o nome da restrição é texto. */
.mz-culpados th { text-align: left; }
.mz-culpados tbody td.mz-num {
  text-align: right; font-variant-numeric: tabular-nums;
}
/* "O que mais se moveu": as duas colunas numéricas (RE e Δ MW) são o que se
   compara linha a linha; o nome da restrição e o "sim/não" são texto. Mesma
   armadilha de `.mz-cobertura` — `.theme-table tbody td` (0,1,2) centraliza
   tudo e deixa `.mz-num` (0,1,0) inerte. */
.mz-movidas th { text-align: left; }
.mz-movidas tbody td.mz-num {
  text-align: right; font-variant-numeric: tabular-nums;
}

/* O rádio do sentido mora ABAIXO do formulário (ver `controles_cenario`): ele
   pertence à secção "até onde dá para ir", que fecha o corpo, e não ao que se
   digita acima. A régua é o que diz isso sem precisar de um segundo título. */
.mz-campo-sentido {
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--theme-line);
}

/* --------------------------------------------------- "até onde dá para ir"
   A sensibilidade fecha o corpo do cenário, separada por uma régua. A régua NÃO
   é decoração: acima dela tudo é medido (o dia da rodada com um número
   trocado); daqui para baixo tudo responde SOB PREMISSA, e o veredito serifado
   é a única peça "alta" da secção. */
.mz-ateonde {
  display: block; margin-top: 18px; padding-top: 14px;
  border-top: 1px solid var(--theme-line);
}

/* ------------------------------------------- as duas secções do formulário
   "Quem move o fluxo" e "Quem move o limite" são efeitos OPOSTOS sobre a mesma
   folga (um consome o espaço por baixo, o outro é a régua por cima), e por isso
   a régua entre elas é mais grossa que a das linhas. As LINHAS são as mesmas
   `.mz-ch-*` nos dois lados: é o mesmo gesto, e dois vocabulários para a mesma
   ação seriam dois para aprender. */
.mz-form-sec + .mz-form-sec {
  margin-top: 16px; padding-top: 12px; border-top: 2px solid var(--theme-line);
}
/* Aviso da própria manopla (nome que não casou com o deck, par de sentido que
   não colapsou). A palavra "aviso:" é o primeiro canal; o âmbar é o segundo. */
.mz-ch-aviso { color: var(--mi-warn); font-size: 11px; }

/* Quem trava o empurrão, no diagrama.
   ⚠️ Não pode usar --mi-cut1/2/3: as três caixas de secção (EXP_NE, FNS_FNESE,
   IMP_SECO) já são tracejadas nessas cores, e um culpado em azul tracejado
   ficava idêntico à caixa da EXP_NE. O âmbar é a única cor Okabe-Ito que
   nenhuma caixa usa, e ainda assim ele não é o único canal: o pontilhado é mais
   curto que o `6 4` das secções, vai um halo junto, e o painel escreve o nome
   do culpado ao lado do mesmo ponto âmbar (`.mz-quem`). O `at-lim` (vermelho,
   contínuo) continua querendo dizer "está no limite AGORA" — os dois podem
   estar na mesma caixa ao mesmo tempo, e precisam continuar legíveis juntos. */
.mi-box.is-culpado .mi-box-bg {
  stroke: var(--mi-warn); stroke-width: 3; stroke-dasharray: 2 3;
  filter: drop-shadow(0 0 4px var(--mi-warn));
}

@media (max-width: 720px) {
  .mz-abas { padding: 0 8px; }
  .mz-aba { padding: 8px 10px; }
  .mz-aba-sub { display: none; }
  .mz-corpo, .mz-controles { padding-left: 8px; padding-right: 8px; }
}

/* ═══════════════════════════════════════════ modo "período" (`_mapa_periodo.py`)
   A quarta aba: a mesma restrição ao longo de N dias. Duas peças novas — o
   wrapper de figura que NÃO é `.mx-graf`, e a lista de mudanças do deck. */

/* Mesma trava de altura de `.mx-graf`, classe diferente de propósito:
   `mapaSin.marcarAgora` varre `.mx-graf` para mover `shapes[0]`, e as figuras
   do período não têm shape — entrar naquela varredura dá erro de JS silencioso
   a cada movimento do slider. */
.mz-graf-per { width: 100%; }

.mz-custo { margin: 6px 0 0; font-size: 11.5px; }

/* ------------------------------------------------- o que mudou no deck */
.mz-mud-sec { margin-top: 18px; }

/* "Nenhuma mudança" é resposta, não ausência de resposta: ganha o mesmo peso
   de um veredito, senão é lido como "a tela não olhou". */
.mz-sem-mud {
  font-size: 15px; font-weight: 600; margin: 0 0 4px;
  padding-left: 10px; border-left: 3px solid var(--mi-cut3);
}
.mz-mud-total { font-size: 14px; margin: 0 0 8px; }

/* Sequência cronológica de verdade (um dia depois do outro), então o trilho à
   esquerda carrega informação: é a linha do tempo do deck. */
.mz-mud {
  list-style: none; margin: 0; padding: 0 0 0 14px;
  border-left: 2px solid var(--theme-line);
}
.mz-mud-item { position: relative; margin-bottom: 8px; }
.mz-mud-item::before {
  content: ""; position: absolute; left: -19px; top: 14px;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--theme-mut);
}
.mz-mud-det { margin: 0; }
.mz-mud-sum { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 9px; }
.mz-mud-dia {
  font-variant-numeric: tabular-nums; font-weight: 700;
  min-width: 5ch;
}
.mz-mud-rot { font-weight: 600; }
.mz-mud-sub { font-weight: 400; color: var(--theme-mut); font-size: 12px; }

/* ------------------------------------------------------ tabelas de diff */
.mz-diff { font-size: 12.5px; }
/* ⚠️ `.theme-table tbody td { text-align: center }` (pages_refactor.css) tem
   especificidade (0,1,2) e vence `.mz-num` (0,1,0) — a classe é inerte dentro
   de qualquer `.theme-table`. Aqui ela precisa valer: a tabela existe para
   comparar coeficiente com coeficiente, e "5.400,0000" contra "5.412,5000"
   centralizados não deixam ver qual casa mudou. O seletor sobe para (0,2,1) em
   vez de `!important`, e só neste componente. */
.mz-diff tbody td.mz-num { text-align: right; font-variant-numeric: tabular-nums; }
.mz-diff + .mx-def-tit { margin-top: 14px; }
/* A coluna do sinal: larga o bastante para o "−"/"+" respirar e alinhada ao
   centro, porque não é número nem texto — é o marcador da linha. */
.mz-diff-sig {
  width: 2.2em; text-align: center; font-weight: 700; font-size: 14px;
  line-height: 1;
}
/* A cor é o SEGUNDO canal. O primeiro é a célula "−"/"+" que o Python emite em
   toda linha, e por isso o diff continua legível em cinza e para quem não
   separa vermelho de verde. A borda grossa à esquerda é o terceiro. */
.mz-diff-out { color: var(--mi-bad); box-shadow: inset 3px 0 0 var(--mi-bad); }
/* Verde-azulado do Okabe-Ito e não o verde da marca: #94D600 em texto fino
   sobre painel branco não chega a 4,5:1 (mesma razão de `.mi-node-cmo`). */
.mz-diff-in { color: var(--mi-cut3); box-shadow: inset 3px 0 0 var(--mi-cut3); }
.mz-diff-out td, .mz-diff-in td { border-bottom-color: var(--theme-line); }

@media (max-width: 720px) {
  .mz-mud { padding-left: 10px; }
  .mz-mud-sub { flex-basis: 100%; }
}
