﻿/* ---------------------------------------------------------------------------------------
   Base
   --------------------------------------------------------------------------------------- */

:root {
    --surface: #ffffff;
    --surface-muted: #f8fafc;
    --surface-sunken: #f1f5f9;
    --border: #e2e8f0;
    --border-strong: #cbd5e1;
    --text: #0f172a;
    --text-muted: #64748b;
    --accent: #2563eb;
    --accent-soft: #dbeafe;
    --danger: #dc2626;
    --success: #16a34a;

    /* O ambar dos avisos: chip de ressalva do no, "esperando voce" do cockpit, item dessincronizado
       e o emblema de "em andamento". Todos esses ja escreviam var(--warning, #d97706) e caiam no
       fallback, porque o token nunca existiu — declarado em 22/08/2026 para que trocar o tom seja
       uma linha, e nao sete. Mais escuro que o #f59e0b usado com texto escuro em cima. */
    --warning: #d97706;

    /* O 'em andamento'. Laranja PROPRIO, e nao o ambar dos avisos, por dois motivos.

       O primeiro e semantico: trabalho acontecendo nao e aviso, e reusar o token faria a proxima
       pessoa que ajustasse o tom dos avisos mexer no status sem querer.

       O segundo apareceu na tela e nao apareceria em teste nenhum: o emblema de status fica ENCOSTADO
       no de prioridade, e o de prioridade critica e ambar #f59e0b. Com o status em #d97706 os dois
       viravam uma mancha so no canvas — duas coisas diferentes, um tom de distancia. Este laranja e
       mais vermelho, e separa. */
    --running: #ea580c;
    --shadow-sm: 0 1px 2px rgba(15, 23, 42, .06), 0 1px 3px rgba(15, 23, 42, .1);
    --shadow-md: 0 4px 6px -1px rgba(15, 23, 42, .1), 0 2px 4px -2px rgba(15, 23, 42, .1);
    --shadow-lg: 0 10px 15px -3px rgba(15, 23, 42, .1), 0 4px 6px -4px rgba(15, 23, 42, .1);
    --radius: 8px;

    /* O chevron dos controles que ABREM alguma coisa: o select da ordem e o botao do filtro de
       status. Fica aqui como token para os dois usarem o MESMO desenho — antes um era este SVG e o
       outro era o glifo bi-chevron-down da fonte de icones, e o glifo, sendo texto, sai com outra
       espessura de traco: a mesma cor nominal parecia duas cores na barra. */
    --caret: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
}

* {
    box-sizing: border-box;
}

html,
body {
    height: 100%;
    margin: 0;
}

body {
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
    font-size: 14px;
    color: var(--text);
    background: var(--surface-muted);
}

button {
    font: inherit;
    color: inherit;
}

a {
    color: var(--accent);
}

/* ---------------------------------------------------------------------------------------
   Controles genericos
   --------------------------------------------------------------------------------------- */

.btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 12px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    background: var(--surface);
    cursor: pointer;
    white-space: nowrap;
    transition: background .12s, border-color .12s;

    /* Um <a class="btn"> herdava o sublinhado do link, e o botao ao lado dele — que e <button> — nao
       tinha nenhum: a mesma barra saia com metade dos rotulos sublinhada. Quem parece botao nao se
       sublinha; a cor e a borda ja dizem que e clicavel. */
    text-decoration: none;
    color: inherit;
}

.btn:hover:not(:disabled) {
    background: var(--surface-sunken);
}

.btn:disabled {
    opacity: .45;
    cursor: default;
}

.btn--primary {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
}

.btn--primary:hover:not(:disabled) {
    background: #1d4ed8;
}

.btn--danger {
    color: var(--danger);
    border-color: #fecaca;
}

.btn--danger:hover:not(:disabled) {
    background: #fef2f2;
}

.btn--icon {
    padding: 7px 9px;
}

.btn--ghost {
    border-color: transparent;
    background: transparent;
}

.btn--ghost:hover:not(:disabled) {
    background: var(--surface-sunken);
}

.field {
    display: flex;
    flex-direction: column;
    gap: 5px;
    margin-bottom: 14px;
}

.field > label {
    font-size: 12px;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: .03em;
}

.input,
.select,
.textarea {
    width: 100%;
    padding: 7px 10px;
    border: 1px solid var(--border-strong);
    border-radius: 6px;
    background: var(--surface);
    font: inherit;
    color: inherit;
}

.input:focus,
.select:focus,
.textarea:focus {
    outline: 2px solid var(--accent-soft);
    border-color: var(--accent);
}

.textarea {
    min-height: 90px;
    resize: vertical;
}

.empty-state {
    padding: 48px 24px;
    text-align: center;
    color: var(--text-muted);
}

.empty-state i {
    display: block;
    font-size: 40px;
    margin-bottom: 12px;
    opacity: .4;
}

/* Carimbo da versao publicada. Canto inferior esquerdo, longe do zoom do editor, que fica no centro
   de baixo. Quase invisivel em repouso e legivel ao passar o mouse: quem procura sabe onde olhar, e
   quem nao procura nao e incomodado por uma data no rodape de toda pagina. */
.app-version {
    position: fixed;
    left: 8px;
    bottom: 6px;
    z-index: 10;
    font-size: 10px;
    font-variant-numeric: tabular-nums;
    color: var(--text-muted);
    opacity: .35;
    /* O texto precisa poder ser selecionado e receber o hover do title — dai nao usar
       pointer-events: none, que seria o atalho obvio para nao atrapalhar o canvas. */
    background: var(--surface);
    padding: 1px 5px;
    border-radius: 4px;
}

.app-version:hover {
    opacity: 1;
}

/* ---------------------------------------------------------------------------------------
   Listagem de mapas
   --------------------------------------------------------------------------------------- */

.page {
    max-width: 1000px;
    margin: 0 auto;
    padding: 40px 24px;
}

/* A pagina que ocupa a TELA INTEIRA. E para o conteudo que e uma grade, e nao um texto: o teto de
   1000px existe porque linha longa demais e ruim de ler, e isso vale para formulario e descricao —
   nao para o cronograma, onde o espaco desperdicado a direita e justamente onde as barras caberiam. */
.page--wide {
    max-width: none;
}

/* Trilha de navegacao. Substituiu o botao "Mapas" que ficava na barra de acoes de cada tela: um
   botao com o nome de OUTRA tela, no meio dos botoes que agem sobre ESTA, se lia como acao. A trilha
   fica acima do titulo, que e onde se procura por onde voltar. */
.breadcrumb {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 6px;
    font-size: 12px;
    color: var(--text-muted);
}

.breadcrumb a {
    color: inherit;
    text-decoration: none;
}

/* O sublinhado aparece so ao passar o mouse: aqui ele e link de verdade, e nao um botao disfarcado
   como os .btn — a diferenca e justamente o que se quer mostrar. */
.breadcrumb a:hover {
    color: var(--accent);
    text-decoration: underline;
}

.breadcrumb__separator {
    opacity: .45;
}

/* A chave recem criada, em claro, na unica vez em que ela aparece. Em destaque de proposito: quem
   sair da tela sem copiar tera de criar outra, e um aviso discreto seria justamente o que se perde. */
.admin-secret {
    margin: 12px 0;
    padding: 12px 14px;
    border: 1px solid var(--accent);
    border-radius: var(--radius);
    background: var(--accent-soft);
}

.admin-secret code {
    display: block;
    margin: 8px 0;
    padding: 8px 10px;
    border-radius: 6px;
    background: var(--surface);
    font-size: 13px;

    /* A chave e longa e nao pode ser cortada: quebrar em qualquer ponto e melhor do que esconder
       metade dela atras de uma reticencia. */
    word-break: break-all;
    user-select: all;
}

/* Citacao do pedido do cliente. Quatro linhas de altura e no maximo dez: a citacao longa rola
   dentro do proprio campo, em vez de esticar o painel e empurrar a estimativa para fora da tela. */
.textarea--evidence {
    min-height: 0;
    max-height: 15em;
    overflow-y: auto;
}

/* A GAVETA: a anatomia unica de toda secao que recolhe dentro do painel de detalhes.

   Trocado em 05/09/2026. Antes havia TRES desenhos para a mesma ideia: o <details> com o titulo em
   texto simples (estilo do no, Azure DevOps, evidencia), o cabecalho de botao do log de alteracoes —
   que ainda por cima escapava do estilo de titulo, porque o '>' de '.inspector__section > h3' nao
   alcanca um <h3> dentro de dois divs, e saia grande e escuro — e as secoes que nao recolhiam nada.
   Tres desenhos para a mesma pergunta ("isto abre?") obriga a aprender a resposta tres vezes.

   E ela precisa PARECER fechada. Um titulo pequeno e cinza com uma seta discreta a direita e
   indistinguivel do rotulo de uma secao comum, e o que se recolhe assim vira o que se esquece. A
   caixa resolve isso sem inventar cor nova: barra afundada, contorno e cantos: fechada, ela e uma
   gaveta; aberta, e uma caixa com tampa.

   TODAS NASCEM FECHADAS, e o que abre e a MEMORIA. Desde 05/09/2026 o painel guarda no localStorage
   quais gavetas a pessoa deixou abertas, e so isso: quem nunca mexeu em nada nao tem nada gravado, e
   ve o painel inteiro recolhido. Antes cada secao trazia um padrao proprio — estimativa e anexos
   abertos, estatisticas e historico fechados —, e um padrao por secao e uma opiniao nossa sobre o
   que a pessoa quer ver, repetida onze vezes. A memoria substitui a opiniao pela escolha dela. */
.inspector__drawer {
    border: 1px solid var(--border);
    border-radius: 8px;

    /* SEM 'overflow: hidden', de proposito: ha seletor de cor e menu dentro destas gavetas, e
       sobreposicao dentro de container que corta o transbordo e cortada — armadilha ja paga no menu
       de linha do cronograma. Quem arredonda o canto de cima e o proprio cabecalho. */
}

/* Cabecalho da gaveta. Veste o mesmo tamanho e a mesma cor dos <h3> das outras secoes para a secao
   fechada nao parecer de outra natureza — o que muda e a barra em volta, e nao a letra.

   O marcador nativo sai e volta como seta a DIREITA, no fim da linha: o triangulo do navegador fica
   colado a esquerda do texto, onde as outras secoes do painel comecam o titulo — e ali ele desalinha
   o cabecalho colapsavel de todos os cabecalhos vizinhos. A seta usa o mesmo --caret dos selects da
   tela, para o gesto de "isto abre" ser o mesmo desenho em todo lugar. */
.inspector__summary {
    display: flex;
    align-items: center;
    gap: 6px;

    /* O raio e UM A MENOS que o da caixa: o cabecalho desenha por dentro do contorno dela, e o mesmo
       raio nos dois deixa uma meia-lua clara no canto. */
    border-radius: 7px;
    padding: 7px 10px;
    background: var(--surface-sunken);
    cursor: pointer;
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--text-muted);
    user-select: none;

    /* list-style para o Firefox, ::-webkit-details-marker para os WebKit: os dois desenham o
       marcador por caminhos diferentes, e esconder so um deixa o triangulo em metade dos
       navegadores. */
    list-style: none;
}

/* O hover e o que promete o clique. Sem ele a barra parece um rotulo pintado, e nada na tela diz
   que a linha inteira e o alvo — o alvo e a linha, e nao a seta. */
.inspector__summary:hover {
    background: var(--border);
    color: var(--text);
}

/* Aberta, a tampa perde os cantos de baixo e ganha a linha que a separa do conteudo. E o que faz
   "aberta" e "fechada" serem dois desenhos, e nao a mesma barra com uma seta virada. */
.inspector__drawer[open] > .inspector__summary {
    border-radius: 7px 7px 0 0;
    border-bottom: 1px solid var(--border);
}

/* O corpo da gaveta. O padding mora AQUI, e nao no <details>: no <details> ele valeria tambem para o
   cabecalho, que precisa encostar no contorno para a barra ir de ponta a ponta. */
.inspector__drawer-body {
    padding: 10px;
}

/* A ultima coisa dentro da gaveta nao carrega margem para fora dela: campo e paragrafo desta base
   nascem com margem de baixo, e ela empurraria o contorno alguns pixels alem do conteudo. */
.inspector__drawer-body > :last-child {
    margin-bottom: 0;
}

/* Um subtitulo DENTRO da gaveta precisa de ar em cima: ele abre um assunto novo depois de um bloco
   que ja terminou, e colado no que vem antes se le como legenda dele. Vale para o "Resumo por ramo",
   que mora dentro da estimativa. O primeiro nao ganha nada — la em cima ja esta o cabecalho. */
.inspector__drawer-body > h3:not(:first-child) {
    margin-top: 18px;
}

.inspector__summary::-webkit-details-marker,
.drawer__summary::-webkit-details-marker {
    display: none;
}

/* margin-left:auto na SETA, e nao justify-content:space-between no summary: com space-between, o
   sufixo "— sem citacao" da secao de evidencia — que e um irmao do titulo — era empurrado para o
   meio da linha, longe do texto que ele completa. Empurrar so a seta mantem o cabecalho junto a
   esquerda, que e como ele se le. */
.inspector__summary::after,
.drawer__summary::after {
    content: "";
    flex: none;
    margin-left: auto;
    width: 14px;
    height: 14px;
    background: var(--caret) center / 14px no-repeat;
    transition: transform .15s ease;
}

details[open] > .inspector__summary::after,
details[open] > .drawer__summary::after {
    transform: rotate(180deg);
}

.inspector__summary .muted {
    text-transform: none;
    letter-spacing: 0;
    font-weight: 400;
}

/* Painel de detalhes em somente leitura. Os campos continuam LEGIVEIS — e para isso que a pessoa
   abriu o painel — e param de aceitar clique e digitacao. O contorno de foco tambem sai: um campo
   que acende ao ser focado promete uma edicao que nao vai acontecer.

   Trocado em 18/08/2026: a regra listava CLASSES (.input, .btn:not(.btn--ghost), ...) e deixava
   passar tudo o que nao usasse uma delas — os oito botoes da barra de formatacao da descricao, que
   nao tem classe nenhuma, seguiam clicaveis num painel supostamente apagado. Listar por classe e a
   lista que alguem esquece de atualizar; listar por ELEMENTO fecha por padrao o controle escrito
   amanha, seja qual for a classe dele. Mesmo argumento do comentario no topo do componente.

   O corte e por elemento interativo, e NAO um pointer-events na .inspector inteira: bloquear o
   container mataria a selecao de texto, e copiar o que esta escrito e justamente o que alguem com
   acesso de leitura precisa fazer.

   Ficam de fora, por serem leitura: <a> (baixar anexo, abrir o work item) e <summary> (expandir a
   evidencia do pedido).

   .inspector.is-readonly .input,
   .inspector.is-readonly .textarea,
   .inspector.is-readonly .select,
   .inspector.is-readonly .btn:not(.btn--ghost), ... */
.inspector.is-readonly button,
.inspector.is-readonly input,
.inspector.is-readonly textarea,
.inspector.is-readonly select,
.inspector.is-readonly [contenteditable] {
    pointer-events: none;
    background: var(--surface-sunken);
    opacity: .75;
}

/* O cabecalho do painel continua clicavel: fechar o painel nao escreve nada. */
.inspector.is-readonly .inspector__header button {
    pointer-events: auto;
    background: none;
    opacity: 1;
}

/* Na barra do editor a trilha divide a linha com o titulo do mapa e com os botoes, entao ela nao tem
   margem embaixo e nao pode encolher quando o titulo e longo. */
.breadcrumb--editor {
    margin-bottom: 0;
    flex: none;
    font-size: 13px;
}

.page__header {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;

    /* Trocado em 19/08/2026 de 28 para 16: o que vem depois do cabecalho deixou de ser a lista e
       passou a ser a barra dela, que e parte do mesmo assunto — 28px separavam demais duas coisas
       que se leem juntas. O respiro maior ficou embaixo da barra. */
    margin-bottom: 16px;
}

.page__header h1 {
    margin: 0 0 4px;
    font-size: 24px;
}

.page__header p {
    margin: 0;
    color: var(--text-muted);
}

/* Busca da lista de mapas. Fica na mesma linha do "Novo mapa": e o par de coisas que se faz ao
   chegar nesta tela, procurar um mapa ou criar outro. */
/* Trocado em 19/08/2026: a lupa e o botao de limpar ficavam FORA do campo, cada um com o proprio
   espaco, e a busca parecia tres controles soltos em vez de um. Agora a borda e do conjunto, e o
   campo por dentro nao tem borda nenhuma. */
.map-search {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 10px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    background: var(--surface);
}

/* O foco acende a caixa inteira, e nao so o input que esta dentro dela. */
.map-search:focus-within {
    outline: 2px solid var(--accent-soft);
    border-color: var(--accent);
}

.map-search > i {
    color: var(--text-muted);
    font-size: 14px;
}

.map-search .input {
    /* Largura fixa: em 100% ela empurraria o botao de novo mapa para fora em tela estreita.
       Trocado em 19/08/2026 de 240 para 200: com a ordem e o status fora da barra, o campo nao
       precisa mais ocupar o lugar deles — e o tooltip cobre o texto que nao couber. */
    width: 200px;
    max-width: 40vw;
    padding: 0;
    border: none;
    background: none;
}

/* A caixa ja tem o foco visivel; repeti-lo aqui desenharia um retangulo dentro do outro. */
.map-search .input:focus {
    outline: none;
}

/* Dentro da caixa o botao de limpar e um X discreto, e nao um botao com area propria. */
.map-search .btn--icon {
    padding: 2px;
    margin-right: -2px;
    font-size: 12px;
    color: var(--text-muted);
}

/* Estreito o bastante para caber ao lado da busca em tela media. */
.map-sort {
    width: auto;
    min-width: 130px;
}

/* A seta NATIVA do select e desenhada pelo sistema operacional: ela muda de forma e de tamanho entre
   Windows, macOS e Linux. Aqui ela e desligada e redesenhada, para o select ter a mesma seta em
   qualquer maquina — SVG embutido, sem arquivo novo para servir.

   Trocado em 19/08/2026: valia para o select da BARRA, que foi para o painel lateral. Segue o
   mesmo desenho, agora no seletor de ordem do painel.

   Trocado em 27/08/2026: o seletor de ordem VOLTOU para a barra da lista, e a regra ficou presa ao
   painel — o select reapareceu com a seta nativa, destoando dos dois botoes ao lado. E a segunda vez
   que este desenho se perde ao mudar de lugar, entao agora ele nao mora mais num container: quem
   ganha a seta e o SELETOR, onde quer que ele esteja.
   .drawer__group > .select { ... }

   O padding a direita abre o espaco dela; sem ele o texto passa por baixo do desenho. */
.drawer__group > .select,
.list-toolbar__sort {
    appearance: none;
    padding-right: 30px;
    background-image: var(--caret);
    background-repeat: no-repeat;
    background-position: right 9px center;
    background-size: 13px;
}

.pager {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-top: 18px;
}

.pager__label {
    font-size: 13px;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.map-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 16px;
}

.map-card {
    display: flex;
    flex-direction: column;
    padding: 18px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--surface);
    box-shadow: var(--shadow-sm);
    transition: box-shadow .15s, transform .15s;
}

.map-card:hover {
    box-shadow: var(--shadow-md);
    transform: translateY(-1px);
}

/* A linha do titulo com a estrela. O titulo e a parte que CEDE (min-width: 0 + o corte por
   reticencias): item de flex nasce com min-width: auto e se recusa a ficar menor que o conteudo, e
   um nome de mapa comprido empurraria a estrela para fora do cartao. */
.map-card__header {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin: 0 0 6px;
}

.map-card__title {
    flex: 1;
    min-width: 0;
    margin: 0;
    font-size: 16px;
    font-weight: 600;
}

/* O recuo de cima compensa o padding do botao, para o glifo alinhar com a PRIMEIRA linha do titulo
   e nao com a caixa dele — o titulo tem duas linhas em varios cartoes, e alinhar pela caixa desceria
   a estrela para o meio das duas.

   O -7px foi MEDIDO, e nao escolhido: com o -5px inicial o centro do glifo ficava 2,5px abaixo do
   centro da primeira linha (430,5 contra 428,0), medido com um Range sobre o texto do titulo. */
.map-card__favorite {
    flex: 0 0 auto;
    margin: -7px -6px 0 0;
    color: var(--text-muted);
    font-size: 15px;
}

/* Ambar, e nao o azul do --accent: a estrela nao e "selecionado", e o azul ja diz isso em toda a
   tela. O tom e o --warning, que aqui nao encosta em nada — os emblemas do cartao sao todos
   neutros, e o unico outro colorido e o link do titulo, que so acende no hover. */
.map-card__favorite.is-on {
    color: var(--warning, #d97706);
}

.map-card__favorite:hover:not(:disabled) {
    color: var(--warning, #d97706);
}

.map-card__title a {
    color: inherit;
    text-decoration: none;
}

.map-card__title a:hover {
    color: var(--accent);
}

.map-card__description {
    flex: 1;
    margin: 0 0 14px;
    color: var(--text-muted);
    font-size: 13px;
    line-height: 1.5;

    /* Corta em tres linhas: a descricao de um mapa e texto livre e chega a varios paragrafos, e um
       cartao esticado por ela empurra os vizinhos da grade e some com os botoes abaixo da dobra.
       O texto inteiro continua acessivel no title do elemento. */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    overflow: hidden;
}

.map-card__meta {
    font-size: 12px;
    color: var(--text-muted);
    margin-bottom: 12px;
}

.map-card__actions {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* A barra fica com a largura que sobrar do cartao — e essa sobra que ela usa como orcamento. */
.map-card__actions > .overflow-toolbar {
    flex: 1;
    min-width: 0;
}

/* A barra PRECISA crescer, e nao apenas encolher.
   Com flex: 0 1 auto a largura dela e a largura do conteudo — entao esconder um botao encolhia a
   propria regua, e a barra concluia que continuava sem espaco. Recolhia tudo e nunca voltava.
   Com flex-grow ela fica com o que sobrar da linha independentemente do que carrega dentro, que e
   a unica medida que responde "quanto espaco eu tenho".
   O justify-content mantem os comandos encostados a direita, onde eles sempre estiveram. */
.editor__topbar > .overflow-toolbar {
    flex: 1 1 auto;
    min-width: 0;
    justify-content: flex-end;
}

/* ---------------------------------------------------------------------------------------
   Barra que se recolhe (OverflowToolbar)
   --------------------------------------------------------------------------------------- */

.overflow-toolbar {
    display: flex;
    align-items: center;
    gap: 6px;

    /* A barra nao pode crescer com o conteudo: e a largura DELA que o JS usa como orcamento, e uma
       barra que se estica para caber tudo mediria sempre "cabe tudo" e nunca recolheria nada. */
    min-width: 0;

    /* NAO ponha overflow: hidden aqui. Parece a defesa obvia contra o excedente vazar antes da
       primeira medicao, mas recorta junto o menu, que e posicionado em absolute logo abaixo da
       barra — o menu abre, ganha a classe is-open, e simplesmente nao aparece. O excedente ja sai
       do fluxo por display: none assim que o JS mede, no primeiro render. */
    overflow: visible;
}

.overflow-toolbar__item {
    display: flex;
    flex: 0 0 auto;
}

.overflow-toolbar .is-hidden {
    display: none;
}

.overflow-toolbar__more {
    position: relative;
    display: flex;
    flex: 0 0 auto;
}

.overflow-toolbar__menu {
    display: none;
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    z-index: 41;
    min-width: 190px;
    padding: 4px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
    box-shadow: var(--shadow-md);
}

.overflow-toolbar__menu.is-open {
    display: block;
}

.overflow-toolbar__menu-row > a,
.overflow-toolbar__menu-row > button {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 7px 10px;
    border: 0;
    border-radius: 6px;
    background: none;
    color: var(--text);
    font: inherit;
    font-size: 13px;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
}

.overflow-toolbar__menu-row > a:hover,
.overflow-toolbar__menu-row > button:hover {
    background: var(--surface-muted);
}

.overflow-toolbar__menu-row > button.is-danger {
    color: var(--danger);
}

.overflow-toolbar__menu-row > button.is-warn {
    color: var(--warn-text, #92400e);
}

/* Estreito de proposito: o botao de excedente disputa a mesma linha que ele existe para desafogar,
   e um botao de largura normal come o espaco de quase um comando. O ⋮ e alto e fino, entao aguenta
   perder a largura sem perder a leitura. */
.overflow-toolbar__more-btn {
    min-width: 0;
    width: 26px;
    padding-left: 0;
    padding-right: 0;

    /* O .btn e flex com justify-content normal: nos demais botoes o icone so parece centrado porque
       o padding lateral o empurra. Zerado o padding para estreitar, o icone encostava na esquerda —
       aqui a centralizacao precisa ser dita. */
    justify-content: center;
}

/* ---------------------------------------------------------------------------------------
   Editor: moldura
   --------------------------------------------------------------------------------------- */

.editor {
    display: flex;
    flex-direction: column;
    height: 100vh;
    overflow: hidden;
}

.editor__topbar {
    display: flex;
    align-items: center;

    /* Ancora da faixa do filtro em tela estreita, que abre logo abaixo da barra. */
    position: relative;
    gap: 10px;
    padding: 10px 14px;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    z-index: 30;
}

/* Com um campo AMPLIADO no painel, a barra desce para baixo dele. O fundo do ampliado mora dentro do
   '.inspector' (z-index 20), e com os 30 daqui a barra ficava por cima do fundo: clicar nela nao
   fechava o ampliado — e ainda acionava os botoes do mapa atras dele. Visto em 16/09/2026. Os 30
   existem para os menus da barra abrirem sobre o painel, e com o ampliado aberto nao ha menu aberto. */
.editor:has(.expandable.is-expanded) .editor__topbar {
    z-index: 19;
}

.editor__title {
    font-weight: 600;
    font-size: 15px;
    margin-right: auto;

    /* Encolhe ANTES dos comandos, e nao junto: o titulo tem reticencias e continua legivel pela
       metade, enquanto um botao pela metade nao serve para nada. */
    flex: 0 8 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.editor__body {
    position: relative;
    flex: 1;
    display: flex;
    min-height: 0;
}

.toolbar-group {
    display: flex;
    gap: 2px;
    padding: 0 6px;
    border-left: 1px solid var(--border);
}

.toolbar-group:first-of-type {
    border-left: none;
}

/* A barra de uma PAGINA, com controles de tamanho inteiro — nao a fileira de icones colados do
   editor, que e para o que o .toolbar-group acima nasceu (gap de 2px e divisoria a esquerda). */
.toolbar-group--page {
    gap: 10px;
    padding: 0;
    border-left: none;
}

/* A barra da LISTA de mapas: linha propria entre o cabecalho e os cartoes. Acrescentada em
   19/08/2026, quando a busca e o "Novo mapa" sairam da linha do titulo. */
.list-toolbar {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 20px;

    /* QUEBRA em vez de espremer. A barra recebeu ordenar, status e "todos" em 27/08/2026, e em tela
       estreita eles nao cabem na mesma linha da busca e do "Novo mapa". Recolher num menu foi
       descartado: este card nasceu justamente de um controle escondido atras de um gatilho que nao
       diz o que abre, e escondelos de novo seria repetir o problema um nivel abaixo. */
    flex-wrap: wrap;
}

/* A busca e a parte que CEDE: ela cresce com o espaco que sobra e encolhe antes dos botoes, que tem
   largura de rotulo e nao teriam para onde encolher. O min-width zero e obrigatorio — item de flex
   nasce com 'min-width: auto' e se recusa a ficar menor que o conteudo, e sem ele a barra estica em
   vez de quebrar. */
/* Trocado em 19/09/2026, a pedido do usuario: era 'flex: 1 1 220px', e a busca crescia ate ocupar
   a linha inteira. Agora ela tem teto — so encolhe, nunca cresce — e o "Novo mapa" vai para a ponta
   direita pela margem automatica. */
.list-toolbar > .map-search {
    flex: 0 1 280px;
    min-width: 0;
}

/* O input acompanha a caixa, e nao os 200px fixos da busca do cabecalho: aqui quem manda na largura
   e o flex de cima. */
.list-toolbar > .map-search .input {
    flex: 1;
    width: auto;
    min-width: 0;
    max-width: none;
}

.list-toolbar > .btn--primary {
    margin-left: auto;
}

/* A ajuda da busca avancada abre ANCORADA na caixa de busca (desde 19/09/2026). */
.list-toolbar > .map-search {
    position: relative;
}

.map-search__help {
    max-width: calc(100vw - 24px);
}

.map-search__help code {
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    color: var(--accent);
}

.list-toolbar__filters {
    display: flex;
    align-items: center;
    gap: 8px;

    /* QUEBRA por dentro tambem, e nao so a barra que a hospeda. Ate 28/08/2026 o grupo era UM item
       de flex indivisivel: com tres controles ele cabia em 375px, e o quarto — o "Favoritos" — o
       levou a 443px dentro de uma tela de 375, empurrando a PAGINA inteira (scrollWidth 467 contra
       clientWidth 375, medido). A barra de fora quebrava; o grupo, nao.

       Sem isto a saida seria esconder um controle num menu, e essa opcao ja foi descartada quando a
       barra nasceu: o card que a originou era justamente sobre controle escondido atras de um
       gatilho que nao diz o que abre. */
    flex-wrap: wrap;
}

/* Descendente, e nao filho direto: o botao de status mora dentro do '.list-toolbar__menu', que e a
   ancora do popover. Com '>' ele ficava de fora e saia com 35px contra os 38px de todos os vizinhos
   — os "dois ou tres pixels" que a regra de altura unica existe para nao deixar acontecer. */
.list-toolbar__filters .btn,
.list-toolbar__sort {
    height: 38px;
}

/* Largura de conteudo, e nao a do formulario: o '.select' e largo porque nasceu para campo dentro do
   painel, e numa barra ele empurraria todo o resto. */
.list-toolbar__sort {
    width: auto;
}

/* ANCORA do popover. Sem ela o absolute sobe ate o primeiro ancestral posicionado, que aqui nao e o
   botao — e o menu abriria longe de quem o abriu. Mesma armadilha ja paga no menu de mapas da trilha
   e na barra do lote. */
.list-toolbar__menu {
    position: relative;
    display: flex;
}

.list-toolbar__popover {
    top: calc(100% + 6px);
    left: 0;
    min-width: 240px;

    /* Teto medido, e nao precaucao: em 375px o menu abria com a borda direita EXATAMENTE na do
       viewport e a pagina ganhava rolagem horizontal. */
    max-width: calc(100vw - 24px);
}

/* Em tela estreita a barra ja quebrou em linhas, e o botao de status pode ficar perto da borda
   direita — ancorado pela esquerda, o menu sai da tela. Ancorado pela DIREITA ele cresce para
   dentro. Na tela larga o botao vive no meio da barra e a ancora pela esquerda e a certa: menu que
   nasce alinhado ao gatilho e o que se le como "abriu daqui". */
@media (max-width: 720px) {
    .list-toolbar__popover {
        left: auto;
        right: 0;
    }
}

/* O menu "mais opcoes" e o ultimo controle antes do "Novo mapa", e abre para DENTRO em qualquer
   largura: ancorado pela esquerda ele passaria por cima do botao primario. */
.list-toolbar__popover--end {
    left: auto;
    right: 0;

    /* Mais largo que o de status: os rotulos daqui sao frases, e em 240px quebravam em duas linhas. */
    min-width: 280px;
}

/* Botao de recorte LIGADO. O estado precisa aparecer com o popover FECHADO: filtro em vigor que nao
   se anuncia faz procurar no lugar errado o mapa que sumiu — mesmo motivo do contador ao lado. */
.btn--active {
    border-color: var(--accent);
    color: var(--accent);
    background: color-mix(in srgb, var(--accent) 10%, var(--surface));
}

.btn--active:hover {
    background: color-mix(in srgb, var(--accent) 18%, var(--surface));
}

/* A altura: botao e campo tem paddings proprios e terminavam com dois ou tres pixels de diferenca
   entre si, o suficiente para a linha parecer desalinhada sem que se descubra onde. Uma altura
   unica resolve os dois de uma vez, nas duas barras. */
.toolbar-group--page > .btn,
.toolbar-group--page > .map-search,
.list-toolbar > .btn,
.list-toolbar > .map-search {
    height: 38px;
}

/* ---------------------------------------------------------------------------------------
   Canvas
   --------------------------------------------------------------------------------------- */

.map-viewport {
    position: relative;
    flex: 1;
    overflow: hidden;
    background-color: var(--surface-muted);
    background-image: radial-gradient(circle, var(--border-strong) 1px, transparent 1px);
    background-size: 24px 24px;
    touch-action: none;
    cursor: grab;
    user-select: none;
}

.map-viewport.is-panning {
    cursor: grabbing;
}

.map-viewport.is-dragging-node {
    cursor: grabbing;
}

/* Camada do pan/zoom. O transform e escrito pelo JS; o Blazor nao renderiza style aqui, senao
   cada re-render apagaria a posicao da tela. */
.map-canvas {
    position: absolute;
    top: 0;
    left: 0;
    transform-origin: 0 0;
}

/* Camada do conteudo. As dimensoes vem do layout, entao quem manda no style e o Blazor. */
.map-content {
    position: relative;
}

/* Primeira passada: os nos precisam ser renderizados para serem medidos, mas mostrar essa
   passada com o layout ainda estimado produziria um salto visivel. */
.map-content.is-measuring {
    opacity: 0;
}

.edge-layer {
    position: absolute;
    top: 0;
    left: 0;
    pointer-events: none;
    overflow: visible;
}

.edge-temp {
    stroke: var(--accent);
    stroke-width: 2;
    stroke-dasharray: 6 4;
}

.cross-link {
    stroke-dasharray: 7 5;
    opacity: .75;
}

.cross-link-hit {
    pointer-events: stroke;
    cursor: pointer;
    stroke: transparent;
    stroke-width: 14;
    fill: none;
}

.cross-link-label {
    font-size: 11px;
    fill: var(--text-muted);
    paint-order: stroke;
    stroke: var(--surface-muted);
    stroke-width: 4px;
    stroke-linejoin: round;
}

/* ---------------------------------------------------------------------------------------
   No
   --------------------------------------------------------------------------------------- */

.node {
    position: absolute;
    display: flex;
    align-items: center;
    gap: 7px;

    /* width: max-content e obrigatorio, nao cosmetico.
       Um elemento absoluto sem largura encolhe ate caber no espaco QUE SOBRA do contenedor a partir
       do seu 'left'. Como a largura do contenedor vem do layout, e o layout vem da medicao dos nos,
       isso fecha um laco: contenedor estreito -> no medido estreito -> layout estreito. Um no
       proximo da borda direita era medido menor do que o texto exige, quebrava linha sem precisar, e
       o botao de novo filho — posicionado pela largura do layout — caia dentro do proprio no. */
    width: max-content;
    max-width: 260px;
    padding: 7px 12px;

    /* O estilo por STATUS entra por variavel, e nao como declaracao inline no elemento.
       A diferenca decide a ordem de aplicacao pedida: declaracao inline venceria TUDO, e o
       esmaecimento da busca (.node.is-dimmed) e o realce da selecao (.node.is-selected) deixariam de
       funcionar em qualquer no com estilo de status. Por variavel, o valor do status e so o PADRAO
       de cada propriedade, e qualquer regra de duas classes o cobre — que e exatamente
       "aplicado antes dos outros estilos".

       O canvas define --status-* no elemento quando ha o que pintar; sem configuracao, os fallbacks
       abaixo mantem o no como sempre foi. */
    border: 2px solid var(--status-border, transparent);
    border-radius: 8px;
    background: var(--status-bg, var(--surface));
    color: var(--status-fg, inherit);
    opacity: var(--status-opacity, 1);
    box-shadow: var(--shadow-sm);
    cursor: grab;
    translate: var(--drag-dx, 0) var(--drag-dy, 0);
}

.node:hover {
    box-shadow: var(--shadow-md);
}

.node.is-selected {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-soft), var(--shadow-md);
}

/* Faixa flutuante abaixo do no: horas estimadas, aviso de recente, e o que vier depois.

   'pointer-events: none' e o detalhe que a mantem inofensiva: ela cobre a area logo abaixo do no, e
   sem isso engoliria o clique de quem tenta selecionar o no de baixo num mapa apertado. */
.node-info {
    position: absolute;
    display: flex;
    gap: 4px;
    pointer-events: none;
    z-index: 6;
}

.node-info__chip {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 0 5px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface);
    font-size: 9px;
    line-height: 15px;
    color: var(--text-muted);
    white-space: nowrap;
    box-shadow: var(--shadow-sm);

    /* A saida do aviso de recente. Ver .is-fading, adiante. */
    opacity: 1;
    transition: opacity .45s ease;
}

/* Chip de SINAL: fundo cheio, sem borda, texto branco.

   A borda existe no chip neutro para separa-lo do fundo pontilhado do canvas; no chip colorido ela
   seria contorno em cima de contorno, e e o que obrigava o desenho a ser maior para caber os dois.
   Sem ela, o mesmo aviso cabe em menos pixels e ainda assim se ve de longe — que e o ponto de um
   aviso. */
.node-info__chip--accent,
.node-info__chip--warning {
    border-color: transparent;
    color: #fff;
}

.node-info__chip--accent {
    background: var(--accent);
}

/* Ambar mais escuro que o #f59e0b dos outros avisos, e de proposito: aquele e usado com texto
   escuro em cima, e aqui o texto e branco — sobre o tom claro ele ficaria ilegivel. */
.node-info__chip--warning {
    background: #d97706;
}

/* O item nao sai da lista quando e dado por visto: ele fica, transparente. Removido do laco,
   desapareceria de um quadro para o outro — e o requisito pede que ele SUMA suavemente. */
.node-info__chip.is-fading {
    opacity: 0;
    border-color: transparent;
    box-shadow: none;
}

/* Chip que AGE, e nao so avisa: hoje o que revela os filhos escondidos pela visão.

   O 'pointer-events: auto' e obrigatorio, e nao cosmetico: a faixa inteira desliga o ponteiro para
   nao engolir o clique de quem tenta selecionar o no de baixo num mapa apertado, e sem religa-lo
   AQUI o botao simplesmente nao seria clicavel.

   As tres primeiras declaracoes desfazem o desenho que o navegador da a <button> — fonte propria,
   margem e o alinhamento de baseline — para ele ficar identico ao chip vizinho, que e um <span>. */
.node-info__chip--action {
    font: inherit;
    font-size: 9px;
    margin: 0;
    pointer-events: auto;
    cursor: pointer;
}

.node-info__chip--action:hover {
    border-color: var(--accent);
    color: var(--accent);
}

.node.is-dragging {
    opacity: .65;
    z-index: 20;
    cursor: grabbing;
}

/* Revelado por quem olha: o no NAO casa com o criterio da visão, e so esta na tela porque alguem
   clicou no chip para ve-lo. Sem esta marca a visão passaria a mentir — o mapa mostraria como
   resultado do recorte um no que ele havia justamente excluido.

   Sao dois sinais, e a duplicidade e proposital. A borda tracejada e o que SOBREVIVE: um no revelado
   que tambem seja resultado da busca recebe .is-match logo abaixo, que devolve a opacidade cheia, e
   ali a transparencia sozinha nao diria mais nada.

   Vem ANTES do .is-dimmed e do .is-match de proposito. As tres regras tem a mesma especificidade,
   entao quem vem depois vence — e a busca tem que continuar mandando na opacidade, senao um no
   revelado ficaria mais aceso que os outros resultados so por estar revelado. */
.node.is-revealed {
    border-style: dashed;
    opacity: .6;
}

/* Fora do filtro: o no continua legivel e clicavel, so recua para o fundo. Esconde-lo quebraria a
   leitura da arvore — o que se procura so faz sentido no lugar onde esta. */
.node.is-dimmed {
    opacity: .28;
}

/* DENTRO do filtro: a opacidade pedida pelo estilo de status e desligada.

   Um status configurado com opacidade baixa somava dois efeitos no mesmo no — a transparencia dele e
   o esmaecimento dos vizinhos excluidos — e o resultado da busca acabava tao apagado quanto o que o
   filtro tinha jogado para o fundo. Buscar por 'status:closed' apagava exatamente os nos procurados.

   Duas classes, para vencer o var(--status-opacity) do .node. Fundo, fonte e borda do status
   continuam valendo: eles nao competem com o esmaecimento, e sao o que diz de que status o resultado
   e. */
.node.is-match {
    opacity: 1;
}

.node.is-dimmed:hover {
    opacity: .75;
}

.node.is-root {
    padding: 11px 18px;
    font-size: 17px;
    font-weight: 700;
}

.node--depth1 {
    font-size: 14px;
    font-weight: 600;
}

.node--depth2 {
    font-size: 13px;
}

/* A PROFUNDIDADE decide o tamanho; o STATUS decide a cor. Antes: color: #334155.

   Este seletor tem uma classe so, igual ao .node, e vem depois no arquivo — com a especificidade
   empatada, quem vem depois vence. O literal cravado aqui sobrepunha o var(--status-fg) do .node, e
   a cor de fonte configurada por status parava de valer da profundidade 3 para baixo, sem erro
   nenhum. Passava despercebido num mapa raso e aparecia num mapa fundo, que foi como ele foi achado.

   O #334155 continua sendo o padrao desta profundidade; ele agora e o FALLBACK, e cede quando o
   status opina. Ver a regra do .node e o MapCanvas.StatusStyleVars. */
.node--deep {
    font-size: 12.5px;
    color: var(--status-fg, #334155);
}

.node__text {
    white-space: pre-wrap;
    word-break: break-word;
    outline: none;
    min-width: 12px;
}

.node[data-editing] {
    cursor: text;
}

.node[data-editing] .node__text {
    cursor: text;
    user-select: text;
}

.node__icon {
    flex-shrink: 0;
    font-size: 15px;
    line-height: 1;
}

/* TODOS os emblemas do no herdam o tamanho daqui: status, prioridade, tem descricao, tem ressalva,
   comentarios e anexos. Mexer neste numero mexe na linha inteira, e e por isso que ele existe — um
   tamanho por emblema divergiria no primeiro que alguem acrescentasse.

   Trocado em 23/08/2026 de 11px para 13px: a pedido do usuario, os glifos estavam pequenos demais
   para serem lidos varrendo o mapa, que e o unico uso que eles tem. O gap subiu junto, de 3 para 4:
   glifo maior com o mesmo respiro anterior encosta um no outro e a linha vira uma mancha. */
/* Pilula de prioridade no canto superior direito do card, meio para fora da borda, para ser a
   primeira coisa vista sem disputar espaco com os emblemas. So existe para critica e alta. */
.node__priority {
    position: absolute;
    top: -8px;
    right: 10px;
    padding: 1px 7px;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 700;
    line-height: 14px;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: #fff;
    pointer-events: auto;
    white-space: nowrap;
}

.node__priority--critical { background: #d32f2f; }
/* Alta era laranja escuro solido (#e65100), mas no tamanho da pilula ficava quase igual ao
   vermelho da critica. Agora e contornada: a diferenca vem da forma, nao so do tom. */
.node__priority--high {
    background: var(--surface, #fff);
    color: #c2410c;
    box-shadow: inset 0 0 0 1.5px #ea580c;
}

.node__badges {
    display: flex;
    gap: 4px;
    flex-shrink: 0;
    font-size: 13px;
    color: var(--text-muted);
}

/* O emblema do submapa. E o unico da fileira que se clica, entao precisa parecer clicavel: em
   repouso ele se parece com os vizinhos, e sob o cursor ganha MOLDURA, fundo e tinta de acento.

   Trocado em 10/09/2026: o hover era so a troca de cor, e num no colorido ele quase nao aparecia —
   o alvo do clique nao se distinguia dos emblemas ao lado, que nao clicam.
   .node__submap:hover { color: var(--accent); }

   A borda e transparente EM REPOUSO, e nao ausente: uma borda que nasce no hover acrescenta dois
   pixels a largura do emblema, e a fileira inteira dancaria ao passar o mouse. */
.node__submap {
    display: inline-flex;
    align-items: center;
    padding: 1px 3px;
    border: 1px solid transparent;
    border-radius: 5px;
    background: none;
    color: inherit;
    font-size: inherit;
    line-height: 1;
    cursor: pointer;
}

.node__submap:hover {
    border-color: var(--accent);
    background: var(--surface);
    color: var(--accent);
}

/* O emblema de finalizado. Verde e MAIOR que os vizinhos: e o estado que a pessoa procura varrendo
   o mapa, e um glifo do mesmo tamanho e da mesma cor dos outros se perde no meio deles.
   A forma tambem e propria — roseta, e nao circulo —, porque de longe se le a forma antes da cor. */
.node__done {
    color: var(--success, #16a34a);

    /* Sobe junto com os vizinhos, mantendo os MESMOS 3px de vantagem: e a diferenca que o faz
       destacar-se, e congela-la em 14px enquanto a linha cresce para 13 a apagaria. */
    font-size: 16px;

    /* Sem isto o emblema encolhe quando o titulo do no e longo e a linha aperta. */
    flex-shrink: 0;

    /* A linha de emblemas alinha pelo topo; o glifo maior desce um fio para centralizar com os
       vizinhos. */
    line-height: 1;
}

.node__accent {
    position: absolute;
    left: 0;
    top: 8px;
    bottom: 8px;
    width: 3px;
    border-radius: 3px;
}

.node--side-left .node__accent {
    left: auto;
    right: 0;
}

/* Indicadores de soltura */
.node.is-drop-child {
    border-color: var(--accent);
    background: var(--accent-soft);
}

.node.is-drop-before {
    box-shadow: 0 -3px 0 0 var(--accent), var(--shadow-sm);
}

.node.is-drop-after {
    box-shadow: 0 3px 0 0 var(--accent), var(--shadow-sm);
}

.node.is-link-target {
    border-color: #7c3aed;
    background: #f5f3ff;
}

/* Marcador de colapsar/expandir */
/* Redondo por padrao, capsula quando o numero nao couber.

   O contador cabia em dois digitos e vazava no terceiro: o interior e de 12px e "137" mede 15,5px,
   com o primeiro e o ultimo algarismo por cima da borda. Medido em 22/08/2026, a partir de 100
   descendentes num ramo recolhido.

   'min-width' no lugar de 'width' faz a caixa crescer SO quando aperta: um digito e dois continuam
   no circulo de 16px (o segundo com 0,4px a mais, invisivel), e o terceiro estica para 21,5px. O
   raio e 999px, e nao 50%: meio por cento numa caixa que cresce vira ELIPSE.

   O translateX faz o crescimento ser para os DOIS lados. Preso pela esquerda, o contador cresceria
   sobre o proprio no no lado esquerdo do mapa e sobre o botao de adicionar filho no direito — a
   folga e de 5px de cada lado. Ancorado pelo centro, tres digitos pedem 2,8px por lado e cabem. O
   'left' que chega aqui e o CENTRO; ver MapCanvas.ToggleX.

   O limite conhecido: com QUATRO digitos (mil descendentes num ramo) a folga acaba e ele encosta. */
.collapse-toggle {
    position: absolute;
    min-width: 16px;
    height: 16px;
    padding: 0 1px;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px solid currentColor;
    border-radius: 999px;
    background: var(--surface);
    font-size: 9px;
    line-height: 1;
    cursor: pointer;
    z-index: 5;
}

.collapse-toggle:hover {
    background: var(--surface-sunken);
}

.collapse-toggle__count {
    font-size: 9px;
    font-weight: 700;
}

/* Ramo recolhido com item em aberto la dentro.
   
   O sinal e PREENCHIMENTO, e nao matiz: o botao normal e um circulo vazado com a cor do RAMO, e
   #f59e0b — o ambar obvio para "pendente" — e uma das cores da paleta de ramos. Num ramo dessa cor,
   um aviso so de matiz ficava indistinguivel do botao comum, e ramo terminado e ramo com pendencia
   viravam o mesmo desenho. Cheio contra vazado se le em qualquer ramo.
   
   O tom escuro (ambar 700) e a segunda linha de defesa, para o contraste sobreviver ao ramo que ja
   e ambar claro; e ambar, e nao vermelho, porque e "ainda tem coisa" e nao "deu errado". */
.collapse-toggle:has(.collapse-toggle__count--open) {
    border-color: #b45309;
    background: #b45309;
}

.collapse-toggle:has(.collapse-toggle__count--open):hover {
    border-color: #92400e;
    background: #92400e;
}

.collapse-toggle__count--open {
    color: #fff;
}

/* ---------------------------------------------------------------------------------------
   Toolbar flutuante do no
   --------------------------------------------------------------------------------------- */

.node-toolbar {
    position: absolute;
    display: flex;
    align-items: center;
    gap: 1px;

    /* Mesmo motivo do .node: sem isso a barra e espremida quando o no esta perto da borda. */
    width: max-content;
    padding: 4px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
    box-shadow: var(--shadow-lg);
    z-index: 25;
    white-space: nowrap;
}

.node-toolbar button {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    border: none;
    border-radius: 7px;
    background: transparent;
    cursor: pointer;
    font-size: 15px;
}

.node-toolbar button:hover {
    background: var(--surface-sunken);
}

/* Botao dividido do status: o alternador de aprovado a esquerda e a seta da lista a direita.
   Os dois ficam colados dentro do mesmo span para se lerem como UM controle — com o gap da barra
   entre eles, a seta pareceria mais um botao independente, sem relacao com o que ela abre. */
/* Os seletores repetem .node-toolbar de proposito. A regra generica acima e
   ".node-toolbar button" — uma classe MAIS um tipo —, e ela vence uma classe sozinha: escritas como
   ".node-toolbar__split-caret", estas declaracoes eram todas perdidas em silencio e a seta saia com
   os 30px e o raio de 7px do botao comum. */
.node-toolbar .node-toolbar__split {
    display: flex;
    align-items: center;

    /* O fundo do hover fica no CONJUNTO, e nao em cada metade: acender so o pedaco sob o cursor
       parte visualmente em dois o que e um controle so. */
    border-radius: 7px;
}

.node-toolbar .node-toolbar__split:hover {
    background: var(--surface-sunken);
}

.node-toolbar .node-toolbar__split-main {
    width: 26px;
    border-radius: 7px 0 0 7px;
}

.node-toolbar .node-toolbar__split-caret {
    width: 13px;
    font-size: 8px;
    color: var(--text-muted);
    border-radius: 0 7px 7px 0;
}

/* Fio tenue entre as duas metades, para se ler um botao com uma aba, e nao um botao unico com a
   seta enfeitando. Feito com border-left, e nao com um ::before posicionado: o unico ancestral
   posicionado aqui e a .node-toolbar, entao o absolute se penduraria na barra inteira. */
.node-toolbar .node-toolbar__split-caret {
    border-left: 1px solid var(--border);
}

.status-picker {
    width: 190px;
}

/* O menu "mais" da barra do no. Um pouco mais largo que o de status porque os rotulos daqui sao
   frases curtas ("Conectar a outro no (arraste)"), e nao uma palavra.

   Ele reusa a .status-list de proposito: as duas sao a mesma lista de icone mais rotulo, e um
   segundo conjunto de regras identicas divergiria na primeira vez que alguem mexesse numa so. */
.action-menu {
    width: 230px;
}

.status-list {
    display: flex;
    flex-direction: column;
    margin-top: 6px;
}

.status-list__item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border: none;
    border-radius: 6px;
    background: none;
    font: inherit;
    font-size: 13px;
    color: inherit;
    text-align: left;
    cursor: pointer;
}

.status-list__item:hover {
    background: var(--surface-sunken);
}

.status-list__item.is-selected {
    color: var(--accent);
}

/* Largura fixa no emblema para os rotulos alinharem: os glifos de status tem larguras diferentes
   — a ampulheta e estreita, a roseta do finalizado e larga — e sem isto o texto de cada linha
   comeca num lugar. */
.status-list__item > .bi:first-child {
    width: 16px;
    text-align: center;
    color: var(--text-muted);
}

.status-list__item.is-selected > .bi:first-child {
    color: inherit;
}

/* O visto vai para a ponta direita, longe do emblema do status: encostados, os dois viram um
   simbolo so e o da esquerda deixa de se ler como o estado. */
.status-list__check {
    margin-left: auto;
}

.node-toolbar__divider {
    width: 1px;
    height: 20px;
    margin: 0 3px;
    background: var(--border);
}

.node-add {
    position: absolute;
    width: 20px;
    height: 20px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 50%;
    background: var(--accent);
    color: #fff;
    font-size: 11px;
    cursor: pointer;
    z-index: 24;
    box-shadow: var(--shadow-sm);
}

.node-add:hover {
    background: #1d4ed8;
}

/* ---------------------------------------------------------------------------------------
   Popovers (cor, icone, link)
   --------------------------------------------------------------------------------------- */

.popover {
    position: absolute;
    padding: 12px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
    box-shadow: var(--shadow-lg);
    z-index: 40;
}

.popover__title {
    font-size: 12px;
    font-weight: 600;
    color: var(--text-muted);
    margin-bottom: 8px;
    text-transform: uppercase;
    letter-spacing: .03em;
}

.color-grid {
    display: grid;
    grid-template-columns: repeat(6, 24px);
    gap: 6px;
}

.color-swatch {
    width: 24px;
    height: 24px;
    border: 2px solid transparent;
    border-radius: 50%;
    cursor: pointer;
    padding: 0;
}

.color-swatch.is-selected {
    border-color: var(--text);
}

.icon-picker {
    width: 300px;
}

/* Editor de rotulo da conexao cruzada */
.link-editor {
    position: absolute;
    width: max-content;
    padding: 10px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
    box-shadow: var(--shadow-lg);
    z-index: 30;
}

.link-editor__row {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 6px;
}

.link-editor__row .input {
    width: 190px;
}

.icon-grid {
    display: grid;
    grid-template-columns: repeat(8, 1fr);
    gap: 2px;
    max-height: 220px;
    overflow-y: auto;
    margin-top: 8px;
}

.icon-grid button {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 32px;
    border: none;
    border-radius: 6px;
    background: transparent;
    cursor: pointer;
    font-size: 16px;
}

.icon-grid button:hover {
    background: var(--surface-sunken);
}

.icon-grid button.is-selected {
    background: var(--accent-soft);
    color: var(--accent);
}

/* ---------------------------------------------------------------------------------------
   Painel lateral
   --------------------------------------------------------------------------------------- */

/* A divisoria arrastavel entre o canvas e o painel. Ela NAO ocupa largura: a linha que se ve continua
   sendo a borda esquerda do painel, e este elemento so poe uma area de pegada por cima dela. Dando
   largura propria a ele, a borda andaria alguns pixels por causa de um controle invisivel.

   Mesma anatomia da .gantt__splitter — ver o inspector-splitter.js para o que muda entre as duas. */
.inspector-splitter {
    position: relative;

    /* O PAINEL vem depois no DOM e ainda por cima tem 'z-index: 20', e entre irmaos posicionados quem
       vem depois pinta por cima: sem um empilhamento MAIOR que o dele, a area de pegada fica atras do
       painel e o clique acerta o cabecalho em vez da divisoria. */
    z-index: 21;

    flex: 0 0 0;

    /* Sem isto, no toque o navegador entende o arraste como rolagem e a divisoria nao anda. */
    touch-action: none;
}

/* Com um campo AMPLIADO no painel — descricao, ressalva ou comentario —, a divisoria desce para baixo
   dele. O ampliado tem z-index 101, mas mora DENTRO do '.inspector', que com 'z-index: 20' e contexto
   de empilhamento: para quem esta fora, o ampliado inteiro vale 20, e o 21 da divisoria pintava a
   faixa por cima do texto. Visto em 16/09/2026, no comentario ampliado; o defeito vinha desde que a
   divisoria entrou, e valia igual para a descricao. */
.inspector-splitter:has(~ .inspector .expandable.is-expanded) {
    z-index: 19;
}

.inspector-splitter::before {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;

    /* A pegada e mais larga que a borda e centrada nela: um alvo de 1px so acerta quem tem a mao
       muito firme. */
    left: -3px;
    width: 7px;
    cursor: col-resize;
}

.inspector-splitter:hover::before,
.inspector-splitter.is-resizing::before {
    background: color-mix(in srgb, var(--accent) 35%, transparent);
}

.inspector {
    /* Trocado em 05/09/2026, quando o painel ganhou a divisoria arrastavel: o 340px virou o FALLBACK
       da variavel, que e o mesmo padrao de antes para quem nunca arrastou. A variavel e escrita pelo
       inspector-splitter.js no elemento raiz, e nao existe ate alguem arrastar.
       width: 340px; */
    width: var(--inspector-width, 340px);

    /* As duas guardas do arraste moram AQUI, e nao so no JS: o JS decide o numero durante o gesto, e
       estas duas seguram o desenho depois dele — sobretudo o teto, que muda quando a JANELA muda de
       tamanho e a largura guardada continua a mesma. O piso e metade do padrao. */
    min-width: 170px;
    max-width: 80vw;

    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border-left: 1px solid var(--border);
    overflow-y: auto;
    z-index: 20;
}

/* Com um campo AMPLIADO, o painel para de rolar. Quem rola e o proprio '.inspector', e o fundo e o
   ampliado moram DENTRO dele — e a barra de rolagem de um elemento e desenhada por cima de todo o
   conteudo dele, fundo incluido: ela continuava clicavel atras do overlay, e o painel coberto rolava.
   Visto em 16/09/2026. Sem barra nao ha o que clicar, e o 'hidden' guarda a posicao da rolagem. */
.inspector:has(.expandable.is-expanded) {
    overflow-y: hidden;
}

.inspector__header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    background: var(--surface);
    z-index: 1;
}

/* Os dois comandos do cabecalho, colados. O gap de 8px da barra vale entre o titulo e o par, e nao
   DENTRO dele: dois icones vizinhos que fazem coisas do mesmo tipo se leem como um par, e num painel
   de 340px os 8px do vao mais os 6px de recuo de cada botao saem do titulo do no. */
.inspector__header-actions {
    display: flex;
    align-items: center;
    flex: none;
}

.inspector__header-actions .btn--icon {
    padding: 7px 6px;
}

.inspector__header h2 {
    margin: 0;
    font-size: 14px;
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.inspector__body {
    padding: 14px;
}

.inspector__section {
    margin-bottom: 22px;
}

/* Os outros dois seletores NAO sao redundantes: o h3 da secao que ganhou botao de expandir passou a
   viver dentro do .inspector__section-head, e o do resumo por ramo passou a viver dentro de uma
   gaveta — nos dois casos o '>' do primeiro deixou de alcanca-lo, e o titulo voltou a ser texto
   grande e escuro, destoando do resto do painel. A armadilha ja mordeu tres vezes nesta tela; ao
   mover um <h3> de secao, confira se ele continua sendo alcancado por alguma destas linhas. */
.inspector__section > h3,
.inspector__section-head > h3,
.inspector__drawer-body > h3 {
    margin: 0 0 10px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: .03em;
}

/* Titulo da secao com um botao a direita. O h3 mantem a margem de baixo dele, entao a linha nao
   muda de altura em relacao as secoes que nao tem botao. */
.inspector__section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

/* Campo que abre em tela cheia.

   Cresce POR CLASSE, no lugar onde ja esta, em vez de ser movido para dentro de um dialogo: mover o
   editor de descricao na arvore de render destruiria o componente, e com ele o texto que so existe
   no DOM (o conteudo entra por JS, e nao pelo Blazor). Um backdrop e desenhado atras por outro
   elemento — e ele tambem faz o teclado do canvas ficar quieto, que ja era a regra para dialogo. */
.expandable.is-expanded {
    position: fixed;
    inset: 40px;
    z-index: 101;
    display: flex;
    flex-direction: column;
    padding: 12px;
    border-radius: 12px;
    background: var(--surface);
    box-shadow: var(--shadow-lg);
}

.expandable__bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 8px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: .03em;
}

.expandable.is-expanded .rich-editor {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* O teto de 320px do editor existe para ele nao empurrar o resto do painel; aqui nao ha resto. */
.expandable.is-expanded .rich-editor__content {
    flex: 1;
    max-height: none;
}

.expandable.is-expanded .field,
.expandable.is-expanded .field__with-action {
    flex: 1;
    min-height: 0;
}

.expandable.is-expanded textarea {
    height: 100%;
    max-height: none;
}

.field-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
}

/* Campo com um botao de acao encostado nele. O campo fica com toda a sobra; o botao so com o que
   o icone pede, para nao competir com o controle principal. */
.field__with-action {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
}

.field__with-action > .select,
.field__with-action > .input,
.field__with-action > .textarea {
    flex: 1;
    min-width: 0;
}

.tag-list {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin-bottom: 8px;
}

.tag {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 8px;
    border-radius: 999px;
    background: var(--surface-sunken);
    font-size: 12px;
}

.tag button {
    border: none;
    background: none;
    padding: 0;
    cursor: pointer;
    color: var(--text-muted);
    font-size: 11px;
    line-height: 1;
}

/* Editor de descricao */
.rich-editor {
    border: 1px solid var(--border-strong);
    border-radius: 6px;
    overflow: hidden;
}

.rich-editor__toolbar {
    display: flex;
    gap: 1px;
    padding: 4px;
    background: var(--surface-sunken);
    border-bottom: 1px solid var(--border);
}

.rich-editor__toolbar button {
    width: 28px;
    height: 26px;
    border: none;
    border-radius: 5px;
    background: transparent;
    cursor: pointer;
    font-size: 13px;
}

.rich-editor__toolbar button:hover {
    background: var(--surface);
}

/* Paleta da cor da fonte. No fluxo, logo abaixo da barra: dentro do painel lateral um popover
   absoluto seria recortado pelo scroll da coluna. */
.rich-editor__colors {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    padding: 6px;
    background: var(--surface-sunken);
    border-bottom: 1px solid var(--border);
}

.rich-editor__content {
    min-height: 110px;
    max-height: 320px;
    overflow-y: auto;

    /* O grip nativo do navegador, em vez de um arrastador escrito a mao: ele ja respeita o
       min-height e o max-height daqui, que sao os limites que a tarefa pediu para manter. O JS
       apenas converte o resultado em min-height e o guarda — ver bindEditorHeight no mindmap.js. */
    resize: vertical;
    padding: 9px 11px;
    outline: none;
    line-height: 1.55;

    /* Mesmo motivo do comentario: a descricao recebe caminho e URL colados. Aqui o estrago seria
       maior — o campo e EDITAVEL, e o cursor sumiria junto com o texto para fora da caixa. */
    overflow-wrap: break-word;
    word-break: break-word;
}

.rich-editor__content p {
    margin: 0 0 8px;
}

/* A imagem colada, com a borda fina que a tarefa pediu.

   SEM border-radius, e isto foi medido em 23/08/2026, a partir de "a borda parece quebrada": com
   raio, a BORDA sai arredondada e os pixels da imagem continuam quadrados — eles invadem os quatro
   cantos e a linha parece interrompida em cada um. Nao e diferenca de navegador, reproduz igual aqui,
   e 'overflow: hidden' nao corrige: overflow nao recorta conteudo substituido. Borda reta fecha em
   qualquer navegador.

   O bloco e o display certo: em linha, a imagem herdaria a linha de base do texto e ficaria com uma
   folga embaixo que ninguem consegue explicar. */
/* A borda e TRANSLUCIDA, e nao o token --border. Ela encosta na imagem, e nao no fundo do campo: uma
   linha opaca clara sobre um print escuro salta, e sobre um print claro desaparece. Com alfa ela
   escurece o que estiver embaixo, entao o contorno se le em qualquer imagem sem nunca gritar.

   Trocado em 23/08/2026 a pedido: com o --border cheio a moldura chamava mais atencao que o
   conteudo dela. */
.rich-editor__content img {
    display: block;
    max-width: 100%;
    margin: 6px 0;
    /* Subido em 23/08/2026 a pedido: a reducao anterior passou do ponto e o contorno quase sumiu
       sobre print claro. O caminho foi .12 -> .06 -> .11, que e a metade de baixo com os 80% que o
       pedido sugeria: escurece o suficiente para fechar a imagem e ainda fica abaixo do .12 que
       chamava atencao antes do conteudo.
       border: 1px solid rgba(15, 23, 42, .06); */
    border: 1px solid rgba(15, 23, 42, .11);
}

/* Ela e clicavel: o clique seleciona a imagem inteira, para o Delete apaga-la. A borda um pouco mais
   escura no hover e o que anuncia isso — sem nenhum sinal, "da para clicar" e adivinhacao. */
.rich-editor__content img:hover {
    /* Sobe junto com a borda de repouso, para o hover continuar sendo um degrau visivel e nao um
       salto: o contraste entre os dois estados e o que anuncia o clique.
       border-color: rgba(15, 23, 42, .16); */
    border-color: rgba(15, 23, 42, .26);
}

/* Imagem que NAO carregou: o arquivo foi expurgado, o storage caiu, ou a chave esta errada.

   A classe vem do JS, por um ouvinte de 'error' — ver bindBrokenImages. A tentativa anterior era um
   ::after com a mensagem dentro, contando com pseudo-elemento nao ser pintado sobre imagem que
   CARREGA. Isso nao e garantido: e comportamento que varia por navegador, e onde ele for pintado a
   moldura tracejada aparece por cima de uma imagem boa. Marcar o estado de fora nao depende de nada.

   A mensagem e o proprio texto do alt, que o navegador ja desenha dentro da caixa quebrada. */
.rich-editor__content img.is-broken {
    min-width: 200px;
    min-height: 52px;
    padding: 8px;
    border-style: dashed;
    border-color: var(--border-strong);
    background: var(--surface-muted);
    color: var(--text-muted);
    font-size: 12px;
}

.rich-editor__content:focus {
    background: #fefefe;
}

/* Comentarios */
.comment {
    padding: 9px 11px;
    margin-bottom: 8px;
    border-radius: 8px;
    background: var(--surface-sunken);
}

.comment__head {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 4px;
}

.comment__author {
    font-weight: 600;
    font-size: 12px;
}

.comment__time {
    font-size: 11px;
    color: var(--text-muted);
    margin-right: auto;
}

.comment__body {
    font-size: 13px;
    line-height: 1.5;

    /* Comentario e onde se cola caminho de rede, URL e id — texto longo SEM espaco, que nao tem
       onde quebrar. Sem isto a linha estoura o painel e o fim dela fica escondido: nao ha barra de
       rolagem horizontal para ir busca-lo, entao o que sobra e um comentario pela metade. */
    overflow-wrap: break-word;
    word-break: break-word;

    /* Teto de altura, desde 16/09/2026: um comentario com um documento colado ficava infinito,
       empurrava o painel ate o fim e escondia o campo de escrever. Passando do teto, ele rola por
       dentro, e o link "Ampliar" aparece. */
    max-height: 240px;
    overflow-y: auto;
}

.comment__body p {
    margin: 0 0 6px;
}

/* Edicao do comentario, desde 16/09/2026. */
.comment__edited {
    margin-left: 4px;
    font-style: italic;
}

.comment.is-editing .rich-editor {
    margin-top: 4px;
}

.comment__edit-actions {
    display: flex;
    gap: 6px;
    margin-top: 6px;
}

.comment__edit-error {
    margin: 4px 0 0;
    font-size: 12px;
    color: var(--danger);
}

/* Removido em 19/09/2026: o selo amarelo "Expira em N dias" do mapa temporario, que virou o tipo
   Backlog e nao expira mais.
.map-card__badge.map-card__badge--warning {
    border-color: #fcd34d;
    background: #fffbeb;
    color: #92400e;
}
*/

/* Trocado em 16/09/2026: o Ampliar era um link embaixo do corpo, e subiu para o grupo de botoes do
   cabecalho, ao lado do lapis, a pedido do usuario.
.comment__zoom {
    display: none;
    align-items: center;
    gap: 4px;
    margin-top: 4px;
    padding: 0;
    border: 0;
    background: none;
    font-size: 12px;
    color: var(--accent);
    cursor: pointer;
}

.comment__zoom:hover {
    text-decoration: underline;
} */

/* Os botoes do cabecalho num grupo so, com vao curto e botao compacto: com o respiro padrao do
   .btn--icon mais o vao do cabecalho, o lapis ficava longe do X. */
.comment__actions {
    display: inline-flex;
    align-items: center;
    gap: 0;
}

.comment__actions .btn--icon {
    padding: 3px 5px;
}

/* Escondido ate o navegador marcar o comentario como estourado — ver bindOverflowFlag. */
.comment__zoom {
    display: none;
}

.comment[data-overflowing] .comment__zoom {
    display: inline-flex;
}

/* O comentario em tela cheia: sem teto, e com letra um pouco maior, que e o motivo de ampliar. */
.expandable.is-expanded .comment__body--expanded {
    flex: 1;
    min-height: 0;
    max-height: none;
    overflow-y: auto;
    font-size: 14px;
}

.expandable.is-expanded:focus {
    outline: none;
}

/* Estimativa */
.toolbar-group--rate {
    display: flex;
    align-items: center;
    gap: 5px;
}

.toolbar-group--rate > label {
    font-size: 12px;
    color: var(--text-muted);
    white-space: nowrap;
}

.input--rate {
    width: 78px;
    padding: 5px 7px;
    font-size: 13px;
    font-variant-numeric: tabular-nums;
}

/* Filtro da barra: estreito o bastante para nao roubar espaco do titulo do mapa.

   Acrescentado em 19/08/2026 o min-width, e ele e o ponto: em flexbox o piso de um item e o tamanho
   MINIMO do conteudo, e um input declara esse piso como a propria largura. Sem isto o filtro era o
   unico elemento rigido do topo — o titulo encolhia ate zero, a barra de comandos recolhia tudo, e
   quando os dois se esgotavam era a linha inteira que transbordava, com o filtro passando por cima
   da borda. Agora ele cede junto, ate um piso em que ainda da para ler o que se digitou. */
.input--filter {
    width: 190px;
    min-width: 92px;
    flex: 0 1 auto;
    padding: 5px 8px;
    font-size: 13px;
}

/* Seletor de visão.

   Trocado em 21/08/2026 de <select> nativo para botao com menu proprio. O select encolhia ate
   truncar o nome da visão, e nao ha como esconder so o ROTULO de um select — ou ele cabe, ou ele
   corta no meio da palavra.
.input--view {
    width: 150px;
    min-width: 96px;
    flex: 0 1 auto;
    padding: 5px 8px;
    font-size: 13px;
}
*/

.toolbar-group--view {
    position: relative;
    align-items: center;
    min-width: 0;
    flex: 0 0 auto;
}

.view-picker {
    display: flex;
    align-items: center;
    gap: 6px;
    max-width: 220px;
    font-size: 13px;
}

.view-picker__label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* O contador nao encolhe nunca: em tela estreita ele e o que resta do controle, e o que impede o
   mapa recortado de ser lido como mapa perdido. */
.view-picker__count {
    flex: 0 0 auto;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--bg-accent, rgba(37, 99, 235, .12));
    color: var(--accent);
    font-size: 11px;
    font-variant-numeric: tabular-nums;
}

.view-picker__count--broken {
    background: rgba(217, 119, 6, .14);
    color: #b45309;
}

.view-picker__caret {
    flex: 0 0 auto;
    font-size: 10px;
    opacity: .55;
}

.view-menu {
    display: none;
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    z-index: 41;
    min-width: 200px;
    padding: 4px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
    box-shadow: var(--shadow-md);
}

.view-menu.is-open {
    display: block;
}

.view-menu > button {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 7px 10px;
    border: 0;
    border-radius: 6px;
    background: none;
    color: var(--text);
    font: inherit;
    font-size: 13px;
    text-align: left;
    cursor: pointer;
}

.view-menu > button:hover {
    background: var(--surface-2, rgba(15, 23, 42, .06));
}

.view-menu > button.is-current {
    color: var(--accent);
    font-weight: 600;
}

/* ---------------------------------------------------------------------------------------
   Alternador de mapas — o segmento do NOME na trilha do editor
   --------------------------------------------------------------------------------------- */

/* A ancora do menu e ESTE elemento, e nao a barra.

   Sem o position aqui o absolute subiria ate a .editor__topbar, que tem position: relative para a
   faixa do filtro — e o menu abriria colado na borda esquerda da barra, longe do nome que o abriu.
   E a mesma armadilha de ancoragem ja paga nos popovers da barra do no. */
.map-switcher {
    position: relative;

    /* Herda do .editor__title o papel de empurrar os comandos para a direita e de ser o primeiro a
       encolher: quem carrega essas regras agora e o grupo, e nao mais o texto. */
    margin-right: auto;
    flex: 0 8 auto;
    min-width: 0;
}

/* O titulo continua sendo titulo: mesma fonte e mesmas reticencias de quando era um span. So o
   cursor e o chevron dizem que ali se clica. */
.map-switcher__button {
    display: flex;
    align-items: center;
    gap: 6px;
    max-width: 100%;
    margin: 0;
    padding: 3px 6px;
    border: 0;
    border-radius: 6px;
    background: none;
    color: inherit;
    font: inherit;
    font-weight: 600;
    font-size: 15px;
    cursor: pointer;
}

.map-switcher__button:hover {
    background: var(--surface-2, rgba(15, 23, 42, .06));
}

.map-switcher__label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.map-switcher__caret {
    flex: 0 0 auto;
    font-size: 10px;
    opacity: .55;
}

.map-switcher__menu {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    z-index: 41;
    width: 320px;
    max-width: 78vw;
    padding: 8px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
    box-shadow: var(--shadow-md);
}

.map-switcher__menu > .input {
    width: 100%;
    margin-bottom: 6px;
}

/* A rolagem vive na LISTA, e nao no menu: o campo de busca tem que ficar parado enquanto se rola,
   senao filtrar exige rolar de volta para cima para corrigir o termo. */
.map-switcher__list {
    max-height: 320px;
    overflow-y: auto;
}

.map-switcher__list > button {
    display: flex;
    flex-direction: column;
    gap: 1px;
    width: 100%;
    padding: 7px 10px;
    border: 0;
    border-radius: 6px;
    background: none;
    color: var(--text);
    font: inherit;
    font-size: 13px;
    text-align: left;
    cursor: pointer;
}

.map-switcher__list > button:hover {
    background: var(--surface-2, rgba(15, 23, 42, .06));
}

.map-switcher__list > button.is-current {
    color: var(--accent);
    font-weight: 600;
}

/* O nome ganha reticencias, e a segunda linha tambem: mapa de cliente costuma ter titulo longo, e
   um item que se estica arrastaria o menu inteiro para fora da tela. */
.map-switcher__name,
.map-switcher__meta {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.map-switcher__meta {
    color: var(--text-muted);
    font-size: 11px;
    font-weight: 400;
}

.map-switcher__empty {
    margin: 0;
    padding: 10px;
    color: var(--text-muted);
    font-size: 12px;
}

/* Cortina dos menus da barra. Invisivel de proposito: ela existe para ENGOLIR o clique, e nao para
   escurecer a tela — o menu de uma barra nao e modal. */
.popover-backdrop {
    position: fixed;
    inset: 0;
    z-index: 40;
}

/* O ponto no botao da lupa: filtro em vigor com a caixa fechada esmaece o mapa, e sem sinal na
   barra isso parece defeito. */
.filter-toggle {
    position: relative;
}

.filter-toggle__dot {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--accent);
}

.filter-fields {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
}

/* Em tela larga a lupa que abre nao existe: a caixa ja esta aberta, e um botao para abrir o que
   esta aberto so confunde. */
.filter-toggle {
    display: none;
}

/* ---------------------------------------------------------------------------------------
   Tela estreita: a barra guarda o rotulo da visão e a caixa do filtro
   ---------------------------------------------------------------------------------------

   O corte e em 1024px porque abaixo disso a barra ja disputa espaco entre trilha, titulo, visão,
   filtro e comandos — e o primeiro a quebrar era sempre o texto de um controle, que corta no meio
   da palavra em vez de sumir inteiro. Aqui o que sai e escolhido: some o ROTULO, ficam o icone e o
   contador; some a CAIXA do filtro, fica a lupa com o ponto de "filtro em vigor". */
@media (max-width: 1024px) {
    .view-picker__label,
    .view-picker__caret {
        display: none;
    }

    .filter-toggle {
        display: inline-flex;
    }

    .toolbar-group--filter .filter-fields {
        display: none;
    }

    /* O grupo do filtro e 'relative' para ancorar a AJUDA nele. Aberta a caixa, ele volta a ser
       static: sem isto a faixa se ancorava no proprio grupo — largura de um botao — e nascia como
       uma caixinha espremida no canto, em vez da faixa de ponta a ponta. */
    .toolbar-group--filter.is-expanded {
        position: static;
    }

    /* Aberta, a caixa ocupa uma faixa propria logo abaixo da barra. Espremer os seis controles do
       filtro na linha do topo seria repetir o problema que este bloco existe para resolver. */
    .toolbar-group--filter.is-expanded .filter-fields {
        display: flex;
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        z-index: 41;
        padding: 8px 14px;
        background: var(--surface);
        border-bottom: 1px solid var(--border);
        box-shadow: var(--shadow-md);
    }

    .toolbar-group--filter .input--filter {
        flex: 1 1 auto;
        width: auto;
    }
}

/* A caixa do filtro do mapa, desde 19/09/2026: o '.map-search' da lista, na altura da barra do
   editor. O input herda do '.map-search .input' a falta de borda, e daqui a largura que cede. */
.filter-box {
    height: 32px;
    gap: 4px;
    padding: 0 6px 0 10px;
    min-width: 0;
}

.filter-box .input.input--filter {
    width: 190px;
    min-width: 92px;
    max-width: none;
    flex: 0 1 auto;
    padding: 0;
    font-size: 13px;
}

.filter-box .btn--icon {
    font-size: 13px;
}

@media (max-width: 1024px) {
    .toolbar-group--filter.is-expanded .filter-box {
        flex: 1 1 auto;
    }

    .toolbar-group--filter.is-expanded .filter-box .input.input--filter {
        flex: 1 1 auto;
        width: auto;
    }
}

/* A ajuda e ancorada neste grupo, e nao na pagina. */
.toolbar-group--filter {
    position: relative;
    align-items: center;
    min-width: 0;
}

.filter-count {
    align-self: center;
    padding-left: 4px;
    font-size: 12px;
    color: var(--text-muted);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* Zero resultados nao e erro, mas e o caso em que a tela inteira esmaece: o vermelho evita que a
   pessoa procure defeito onde so faltou resultado. */
.filter-count--empty {
    color: var(--danger);
}

.filter-help {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 40;
    width: 420px;
    max-height: 60vh;
    overflow-y: auto;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow-lg);
    font-size: 12px;
}

.filter-help dl {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 3px 12px;
    margin: 0;
}

.filter-help dt {
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    color: var(--accent);
    white-space: nowrap;
}

/* Botao que herda a aparencia do <dt> que ele substituiu: o exemplo continua parecendo codigo, e nao
   um controle a mais competindo com o texto ao lado. O affordance aparece no hover. */
.filter-help__example {
    padding: 0;
    border: none;
    background: none;
    font: inherit;
    color: inherit;
    cursor: pointer;
    text-align: left;
}

.filter-help__example:hover,
.filter-help__example:focus-visible {
    text-decoration: underline;
}

.filter-help dd {
    margin: 0;
    color: var(--text-muted);
}

.filter-help p {
    margin: 10px 0 0;
    color: var(--text-muted);
}

/* Alinha o valor lido com a altura do campo ao lado, para a linha nao ficar torta. */
.readout {
    display: flex;
    align-items: center;
    min-height: 34px;
    font-size: 13px;
    font-variant-numeric: tabular-nums;
}

.readout--muted {
    color: var(--text-muted);
    font-style: italic;
}

/* Explica por que o campo esta travado, em vez de deixar o usuario procurar onde editar. */
.readout__hint {
    margin-left: 6px;
    font-size: 10px;
    color: var(--text-muted);
    white-space: nowrap;
}

/* O valor-hora e o unico campo do painel com botao proprio: ele so grava no clique. O botao fica
   na mesma linha do campo para que a relacao entre os dois seja obvia sem ler o texto de apoio. */
.rate-field {
    display: flex;
    gap: 6px;
    align-items: center;
}

.rate-field > .input {
    flex: 1;
    min-width: 0;
}

/* Nota abaixo de um campo, para a regra que o campo sozinho nao consegue afirmar — o valor-hora
   em branco cair no padrao da instalacao, por exemplo. */
.field__hint {
    margin: 4px 0 0;
    font-size: 11px;
    line-height: 1.4;
    color: var(--text-muted);
}

.estimate-total {
    margin-top: 10px;
    padding: 9px 11px;
    border-radius: 8px;
    background: var(--surface-sunken);
}

.estimate-total__row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    font-size: 13px;
}

.estimate-total__row strong {
    font-size: 15px;
    font-variant-numeric: tabular-nums;
}

.estimate-total__meta {
    margin-top: 3px;
    font-size: 11px;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

/* Virou botao em 16/08/2026 (ver o InspectorPanel): o reset existe para ele continuar parecendo o
   texto que sempre foi, e nao um botao a mais dentro do bloco de total. */
.estimate-total__pending {
    padding: 0;
    border: none;
    background: none;
    font: inherit;
    color: var(--danger);
    cursor: pointer;
}

.estimate-total__pending:hover {
    text-decoration: underline;
}

.estimate-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
}

.estimate-table td {
    padding: 5px 4px;
    border-bottom: 1px solid var(--border);
}

.estimate-table tfoot td {
    border-bottom: none;
    border-top: 2px solid var(--border-strong);
    font-weight: 600;
    padding-top: 7px;
}

.estimate-table__name {
    /* O nome cede espaco: os numeros a direita nao podem quebrar linha. */
    word-break: break-word;
}

.estimate-table__hours,
.estimate-table__value {
    text-align: right;
    white-space: nowrap;
}

/* O nome do ramo e um botao, mas nao deve parecer um: dentro de uma tabela de numeros um botao
   desenhado tira a atencao da coluna que importa. Fica como link, e so o sublinhado no hover diz
   que ele responde. */
.estimate-table__link {
    padding: 0;
    border: none;
    background: none;
    font-family: inherit;
    font-size: inherit;
    color: inherit;
    text-align: left;
    word-break: break-word;
    cursor: pointer;
}

.estimate-table__link:hover {
    text-decoration: underline;
}

.estimate-table__pending {
    margin-left: 3px;
    color: var(--danger);
}

.estimate-note {
    display: flex;
    align-items: baseline;
    gap: 5px;
    margin: 8px 0 0;
    font-size: 11px;
    color: var(--text-muted);
}

/* O aviso de pendencia e um botao, mas continua com cara de aviso: destacar como botao competiria
   com o "Aplicar" do valor-hora, que e a unica acao de peso desta area do painel. */
.estimate-note--toggle {
    width: 100%;
    padding: 0;
    border: none;
    background: none;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
}

.estimate-note--toggle:hover {
    color: var(--text);
}

.estimate-note__text {
    /* Empurra o chevron para a direita sem prender a largura do texto. */
    flex: 1;
}

.gap-list {
    margin: 6px 0 0;
    padding: 0;
    list-style: none;
    /* A lista pode ser longa: num mapa com dezenas de pendencias ela empurraria o resto do painel
       para fora da tela. Rolar aqui dentro mantem o resumo e o valor-hora ao alcance. */
    max-height: 220px;
    overflow-y: auto;
    border: 1px solid var(--border);
    border-radius: 7px;
}

.gap-list__item {
    display: block;
    width: 100%;
    padding: 5px 8px;
    border: none;
    border-bottom: 1px solid var(--border);
    background: none;
    font-family: inherit;
    font-size: 12px;
    color: var(--text);
    text-align: left;
    cursor: pointer;
}

.gap-list li:last-child .gap-list__item {
    border-bottom: none;
}

.gap-list__item:hover {
    background: var(--surface-sunken);
}

.gap-list__title {
    display: block;
    word-break: break-word;
}

.gap-list__path {
    display: block;
    font-size: 10px;
    color: var(--text-muted);
    word-break: break-word;
}

/* Cockpit de IA */
.cockpit {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
}

.cockpit th {
    padding: 6px 8px;
    border-bottom: 2px solid var(--border-strong);
    text-align: left;
    font-weight: 600;
    color: var(--text-muted);
}

.cockpit td {
    padding: 8px;
    border-bottom: 1px solid var(--border);
    vertical-align: top;
}

/* A linha que espera uma PESSOA se destaca das outras: numa tela deixada aberta, o que importa e
   achar de longe o que precisa de resposta. Uma borda lateral, e nao um fundo colorido — fundo na
   linha inteira competiria com a leitura do texto que esta dentro dela. */
.cockpit--asking td:first-child {
    border-left: 3px solid var(--warning, #d97706);
    padding-left: 6px;
}

/* A linha que mudou desde a ultima olhada. Uma etiqueta ao lado do nome, e nao fundo colorido, pelo
   mesmo motivo do "esperando voce" logo acima: o fundo brigaria com a leitura do texto da linha —
   e aqui brigaria tambem com a borda do asking, que pode estar na mesma linha. */
.cockpit--unread td:first-child a {
    font-weight: 600;
}

.cockpit__unread {
    margin-left: 6px;
    padding: 0 6px;
    border: 0;
    border-radius: 9px;
    background: var(--accent, #2563eb);
    color: #fff;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    cursor: pointer;
    vertical-align: middle;
}

.cockpit__status {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-muted);
}

/* O MESMO laranja do emblema de "em andamento" no mapa — ver RequirementLabels.IconColor. As duas
   telas ficam abertas lado a lado, e trabalho acontecendo tem que ter uma cor so nas duas. */
.cockpit__status--working {
    color: var(--running);
}

.cockpit__status--asking {
    color: var(--warning, #d97706);
}

.cockpit__status--finished {
    color: var(--success, #16a34a);
}

.cockpit__message {
    margin-top: 2px;
    word-break: break-word;
}

.cockpit__user {
    color: var(--text-muted);
    word-break: break-word;
}

.cockpit__when {
    white-space: nowrap;
    color: var(--text-muted);
}

.cockpit__none {
    color: var(--text-muted);
}

/* O contador no item do menu */
.drawer__badge {
    margin-left: auto;
    padding: 0 6px;
    border-radius: 9px;
    background: var(--warning, #d97706);
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* Log de alteracoes */

/* Removido em 05/09/2026: o cabecalho proprio do log de alteracoes. Ele existia porque a secao era a
   unica do painel que abria por botao, e nao por <details> — e a secao passou a ser a mesma gaveta
   das outras. Com o <summary> no lugar, a area de clique cobrindo a linha inteira e a seta que gira
   vem do .inspector__summary, e nao ha mais o que alinhar aqui.

   .changelog__head { display: flex; align-items: center; gap: 6px; }
   .changelog__head .changelog__toggle { flex: 1; min-width: 0; }
   .changelog__toggle { display: flex; align-items: center; width: 100%; padding: 0; border: none;
                        background: none; color: var(--text); text-align: left; cursor: pointer; }
   .changelog__toggle h3 { margin: 0; }
   .changelog__chevron { flex: none; padding: 2px 0 2px 2px; border: none; background: none;
                         color: var(--text); cursor: pointer; } */

/* O refresh desceu para dentro do corpo da gaveta, e vai encostado a direita: ele age sobre a lista
   logo abaixo, e a lista comeca na esquerda. */
.changelog__tools {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 4px;
}

.changelog__refresh {
    flex: none;
    padding: 2px 5px;
    border: none;
    border-radius: 6px;
    background: none;
    color: var(--text-muted);
    cursor: pointer;
}

.changelog__refresh:hover:not(:disabled) {
    background: var(--surface-sunken);
    color: var(--text);
}

.changelog__refresh:disabled {
    cursor: default;
    opacity: 0.5;
}

.changelog {
    margin: 8px 0 0;
    padding: 0;
    list-style: none;
    border: 1px solid var(--border);
    border-radius: 7px;
}

.changelog__item {
    padding: 6px 8px;
    border-bottom: 1px solid var(--border);
}

.changelog__item:last-child {
    border-bottom: none;
}

.changelog__line {
    display: flex;
    align-items: baseline;
    gap: 6px;
}

.changelog__icon {
    flex: none;
    font-size: 11px;
    color: var(--text-muted);
}

/* O min-width: 0 nao e enfeite. Item de flex nasce com min-width: auto, ou seja, ele se recusa a
   ficar menor que o proprio conteudo — e o texto do log e nowrap para truncar em uma linha. Sem
   isto a linha estica ate o comprimento da descricao inteira: o painel de 324px passou a rolar ate
   1548px, empurrando o conteudo para fora da tela. Nao aparece em build nem em teste. */
.changelog__what {
    min-width: 0;
    font-size: 12px;
    word-break: break-word;
}

/* Cada campo alterado numa linha propria: dois ou tres campos numa alteracao so, corridos, viram
   uma frase que nao se le. */
.changelog__field {
    display: block;
}

.changelog__field-name {
    font-weight: 600;
}

.changelog__field-name::after {
    content: ":";
}

.changelog__field-from {
    color: var(--text-muted);
    text-decoration: line-through;
}

.changelog__arrow {
    margin: 0 3px;
    color: var(--text-muted);
}

.changelog__field-name + .changelog__field-from {
    margin-left: 3px;
}

/* Texto longo: o antes e o depois empilhados, cada um com o proprio rotulo. Lado a lado com uma
   seta no meio, dois paragrafos nao se leem. */
.changelog__block {
    display: block;
    margin: 2px 0 0 8px;
}

.changelog__block-label {
    display: block;
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}

/* Corta em UMA linha: uma descricao de requisito inteira dentro do painel empurraria para fora as
   outras alteracoes do historico. Clicar abre o texto por inteiro — e por isso e um button, e nao
   um span: precisa chegar pelo teclado e parecer clicavel. */
.changelog__text {
    display: block;
    width: 100%;
    padding: 0;
    border: none;
    background: none;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;

    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.changelog__text:hover {
    text-decoration: underline;
}

/* Aberto: o texto inteiro, quebrando linha. A palavra sem espaco — um link colado, por exemplo —
   quebra no meio em vez de esticar a linha e criar rolagem horizontal no painel. */
.changelog__text--open {
    white-space: normal;
    overflow: visible;
    word-break: break-word;
}

.changelog__text--old {
    color: var(--text-muted);
}

.changelog__context {
    margin-left: 17px;
    font-size: 10px;
    font-style: italic;
    color: var(--text-muted);
}

.changelog__where {
    /* Alinha com o texto, e nao com o icone: o recuo e a largura do icone mais o gap. */
    margin-left: 17px;
    font-size: 11px;
    color: var(--text-muted);
    word-break: break-word;
}

.changelog__more {
    margin-left: 4px;
    font-style: italic;
}

.changelog__who {
    margin-left: 17px;
    font-size: 10px;
    color: var(--text-muted);
}

.changelog__empty {
    margin: 8px 0 0;
    font-size: 12px;
    color: var(--text-muted);
}

.changelog__pager {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-top: 6px;
}

.changelog__page {
    padding: 2px 7px;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: none;
    color: var(--text);
    cursor: pointer;
}

.changelog__page:disabled {
    color: var(--text-muted);
    cursor: default;
}

.changelog__count {
    font-size: 11px;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

/* Add-ons do no */
.addon {
    margin-bottom: 10px;
    border: 1px solid var(--border);
    border-radius: 7px;
    overflow: hidden;
}

.addon__head {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 6px 6px 6px 10px;
    background: var(--surface-sunken);
    font-size: 12px;
    font-weight: 600;
}

.addon__name {
    margin-right: auto;
}

.addon__body {
    padding: 9px 10px;
}

.addon__unknown {
    margin: 0;
    font-size: 12px;
    color: var(--text-muted);
}

.addon-catalog {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.addon-catalog__item {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 2px 8px;
    padding: 8px 10px;
    text-align: left;
    cursor: pointer;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 7px;
}

.addon-catalog__item:hover {
    border-color: var(--accent);
    background: var(--accent-soft);
}

.addon-catalog__item > i {
    grid-row: span 2;
    align-self: center;
    font-size: 16px;
    color: var(--accent);
}

.addon-catalog__name {
    font-size: 13px;
    font-weight: 600;
}

.addon-catalog__desc {
    font-size: 12px;
    color: var(--text-muted);
}

/* Checklist */
.checklist__progress {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 9px;
}

.checklist__bar {
    flex: 1;
    height: 5px;
    border-radius: 999px;
    background: var(--surface-sunken);
    overflow: hidden;
}

.checklist__bar > span {
    display: block;
    height: 100%;
    background: var(--accent);
    transition: width .15s ease;
}

.checklist__count {
    font-size: 11px;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.checklist__item {
    display: flex;

    /* Trocado em 15/08/2026: o texto virou campo de varias linhas, e 'center' punha a caixa de
       marcar no meio do paragrafo. A caixa pertence a PRIMEIRA linha.
       align-items: center; */
    align-items: flex-start;
    gap: 7px;
    margin-bottom: 3px;
}

/* Alinha com a primeira linha do texto: 1px de borda + 3px de padding + meia linha. Nada de
   'baseline' — a de um textarea difere entre Chrome e Firefox. */
.checklist__item > input[type="checkbox"] {
    flex: none;
    margin-top: 5px;
}

.checklist__item > .btn--icon {
    flex: none;
    align-self: flex-start;
}

.checklist__text {
    flex: 1;
    min-width: 0;

    /* Sem 'block' o textarea, que e inline-block, deixa um vao de baseline embaixo. */
    display: block;
    box-sizing: border-box;
    padding: 3px 5px;
    font: inherit;
    font-size: 13px;

    /* Depois do 'font: inherit', que reseta o line-height — e as contas de altura dependem dele. */
    line-height: 1.35;
    color: inherit;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 5px;

    /* A alca de redimensionar brigaria com a altura calculada pelo autogrow. */
    resize: none;
    overflow-x: hidden;
    overflow-y: auto;

    /* Uma linha, para o campo ficar decente mesmo se o JS nao rodar; teto de ~6 linhas, a partir do
       qual o proprio campo rola em vez de empurrar a lista inteira para fora da tela. */
    min-height: calc(1.35em + 8px);
    max-height: calc(6 * 1.35em + 8px);
}

.checklist__text:hover {
    border-color: var(--border);
}

.checklist__text:focus {
    outline: none;
    background: var(--surface);
    border-color: var(--accent);
}

/* O texto riscado marca o item concluido sem precisar procurar a caixa marcada. */
.checklist__item.is-done .checklist__text {
    color: var(--text-muted);
    text-decoration: line-through;
}

.checklist__new {
    margin-top: 7px;
}

/* Anexos */
.attachment {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 9px;
    margin-bottom: 6px;
    border: 1px solid var(--border);
    border-radius: 7px;
    font-size: 13px;
}

.attachment__name {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.attachment__size {
    font-size: 11px;
    color: var(--text-muted);
}

.attachment-thumb {
    max-width: 100%;
    border-radius: 6px;
    margin-bottom: 6px;
    display: block;
}

/* Zona de arrastar arquivos.

   O <InputFile> fica POR CIMA dela, esticado e invisivel: soltar um arquivo sobre um input de
   arquivo e um gesto que o proprio navegador entende, e ele preenche o input e dispara o change que
   o Blazor ja escuta. Assim o arrastar e o clicar sao o MESMO caminho de codigo — e nao existe
   interop de JS para manter em pe. */
.dropzone {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: 14px 10px;
    border: 1px dashed var(--border);
    border-radius: 8px;
    color: var(--text-muted);
    font-size: 12px;
    text-align: center;
    transition: border-color .12s, background-color .12s;
}

.dropzone i {
    font-size: 18px;
}

.dropzone input[type="file"] {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

.dropzone.is-over {
    border-color: var(--accent);
    background: var(--accent-soft);
    color: var(--accent);
}

/* Somente leitura: sem input por cima, a zona vira so um aviso. */
.inspector.is-readonly .dropzone {
    display: none;
}

.upload-progress {
    margin-top: 8px;
    font-size: 12px;
    color: var(--text-muted);
}

.upload-progress__bar {
    height: 6px;
    margin-top: 4px;
    border-radius: 999px;
    background: var(--border);
    overflow: hidden;
}

.upload-progress__fill {
    height: 100%;
    background: var(--accent);
    border-radius: 999px;
    transition: width .1s linear;
}

/* ---------------------------------------------------------------------------------------
   Rodape de zoom
   --------------------------------------------------------------------------------------- */

.zoom-bar {
    position: absolute;
    right: 18px;
    bottom: 18px;
    display: flex;
    align-items: center;
    gap: 3px;
    padding: 5px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface);
    box-shadow: var(--shadow-md);
    z-index: 15;
}

.zoom-bar button {
    width: 28px;
    height: 28px;
    border: none;
    border-radius: 50%;
    background: transparent;
    cursor: pointer;
}

.zoom-bar button:hover {
    background: var(--surface-sunken);
}

/* O interruptor do aviso, primeiro item da barra.

   Ligado ele acende no acento, e nao apenas troca o glifo: icone sozinho nao diz se esta ativo, e
   olho aberto contra olho riscado e distincao de forma fina demais para um botao de 28px. */
.zoom-bar__hints.is-on {
    color: var(--accent);
}

/* Separa o que e LENTE do que e CAMERA. Sem ele os quatro botoes se leem como uma coisa so, e o
   primeiro pareceria mais um controle de zoom. */
.zoom-bar__divider {
    width: 1px;
    height: 18px;
    margin: 0 2px;
    background: var(--border);
}

/* Mesmo recado do .zoom-bar__hints, na barra do modo lista. */
.tree-bar__hints.is-on {
    color: var(--accent);
}

.zoom-bar__value {
    min-width: 46px;
    text-align: center;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
    color: var(--text-muted);
}

/* ---------------------------------------------------------------------------------------
   Modal
   --------------------------------------------------------------------------------------- */

.modal-backdrop {
    position: fixed;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(15, 23, 42, .45);
    z-index: 100;
}

.modal {
    width: min(540px, calc(100vw - 40px));
    max-height: calc(100vh - 80px);
    display: flex;
    flex-direction: column;
    border-radius: 12px;
    background: var(--surface);
    box-shadow: var(--shadow-lg);
}

.modal__header {
    padding: 16px 18px;
    border-bottom: 1px solid var(--border);
}

.modal__header h2 {
    margin: 0;
    font-size: 16px;
}

.modal__body {
    padding: 18px;
    overflow-y: auto;

    /* Conteudo largo se resolve quebrando, e nao empurrando o dialogo para o lado. */
    overflow-x: hidden;
}

.modal__footer {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    padding: 14px 18px;
    border-top: 1px solid var(--border);
}

/* ---------------------------------------------------------------------------------------
   Sobreposicao de imagem ampliada

   Aberta pelo duplo clique numa imagem da descricao. A cortina e um '.modal-backdrop' de verdade,
   e nao um parecido: o page-scroll.js trava a rolagem da pagina por esse seletor, e o canvas cala o
   proprio teclado por ele. Aqui ela so fica mais escura, porque o que esta por cima e uma imagem e
   nao um dialogo com fundo proprio.
   --------------------------------------------------------------------------------------- */

.image-viewer {
    background: rgba(15, 23, 42, .82);

    /* A imagem transformada passa da area da cortina em qualquer zoom acima do enquadramento; sem
       isto ela devolveria barras de rolagem a uma tela que nao rola. */
    overflow: hidden;

    /* O arraste move a imagem, e nao a selecao de texto do navegador: sem isto o ponteiro pinta o
       azul nativo por cima dela no meio do gesto. Mesma regra que o canvas do mapa ja usa. */
    user-select: none;
}

.image-viewer__image {
    /* O tamanho e o NATURAL, e o enquadramento inicial e uma escala aplicada por cima dele. Limitar
       por max-width aqui brigaria com o transform: a conta do zoom passaria a partir de um tamanho
       que depende da viewport, e o "1x" deixaria de querer dizer tamanho real.

       POSICAO ABSOLUTA, e a centralizacao vem do JS. O caminho obvio — deixar o flex do
       '.modal-backdrop' centralizar — foi medido e NAO funciona: o transform nao muda a caixa de
       LAYOUT, entao o flex continua distribuindo um item de 2400px dentro de 922px. Item maior que o
       container estoura para os dois lados e o 'justify-content: center' deixa de centralizar o que
       se ve; a imagem abria em left: -725px, quando o certo era 48px. Com left/top calculados sobre
       as medidas naturais, a conta e exata e nao depende do tamanho do container. */
    position: absolute;
    display: block;
    transform-origin: center center;
    cursor: grab;

    /* NAO ha transition no transform. Roda e arraste emitem dezenas de transformacoes por segundo, e
       cada uma reiniciaria a interpolacao da anterior — a imagem passaria a boiar atras do cursor.
       E a mesma armadilha ja paga no canvas do mapa. */
}

.image-viewer.is-dragging .image-viewer__image {
    cursor: grabbing;
}

/* Dois seletores, e nao um: o '.btn--icon' redeclara 'position: relative' mais abaixo neste arquivo,
   e com a mesma especificidade de '.image-viewer__close' quem vem depois vence. O botao ficava
   RELATIVO, e ai 'top' e 'right' viravam deslocamento a partir da posicao estatica — que num
   container flex centralizado e o meio da tela. O X abria no centro da imagem. */
.image-viewer .image-viewer__close {
    position: absolute;
    top: 16px;
    right: 16px;
    color: #fff;
    background: rgba(15, 23, 42, .5);
}

.image-viewer .image-viewer__close:hover {
    background: rgba(15, 23, 42, .75);
}

/* Menu de contexto da imagem ampliada.

   Posicionado no ponteiro pelo JS, que e quem sabe onde o clique caiu. Fica fora do fluxo do flex da
   cortina, como o botao de fechar, e pelo mesmo motivo. */
.image-viewer__menu {
    position: absolute;
    z-index: 1;
    min-width: 150px;
    padding: 4px;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--surface);
    box-shadow: var(--shadow-lg);
}

.image-viewer__menu button {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 7px 10px;
    border: 0;
    border-radius: 6px;
    background: transparent;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
}

.image-viewer__menu button:hover {
    background: var(--surface-sunken);
}

/* Aviso curto de resultado.
   Dentro de um dialogo ele fica FORA do corpo rolavel, logo acima do rodape — e o unico lugar em que
   se ve o resultado de um botao do rodape sem depender de onde o corpo esta rolado. No topo do corpo,
   como estava, a mensagem saia de visão exatamente para quem acabou de clicar. */
.notice {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 10px 14px;
    border-radius: 8px;
    font-size: 13px;
    background: rgba(148, 163, 184, .12);
}

.modal > .notice {
    border-radius: 0;
    border-top: 1px solid var(--border);
}

.notice--ok i {
    color: var(--success, #16a34a);
}

.notice--warn i {
    color: var(--danger, #dc2626);
}

.notice__text {
    flex: 1 1 auto;
    min-width: 0;
}

/* Dialogo de sincronizacao com o Azure DevOps. Mais largo que o modal padrao porque cada linha
   carrega titulo, id, desfecho e o motivo — e quebrar isso em duas linhas dobraria a altura. */
.modal--wide {
    width: min(760px, calc(100vw - 40px));
}

.sync-list {
    margin: 12px 0 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.sync-item {
    display: flex;

    /* Sem o wrap, o detalhe — que tem flex-basis de 100% e nao encolhe — fica na MESMA linha do
       titulo, espreme o titulo ate zero e estoura a largura do dialogo. O efeito e perverso: some
       exatamente o nome do no que falhou, que e a unica informacao que interessa numa linha de
       falha, e sobra uma barra de rolagem horizontal no lugar. */
    flex-wrap: wrap;
    align-items: baseline;
    gap: 8px;
    padding: 6px 8px;
    border-radius: 6px;
    font-size: 13px;
}

/* Cores da CONFIRMACAO, antes de qualquer escrita. Nada aqui e verde de proposito: verde diria
   "deu certo", e ainda nao aconteceu nada. Criar e azul — item novo no board de outra pessoa — e
   atualizar e ambar, porque sobrescreve o que estiver la. */
.sync-item--created i { color: var(--accent, #2563eb); }
.sync-item--updated i { color: var(--warning, #d97706); }

.sync-item--ok i { color: var(--success, #16a34a); }
.sync-item--warn i { color: var(--warning, #d97706); }
.sync-item--failed i { color: var(--danger, #dc2626); }

/* O titulo cede o espaco; o desfecho e o id nunca encolhem, porque sao eles que respondem a
   pergunta que a lista existe para responder. */
.sync-item__title {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sync-item__id,
.sync-item__action {
    flex: 0 0 auto;
    color: var(--muted);
    font-size: 12px;
}

.sync-item__detail {
    flex: 0 0 100%;
    padding-left: 24px;
    color: var(--muted);
    font-size: 12px;

    /* A mensagem vem da API e pode ser longa. Quebra normalmente, e quebra tambem no meio de uma
       palavra quando nao houver espaco — nome de campo do Azure DevOps nao tem. */
    white-space: normal;
    overflow-wrap: anywhere;
}

/* Link para o work item no painel do no. */
.azure-link {
    flex: 1 1 auto;
    font-size: 13px;
}

.stat-line {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    margin: 0 0 2px;
    padding: 4px 6px;
    font-size: 13px;
    border-radius: 4px;
}

/* Botao que nao parece botao: a linha e leitura primeiro, e atalho depois. O affordance aparece no
   hover, para nao transformar a secao inteira numa fileira de botoes competindo com o conteudo. */
.stat-line--action {
    background: none;
    border: none;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.stat-line--action:hover {
    background: #eef2ff;
}

.stat-line__label {
    /* Quebra dentro da palavra: rotulo longo nao pode empurrar a contagem para fora do painel. */
    overflow-wrap: anywhere;
}

.stat-line__count {
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

.stat-group {
    margin: 12px 0 4px;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: #6b7280;
}

.azure-conflict {
    margin-top: 8px;
    font-size: 13px;
}

.azure-conflict__warn {
    margin: 0 0 8px;
    color: #92400e;
}

.azure-conflict__error {
    margin: 0;
    color: #b91c1c;
}

.azure-conflict__side {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-bottom: 6px;
}

.azure-conflict__label {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: #6b7280;
}

.azure-conflict__text {
    /* Quebra dentro da palavra: titulo longo sem espaco estouraria a largura do painel. */
    overflow-wrap: anywhere;
}

.azure-conflict__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 8px;
}

.code-block {
    width: 100%;
    min-height: 260px;
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 12.5px;
    line-height: 1.5;
    white-space: pre;
    overflow: auto;
}

/* ---------------------------------------------------------------------------------------
   Autorizacao OAuth

   Tela de fora do aplicativo: quem chega aqui veio de um conector e precisa reconhecer o que
   esta aprovando. Nada de menu ou navegacao — a unica saida e autorizar ou negar.
   --------------------------------------------------------------------------------------- */

.auth-page {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: 24px;
}

.auth-card {
    width: 100%;
    max-width: 420px;
    padding: 28px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    box-shadow: var(--shadow-lg);
}

.auth-card__head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 16px;
}

.auth-card__head h1 {
    margin: 0;
    font-size: 19px;
    font-weight: 600;
}

.auth-card__icon {
    font-size: 22px;
    color: var(--accent);
}

.auth-card__icon--danger {
    color: var(--danger);
}

.auth-intro {
    margin: 0 0 20px;
    line-height: 1.5;
    color: var(--text-muted);
}

.auth-intro strong {
    color: var(--text);
}

.auth-error {
    margin: 12px 0 0;
    padding: 9px 11px;
    border-radius: var(--radius);
    background: #fef2f2;
    border: 1px solid #fecaca;
    color: var(--danger);
    font-size: 13px;
}

/* Documentacao das tags do modelo, no proprio dialogo de envio: quem chega com um .docx pronto
   precisa saber o que ele deve conter ANTES de escolher o arquivo. */
.template-help {
    margin-bottom: 16px;
    padding: 12px 14px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface-muted, #f8fafc);
    font-size: 13px;
    line-height: 1.5;
}

.template-help__title {
    margin: 0 0 8px;
    font-weight: 600;
}

.template-help p {
    margin: 0 0 8px;
}

.template-help code {
    padding: 1px 5px;
    border-radius: 4px;
    background: #eef2ff;
    color: #3730a3;
    font-size: 12px;
    white-space: nowrap;
}

.template-help__tags td {
    padding: 4px 8px 4px 0;
    vertical-align: top;
}

.template-help__tags td:first-child {
    white-space: normal;
}

.template-help__rule {
    margin-bottom: 0 !important;
}

/* Diagnostico do arquivo escolhido. Verde nao e enfeite: e a diferenca entre um modelo que a
   geracao preenche e um que falharia so na frente do cliente. */
.template-diagnosis {
    margin-top: 12px;
    padding: 10px 12px;
    border-radius: var(--radius);
    font-size: 13px;
    line-height: 1.5;
}

.template-diagnosis.is-ok {
    background: #f0fdf4;
    border: 1px solid #bbf7d0;
}

.template-diagnosis.is-bad {
    background: #fef2f2;
    border: 1px solid #fecaca;
}

.template-diagnosis__title {
    margin: 0 0 6px;
    font-weight: 600;
}

.template-diagnosis ul {
    margin: 0 0 6px;
    padding-left: 18px;
    list-style: none;
}

.template-diagnosis p {
    margin: 0 0 4px;
}

.template-diagnosis__problem {
    color: var(--danger);
}

/* Contraparte verde do .auth-error, para a confirmacao de senha trocada. */
.auth-success {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 12px 0 0;
    padding: 9px 11px;
    border-radius: var(--radius);
    background: #f0fdf4;
    border: 1px solid #bbf7d0;
    color: #15803d;
    font-size: 13px;
}

.auth-actions {
    display: flex;
    gap: 8px;
    margin-top: 20px;
}

.auth-actions .btn {
    flex: 1;
    justify-content: center;
}

.auth-hint {
    margin: 18px 0 0;
    font-size: 12px;
    line-height: 1.5;
    color: var(--text-muted);
}

/* ---------------------------------------------------------------------------------------
   Administracao de acessos
   --------------------------------------------------------------------------------------- */

.page__subtitle {
    max-width: 60ch;
}

/* O historico do pedido e transcricao, nao frase: nasce alto o bastante para se ler um paragrafo
   sem rolar, e o usuario ainda pode esticar. */
.textarea--tall {
    min-height: 160px;
    resize: vertical;
}

/* Removido em 17/08/2026: o nome de quem esta logado saiu do cabecalho da home e foi para o topo do
   painel lateral, com estilo proprio (.drawer__user). Nenhuma outra tela usava esta classe.
.page__user {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin-right: 4px;
    font-size: 12px;
    color: var(--text-muted);
}
*/

/* Interruptor do administrador: so aparece para quem tem o papel. */
.page__switch {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-right: 4px;
    font-size: 12px;
    color: var(--text-muted);
    cursor: pointer;
    user-select: none;
}

.page__switch input {
    cursor: pointer;
}

/* ---------------------------------------------------------------------------------------
   Painel lateral do menu (flyout)
   --------------------------------------------------------------------------------------- */

/* Trocado em 17/08/2026: as acoes de conta e administracao ficavam soltas no cabecalho da home, uma
   ao lado da outra. Eram seis controles disputando a mesma linha do titulo e do "Novo mapa", e em
   tela estreita elas se encavalavam. Agora so o hamburguer e o "Novo mapa" ficam no cabecalho.

   Painel lateral, e nao menu suspenso: o conteudo e uma LISTA de destinos com rotulo por extenso, e
   um dropdown ancorado no botao teria que caber acima do cartao do primeiro mapa. */
/* Chip de conta: o gatilho do painel da lista de mapas.

   Redondo de 999px, e nao 50%: a caixa cresce com o tamanho do nome, e 50% numa caixa que estica
   vira elipse. Ver a armadilha ja paga no contador do ramo recolhido. */
.account-chip {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    height: 34px;
    padding: 3px 10px 3px 3px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface);
    color: var(--text);
    font-size: 13px;
    cursor: pointer;
}

.account-chip:hover {
    border-color: var(--border-strong);
    background: var(--surface-sunken);
}

.account-chip__avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    flex-shrink: 0;
    border-radius: 50%;
    background: var(--accent-soft);
    color: var(--accent);
    font-size: 12px;
    font-weight: 600;
}

/* O nome cede antes do resto: em tela estreita o que importa e o circulo e a seta continuarem
   clicaveis, e nao o nome inteiro caber. */
.account-chip__name {
    max-width: 140px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Mesma forma do aviso de dentro do painel: e o MESMO numero, e duas formas para o mesmo dado
   fariam a pessoa procurar diferenca onde nao ha. */
.account-chip__badge {
    padding: 0 6px;
    border-radius: 9px;
    background: var(--warning, #d97706);
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.account-chip .bi-chevron-down {
    font-size: 11px;
    color: var(--text-muted);
}

.drawer-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, .35);
    z-index: 90;
}

.drawer {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: min(300px, 86vw);
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border-left: 1px solid var(--border);
    box-shadow: var(--shadow-lg);
    z-index: 91;
}

.drawer__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--border);
}

.drawer__user {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.drawer__nav {
    display: flex;
    flex-direction: column;
    padding: 8px;
    gap: 2px;
    overflow-y: auto;
}

/* Item de largura inteira e alinhado a esquerda: numa lista vertical, rotulos comecando em colunas
   diferentes obrigam a reler cada linha do zero. */
.drawer__item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 9px 10px;
    border: none;
    border-radius: var(--radius);
    background: none;
    color: inherit;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
}

.drawer__item:hover {
    background: var(--surface-sunken);
}

.drawer__item i {
    width: 18px;
    text-align: center;
    color: var(--text-muted);
}

/* O interruptor mora na mesma lista dos destinos, entao veste a mesma linha — mas o clique cai no
   <label>, e nao num link. */
.drawer__item--switch {
    justify-content: space-between;
}

/* Campo de interruptor no painel: a caixa e o texto na mesma linha, e a linha inteira clicavel por
   ser um <label>. */
.field--switch {
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
}

.field--switch input {
    width: auto;
    margin: 0;
}

/* Lista de destinos do "mover para". Rolavel e estreita: o caminho e texto longo, e um popover que
   cresce com o mapa cobriria o canvas inteiro. */
.move-picker {
    width: 320px;
}

.move-list {
    display: flex;
    flex-direction: column;
    max-height: 260px;
    overflow-y: auto;
    margin-top: 6px;
}

.move-list__item {
    padding: 6px 8px;
    border: none;
    border-radius: 6px;
    background: none;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
}

.move-list__item:hover {
    background: var(--surface-sunken);
}

/* O caminho fica numa linha so. O corte do COMECO ja vem pronto do MoveTargets.PathOf, que abrevia
   para os tres ultimos niveis — a ponta e o que identifica o destino.

   Sem direction: rtl aqui, que era a tentativa anterior de cortar pela esquerda: o "... /" e as
   barras sao caracteres neutros, e a reordenacao bidirecional os jogava para o fim da linha, com o
   caminho aparecendo terminado em "/ ...". */
.move-list__path {
    display: block;
    font-size: 13px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.move-list__empty {
    margin: 8px 4px;
    font-size: 13px;
    color: var(--text-muted);
}

.drawer__separator {
    margin: 6px 4px;
    border: none;
    border-top: 1px solid var(--border);
}

/* Alerta de item fora de sincronia com o Azure DevOps: selo no botao da barra e aviso no painel. */
.btn--warn {
    color: var(--warn-text, #92400e);
}

.sync-badge {
    position: absolute;
    top: -4px;
    right: -4px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 999px;
    background: #f59e0b;
    color: #fff;
    font-size: 10px;
    line-height: 16px;
    text-align: center;
}

/* O botao vira a ancora do selo, que e posicionado em relacao a ele. */
.btn--icon {
    position: relative;
}

.azure-outofsync {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    margin: 0 0 10px;
    padding: 8px 10px;
    border: 1px solid #fcd34d;
    border-radius: 8px;
    background: #fffbeb;
    color: #92400e;
    font-size: 12px;
}

/* Removido em 19/08/2026: o bloco .status-filter — botao, painel ancorado, contagem e chevron.
   O filtro de status foi para o painel lateral, onde ele e uma lista de caixas como as demais
   escolhas, e nao um menu proprio pendurado na barra. */

/* Um bloco de ESCOLHA dentro do painel: rotulo em cima, controle embaixo. Diferente dos itens de
   navegacao, que sao uma linha clicavel inteira. */
.drawer__group {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 6px 10px 10px;
}

.drawer__label {
    font-size: 12px;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: .03em;
}

/* Cabecalho que abre e fecha uma secao do painel lateral. A tipografia nao se repete aqui: o texto
   continua sendo um .drawer__label DENTRO do summary, e o que esta classe acrescenta e so o
   comportamento de cabecalho — cursor, alinhamento e a seta, que vem das regras do
   .inspector__summary la em cima, compartilhadas com esta. */
.drawer__summary {
    display: flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    user-select: none;

    /* Mesmo motivo do .inspector__summary: cada navegador desenha o marcador nativo por um caminho,
       e esconder so um deixa o triangulo em metade deles. */
    list-style: none;
}

/* A caixa de status veste a linha dos demais itens do painel, mas com a marca a esquerda: aqui o
   clique alterna um estado, e nao leva para outro lugar. */
.drawer__item--check {
    gap: 8px;
    padding: 6px 0;
}

.drawer__hint {
    margin: 2px 0 0;
    font-size: 11px;
    color: var(--text-muted);
}

/* Marca de "publico" e de "de outro usuario" no cartao do mapa. */
.map-card__badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-right: 8px;
    padding: 1px 6px;
    border: 1px solid var(--border);
    border-radius: 999px;
    font-size: 11px;
}

.muted {
    color: var(--text-muted);
}

.admin-section {
    margin-bottom: 32px;
}

/* ---------------------------------------------------------------------------------------
   Painel de status do sistema
   --------------------------------------------------------------------------------------- */

/* Cartoes que se ajustam sozinhos a largura, sem media query: 'auto-fit' com um piso de 240px poe
   quatro num monitor grande e um no celular, e o piso e o que impede um cartao de ficar mais estreito
   que a frase que ele carrega. */
.status-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 12px;
    margin-bottom: 12px;
}

.status-card {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 12px 14px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);

    /* Item de grade nasce com 'min-width: auto' e se recusa a ficar menor que o conteudo — a mesma
       armadilha ja paga no flex. Sozinho ele nao basta aqui; ver o .status-card__hint. */
    min-width: 0;
}

.status-card__label {
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--text-muted);
}

.status-card__value {
    font-size: 22px;
    font-weight: 600;
    line-height: 1.2;

    /* Numero grande alinha melhor com numero grande quando os digitos tem a mesma largura: sem isto
       a coluna de cartoes "dança" ao trocar 1 por 8. */
    font-variant-numeric: tabular-nums;
}

/* O 'anywhere' NAO e exagero, e o 'break-word' nao serve no lugar dele.
   Medido em 08/09/2026: o caminho do storage local — "D:\Wetok\projetos\..." — nao tem onde quebrar,
   e empurrou o cartao para 487px dentro de uma coluna de 308, a grade para 1132 e a PAGINA INTEIRA
   para 1156px numa janela de 1002, com barra de rolagem horizontal no rodape. O 'break-word' quebra
   a linha e nao muda o tamanho minimo que o elemento declara a grade, entao o empurrao continuaria;
   'anywhere' e o que faz o min-content encolher junto. */
.status-card__hint {
    font-size: 12px;
    color: var(--text-muted);
    overflow-wrap: anywhere;
}

.status-card__actions {
    margin-top: 4px;
}

/* A tabela do banco tem mais de vinte linhas, e aberta ela empurrava o resto do painel para muito
   abaixo da dobra. Nasce com 200px, rola por dentro, e quem quiser ve mais arrastando o canto — o
   'resize' do navegador so funciona com overflow diferente de visible, que a rolagem ja garante. */
.status-table-scroll {
    height: 200px;
    min-height: 120px;
    max-height: 500px;
    overflow: auto;
    resize: vertical;
    border: 1px solid var(--border);
    border-radius: 8px;
}

/* Dentro do container a tabela nao repete a propria borda: seriam duas linhas coladas.
   
   E as duas ultimas linhas nao sao enfeite — sem elas o cabecalho GRUDADO nao gruda. Medido em
   09/09/2026: com 'border-collapse: collapse' o navegador nao aplica 'position: sticky' a um <th>, e
   o 'overflow: hidden' da tabela abre um contexto de recorte proprio que corta o que ficaria fixo.
   As duas vem do .admin-table, que nunca precisou rolar por dentro. */
.status-table-scroll .admin-table {
    border: none;
    border-radius: 0;
    border-collapse: separate;
    border-spacing: 0;
    overflow: visible;
}

/* O cabecalho gruda no topo da rolagem. Sem isto, rolar dez linhas e rolar sem saber mais qual coluna
   e qual — e a tabela tem tres colunas de numero parecidas entre si.

   O fundo e OPACO de proposito: cabecalho transparente deixa as linhas passarem por baixo dele. */
.status-table-scroll thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--surface-sunken);
}

/* A quebra por tipo dentro do cartao. Duas colunas — o nome a esquerda e o tamanho a direita — para
   os numeros se compararem pelo comprimento, sem precisar ler. */
.status-breakdown {
    margin: 6px 0 0;
    padding: 0;
    list-style: none;
    font-size: 12px;
    color: var(--text-muted);
}

.status-breakdown li {
    display: flex;
    justify-content: space-between;
    gap: 10px;
}

/* O aviso mora dentro do cartao a que ele se refere, e nao no rodape da secao: aviso de custo lido
   depois do clique nao e aviso, e relatorio.

   NAO E FLEX, e isso foi medido em 09/09/2026. Como flex, todo elemento inline dentro do aviso vira
   um ITEM proprio — um <strong> no meio da frase partia o texto em tres blocos que quebravam linha
   cada um por conta, e a frase saia em colunas desalinhadas. O recuo pendurado abaixo faz o mesmo
   desenho que o gap fazia e deixa o conteudo fluir como texto, que e o que ele e. */
/* Trocado em 09/09/2026 pelo desenho abaixo: o recuo pendurado alinhava as linhas de TEXTO entre si,
   e deixava o icone pendurado fora do bloco, sem nada com que se alinhar — parecia vazando do cartao.
   Grade de duas colunas resolve, e de quebra o icone deixa de depender de um numero magico que
   precisava casar com a largura da fonte de icones.
   padding-left: 18px; text-indent: -18px; */
.status-note {
    display: grid;

    /* O icone ocupa o que precisa; o texto fica com o resto e quebra dentro da PROPRIA coluna, entao
       a segunda linha nasce alinhada com a primeira. */
    grid-template-columns: auto 1fr;
    gap: 6px;

    /* No topo, e nao centralizado: com duas ou tres linhas de texto o icone iria para o meio do
       paragrafo, longe da linha que ele anuncia. */
    align-items: start;
    margin: 8px 0 0;
    font-size: 12px;
    color: var(--text-muted);
}

/* O TEXTO PRECISA VIR NUM <span>. Numa grade cada filho vira uma celula, entao um <strong> solto no
   meio da frase abriria uma terceira coluna e partiria o paragrafo — foi o que aconteceu quando isto
   aqui era flex. O <span> mantem a frase inteira numa celula so. */
.status-note > i {
    /* Alinha o glifo com a primeira linha do texto: a fonte de icones tem line-height propria, e sem
       isto ele nasce um ou dois pixels acima. */
    line-height: 1.5;
}

.status-note--ok {
    color: var(--success, #15803d);
}

.status-note--bad {
    color: var(--danger, #b91c1c);
}

/* Numero alinhado a direita e com digito de largura fixa: e assim que duas linhas de tamanho se
   comparam sem ler, so pelo comprimento da coluna.

   O seletor precisa do '.admin-table' na frente, e nao e enfeite: '.admin-table th, .admin-table td'
   declara 'text-align: left' com especificidade maior que a de uma classe sozinha, entao '.status-num'
   perdia — e a coluna saia a esquerda, com os numeros desalinhados entre si. Nao se ve num print de
   coluna estreita; so medindo o 'textAlign' computado. */
.admin-table .status-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.admin-section h2 {
    margin: 0 0 12px;
    font-size: 16px;
    font-weight: 600;
}

.admin-table {
    width: 100%;
    border-collapse: collapse;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
}

.admin-table th,
.admin-table td {
    padding: 9px 12px;
    text-align: left;
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
}

.admin-table thead th {
    background: var(--surface-sunken);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--text-muted);
}

.admin-table tbody tr:last-child td {
    border-bottom: none;
}

.admin-table code {
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 12px;
}

/* O nome secundario (login do cliente, nome de exibicao) vai numa segunda linha em cinza: na mesma
   linha ele competiria com o nome principal, que e o que se procura ao varrer a tabela. */
.admin-table__meta {
    display: block;
    margin-top: 2px;
    font-size: 11px;
    color: var(--text-muted);
}

.admin-table__actions {
    text-align: right;
    white-space: nowrap;
}

.admin-table__actions .btn + .btn {
    margin-left: 4px;
}

.btn--sm {
    padding: 3px 9px;
    font-size: 12px;
}

.badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
}

.badge--ok {
    background: #dcfce7;
    color: #166534;
}

.badge--off {
    background: var(--surface-sunken);
    color: var(--text-muted);
}

.badge--danger {
    background: #fef2f2;
    color: var(--danger);
}

.admin-note {
    margin: 10px 0 0;
    max-width: 70ch;
    font-size: 12px;
    line-height: 1.5;
    color: var(--text-muted);
}

.admin-form {
    margin-top: 18px;
    padding: 16px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    max-width: 520px;
}

.admin-form h3 {
    margin: 0 0 12px;
    font-size: 14px;
    font-weight: 600;
}

/* ---------------------------------------------------------------------------------------
   Erro do Blazor
   --------------------------------------------------------------------------------------- */

#blazor-error-ui {
    display: none;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1000;
    padding: 12px 16px;
    background: #fef3c7;
    border-top: 1px solid #fcd34d;
    box-shadow: 0 -1px 3px rgba(0, 0, 0, .1);
}

#blazor-error-ui .dismiss {
    position: absolute;
    top: 10px;
    right: 14px;
    cursor: pointer;
}

/* ---------------------------------------------------------------------------------------
   Estilo do no por status
   --------------------------------------------------------------------------------------- */

.style-layer {
    margin-bottom: 32px;
}

.style-layer h2 {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 4px;
    font-size: 17px;
}

/* O mesmo editor vive numa pagina larga e no painel estreito do mapa. No painel a grade nao cabe, e
   sem isto a coluna de opacidade era CORTADA — sem barra, sem sinal de que havia mais a direita. */
.status-style-editor {
    overflow-x: auto;
}

.status-style-table {
    width: 100%;
    min-width: 340px;
    margin-top: 10px;
    border-collapse: collapse;
    font-size: 13px;
}

.status-style-table th {
    padding: 4px 8px;
    text-align: left;
    font-weight: 600;
    font-size: 12px;
    color: var(--text-muted);
}

.status-style-table td {
    padding: 4px 8px;
    border-top: 1px solid var(--border);
}

.status-style-table__label {
    display: flex;
    align-items: center;
    gap: 8px;
    white-space: nowrap;
}

.status-style-table__opacity {
    width: 84px;
}

/* O seletor nativo de cor nao tem estado vazio. Quando esta camada nao opina, o quadrado ganha o
   xadrez de transparencia — o mesmo desenho que editores de imagem usam para "nada aqui" —, e o
   preto que o input mostra por dentro deixa de se ler como uma cor escolhida. */
/* As duas metades ficam COLADAS e com a mesma altura, como o split button da barra do no: com o
   gap e o botao redondo de .btn--icon, o x se lia como um controle vizinho solto, e nao como o
   "limpar" daquela amostra. */
.color-cell {
    display: inline-flex;
    align-items: stretch;
}

/* O 'appearance: none' e o ponto desta regra, e nao um enfeite: sem ele o navegador desenha o cromo
   DELE dentro do controle — uma moldura quadrada e grossa, cinza, que ignora o border-radius e
   aparece por dentro da nossa borda de 1px. Fica um quadrado dentro de um arredondado, que e o
   "problema de bordas" que a tarefa apontou.

   E 'overflow' NAO corrige, pelo mesmo motivo ja registrado na borda da imagem colada: o swatch e
   conteudo substituido, e overflow nao recorta conteudo substituido. Quem tem de obedecer ao raio e
   o proprio swatch, pelos pseudo-elementos abaixo. */
.color-cell__picker {
    -webkit-appearance: none;
    appearance: none;
    width: 34px;
    height: 24px;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: 6px 0 0 6px;
    background: none;
    cursor: pointer;
}

/* Os dois motores nomeiam o mesmo pedaco de formas diferentes, e as regras ficam SEPARADAS de
   proposito: num seletor em lista, um nome que o navegador nao conhece invalida a lista inteira — a
   regra sumiria nos dois em vez de valer em cada um. */
.color-cell__picker::-webkit-color-swatch-wrapper {
    padding: 0;
}

/* 5px, e nao 6px: o raio de dentro e o de fora menos a espessura da borda. Com 6px nos dois, a curva
   interna sobra e reaparece a fresta no canto. */
.color-cell__picker::-webkit-color-swatch {
    border: none;
    border-radius: 5px 0 0 5px;
}

.color-cell__picker::-moz-color-swatch {
    border: none;
    border-radius: 5px 0 0 5px;
}

.color-cell__picker.is-empty {
    background-image:
        linear-gradient(45deg, var(--border) 25%, transparent 25%),
        linear-gradient(-45deg, var(--border) 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, var(--border) 75%),
        linear-gradient(-45deg, transparent 75%, var(--border) 75%);
    background-size: 8px 8px;
    background-position: 0 0, 0 4px, 4px -4px, -4px 0;
}

.color-cell__picker.is-empty::-webkit-color-swatch-wrapper {
    opacity: 0;
}

/* O mesmo para o Firefox, e ele passou a ser necessario junto com o 'appearance: none': antes o
   cromo nativo tampava o swatch, e agora ele preenche o controle inteiro — sem esta regra o campo
   "herda" apareceria como um retangulo preto solido no lugar do xadrez. */
.color-cell__picker.is-empty::-moz-color-swatch {
    opacity: 0;
}

.color-cell__clear {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 24px;
    padding: 0;
    border: 1px solid var(--border);
    border-left: none;
    border-radius: 0 6px 6px 0;
    background: var(--surface);
    color: var(--text-muted);
    font-size: 11px;
    cursor: pointer;
}

.color-cell__clear:hover {
    background: var(--surface-sunken);
    color: var(--text);
}

/* Invisivel, e nao ausente: ele continua ocupando a largura dele para as celulas de todas as linhas
   terminarem no mesmo lugar. O visibility tambem o tira da ordem de tabulacao. */
.color-cell__clear.is-hidden {
    visibility: hidden;
}

.status-style-preview {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 10px;
}

/* A amostra usa as MESMAS variaveis do no no canvas, com os mesmos fallbacks: o que se ve aqui e o
   que aparece la. Ver o comentario do .node. */
.status-style-preview__chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 11px;
    border: 2px solid var(--status-border, transparent);
    border-radius: 8px;
    background: var(--status-bg, var(--surface));
    color: var(--status-fg, inherit);
    opacity: var(--status-opacity, 1);
    box-shadow: var(--shadow-sm);
    font-size: 13px;
}

.field__hint--danger {
    color: var(--danger);
}

/* ---------------------------------------------------------------------------------------
   Multisseleção: nó marcado e barra do lote
   --------------------------------------------------------------------------------------- */

/* O marcado usa PREENCHIMENTO, e o de foco continua com o anel da .node.is-selected. São sinais
   diferentes de propósito: um nó do lote pode estar em qualquer canto do mapa, e um anel repetido
   em quinze nós não diria mais qual deles o painel lateral está mostrando. */
.node.is-marked {
    border-color: var(--accent);
    background: var(--accent-soft);
}

/* Acima da faixa do zoom, e não na mesma linha: a barra é larga e centralizada, e em tela estreita
   ela passava por cima do controle de zoom, que fica na direita. */
.multi-bar {
    position: absolute;
    left: 50%;
    bottom: 62px;
    max-width: calc(100% - 36px);
    flex-wrap: wrap;
    justify-content: center;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 6px 8px;
    border: 1px solid var(--border);
    /* Canto arredondado e não pílula: em tela estreita a barra quebra em duas linhas, e o raio de
       999px numa caixa de duas linhas vira uma cápsula deformada. */
    border-radius: 18px;
    background: var(--surface);
    box-shadow: var(--shadow-md);
    z-index: 16;
}

.multi-bar__count {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 0 8px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-muted);
    white-space: nowrap;
}

/* Quantos do lote estao ali so porque alguem os revelou.

   Tracejado como a borda do proprio no revelado no canvas — ver .node.is-revealed. O mesmo desenho
   nos dois lugares e o que liga o numero da barra aos nos de que ele fala; um segundo vocabulario
   visual obrigaria a pessoa a aprender duas vezes a mesma ideia. */
.multi-bar__revealed {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 0 7px;
    border: 1px dashed var(--border);
    border-radius: 999px;
    font-weight: 400;
}

.multi-bar__divider {
    width: 1px;
    height: 18px;
    background: var(--border);
}

.multi-bar__action {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 28px;
    padding: 0 10px;
    border: none;
    border-radius: 999px;
    background: transparent;
    font-size: 12px;
    color: var(--text);
    cursor: pointer;
    white-space: nowrap;
}

.multi-bar__action:hover,
.multi-bar__action.is-open {
    background: var(--surface-sunken);
}

.multi-bar__action--danger {
    color: var(--danger);
}

/* O popover nasce ACIMA da barra, e não abaixo: a barra já mora na base da área do mapa, e uma
   lista aberta para baixo sairia da tela. */
.multi-bar__popover {
    left: 0;
    bottom: calc(100% + 8px);
    min-width: 190px;
}

.multi-bar__popover--form {
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 260px;
}

.multi-bar__list {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.multi-bar__item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border: none;
    border-radius: 6px;
    background: transparent;
    font-size: 13px;
    color: var(--text);
    text-align: left;
    cursor: pointer;
}

.multi-bar__item:hover {
    background: var(--surface-sunken);
}

.multi-bar__label {
    font-size: 11px;
    color: var(--text-muted);
}

.multi-bar__hint {
    font-size: 11px;
    line-height: 1.4;
    color: var(--text-muted);
}

.multi-bar__buttons {
    display: flex;
    justify-content: flex-end;
    gap: 6px;
    margin-top: 2px;
}

/* ---------------------------------------------------------------------------------------
   Visão em árvore (modo lista do editor)
   --------------------------------------------------------------------------------------- */

/* Ocupa o lugar do canvas dentro do .editor__body, que é flex: sem o flex:1 a tabela encolhe
   para a largura do conteúdo e deixa o painel lateral colado nela.

   Quem rola é o corpo, e não esta caixa: a barra e a paginação ficam parados nas pontas, e o
   cabeçalho grudento da tabela tem um contexto de rolagem só dele para grudar. */
/* O seletor de linhas por pagina, na barra da lista. O rotulo encolhe primeiro e o campo nao: um
   campo pela metade nao serve, e "Por pagina" se deduz pelo que esta dentro dele. */
.tree-bar__page-size {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    font-size: 12px;
    color: var(--text-muted);
}

.tree-bar__page-size select {
    width: auto;
    padding: 3px 6px;
    font-size: 12px;
}

.tree-view {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    background: var(--surface);

    /* Ancora da barra do lote, que flutua sobre a tabela. Sem isto ela subiria ate a .editor__body e
       herdaria dela o enquadramento — o mesmo problema de ancoragem ja pago nos popovers da barra do
       no. Ver o comentario do .multi-bar. */
    position: relative;
}

/* No modo lista nao ha barra de zoom no canto, e os 62px que existem no canvas para nao cobri-la
   deixariam a barra do lote flutuando alto, longe da ultima linha. */
.tree-view .multi-bar {
    bottom: 18px;
}

.tree-view__scroll {
    flex: 1;
    min-height: 0;
    overflow: auto;
}

.tree-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
}

.tree-table th {
    position: sticky;
    top: 0;
    z-index: 1;
    padding: 8px 10px;
    border-bottom: 1px solid var(--border);
    background: var(--surface);
    text-align: left;
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: .03em;
    white-space: nowrap;
}

.tree-table td {
    padding: 6px 10px;
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
}

.tree-table tbody tr {
    cursor: pointer;
}

/* Shift+clique estende a selecao de TEXTO do navegador, e a tabela ficava pintada de azul por baixo
   da marcacao das linhas — duas selecoes disputando a mesma tela, e a nativa por cima. Nao aparece
   em build nem em teste: so clicando com Shift.

   O canvas ja proibe selecao de texto, pelo mesmo motivo. E o texto daqui se leva pelo botao Copiar,
   que entrega a lista INTEIRA em formato de planilha — bem mais do que arrastar o cursor daria. */
.tree-table tbody {
    user-select: none;
}

.tree-table tbody tr:hover {
    background: var(--surface-sunken);
}

/* A linha do LOTE e a linha em FOCO tem o MESMO fundo, de proposito: as duas dizem "escolhida", e
   dois tons para dois graus da mesma coisa fariam a pessoa procurar uma diferenca de significado que
   nao existe. O que separa uma da outra e a faixa a esquerda, que so a linha em foco tem — e e ela
   que diz de qual no o painel lateral esta falando.

   A faixa e box-shadow, e nao border-left: borda muda a largura da celula e desalinha a coluna
   inteira quando a selecao anda de linha. */
.tree-table tbody tr.is-marked,
.tree-table tbody tr.is-selected {
    background: var(--accent-soft);
}

.tree-table tbody tr.is-selected td:first-child {
    box-shadow: inset 3px 0 0 var(--accent);
}

/* O resultado do filtro é marcado pelo TÍTULO em negrito, e não por fundo: o fundo já diz qual
   linha está selecionada, e duas cores de fundo disputando a mesma linha não dizem nenhuma das
   duas. Os ancestrais, que entram só pelo caminho, ficam sem marca. */
.tree-table tbody tr.is-match .tree-row__title {
    font-weight: 600;
}

.tree-table__title {
    width: 45%;
}

.tree-table__hours {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.tree-table__flags {
    text-align: center;
    white-space: nowrap;
}

.tree-row {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
}

.tree-row__toggle {
    flex: none;
    width: 18px;
    height: 18px;
    padding: 0;
    border: none;
    border-radius: 4px;
    background: transparent;
    color: var(--text-muted);
    font-size: 10px;
    cursor: pointer;
}

.tree-row__toggle:hover {
    background: var(--surface-sunken);
    color: var(--text);
}

.tree-row__toggle--empty {
    cursor: default;
}

.tree-row__icon {
    flex: none;
    color: var(--text-muted);
}

.tree-row__title {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tree-row__children {
    flex: none;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--surface-sunken);
    font-size: 11px;
    color: var(--text-muted);
}

/* Quantos nós a VISÃO esconde debaixo desta linha, e o botão que os traz.

   Desenho diferente do .tree-row__children ao lado, e de propósito: aquele conta o que o
   RECOLHIMENTO escondeu — decisão de alguém, gravada no mapa — e este conta o que o RECORTE em vigor
   escondeu. Dois números com a mesma pastilha na mesma linha seriam lidos como a mesma coisa. */
.tree-row__reveal {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 1px 7px;
    border: 1px dashed var(--border);
    border-radius: 999px;
    background: transparent;
    font-size: 11px;
    color: var(--text-muted);
    cursor: pointer;
}

.tree-row__reveal:hover {
    border-color: var(--accent);
    color: var(--accent);
}

/* Aberto: a borda deixa de ser tracejada porque não há mais nada escondido ali — o que o botão
   oferece agora é o caminho de volta. */
.tree-row__reveal.is-open {
    border-style: solid;
}

/* Linha que só está aqui porque alguém a revelou. Mesmo recado do .node.is-revealed no canvas, com
   o meio que a tabela tem: a linha inteira recua, e o título entra em itálico porque numa tabela a
   transparência sozinha se confunde com o zebrado. */
.tree-table tr.is-revealed {
    opacity: .65;
    font-style: italic;
}

.tree-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    white-space: nowrap;
}

.tree-flag {
    color: var(--text-muted);
    font-size: 12px;
}

/* O mesmo âmbar do chip de ressalva do nó — ver .node-info__chip--warning. Dois tons para o mesmo
   aviso fariam a pessoa procurar a diferença que não existe. */
.tree-flag--warning {
    color: #d97706;
}

.tree-pager {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 10px;
}

.tree-pager__label {
    font-size: 12px;
    color: var(--text-muted);
}

/* A barra da lista: contagem à esquerda, comandos à direita. Fica FORA da área que rola, para o
   botão de copiar não sumir enquanto se percorre a tabela. */
.tree-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 10px;
    border-bottom: 1px solid var(--border);
    background: var(--surface);
}

.tree-bar__count {
    flex: 1;
    font-size: 12px;
    color: var(--text-muted);
}

.tree-bar__feedback {
    font-size: 12px;
    color: var(--text-muted);
}

.tree-bar__feedback.is-error {
    color: var(--danger);
}

/* ---------------------------------------------------------------------------------------
   Cronograma (modulo Gantt)

   Duas metades que precisam ficar ALINHADAS linha a linha: a tabela a esquerda e a linha do tempo a
   direita. O alinhamento e o que faz um Gantt ser legivel, e ele depende de as duas usarem a mesma
   altura de linha — por isso ela e uma variavel, e nao um numero repetido.

   A altura tambem existe no C# (GanttView.RowHeight). As duas precisam bater; se um dia divergirem,
   o sintoma e a barra desencontrada do nome dela.
   --------------------------------------------------------------------------------------- */

.gantt {
    --gantt-row: 32px;

    /* As larguras das colunas moram AQUI, e nao soltas em cada regra, porque a tabela precisa saber
       a soma delas: sem um piso igual ao que as colunas ocupam, a linha transborda e a ultima delas
       e desenhada POR CIMA da linha do tempo. Ver o min-width do .gantt__table. */
    --gantt-col-id: 34px;
    --gantt-col-num: 56px;
    --gantt-col-date: 60px;
    --gantt-col-start: 96px;
    --gantt-col-dep: 104px;

    /* Piso do nome, e nao largura: ele e a coluna que CEDE, e so nao pode sumir. */
    --gantt-col-name: 90px;

    display: flex;
    border: 1px solid var(--border);
    border-radius: 10px;
    overflow: hidden;
    background: var(--surface);
}

/* A tabela nao encolhe: os nomes sao o que se le primeiro, e deixa-los ceder faria a coluna virar
   reticencias antes de a linha do tempo apertar. Quem rola e o lado direito.

   O PISO E A SOMA DAS COLUNAS, e nao um numero escolhido: as celulas tem flex-shrink zero, entao
   numa tabela mais estreita que elas ninguem cede — a linha transborda e a coluna de dependencia
   aparece DESENHADA POR CIMA da linha do tempo, com o "sem estimativa" por baixo. Medido em
   27/08/2026 numa janela de 949px: a tabela ficava com 407px para uma linha que pedia 496px.

   O 'min-content' resolveria sozinho, e nao serve: as celulas sao nowrap, entao ele mede o titulo
   INTEIRO do no mais longo — a tabela pulava para 743px e comia a linha do tempo.
   min-width: 0;

   E O PISO VENCE SEMPRE, hoje: a .page tem max-width de 1000px, entao os 46% dao no maximo ~438px e
   nunca alcancam a soma das colunas. A expressao de largura acima so volta a decidir alguma coisa se
   as colunas encolherem ou a pagina ficar mais larga — ela nao esta escrita a toa, mas tambem nao e
   ela que manda. */
/* Trocado em 27/08/2026, junto com a pagina inteira virar full width: com o teto de 520px a tabela
   nao aproveitava nada da tela nova — numa janela de 1920 o nome ficava com 113px enquanto sobravam
   1300px de linha do tempo. O teto continua existindo porque tabela larga demais transforma o Gantt
   numa planilha com uma tira de barras do lado.
   width: min(46%, 520px); */
.gantt__table {
    flex: 0 0 auto;

    /* A largura arrastada VENCE a proporcional, e some no recarregar: a variavel e escrita pelo
       gantt-splitter.js no elemento .gantt, e nao existe ate alguem arrastar. */
    width: var(--gantt-table-width, min(46%, 760px));
    /* Trocado em 16/09/2026: tres colunas numericas desde a das horas feitas.
       min-width: calc(
           var(--gantt-col-id) + var(--gantt-col-name) + (2 * var(--gantt-col-num))
           + var(--gantt-col-start) + var(--gantt-col-date) + var(--gantt-col-dep)); */
    min-width: calc(
        var(--gantt-col-id) + var(--gantt-col-name) + (3 * var(--gantt-col-num))
        + var(--gantt-col-start) + var(--gantt-col-date) + var(--gantt-col-dep));
    border-right: 1px solid var(--border);
}

/* A divisoria arrastavel. Ela nao OCUPA largura: a linha que se ve continua sendo a borda direita da
   tabela, e este elemento so poe uma area de pegada por cima dela. Dando largura propria a ele, a
   borda andaria alguns pixels e a grade sairia do lugar por causa de um controle invisivel. */
.gantt__splitter {
    position: relative;

    /* A LINHA DO TEMPO vem depois no DOM, e entre irmaos posicionados quem vem depois pinta por cima:
       sem o empilhamento, a area de pegada fica ATRAS da grade e o clique acerta a linha da tabela em
       vez da divisoria. Medido com elementFromPoint, que devolvia o .gantt__row. */
    z-index: 2;

    flex: 0 0 0;

    /* Sem isto, no toque o navegador entende o arraste como rolagem e a divisoria nao anda. */
    touch-action: none;
}

.gantt__splitter::before {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;

    /* A pegada e mais larga que a borda e centrada nela: um alvo de 1px so acerta quem tem a mao
       muito firme. */
    left: -3px;
    width: 7px;
    cursor: col-resize;
}

.gantt__splitter:hover::before,
.gantt.is-resizing .gantt__splitter::before {
    background: color-mix(in srgb, var(--accent) 35%, transparent);
}

/* Enquanto arrasta, o cursor e a proibicao de selecionar valem para a PAGINA inteira: o ponteiro sai
   da divisoria o tempo todo durante o gesto, e sem isto ele vira seta e comeca a selecionar a tabela
   no meio do arraste. */
body.is-col-resizing {
    cursor: col-resize;
    user-select: none;
}

.gantt__timeline {
    flex: 1 1 auto;

    /* Item de flex nasce com 'min-width: auto' e se recusa a ficar menor que o conteudo: sem isto a
       tela de mil pixels da grade estica a pagina inteira em vez de rolar aqui dentro. */
    min-width: 0;
}

.gantt__scroll {
    overflow-x: auto;
    overflow-y: hidden;
}

/* A tela da linha do tempo: largura conhecida, e tudo dentro dela posicionado por CALCULO. O
   transform nao muda a caixa de layout, entao delegar a posicao ao fluxo faria cada linha depender
   do conteudo da anterior. */
.gantt__canvas {
    position: relative;
}

.gantt__row {
    display: flex;
    align-items: center;
    height: var(--gantt-row);
    border-bottom: 1px solid var(--border-subtle, rgba(148, 163, 184, .18));
    cursor: pointer;
}

.gantt__timeline .gantt__row {
    position: relative;
}

.gantt__row:hover {
    background: var(--surface-sunken);
}

.gantt__row.is-selected {
    background: color-mix(in srgb, var(--accent) 10%, var(--surface));
}

.gantt__head {
    height: var(--gantt-row);
    font-size: 12px;
    font-weight: 600;
    color: var(--text-muted);
    background: var(--surface-muted);
    cursor: default;
}

/* O cabecalho da TABELA vale por DOIS, porque a linha do tempo tem duas faixas: mes em cima e a
   unidade da escala embaixo. Com uma altura so, as duas metades comecavam em alturas diferentes e
   toda barra saia 32px abaixo do nome dela — medido, e nao estimado. E o desalinhamento que o Gantt
   nao pode ter, porque ler a barra na linha errada e pior do que nao ter barra. */
.gantt__table .gantt__head {
    height: calc(var(--gantt-row) * 2);
}

.gantt__cell {
    padding: 0 8px;
    font-size: 13px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* O NOME e a parte que cede, e as outras colunas tem largura fixa: numero e data mudam de largura
   com o valor, e uma coluna que dança a cada recalculo faz a tabela inteira tremer. */
/* O piso existe para a coluna nao SUMIR: ela e a unica que cede, e numa janela estreita as fixas
   comiam os 100% dela. Nome cortado por reticencias ainda diz de que tarefa a linha e; coluna de
   largura zero nao diz nada. */
.gantt__cell--name {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 1 1 auto;
    min-width: var(--gantt-col-name);
}

.gantt__name {
    overflow: hidden;
    text-overflow: ellipsis;
}

/* O ⋮ da linha. Ele e o caminho DESCOBERTO para o menu — o botao direito e atalho de quem ja sabe.

   Invisivel em repouso e visivel no hover, na linha selecionada e com o menu aberto: uma coluna de
   reticencias em todas as linhas competiria com os nomes, que sao o que se le primeiro aqui.

   E ele OCUPA LUGAR sempre (visibility, e nao display): aparecendo no hover com display, a celula
   mudaria de largura sob o ponteiro e o nome saltaria alguns pixels a cada linha percorrida. */
.gantt__row-menu-btn {
    flex: 0 0 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-left: auto;
    padding: 0;
    height: 18px;
    border: 0;
    border-radius: 4px;
    background: none;
    color: var(--text-muted);
    font-size: 12px;
    line-height: 1;
    cursor: pointer;
    visibility: hidden;
}

.gantt__row:hover .gantt__row-menu-btn,
.gantt__row.is-selected .gantt__row-menu-btn,
.gantt__row-menu-btn.is-on {
    visibility: visible;
}

.gantt__row-menu-btn:hover,
.gantt__row-menu-btn.is-on {
    background: var(--surface-muted);
    color: var(--text);
}

/* O vao que guarda o lugar do ⋮ onde ele nao existe — a raiz, hoje. Sem ele o emblema daquela linha
   ia 28px mais para a direita que os das outras, e a coluna de numeros saia torta. Mesma solucao do
   .gantt__toggle--empty na outra ponta desta celula. */
.gantt__row-menu-btn--empty {
    cursor: default;
}

.gantt__row-menu-btn--empty:hover {
    background: none;
}

/* A linha do ramo que ficou fora do cronograma. Ela CONTINUA na tela, apagada: escondida por
   completo, o unico caminho de volta seria achar o no no mapa — e quem exclui por engano precisa
   desfazer de onde excluiu. A descendencia dela nao aparece; o ramo inteiro vale esta linha. */
.gantt__row.is-excluded .gantt__cell--name {
    color: var(--text-muted);
    font-style: italic;
}

.gantt__row.is-excluded .gantt__name {
    text-decoration: line-through;
    text-decoration-color: var(--border);
}

/* O menu da linha, e a cortina que o fecha.

   FIXED, e nao absolute: o .gantt tem overflow hidden para a linha do tempo rolar por dentro, e um
   menu absoluto ali dentro seria cortado na borda da grade. As coordenadas vem do ponteiro, ja em
   viewport, e por isso nao ha nada a converter. */
.gantt__menu-backdrop {
    position: fixed;
    inset: 0;
    z-index: 60;
}

.gantt__menu {
    position: fixed;
    z-index: 61;
    min-width: 190px;
    padding: 4px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
    box-shadow: var(--shadow-md);
}

.gantt__menu-row > button {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 7px 10px;
    border: 0;
    border-radius: 6px;
    background: none;
    color: var(--text);
    font: inherit;
    font-size: 13px;
    text-align: left;
    cursor: pointer;
}

.gantt__menu-row > button:hover {
    background: var(--surface-muted);
}

/* O menu do FUNIL da barra.

   Aqui o menu e ANCORADO no botao, e nao no ponteiro como o da linha: ele nasce sempre do mesmo
   lugar, e posiciona-lo pelo clique o faria pular alguns pixels conforme onde o dedo caiu. Por isso
   o wrapper e relativo e o menu volta a ser absoluto — e ele pode, porque a barra mora FORA do
   .gantt, que e quem tem o overflow hidden. */
.gantt__filters {
    position: relative;
    display: inline-flex;
}

.gantt__menu--filters {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    min-width: 210px;
}

/* O expansor do ramo. Ele guarda o lugar mesmo na folha (--empty), senao o titulo de cada folha
   andaria para a esquerda e o recuo deixaria de dizer profundidade. */
.gantt__toggle {
    flex: 0 0 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    padding: 0;
    border: 0;
    border-radius: 4px;
    background: transparent;
    font-size: 9px;
    color: var(--text-muted);
    cursor: pointer;
}

.gantt__toggle:hover {
    background: var(--surface-sunken);
    color: var(--text);
}

.gantt__toggle--empty {
    cursor: default;
}

/* Removido em 27/08/2026 o .gantt__spill, o aviso de filho fora do recorte esticando o resumo. Ele
   remendava o filtro por TIPO, que escondia a linha e deixava o no no calculo; sem esse filtro nao ha
   mais no com barra escondido da tela, e o aviso ficou sem o que avisar. Ver GanttExclusion. */

/* O total de horas do ramo, na linha de resumo.

   NAO ENCOLHE, pelo mesmo motivo que o antigo aviso de ocultos nao encolhia: numa coluna apertada
   quem cede e o nome, porque nome cortado ainda se reconhece e um numero cortado vira outro numero.

   Ele e o ULTIMO da celula, depois do ⋮: quem carrega o margin-left auto e o botao, e o emblema vem
   colado nele, na borda direita. Assim os numeros de todas as linhas formam uma coluna — o que so
   funciona porque o lugar do ⋮ e reservado ate onde ele nao existe. */
.gantt__total {
    flex: 0 0 auto;
    margin-left: 4px;
    padding: 0 5px;
    border-radius: 8px;
    background: var(--surface-sunken);
    font-size: 10px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--text-muted);
    cursor: help;
}

.gantt__cell--num {
    flex: 0 0 var(--gantt-col-num);
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.gantt__cell--date {
    flex: 0 0 var(--gantt-col-date);
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.gantt__ticks {
    position: relative;
    display: block;
}

.gantt__ticks--month {
    border-bottom: 1px solid var(--border);
}

.gantt__band,
.gantt__tick {
    position: absolute;
    top: 0;
    height: var(--gantt-row);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    border-left: 1px solid var(--border);
    overflow: hidden;
}

/* Fim de semana e feriado esmaecidos: sao a explicacao visual de por que uma barra de tres dias
   ocupa cinco colunas. Sem isso o calendario parece errado. */
.gantt__tick.is-rest {
    background: var(--surface-sunken);
    color: var(--text-muted);
}

/* HOJE por cima das faixas e ATRAS das barras: na frente ele cortaria a barra ao meio, e atras de
   tudo sumiria sob a primeira que passasse por cima. */
/* Trocado em 27/08/2026: a meia opacidade sobre 2px ainda desenhava um traco vermelho vivo, que
   disputava a leitura com as barras — e "hoje" e uma referencia de fundo, e nao um alerta. Passa a
   ser mais discreta, e continua atravessando a grade inteira, que e o que a torna util.
   width: 2px;
   opacity: .5; */
.gantt__today {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 1px;
    background: var(--danger);
    opacity: .3;
}

.gantt__bar {
    position: absolute;
    top: 6px;
    height: calc(var(--gantt-row) - 12px);
    border-radius: 4px;
    background: var(--accent);
    overflow: hidden;

    /* SEM transition. Quando o arraste entrar (fase 2), cada quadro reiniciaria a interpolacao do
       anterior e a barra passaria a boiar atras do cursor — a armadilha ja paga no canvas do mapa e
       na imagem ampliada. Deixar de fora agora evita descobrir isso depois. */
}

/* O resumo do ramo e mais fino e neutro: ele nao e trabalho, e sim o envelope do que esta dentro.
   Com a mesma altura das outras, um ramo parecia uma tarefa gigante. */
.gantt__bar--summary {
    top: 10px;
    height: calc(var(--gantt-row) - 20px);
    border-radius: 2px;
    background: var(--text-muted);
}

.gantt__bar--pinned {
    outline: 2px solid var(--warning);
    outline-offset: -2px;
}

.gantt__progress {
    display: block;
    height: 100%;
    background: rgba(15, 23, 42, .28);
}

/* O marco e um losango, e nao uma barra de largura zero: duracao nenhuma precisa de uma forma
   propria, ou ele desaparece na grade. */
.gantt__milestone {
    position: absolute;
    top: calc(var(--gantt-row) / 2 - 6px);
    width: 12px;
    height: 12px;
    margin-left: -6px;
    background: var(--text);
    transform: rotate(45deg);
}

.gantt__absent {
    padding-left: 8px;
    font-size: 11px;
    color: var(--text-muted);
}

/* O botao que troca de tela vai para a DIREITA da barra, longe dos controles que agem sobre esta.
   Mesmo criterio do "Ver como lista" na barra do editor. */
.list-toolbar__end {
    margin-left: auto;
}

/* Legenda do cronograma.

   Ela existe porque a grade fala por FORMA e COR — barra fina para resumo, contorno laranja para
   data fixada, losango para marco —, e nada disso se adivinha olhando. Fica depois da grade: no
   topo empurraria a primeira barra para fora da primeira olhada. */
.gantt-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 18px;
    margin-top: 12px;
    font-size: 12px;
    color: var(--text-muted);
}

.gantt-legend__item {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* As amostras reusam as CLASSES reais das barras, e nao cores copiadas: uma legenda com a cor
   escrita a mao mente no dia em que a barra mudar de tom, e ninguem vai lembrar de acertar as duas.
   Por isso aqui so se desfaz o posicionamento absoluto que as barras tem na grade. */
.gantt-legend__swatch {
    position: static;
    flex: 0 0 auto;
    width: 28px;
    height: 12px;
    top: auto;
    border-radius: 3px;
}

.gantt-legend__swatch.gantt__bar--summary {
    height: 6px;
}

.gantt-legend__swatch--milestone {
    width: 12px;
    height: 12px;
    margin-left: 4px;
    background: var(--text);
    transform: rotate(45deg);
}

.gantt-legend__swatch--today {
    width: 2px;
    height: 14px;
    background: var(--danger);
    opacity: .5;
}

.gantt-legend__swatch--rest {
    background: var(--surface-sunken);
    border: 1px solid var(--border);
}

/* A coluna "#": numero da linha, usado na coluna de dependencia. Estreita e tabular, para os
   numeros ficarem alinhados uns sob os outros. */
.gantt__cell--id {
    flex: 0 0 var(--gantt-col-id);
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--text-muted);
}

.gantt__cell--dep {
    flex: 0 0 var(--gantt-col-dep);
}

/* O campo da dependencia mora DENTRO da linha, e por isso perde a altura e a moldura de um campo de
   formulario: a tabela e para varrer, e uma caixa desenhada em cada linha viraria um paredao de
   bordas. A borda so aparece no foco e no erro, que e quando ela informa alguma coisa. */
.gantt__dep {
    width: 100%;
    height: 22px;
    padding: 0 4px;
    border-color: transparent;
    background: transparent;
    font-size: 12px;
}

.gantt__dep:hover:not(:disabled) {
    border-color: var(--border);
}

.gantt__dep.is-invalid {
    border-color: var(--danger);
    background: color-mix(in srgb, var(--danger) 8%, var(--surface));
}

/* O interruptor do ramo sequencial, na coluna de dependencia da linha de resumo. Cabe nos 104px da
   coluna porque e uma palavra e um icone, e nao um botao de formulario. */
.gantt__chain {
    width: 100%;
    height: 22px;
    padding: 0 4px;
    gap: 4px;
    border-color: transparent;
    background: transparent;
    font-size: 11px;
    color: var(--text-muted);
}

.gantt__chain:hover:not(:disabled) {
    border-color: var(--border);
}

/* Ligado, ele deixa de ser um botao apagado e vira o estado do ramo: e a unica coisa na tela que
   explica por que aquelas barras estao em fila, ja que a amarra do ramo nao vira seta. */
.gantt__chain.is-on {
    color: var(--accent);
    font-weight: 600;
}

.gantt__dep-locked {
    padding-left: 4px;
    font-size: 12px;
    color: var(--text-muted);
}

/* A coluna de INICIO quando ela e editavel: os 60px da coluna de leitura mostram "27/08", e o campo
   mostra o ano inteiro. */
.gantt__cell--start {
    flex: 0 0 var(--gantt-col-start);
}

/* Campo dentro da linha da tabela: mesma escolha do .gantt__dep — sem altura e sem moldura de
   formulario, porque uma caixa desenhada em cada linha viraria um paredao de bordas numa tabela que
   existe para ser varrida. A borda aparece no hover e no foco, que e quando ela informa alguma
   coisa. */
/* Todo campo editavel desta tabela guarda numero ou data, e as colunas em que eles moram sao
   alinhadas a DIREITA. Acrescentado em 27/08/2026: o alinhamento estava so no --num, entao a data
   fixada era o unico valor da coluna Inicio com o texto encostado a esquerda — as outras datas sao
   spans de leitura, que herdam o right da celula.

   O padding de 7px, e nao 8: a celula de leitura tem 8px de padding e o campo tem 1px de borda, que
   soma por fora. Com 8 aqui a data fixada ficava 1px a esquerda das outras. */
.gantt__cell-edit {
    width: 100%;
    height: 22px;
    padding: 0 7px;
    border-color: transparent;
    background: transparent;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
    text-align: right;
}

.gantt__cell-edit:hover:not(:disabled) {
    border-color: var(--border);
}

/* Data que a tela nao entendeu. O campo e de texto desde que o formato passou a ser forcado, entao
   nao ha mais o navegador barrando o que nao e data — o aviso tem que vir daqui. */
.gantt__cell-edit.is-invalid {
    border-color: var(--danger);
    background: color-mix(in srgb, var(--danger) 8%, var(--surface));
}

/* O que foi DECLARADO a mao — data fixada, duracao propria — contra o que o escalonador calculou.
   Sem esta marca a coluna deixaria de dizer o que e compromisso, que e a informacao que ela carrega
   desde que virou campo. */
.gantt__cell-edit.is-pinned {
    color: var(--accent);
    font-weight: 600;
}

/* O text-align subiu para o .gantt__cell-edit em 27/08/2026, junto com a data. O modificador fica
   pelas setinhas abaixo.
.gantt__cell-edit--num {
    text-align: right;
} */

/* Onde a coluna MISTURA campo e texto, os dois precisam cair no mesmo pixel — o resumo mostra texto,
   a folha mostra campo, e e a mesma coluna. Quem cede e a CELULA que hospeda o campo: ela abre mao do
   recuo da direita, e o recuo do proprio campo (7px de padding mais 1px de borda) ocupa aquele lugar.

   Medido em 27/08/2026: a data fixada da linha START terminava em 409px e as datas calculadas das
   outras em 417px.

   TENTADO E DESCARTADO: dar o mesmo recuo ao texto de leitura. Ele alinhava, e roubava 8px da largura
   util da celula — o "marco" da coluna Dias, que ja mal cabia em 56px, passava a transbordar 4px por
   cima da coluna vizinha. Alinhar nao pode custar o conteudo.
.gantt__row .gantt__cell--start > span { padding-right: 8px; } */
.gantt__cell--editing {
    padding-right: 0;
}

/* As setinhas do campo numerico ocupam a largura que o numero precisa, e aparecem em toda linha da
   coluna. A roda do mouse e as setas do teclado continuam funcionando. */
.gantt__cell-edit--num::-webkit-inner-spin-button,
.gantt__cell-edit--num::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.gantt__cell-edit--num {
    -moz-appearance: textfield;
    appearance: textfield;
}

/* As setas de dependencia, numa camada por cima da grade.

   O 'pointer-events: none' e o que faz esta camada existir sem atrapalhar: sem ele o SVG cobriria a
   grade inteira e comeria o clique de toda barra embaixo dele. */
.gantt__arrows {
    position: absolute;
    left: 0;

    /* Comeca abaixo das DUAS faixas de cabecalho, que e onde a primeira linha comeca. As setas sao
       desenhadas em coordenadas de linha (zero e a primeira), entao sem este deslocamento elas
       sairiam todas em cima do cabecalho. */
    top: calc(var(--gantt-row) * 2);

    pointer-events: none;
    overflow: visible;
}

.gantt__arrows path {
    fill: none;
    stroke: var(--text-muted);
    stroke-width: 1.5;
}

.gantt__arrows polygon {
    fill: var(--text-muted);
}


/* -------------------------------------------------------------------------------------------
   Popup do submapa
   ------------------------------------------------------------------------------------------- */

/* Ele e uma JANELA DA TELA, e nao um objeto do mapa: fixed, e nao absolute. Dentro do conteudo
   transformado do canvas, herdaria zoom e deslocamento, e um mapa aberto a 43% mostraria o popup
   ilegivel no canto. */
.submap-dialog__backdrop {
    position: fixed;
    inset: 0;
    background: rgb(15 23 42 / 45%);
    z-index: 60;
}

.submap-dialog {
    position: fixed;
    top: 5vh;
    left: 50%;
    display: flex;
    flex-direction: column;
    width: min(1200px, 90vw);
    height: 90vh;
    transform: translateX(-50%);
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--surface);
    box-shadow: var(--shadow-lg);
    z-index: 61;
    overflow: hidden;
}

.submap-dialog__head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    border-bottom: 1px solid var(--border);
}

/* O titulo empurra os botoes para a direita e cede espaco antes deles: mapa de nome longo nao pode
   expulsar da barra o botao de fechar. */
.submap-dialog__title {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    font-weight: 600;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.submap-dialog__body {
    flex: 1;
    min-height: 0;
}

.submap-dialog__frame {
    width: 100%;
    height: 100%;
    border: none;
}

/* -------------------------------------------------------------------------------------------
   Add-on de submapa, no painel
   ------------------------------------------------------------------------------------------- */

.submap-addon {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.submap-addon__current {
    display: flex;
    align-items: center;
    gap: 6px;
}

.submap-addon__title {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.submap-addon__hint,
.submap-addon__missing,
.submap-addon__error {
    margin: 0;
    font-size: 12px;
    color: var(--text-muted);
}

.submap-addon__error {
    color: var(--danger);
}

/* O aviso dentro de um dialogo de confirmacao. Ambar, e nao vermelho: o vermelho ali ja e do botao
   que executa a exclusao, e dois vermelhos disputando fariam o olho ler o aviso como parte do botao. */
.modal__warning {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    margin: 10px 0 0;
    padding: 8px 10px;
    border: 1px solid #fbbf24;
    border-radius: 8px;
    background: #fffbeb;
    color: #92400e;
    font-size: 13px;
}

/* Teste da sintaxe da expressao no dialogo de visões: botao e veredito na mesma linha. */
.view-test {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: -4px 0 12px;
    font-size: 13px;
}

.view-test__ok { color: #16a34a; }
.view-test__error { color: #dc2626; }

/* =========================================================================================
   Modulo de checklists (08/10/2026). Ver Components/Pages/ChecklistPage.razor.
   ========================================================================================= */

.btn--small {
    padding: 3px 8px;
    font-size: 12px;
}

.checklist-page {
    max-width: 900px;
}

.checklist-page__title-input {
    font-size: 22px;
    font-weight: 700;
    min-width: 320px;
}

.checklist-page__project-input {
    display: block;
    max-width: 260px;
    margin-bottom: 6px;
    font-size: 12px;
}

.checklist-page__description {
    color: var(--text-muted);
    margin: 0 0 14px;
}

/* Conteudo HTML lido (descricao do checklist e do item): imagens coladas nao estouram a coluna. */
.rich-text img {
    max-width: 100%;
    height: auto;
    border-radius: 6px;
}

.rich-text p { margin: 0 0 6px; }

.rich-text pre {
    background: var(--surface-sunken);
    padding: 8px 10px;
    border-radius: 6px;
    overflow-x: auto;
}

.checklist-pills {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
    margin: 0 0 14px;
}

/* A cor da pilula vem por variavel: so a borda e o rotulo ganham a cor, e o texto continua legivel
   em qualquer escolha de quem cadastrou. */
.checklist-pill {
    --pill-color: var(--border-strong);
    display: inline-flex;
    gap: 6px;
    align-items: baseline;
    padding: 3px 10px;
    border: 1px solid var(--pill-color);
    border-radius: 999px;
    font-size: 12px;
    background: var(--surface);
}

.checklist-pill__label {
    color: var(--pill-color);
    font-weight: 600;
    text-transform: uppercase;
    font-size: 10px;
    letter-spacing: .04em;
}

.checklist-pill__value {
    font-size: 11px;
    font-weight: 600;
    /* Valor longo nao estoura o cartao: corta com reticencias, e o texto inteiro fica no title. */
    max-width: 220px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.checklist-card__project {
    display: inline-flex;
    gap: 5px;
    align-items: center;
    color: var(--text-muted);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    margin-bottom: 4px;
}



.checklist-pill-row {
    display: flex;
    gap: 6px;
    align-items: center;
    margin-bottom: 6px;
}

.checklist-pill-row__color {
    width: 34px;
    height: 30px;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: 6px;
}

.checklist-progress {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    color: var(--text-muted);
}

.checklist-progress__bar {
    display: inline-block;
    width: 90px;
    height: 6px;
    border-radius: 3px;
    background: var(--surface-sunken);
    overflow: hidden;
}

.checklist-progress__bar > span {
    display: block;
    height: 100%;
    background: var(--success);
}

.checklist-progress--wide {
    display: flex;
    margin: 0 0 18px;
}

.checklist-progress--wide .checklist-progress__bar {
    flex: 1;
}

.checklist-section {
    margin: 0 0 22px;
}

.checklist-section__title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 18px;
    margin: 0 0 8px;
}

.checklist-section__number {
    color: var(--accent);
    font-size: 14px;
}

.checklist-entries {
    list-style: none;
    margin: 0;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--surface);
}

.checklist-entries:empty {
    display: none;
}

.checklist-entry {
    display: flex;
    gap: 12px;
    padding: 12px 14px;
    border-top: 1px solid var(--border);
}

.checklist-entry:first-child {
    border-top: none;
}

.checklist-entry__check {
    width: 18px;
    height: 18px;
    margin-top: 2px;
    flex-shrink: 0;
}

.checklist-entry__body {
    flex: 1;
    min-width: 0;
}

.checklist-entry__title {
    font-weight: 600;
}

.checklist-entry__description {
    color: var(--text-muted);
    font-size: 13px;
    margin-top: 4px;
}

.checklist-entry.is-checked .checklist-entry__title {
    color: var(--text-muted);
    text-decoration: line-through;
}

.checklist-entry__actions {
    display: flex;
    gap: 2px;
    flex-shrink: 0;
}

.checklist-add {
    display: flex;
    gap: 6px;
    margin-top: 8px;
}

.checklist-add .input {
    flex: 1;
}

.checklist-share-row {
    display: flex;
    gap: 6px;
    align-items: center;
    margin: 6px 0;
}

.checklist-share-row__name {
    flex: 1;
    min-width: 0;
}

.checklist-share-row.is-muted .checklist-share-row__name {
    color: var(--text-muted);
    text-decoration: line-through;
}

.checklist-share__invite-title {
    display: block;
    margin-top: 16px;
}

/* Lista de checklists em cartoes (08/10/2026). Reaproveita .map-grid/.map-card da lista de mapas. */
.checklist-list__search {
    position: relative;
    display: flex;
    gap: 8px;
    max-width: 600px;
    margin: 0 0 18px;
}

.checklist-list__search > i {
    position: absolute;
    left: 10px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-muted);
    font-size: 13px;
}

.checklist-list__search .input {
    flex: 1;
    min-width: 0;
    padding-left: 30px;
}

.checklist-list__search .checklist-list__project {
    flex: 0 1 200px;
    padding-left: 10px;
}

.checklist-card {
    color: inherit;
    text-decoration: none;
    gap: 12px;
    border-left: 4px solid var(--accent);
}

.checklist-card.is-done {
    border-left-color: var(--success);
}

.checklist-card:hover .map-card__title {
    color: var(--accent);
}

.checklist-card .map-card__header {
    margin: 0;
}

.checklist-card__pills {
    margin: 0;
}

.checklist-card__more {
    font-size: 12px;
    color: var(--text-muted);
}

.checklist-card__progress {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: auto;
}

.checklist-card__progress .checklist-progress__bar {
    width: 100%;
    height: 8px;
    border-radius: 4px;
}

.checklist-card__count {
    font-size: 12px;
    color: var(--text-muted);
}

.checklist-card__count strong {
    color: var(--text);
}

.checklist-card__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    font-size: 12px;
    color: var(--text-muted);
    border-top: 1px solid var(--border);
    padding-top: 10px;
}

.checklist-card__updated {
    margin-left: auto;
}

/* Ajustes conferidos na tela em 08/10/2026: o .select global ocupa a largura toda, e na linha de
   compartilhamento ele espremia o nome da pessoa ate sumir; o titulo em edicao cortava o nome. */
.checklist-share-row .select {
    width: auto;
    flex: 0 0 140px;
}

.checklist-share-row .select:first-child {
    flex: 1;
}

.checklist-share-row__name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.checklist-page .page__header > div:first-child {
    flex: 1;
    min-width: 0;
    margin-right: 16px;
}

.checklist-page__title-input {
    width: 100%;
}

/* -----------------------------------------------------------------------------------------
   Checklist: layout refinado (08/10/2026) — arrastar, acoes discretas, adicionar embutido.
   ----------------------------------------------------------------------------------------- */

.checklist-page h1 {
    font-size: 30px;
    letter-spacing: -0.01em;
    margin: 4px 0 0;
}

.checklist-page__description {
    font-size: 15px;
    line-height: 1.55;
    max-width: 68ch;
}

/* Descricao em edicao: o editor nao precisa da altura de um documento. */
.checklist-page .rich-editor [contenteditable] {
    min-height: 70px;
}

.checklist-section {
    margin: 0 0 26px;
    border-radius: 12px;
}

.checklist-section__title {
    font-size: 19px;
    font-weight: 650;
    gap: 10px;
    margin: 0 0 10px;
}

.checklist-section__number {
    font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
    font-size: 13px;
    font-weight: 600;
    color: var(--accent);
    background: var(--accent-soft);
    border-radius: 6px;
    padding: 1px 7px;
}

.checklist-section__count {
    margin-left: auto;
    font-size: 12px;
    font-weight: 500;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

/* Titulo da secao editavel com cara de titulo: a moldura so aparece no foco ou sob o cursor. */
.checklist-section__title-input {
    flex: 1;
    min-width: 0;
    font: inherit;
    color: inherit;
    border: 1px solid transparent;
    background: transparent;
    border-radius: 6px;
    padding: 2px 6px;
}

.checklist-section__title-input:hover {
    border-color: var(--border);
}

.checklist-section__title-input:focus {
    outline: none;
    border-color: var(--accent);
    background: var(--surface);
}

.checklist-entries {
    border-radius: 12px;
    box-shadow: var(--shadow-sm);
}

.checklist-entries:empty {
    display: none;
}

.checklist-entry {
    align-items: flex-start;
    position: relative;
    transition: background .12s;
}

.checklist-page.is-editing .checklist-entry:hover {
    background: var(--surface-muted);
}

.checklist-entry__check {
    accent-color: var(--success);
    cursor: pointer;
}

.checklist-entry__who {
    margin-top: 4px;
    font-size: 12px;
    color: var(--success);
}

/* Acoes do item: aparecem so sob o cursor (ou no foco por teclado), para a lista em edicao nao
   virar uma parede de botoes. */
.checklist-entry__actions {
    opacity: 0;
    transition: opacity .12s;
}

.checklist-entry:hover .checklist-entry__actions,
.checklist-entry:focus-within .checklist-entry__actions {
    opacity: 1;
}

.checklist-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
}

.checklist-icon-btn:hover {
    background: var(--surface-sunken);
    color: var(--text);
}

.checklist-icon-btn--danger:hover {
    background: #fee2e2;
    color: var(--danger);
}

.checklist-section__title .checklist-icon-btn {
    opacity: .6;
}

.checklist-section__title:hover .checklist-icon-btn {
    opacity: 1;
}

/* Alca de arrastar. */
.checklist-drag {
    display: inline-flex;
    align-items: center;
    color: var(--border-strong);
    cursor: grab;
    margin-left: -6px;
    padding-top: 2px;
    user-select: none;
}

.checklist-drag:hover {
    color: var(--text-muted);
}

.checklist-section__title .checklist-drag {
    padding-top: 0;
}

[data-drag-kind].is-dragging {
    opacity: .45;
}

/* Onde o item vai cair: uma linha azul na borda de cima ou de baixo. */
.checklist-entry.drop-before {
    box-shadow: inset 0 3px 0 var(--accent);
}

.checklist-entry.drop-after {
    box-shadow: inset 0 -3px 0 var(--accent);
}

.checklist-entries.drop-into {
    outline: 2px dashed var(--accent);
    outline-offset: 2px;
}

.checklist-section.drop-before {
    box-shadow: 0 -3px 0 var(--accent);
}

.checklist-section.drop-after {
    box-shadow: 0 3px 0 var(--accent);
}

/* Adicionar item: a ultima linha da lista, sem moldura. */
.checklist-entry--add {
    align-items: center;
    color: var(--text-muted);
}

.checklist-entry__add-input,
.checklist-new-section__input {
    flex: 1;
    min-width: 0;
    border: 0;
    background: transparent;
    font: inherit;
    color: var(--text);
    padding: 2px 0;
}

.checklist-entry__add-input:focus,
.checklist-new-section__input:focus {
    outline: none;
}

.checklist-new-section {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    border: 1px dashed var(--border-strong);
    border-radius: 12px;
    color: var(--text-muted);
    font-size: 15px;
}

.checklist-new-section:focus-within {
    border-color: var(--accent);
    color: var(--accent);
}

/* Blocos de codigo da descricao, com o "Copiar" que o checklist.js poe dentro do <pre>. */
.rich-text pre {
    position: relative;
    margin: 8px 0 0;
    padding: 12px 14px;
    font: 13px/1.5 ui-monospace, SFMono-Regular, Consolas, monospace;
    white-space: pre-wrap;
    color: var(--text);
}

.checklist-code__copy {
    position: absolute;
    top: 6px;
    right: 6px;
    font: 500 12px system-ui, sans-serif;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text);
    border-radius: 6px;
    padding: 2px 9px;
    cursor: pointer;
    opacity: .85;
}

.checklist-code__copy:hover {
    opacity: 1;
}

.rich-text code {
    font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
    font-size: .9em;
    background: var(--surface-sunken);
    padding: 1px 5px;
    border-radius: 4px;
}

.rich-text pre code {
    background: none;
    padding: 0;
}

/* A "nota" do roteiro (HM x Producao) vira um blockquote ambar. */
.rich-text blockquote {
    margin: 10px 0 0;
    padding: 10px 14px;
    border-radius: 10px;
    background: #fbf1df;
    color: var(--text);
    border: 0;
}

/* Compartilhar: resumo das pessoas e o segundo dialogo por cima do primeiro. */
.checklist-share-summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 12px;
    margin: 4px 0 8px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface-muted);
}

.checklist-share-summary .field__label {
    display: block;
}

.checklist-share-summary__text {
    font-size: 14px;
}

.modal-backdrop--stacked {
    z-index: 1100;
}

/* Ressalva de conclusao do item (08/10/2026). */
.checklist-remarks-btn {
    margin-left: 8px;
    border: 0;
    background: transparent;
    color: var(--text-muted);
    font-size: 12px;
    cursor: pointer;
    padding: 0 4px;
    border-radius: 4px;
}

.checklist-remarks-btn:hover {
    color: var(--warning);
    background: #fbf1df;
}

.checklist-entry__remarks {
    margin-top: 6px;
    padding: 6px 10px;
    border-radius: 8px;
    background: #fbf1df;
    color: var(--text);
    font-size: 13px;
}

.checklist-entry__remarks i {
    color: var(--warning);
}

.checklist-remarks-edit {
    margin-top: 6px;
}

.checklist-remarks-edit textarea {
    width: 100%;
    resize: vertical;
}

.checklist-remarks-edit__actions {
    display: flex;
    justify-content: flex-end;
    gap: 6px;
    margin-top: 4px;
}

/* Secoes recolhiveis (09/10/2026). */
.checklist-section__toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    font-size: 13px;
}

.checklist-section__toggle:hover {
    background: var(--surface-sunken);
    color: var(--text);
}

.checklist-section__toggle i {
    transition: transform .15s;
}

.checklist-section.is-collapsed .checklist-section__toggle i {
    transform: rotate(-90deg);
}

.checklist-section__name {
    cursor: pointer;
}

.checklist-section.is-collapsed {
    margin-bottom: 12px;
}

.checklist-section.is-collapsed .checklist-section__title {
    margin-bottom: 0;
    padding: 8px 10px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--surface);
}

.checklist-collapse-all {
    margin-left: 8px;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text-muted);
    border-radius: 6px;
    padding: 2px 8px;
    font-size: 12px;
    cursor: pointer;
    white-space: nowrap;
}

.checklist-collapse-all:hover {
    color: var(--text);
    border-color: var(--border-strong);
}

.checklist-section.is-collapsed.drop-into .checklist-section__title {
    outline: 2px dashed var(--accent);
    outline-offset: 2px;
}

/* Lista unica de pessoas: aceitos e convites pendentes (09/10/2026). */
.checklist-people {
    border: 1px solid var(--border);
    border-radius: 10px;
    margin-bottom: 10px;
}

.checklist-people:empty {
    display: none;
}

.checklist-people .checklist-share-row {
    margin: 0;
    padding: 8px 10px;
}

.checklist-people .checklist-share-row + .checklist-share-row {
    border-top: 1px solid var(--border);
}

.checklist-people__avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    flex: 0 0 28px;
    border-radius: 50%;
    background: var(--accent-soft);
    color: var(--accent);
    font-size: 13px;
}

.checklist-people__pending .checklist-people__avatar {
    background: #fbf1df;
    color: var(--warning);
}

.checklist-people__state {
    display: block;
    font-size: 11px;
    color: var(--text-muted);
}

.checklist-people__pending .checklist-people__state {
    color: var(--warning);
}

.checklist-people .checklist-share-row__name {
    white-space: normal;
}

.checklist-people__level {
    flex: 0 0 140px;
    font-size: 13px;
    color: var(--text-muted);
    padding-left: 10px;
}

/* O botao de revogar ocupa o lugar dos DOIS botoes das linhas de aceitos, para a coluna alinhar. */
.checklist-people__pending .btn--danger {
    margin-left: 40px;
}

/* Historico do checklist (09/10/2026). */
.checklist-entry__title {
    display: flex;
    align-items: flex-start;
    gap: 6px;
}

.checklist-entry__history {
    border: 0;
    background: transparent;
    color: var(--text-muted);
    padding: 0 4px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 12px;
    opacity: 0;
    transition: opacity .12s;
}

.checklist-entry:hover .checklist-entry__history,
.checklist-entry__history:focus-visible {
    opacity: 1;
}

.checklist-entry__history:hover {
    background: var(--surface-sunken);
    color: var(--text);
}

.checklist-history {
    max-height: 65vh;
    overflow-y: auto;
}

.checklist-history__day {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--text-muted);
    margin: 14px 0 6px;
}

.checklist-history__day:first-child {
    margin-top: 0;
}

.checklist-history__list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.checklist-history__item {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    padding: 8px 0;
    border-bottom: 1px solid var(--border);
    font-size: 14px;
}

.checklist-history__item:last-child {
    border-bottom: 0;
}

.checklist-history__icon {
    flex: 0 0 26px;
    height: 26px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--surface-sunken);
    color: var(--text-muted);
    font-size: 13px;
}

.checklist-history__item--success .checklist-history__icon { background: #dcfce7; color: var(--success); }
.checklist-history__item--warning .checklist-history__icon { background: #fbf1df; color: var(--warning); }
.checklist-history__item--danger .checklist-history__icon { background: #fee2e2; color: var(--danger); }

.checklist-history__body {
    flex: 1;
    min-width: 0;
}

.checklist-history__target {
    font-weight: 600;
}

.checklist-history__diff {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 6px;
    margin-top: 4px;
    font-size: 13px;
    color: var(--text-muted);
}

.checklist-history__before {
    text-decoration: line-through;
    white-space: pre-wrap;
}

.checklist-history__after {
    color: var(--text);
    white-space: pre-wrap;
}

.checklist-history__when {
    flex: 0 0 auto;
    font-size: 12px;
    color: var(--text-muted);
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.checklist-history__channel {
    display: block;
    font-size: 10px;
    color: var(--accent);
}

/* O Razor apara o espaco entre o verbo e o alvo da frase do historico. */
.checklist-history__target {
    margin-left: 4px;
}

/* Com o botao Historico, o cabecalho tem cinco botoes: em vez de espremer o titulo em duas linhas,
   a barra desce para baixo dele quando falta largura. */
.checklist-page .page__header {
    flex-wrap: wrap;
    row-gap: 10px;
}

.checklist-page .page__header > div:first-child {
    flex: 1 1 360px;
}

/* Historico: antes/depois em duas linhas, com "ver tudo"; paginacao (09/10/2026). */
.checklist-history__diff > span {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
}

.checklist-history__diff.is-expanded > span {
    display: block;
    -webkit-line-clamp: unset;
    line-clamp: unset;
}

.checklist-history__more {
    border: 0;
    background: transparent;
    color: var(--accent);
    font-size: 12px;
    padding: 2px 0;
    cursor: pointer;
}

.checklist-history__load {
    display: flex;
    justify-content: center;
    margin-top: 12px;
}

.checklist-history__end {
    text-align: center;
    font-size: 12px;
    color: var(--text-muted);
    margin: 12px 0 0;
}

/* Secao concluida (09/10/2026): check no lugar do numero, titulo apagado, contador verde. */
.checklist-section__number--done {
    background: #dcfce7;
    color: var(--success);
}

.checklist-section.is-done .checklist-section__name,
.checklist-section.is-done .checklist-section__title-input {
    color: var(--text-muted);
}

.checklist-section.is-done .checklist-section__count {
    color: var(--success);
    font-weight: 600;
}

/* O check da secao concluida mora junto do contador, a direita (09/10/2026). */
.checklist-section__count {
    display: inline-flex;
    align-items: center;
    gap: 5px;
}

.checklist-section.is-done .checklist-section__number {
    background: #dcfce7;
    color: var(--success);
}
