/* FABIM Controle — views: regras específicas de cada tela.
 * Valores migrados dos antigos styles.css + design-system.css + enterprise.css
 * (propriedade a propriedade, o valor que valia por último na cascata). */
@layer views {
  /* ================= Shell da aplicação ================= */
  .page-shell { min-height: 100vh; padding: 0; }
  .dashboard { min-height: 100vh; }
  .brand { display: flex; align-items: center; justify-content: center; min-width: 0; }
  .brand-logo { display: block; width: 180px; height: auto; }

  #dashboard-view:not([hidden]) {
    min-height: 100vh;
    display: grid;
    grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
    background: var(--fabim-canvas);
  }

  .app-sidebar {
    position: sticky;
    top: 0;
    z-index: 90;
    min-width: 0;
    height: 100vh;
    display: flex;
    flex-direction: column;
    padding: 22px 14px 16px;
    overflow: hidden;
    border-right: 1px solid var(--fabim-line);
    background: var(--app-navy);
    box-shadow: 12px 0 34px rgba(4, 10, 18, 0.12);
  }

  .sidebar-brand {
    min-height: 112px;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 10px;
    padding: 0 12px 22px;
    border-bottom: 1px solid rgba(91, 157, 255, 0.22);
  }

  .sidebar-brand .brand-logo {
    width: 126px;
    max-height: 76px;
    margin-inline: auto;
    object-fit: contain;
    object-position: center;
  }

  .sidebar-brand > span {
    text-align: center;
    width: 100%;
    color: var(--fabim-steel);
    font-size: var(--fs-1);
    font-weight: var(--fw-bold);
    text-transform: uppercase;
    letter-spacing: 0.08em;
  }

  .view-tabs.sidebar-nav {
    width: 100%;
    min-height: 0;
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    align-items: stretch;
    gap: 5px;
    margin: 22px 0 12px;
    padding: 0;
    overflow: auto;
    border: 0;
    background: transparent;
    box-shadow: none;
  }

  .sidebar-nav .view-tab {
    position: relative;
    width: 100%;
    min-height: 44px;
    justify-content: flex-start;
    gap: 12px;
    padding: 9px 12px;
    border: 1px solid transparent;
    border-radius: var(--r-1);
    background: transparent;
    color: #aeb9c0;
    font-size: var(--fs-2);
    font-weight: var(--fw-medium);
    text-align: left;
    white-space: nowrap;
    box-shadow: none;
  }

  .sidebar-nav .view-tab svg {
    width: 18px;
    height: 18px;
    flex: 0 0 18px;
    stroke-width: 1.8;
  }

  .sidebar-nav .view-tab:hover {
    border-color: rgba(91, 157, 255, 0.16);
    background: rgba(255, 255, 255, 0.045);
    color: #ffffff;
    transform: none;
  }

  .sidebar-nav .view-tab.is-active {
    border-color: rgba(91, 157, 255, 0.26);
    background: rgba(91, 157, 255, 0.11);
    color: #ffffff;
    box-shadow: inset 3px 0 0 var(--fabim-bronze);
  }

  .sidebar-nav .view-tab.is-active svg { color: var(--fabim-bronze-strong); }
  .sidebar-nav .view-tab:disabled { cursor: not-allowed; opacity: 0.42; }
  .sidebar-nav .view-tab:disabled:hover { color: #aeb9c0; background: transparent; }

  html.light .app-sidebar { color-scheme: dark; }
  html.light .view-tabs.sidebar-nav { background: transparent; }
  html.light .sidebar-nav .view-tab { background: transparent; color: #aeb9c0; }

  html.light .sidebar-nav .view-tab:hover {
    border-color: rgba(91, 157, 255, 0.16);
    background: rgba(255, 255, 255, 0.045);
    color: #ffffff;
  }

  html.light .sidebar-nav .view-tab.is-active {
    border-color: rgba(91, 157, 255, 0.26);
    background: rgba(91, 157, 255, 0.11);
    color: #ffffff;
  }

  .sidebar-footer {
    min-height: 58px;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px;
    border-top: 1px solid rgba(91, 157, 255, 0.2);
    color: #e6eaed;
  }

  .sidebar-footer strong,
  .sidebar-footer small { display: block; }
  .sidebar-footer strong { font-size: var(--fs-1); }
  .sidebar-footer small { margin-top: 2px; color: var(--fabim-steel); font-size: var(--fs-1); }

  .sidebar-status-dot {
    width: 8px;
    height: 8px;
    flex: 0 0 8px;
    border-radius: var(--r-full);
    background: var(--fabim-success);
    box-shadow: 0 0 0 4px rgba(61, 220, 151, 0.11);
  }

  /* ---- Botao de recolher o menu lateral ---- */
  .sidebar-collapse {
    width: 100%;
    min-height: 40px;
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 10px;
    margin-top: 8px;
    padding: 8px 12px;
    border: 1px solid transparent;
    border-radius: var(--r-1);
    background: transparent;
    color: #aeb9c0;
    font-size: var(--fs-2);
    font-weight: var(--fw-medium);
    cursor: pointer;
  }

  .sidebar-collapse:hover {
    border-color: rgba(91, 157, 255, 0.16);
    background: rgba(255, 255, 255, 0.045);
    color: #ffffff;
    transform: none;
  }

  .sidebar-collapse i,
  .sidebar-collapse svg { width: 18px; height: 18px; flex: 0 0 18px; }

  html.light .sidebar-collapse { background: transparent; color: #aeb9c0; }
  html.light .sidebar-collapse:hover { background: rgba(255, 255, 255, 0.045); color: #ffffff; }

  /* ---- Menu lateral recolhido (estado lembrado em localStorage) ----
   * A largura do sidebar vem do grid de #dashboard-view (var(--sidebar-width)),
   * entao recolher exige sobrescrever a variavel, nao so o width do <aside>. */
  html.nav-collapsed { --sidebar-width: 56px; }

  html.nav-collapsed .app-sidebar { padding-left: 8px; padding-right: 8px; }

  html.nav-collapsed .app-sidebar .sidebar-brand {
    padding-left: 0;
    padding-right: 0;
    align-items: center;
  }

  html.nav-collapsed .app-sidebar .sidebar-brand .brand-logo {
    width: 32px;
    max-width: 32px;
  }

  html.nav-collapsed .app-sidebar .sidebar-brand span,
  html.nav-collapsed .app-sidebar .view-tab span,
  html.nav-collapsed .app-sidebar .sidebar-collapse span,
  html.nav-collapsed .app-sidebar .sidebar-footer { display: none; }

  html.nav-collapsed .app-sidebar .view-tab,
  html.nav-collapsed .app-sidebar .sidebar-collapse {
    justify-content: center;
    padding-left: 0;
    padding-right: 0;
  }

  .app-workspace { min-width: 0; min-height: 100vh; background: var(--fabim-canvas); }

  .topbar {
    position: sticky;
    top: 0;
    z-index: 80;
    width: 100%;
    min-height: var(--workspace-header-height);
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 14px;
    padding: 10px var(--content-gutter);
    border-bottom: 1px solid var(--border-glass);
    background: var(--surface-glass-strong);
    -webkit-backdrop-filter: blur(var(--blur-1));
    backdrop-filter: blur(var(--blur-1));
    box-shadow: 0 5px 22px rgba(4, 10, 18, 0.08);
  }

  .page-context { min-width: 0; }

  .page-context p {
    margin: 0 0 2px;
    color: var(--fabim-bronze);
    font-size: var(--fs-1);
    font-weight: var(--fw-bold);
    line-height: 1.2;
    text-transform: uppercase;
    letter-spacing: 0.07em;
  }

  .page-context h1 {
    margin: 0;
    overflow: hidden;
    color: var(--fabim-text);
    font-size: var(--fs-5);
    font-weight: var(--fw-medium);
    line-height: 1.2;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .account {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    min-height: 42px;
    color: #c5ced7;
  }

  .account button {
    min-width: 38px;
    min-height: 38px;
    border-color: rgba(91, 157, 255, 0.48);
    background: rgba(8, 17, 29, 0.34);
    color: var(--fabim-muted);
    box-shadow: inset 0 1px rgba(255, 255, 255, 0.05);
  }

  .account button:hover {
    border-color: var(--app-bronze);
    background: rgba(91, 157, 255, 0.13);
    color: #ffffff;
    transform: translateY(-1px);
  }

  html.light .account { color: #5f6e7e; }

  html.light .account button {
    border-color: rgba(155, 128, 104, 0.38);
    background: rgba(255, 255, 255, 0.72);
    color: #55636f;
  }

  .account-identity {
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 9px;
    margin-left: 3px;
    padding-left: 4px;
  }

  #user-name {
    max-width: 160px;
    overflow: hidden;
    color: var(--fabim-text);
    font-size: var(--fs-2);
    font-weight: var(--fw-medium);
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .logout-button { min-height: 38px; padding: 7px 11px; }

  .alerts-button span {
    position: absolute;
    top: -6px;
    right: -5px;
    min-width: 18px;
    height: 18px;
    padding: 1px 5px;
    border: 2px solid var(--fabim-surface);
    border-radius: var(--r-full);
    background: var(--fabim-bronze);
    color: var(--fabim-navy-950);
    font-size: var(--fs-1);
    font-weight: var(--fw-strong);
    line-height: 14px;
  }

  .alerts-panel {
    position: absolute;
    top: calc(100% - 4px);
    right: var(--content-gutter);
    z-index: 100;
    width: min(430px, calc(100vw - 32px));
    max-height: min(560px, calc(100vh - 96px));
    padding: 14px;
    overflow: auto;
  }

  .alerts-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 10px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--fabim-line);
  }

  .alerts-panel-header strong { color: var(--fabim-text); }
  .alerts-list { display: grid; gap: 8px; }

  .alert-item {
    display: grid;
    grid-template-columns: 18px minmax(0, 1fr) 24px;
    align-items: center;
    gap: 10px;
    width: 100%;
    min-height: 38px;
    text-align: left;
    border: 1px solid var(--fabim-line);
    border-radius: var(--r-1);
    background: var(--fabim-surface-raised);
    color: var(--fabim-text);
    box-shadow: none;
  }

  /* Emoji picker (estilo WhatsApp) nos campos de mensagem. */
  .emoji-field { position: relative; display: flex; }
  .emoji-field textarea, .emoji-field input { flex: 1; padding-right: 34px; }
  .emoji-trigger {
    position: absolute; right: 6px; bottom: 6px;
    width: 26px; height: 26px; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border: 0; border-radius: 6px; background: transparent;
    color: var(--fabim-muted); cursor: pointer;
  }
  .emoji-field input ~ .emoji-trigger { top: 50%; bottom: auto; transform: translateY(-50%); }
  .emoji-trigger:hover { color: var(--fabim-bronze); background: rgba(91, 157, 255, 0.14); }
  .emoji-trigger svg { width: 18px; height: 18px; }
  #emoji-picker {
    position: fixed; z-index: 130;
    display: grid; grid-template-columns: repeat(8, 1fr); gap: 2px;
    width: 288px; max-height: 220px; overflow-y: auto; padding: 8px;
    border: 1px solid var(--fabim-line); border-radius: 10px;
    background: var(--fabim-surface-raised);
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5);
  }
  .emoji-cell {
    border: 0; background: transparent; cursor: pointer;
    font-size: 18px; line-height: 1; padding: 5px; border-radius: 6px;
  }
  .emoji-cell:hover { background: rgba(91, 157, 255, 0.18); }

  /* Botao GIF (ao lado do emoji) e seletor de GIFs do Giphy. */
  .emoji-field.has-gif textarea, .emoji-field.has-gif input { padding-right: 70px; }
  .gif-trigger {
    position: absolute; right: 36px; bottom: 8px;
    height: 22px; padding: 0 6px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--fabim-line); border-radius: 6px; background: transparent;
    color: var(--fabim-muted); cursor: pointer;
    font-size: 11px; font-weight: 700; letter-spacing: 0.03em; line-height: 1;
  }
  .emoji-field input ~ .gif-trigger { top: 50%; bottom: auto; transform: translateY(-50%); }
  .gif-trigger:hover { color: var(--fabim-bronze); border-color: var(--fabim-bronze); background: rgba(91, 157, 255, 0.14); }

  #gif-picker {
    position: fixed; z-index: 130;
    display: flex; flex-direction: column; gap: 8px;
    width: 320px; padding: 10px;
    border: 1px solid var(--fabim-line); border-radius: 10px;
    background: var(--fabim-surface-raised);
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5);
  }
  .gif-search input {
    width: 100%; padding: 8px 10px;
    border: 1px solid var(--fabim-line); border-radius: 8px;
    background: var(--fabim-surface); color: var(--fabim-text); font-size: 13px;
  }
  .gif-results {
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px;
    max-height: 260px; overflow-y: auto;
  }
  .gif-cell {
    border: 0; padding: 0; background: rgba(255, 255, 255, 0.04);
    border-radius: 6px; overflow: hidden; cursor: pointer; aspect-ratio: 1 / 1;
  }
  .gif-cell img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .gif-cell:hover { outline: 2px solid var(--fabim-bronze); outline-offset: -2px; }
  .gif-msg { grid-column: 1 / -1; padding: 18px 6px; text-align: center; color: var(--fabim-muted); font-size: 13px; }
  .gif-powered { text-align: right; font-size: 10px; color: var(--fabim-muted); letter-spacing: 0.04em; }

  /* GIF dentro de uma mensagem da conversa. */
  .request-message .request-gif {
    max-width: min(260px, 100%); max-height: 240px;
    border-radius: 10px; display: block; margin-top: 2px;
  }

  .alert-item { cursor: pointer; }
  .alert-item:hover { border-color: var(--app-bronze); background: rgba(91, 157, 255, 0.08); color: var(--fabim-text); }
  .alert-item > svg { width: 16px; height: 16px; color: var(--fabim-bronze); }
  /* Botao "marcar como lido" (check) na 3a coluna do alerta. */
  .alert-dismiss {
    display: inline-flex; align-items: center; justify-content: center;
    width: 24px; height: 24px; padding: 0;
    border: 1px solid var(--fabim-line); border-radius: 6px;
    background: transparent; color: var(--fabim-muted); cursor: pointer;
  }
  .alert-dismiss:hover { border-color: var(--app-bronze); color: var(--fabim-bronze); background: rgba(91, 157, 255, 0.12); }
  .alert-dismiss svg { width: 14px; height: 14px; }
  html.light .alert-item { background: #f4f7fa; color: var(--fabim-text); }

  .dashboard-content { width: 100%; max-width: none; margin: 0; padding: 24px var(--content-gutter) 42px; }
  .app-view { width: 100%; min-width: 0; max-width: 1760px; margin: 0 auto; }

  .view-heading {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    min-height: 48px;
    margin: 0 0 16px;
  }

  .view-heading > div:first-child { flex: 1 1 auto; min-width: 0; }

  .view-heading .eyebrow,
  .view-heading h1 {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  .view-heading .muted { margin: 0; color: var(--fabim-muted); font-size: var(--fs-2); }

  .view-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 8px;
  }

  .view-actions .status-message { flex-basis: 100%; }

  /* ================= Login ================= */
  .login-view {
    position: relative;
    isolation: isolate;
    min-height: 100vh;
    display: grid;
    grid-template-columns: minmax(320px, 0.8fr) minmax(420px, 1.2fr);
    grid-template-rows: minmax(0, 1fr);
    align-items: stretch;
    align-content: stretch;
    gap: 22px;
    padding: 0;
    background: var(--fabim-canvas);
  }

  .login-view::before {
    content: "";
    position: absolute;
    z-index: -1;
    inset: 0;
    background: repeating-linear-gradient(90deg, transparent 0 119px, rgba(154, 167, 176, 0.035) 120px);
  }

  .login-view > .brand {
    display: grid;
    place-items: center;
    padding: var(--sp-12);
    background: var(--app-navy);
    border-right: 1px solid var(--fabim-line-strong);
  }

  .login-view .brand-logo {
    width: min(240px, 65%);
    height: auto;
    filter: drop-shadow(0 14px 28px rgba(0, 0, 0, 0.18));
  }

  .login-view .login-form {
    display: grid;
    gap: 17px;
    width: min(410px, calc(100% - 48px));
    align-self: center;
    justify-self: center;
    margin: 0;
    padding: 34px;
    position: relative;
    overflow: hidden;
  }

  .login-form h1 { margin: 3px 0 26px; font-size: var(--fs-6); line-height: 1.2; }
  .login-form label { color: #dce4eb; }
  .login-form select,
  .login-form input { min-height: 46px; border-color: rgba(154, 167, 176, 0.48); }
  .login-form button[type="submit"] { width: 100%; min-height: 44px; margin-top: 8px; }

  html.light .login-view { background: linear-gradient(145deg, #f7f9fc, #e7edf4); }
  html.light .login-form { background: linear-gradient(145deg, #ffffff, #edf2f7); }
  html.light .login-form label { color: #26394e; }

  /* ================= Dashboard (relatório analítico) =================
   * Padrão Navy + Glass (decisão 2026-07-17): o Dashboard abandona a paleta
   * própria (fundo quase preto) e herda os tokens da marca. As variáveis
   * --report-* seguem existindo porque dashboard.js as lê para os gráficos —
   * agora elas apontam para os tokens e mudam sozinhas no tema claro.
   * Os acentos coloridos (azul/teal/roxo/rosa/laranja/verde) permanecem como
   * cores de dado (mesma paleta de people.js), sobre superfícies padrão. */
  .fabim-report-shell {
    --report-surface: var(--fabim-surface);
    --report-surface-2: var(--fabim-surface-soft);
    --report-line: var(--fabim-line);
    --report-text: var(--fabim-text);
    --report-muted: var(--fabim-muted);
    --report-muted-2: var(--app-text-soft);
    --report-blue: #5b9dff;
    --report-teal: #3fbfa8;
    --report-purple: #9d8cf0;
    --report-pink: #d984ab;
    --report-orange: #e09a62;
    --report-green: #5fc57e;
    --report-yellow: #d9bb5c;
    --report-red: #f07178;
    /* Um único tamanho para todos os números grandes de KPI (antes: 42/27/22px). */
    --report-kpi-size: 32px;
    color: var(--fabim-text);
    background: transparent;
  }

  .report-topbar {
    position: sticky;
    top: var(--workspace-header-height);
    z-index: 35;
    min-height: 58px;
    display: grid;
    /* Abas ocupam so a largura do conteudo; o resto sobra para o periodo/botoes
       caberem numa linha so (antes a coluna das abas travava em 680px). */
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: 16px;
    margin: -24px calc(var(--content-gutter) * -1) 24px;
    padding-block: 10px;
    padding-inline: max(var(--content-gutter), calc((100vw - var(--sidebar-width) - 1420px) / 2));
    border-bottom: 1px solid var(--border-glass);
    background: var(--surface-glass-strong);
    -webkit-backdrop-filter: blur(var(--blur-1));
    backdrop-filter: blur(var(--blur-1));
    box-shadow: 0 8px 24px rgba(4, 10, 18, 0.08);
  }

  .report-nav {
    justify-self: start;
    display: grid;
    grid-template-columns: repeat(6, minmax(74px, 1fr));
    gap: 3px;
    width: min(100%, 680px);
    min-width: 0;
    padding: 3px;
    border: 1px solid var(--border-glass);
    border-radius: var(--r-2);
    background: var(--surface-glass);
  }

  .report-nav button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: 34px;
    padding: 5px 10px;
    border: 1px solid transparent;
    border-radius: var(--r-1);
    background: transparent;
    color: var(--fabim-muted);
    box-shadow: none;
    font-size: var(--fs-1);
    font-weight: var(--fw-bold);
    white-space: nowrap;
    transition: color 0.2s, border-color 0.2s, background 0.2s, box-shadow 0.2s, transform 0.2s;
  }

  /* Icone do menu (estilo netlify) tambem no desktop, ao lado do rotulo. */
  .report-nav button i,
  .report-nav button svg {
    flex: 0 0 auto;
    width: 15px;
    height: 15px;
    stroke-width: 2;
  }

  .report-nav button:hover { color: var(--fabim-text); transform: translateY(-1px); }
  .report-nav button:hover svg { transform: scale(1.06); }

  /* Mesma linguagem das abas do resto do sistema: tinta bronze + indicador bronze. */
  .report-nav button.is-active {
    border-color: rgba(91, 157, 255, 0.26);
    background: rgba(91, 157, 255, 0.11);
    color: var(--fabim-text);
    box-shadow: inset 0 -2px 0 var(--fabim-bronze);
  }

  html.light .report-nav button.is-active {
    border-color: rgba(126, 103, 84, 0.32);
    background: rgba(91, 157, 255, 0.18);
  }

  .report-period {
    display: flex;
    align-items: flex-end;
    justify-content: flex-end;
    justify-self: end;
    min-width: 0;
    gap: 7px;
    /* Barra cheia (abas + periodo + Atualizar + Compartilhar): em telas estreitas
       quebra em linha nova; em telas largas fica tudo numa linha (regra abaixo). */
    flex-wrap: wrap;
    row-gap: 8px;
  }

  @media (min-width: 1500px) {
    .report-period { flex-wrap: nowrap; }
  }

  .report-period-badge {
    display: inline-flex;
    align-items: center;
    height: 34px;
    min-height: 30px;
    padding: 5px 9px;
    border: 1px solid var(--report-line);
    border-radius: var(--r-1);
    color: var(--report-muted-2);
    background: var(--report-surface);
    font-size: var(--fs-1);
    font-weight: var(--fw-bold);
    white-space: nowrap;
  }

  .report-period-live {
    border-color: rgba(95, 197, 126, 0.38);
    color: var(--report-green);
    box-shadow: 0 0 14px rgba(95, 197, 126, 0.1);
  }

  .report-period-control { display: flex; align-items: end; gap: 5px; }

  .report-period-control label {
    align-content: end;
    gap: 2px;
    min-width: 100px;
    color: var(--report-muted);
    font-size: var(--fs-1);
  }

  /* Rotulo em cima do badge (Semana / Periodo), no mesmo estilo de De/Ate. */
  .report-period-field {
    display: flex;
    flex-direction: column;
    gap: 2px;
    color: var(--report-muted);
    font-size: var(--fs-1);
  }

  .report-period-control input {
    width: 100px;
    height: 34px;
    min-height: 34px;
    padding: 4px 6px;
    border-color: var(--report-line);
    background: var(--report-surface);
    color: var(--report-text);
    font-size: var(--fs-1);
  }

  .report-period-control button {
    height: 34px;
    min-height: 34px;
    padding: 5px 10px;
    border-radius: var(--r-1);
    font-size: var(--fs-1);
  }

  .report-tab-content { width: min(100%, 1420px); margin: 0 auto; padding: 0; }

  /* Transicao de abas (desktop + mobile): a aba entra com fade+slide suave e os
     cartoes de dentro cascateiam em sequencia, dando um ar moderno de app. */
  .report-tab { animation: report-tab-enter 0.42s cubic-bezier(0.22, 1, 0.36, 1) both; }
  .report-tab > * { animation: report-card-enter 0.5s cubic-bezier(0.22, 1, 0.36, 1) both; }
  .report-tab > *:nth-child(1) { animation-delay: 0.04s; }
  .report-tab > *:nth-child(2) { animation-delay: 0.09s; }
  .report-tab > *:nth-child(3) { animation-delay: 0.14s; }
  .report-tab > *:nth-child(4) { animation-delay: 0.19s; }
  .report-tab > *:nth-child(5) { animation-delay: 0.24s; }
  .report-tab > *:nth-child(n + 6) { animation-delay: 0.28s; }

  @keyframes report-tab-enter {
    from { opacity: 0; transform: translateY(12px) scale(0.99); }
    to { opacity: 1; transform: none; }
  }
  @keyframes report-card-enter {
    from { opacity: 0; transform: translateY(16px); }
    to { opacity: 1; transform: none; }
  }
  @media (prefers-reduced-motion: reduce) {
    .report-tab, .report-tab > * { animation: none; }
  }

  .report-loading,
  .report-empty {
    display: grid;
    min-height: 140px;
    place-items: center;
    color: var(--report-muted);
    font-size: var(--fs-2);
  }

  @keyframes report-rise {
    from { opacity: 0; transform: translateY(9px); }
    to { opacity: 1; transform: translateY(0); }
  }

  .report-hero,
  .report-week-hero {
    position: relative;
    overflow: hidden;
    margin-bottom: 14px;
    padding: 22px;
    border: 1px solid var(--border-glass);
    border-radius: var(--r-2);
    background:
      linear-gradient(115deg, rgba(91, 157, 255, 0.09), transparent 52%),
      var(--surface-glass);
    -webkit-backdrop-filter: blur(var(--blur-1));
    backdrop-filter: blur(var(--blur-1));
    box-shadow: var(--shadow-glass-soft), inset 0 1px rgba(255, 255, 255, 0.04);
  }

  .report-hero::before,
  .report-week-hero::before {
    content: "";
    position: absolute;
    inset: 0 auto 0 0;
    width: 3px;
    background: var(--accent-line);
  }

  .report-hero-row { display: flex; align-items: center; justify-content: space-between; gap: 18px; }

  .report-hero h1,
  .report-week-hero h1 {
    margin: 0 0 5px;
    color: var(--report-text);
    font-size: var(--fs-6);
    font-weight: var(--fw-bold);
    letter-spacing: 0;
  }

  .report-hero p,
  .report-week-hero p { margin: 0; color: var(--report-muted); }

  .report-eyebrow {
    margin: 0 0 7px;
    color: var(--app-bronze);
    font-size: var(--fs-1);
    font-weight: var(--fw-strong);
    letter-spacing: 1px;
    text-transform: uppercase;
  }

  .report-kpi-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin-bottom: 14px; }
  .report-kpi-grid.five { grid-template-columns: repeat(5, minmax(0, 1fr)); }

  /* Card de indicador: superfície neutra, título à esquerda, ícone discreto à
     direita, valor alinhado à esquerda e contexto real abaixo (spec 2026-07). */
  .report-kpi {
    position: relative;
    min-width: 0;
    min-height: 104px;
    display: grid;
    align-content: start;
    gap: 6px;
    overflow: hidden;
    padding: 18px 20px;
    border: 1px solid var(--border-glass);
    border-radius: var(--r-2);
    background: var(--surface-glass);
    -webkit-backdrop-filter: blur(var(--blur-1));
    backdrop-filter: blur(var(--blur-1));
    box-shadow: var(--shadow-glass-soft);
    text-align: left;
    transition: border-color 140ms ease, background-color 140ms ease;
  }

  .report-kpi:hover { border-color: var(--fabim-line-strong); }

  .report-kpi-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-2);
  }

  .report-kpi-label {
    overflow: hidden;
    color: var(--report-muted);
    font-size: var(--fs-1);
    font-weight: var(--fw-medium);
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .report-kpi-icon {
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    flex: 0 0 30px;
    border-radius: var(--r-1);
    color: var(--accent);
    background: var(--accent-soft);
  }

  .report-kpi-icon svg { width: 17px; height: 17px; stroke-width: 1.8; }

  .report-kpi-value,
  .report-kpi strong {
    display: block;
    overflow: hidden;
    color: var(--report-text);
    font-weight: var(--fw-medium);
    font-size: var(--report-kpi-size);
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
    letter-spacing: -0.01em;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .report-kpi-note,
  .report-kpi span:not(.report-kpi-label):not(.report-kpi-icon) { display: block; color: var(--report-muted); font-size: var(--fs-1); }

  .report-kpi small {
    display: inline-flex;
    margin-top: 2px;
    color: var(--report-muted);
    font-size: var(--fs-1);
  }

  /* stretch: os dois cards da linha ficam com a MESMA altura (ex.: ranking =
     altura do grafico de anel ao lado). */
  .report-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; align-items: stretch; margin-bottom: 14px; }
  .report-grid.single { grid-template-columns: minmax(0, 1fr); }

  .report-chart-card,
  .report-panel,
  .report-person-card,
  .report-client-card {
    min-width: 0;
    padding: 20px;
    border: 1px solid var(--border-glass);
    border-radius: var(--r-2);
    background: var(--surface-glass);
    -webkit-backdrop-filter: blur(var(--blur-1));
    backdrop-filter: blur(var(--blur-1));
    box-shadow: var(--shadow-glass-soft);
  }

  .report-chart-card:hover,
  .report-person-card:hover,
  .report-client-card:hover {
    border-color: color-mix(in srgb, var(--card-tint, var(--report-blue)) 45%, var(--report-line));
  }

  .report-chart-title {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 16px;
    color: var(--report-muted-2);
    font-size: var(--fs-1);
    font-weight: var(--fw-strong);
    letter-spacing: 1px;
    text-transform: uppercase;
  }

  .report-chart-title::before {
    content: "";
    width: 4px;
    height: 14px;
    border-radius: var(--r-full);
    background: var(--accent);
  }

  .report-chart-wrap { position: relative; width: 100%; height: 220px; }
  .report-chart-wrap.h160 { height: 160px; }
  .report-chart-wrap.h200 { height: 200px; }
  .report-chart-wrap.h260 { height: 260px; }
  .report-chart-wrap.h300 { height: 300px; }
  .report-chart-wrap canvas { display: block; width: 100% !important; height: 100% !important; }

  .report-legend { display: flex; flex-wrap: wrap; justify-content: center; gap: 7px 12px; margin-top: 12px; }
  .report-legend-item { display: inline-flex; align-items: center; gap: 5px; color: var(--report-muted); font-size: var(--fs-1); }
  .report-legend-item strong { color: var(--report-text); }
  .report-legend-dot { width: 7px; height: 7px; border-radius: var(--r-full); }

  .report-week-number {
    color: var(--accent);
    font-size: var(--report-kpi-size);
    font-weight: var(--fw-strong);
    line-height: 1;
  }

  .report-week-meta { display: flex; align-items: center; gap: 18px; }
  .report-week-badges { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 16px; }

  /* Cabecalho da Semana em duas colunas: meta a esquerda, resumo em cartoes
     neon ocupando o espaco vazio a direita. */
  .report-week-hero--split {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 26px;
    flex-wrap: wrap;
  }
  .report-week-hero-main { min-width: 240px; flex: 1 1 260px; }

  /* Resumo da Semana: uma fileira de cards -> card bronze do S29 + 4 KPIs neon,
     cada um com rotulo em cima e icone no canto. */
  .report-week-summary {
    display: grid;
    grid-template-columns: 1.7fr repeat(4, minmax(0, 1fr));
    gap: 12px;
    margin-bottom: 14px;
  }

  /* Com Folhas concluídas + Folhas por dia são 6 indicadores: viram 3 + 3 e o
     card bronze da semana ocupa as duas linhas na coluna da esquerda. Em uma
     fileira só cada card ficaria com ~140px e a legenda ("69 em 5 dias úteis")
     quebraria em três linhas. */
  .report-week-summary.com-folhas { grid-template-columns: 1.7fr repeat(3, minmax(0, 1fr)); }
  .report-week-summary.com-folhas .report-week-card { grid-row: 1 / span 2; }

  /* O cartao da SEMANA e o titulo da tela, nao mais um KPI entre os outros:
     ele diz DE QUE semana o resto do painel esta falando. Empatado com os
     cinco cards ao lado, a leitura comecava em qualquer lugar -- por isso
     bronze mais forte, moldura mais grossa e o numero bem maior (abaixo). */
  .report-week-card {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 9px;
    min-height: 100px;
    padding: 18px 22px;
    border-radius: var(--r-2);
    border: 2px solid color-mix(in srgb, var(--fabim-bronze) 62%, transparent);
    background:
      radial-gradient(150% 150% at 0% 0%, color-mix(in srgb, var(--fabim-bronze) 24%, transparent), transparent 62%),
      var(--surface-glass);
    box-shadow:
      inset 0 0 0 1px color-mix(in srgb, var(--fabim-bronze) 26%, transparent),
      0 0 26px color-mix(in srgb, var(--fabim-bronze) 24%, transparent);
  }
  .report-week-card-eyebrow {
    color: var(--app-bronze);
    font-size: var(--fs-1);
    font-weight: var(--fw-strong);
    letter-spacing: 1px;
    text-transform: uppercase;
  }
  .report-week-card-body { display: flex; align-items: center; gap: 16px; min-width: 0; }
  /* Tamanho ORIGINAL do numero da semana. Ele chegou a crescer para
     clamp(46px, 6vw, 74px) em 07/08/2026, junto do destaque do cartao -- mas
     esse aumento nao foi pedido e foi desfeito no mesmo dia. O destaque do
     cartao (moldura, brilho, respiro) fica; a fonte volta ao que era. */
  .report-week-card .report-week-number {
    color: var(--fabim-bronze);
    font-size: clamp(30px, 4vw, 44px);
    font-weight: var(--fw-strong);
    line-height: 1;
    letter-spacing: -1px;
    flex: 0 0 auto;
    text-shadow: 0 0 22px color-mix(in srgb, var(--fabim-bronze) 40%, transparent);
  }
  .report-week-card .report-week-card-eyebrow { font-size: var(--fs-2); letter-spacing: 1.6px; }
  .report-week-card-info {
    display: flex;
    flex-direction: column;
    gap: 5px;
    min-width: 0;
    padding-left: 16px;
    border-left: 1px solid var(--border-glass);
  }
  .report-week-card-line {
    display: flex;
    align-items: center;
    gap: 7px;
    color: var(--report-text);
    font-size: var(--fs-2);
    font-weight: var(--fw-bold);
  }
  .report-week-card-line i,
  .report-week-card-line svg { width: 15px; height: 15px; flex: 0 0 auto; color: var(--app-bronze); }
  .report-week-card-people { color: var(--report-muted); font-size: var(--fs-1); font-weight: var(--fw-bold); }

  .report-week-stats {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-content: center;
    gap: 14px;
    flex: 1 1 420px;
    max-width: 600px;
  }

  /* Cartao de estatistica "neon sem exageros": borda e valor com brilho suave
     na cor do indicador, sobre o vidro escuro do painel. Altura uniforme e
     conteudo centralizado para o bloco ficar simetrico ao lado da meta. */
  .report-stat {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 10px;
    min-height: 100px;
    padding: 14px 16px;
    border-radius: var(--r-2);
    border: 1px solid var(--border-glass);
    background: var(--surface-glass);
    box-shadow: var(--shadow-glass-soft);
  }
  .report-stat-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
  .report-stat-head i,
  .report-stat-head svg {
    width: 17px; height: 17px; flex: 0 0 auto;
    color: var(--report-muted);
    opacity: 0.92;
  }
  .report-stat-sub { color: var(--report-muted); font-size: var(--fs-1); font-weight: var(--fw-bold); }
  .report-stat-value {
    color: var(--report-text);
    font-size: var(--fs-6);
    font-weight: var(--fw-medium);
    line-height: 1;
    letter-spacing: -0.4px;
    font-variant-numeric: tabular-nums;
  }
  .report-stat-label {
    color: var(--report-muted);
    font-size: var(--fs-1);
    font-weight: var(--fw-strong);
    letter-spacing: 0.7px;
    text-transform: uppercase;
  }

  /* No claro o brilho fica discreto para nao "estourar" sobre fundo claro. */
  html.light .report-stat-value { color: var(--report-text); }

  @media (max-width: 720px) {
    .report-week-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }

  .report-chip,
  .report-person-chip,
  .report-phase-chip {
    display: inline-flex;
    align-items: center;
    min-height: 24px;
    gap: 5px;
    padding: 3px 8px;
    border: 1px solid var(--report-line);
    border-radius: var(--r-1);
    color: var(--report-muted-2);
    background: color-mix(in srgb, var(--chip-color, var(--report-blue)) 10%, transparent);
    font-size: var(--fs-1);
    font-weight: var(--fw-bold);
  }

  .report-load-list,
  .report-ranking { display: grid; gap: 10px; }

  /* Como os cards da linha tem altura igual (report-grid stretch), centraliza o
     conteudo no eixo vertical em vez de deixar tudo colado no topo. O titulo
     fica no topo; o restante (lista/grafico + legenda) centra no espaco livre. */
  .report-chart-card,
  .report-panel { display: flex; flex-direction: column; }
  .report-panel > .report-load-list,
  .report-panel > .report-ranking { margin-block: auto; }
  .report-chart-card > .report-chart-wrap { margin-top: auto; }
  .report-chart-card > .report-legend,
  .report-chart-card > .report-chart-wrap:last-child { margin-bottom: auto; }

  .report-load-row { display: grid; grid-template-columns: 145px minmax(0, 1fr) 62px 42px; align-items: center; gap: 10px; }

  .report-load-name {
    overflow: hidden;
    color: var(--row-color, var(--report-blue));
    font-size: var(--fs-1);
    font-weight: var(--fw-strong);
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .report-load-track,
  .report-rank-track,
  .report-month-track {
    height: 9px;
    overflow: hidden;
    border-radius: var(--r-1);
    background: color-mix(in srgb, var(--report-line) 58%, transparent);
  }

  .report-load-fill,
  .report-rank-fill,
  .report-month-fill {
    height: 100%;
    border-radius: inherit;
    background: linear-gradient(90deg, color-mix(in srgb, var(--row-color, var(--report-blue)) 60%, transparent), var(--row-color, var(--report-blue)));
    box-shadow: 0 0 12px color-mix(in srgb, var(--row-color, var(--report-blue)) 45%, transparent);
  }

  .report-load-value { color: var(--row-color, var(--report-blue)); font-size: var(--fs-1); font-weight: var(--fw-strong); text-align: right; }
  .report-load-pct { color: var(--report-muted); font-size: var(--fs-1); text-align: right; }

  .report-section-title { display: flex; align-items: end; justify-content: space-between; gap: 14px; margin: 22px 0 10px; }
  .report-section-title h2 { color: var(--report-text); font-size: var(--fs-4); }
  .report-section-title span { color: var(--report-muted); font-size: var(--fs-1); }

  .report-project-list,
  .report-client-list,
  .report-delivery-weeks { display: grid; gap: 9px; }

  .report-project-item {
    display: grid;
    grid-template-columns: 40px minmax(0, 1fr) auto 90px;
    align-items: center;
    gap: 12px;
    padding: 13px 15px;
    border: 1px solid var(--border-glass);
    border-radius: var(--r-1);
    background: var(--surface-glass);
    transition: transform 0.2s, border-color 0.2s;
  }

  .report-project-item:hover {
    transform: translateX(3px);
    border-color: color-mix(in srgb, var(--row-color, var(--report-blue)) 46%, var(--report-line));
  }

  .report-rank-number {
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border: 1px solid color-mix(in srgb, var(--row-color) 40%, var(--report-line));
    border-radius: var(--r-1);
    color: var(--row-color);
    background: color-mix(in srgb, var(--row-color) 12%, transparent);
    font-size: var(--fs-1);
    font-weight: var(--fw-strong);
  }

  .report-project-name,
  .report-client-name {
    overflow: hidden;
    color: var(--report-text);
    font-size: var(--fs-1);
    font-weight: var(--fw-strong);
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .report-project-meta,
  .report-client-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin-top: 5px;
    color: var(--report-muted);
    font-size: var(--fs-1);
  }

  .report-project-hours,
  .report-client-hours { color: var(--row-color, var(--report-blue)); font-size: var(--fs-4); font-weight: var(--fw-strong); text-align: right; }

  .report-new-tag {
    padding: 2px 5px;
    border: 1px solid rgba(95, 197, 126, 0.35);
    border-radius: var(--r-1);
    color: var(--report-green);
    background: rgba(95, 197, 126, 0.08);
    font-size: var(--fs-1);
  }

  .report-person-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
  .report-person-card { --card-tint: var(--person-color, var(--report-blue)); }
  .report-person-header { display: grid; grid-template-columns: 46px minmax(0, 1fr) auto; align-items: center; gap: 12px; }

  /* Pastilha 3D: mesma linguagem dos avatares de Solicitações (cor da pessoa,
   * iniciais em tinta escura — contraste AA garantido em people.js). */
  .report-avatar {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    border: 1px solid rgba(255, 255, 255, 0.35);
    border-radius: var(--r-full);
    color: #0f1b29;
    background:
      linear-gradient(175deg, rgba(255, 255, 255, 0.28), rgba(255, 255, 255, 0) 52%, rgba(0, 0, 0, 0.1)),
      var(--person-color, var(--report-blue));
    box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.35), 0 2px 4px rgba(0, 0, 0, 0.35);
    font-size: var(--fs-3);
    font-weight: var(--fw-strong);
  }

  .report-person-name { color: var(--report-text); font-size: var(--fs-4); font-weight: var(--fw-strong); }
  .report-person-sub { margin-top: 3px; color: var(--report-muted); font-size: var(--fs-1); }
  .report-person-total { color: var(--person-color); font-size: var(--report-kpi-size); font-weight: var(--fw-strong); text-align: right; }
  .report-person-total small { display: block; margin-top: 2px; color: var(--report-muted); font-size: var(--fs-1); font-weight: var(--fw-medium); }

  .report-months { display: grid; grid-template-columns: repeat(auto-fit, minmax(52px, 1fr)); gap: 6px; margin-top: 17px; }

  .report-month {
    min-width: 0;
    padding: 7px;
    border: 1px solid var(--report-line);
    border-radius: var(--r-1);
    background: color-mix(in srgb, var(--report-surface-2) 82%, transparent);
  }

  .report-month span { display: block; overflow: hidden; color: var(--report-muted); font-size: var(--fs-1); text-overflow: ellipsis; white-space: nowrap; }
  .report-month strong { display: block; margin: 4px 0 5px; color: var(--person-color, var(--row-color, var(--report-blue))); font-size: var(--fs-1); }

  .report-divider { height: 1px; margin: 16px 0; background: linear-gradient(90deg, transparent, var(--report-line), transparent); }

  .report-mini-title {
    margin-bottom: 8px;
    color: var(--report-muted);
    font-size: var(--fs-1);
    font-weight: var(--fw-strong);
    letter-spacing: 0.8px;
    text-transform: uppercase;
  }

  .report-phase-list { display: flex; flex-wrap: wrap; gap: 6px; }
  .report-top-projects { display: grid; gap: 7px; }

  .report-rank-row { display: grid; grid-template-columns: minmax(100px, 1.1fr) minmax(80px, 1fr) 48px; align-items: center; gap: 8px; }
  .report-rank-row span { overflow: hidden; color: var(--report-muted-2); font-size: var(--fs-1); text-overflow: ellipsis; white-space: nowrap; }
  .report-rank-row strong { color: var(--person-color, var(--row-color, var(--report-blue))); font-size: var(--fs-1); text-align: right; }

  .report-client-card { --card-tint: var(--row-color, var(--report-blue)); }
  .report-client-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; }

  .report-client-progress { height: 5px; margin: 12px 0; overflow: hidden; border-radius: var(--r-1); background: var(--report-line); }

  .report-client-progress span {
    display: block;
    height: 100%;
    background: linear-gradient(90deg, color-mix(in srgb, var(--row-color) 55%, transparent), var(--row-color));
    box-shadow: 0 0 12px var(--row-color);
  }

  .report-delivery-summary { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 9px; margin-bottom: 14px; }
  .report-delivery-summary .report-kpi { padding: 15px 18px; }

  .report-delivery-week {
    overflow: hidden;
    border: 1px solid var(--border-glass);
    border-radius: var(--r-2);
    background: var(--surface-glass);
    -webkit-backdrop-filter: blur(var(--blur-1));
    backdrop-filter: blur(var(--blur-1));
    box-shadow: var(--shadow-glass-soft);
  }

  /* Faixa de semana: mesma linguagem dos cabeçalhos de painel (tinta bronze sutil). */
  .report-delivery-week-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 13px 16px;
    border-bottom: 1px solid var(--border-glass);
    background: linear-gradient(100deg, rgba(91, 157, 255, 0.09), transparent 55%);
  }

  .report-delivery-week-header strong { color: var(--report-text); font-size: var(--fs-1); }
  .report-delivery-week-header span { color: var(--report-muted); font-size: var(--fs-1); }

  .report-delivery-list { display: grid; }

  /* Correção obrigatória da spec: era 9px. */
  .report-delivery-row {
    display: grid;
    grid-template-columns: 88px minmax(180px, 1.4fr) minmax(120px, 1fr) 72px 72px 60px 105px;
    align-items: center;
    gap: 10px;
    min-height: 44px;
    padding: 8px 14px;
    border-bottom: 1px solid color-mix(in srgb, var(--report-line) 65%, transparent);
    color: var(--report-muted-2);
    font-size: var(--fs-2);
  }

  /* Zebrado translúcido sutil, como as demais tabelas. */
  .report-delivery-row:nth-child(even) { background: var(--zebra-glass); }
  .report-delivery-row:last-child { border-bottom: 0; }
  .report-delivery-row strong { overflow: hidden; color: var(--report-text); text-overflow: ellipsis; white-space: nowrap; }

  .report-status {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    min-width: 92px;
    min-height: 25px;
    padding: 3px 7px;
    border: 1px solid currentColor;
    border-radius: var(--r-1);
    font-weight: var(--fw-strong);
  }

  .report-status b { display: inline-grid; place-items: center; }
  .report-status b svg { width: 14px; height: 14px; }
  .report-status.aprovado { color: var(--fabim-success); background: var(--success-soft); }
  .report-status.pendente { color: var(--fabim-warning); background: var(--warning-soft); }
  .report-status.reprovado { color: var(--fabim-danger); background: var(--danger-soft); }

  /* Tema claro: os acentos de dado (paleta de people.js) sao calibrados para o
   * navy; sobre superficies claras eles reprovariam no AA. Escurece na leitura,
   * sem tocar na fonte da cor (JS segue mandando a mesma cor). */
  html.light .report-kpi strong,
  html.light .report-kpi-value { color: var(--report-text); }
  html.light .report-week-number { color: var(--accent-strong); }
  html.light .report-person-total { color: color-mix(in srgb, var(--person-color, var(--report-blue)) 58%, #16283c); }
  html.light .report-project-hours,
  html.light .report-client-hours,
  html.light .report-load-name,
  html.light .report-load-value,
  html.light .report-rank-number,
  html.light .report-rank-row strong,
  html.light .report-month strong { color: color-mix(in srgb, var(--person-color, var(--row-color, var(--report-blue))) 58%, #16283c); }
  html.light .report-status.aprovado { color: #1c7a44; }
  html.light .report-status.pendente { color: #96660a; }
  html.light .report-status.reprovado { color: #b13a49; }
  html.light .report-period-live { color: #1c7a44; border-color: rgba(28, 122, 68, 0.4); box-shadow: none; }

  /* Lapide: aqui moravam 87 linhas de widgets analiticos do Dashboard
     antigo -- insight-card, dash-row, tbrow, chart-wrap, leg-item,
     dashboard-insights e companhia. O proprio CSS ja os rotulava
     "legados (renderizados por app.js)" e o app.js nao os renderizava
     mais: nenhuma das classes aparecia em JS, HTML, testes ou Python.
     Removidos em 22/08/2026 (auditoria). O risco que eles criavam era
     concreto: `.chart-wrap.h260` era copia exata de `.report-chart-wrap
     .h260`, que e a viva -- quem procurasse a regra do grafico podia
     copiar a que nao pinta nada. */

  /* ================= Consulta ================= */
  .consultation-filters {
    display: grid;
    grid-template-columns: minmax(240px, 1.5fr) repeat(4, minmax(140px, 0.8fr)) auto;
    align-items: end;
    gap: 10px;
    margin-bottom: 18px;
    padding: 14px;
  }

  .project-results { display: grid; gap: 18px; }



  .project-phase-table-wrap { padding: 0; overflow-x: auto; }
  .project-phase-table { min-width: 1100px; }

  .consultation-table th:nth-child(1), .consultation-table td:nth-child(1) { width: 90px; }
  .consultation-table th:nth-child(2), .consultation-table td:nth-child(2) { width: 260px; }
  .consultation-table th:nth-child(3), .consultation-table td:nth-child(3) { width: 190px; }
  .consultation-table th:nth-child(4), .consultation-table td:nth-child(4) { width: 90px; }
  .consultation-table th:nth-child(5), .consultation-table td:nth-child(5),
  .consultation-table th:nth-child(6), .consultation-table td:nth-child(6),
  .consultation-table th:nth-child(7), .consultation-table td:nth-child(7) { width: 120px; }
  /* Coluna "Última OS": 110px cabia so "Sem OS". A OS lida do apontamento vem
     com a marca "(do apontamento)" ao lado, entao a largura sobe -- a tabela ja
     rola na horizontal (min-width 1100px), ninguem perde coluna por isso. */
  .consultation-table th:nth-child(8), .consultation-table td:nth-child(8) { width: 175px; }
  .os-do-apontamento { white-space: nowrap; }
  .os-do-apontamento small { color: var(--muted); font-size: 0.78em; }
  .consultation-table th:nth-child(9), .consultation-table td:nth-child(9) { width: 95px; }

  /* Cabecalho clicavel: ordena asc/desc. A seta some no hover no lado do
     redimensionador, mas o clique no rotulo ordena. */
  /* O cabecalho ordenavel virou regra do sistema (19/08/2026): a Consulta
     monta o <thead> em JS, as demais tabelas o trazem do index.html com
     `data-sort-key`. Um seletor generico atende as duas. */
  th.sortable { cursor: pointer; user-select: none; }
  th.sortable:hover { color: var(--text); }
  th.sortable .sort-ind { font-size: 10px; opacity: 0.9; }
  .consultation-table th.sortable { cursor: pointer; user-select: none; }
  .consultation-table th.sortable .th-sort { display: inline-flex; align-items: center; gap: 5px; }
  .consultation-table th.sortable:hover { color: var(--text); }
  .consultation-table th.is-sorted { color: var(--text); }
  .consultation-table th .sort-ind { font-size: 9px; color: var(--accent); line-height: 1; }

  /* ---- Clicar na fase abre as OS dela (18/08/2026) ----
     A linha mostrava so a ultima OS; aberta, ela se reparte por OS com as
     mesmas colunas de datas e horas. */
  /* ---- Legenda das siglas (19/08/2026) ----
     A primeira versao era uma linha de texto cinza ("Siglas — OS: ... · HE:
     ..."), e ele reagiu na letra: "deixe um layout mais agradavel está feio
     assim". Agora cada sigla e uma PILULA -- a mesma forma que ela tem dentro
     da tabela --, com o nome por extenso ao lado.

     `flex-wrap` e o que segura o cabecalho: sao oito siglas, e sem quebra elas
     esticariam a linha (ou sumiriam) em tela estreita. */
  .siglas-legend {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 14px;
    margin: 8px 0 0;
    font-size: 11px;
    color: var(--muted);
  }
  .siglas-legend span { display: inline-flex; align-items: center; gap: 6px; }
  .siglas-legend b {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 28px;
    padding: 2px 7px;
    border-radius: 999px;
    background: var(--accent-soft);
    color: var(--accent);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.02em;
  }

  /* Tres niveis: projeto (a linha de cima) -> fase -> OS. Os dois de cima sao
     clicaveis e abrem o de baixo. */
  .consulta-projeto-row, .consulta-fase-row { cursor: pointer; }
  .consulta-projeto-row:hover > td,
  .consulta-fase-row:hover > td { background: rgba(91, 157, 255, 0.06); }
  .consulta-projeto-row.is-aberta > td,
  .consulta-fase-row.is-aberta > td { background: rgba(91, 157, 255, 0.09); }
  .consulta-projeto-row:focus-visible,
  .consulta-fase-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
  /* O projeto e o titulo do grupo -- as fases embaixo dele leem como sub-item. */
  .consulta-projeto-row > td:nth-child(2) { font-weight: 600; }
  .consulta-fases-conta { color: var(--muted); }

  /* A seta e um icone lucide, e lucide TROCA o <i> por um <svg> na hora de
     desenhar -- por isso os dois seletores. Estilo so em `i` nao pegaria. */
  .consulta-seta { display: inline-flex; vertical-align: -2px; margin-right: 6px; color: var(--muted); }
  .consulta-seta i, .consulta-seta svg { width: 13px; height: 13px; transition: transform 120ms ease; }
  .consulta-fase-row.is-aberta .consulta-seta i,
  .consulta-fase-row.is-aberta .consulta-seta svg { transform: rotate(90deg); }
  .consulta-fase-row.is-aberta .consulta-seta { color: var(--accent); }

  /* `height` E O QUE MANDA AQUI, nao o padding: `tbody td` (components.css)
     crava `height: 46px` em TODA celula do sistema, e num <td> isso vale como
     altura MINIMA -- sem anular, a expansao nasce com uma faixa vazia por
     baixo da tabelinha. Armadilha ja registrada no projeto. */
  /* A OS e uma linha da PROPRIA tabela, nas mesmas colunas: as datas caem
     debaixo de Inicio/Termino/Entrega e o numero debaixo de Ultima OS, sem
     cabecalho novo. Mais baixa que a linha da fase, para ler como sub-item.

     `height` E O QUE MANDA AQUI, nao o padding: `tbody td` (components.css)
     crava `height: 46px` em TODA celula do sistema, e num <td> isso vale como
     altura MINIMA -- so mexer no padding deixaria a linha nos mesmos 46px.
     Armadilha ja registrada no projeto. */
  .consulta-os-linha > td {
    height: 30px;
    padding-top: 2px;
    padding-bottom: 2px;
    font-size: 11px;
  }
  /* Fundo por TOKEN, nao rgba preto: no tema claro o preto vira uma faixa
     cinza pesada. `--accent-soft` e o mesmo azul da linha aberta.
     A ULTIMA celula de qualquer tabela e coluna FIXA, com fundo proprio
     (`tbody tr:nth-child(odd) td:last-child` e irmas): sem repetir o seletor
     com a classe, a coluna Horas ficava branca no tema claro. */
  .consulta-os-linha > td,
  .consulta-os-linha:hover > td,
  .consultation-table tbody .consulta-os-linha > td:last-child,
  .consultation-table tbody .consulta-os-linha:hover > td:last-child { background: var(--accent-soft); }
  .consulta-os-sem { color: var(--muted); font-style: italic; }

  /* ================= Horas e Entregas ================= */
  .entry-layout {
    display: grid;
    grid-template-columns: minmax(300px, 420px) minmax(0, 1fr);
    gap: var(--sp-6);
    align-items: start;
  }

  .hours-report-layout { display: grid; grid-template-columns: minmax(0, 1fr); }

  .form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 13px; }
  .form-grid label:nth-child(2),
  .form-grid label:nth-child(3),
  .form-field-wide { grid-column: 1 / -1; }

  #time-entry-form .form-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  #time-entry-form .form-grid label { grid-column: auto; }
  #time-entry-form .form-grid label:nth-of-type(1) { grid-column: 1 / -1; }
  #time-entry-form .form-grid label:nth-of-type(2) { grid-column: 1 / 3; }

  #time-entry-form select[name="os"] {
    border-color: var(--fabim-bronze);
    background-color: var(--fabim-navy-700);
    font-weight: var(--fw-bold);
  }

  .password-reset-dialog { width: min(100% - 32px, 420px); }
  .time-entry-dialog { width: min(100% - 32px, 760px); }

  .active-toggle { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; min-height: 40px; }
  .active-toggle input { width: 18px; min-height: 18px; }
  /* A ressalva do checkbox "Usuario ativo" (Task 6, 2026-09-10): explica que
     suspender acesso e desligar sao coisas diferentes. Ocupa a linha inteira
     por baixo do checkbox -- colada ao lado dele ficava espremida. */
  .active-toggle small { flex-basis: 100%; margin-left: 26px; color: var(--fabim-muted); font-weight: var(--fw-normal); }

  /* Desligamento de colaborador (Task 6, 2026-09-10): lista de impacto fixa
     (muted) e lista de avisos da previa (cor de alerta) -- os avisos so
     informam, nunca desabilitam o botao de confirmar. */
  .desligamento-impacto,
  .desligamento-avisos { margin: 0; padding-left: 20px; font-size: var(--fs-2); line-height: 1.5; }
  .desligamento-impacto { color: var(--fabim-muted); }
  .desligamento-avisos { color: var(--fabim-warning); font-weight: var(--fw-medium); }

  /* Horas: mesma receita das Entregas — colunas de dados cabem na largura e a
     coluna Acoes fica fixa (sticky) a direita, sempre visivel. */
  /* Filtros em linha propria, alinhados a esquerda (grudavam no titulo). */
  .entries-panel .table-header { flex-direction: column; align-items: flex-start; gap: var(--sp-3); }
  .entries-panel .filters { justify-content: flex-start; }

  .hours-table { width: 100%; min-width: 0; table-layout: fixed; }
  .hours-table th, .hours-table td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .hours-table td:nth-child(3), .hours-table td:nth-child(4) { min-width: 0; }
  .hours-table th:last-child, .hours-table td:last-child { overflow: visible; }
  /* Coluna Nº: numeracao de linha (tipo Excel) — fundo distinto, compacta, centralizada. */
  .hours-table th.row-id-head, .hours-table td.row-id-cell { text-align: center; padding-left: 6px; padding-right: 6px; }
  .hours-table td.row-id-cell {
    background: var(--sticky-head);
    color: var(--thead-text);
    font-variant-numeric: tabular-nums;
    font-weight: var(--fw-strong);
  }
  /* Numeros com largura fixa (tabular) — horas, PR, OS e datas alinham melhor. */
  .hours-table td, .deliveries-table td { font-variant-numeric: tabular-nums; }
  /* Indices contam a coluna Nº (1a). Redistribuicao de 21/08/2026 (Fabio, na
     letra: "distribua melhor as colunas, de prioridade para o nome do projeto
     e do cliente a coluna de TIPO por exemplo pode ficar o mais justo, deixe
     todas mais justas e priorize o projetista, data projeto e cliente").
     Antes TODAS as colunas tinham largura e a folga da tabela era repartida
     entre todas — as de codigo engordavam e o Projeto cortava em reticencias.
     Agora: pixel FIXO nas colunas de codigo (nunca crescem), porcentagem em
     Projetista/Cliente, e Projeto SEM largura — em table-layout fixed a
     coluna sem largura e quem absorve toda a sobra. */
  .hours-table th:nth-child(1), .hours-table td:nth-child(1) { width: 40px; }   /* Nº */
  .hours-table th:nth-child(2), .hours-table td:nth-child(2) { width: 52px; }   /* Tipo: so o icone (52 = rotulo "TIPO" inteiro) */
  .hours-table th:nth-child(3), .hours-table td:nth-child(3) { width: 10%; }    /* Projetista */
  .hours-table th:nth-child(4), .hours-table td:nth-child(4) { width: 96px; }   /* Data */
  /* Projeto (5): sem largura de proposito — absorve a folga inteira. */
  .hours-table th:nth-child(6), .hours-table td:nth-child(6) { width: 12%; }    /* Cliente */
  .hours-table th:nth-child(7), .hours-table td:nth-child(7) { width: 56px; }   /* PR */
  .hours-table th:nth-child(8), .hours-table td:nth-child(8) { width: 88px; }   /* OS ("OS Especial") */
  /* Larguras medidas no navegador (scrollWidth do cabecalho + 2px): justas
     sem cortar o rotulo em reticencias. */
  .hours-table th:nth-child(9), .hours-table td:nth-child(9) { width: 134px; }  /* Tipo de emissão */
  .hours-table th:nth-child(10), .hours-table td:nth-child(10) { width: 52px; } /* Fase */
  .hours-table th:nth-child(11), .hours-table td:nth-child(11) { width: 64px; } /* Início */
  .hours-table th:nth-child(12), .hours-table td:nth-child(12) { width: 84px; } /* Término */
  .hours-table th:nth-child(13), .hours-table td:nth-child(13) { width: 68px; } /* Horas */
  .hours-table th:nth-child(14), .hours-table td:nth-child(14) { width: 78px; } /* Semana */

  /* ---- Formulario de entrega: layout rico (21/08/2026) -------------------
     Mock do Fabio, na letra: "Eu quero esse layout incluindo os icones".
     Secoes azuis com icone, pares em grade, icones DENTRO de Fase/OS/Data,
     os quatro Sim/Nao em linha e Salvar de largura total. Icones sempre
     dimensionados em i E svg (o lucide troca a tag i por svg). */
  .delivery-form-rico .form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .delivery-form-rico .form-grid label { grid-column: auto; }
  .delivery-form-rico .form-grid label.form-field-wide { grid-column: 1 / -1; }
  .delivery-form-rico .form-grid.entrega-quatro { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .entrega-cabecalho { align-items: flex-start; }
  .entrega-titulo { display: flex; align-items: center; gap: 12px; }
  .entrega-icone {
    display: grid; place-items: center; width: 42px; height: 42px; flex: none;
    border: 1px solid var(--fabim-line-strong); border-radius: 10px;
    color: var(--accent-strong);
    background: color-mix(in srgb, var(--accent-strong) 10%, transparent);
  }
  .entrega-icone i, .entrega-icone svg { width: 20px; height: 20px; }
  #delivery-form-subtitle { margin: 2px 0 0; font-size: var(--fs-2); }
  .secao-entrega {
    display: flex; align-items: center; gap: 8px; margin: 20px 0 12px;
    color: var(--accent-strong); font-size: var(--fs-3); font-weight: var(--fw-bold);
  }
  .secao-entrega i, .secao-entrega svg { width: 16px; height: 16px; flex: none; }
  .campo-com-icone { position: relative; display: block; }
  .campo-com-icone > i, .campo-com-icone > svg {
    position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
    width: 16px; height: 16px; color: var(--accent-strong); pointer-events: none;
  }
  .campo-com-icone input, .campo-com-icone select { width: 100%; padding-left: 38px; }
  .rotulo-com-icone { display: inline-flex; align-items: center; gap: 6px; }
  .rotulo-com-icone i, .rotulo-com-icone svg { width: 14px; height: 14px; flex: none; color: var(--accent-strong); }
  .delivery-form-rico textarea[name="escopo_entrega"] { width: 100%; resize: vertical; font-family: inherit; }
  .delivery-form-rico .entrega-salvar { width: 100%; justify-content: center; margin-top: 18px; }

  /* Entregas: as colunas de dados cabem na largura (reticencias por celula) e a
     coluna Acoes fica fixa (sticky) a direita, sempre visivel. Remove o
     min-width da tabela e de Projeto/Cliente que alargavam demais; NAO usa
     overflow-x hidden (cortava os botoes). */
  .deliveries-table { width: 100%; min-width: 0; table-layout: fixed; }
  .deliveries-table th, .deliveries-table td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .deliveries-table td:nth-child(4), .deliveries-table td:nth-child(5) { min-width: 0; }
  .deliveries-table th:last-child, .deliveries-table td:last-child { overflow: visible; }
  .deliveries-table th:nth-child(1), .deliveries-table td:nth-child(1) { width: 9%; }    /* Status */
  .deliveries-table th:nth-child(2), .deliveries-table td:nth-child(2) { width: 52px; }  /* Email */
  .deliveries-table th:nth-child(3), .deliveries-table td:nth-child(3) { width: 7%; }    /* Data */
  .deliveries-table th:nth-child(4), .deliveries-table td:nth-child(4) { width: 14%; }   /* Projeto */
  .deliveries-table th:nth-child(5), .deliveries-table td:nth-child(5) { width: 12%; }   /* Cliente */
  .deliveries-table th:nth-child(6), .deliveries-table td:nth-child(6) { width: 5%; }    /* PR */
  .deliveries-table th:nth-child(7), .deliveries-table td:nth-child(7) { width: 5%; }    /* OS */
  .deliveries-table th:nth-child(8), .deliveries-table td:nth-child(8) { width: 5%; }    /* Fase */
  .deliveries-table th:nth-child(9), .deliveries-table td:nth-child(9) { width: 5%; }    /* Quadro */
  .deliveries-table th:nth-child(10), .deliveries-table td:nth-child(10) { width: 5%; }  /* Plantas */
  .deliveries-table th:nth-child(11), .deliveries-table td:nth-child(11) { width: 5%; }  /* Detalhes */
  .deliveries-table th:nth-child(12), .deliveries-table td:nth-child(12) { width: 11%; } /* Escopo Entrega */
  .deliveries-table th:nth-child(13), .deliveries-table td:nth-child(13) { width: 5%; }  /* Semana */

  /* Coluna de email: so um icone-botao. */
  /* Dois botoes (e-mail e lista mestra) nesta celula. Sem zerar o
     text-overflow, o ellipsis herdado de `tbody td` cortava o segundo e
     desenhava um "..." no lugar dele. */
  /* Sem min-width aqui: os 80px eram de quando o botao tinha 38px de caixa e
     contradiziam a largura declarada no <th> logo abaixo. Duas regras
     disputando a mesma coluna e receita para a largura nao obedecer. */
  .delivery-email-cell { text-align: center; overflow: visible; text-overflow: clip; white-space: nowrap; }
  .delivery-email-cell .icon-button { display: inline-flex; vertical-align: middle; }
  /* "S32" nao precisa de coluna larga -- o espaco vai para Escopo Entrega. */
  .semana-head { width: 1%; }
  .deliveries-table tbody td:nth-child(13) { width: 1%; white-space: nowrap; }
  .email-send-button i { width: 17px; height: 17px; }
  .email-send-button:not(:disabled) { color: var(--fabim-bronze-strong); }
  .email-send-button:disabled { opacity: 0.35; cursor: not-allowed; }
  /* Estado do envio: ambar = aprovado e ainda nao enviado; verde = ja enviado.
     Usa os tokens da marca (--fabim-warning / --fabim-success) para consistencia. */
  .email-send-button.email-pending { color: var(--fabim-warning); }
  .email-send-button.email-sent { color: var(--fabim-success); }

  /* Editor de destinatarios (Para/Cc) — salvo para todos. */
  .email-recipients-edit-row { display: flex; align-items: center; gap: 10px; margin: 6px 0 2px; flex-wrap: wrap; }
  .email-recipients-edit-row .button-secondary { min-height: 32px; padding: 6px 12px; }
  .email-recipients-editor { display: flex; flex-direction: column; gap: 10px; padding: 12px; margin-top: 8px; border: 1px solid var(--fabim-line); border-radius: var(--r-1); background: var(--fabim-surface-soft); }
  .email-recipients-editor label { display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-1); color: var(--fabim-muted); }
  .email-recipients-editor textarea { width: 100%; resize: vertical; min-height: 48px; font: inherit; padding: 8px; border-radius: var(--r-1); border: 1px solid var(--fabim-line-strong); background: var(--fabim-surface); color: var(--fabim-text); }
  .email-recipients-actions { display: flex; justify-content: flex-end; gap: 8px; }

  /* Modal de confirmacao profissional (centralizado, com logo FABIM). */
  .confirm-dialog { border: none; padding: 0; background: transparent; max-width: min(430px, calc(100vw - 32px)); }
  .confirm-dialog::backdrop { background: rgba(6, 10, 18, 0.62); }
  .confirm-dialog-body {
    background: var(--fabim-surface-raised);
    border: 1px solid var(--fabim-line);
    border-radius: var(--r-2, 16px);
    padding: 30px 28px 24px;
    text-align: center;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
  }
  .confirm-dialog-logo { display: block; height: 42px; width: auto; margin: 0 auto 16px; }
  .confirm-dialog-title { margin: 0 0 8px; font-size: var(--fs-3, 18px); color: var(--fabim-text); }
  .confirm-dialog-message { margin: 0 0 24px; color: var(--fabim-muted); line-height: 1.5; }
  .confirm-dialog-actions { display: flex; justify-content: center; gap: 10px; }
  .confirm-dialog-actions button { min-width: 120px; }
  .confirm-dialog-actions button.danger { background: var(--fabim-danger); border-color: var(--fabim-danger); color: #fff; }

  /* Aviso de projeto que entra em execucao sem Ordem de Servico.
     Segue a casca do confirm-dialog, mas alinhado a esquerda: aqui se LE uma
     lista de projetos, nao uma pergunta curta e centrada. */
  .os-aviso-dialog { border: none; padding: 0; background: transparent; max-width: min(560px, calc(100vw - 32px)); }
  .os-aviso-dialog::backdrop { background: rgba(6, 10, 18, 0.62); }
  .os-aviso-body {
    background: var(--fabim-surface-raised);
    border: 1px solid var(--fabim-line);
    border-radius: var(--r-2, 16px);
    padding: 24px 24px 20px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
  }
  .os-aviso-head { display: flex; align-items: flex-start; gap: var(--sp-3); margin-bottom: var(--sp-4); }
  /* O Lucide troca o <i> por <svg>: dimensionar so `i` nao pega no icone. */
  .os-aviso-head i, .os-aviso-head svg { width: 26px; height: 26px; flex: none; color: var(--fabim-warning, #e0a33a); }
  .os-aviso-head h2 { margin: 0 0 4px; font-size: var(--fs-4, 16px); color: var(--fabim-text); }
  .os-aviso-head p { margin: 0; font-size: var(--fs-2, 13px); }
  /* Lista rolante: dez projetos sem OS nao podem empurrar o botao para fora da tela. */
  .os-aviso-list { display: grid; gap: var(--sp-2); max-height: min(52vh, 420px); overflow-y: auto; }
  .os-aviso-item {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--sp-3); flex-wrap: wrap;
    padding: var(--sp-3); border: 1px solid var(--fabim-line);
    border-radius: var(--r-1, 6px); background: var(--fabim-surface);
  }
  /* Ja comecou: mais grave do que "comeca amanha", e a tela mostra isso. */
  .os-aviso-item.is-atrasado { border-color: var(--fabim-danger); }
  .os-aviso-item-dados { display: grid; gap: 2px; min-width: 180px; }
  .os-aviso-item-dados strong { color: var(--fabim-text); font-size: var(--fs-3, 14px); }
  .os-aviso-item-dados small { color: var(--fabim-muted); font-size: var(--fs-1, 12px); }
  .os-aviso-item.is-atrasado .os-aviso-inicio { color: var(--fabim-danger); }
  .os-aviso-item-acoes { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
  .os-aviso-item-acoes button { font-size: var(--fs-1, 12px); }
  .os-aviso-actions { display: flex; justify-content: flex-end; margin-top: var(--sp-4); }

  /* A PEGADA do pill de acoes: o quanto ele avanca a partir da borda direita da
     linha. Medida no Chrome 151 (4 botoes de 38px + folgas + a etiqueta do dia).
     Eram 6 botoes/305px ate 20/08/2026, quando o olho e o "Revisar folha"
     sairam da linha -- por isso as duas ultimas colunas puderam voltar ao
     tamanho que o CONTEUDO delas pede (110 e 150), em vez dos 135/185 que
     existiam so para hospedar o pill grande
     e usada para dimensionar as duas ultimas colunas do Controle -- ver
     --ctrl-col-exec/--ctrl-col-prog la embaixo. Mora aqui, junto de quem a
     produz, para nao virar um numero solto que ninguem sabe de onde saiu. */
     24/08/2026: entrou o botao de concluir/reabrir a folha (a porta que
     faltava para fechar folha que chega a 100% sem a pergunta aparecer), e a
     pegada subiu de 221 para 263px -- +42px MEDIDOS no Chrome por botao novo
     (38px do .icon-button + os 4px de gap do .ctrl-acoes-pill). Botao novo
     aqui obriga a refazer esta conta; ha teste que quebra de proposito. */
  :root { --ctrl-pill-w: 263px; --ctrl-pill-right: 10px; }

  /* Acoes recolhidas: a coluna colapsa (botoes ficam fora do fluxo) e um
     "pill" com os icones aparece sobreposto a direita ao passar o mouse. */
  .table-row-actions {
    position: absolute;
    /* Continua sendo 10px; virou variavel porque a largura das colunas do
       Controle depende deste numero. O recuo dentro do var() e proposital: se um
       dia a variavel sair de escopo, sem ele a declaracao inteira cairia e o
       pill iria parar na ponta ESQUERDA da linha. */
    right: var(--ctrl-pill-right, 10px);
    top: 50%;
    display: inline-flex;
    gap: 6px;
    padding: 4px 6px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--fabim-surface-raised) 94%, transparent);
    border: 1px solid var(--fabim-line);
    box-shadow: -8px 0 18px rgba(0, 0, 0, 0.28);
    opacity: 0;
    transform: translate(8px, -50%);
    transition: opacity 0.14s ease, transform 0.14s ease;
    pointer-events: none;
  }
  tbody tr:hover .table-row-actions,
  tbody tr:focus-within .table-row-actions { opacity: 1; transform: translate(0, -50%); pointer-events: auto; }
  /* Touch nao tem hover: sem isto o pill fica opacity:0 + pointer-events:none
     para sempre e as acoes da linha sao inalcancaveis no celular (o toque nem
     chega a focar um botao, o pointer-events engole). Custo aceito: no touch
     o pill fica sempre visivel, sobreposto a ponta direita da linha.
     (auditoria 14/08/2026) */
  @media (hover: none) {
    .table-row-actions {
      opacity: 1;
      transform: translate(0, -50%);
      pointer-events: auto;
    }
  }
  .table-row-actions .icon-button.danger { color: var(--fabim-danger); }

  /* Coluna de acoes das Entregas some do fluxo (mais espaco para os dados). */
  .deliveries-table th.row-actions-head { width: 0; min-width: 0; padding: 0; }
  .deliveries-table tbody tr td.delivery-actions-cell,
  .deliveries-table tbody tr:nth-child(odd) td.delivery-actions-cell,
  .deliveries-table tbody tr:hover td.delivery-actions-cell {
    border-left: 0;
    background: transparent;
    box-shadow: none;
    padding: 0;
  }

  /* Padrao UNICO de acoes recolhidas para qualquer tabela (Horas, Equipe, ...).
     O cabecalho colapsa (largura 0) e a celula perde borda/fundo/sombra: os
     botoes viram o "pill" sobreposto (.table-row-actions) que aparece no hover. */
  th.row-actions-head { width: 0; min-width: 0; padding: 0; }
  tbody tr td.row-actions-cell,
  tbody tr:nth-child(odd) td.row-actions-cell,
  tbody tr:nth-child(even) td.row-actions-cell,
  tbody tr:hover td.row-actions-cell {
    border-left: 0;
    background: transparent;
    box-shadow: none;
    padding: 0;
  }

  /* Cada tabela tem regra propria de largura da ultima coluna (:last-child),
     mais especifica que a generica acima. Por isso precisamos forcar o colapso
     por tabela, senao sobra uma coluna vazia depois dos dados (ex.: Horas). */
  .hours-table th.row-actions-head,
  .hours-table td.row-actions-cell,
  .users-table th.row-actions-head,
  .users-table td.row-actions-cell,
  .service-orders-table th.row-actions-head,
  .service-orders-table td.row-actions-cell,
  .revisions-table th.row-actions-head,
  .revisions-table td.row-actions-cell { width: 0; min-width: 0; }

  .service-orders-table tbody tr[data-service-order-id],
  .revisions-table tbody tr[data-service-order-id] { cursor: pointer; }
  .users-table tbody tr[data-user-id] { cursor: pointer; }

  /* Preview do email da entrega (texto + anexo PDF). */
  .email-preview-dialog {
    width: min(900px, calc(100vw - 32px));
    max-height: calc(100vh - 48px);
    padding: 0;
    border: 1px solid var(--fabim-line);
    border-radius: var(--r-1);
    background: var(--fabim-surface);
    color: var(--fabim-text);
    overflow: hidden;
  }
  .email-preview-dialog::backdrop { background: rgba(5, 9, 15, 0.55); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); }
  .email-preview-header,
  .email-preview-footer { display: flex; align-items: center; gap: 16px; padding: 16px 20px; }
  .email-preview-header { justify-content: space-between; border-bottom: 1px solid var(--fabim-line); }
  .email-preview-footer { justify-content: flex-end; border-top: 1px solid var(--fabim-line); }
  .email-preview-header h2 { margin: 0; font-size: var(--fs-3); }
  .email-preview-footer .status-message { margin-right: auto; }
  .email-preview-body { padding: 18px 20px; overflow-y: auto; max-height: calc(100vh - 210px); display: grid; gap: 14px; }
  .email-preview-fields { display: grid; gap: 8px; margin: 0; }
  .email-preview-fields > div { display: grid; grid-template-columns: 84px 1fr; gap: 10px; align-items: baseline; }
  .email-preview-fields dt { color: var(--fabim-muted); text-transform: uppercase; font-size: var(--fs-1); letter-spacing: 0.05em; }
  .email-preview-fields dd { margin: 0; color: var(--fabim-text); overflow-wrap: anywhere; }
  .email-preview-html {
    width: 100%;
    height: 360px;
    border: 1px solid var(--fabim-line);
    border-radius: var(--r-1);
    background: #f4f5f7;
  }
  .email-preview-attach { border: 1px solid var(--fabim-line); border-radius: var(--r-1); overflow: hidden; }
  .email-attach-head { display: flex; align-items: center; gap: 10px; padding: 10px 14px; background: var(--fabim-surface-raised); border-bottom: 1px solid var(--fabim-line); }
  .email-attach-head a { margin-left: auto; color: var(--fabim-bronze-strong); }
  .email-preview-frame { width: 100%; height: 340px; border: 0; background: #fff; }

  #download-backup-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 38px;
    padding: 8px 14px;
    border: 1px solid var(--fabim-line);
    border-radius: var(--r-1);
    background: transparent;
    color: var(--fabim-muted);
    box-shadow: none;
    font: inherit;
    font-size: var(--fs-2);
    font-weight: var(--fw-medium);
    letter-spacing: 0;
    text-decoration: none;
    transition: border-color 160ms ease, background-color 160ms ease, color 160ms ease, box-shadow 160ms ease, transform 160ms ease;
  }

  #download-backup-link:hover {
    border-color: var(--fabim-line-strong);
    background: var(--fabim-surface-soft);
    color: var(--fabim-text);
    transform: translateY(-1px);
  }

  #download-backup-link:active { transform: translateY(0); box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.12); }

  #download-backup-link:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }

  #download-backup-link svg { width: 17px; height: 17px; flex: 0 0 auto; stroke-width: 1.9; }

  .backup-panel {
    margin-top: 22px;
    background:
      linear-gradient(120deg, rgba(91, 157, 255, 0.055), transparent 44%),
      linear-gradient(var(--surface-glass), var(--surface-glass));
  }

  .backup-form { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
  .backup-form .active-toggle { align-self: end; }
  .backup-actions { display: flex; align-items: end; gap: 10px; }
  .backup-status { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; margin: 18px 0 0; }

  .backup-status div {
    padding: 12px;
    border: 1px solid var(--fabim-line);
    border-radius: var(--r-1);
    background: var(--surface-glass);
  }

  .backup-status dt { margin-bottom: 5px; color: var(--app-bronze); font-size: var(--fs-1); font-weight: var(--fw-strong); }
  .backup-status dd { margin: 0; color: var(--fabim-text); font-size: var(--fs-2); overflow-wrap: anywhere; }

  /* ================= Solicitações ================= */
  .requests-layout {
    display: grid;
    grid-template-columns: minmax(320px, 390px) minmax(0, 1fr);
    gap: 18px;
    align-items: start;
  }

  #requests-view > .view-heading { margin-bottom: 20px; }
  #requests-view .entry-form { position: sticky; top: 142px; }

  #requests-view .entries-panel {
    padding: 0;
    border: 0;
    background: transparent;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    box-shadow: none;
  }

  .requests-panel-header { padding: 2px 2px 10px; border-bottom: 1px solid var(--fabim-line); }
  .requests-panel-header > div { display: flex; align-items: center; gap: 12px; }

  .live-state { display: inline-flex; align-items: center; gap: 6px; margin: 2px 0 0; color: var(--fabim-muted); font-size: var(--fs-1); }
  .live-state span { width: 7px; height: 7px; border-radius: var(--r-full); background: #5fc57e; box-shadow: 0 0 9px rgba(95, 197, 126, 0.65); }

  .recipient-field {
    display: grid;
    gap: 9px;
    color: var(--app-text-soft);
    font-size: var(--fs-1);
    font-weight: var(--fw-medium);
  }

  .recipient-field > span { color: var(--fabim-muted); font-size: var(--fs-1); font-weight: var(--fw-medium); }

  .recipient-dropzone {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 8px;
    min-height: 68px;
    padding: 10px;
    border: 1px dashed rgba(91, 157, 255, 0.48);
    border-radius: var(--r-1);
    background: rgba(91, 157, 255, 0.035);
  }

  .recipient-dropzone.is-drag-over,
  .recipient-dropzone.is-dragover { border-style: solid; border-color: var(--app-bronze); background: rgba(91, 157, 255, 0.1); }

  .recipient-placeholder { color: var(--app-muted); font-size: var(--fs-2); }

  .recipient-picker {
    display: flex;
    flex-wrap: wrap;
    gap: 7px;
    background: var(--fabim-surface-raised);
  }

  .requests-list { display: grid; gap: 14px; }
  .request-card { overflow: hidden; }

  .request-card.is-highlighted {
    border-color: var(--app-bronze);
    box-shadow: 0 0 0 2px rgba(91, 157, 255, 0.12), 0 18px 46px rgba(0, 0, 0, 0.2);
  }

  .request-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    padding: 15px 16px;
    border-bottom: 1px solid var(--fabim-line);
    background: linear-gradient(100deg, rgba(91, 157, 255, 0.075), transparent 48%);
  }

  .request-card-title { display: flex; min-width: 0; align-items: center; gap: 10px; }
  .request-card-title > div { min-width: 0; }

  .request-card-title h2 {
    overflow: hidden;
    color: var(--fabim-text);
    font-size: var(--fs-3);
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .request-card-title p { margin: 3px 0 0; color: var(--fabim-muted); font-size: var(--fs-1); }

  .request-card-state { display: grid; align-items: center; justify-items: end; gap: 4px; }
  .request-card-state span { color: var(--fabim-muted); font-size: var(--fs-1); }

  .request-card-state strong {
    padding: 3px 7px;
    border: 1px solid var(--fabim-line-strong);
    border-radius: var(--r-1);
    color: var(--app-bronze);
    background: rgba(91, 157, 255, 0.06);
    font-size: var(--fs-1);
    text-transform: capitalize;
  }

  .request-recipients-summary {
    display: flex;
    align-items: center;
    gap: 7px;
    margin: 0;
    padding: 9px 16px;
    border-bottom: 1px solid var(--fabim-line);
    color: var(--app-text-soft);
    font-size: var(--fs-1);
  }

  .request-recipients-summary svg { width: 15px; height: 15px; color: var(--fabim-bronze); }
  .request-recipients-summary span { color: var(--app-bronze); font-weight: var(--fw-bold); text-transform: uppercase; }

  .request-messages {
    display: grid;
    gap: 9px;
    max-height: 360px;
    overflow: auto;
    padding: 14px 16px;
    background: rgba(4, 10, 18, 0.12);
  }

  .request-message {
    width: min(84%, 720px);
    padding: 10px 12px;
    border: 1px solid var(--fabim-line);
    border-radius: var(--r-1);
    background: var(--fabim-surface-soft);
    color: var(--app-text-soft);
  }

  .request-message.is-own {
    justify-self: end;
    border-color: rgba(91, 157, 255, 0.3);
    background: linear-gradient(145deg, rgba(91, 157, 255, 0.11), rgba(91, 157, 255, 0.045));
  }

  .request-message header {
    display: flex;
    align-items: baseline;
    justify-content: flex-start;
    gap: 12px;
    margin-bottom: 5px;
  }

  .request-message header strong {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .request-message strong { color: var(--fabim-text); font-size: var(--fs-1); }
  .request-message time { color: var(--fabim-muted); font-size: var(--fs-1); white-space: nowrap; }
  .request-message p { margin: 0; color: var(--app-text-soft); font-size: var(--fs-1); white-space: pre-wrap; }

  .request-message-edited {
    flex: 0 0 auto;
    color: var(--fabim-muted);
    font-size: var(--fs-1);
    font-style: normal;
    opacity: 0.75;
  }

  .request-message-actions {
    display: inline-flex;
    flex: 0 0 auto;
    gap: 2px;
    opacity: 0;
    transition: opacity 120ms ease;
  }

  .request-message:hover .request-message-actions,
  .request-message:focus-within .request-message-actions { opacity: 1; }

  @media (hover: none) {
    .request-message-actions { opacity: 1; }
  }

  .request-message-actions button,
  .request-resolve-button,
  .request-delete-button {
    display: inline-grid;
    place-items: center;
    width: 22px;
    min-width: 0;
    min-height: 22px;
    height: 22px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--r-1);
    background: transparent;
    box-shadow: none;
    color: var(--fabim-muted);
    cursor: pointer;
  }

  /* `i, svg` juntos: o Lucide troca o <i> por <svg> depois do render, e regra
     escrita so no `i` nao pega. */
  .request-message-actions button i,
  .request-resolve-button i,
  .request-delete-button i,
  .request-message-actions button svg,
  .request-resolve-button svg,
  .request-delete-button svg { width: 13px; height: 13px; }

  .request-message-actions button:hover,
  .request-resolve-button:hover,
  .request-delete-button:hover {
    border-color: var(--app-line-strong);
    background: rgba(91, 157, 255, 0.1);
    color: var(--fabim-text);
  }

  /* Resolver e a acao BRANDA: verde, e sem o vermelho do apagar logo ao lado. */
  .request-resolve-button:hover {
    border-color: rgba(95, 197, 126, 0.5);
    background: rgba(95, 197, 126, 0.12);
    color: #7fd79a;
  }

  /* Conversa encerrada continua legivel -- ela so saiu da frente. O recuo e de
     cor, nao de opacidade: `opacity` apagaria o texto das mensagens junto. */
  .request-card.is-resolvida .request-card-header h2,
  .request-card.is-resolvida .request-recipients-summary { color: var(--fabim-muted); }

  .request-card-state strong.is-resolvida {
    border-color: rgba(95, 197, 126, 0.45);
    background: rgba(95, 197, 126, 0.1);
    color: #7fd79a;
  }

  /* Os botoes do card em UMA linha. `.request-card-state` e um grid de coluna
     unica: com dois botoes soltos ali o cabecalho virava quatro andares
     (contagem / selo / resolver / apagar) e crescia a altura de todo card.
     Conferido em pixels antes e depois. */
  .request-card-actions { display: flex; align-items: center; gap: 4px; }

  .requests-resolved-toggle {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    color: var(--fabim-muted);
    font-size: var(--fs-1);
    cursor: pointer;
    white-space: nowrap;
  }

  /* O interruptor na ponta oposta do titulo.
     O seletor precisa de DUAS classes: `.entries-panel .table-header` (linha
     1578) manda `flex-direction: column` e ganha de `.requests-panel-header`
     sozinho por especificidade -- nao por ordem. Medido no navegador: com uma
     classe so, o computed continuava `column` e os dois seguiam empilhados.
     `wrap` fica para a tela estreita nao espremer os dois numa linha so. */
  .entries-panel .requests-panel-header {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
  }

  .requests-resolved-toggle input {
    width: 14px;
    min-width: 0;
    height: 14px;
    min-height: 0;
    margin: 0;
    padding: 0;
    accent-color: var(--app-bronze);
    cursor: pointer;
  }

  .request-message-delete:hover,
  .request-delete-button:hover {
    border-color: rgba(216, 96, 106, 0.5);
    background: rgba(216, 96, 106, 0.12);
    color: #f18d95;
  }

  .request-message-actions button:focus-visible,
  .request-delete-button:focus-visible {
    outline: 2px solid var(--app-bronze);
    outline-offset: 1px;
  }

  .request-reply-form {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 8px;
    padding: 12px 16px 15px;
    border-top: 1px solid var(--fabim-line);
  }

  .request-reply-form input { min-height: 38px; }

  html.light .request-messages { background: rgba(26, 45, 65, 0.025); }
  html.light .request-message { background: #f1f5f9; }
  html.light .request-message.is-own { background: linear-gradient(145deg, #f2eae2, #f7f3ee); }

  /* ================= Ordens de Serviço e Revisões ================= */
  .service-order-module { min-width: 0; }

  .service-order-filters {
    display: grid;
    grid-template-columns: minmax(96px, 0.55fr) minmax(190px, 1.35fr) minmax(92px, 0.55fr) minmax(150px, 0.9fr) minmax(168px, 1fr) minmax(126px, 0.72fr) minmax(126px, 0.72fr) auto;
    align-items: end;
    gap: 9px;
    margin-bottom: 14px;
    padding: 14px;
  }

  .service-order-filters .filter-actions { flex-wrap: nowrap; }

  .service-order-list { width: 100%; min-width: 0; }
  .service-order-list .table-header { align-items: center; }
  /* Titulo no padrao das outras abas (tamanho e posicao): herda o h2 base e
     encosta a esquerda, como "Entregas registradas" e "Apontamentos". */
  #service-orders-title { margin-right: auto; }

  .service-order-table-wrap {
    width: 100%;
    max-height: calc(100vh - 300px);
    overflow: auto;
  }

  .revisions-table {
    width: 100%;
    min-width: 100%;
    table-layout: auto;
  }
  /* Layout fixo: a soma das colunas nunca passa de 100% — sem a rolagem
     horizontal piscando quando a largura util muda alguns pixels. */
  .service-orders-table {
    width: 100%;
    min-width: 100%;
    table-layout: fixed;
  }

  /* Mapa POSICIONAL de larguras: cada indice abaixo tem de casar com a ordem
     dos <th> em public/index.html (tabela .service-orders-table) e com a ordem
     dos <td> em prRowMarkup (public/service-orders.js). Ao inserir ou remover
     uma coluna, renumerar este bloco INTEIRO -- o escorregao de um indice nao
     da erro nenhum, so pinta a largura na coluna errada. Guardado por teste em
     tests/test_service_orders_ui.mjs. Acoes e a 13a e nao entra aqui: ela e
     presa pelo :last-child em components.css. */
  /* Larguras MEDIDAS, nao chutadas (02/09/2026, no shell real com o menu de
     236px -- a primeira versao mediu a tabela solta e errou por 144px).
     A necessidade natural de cada coluna, medida com table-layout:auto:
     OS atual 84 | PR 48 | Fase 52 | cada data 84 | Situacao 105 | Status 193
     | Gerada por 104 (o ROTULO, as celulas cortam) | Ultima edicao 132.
     PR, Fase e as datas estavam gordas (82/70/104): apara-las paga quase toda
     a coluna nova. Custo fixo total 956px contra 928px de antes -- 28px por
     uma coluna inteira -- e a fatia elastica de Projeto/Cliente fica nos 38%
     de sempre, senao sao elas que pagam a conta e somem. */
  .service-orders-table th:nth-child(1) { width: 84px; }   /* OS atual */
  .service-orders-table th:nth-child(2) { width: 56px; }   /* PR */
  .service-orders-table th:nth-child(3) { width: 22%; }    /* Projeto */
  .service-orders-table th:nth-child(4) { width: 16%; }    /* Cliente */
  .service-orders-table th:nth-child(5) { width: 56px; }   /* Fase */
  /* As TRES datas com a MESMA largura: mesmo formato (dd/mm/aaaa), e larguras
     diferentes deixariam a linha visualmente torta. */
  .service-orders-table th:nth-child(6),
  .service-orders-table th:nth-child(7),
  .service-orders-table th:nth-child(8) { width: 86px; }   /* Emissão, Início, Término */
  .service-orders-table th:nth-child(9) { width: 106px; }  /* Situação */
  .service-orders-table th:nth-child(10) { width: 160px; } /* Status */
  .service-orders-table th:nth-child(11) { width: 104px; } /* Gerada por */
  .service-orders-table th:nth-child(12) { width: 132px; } /* Última edição */
  /* Projeto/Cliente encolhem com reticencias: sem o minimo generico de 180px
     a tabela cabe na largura e a rolagem horizontal nao fica piscando. */
  .service-orders-table td:nth-child(3),
  .service-orders-table td:nth-child(4) { min-width: 0; }

  .service-order-number strong {
    color: var(--fabim-bronze-strong);
    font-variant-numeric: tabular-nums;
  }

  .service-order-status {
    min-height: 27px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 8px;
    border: 1px solid var(--fabim-line-strong);
    border-radius: var(--r-1);
    background: var(--fabim-surface-raised);
    color: var(--fabim-muted);
    font-size: var(--fs-1);
    font-weight: var(--fw-bold);
    white-space: nowrap;
  }

  /* O rotulo mais longo ("Aguardando aprovacao") pede 193px e a coluna tem
     160 -- e ja transbordava antes da coluna Inicio existir, pintando por cima
     de "Gerada por" (medido em 02/09/2026). Cortar com reticencias resolve sem
     comprar largura; o texto inteiro continua no title da celula. */
  .service-order-status { max-width: 100%; overflow: hidden; }
  .service-order-status > span {
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
  }
  .service-order-status svg { width: 14px; height: 14px; flex: none; }

  .service-order-status.progress,
  .service-order-status.open {
    border-color: color-mix(in srgb, var(--fabim-bronze) 55%, transparent);
    color: var(--fabim-bronze-strong);
  }

  .service-order-status.waiting {
    border-color: rgba(242, 169, 59, 0.56);
    background: rgba(242, 169, 59, 0.09);
    color: var(--fabim-warning);
  }

  .service-order-status.approved {
    border-color: rgba(61, 220, 151, 0.5);
    background: rgba(61, 220, 151, 0.08);
    color: var(--fabim-success);
  }

  .service-order-status.rejected,
  .service-order-status.cancelled {
    border-color: rgba(255, 100, 124, 0.52);
    background: rgba(255, 100, 124, 0.08);
    color: var(--fabim-danger);
  }

  .service-order-empty {
    min-height: 190px;
    display: grid;
    place-items: center;
    align-content: center;
    gap: 7px;
    margin: 0;
    border: 1px dashed var(--fabim-line-strong);
    border-radius: var(--r-1);
    color: var(--fabim-muted);
    text-align: center;
  }

  .service-order-empty[hidden] { display: none; }
  .service-order-empty svg { width: 28px; height: 28px; margin-bottom: 3px; color: var(--fabim-bronze); }
  .service-order-empty strong { color: var(--fabim-text); font-size: var(--fs-2); }
  .service-order-empty span { font-size: var(--fs-1); }

  .service-order-detail {
    inset: 0;
    width: 100vw;
    max-width: 100vw;
    height: 100vh;
    max-height: 100vh;
    margin: 0;
    border-radius: 0;
    background: var(--fabim-surface);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  .service-order-detail-header {
    position: sticky;
    top: 0;
    z-index: 8;
    min-height: 88px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 18px 20px;
    border-bottom: 1px solid var(--fabim-line);
    background: color-mix(in srgb, var(--fabim-surface) 96%, transparent);
    -webkit-backdrop-filter: blur(var(--blur-1));
    backdrop-filter: blur(var(--blur-1));
  }

  .service-order-detail-header .eyebrow { margin-bottom: 4px; }
  .service-order-detail-header h2 { margin: 0; color: var(--fabim-text); font-size: var(--fs-5); }
  .service-order-detail-header .muted { margin: 4px 0 0; font-size: var(--fs-1); }

  .service-order-detail-tools {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
  }

  .service-order-detail-tools .button-secondary { min-height: 36px; padding: 7px 10px; }

  .service-order-detail-content { display: grid; gap: 0; padding: 0 20px 28px; }

  .service-order-detail-section { padding: 20px 0; border-bottom: 1px solid var(--fabim-line); }

  .service-order-detail-section h3 {
    margin: 0 0 12px;
    color: var(--fabim-bronze-strong);
    font-size: var(--fs-1);
    text-transform: uppercase;
    letter-spacing: 0.07em;
  }

  /* OS unificada: Check-in e Check-out lado a lado (cabe no formulario em tela cheia). */
  .service-order-checklists { display: grid; grid-template-columns: 1fr 1fr; gap: 28px; border-bottom: 1px solid var(--fabim-line); }
  .service-order-checklists .checklist-section { border-bottom: none; }

  .service-order-facts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 0; }

  .service-order-facts div {
    min-width: 0;
    padding: 11px;
    border-left: 2px solid var(--fabim-line-strong);
    background: var(--fabim-surface-raised);
  }

  .service-order-facts dt,
  .service-order-facts dd { margin: 0; }

  .service-order-facts dt {
    color: var(--fabim-muted);
    font-size: var(--fs-1);
    font-weight: var(--fw-bold);
    text-transform: uppercase;
  }

  .service-order-facts dd { margin-top: 6px; color: var(--fabim-text); font-size: var(--fs-1); font-weight: var(--fw-medium); }

  /* O `.date-prompt-field` saiu em 20/08/2026 com o diálogo de data inteiro. */

  /* Registros Gerenciais: o tipo etiqueta cada linha da lista, e Horas
     Paradas ganha cor propria porque nao e trabalho -- e ausencia dele. */
  .ctrl-reu-tipo {
    margin: 2px 0 0;
    font-size: 11px;
    font-weight: var(--fw-semibold, 600);
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--fabim-accent, #7aa2f7);
  }

  .ctrl-reu-tipo[data-tipo="horas_paradas"] { color: #e0af68; }

  .ctrl-reu-desc {
    margin: 4px 0 0;
    font-size: 12px;
    line-height: 1.5;
    color: var(--fabim-muted, #9aa5b1);
    white-space: pre-wrap;
  }

  .ctrl-reu-desc strong { font-weight: var(--fw-semibold, 600); }
  .ctrl-reu-desc em { font-style: italic; }
  .ctrl-reu-desc u { text-decoration: underline; }

  .ctrl-reu-descricao textarea { width: 100%; resize: vertical; }

  /* Barra de formatacao do Escopo (N / I / S). O lucide troca o <i> por um
     <svg> ao desenhar, entao o seletor precisa cobrir os dois -- mirar so em
     `i` nao pega nada depois que os icones sao renderizados. */
  .format-toolbar {
    display: flex;
    gap: 4px;
    margin: 4px 0 6px;
  }

  .format-toolbar .format-button {
    min-height: 0;
    width: 26px;
    height: 26px;
    padding: 0;
    border-radius: 6px;
  }

  .format-toolbar .format-button i,
  .format-toolbar .format-button svg {
    width: 14px;
    height: 14px;
  }

  /* O escopo agora chega como HTML (negrito/italico/sublinhado). O
     `white-space: pre-wrap` continua valendo para as quebras de linha. */
  .service-order-scope strong { font-weight: var(--fw-semibold, 600); }
  .service-order-scope em { font-style: italic; }
  .service-order-scope u { text-decoration: underline; }

  .service-order-scope {
    margin: 0;
    color: var(--fabim-text);
    font-size: var(--fs-1);
    line-height: 1.65;
    white-space: pre-wrap;
  }

  .service-order-team { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }

  .service-order-person {
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 9px;
    border: 1px solid var(--fabim-line);
    border-radius: var(--r-1);
    background: var(--fabim-surface-raised);
  }

  .service-order-person > b {
    width: 30px;
    height: 30px;
    flex: 0 0 30px;
    display: grid;
    place-items: center;
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: var(--r-full);
    background:
      linear-gradient(175deg, rgba(255, 255, 255, 0.24), rgba(255, 255, 255, 0) 52%, rgba(0, 0, 0, 0.08)),
      var(--avatar-color, rgba(91, 157, 255, 0.35));
    color: var(--fabim-bronze-strong);
    box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.3), 0 2px 4px rgba(0, 0, 0, 0.3);
    font-size: var(--fs-1);
  }

  .service-order-person strong,
  .service-order-person small {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .service-order-person strong { color: var(--fabim-text); font-size: var(--fs-1); }
  .service-order-person small { margin-top: 2px; color: var(--fabim-muted); font-size: var(--fs-1); }

  .service-order-progress-summary,
  .service-order-loading,
  .service-order-form-placeholder {
    display: flex;
    align-items: center;
    gap: 12px;
    color: var(--fabim-muted);
  }

  .service-order-progress-summary svg,
  .service-order-form-placeholder > svg { width: 28px; height: 28px; color: var(--fabim-bronze); }

  .service-order-progress-summary strong,
  .service-order-progress-summary small { display: block; }
  .service-order-progress-summary strong { color: var(--fabim-text); font-size: var(--fs-1); }
  .service-order-progress-summary small { margin-top: 3px; font-size: var(--fs-1); }

  .service-order-loading { min-height: 240px; justify-content: center; }
  .service-order-loading svg { animation: fabim-spin 900ms linear infinite; }

  @keyframes fabim-spin {
    to { transform: rotate(360deg); }
  }

  .service-order-dialog {
    width: min(940px, calc(100vw - 28px));
    max-height: min(900px, calc(100vh - 28px));
    overflow: hidden;
  }

  .service-order-dialog .form-title-row > div { min-width: 0; }
  .service-order-dialog .form-title-row .eyebrow { margin-bottom: 5px; }

  .service-order-form-placeholder {
    min-height: 190px;
    padding: 24px;
    border: 1px dashed var(--fabim-line-strong);
    border-radius: var(--r-1);
    background: var(--fabim-surface-raised);
  }

  .service-order-form-placeholder p { margin: 5px 0 0; }

  .service-order-dialog .form-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 18px;
  }

  .service-order-dialog .entry-form {
    max-height: calc(100vh - 30px);
    grid-template-rows: auto minmax(0, 1fr) auto;
    overflow: hidden;
  }

  .service-order-dialog .service-order-wizard {
    min-height: 0;
    padding-right: 4px;
    overflow-y: auto;
  }

  /* 12px (era 18px): o Fabio pediu para compactar o vao entre as abas e o
     quadro -- "diminua esses espacos sem grudar" (21/08/2026). O resto do
     vao era a linha de mensagem vazia, tratada logo abaixo. */
  .service-order-wizard { display: grid; gap: 12px; }

  /* A linha de mensagem do assistente: INVISIVEL quando vazia (com min-height
     e os dois gaps ela abria ~54px de vao) e um ALERTA de verdade quando tem
     texto -- "ao tentar avançar sem escopo precisa dar a mensagem de alerta". */
  .service-order-dialog .service-order-form-message { min-height: 0; }
  .service-order-dialog .service-order-form-message:empty { display: none; }
  .service-order-dialog .service-order-form-message.error {
    padding: 10px 12px;
    border-left: 3px solid var(--fabim-danger);
    background: color-mix(in srgb, var(--fabim-danger) 10%, transparent);
    font-size: var(--fs-2);
  }

  .wizard-steps {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1px;
    overflow: hidden;
    border: 1px solid var(--fabim-line-strong);
    border-radius: var(--r-1);
    background: var(--fabim-line);
  }

  /* Abas no layout rico (mock do Fabio, 21/08/2026): número em círculo,
     ícone e rótulo com subtítulo; a ativa fica azul (accent), com o número
     preenchido e a barra embaixo. */
  .wizard-steps button {
    min-height: 58px;
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 10px;
    padding: 8px 14px;
    border: 0;
    border-radius: 0;
    background: var(--fabim-surface-raised);
    color: var(--fabim-muted);
    box-shadow: none;
    font-size: var(--fs-1);
    text-align: left;
  }

  .wizard-steps button .wizard-step-num {
    width: 26px;
    height: 26px;
    flex: none;
    display: grid;
    place-items: center;
    border: 1px solid currentColor;
    border-radius: var(--r-full);
    font-size: var(--fs-1);
  }

  .wizard-steps button i,
  .wizard-steps button svg { width: 16px; height: 16px; flex: none; }

  .wizard-step-rotulo { display: grid; min-width: 0; }
  .wizard-step-rotulo strong,
  .wizard-step-rotulo small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .wizard-step-rotulo strong { font-size: var(--fs-2); }
  .wizard-step-rotulo small { margin-top: 2px; color: var(--fabim-muted); font-size: var(--fs-1); }

  .wizard-steps button.active {
    background: color-mix(in srgb, var(--accent-strong) 9%, var(--fabim-surface-raised));
    color: var(--accent-strong);
    box-shadow: inset 0 -2px var(--accent-strong);
  }

  .wizard-steps button.active .wizard-step-num {
    border-color: var(--accent-strong);
    background: var(--accent-strong);
    color: #fff;
  }

  /* O fluxo de revisão tem duas etapas só. */
  .revision-wizard-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .wizard-panel {
    /* O dialogo tem `max-height` + `overflow: hidden` e o form e um grid: quando
       o conteudo nao cabe, a LINHA do painel e comprimida e o que esta dentro
       escapava para fora da borda, por cima dos botoes. Rolar por dentro e o
       que impede isso -- vale para qualquer passo, nao so o do escopo.
       `min-height: 0` porque o 330px abaixo e piso de conforto, nao pode virar
       trava que impeca a compressao numa tela baixa. */
    overflow: auto;
    min-height: 330px;
    padding: 20px;
    border: 1px solid var(--fabim-line);
    border-radius: var(--r-1);
    background: var(--fabim-surface-soft);
  }

  .wizard-panel[hidden] { display: none; }

  /* Escopo: e um texto LONGO (a solicitacao de revisao vem com varios
     paragrafos). Ficava com a altura de 5 linhas e sem `width`, entao o
     conteudo esticava a caixa para fora do quadro do passo. Agora ocupa a
     largura toda, nasce alto e ROLA por dentro -- o `box-sizing` e o que
     impede o padding de somar por cima dos 100%. */
  .service-order-dialog .wizard-panel textarea {
    width: 100%; box-sizing: border-box;
    /* 220px empurrava o total para alem do dialogo e era o painel que estourava.
       160px cabe com folga; quem precisa de mais arrasta pelo canto (resize) ou
       rola -- e o painel acima nunca deixa vazar. */
    min-height: 160px; max-height: 46vh;
    overflow-y: auto; resize: vertical;
    line-height: 1.5; word-break: break-word;
  }

  /* Revisao (passo 4): o escopo inteiro cabia sem limite e transbordava por
     baixo da borda do quadro, por cima do aviso e dos botoes. Mesma solucao --
     altura maxima e rolagem por dentro do proprio bloco.
     `overscroll-behavior: contain` para a rolagem nao vazar para o dialogo
     quando o texto chega ao fim. */
  /* Aviso que substitui o seletor quando ha uma pessoa so na OS: ela e a
     principal por definicao e nao ha o que escolher. */
  .os-principal-auto {
    display: flex; align-items: center; gap: 9px; margin: 10px 0 0;
    padding: 10px 12px; border-radius: var(--r-1);
    border: 1px solid color-mix(in srgb, var(--fabim-success) 40%, transparent);
    background: color-mix(in srgb, var(--fabim-success) 10%, transparent);
    color: var(--fabim-text); font-size: var(--fs-1); line-height: 1.45;
  }
  .os-principal-auto i, .os-principal-auto svg {
    width: 16px; height: 16px; flex: 0 0 16px; color: var(--fabim-success);
  }

  .wizard-review .wide p {
    max-height: 34vh; overflow-y: auto; overscroll-behavior: contain;
    padding-right: 8px; word-break: break-word;
  }

  .service-order-dialog .two-columns,
  .service-order-detail .two-columns { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .service-order-dialog .three-columns,
  .service-order-detail .three-columns { grid-template-columns: repeat(3, minmax(0, 1fr)); }

  /* A regra generica do .form-grid (labels 2 e 3 atravessam a linha) serve ao
     formulario de entrega; aqui ela EMPILHAVA os grids do wizard e da gaveta
     -- o passo 2 saia com tudo em coluna unica (Fabio, 21/08/2026: "o novo
     registro está com um layout ruim"). Nos grids da OS quem manda e a classe
     two/three-columns; form-field-wide continua atravessando. */
  .service-order-dialog .form-grid label,
  .service-order-detail .form-grid label { grid-column: auto; }
  .service-order-dialog .form-grid label.form-field-wide,
  .service-order-detail .form-grid label.form-field-wide { grid-column: 1 / -1; }

  .project-lookup-toolbar { display: flex; align-items: center; gap: 12px; margin: 12px 0; }

  .project-lookup-results {
    /* 255px: o estado vazio grande (lembrete + círculo de busca + duas
       linhas) cabe inteiro sem rolagem. */
    max-height: 255px;
    overflow: auto;
    border-block: 1px solid var(--fabim-line);
  }

  .project-lookup-result {
    width: 100%;
    min-height: 54px;
    display: grid;
    grid-template-columns: 26px minmax(0, 1fr);
    justify-content: stretch;
    text-align: left;
    border: 0;
    border-bottom: 1px solid var(--fabim-line);
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    color: var(--fabim-text);
  }

  .project-lookup-result:hover,
  .project-lookup-result:focus-visible { background: color-mix(in srgb, var(--fabim-bronze) 9%, transparent); }

  /* Truncar, nao quebrar (Fabio, 16/08/2026: *"na imagem precisa ser truncada
     as linhas"*). Nome de projeto longo quebrava em duas ou tres linhas: o
     cartao crescia e empurrava os resultados seguintes para fora da area
     visivel -- a lista tem `max-height: 235px`, entao o que cresce aqui some
     ali. O nome inteiro continua acessivel no `title` do botao. */
  .project-lookup-result strong,
  .project-lookup-result small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .project-lookup-result small { margin-top: 4px; color: var(--fabim-muted); font-size: var(--fs-1); }
  /* O <span> e ITEM de grid, e item de grid nasce com `min-width: auto`: ele
     se recusa a encolher abaixo do proprio conteudo e o texto vaza para fora
     do botao em vez de truncar. A trilha `minmax(0, 1fr)` acima nao resolve
     isso -- ela governa a COLUNA, nao o item dentro dela. */
  .project-lookup-result > span { min-width: 0; }

  .team-picker { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
  .team-picker h3 { margin: 0; font-size: var(--fs-2); }
  .team-picker > div > .muted { margin: 4px 0 10px; font-size: var(--fs-1); }

  /* Cabeçalho de seção dos passos (layout rico): ícone no quadrado azul
     (reusa o .entrega-icone do formulário de entrega), título azul e
     subtítulo mudo. */
  .wizard-panel .os-secao { display: flex; align-items: center; gap: 12px; margin: 0 0 16px; }
  .wizard-panel .os-secao .entrega-icone { width: 36px; height: 36px; }
  .wizard-panel .os-secao h3 { margin: 0; color: var(--accent-strong); font-size: var(--fs-3); font-weight: var(--fw-bold); }
  .wizard-panel .os-secao p { margin: 3px 0 0; font-size: var(--fs-1); }

  /* Estado vazio grande da busca de projeto (passo 1). */
  .busca-vazia-rica { display: grid; justify-items: center; gap: 4px; padding: 20px 12px 26px; text-align: center; }
  .busca-vazia-rica > span {
    width: 56px; height: 56px; margin-bottom: 8px;
    display: grid; place-items: center;
    border: 1px solid var(--fabim-line-strong); border-radius: var(--r-full);
    background: var(--fabim-surface-raised); color: var(--fabim-muted);
  }
  .busca-vazia-rica > span i, .busca-vazia-rica > span svg { width: 22px; height: 22px; }
  .busca-vazia-rica strong { font-size: var(--fs-2); }
  .busca-vazia-rica p { margin: 0; color: var(--fabim-muted); font-size: var(--fs-1); }

  /* Busca de pessoa (passo 3) e a dica de arraste. */
  .team-busca { display: block; margin: 0 0 10px; }
  .team-dica { display: flex; align-items: center; gap: 7px; margin: 10px 0 0; font-size: var(--fs-1); }
  .team-dica i, .team-dica svg { width: 14px; height: 14px; flex: none; }

  /* Datas da OS agrupadas num quadro próprio (passo 2). */
  .os-datas-grupo { padding: 14px; border: 1px solid var(--fabim-line); border-radius: var(--r-1); background: var(--fabim-surface-raised); }

  /* "Avançar" ao pé da etapa (01/09/2026). O passo Escopo é o mais alto do
     wizard: quem termina de escrever o escopo está no fim da rolagem, longe do
     rodapé do diálogo -- e voltava ao topo procurando como seguir. Mesmo botão
     do rodapé (`data-action="wizard-next"`), só mais perto da mão. */
  .wizard-step-acoes { display: flex; justify-content: flex-end; margin-top: 4px; }

  /* Campo travado cujo valor pode não caber: corta com reticências e o valor
     inteiro fica no `title`. Nunca muda o valor -- só o que se vê. */
  .campo-truncado { text-overflow: ellipsis; overflow: hidden; white-space: nowrap; }

  /* Nota de rodapé de um grupo de campos (ex.: "vêm do Planejamento"). Atravessa
     a linha inteira: dentro de um grid de 3 colunas ela caía numa coluna só e
     quebrava em três linhas. */
  .campo-nota {
    grid-column: 1 / -1;
    display: flex; align-items: center; gap: 6px;
    margin: 2px 0 0; font-size: var(--fs-1);
  }
  .campo-nota i, .campo-nota svg { width: 14px; height: 14px; flex: none; }

  .avatar-pool {
    min-height: 220px;
    max-height: 260px;
    display: grid;
    align-content: start;
    gap: 6px;
    overflow: auto;
    padding: 8px;
    border: 1px dashed var(--fabim-line-strong);
    border-radius: var(--r-1);
    background: var(--fabim-surface-raised);
  }

  .selected-pool {
    border-style: solid;
    border-color: color-mix(in srgb, var(--fabim-bronze) 55%, var(--fabim-line));
  }

  .service-order-avatar {
    width: 100%;
    display: grid;
    grid-template-columns: 34px minmax(0, 1fr) 18px;
    align-items: center;
    gap: 9px;
    padding: 8px;
    text-align: left;
    border: 1px solid var(--fabim-line);
    border-radius: var(--r-1);
    background: var(--fabim-surface-soft);
    color: var(--fabim-text);
    box-shadow: none;
    cursor: grab;
  }

  .service-order-avatar.selected {
    border-color: color-mix(in srgb, var(--fabim-bronze) 62%, var(--fabim-line));
    background: color-mix(in srgb, var(--fabim-bronze) 9%, var(--fabim-surface-soft));
  }

  .service-order-avatar > b {
    width: 34px;
    height: 34px;
    display: grid;
    place-items: center;
    border: 1px solid rgba(255, 255, 255, 0.35);
    border-radius: var(--r-full);
    background:
      linear-gradient(175deg, rgba(255, 255, 255, 0.28), rgba(255, 255, 255, 0) 52%, rgba(0, 0, 0, 0.1)),
      var(--avatar-color, var(--fabim-navy-700));
    color: var(--fabim-bronze-strong);
    box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.3), 0 2px 4px rgba(0, 0, 0, 0.35);
    font-size: var(--fs-1);
  }

  .service-order-avatar strong,
  .service-order-avatar small {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .service-order-avatar small { margin-top: 3px; color: var(--fabim-muted); font-size: var(--fs-1); }
  .service-order-avatar svg { width: 15px; color: var(--fabim-muted); }

  .wizard-review {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    border: 1px solid var(--fabim-line);
  }

  /* Cada cartão do resumo leva o ícone no quadrado azul (layout rico). */
  .wizard-review > div { display: flex; align-items: flex-start; gap: 12px; padding: 15px; border: 1px solid var(--fabim-line); }
  .wizard-review > div > .entrega-icone { width: 34px; height: 34px; flex: none; }
  .wizard-review > div > div { min-width: 0; flex: 1; }
  .wizard-review .wide { grid-column: 1 / -1; }

  .wizard-review small,
  .wizard-review strong { display: block; }

  .wizard-review small {
    margin-bottom: 6px;
    color: var(--fabim-muted);
    font-size: var(--fs-1);
    text-transform: uppercase;
  }

  .wizard-review p,
  .wizard-notice { margin: 0; line-height: 1.55; }

  .wizard-notice {
    display: flex;
    gap: 9px;
    margin-top: 14px;
    padding: 12px;
    border-left: 3px solid var(--accent-strong);
    background: color-mix(in srgb, var(--accent-strong) 8%, transparent);
    color: var(--fabim-muted);
    font-size: var(--fs-1);
  }

  .wizard-notice svg { width: 16px; flex: 0 0 16px; color: var(--accent-strong); }

  /* Aqui moravam sete regras do editor "Pendencias e solucoes" do assistente
     de OS -- o quadro, a lista, a linha de tres colunas e o cabecalho de secao
     (`.section-title-row`, que so existia dentro desse markup). Saíram em
     23/08/2026 com a cadeia de JS que as usava (auditoria 21/08/2026, MEDIO):
     a funcao que montava o editor nunca era chamada, entao nenhum destes
     seletores jamais encontrou um elemento na tela. */

  .service-order-form-message,
  .service-order-detail-message,
  .service-order-drawer-message,
  .revision-file-message {
    min-height: 18px;
    color: var(--fabim-success);
    font-size: var(--fs-1);
  }

  .service-order-form-message.error,
  .service-order-detail-message.error,
  .service-order-drawer-message.error,
  .revision-file-message.error { color: var(--fabim-danger); }

  /* A recusa dentro da gaveta e um ALERTA, nao um sussurro: e ela que explica
     por que "Salvar dados gerenciais" nao gravou. Mesmo desenho da mensagem de
     erro do assistente (.service-order-form-message.error). */
  .service-order-drawer-message { display: block; }
  .service-order-drawer-message:empty { display: none; }
  .service-order-drawer-message.error {
    margin-bottom: 10px;
    padding: 10px 12px;
    border-left: 3px solid var(--fabim-danger);
    background: color-mix(in srgb, var(--fabim-danger) 10%, transparent);
    font-size: var(--fs-2);
  }

  /* Badge de contagem de OS na lista (uma linha por PR). */
  .os-count-badge {
    display: inline-block;
    margin-left: 8px;
    padding: 1px 8px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--fabim-bronze) 22%, transparent);
    color: var(--fabim-bronze-strong);
    font-size: var(--fs-0, 11px);
    font-weight: var(--fw-strong);
    vertical-align: middle;
  }

  /* Barra de abas por OS no detalhe do PR (acumulativo). */
  .service-order-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 0 calc(clamp(24px, 3vw, 52px) * -1);
    padding: 12px clamp(24px, 3vw, 52px);
    border-bottom: 1px solid var(--fabim-line);
    background: var(--fabim-surface-raised);
  }
  .os-tab {
    min-height: 34px;
    padding: 6px 15px;
    border: 1px solid var(--fabim-line);
    border-radius: 999px;
    background: transparent;
    color: var(--fabim-muted);
    font-weight: var(--fw-strong);
    cursor: pointer;
  }
  .os-tab:hover { color: var(--fabim-text); border-color: var(--fabim-line-strong); }
  .os-tab.is-active {
    background: color-mix(in srgb, var(--fabim-bronze) 20%, transparent);
    border-color: var(--fabim-bronze-strong);
    color: var(--fabim-bronze-strong);
  }

  /* Menu unico no topo do detalhe da OS (fixo abaixo do cabecalho). */
  .service-order-detail-toolbar {
    position: sticky;
    top: var(--so-header-h, 96px);
    z-index: 7;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 10px 16px;
    margin: 0 calc(clamp(24px, 3vw, 52px) * -1);
    padding: 12px clamp(24px, 3vw, 52px);
    border-bottom: 1px solid var(--fabim-line);
    background: color-mix(in srgb, var(--fabim-surface) 96%, transparent);
    -webkit-backdrop-filter: blur(var(--blur-1));
    backdrop-filter: blur(var(--blur-1));
  }
  .service-order-detail-toolbar-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
  .service-order-detail-toolbar .button-secondary,
  .service-order-detail-toolbar .toolbar-primary { min-height: 36px; padding: 8px 14px; }
  .service-order-detail-toolbar .toolbar-danger {
    color: var(--fabim-danger);
    border-color: color-mix(in srgb, var(--fabim-danger) 40%, var(--fabim-line));
  }
  .service-order-detail-toolbar .service-order-detail-message { margin: 0; }

  /* Gaveta lateral de edicao dos dados gerenciais. */
  .manager-drawer { position: fixed; inset: 0; z-index: 20; }
  .manager-drawer[hidden] { display: none; }
  .manager-drawer-backdrop {
    position: absolute;
    inset: 0;
    background: color-mix(in srgb, #05090f 60%, transparent);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
  }
  .manager-drawer-panel {
    position: absolute;
    top: 0;
    right: 0;
    height: 100%;
    width: min(540px, 94vw);
    display: flex;
    flex-direction: column;
    background: var(--fabim-surface);
    border-left: 1px solid var(--fabim-line);
    box-shadow: -18px 0 52px rgba(0, 0, 0, 0.4);
    animation: manager-drawer-in 0.18s ease;
  }
  @keyframes manager-drawer-in {
    from { transform: translateX(28px); opacity: 0.35; }
    to { transform: none; opacity: 1; }
  }
  .manager-drawer-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 18px 22px;
    border-bottom: 1px solid var(--fabim-line);
  }
  .manager-drawer-head h3 {
    margin: 0;
    color: var(--fabim-bronze-strong);
    font-size: var(--fs-1);
    text-transform: uppercase;
    letter-spacing: 0.07em;
  }
  .manager-drawer-body {
    display: grid;
    align-content: start;
    gap: 12px;
    padding: 20px 22px 28px;
    overflow-y: auto;
  }

  /* Equipe: uma pessoa por linha para leitura organizada. */
  .service-order-team.service-order-team--rows { grid-template-columns: 1fr; }

  .checklist-table { border: 1px solid var(--fabim-line); }

  /* Tres colunas desde 22/08/2026 (auditoria): Item | Resposta | Respondido
     por. A terceira existe porque a resposta do check-out AFIRMA quem
     verificou ("Coordenador") e qualquer participante podia grava-la sem que a
     tela ou o PDF dissessem quem foi. */
  .checklist-heading,
  .checklist-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 170px 110px;
    align-items: center;
    gap: 12px;
    min-height: 46px;
    padding: 7px 10px;
    border-bottom: 1px solid var(--fabim-line);
  }

  .checklist-heading {
    position: sticky;
    top: 88px;
    z-index: 4;
    min-height: 34px;
    background: var(--fabim-navy-700);
    color: var(--fabim-bronze-strong);
    font-size: var(--fs-1);
    font-weight: var(--fw-strong);
    text-transform: uppercase;
  }

  .checklist-row:nth-child(odd) { background: var(--fabim-surface-raised); }

  .checklist-row > span {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    color: var(--fabim-text);
    font-size: var(--fs-1);
    line-height: 1.45;
  }

  .checklist-row > span b { min-width: 22px; color: var(--fabim-bronze-strong); }

  /* "Respondido por": DEPOIS de `.checklist-row > span` e com a MESMA
     especificidade, de proposito (revisao pre-publicacao, 23/08/2026).

     Escrito como `.checklist-author` (0-1-0) e colocado ANTES, o bloco existia
     e nao fazia efeito nenhum: `.checklist-row > span` (0-2-0) vence por
     especificidade, entao a coluna saia na cor do texto comum em vez do cinza,
     e o `display: flex` de la anulava o `text-overflow` -- o nome longo era
     cortado a seco, sem reticencia.

     `display: block` e o que devolve a reticencia: ellipsis nao vale para
     container flex. Regra existir nao e regra fazer efeito. */
  .checklist-row > .checklist-author {
    display: block;
    color: var(--fabim-muted);
    font-size: var(--fs-1);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .notes-list,
  .revision-editor { display: grid; gap: 8px; margin-bottom: 10px; }

  .note-row {
    display: grid;
    grid-template-columns: 1.3fr 0.8fr 132px 1fr 34px;
    gap: 7px;
    align-items: center;
  }

  .revision-item {
    padding: 14px;
    border: 1px solid var(--fabim-line);
    border-left: 3px solid var(--fabim-bronze);
    border-radius: var(--r-1);
    background: var(--fabim-surface-raised);
  }

  .revision-item > header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 12px;
    color: var(--fabim-bronze-strong);
    font-size: var(--fs-1);
    font-weight: var(--fw-strong);
    text-transform: uppercase;
  }

  .revision-item > header select { width: 170px; }

  .revision-attachment {
    min-height: 52px;
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 10px;
  }

  .revision-attachment img {
    width: 92px;
    height: 62px;
    object-fit: cover;
    border: 1px solid var(--fabim-line-strong);
    border-radius: var(--r-1);
  }

  .service-order-detail.revision-detail { width: min(1520px, calc(100vw - 30px)); }

  .service-order-detail[open].revision-detail {
    inset: 0;
    width: 100vw;
    max-width: none;
    height: 100vh;
    max-height: 100vh;
    margin: 0;
    border: 0;
    border-radius: 0;
    background: var(--fabim-surface);
    box-shadow: none;
  }

  .service-order-detail[open].revision-detail::backdrop {
    background: transparent;
    backdrop-filter: none;
  }

  .service-order-detail[open].revision-detail .service-order-detail-header {
    min-height: 76px;
    padding-inline: clamp(24px, 3vw, 52px);
  }

  .service-order-detail[open].revision-detail .service-order-detail-content {
    padding: 0 clamp(24px, 3vw, 52px) 34px;
  }

  .service-order-detail[open].revision-detail .revision-report {
    margin-inline: calc(clamp(24px, 3vw, 52px) * -1);
  }

  .revision-report {
    margin: 0 -20px;
    border-bottom: 1px solid var(--fabim-line);
    background: var(--fabim-surface-raised);
  }

  .revision-report-header {
    display: grid;
    grid-template-columns: minmax(340px, 1.4fr) minmax(280px, 0.9fr);
    border-bottom: 1px solid var(--fabim-line-strong);
    background: var(--fabim-surface);
  }

  .revision-report-brand {
    min-height: 112px;
    display: flex;
    align-items: center;
    gap: 18px;
    padding: 18px 22px;
    border-right: 1px solid var(--fabim-line-strong);
  }

  .revision-report-brand img {
    width: 112px;
    height: 70px;
    object-fit: contain;
    flex: 0 0 112px;
  }

  .revision-report-brand span,
  .revision-report-brand small,
  .revision-report-brand strong { display: block; }

  .revision-report-brand small {
    margin-bottom: 6px;
    color: var(--fabim-bronze-strong);
    font-size: var(--fs-1);
    font-weight: var(--fw-strong);
    text-transform: uppercase;
  }

  .revision-report-brand strong { color: var(--fabim-text); font-size: var(--fs-5); line-height: 1.2; }

  /* No lugar da legenda: botoes de exportar o Relatorio de Revisoes. */
  .revision-report-exports {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 10px;
    padding: 18px 22px;
  }

  .revision-report-exports .button-secondary { min-height: 40px; padding: 9px 15px; }

  /* Pagina Revisoes: historico por PR (leitura + acesso ao relatorio). */
  .revision-history { display: grid; gap: 16px; }
  .revision-history-group {
    border: 1px solid var(--fabim-line);
    border-radius: var(--r-1);
    background: var(--fabim-surface-raised);
    overflow: hidden;
  }
  .revision-history-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 14px 18px;
    border-bottom: 1px solid var(--fabim-line);
  }
  .revision-history-head strong { color: var(--fabim-text); font-size: var(--fs-3); }
  .revision-history-head small { display: block; margin-top: 2px; color: var(--fabim-muted); }
  .revision-history-total {
    color: var(--fabim-bronze-strong);
    font-size: var(--fs-1);
    font-weight: var(--fw-strong);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    white-space: nowrap;
  }
  .revision-history-list { list-style: none; margin: 0; padding: 0; }
  .revision-history-os {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 11px 18px;
    border-top: 1px solid var(--fabim-line);
  }
  .revision-history-os:first-child { border-top: 0; }
  .revision-history-os.has-rev { cursor: pointer; }
  .revision-history-os.has-rev:hover { background: color-mix(in srgb, var(--fabim-bronze) 9%, transparent); }
  .rev-os-tag { flex: 0 0 auto; min-width: 82px; font-weight: var(--fw-bold); color: var(--fabim-text); }
  .rev-os-meta { flex: 1 1 auto; display: flex; align-items: center; gap: 8px; color: var(--fabim-muted); font-size: var(--fs-1); }
  /* Colunas fixas, nao texto corrido: fase curta ("LO") e longa ("ESTUDO")
     deixavam o "Aprovada" de cada linha num lugar diferente. `minmax(0, ...)`
     no ultimo: sem ele o conteudo define a faixa e a coluna volta a dancar.
     Vale SO na lista do historico: o mesmo `.rev-os-meta` aparece no cabecalho
     de cada OS do relatorio (`.revision-pr-os-head`), e la o conteudo e uma
     frase unica -- em grade ela cairia dentro dos 76px e sairia truncada. */
  .revision-history-os .rev-os-meta {
    display: grid;
    grid-template-columns: 76px 104px minmax(0, 1fr);
  }
  .rev-os-fase, .rev-os-data { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .rev-os-data { font-variant-numeric: tabular-nums; }
  .rev-os-situacao { min-width: 0; display: flex; }
  .rev-os-badge {
    flex: 0 0 auto;
    padding: 3px 10px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--fabim-bronze) 22%, transparent);
    color: var(--fabim-bronze-strong);
    font-size: var(--fs-1);
    font-weight: var(--fw-strong);
  }
  .rev-os-none { flex: 0 0 auto; color: var(--fabim-muted); font-size: var(--fs-1); }
  .revision-history-head { cursor: pointer; }
  .revision-history-head:hover { background: color-mix(in srgb, var(--fabim-bronze) 8%, transparent); }
  /* Sanfona do PR: fechado e o estado inicial. A borda de baixo do cabecalho
     so faz sentido quando ha lista embaixo dele. */
  .revision-history-group:not(.is-aberta) .revision-history-head { border-bottom: 0; }
  .revision-history-head-title { display: flex; align-items: center; gap: 10px; min-width: 0; }
  /* O Lucide troca o <i> por <svg>: dimensionar so `i` nao pega no icone. */
  .revision-history-seta { display: inline-flex; color: var(--fabim-muted); transition: transform 0.15s ease; }
  .revision-history-seta i, .revision-history-seta svg { width: 18px; height: 18px; }
  .revision-history-group.is-aberta .revision-history-seta { transform: rotate(90deg); }
  @media (prefers-reduced-motion: reduce) { .revision-history-seta { transition: none; } }
  .revision-history-head-actions { display: flex; align-items: center; gap: 14px; }
  .revision-history-head-actions .button-secondary { flex: 0 0 auto; min-height: 34px; padding: 7px 12px; }

  /* Relatorio consolidado por PR (dialog): metricas + itens de cada OS. */
  .revision-pr-metrics {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 14px;
    padding: 22px 0;
    border-bottom: 1px solid var(--fabim-line);
  }
  .revision-pr-metrics .metric {
    display: flex;
    flex-direction: column;
    gap: 5px;
    padding: 16px 18px;
    border: 1px solid var(--fabim-line);
    border-radius: var(--r-1);
    background: var(--fabim-surface-raised);
  }
  .revision-pr-metrics .metric-value { color: var(--fabim-text); font-size: var(--fs-5); font-weight: var(--fw-bold); }
  .revision-pr-metrics .metric-label { color: var(--fabim-muted); font-size: var(--fs-1); text-transform: uppercase; letter-spacing: 0.05em; }
  .revision-pr-os { padding: 22px 0; border-bottom: 1px solid var(--fabim-line); }
  .revision-pr-os:last-child { border-bottom: 0; }
  .revision-pr-os-head { display: flex; align-items: center; gap: 14px; margin-bottom: 12px; }
  .revision-pr-os-head strong { color: var(--fabim-text); font-size: var(--fs-3); }
  .revision-pr-os-count { margin-left: auto; color: var(--fabim-bronze-strong); font-weight: var(--fw-strong); white-space: nowrap; }

  .revision-report-meta {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: 1.6fr 0.8fr;
    margin: 0;
    border-top: 1px solid var(--fabim-line);
  }

  .revision-report-meta > div {
    min-width: 0;
    padding: 10px 14px;
    border-right: 1px solid var(--fabim-line);
  }

  .revision-report-meta > div:last-child { border-right: 0; }

  .revision-report-meta dt,
  .revision-report-meta dd { margin: 0; }

  .revision-report-meta dt,
  .revision-report-reference span {
    margin-bottom: 4px;
    color: var(--fabim-muted);
    font-size: var(--fs-1);
    font-weight: var(--fw-strong);
    text-transform: uppercase;
  }

  .revision-report-meta dd {
    color: var(--fabim-text);
    font-size: var(--fs-1);
    font-weight: var(--fw-bold);
    white-space: normal;
    overflow-wrap: anywhere;
  }

  .revision-report-reference {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: 90px minmax(0, 1fr);
    align-items: center;
    gap: 12px;
    min-height: 48px;
    padding: 10px 14px;
    border-top: 1px solid var(--fabim-line);
    border-left: 4px solid var(--fabim-bronze);
  }

  .revision-report-reference span { margin: 0; }

  .revision-report-reference strong {
    overflow: hidden;
    color: var(--fabim-text);
    font-size: var(--fs-1);
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .revision-report-toolbar {
    position: sticky;
    top: 76px;
    z-index: 7;
    min-height: 58px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 10px 20px;
    border-bottom: 1px solid var(--fabim-line);
    background: color-mix(in srgb, var(--fabim-surface-raised) 94%, transparent);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
  }

  .revision-report-toolbar small,
  .revision-report-toolbar strong { display: block; }

  .revision-report-toolbar small {
    margin-bottom: 3px;
    color: var(--fabim-muted);
    font-size: var(--fs-1);
    text-transform: uppercase;
  }

  .revision-report-toolbar strong { color: var(--fabim-text); font-size: var(--fs-2); }

  .revision-grid {
    --revision-columns: 46px minmax(90px, 0.6fr) minmax(170px, 1fr) minmax(250px, 1.55fr) 120px minmax(250px, 1.55fr) 132px 94px 48px;
    max-width: 100%;
    overflow: visible;
    background: var(--fabim-surface);
  }

  .revision-grid-heading,
  .revision-grid-row {
    min-width: 1270px;
    display: grid;
    grid-template-columns: var(--revision-columns);
  }

  .revision-grid-heading {
    position: sticky;
    top: 134px;
    z-index: 5;
    min-height: 40px;
    align-items: center;
    background: var(--fabim-navy-700);
    color: var(--fabim-bronze-strong);
    box-shadow: 0 1px 0 var(--fabim-line-strong);
  }

  .revision-grid-heading span {
    min-width: 0;
    height: 100%;
    display: flex;
    align-items: center;
    padding: 8px 9px;
    border-right: 1px solid var(--fabim-line-strong);
    font-size: var(--fs-1);
    font-weight: var(--fw-strong);
    text-transform: uppercase;
  }

  .revision-grid-row.revision-item {
    padding: 0;
    border: 0;
    border-bottom: 1px solid var(--fabim-line);
    border-radius: 0;
    background: var(--fabim-surface);
  }

  .revision-grid-row.revision-item:nth-child(even) { background: var(--fabim-surface-raised); }

  .revision-grid-cell {
    min-width: 0;
    min-height: 112px;
    display: flex;
    align-items: stretch;
    padding: 8px;
    border-right: 1px solid var(--fabim-line);
  }

  label.revision-grid-cell { margin: 0; }

  .revision-grid-cell > span:not(.revision-no-image),
  .revision-response-date > span { display: none; }

  .revision-grid-cell input,
  .revision-grid-cell textarea,
  .revision-grid-cell select {
    width: 100%;
    min-width: 0;
    margin: 0;
    border-color: transparent;
    background: transparent;
  }

  .revision-grid-cell input:focus,
  .revision-grid-cell textarea:focus,
  .revision-grid-cell select:focus {
    border-color: var(--fabim-bronze);
    background: var(--fabim-surface-soft);
  }

  .revision-grid-cell textarea {
    min-height: 88px;
    resize: vertical;
    line-height: 1.45;
  }

  .revision-sequence,
  .revision-response-date,
  .revision-row-actions,
  .revision-image-cell,
  .revision-status-cell {
    align-items: center;
    justify-content: center;
  }

  .revision-sequence b {
    width: 28px;
    height: 28px;
    display: grid;
    place-items: center;
    border: 1px solid var(--fabim-line-strong);
    border-radius: var(--r-full);
    color: var(--fabim-bronze-strong);
    font-size: var(--fs-1);
  }

  .revision-response-date strong { color: var(--fabim-text); font-size: var(--fs-1); white-space: nowrap; }

  .revision-status-cell select {
    border: 1px solid var(--fabim-line-strong);
    font-weight: var(--fw-strong);
  }

  .revision-status-cell select[data-status="attended"] { border-color: #45bd79; color: #59d990; }
  .revision-status-cell select[data-status="justified"] { border-color: #c8a533; color: #e7c553; }
  .revision-status-cell select[data-status="pending"] { border-color: #d15760; color: #f07b82; }

  .revision-image-cell .revision-attachment {
    width: 100%;
    min-height: 0;
    display: grid;
    grid-template-columns: 1fr auto;
    place-items: center;
    gap: 6px;
    margin: 0;
  }

  .revision-image-preview { grid-column: 1 / -1; }

  .revision-image-preview img {
    width: 82px;
    height: 52px;
    display: block;
    object-fit: cover;
    border: 1px solid var(--fabim-line-strong);
    border-radius: var(--r-1);
  }

  .revision-no-image { grid-column: 1 / -1; color: var(--fabim-muted); font-size: var(--fs-1); }

  .revision-file-button {
    min-height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    margin: 0;
    padding: 5px 7px;
    border: 1px solid var(--fabim-line-strong);
    border-radius: var(--r-1);
    color: var(--fabim-text);
    cursor: pointer;
  }

  .revision-file-button:hover { border-color: var(--fabim-bronze); background: var(--fabim-surface-soft); }
  .revision-file-button svg { width: 13px; height: 13px; }
  .revision-file-button span { font-size: var(--fs-1); }

  .revision-file-button input {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
  }

  .revision-file-message {
    grid-column: 1 / -1;
    width: 100%;
    min-height: 0;
    overflow: hidden;
    text-align: center;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .revision-grid-empty {
    min-width: 100%;
    margin: 0;
    padding: 42px 20px;
    color: var(--fabim-muted);
    text-align: center;
  }


  /* ================= Configurações ================= */
  .settings-layout {
    display: grid;
    grid-template-columns: minmax(260px, 0.72fr) minmax(480px, 1.28fr);
    gap: 18px;
    align-items: start;
  }

  .first-access-notice {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 20px;
    border: 1px solid rgba(91, 157, 255, 0.5);
    background: linear-gradient(145deg, rgba(91, 157, 255, 0.12), rgba(26, 45, 65, 0.76));
    box-shadow: var(--shadow-glass-soft), inset 0 1px rgba(255, 255, 255, 0.05);
  }

  .first-access-notice { grid-column: 1 / -1; }
  .settings-side {
    display: grid;
    gap: 18px;
    align-content: start;
    position: sticky;
    top: calc(var(--workspace-header-height) + 18px);
  }
  .settings-side .settings-form { position: static; }

  .notice-icon {
    display: grid;
    flex: 0 0 38px;
    height: 38px;
    place-items: center;
    border: 0;
    border-radius: var(--r-full);
    color: var(--fabim-warning);
    background: var(--warning-soft);
    box-shadow: none;
    font-size: var(--fs-5);
    font-weight: var(--fw-strong);
  }

  .first-access-notice strong { display: block; margin: 2px 0 7px; color: var(--fabim-text); font-size: var(--fs-4); }
  .first-access-notice p { margin: 0; color: var(--fabim-muted); font-size: var(--fs-1); line-height: 1.55; }

  html.light .first-access-notice { background: linear-gradient(145deg, #fffaf4, #eef3f7); }

  .settings-form { gap: 20px; padding: var(--sp-6); }

  .request-form,
  .settings-form,
  .admin-layout > .entry-form {
    position: sticky;
    top: calc(var(--workspace-header-height) + 18px);
  }

  .settings-profile {
    display: flex;
    align-items: center;
    gap: 13px;
    padding-bottom: 18px;
    border-bottom: 1px solid var(--fabim-line);
  }

  .settings-profile strong { display: block; color: var(--fabim-text); font-size: var(--fs-4); }
  .settings-profile div span { display: block; margin-top: 3px; color: var(--fabim-muted); font-size: var(--fs-1); }

  .password-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .password-grid label:first-child { grid-column: 1 / -1; }
  .password-guidance { margin: -4px 0 0; color: var(--fabim-muted); font-size: var(--fs-1); }

  /* Resposta pontual nas Solicitações. */
  .request-quote {
    display: grid;
    gap: 2px;
    margin: 6px 0 4px;
    padding: 6px 10px;
    border-left: 3px solid var(--fabim-bronze);
    border-radius: 4px;
    background: rgba(91, 157, 255, 0.09);
    font-size: 11px;
  }
  .request-quote b { color: var(--fabim-bronze-strong); }
  .request-quote span { color: var(--fabim-muted); }
  .request-replying-chip {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 8px 0 0;
    padding: 6px 10px;
    border: 1px dashed var(--fabim-line-strong);
    border-radius: 6px;
    color: var(--fabim-muted);
    font-size: 11px;
  }
  .request-replying-chip svg { width: 13px; height: 13px; color: var(--fabim-bronze); }
  .request-replying-cancel {
    margin-left: auto;
    padding: 0 6px;
    border: 0;
    background: transparent;
    color: var(--fabim-muted);
    font-size: 15px;
    cursor: pointer;
  }
  .request-message-reply { color: var(--fabim-muted); }

  /* Checklist somente leitura na aprovação da OS. */
  .checklist-row.readonly { cursor: default; }
  .checklist-answer {
    padding: 3px 10px;
    border-radius: 999px;
    background: rgba(85, 184, 120, 0.16);
    color: #55b878;
    font-size: 11px;
    font-weight: 700;
    white-space: nowrap;
  }
  .checklist-answer.pending { background: rgba(154, 167, 176, 0.14); color: var(--fabim-muted); }

  /* ================= Planejamento de equipe ================= */
  .planning-toolbar {
    display: flex;
    /* Rodada 8: alinhar pela BASE, nao pelo centro -- a etiqueta "Início"
       flutua acima do campo de data e deixava o resto dos botoes uns 8px
       acima da linha do input. Com flex-end os controles (todos ~38-40px)
       ficam com o centro na mesma linha do campo. */
    align-items: flex-end;
    justify-content: flex-start;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 14px;
  }
  .planning-week-nav { display: flex; align-items: end; gap: 8px; }
  .planning-week-nav .button-secondary { min-height: 38px; padding-inline: 10px; }
  .planning-start { display: grid; gap: 4px; font-size: 11px; color: var(--fabim-muted); }
  /* flex:1 -- o bloco ocupa o resto da faixa para o margin-right:auto do
     Ordenar por inicio empurrar o conjunto ate a borda DIREITA (Rodada 8:
     "mantenha somente o seletor de inicio a esquerda e ordenar por inicio"). */
  .planning-tools { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; flex: 1; }
  .planning-tools > #planning-sort-start { margin-right: auto; }
  /* Rodada 8: mesma altura do campo de data (38px) para o centro de TODOS os
     controles cair na mesma linha. So os controles da FAIXA -- os itens do
     menu Mais tambem descendem de .planning-tools e nao podem engordar. */
  /* A altura vai no LABEL do seletor de pessoas (o chip com borda), nao no
     select: a cauda sem @layer crava min-height:0 no select de proposito. */
  .planning-tools > .button-secondary,
  .planning-tool-group > .button-secondary,
  .planning-more > #planning-more-button,
  .planning-tools .planning-person-filter,
  #planning-new-demand { min-height: 38px; }
  /* Botao de filtro ligado ("Projetos do dia"): mesmo realce dos demais
     filtros do sistema, para o usuario ver que o quadro esta reduzido. */
  .planning-tools .button-secondary.is-active {
    background: var(--accent-soft);
    color: var(--accent);
    border-color: var(--accent);
  }
  .planning-tools .button-secondary.is-active i,
  .planning-tools .button-secondary.is-active svg { color: var(--accent); }
  .planning-legend { display: inline-flex; align-items: center; gap: 6px; color: var(--fabim-muted); font-size: 11px; }
  .planning-flag {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    border-radius: 4px;
    font-size: 10px;
    font-weight: 800;
  }
  .planning-flag.alocado { background: rgba(85, 184, 120, 0.18); color: #55b878; }
  .planning-flag.vaga { background: rgba(154, 167, 176, 0.16); color: var(--fabim-muted); }
  .planning-flag.super { background: rgba(216, 92, 92, 0.2); color: #d85c5c; }
  .planning-swatch {
    display: inline-block;
    width: 14px;
    height: 14px;
    border-radius: 4px;
    vertical-align: -2px;
  }
  .planning-swatch.filled { background: rgba(85, 184, 120, 0.6); }
  .planning-swatch.over { background: rgba(216, 92, 92, 0.6); }
  /* Sem folga: a amostra repete o que a celula faz -- fundo vermelho fraco e
     contorno TRACEJADO. E o tracejado que separa "ja alocado" (vazio) do
     "acima da capacidade" (cheio) na propria legenda; sem ele os dois
     quadradinhos sairiam vermelhos iguais e a legenda explicaria duas
     coisas com um simbolo so. */
  .planning-swatch.sem-folga { background: rgba(216, 92, 92, 0.22); border: 1px dashed rgba(216, 92, 92, 0.75); }
  /* Rodada 5 (14/08): a grade tem mais cores que verde/vermelho e a legenda
     nao contava -- as amostras abaixo espelham as celulas reais, so com alfa
     mais forte (as celulas usam ~0.16, invisivel num quadrado de 14px).
     Cada item da legenda carrega a explicacao no title (cursor de ajuda).
     Rodada 6 (14/08): a legenda MUDOU DE LINHA -- foi para o subtitulo da
     view, que ja explicava verde/vermelho em texto corrido e tinha a linha
     quase vazia. La ela cabe em fileira unica com folga, e a barra de botoes
     volta a caber numa linha so em tela cheia (medido: legenda 3x2 na barra
     pedia ~1769px contra ~1747 disponiveis -- quebrava na trave). */
  .planning-subtitle { display: flex; align-items: center; column-gap: 14px; row-gap: 4px; flex-wrap: wrap; }
  /* Respiro proprio entre os itens (o gap 6px da regra base da legenda
     e apertado demais para uma fileira longa). */
  .planning-subtitle .planning-legend { gap: 12px; flex-wrap: wrap; }
  /* Rodada 7: DUAS legendas com titulo proprio -- "Pilulas" e "Datas". As
     mesmas cores dizem coisas diferentes em cada lugar (verde na pilula e
     planejado; verde na data e dia com vaga), entao cada grupo se apresenta. */
  .planning-legend-title {
    font-size: 10px; font-weight: 800; letter-spacing: .06em;
    text-transform: uppercase; color: var(--fabim-muted);
  }
  .planning-subtitle .planning-legend + .planning-legend {
    padding-left: 14px; border-left: 1px solid var(--border);
  }
  /* Amostras do CALENDARIO: mesmos tons dos cabecalhos de data (day-full,
     day-free, day-next-free, today-col, past-day em views.css). */
  .planning-swatch.cal-hoje { background: color-mix(in srgb, var(--sticky-head) 74%, #5b9dff); box-shadow: inset 0 0 0 2px rgba(91, 157, 255, 0.7); }
  .planning-swatch.cal-disponivel { background: color-mix(in srgb, var(--sticky-head) 72%, #55b878); }
  .planning-swatch.cal-indisponivel { background: color-mix(in srgb, var(--sticky-head) 70%, #d85c5c); }
  .planning-swatch.cal-proxima { background: color-mix(in srgb, var(--sticky-head) 68%, #55b878); box-shadow: inset 0 0 0 1px rgba(85, 184, 120, 0.55), 0 0 0 1px rgba(85, 184, 120, 0.45); }
  .planning-swatch.cal-passado { background: color-mix(in srgb, var(--sticky-head) 84%, #9aa7b0); }
  .planning-legend-item { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; cursor: help; line-height: 1.2; }
  /* Amostra um ponto menor que a da LOB do usuario (14px): acompanha o corpo
     de texto do subtitulo. */
  .planning-legend-item .planning-swatch { width: 12px; height: 12px; }
  /* Ambar do real do Controle divergente do planejado (par na pilula). */
  .planning-swatch.real { background: rgba(224, 168, 91, 0.55); }
  /* Ambar de celula mexida e ainda nao salva (outline, como na celula). */
  .planning-swatch.dirty { background: rgba(224, 168, 91, 0.12); outline: 2px solid var(--fabim-warning); outline-offset: -2px; }
  /* Hachura de ferias, mesmo desenho listrado da celula. */
  .planning-swatch.ferias { background: repeating-linear-gradient(-45deg, rgba(154, 167, 176, 0.42) 0 4px, transparent 4px 8px); border: 1px solid rgba(154, 167, 176, 0.35); }
  /* Cinza de projeto concluido (realizado) -- mesmo tom das pilulas travadas
     (tr.planning-person-row.is-locked), com alfa mais forte para a amostra. */
  .planning-swatch.realizado { background: rgba(154, 163, 178, 0.35); border: 1px solid rgba(154, 163, 178, 0.5); }
  /* Violeta de Dia Especial (coluna liberada a mao) -- na legenda de DATAS,
     no mesmo tom do cabecalho (th.planning-day-head.special-day). */
  .planning-swatch.especial { background: color-mix(in srgb, var(--sticky-head) 72%, #a855f7); }
  /* Cabecalho da demanda em card (padrao do mockup): icone + titulo + carga,
   * faixa de status (Meta atingida / Disponível / Estouro) e acoes. */
  .pd-head { display: flex; align-items: center; gap: 10px; }
  .pd-ico {
    width: 38px;
    height: 38px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.12);
    color: #9fb3c8;
    flex: none;
  }
  .pd-ico i { width: 18px; height: 18px; }
  .pd-titles { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
  /* CHIPS ALINHADOS EM TODAS AS RAIAS (19/08/2026). Pedido do Fabio, na letra:
     "deixar os itens de data, status, os fase e carga sempre alinhados em
     todas as raias (...) quando não ter um item ele deixar transparente com
     slot nulo mas o espaço é dele".

     Era `flex`: cada chip encostava no anterior, entao a raia sem OS puxava a
     fase e a carga para a esquerda e nada batia entre as linhas. Agora e um
     GRID de colunas fixas, com cada chip fixado na SUA coluna (regras logo
     abaixo) -- coluna sem chip fica vazia sozinha, sem precisar de placeholder
     no HTML.

     Alinhar tudo pela DIREITA foi descartado: esta celula tem colspan de todos
     os dias do quadro, entao a direita fica a metros do nome e fora da vista.
     O nome tem largura fixa justamente para que a primeira pilula comece no
     mesmo ponto em toda raia; nome comprido ganha reticencias (o completo fica
     no title). */
  /* Em cima, so o NOME (19/08/2026): "nada ficará ao lado do nome". */
  .pd-title-line { display: flex; align-items: center; min-width: 0; }
  .pd-title-line > strong {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* Canto SUPERIOR DIREITO: so os botoes, encostados no FIM DA PAGINA
     (19/08/2026, na letra: "todos os botões de cima alinhar totalmente ... com
     o fim da pagina"). A celula da raia tem colspan de todos os dias e e mais
     larga que a tela, entao `margin-left: auto` sozinho jogaria os botoes para
     fora da vista: `position: sticky; right: 0` os prende na borda VISIVEL,
     onde eles ficam a um clique em qualquer rolagem. */
  /* A celula da raia tem colspan de todos os dias e fica `sticky left: 0`:
     ela e larguissima, e o "fim" dela esta a milhares de pixels da vista.
     Por isso o cabecalho da raia usa a LARGURA VISIVEL do quadro
     (`--pd-vw`, escrita por planning.js e atualizada no resize) -- so assim
     "totalmente a direita" quer dizer a direita que ele enxerga. */
  .pd-head, .pd-meta { width: var(--pd-vw, 100%); max-width: 100%; }
  .pd-right {
    margin-left: auto;
    display: flex;
    align-items: center;
  }
  .pd-right .planning-demand-actions { margin-top: 0; }
  /* O chevron da raia tambem nascia com `margin-left: auto` (regra propria dele,
     de quando era o unico item da direita). Com os dois empurrando, o espaco
     livre era DIVIDIDO entre eles e sobrava uma folga entre "Arquivar" e o
     chevron. Zerado aqui, quem empurra e so o `.pd-right`: os botoes encostam
     na direita e o chevron fica colado no ultimo deles -- pedido dele em
     19/08/2026: "alinhe o arquivar ao lado do botão de recolher na direita,
     quero todos os conjuntos daqueles botões 100% alinhado a direita". */
  .pd-head .pd-chevron { margin-left: 0; }

  /* Situacao, OS e fase acompanham a linha "Demanda / Recurso" (19/08/2026:
     "andamento os07 e lo podem ficar ao lado de demanda"). */
  /* Segunda linha da raia: "Demanda / Fase", a OS e a fase, e entao a palavra
     "Status" abrindo a pilula da situacao -- desenho dele em 19/08/2026. O
     rotulo existe porque "ANDAMENTO" sozinho, solto ao lado de duas pilulas
     azuis, nao diz de que ele esta falando. */
  .pd-sub { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
  .pd-sub-rotulo { margin-left: 8px; color: var(--muted); }

  /* Canto INFERIOR ESQUERDO: data, situacao, OS, fase, carga e a faixa de
     bateria/folhas/produtividade -- nesta ordem, em COLUNAS FIXAS para que a
     mesma informacao caia no mesmo ponto em todas as raias (era o pedido
     original: "sempre alinhados em todas as raias (...) quando não ter um item
     ele deixar transparente com slot nulo mas o espaço é dele"). Coluna sem
     chip fica vazia sozinha -- por isso cada um tem `grid-column` proprio. */
  /* A ordem e a que ele ditou em 19/08/2026: "o conjunto da bateria vem
     primeiro depois 12 folhas depois meta 1,8 depois a data 17/08 depois carga
     21,5". As tres primeiras vem juntas dentro de `.pd-status` (a faixa que o
     servidor reescreve), por isso a primeira coluna e larga. */
  .pd-meta {
    display: grid;
    /* Colunas FIXAS para a mesma informacao cair no mesmo ponto em toda raia
       (o pedido dos "slots"). A primeira guarda a faixa inteira -- bateria,
       folhas e produtividade --, depois a data e a carga. */
    grid-template-columns: 520px 240px max-content;
    align-items: stretch;
    gap: 8px 10px;
    margin: 8px 0 2px;
    /* Colada na ESQUERDA, no mesmo prumo do icone do PR (19/08/2026, na letra:
       "o de bateria totalmente a esquerda junto com o icone do pr"). Chegou a
       ter 48px de recuo para nascer debaixo do texto; ele preferiu o alinhamento
       com a borda do cartao. */
    padding-left: 0;
  }
  .pd-meta > * { justify-self: stretch; }
  .pd-meta .pd-status { grid-column: 1; margin: 0; }
  .pd-meta .pd-period { grid-column: 2; margin: 0; }
  .pd-meta .pd-load { grid-column: 3; }
  /* A data e a carga viram CARTOES do mesmo tamanho dos da faixa (mesma altura,
     mesmo respiro, mesmo canto) -- pedido dele em 19/08/2026: "tudo na mesma
     linha e com as pílulas da data e carga do mesmo tamanho". Antes eram
     pilulas de canto redondo no meio de cartoes retangulares, e a linha
     parecia montada com duas peças de jogos diferentes. */
  .pd-meta .pd-period,
  .pd-meta .pd-load {
    display: inline-flex;
    align-items: center;
    justify-content: flex-start;
    gap: 10px;
    padding: 7px 14px;
    border-radius: 10px;
    font-size: 0.72rem;
    min-height: 44px;
    box-sizing: border-box;
  }
  .pd-meta .pd-period i, .pd-meta .pd-period svg,
  .pd-meta .pd-load i, .pd-meta .pd-load svg { width: 20px; height: 20px; flex: none; }
  .pd-titles small { color: var(--fabim-muted); font-size: 0.7rem; }
  .pd-load {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.1);
    color: #d7dee7;
    font-size: 0.72rem;
    font-weight: 700;
  }
  .pd-load i { width: 13px; height: 13px; }
  /* Reloginho na cor do estado da estimativa: âmbar abaixo, verde na meta,
   * vermelho no estouro (mesma paleta da faixa de status). */
  /* Filtro de recurso ativo: data cheia (100% da capacidade ou ferias) em
   * vermelho, data com horas livres em verde. Sem filtro, sem classe. */
  /* Cabecalho e STICKY: fundo OPACO (tom misturado sobre --sticky-head) para o
   * conteudo nao vazar por baixo ao rolar. */
  .planning-table th.planning-day-head.day-full { background: color-mix(in srgb, var(--sticky-head) 70%, #d85c5c); color: #f2b8b8; }
  .planning-table th.planning-day-head.day-free { background: color-mix(in srgb, var(--sticky-head) 72%, #55b878); color: #b7e6c6; }
  /* Proxima data com horas livres: so a primeira fica verde. */
  .planning-table th.planning-day-head.day-next-free {
    background: color-mix(in srgb, var(--sticky-head) 68%, #55b878);
    color: #b7e6c6;
    box-shadow: inset 0 0 0 1px rgba(85, 184, 120, 0.55);
    cursor: help;
  }
  /* Balao flutuante da data: recursos e horas livres no dia. */
  .planning-avail-tip {
    position: fixed;
    transform: translateX(-50%);
    z-index: 90;
    display: grid;
    gap: 4px;
    min-width: 170px;
    padding: 10px 12px;
    border: 1px solid rgba(85, 184, 120, 0.45);
    border-radius: 10px;
    background: #101a26;
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.45);
    font-size: 0.74rem;
    pointer-events: none;
  }
  .planning-avail-tip strong { color: #b7e6c6; font-size: 0.7rem; letter-spacing: 0.04em; }
  .planning-avail-tip span { display: flex; justify-content: space-between; gap: 14px; color: #dbe4ee; }
  .planning-avail-tip span b { color: #55b878; }
  .pd-load.under i, .pd-load.under svg { color: #7ba6e0; }
  .pd-load.ok i, .pd-load.ok svg { color: #55b878; }
  .pd-load.over i, .pd-load.over svg { color: #d85c5c; }
  .pd-chevron {
    margin-left: auto;
    width: 34px;
    height: 34px;
    border-radius: 10px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    background: transparent;
    color: #d7dee7;
    display: grid;
    place-items: center;
    cursor: pointer;
  }
  .pd-chevron:hover { background: rgba(255, 255, 255, 0.06); }
  .pd-chevron i { width: 16px; height: 16px; }
  .pd-status { display: flex; align-items: stretch; gap: 10px; margin: 6px 0 2px; }
  .pd-status:empty { display: none; }
  .pd-band {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 7px 14px;
    border-radius: 10px;
    font-size: 0.72rem;
  }
  .pd-band i { width: 20px; height: 20px; flex: none; }
  .pd-band strong { display: block; font-size: 0.8rem; }
  .pd-band small { opacity: 0.9; }
  /* Disponivel em AZUL: significa economia (ainda nao atingiu o total), nao alerta. */
  .pd-band.under { background: linear-gradient(90deg, rgba(91, 157, 255, 0.22), rgba(91, 157, 255, 0.04)); color: #7ba6e0; }
  .pd-band.ok { background: linear-gradient(90deg, rgba(85, 184, 120, 0.24), rgba(85, 184, 120, 0.04)); color: #55b878; }
  .pd-band.over { background: linear-gradient(90deg, rgba(216, 92, 92, 0.24), rgba(216, 92, 92, 0.04)); color: #d85c5c; }
  .pd-gauge {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 7px 12px;
    border-radius: 10px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    background: rgba(255, 255, 255, 0.03);
    color: #d7dee7;
    font-size: 0.74rem;
    font-weight: 700;
  }
  .pd-gauge i { width: 15px; height: 15px; color: #7ba6e0; }
  /* Total de folhas. Mesma caixa do velocimetro -- os dois sao leitura da
     estimativa, e separar o desenho sugeriria que um vale mais que o outro.
     O icone e que muda: aqui e a pilha de pranchas. */
  .pd-sheets {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 7px 12px;
    border-radius: 10px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    background: rgba(255, 255, 255, 0.03);
    color: #d7dee7;
    font-size: 0.74rem;
    font-weight: 700;
  }
  /* Lucide troca o <i> por <svg>: dimensionar so `i` nao pega no icone. */
  .pd-sheets i, .pd-sheets svg { width: 15px; height: 15px; color: #7ba6e0; }
  .pd-primary {
    border-color: rgba(91, 157, 255, 0.55) !important;
    background: rgba(47, 111, 206, 0.16) !important;
    color: #cfe1fb !important;
  }
  /* Raia RECOLHIDA: o botao acende, porque com a grade fora da tela ele e a
     unica pista de que ha equipe e horas escondidas ali. */
  .pd-raia-off {
    border-color: rgba(234, 179, 8, 0.55) !important;
    background: rgba(234, 179, 8, 0.14) !important;
    color: #f3d78a !important;
  }
  .pd-kebab { margin-left: auto; }
  .pd-kebab span { display: none; }

  /* Dialogo "Folhas e produtividade" no padrao do mockup: icones nos campos,
   * faixa de estimativa e cards de sugestoes automaticas. */
  /* Mais largo que o dialogo base (420px) para os cards de sugestao nao
   * espremerem o texto em varias linhas. */
  .sheets-dialog { width: min(100% - 32px, 720px); max-width: none; }
  .sheets-subtitle { text-transform: uppercase; letter-spacing: 0.05em; font-size: 0.8rem; }
  .sheets-field { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 12px; }
  .sheets-field label { flex: 1; }
  .sheets-field-icon {
    width: 44px;
    height: 44px;
    border-radius: 12px;
    display: grid;
    place-items: center;
    background: rgba(91, 157, 255, 0.12);
    border: 1px solid rgba(91, 157, 255, 0.3);
    color: #7ba6e0;
    flex: none;
    margin-top: 6px;
  }
  .sheets-field-icon i { width: 20px; height: 20px; }
  /* Acao "Ajustar produção com plano": botao + explicacao do calculo. */
  .sheets-fit-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin: 0 0 12px;
  }
  .sheets-fit-row .sheets-fit { min-height: 38px; }
  .sheets-fit-row small { font-size: 11px; line-height: 1.3; }
  .sheets-fit-row small.error { color: var(--fabim-danger); font-weight: 600; }
  .sheets-estimate {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 4px 0 14px;
    padding: 12px 14px;
    border-radius: 12px;
    border: 1px solid rgba(91, 157, 255, 0.3);
    background: rgba(91, 157, 255, 0.08);
    font-weight: 600;
  }
  .sheets-estimate i { width: 18px; height: 18px; color: #5b9dff; flex: none; }
  .sheets-estimate b { color: #5b9dff; }
  .sheets-suggestions {
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 14px;
    padding: 12px 14px;
    margin-bottom: 14px;
  }
  .sheets-suggestions h3 {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 10px;
    font-size: 0.9rem;
  }
  .sheets-suggestions h3 i { width: 16px; height: 16px; color: #9d8cf0; }
  .sheets-suggestion-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
  .sheets-suggestion-grid article {
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 12px;
    padding: 10px;
    background: rgba(255, 255, 255, 0.02);
  }
  .sheets-suggestion-grid strong {
    display: block;
    margin: 8px 0;
    padding-bottom: 8px;
    border-bottom: 1px dashed rgba(255, 255, 255, 0.14);
    font-size: 0.76rem;
  }
  .sheets-suggestion-grid p { margin: 0; font-size: 0.76rem; color: var(--fabim-muted); }
  .sheets-sug-icon { width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center; }
  .sheets-sug-icon i { width: 16px; height: 16px; }
  .sheets-sug-icon.blue { background: rgba(91, 157, 255, 0.16); color: #5b9dff; }
  .sheets-sug-icon.green { background: rgba(85, 184, 120, 0.16); color: #55b878; }
  .sheets-sug-icon.purple { background: rgba(157, 140, 240, 0.16); color: #9d8cf0; }
  .sheets-suggestion-grid article:nth-child(1) p b { color: #5b9dff; }
  .sheets-suggestion-grid article:nth-child(2) p b { color: #55b878; }
  .sheets-suggestion-grid article:nth-child(3) p b { color: #9d8cf0; }
  .sheets-primary {
    background: #2f6fce;
    border-color: #2f6fce;
    color: #fff;
  }
  .sheets-primary:hover { background: #3c7cdb; }

  /* Seletor de semanas do Dashboard: chip clicavel + menu (atual verde,
   * anteriores cinza claro). */
  .week-chip-clickable { cursor: pointer; }
  .week-chip-clickable:hover { filter: brightness(1.15); }
  .report-period { position: relative; }
  .week-menu {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    z-index: 60;
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 220px;
    max-height: 320px;
    overflow-y: auto;
    padding: 6px;
    border-radius: 10px;
    border: 1px solid var(--fabim-line-strong);
    background: var(--fabim-navy-800, #0f1b29);
    box-shadow: 0 12px 28px rgba(0, 0, 0, 0.45);
  }
  .week-menu button {
    border: 0;
    background: transparent;
    text-align: left;
    padding: 5px 9px;
    border-radius: 7px;
    font-size: 0.74rem;
    font-weight: 700;
    cursor: pointer;
  }
  .week-menu button.current { color: #55b878; }
  .week-menu button.past { color: #c9d2dc; }
  .week-menu button:hover { background: rgba(255, 255, 255, 0.08); }

  /* Horas do mes: pivo dia x projetista acima dos apontamentos.
   * Fim de semana: cabecalho em vermelho; celula trabalhada destacada. */
  .month-hours-panel { margin-bottom: 10px; }
  /* "Mês" ao LADO do campo (nao em cima): ganha altura para os apontamentos. */
  .month-hours-panel .table-header { align-items: center; }
  .month-hours-panel .filters label {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 8px;
    white-space: nowrap;
  }
  .month-hours-panel .filters input[type="month"] { margin-top: 0; }
  /* Sem "faixinha" a direita: o table-wrap generico reserva a calha da
   * barra de rolagem vertical (scrollbar-gutter: stable) que esta tabela
   * baixa nao usa. */
  .month-hours-wrap { overflow-x: auto; scrollbar-gutter: auto; }
  /* Colunas de dia SIMETRICAS (largura fixa) e linhas slim para a tabela
   * ocupar o minimo de altura acima dos apontamentos. */
  /* Largura fluida: os dias dividem o espaco igualmente (table-layout fixed)
   * e o mes inteiro cabe no painel; abaixo de 1080px entra a rolagem. */
  .month-hours-table { width: 100%; min-width: 1080px; table-layout: fixed; border-collapse: collapse; font-size: 0.7rem; }
  .month-hours-table th, .month-hours-table td {
    padding: 2px 3px;
    height: 20px;
    border: 1px solid var(--fabim-line);
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    line-height: 1.2;
    font-variant-numeric: tabular-nums;
  }
  .month-hours-table .mh-name { width: 90px; }
  .month-hours-table .mh-total { width: 90px; }
  /* components.css congela a ULTIMA coluna de toda tabela (padrao "Acoes").
   * Aqui a ultima coluna e o Total Geral: sem faixa congelada — ele rola
   * junto com os dias, como uma coluna comum. */
  .month-hours-table th:last-child,
  .month-hours-table td:last-child { position: static; box-shadow: none; }
  .month-hours-table tbody td:last-child { background: transparent; }
  /* Celula sem lancamento: cinza solido, leitura imediata de "dia vazio". */
  .month-hours-table tbody td:not(.mh-name):not(.mh-total):empty {
    background: color-mix(in srgb, var(--fabim-muted) 14%, var(--fabim-surface));
  }
  .month-hours-table thead th { background: var(--sticky-head); color: var(--thead-text); font-weight: 800; }
  .month-hours-table thead th.mh-weekend { color: #d85c5c; }
  .month-hours-table td.mh-weekend-work { background: rgba(216, 92, 92, 0.2); color: #f2b8b8; font-weight: 700; }
  .month-hours-table thead th.mh-holiday { color: #e09a62; }
  .month-hours-table td.mh-holiday-work { background: rgba(224, 154, 98, 0.22); color: #fdba74; font-weight: 700; }
  /* Roxo = lancou menos que a jornada (6h estagiario, 8h os demais). */
  .month-hours-table td.mh-below-target { color: #a78bfa; font-weight: 700; }
  .mh-legend-below { background: #a78bfa; }
  /* Legenda das cores (fim de semana x feriado). */
  .mh-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px; margin-top: 8px; font-size: 0.72rem; color: var(--muted); }
  /* Faltas nao carregadas: a tabela pinta todo dia como comum e a legenda
     abaixo promete cores que nao vao aparecer. Sem este aviso a tela afirmava
     que nao havia falta nenhuma (auditoria 21/08/2026, ALTO). */
  .mh-legend-erro { margin: 8px 0 0; padding: 6px 10px; border-radius: 6px;
    border: 1px solid rgba(216, 92, 92, 0.45); background: rgba(216, 92, 92, 0.10);
    color: var(--fabim-danger, #b03a3a); font-size: 0.72rem; }
  .mh-legend-item { display: inline-flex; align-items: center; gap: 6px; }
  .mh-legend-swatch { width: 12px; height: 12px; border-radius: 3px; border: 1px solid var(--fabim-line); }
  .mh-legend-weekend { background: rgba(216, 92, 92, 0.45); }
  .mh-legend-holiday { background: rgba(224, 154, 98, 0.55); }

  /* Falta: MAGENTA. As tres cores ja usadas sao vermelho apagado (fim de
     semana), laranja (feriado) e roxo (abaixo da jornada) -- um quarto tom
     avermelhado ficaria igual ao primeiro na legenda, que foi exatamente o
     que apareceu no primeiro screenshot. O magenta nao se confunde com
     nenhum deles, e a celula ainda escreve "Falta" por extenso. */
  .mh-legend-absence { background: rgba(197, 61, 168, 0.85); }

  .mh-absence {
    background: rgba(197, 61, 168, 0.26);
    color: #f0a3e0;
    font-weight: var(--fw-semibold, 600);
    font-size: 11px;
    letter-spacing: .02em;
  }

  /* Atestado (14/08, pedido do Fabio): falta ATESTADA e atestado de HORAS tem
     cor propria -- ambar, que nao existe na tabela (magenta = falta seca,
     laranja-feriado e vermelho-fds sao so de quem TRABALHOU nesses dias).
     Falta sem justificativa fica como esta. */
  .mh-legend-atestado { background: rgba(224, 168, 91, 0.85); }

  .mh-atestado {
    background: rgba(224, 168, 91, 0.24);
    color: #f0cf9d;
    font-weight: var(--fw-semibold, 600);
    font-size: 11px;
    letter-spacing: .02em;
  }

  .mh-add-absence { margin-left: 6px; }

  .mh-absence-chip { max-width: 100%; }
  /* Botao "+ Feriado" na barra do painel, ao lado do seletor de mes. */
  .mh-add-holiday {
    padding: 4px 12px; font-size: 0.7rem; font-weight: 700;
    line-height: 1.4; border: 1px solid rgba(224, 154, 98, 0.55); border-radius: 999px;
    background: rgba(224, 154, 98, 0.16); color: #e09a62; cursor: pointer; white-space: nowrap;
  }
  .mh-add-holiday:hover { background: rgba(224, 154, 98, 0.28); }
  /* Barra do painel: "+ Feriado" e o seletor de mes lado a lado, DENTRO do
   * painel. O grid generico de .filters clampava o rotulo em 150px e o campo
   * vazava alem da borda (era isso que "cortava"). */
  .month-hours-panel .filters {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    align-items: center;
    gap: 10px;
  }
  .month-hours-panel .filters label { min-width: 0; width: auto; }
  .month-hours-panel .filters input[type="month"] { width: 150px; }
  /* Lista de feriados cadastrados dentro do dialogo. */
  .mh-holiday-list-wrap { margin-top: 14px; }
  .mh-holiday-list-wrap h3 { margin: 0 0 8px; font-size: 0.82rem; color: var(--muted); }
  .mh-holiday-list { display: flex; flex-wrap: wrap; gap: 8px; }
  .mh-holiday-chip {
    display: inline-flex; align-items: center; gap: 6px; padding: 4px 6px 4px 10px;
    border-radius: 999px; background: rgba(224, 154, 98, 0.16);
    border: 1px solid rgba(224, 154, 98, 0.4); color: #fdba74; font-size: 0.75rem; font-weight: 700;
  }
  .mh-holiday-chip button {
    display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px;
    border: none; border-radius: 50%; background: rgba(224, 154, 98, 0.25); color: inherit; cursor: pointer;
  }
  .mh-holiday-chip button:hover { background: rgba(224, 154, 98, 0.5); }
  .mh-holiday-chip button i { width: 12px; height: 12px; }
  .month-hours-table .mh-name { text-align: left; font-weight: 700; position: sticky; left: 0; background: var(--sticky-col); z-index: 2; }
  .month-hours-table .mh-total { font-weight: 800; }
  .month-hours-table tfoot td { background: var(--sticky-head); color: var(--thead-text); font-weight: 800; }

  /* Relatorio de revisoes por PR (dialogo): SEM a coluna Acoes — ela existe
   * para excluir linhas dentro da OS; o relatorio e somente leitura. */
  #revision-pr-dialog .revision-grid-heading span:nth-child(9),
  #revision-pr-dialog .revision-row-actions { display: none; }
  #revision-pr-dialog .revision-grid-heading,
  #revision-pr-dialog .revision-grid-row {
    --revision-columns: 46px minmax(90px, 0.6fr) minmax(170px, 1fr) minmax(250px, 1.55fr) 120px minmax(250px, 1.55fr) 132px 94px;
    min-width: 1222px;
  }

  /* Editor de participantes no drawer "Editar dados" da OS. */
  .header-team-editor h3 { margin: 14px 0 6px; font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.06em; }
  .header-team-list { display: flex; flex-direction: column; gap: 4px; margin-bottom: 10px; }
  .header-team-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 6px;
    border-radius: 8px;
    cursor: pointer;
  }
  .header-team-row:hover { background: rgba(255, 255, 255, 0.05); }
  .header-team-row input[type="checkbox"] { width: 15px; height: 15px; accent-color: var(--fabim-bronze-strong, #7fb3ff); }
  .header-team-row b {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    font-size: 10px;
    font-weight: 800;
    overflow: hidden;
    flex: none;
  }
  .planning-person-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    margin-right: 7px;
    border-radius: 50%;
    font-size: 9px;
    font-weight: 800;
    vertical-align: -6px;
    overflow: hidden;
    flex: none;
  }
  /* Verde = ja planejado (mesmo padrao visual do vermelho de estouro). */
  .planning-cell.filled { background: rgba(85, 184, 120, 0.16); }
  .planning-cell.filled input { background: rgba(85, 184, 120, 0.24); border-color: rgba(85, 184, 120, 0.55); color: #9fdcb4; font-weight: 700; }
  /* Real do Controle SEMPRE ao lado do planejado (pedido do Fabio,
     14/08/2026): pilula PARTIDA `planejado|real` -- a esquerda o plano, a
     direita o que o Controle apontou no dia vivido. Herda a mecanica da
     antiga pilula da linha de base: pseudo-elemento ABSOLUTO, porque um no
     de fluxo dentro do <td> empurraria o input e quebraria a grade
     (table-layout fixo). Real IGUAL ao plano fica discreto (cinza,
     confirmacao); DIVERGENTE fica ambar -- o sinal de que o plano nao conta
     a historia do dia. Ao focar a celula o par sai (:focus-within) e o campo
     volta inteiro para quem digita; reaparece ao sair. */
  .planning-cell[data-real] { position: relative; }
  .planning-cell[data-real]::after {
    content: attr(data-real);
    position: absolute;
    top: 50%;
    /* Ancorado em `left: 50%`: a borda esquerda do bloco cai no centro da
       pilula e o divisor sai exatamente no meio (espelho do antigo par da
       base, que ocupava a metade esquerda). */
    left: 50%;
    /* Rotulo de 4+ caracteres (ex.: "10,5") nao cabe em 20px fixos e vazava
       torto por cima do plano. min-width preserva o visual atual ate 3
       caracteres (centrado nos 20px); acima disso o bloco cresce so para a
       DIREITA a partir do divisor central, sem tocar na grade -- o pseudo e
       absoluto, fora do fluxo do table-layout fixo. nowrap porque em caixa
       estreita o rotulo quebraria em duas linhas. (auditoria 14/08/2026) */
    min-width: 20px;
    width: max-content;
    white-space: nowrap;
    text-align: center;
    transform: translateY(-50%);
    z-index: 1;
    font-size: 12px;
    font-weight: 700;
    line-height: 1;
    color: rgba(170, 178, 189, 0.8);
    /* O divisor e uma BORDA, nao o caractere "|": em corpo pequeno o pipe
       fica torto contra o digito e a altura varia com a fonte. */
    border-left: 1px solid rgba(170, 178, 189, 0.4);
    pointer-events: none;
    transition: opacity 0.12s ease;
  }
  /* O planejado ocupa a METADE ESQUERDA: padding-right de 2x o deslocamento
     desejado joga o centro do conteudo 10px a esquerda do meio. */
  .planning-cell[data-real] input {
    padding-right: 23px;
    padding-left: 3px;
    transition: padding-right 0.12s ease;
  }
  .planning-cell[data-real]:focus-within::after { opacity: 0; }
  .planning-cell[data-real]:focus-within input { padding-left: 4px; padding-right: 4px; }
  /* Divergencia real x plano: ambar na celula e no lado do real. */
  .planning-cell.real-diverge { background: rgba(224, 168, 91, 0.14); }
  .planning-cell.real-diverge::after { color: #f0c48a; border-left-color: rgba(240, 196, 138, 0.5); }
  .planning-cell.real-diverge input { border-color: rgba(224, 148, 62, 0.55); }
  html.light .planning-cell[data-real]::after { color: rgba(90, 98, 110, 0.85); }
  html.light .planning-cell.real-diverge::after { color: #9a5b12; }
  .planning-cell.over { background: rgba(216, 92, 92, 0.16); }
  /* SEM FOLGA: slot VAZIO de quem ja fechou o dia (pedido do Fabio,
     01/09/2026 -- "quando um recurso estiver alocado as 8h, todos os slots
     vazios dele naquele dia devem ficar vermelhos sinalizando ja alocado").
     Antes o vermelho so acendia DEPOIS de digitar: o aviso chegava depois do
     erro.

     MESMO vermelho do estouro no fundo -- a leitura da linha e uma so, "aqui
     nao cabe mais" --, mas a CAIXINHA fica so contornada, tracejada, sem
     preenchimento forte nem negrito: e o que separa "ja alocado" (celula
     vazia, nada errado) de "acima da capacidade" (tem hora demais AQUI). O
     tracejado diz isso sem depender de cor, que e a regra da casa desde a
     auditoria de 14/08/2026 (C3): cor nunca sozinha. */
  .planning-cell.sem-folga { background: rgba(216, 92, 92, 0.16); }
  .planning-cell.sem-folga input {
    background: rgba(216, 92, 92, 0.08);
    border-style: dashed;
    border-color: rgba(216, 92, 92, 0.5);
  }
  /* Celula ativa pisca aguardando dados (slot em edicao). */
  .planning-cell input:focus {
    border-color: var(--fabim-bronze-strong);
    animation: planning-slot-blink 0.9s ease-in-out infinite;
  }
  @keyframes planning-slot-blink {
    0%, 100% { box-shadow: 0 0 0 0 rgba(91, 157, 255, 0); }
    50% { box-shadow: 0 0 0 3px rgba(91, 157, 255, 0.4); }
  }
  /* Foco em uma celula: filtra de verdade — some com as linhas dos outros
     recursos e as demandas empilham com o cabecalho como separador, deixando
     visivel apenas o caminho de alocacao da pessoa acionada. */
  .planning-person-row.person-dim { display: none; }
  /* Filtro por pessoa: esconde as demandas inteiras onde ela nao participa. */
  .planning-table tr.demand-hidden { display: none; }
  /* Ferias: celula bloqueada (listrada), pessoa indisponivel no dia. */
  .planning-cell.vacation {
    background: repeating-linear-gradient(
      -45deg,
      rgba(154, 167, 176, 0.16), rgba(154, 167, 176, 0.16) 5px,
      transparent 5px, transparent 10px
    );
    cursor: not-allowed;
  }
  /* Foto de perfil em Configuracoes. */
  .settings-photo-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; }
  .settings-photo-button { cursor: pointer; }
  .settings-avatar { overflow: hidden; }

  /* Funcoes somente visualizacao (Administrativo, Cliente): filtros continuam,
     mas botoes de criacao/edicao/envio somem (backend tambem bloqueia). */
  /* #import-controle-button saiu da lista em 17/08/2026 junto com o proprio
     botao: a aba Horas virou espelho do Controle e nao ha mais o que importar. */
  body.viewer-mode #new-delivery-button,
  body.viewer-mode .service-order-create,
  body.viewer-mode #planning-new-demand,
  body.viewer-mode #planning-holidays-button,
  body.viewer-mode #planning-special-days-button,
  body.viewer-mode #planning-vacations-button,
  /* O chat de Solicitacoes NAO entra nesta lista: e a excecao acordada com o
     Fabio em 05/08/2026 -- o Cliente conversa com a equipe, abre solicitacao,
     responde e edita a propria mensagem. Ver VIEWER_CHAT_PATH em app/api.py.
     Nao reintroduzir #request-form / .request-reply-form aqui. */
  /* Controle: o viewer-mode nasceu antes desta pagina e nunca a alcancou. */
  body.viewer-mode #ctrl-add-item,
  body.viewer-mode #controle-proassp-button,
  /* Varredura de 05/08/2026: os botoes abaixo tinham escapado da lista. O
     servidor ja recusava todos; o problema era aparecerem na tela e convidarem
     ao clique. Ver tests/test_controle_ui.mjs. */
  body.viewer-mode #mh-add-absence-button,
  body.viewer-mode #mh-add-holiday-button,
  body.viewer-mode #email-recipients-edit-btn,
  body.viewer-mode #email-recipients-save,
  body.viewer-mode #email-preview-send,
  body.viewer-mode #planning-demand-delete,
  /* Aviso de projeto sem OS: o quadro APARECE para todo mundo -- quem so
     acompanha tambem precisa saber que a OS falta --, mas so cria a OS quem
     pode abri-la. O backend ja recusa; aqui e para nao convidar ao clique.
     Sem escopo de <section>: o dialogo mora fora das abas, de proposito. */
  body.viewer-mode [data-os-aviso-criar],
  body.viewer-mode [data-os-aviso-silenciar],
  body.viewer-mode #save-admin-entry-button { display: none !important; }
  body.viewer-mode [data-delivery-action="lista-mestra"] { display: none !important; }
  /* Status e horas da atividade continuam VISIVEIS (sao a informacao), mas
     inertes: esconder deixaria a folha ilegivel. O servidor recusa a escrita de
     qualquer forma -- isto aqui e para nao convidar ao clique.

     ATENCAO ao escopo: os <dialog> do Controle vivem FORA de #controle-view.
     `#controle-detail-dialog` e irmao da secao no index.html, nao filho dela.
     Uma primeira versao desta regra usava "#controle-view [data-stage-status]"
     e nao pegava nada dentro do detalhe -- foi assim que o seletor de status
     continuou clicavel para o perfil Cliente. Nao reintroduzir esse escopo.

     O comentario cita os IDS, e nao numeros de linha, de proposito: ele dizia
     "linha 538, a secao fecha na 520", a auditoria de 21/08/2026 apontou que os
     numeros ja estavam errados, e quando fui corrigi-los em 23/08 eles tinham
     apodrecido DE NOVO (viraram 641 e 775 em dois dias). Coordenada de linha
     nao sobrevive num arquivo que muda todo dia; id sobrevive. */
  body.viewer-mode [data-stage-status],
  body.viewer-mode .ctrl-hours,
  body.viewer-mode .ctrl-hours-mini,
  body.viewer-mode .ctrl-hours-steps,
  body.viewer-mode .ctrl-hours-val,
  body.viewer-mode #controle-detail-dialog input,
  body.viewer-mode #controle-detail-dialog select,
  body.viewer-mode #controle-detail-dialog textarea,
  body.viewer-mode #controle-day-dialog input,
  body.viewer-mode #controle-day-dialog select,
  body.viewer-mode #controle-day-dialog textarea {
    pointer-events: none !important;
    opacity: 0.65;
    cursor: not-allowed;
  }
  /* FILTROS CONTINUAM VALENDO. #controle-day-filters mora DENTRO do
     #controle-day-dialog, entao a regra acima o pegava junto e tirava dela o
     filtro do Controle diario -- o oposto do combinado. Esta regra vem depois
     e devolve o controle. Ao mexer na regra de cima, conferir esta. */
  body.viewer-mode #controle-day-filters input,
  body.viewer-mode #controle-day-filters select,
  body.viewer-mode #controle-filters input,
  body.viewer-mode #controle-filters select {
    pointer-events: auto !important;
    opacity: 1;
    cursor: auto;
  }
  /* Botoes de acrescentar (o "+" da celula, inserir pessoa no dia) e os
     dialogos que so existem para escrever somem por inteiro. */
  body.viewer-mode .ctrl-add-icon,
  body.viewer-mode .ctrl-dia-mini,
  body.viewer-mode [data-add-pessoa],
  /* "Entrar nesta atividade": o + dentro da celula da etapa. E outro botao,
     diferente do [data-add-pessoa] do rodape do dia -- os dois sao "+". */
  body.viewer-mode [data-stage-participar],
  body.viewer-mode .ctrl-stage-participar,
  body.viewer-mode #controle-detail-dialog button[data-add-day],
  body.viewer-mode #controle-exec-dialog,
  body.viewer-mode #controle-reuniao-dialog,
  body.viewer-mode #controle-proassp-dialog { display: none !important; }
  body.viewer-mode .ctrl-card { cursor: default; }
  /* Chip do Dia Especial na lista do dialogo. A COLUNA violeta do quadro esta
     mais abaixo, junto de past-day/today-col -- ver "Dia Especial: SOMBRA". */
  .planning-special-chip {
    border-color: #a855f7;
    color: #c4a7fb;
  }
  /* No tema claro o violeta claro sumiria no fundo branco. */
  html.light .planning-special-chip { color: #6d28d9; }
  /* Some com as acoes da linha, MENOS "Abrir OS": esconder a celula inteira
     tirava a unica forma de ler uma OS no perfil somente visualizacao. */
  body.viewer-mode .table-row-actions > *:not(.service-order-open) { display: none !important; }
  /* Envio de e-mail no viewer-mode: o icone continua VISIVEL, mas travado
     (cadeado, sem clique) — a coluna vazia parecia erro. */
  body.viewer-mode .email-send-button {
    pointer-events: none;
    opacity: 0.5;
    cursor: not-allowed;
    color: var(--fabim-muted) !important;
    border-color: var(--fabim-line) !important;
    background: transparent !important;
  }
  /* "Exibir Concluidos": o projeto concluido (arquivado ou nao) volta ao
     quadro so para consulta. A linha do cartao e as linhas de PESSOA da
     MESMA demanda ficam inertes -- para editar, desarquive em "Arquivados"
     ou reabra o interruptor Concluido. A trava mora na classe is-locked do
     proprio <tr> de cada linha de pessoa: NAO usar "~ tr" aqui de novo --
     esse seletor pega TODAS as linhas seguintes no tbody unico do quadro, e
     travava tambem as demandas vivas abaixo de uma concluida no meio da
     lista (achado da revisao final da Task 5). */
  .planning-demand-row.is-locked { opacity: 0.7; }
  .planning-demand-row.is-locked .pd-title-line strong::after {
    content: " 🔒 concluído · somente leitura";
    font-size: var(--fs-1);
    font-weight: var(--fw-normal);
    color: var(--fabim-muted);
  }
  tr.planning-person-row.is-locked input,
  tr.planning-person-row.is-locked select,
  tr.planning-person-row.is-locked button {
    pointer-events: none;
    cursor: not-allowed;
  }
  .planning-demand-row.is-locked button {
    pointer-events: none;
    cursor: not-allowed;
  }
  /* Concluida SEM arquivar precisa de saida: "Concluido" reabre e "Arquivar"
     manda para o historico -- os dois unicos caminhos para tirar a demanda
     deste estado (desmarcar Concluido e o unico jeito de corrigir horas).
     Arquivada nao tem excecao nenhuma: destravar mora so no dialogo
     "Arquivados", por isso a excecao exige ":not(.is-archived)". */
  .planning-demand-row.is-locked:not(.is-archived) button[data-planning-action="conclude"],
  .planning-demand-row.is-locked:not(.is-archived) button[data-planning-action="execute"] {
    pointer-events: auto;
    cursor: pointer;
  }
  /* Rodada 2 (14/08/2026): pedido literal do Fabio -- "os projetos que sao
     colocados como concluidos nao ficam com pilulas cinzas". O primeiro
     deploy so pintou a badge de situacao (.pd-state.done) e as LOBs; celula
     de horas da grade, badge de periodo e o botao "Concluido" continuaram
     verdes/vermelhos. Mesma familia de cinza do .pd-state.done nos tres
     lugares que faltavam. */
  /* :last-child em dobro (fix round 1, achado por pixel): a ultima coluna
     de dia tem regra propria mais especifica na grade principal
     (`.planning-table tbody tr td.planning-cell.filled:last-child`, mais
     abaixo -- 3 seletores de tipo contra o nosso 1), e ela vencia o cinza
     por especificidade mesmo vindo antes no arquivo. Repetir aqui com
     :last-child soma uma classe/pseudo-classe e fecha a conta a nosso
     favor (5 contra 4). */
  tr.planning-person-row.is-locked .planning-cell.filled,
  tr.planning-person-row.is-locked .planning-cell.over,
  tr.planning-person-row.is-locked .planning-cell.sem-folga,
  tr.planning-person-row.is-locked .planning-cell.filled:last-child,
  tr.planning-person-row.is-locked .planning-cell.over:last-child,
  tr.planning-person-row.is-locked .planning-cell.sem-folga:last-child {
    background: rgba(154, 163, 178, .14);
  }
  /* Projeto concluido nao aceita hora nova, entao "sem folga" ali nao avisa
     nada -- so pintaria de vermelho uma raia que ja e historia. Vira cinza
     junto com o verde e o vermelho, pela mesma razao. */
  tr.planning-person-row.is-locked .planning-cell.filled input,
  tr.planning-person-row.is-locked .planning-cell.over input,
  tr.planning-person-row.is-locked .planning-cell.sem-folga input {
    background: rgba(154, 163, 178, .14);
    border-color: rgba(154, 163, 178, .35);
    border-style: solid;
    color: #9aa3b2;
    font-weight: 700;
  }
  /* Badge de periodo (qualquer variante ended/running/upcoming) do cartao
     travado: cinza neutro, o cartao inteiro le "historia". O botao
     "Concluido" (.pd-done-on) tem a mesma regra mais abaixo, junto da sua
     versao verde original -- ela vive FORA do @layer views (perto da linha
     6950), e uma regra dentro do layer nunca vence uma de fora dele, por
     maior que seja a especificidade (achado ao verificar por pixel: o botao
     continuava verde mesmo com a regra "vencendo" no papel). */
  .planning-demand-row.is-locked .pd-period {
    color: #9aa3b2; background: rgba(154, 163, 178, .14); border-color: rgba(154, 163, 178, .35);
  }
  html.light tr.planning-person-row.is-locked .planning-cell.filled input,
  html.light tr.planning-person-row.is-locked .planning-cell.over input,
  html.light .planning-demand-row.is-locked .pd-period {
    color: #5b6472;
  }
  #planning-show-done-button.is-active { border-color: var(--fabim-success); color: var(--fabim-success); }
  .planning-cell.over input { background: rgba(216, 92, 92, 0.24); border-color: rgba(216, 92, 92, 0.55); color: #f0a0a0; font-weight: 700; }
  .planning-lob-header td { padding: 9px 11px; background: color-mix(in srgb, var(--fabim-surface-raised) 88%, var(--fabim-navy-700)); }
  .planning-lob-title { display: flex; align-items: center; gap: 22px; text-align: left; }
  .planning-lob-title > div { text-align: left; }
  .planning-lob-axes {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    color: var(--fabim-bronze-strong);
    white-space: nowrap;
  }
  .planning-lob-axes > span { display: grid; gap: 2px; text-align: left; }
  .planning-lob-axes b {
    color: var(--fabim-bronze-strong);
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.06em;
  }
  .planning-lob-header small { margin-left: 8px; color: var(--fabim-muted); }
  .planning-lob-cell { padding: 3px 2px; text-align: center; }
  /* Rotulo da linha de balanco (PR · cliente · projeto): quebra em ate 2
   * linhas em vez de cortar com reticencias numa linha so. */
  /* Concluido na linha de balanco: SOMBRA. Ele esta ali como contexto -- o que
     veio antes na fila -- e nao pode competir com o que esta em andamento.
     Cinza transparente em vez de esconder: sumir deixaria buracos na sequencia
     e a leitura da ordem de execucao se perderia.
     `filter: grayscale` mata a cor da barra (verde/vermelho de conflito) sem
     precisar reescrever cada estado. */
  .planning-lob-row.is-concluida { opacity: .42; }
  .planning-lob-row.is-concluida .planning-lob-bar {
    filter: grayscale(1);
    box-shadow: none;
  }
  .planning-lob-row.is-concluida .planning-person {
    color: var(--fabim-muted); font-style: italic;
  }
  /* Mesma sombra na "Linha de Balanço do Usuário" (dialogo proprio). A pilula
     dali usa `--lob-color` (a cor do projeto) no fundo, entao o grayscale tem
     de cair nela, nao so na barra do quadro. */
  .user-lob-row.is-concluida { opacity: .42; }
  .user-lob-row.is-concluida .user-lob-pill,
  .user-lob-row.is-concluida .user-lob-cell.has-block { filter: grayscale(1); }
  .user-lob-row.is-concluida .user-lob-label strong { color: var(--fabim-muted); font-style: italic; }

  .planning-lob-row .planning-person {
    white-space: normal;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    line-height: 1.2;
  }
  /* Cor unica para todas as barras da linha de balanco. */
  .planning-lob-bar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 40px;
    height: 22px;
    border-radius: 4px;
    font-size: 10px;
    font-weight: 700;
    color: #0c1f14;
    /* Mesma cor "planejado" dos slots (verde), para leitura consistente. */
    background: #55b878;
  }

  /* Conflito (recurso acima da capacidade no dia): mesma régua da grade
     e da LOB do usuário. */
  .planning-lob-cell.conflict .planning-lob-bar {
    background: #d85c5c;
    color: #ffffff;
  }
  /* LOB de lancamento em janela flutuante: fora do quadro, com eixo de
     datas proprio. Sem zoom (pedido do Fabio 14/08: "esta dificultando e nao
     vai ter muita vantagem") -- as medidas abaixo sao fixas. */
  .planning-lob-window { position: fixed; z-index: 60; top: 130px; right: 24px; width: 520px; height: 360px; min-width: 320px; min-height: 220px; resize: both; overflow: hidden; display: flex; flex-direction: column; background: var(--panel); border: 1px solid var(--border); border-radius: 12px; box-shadow: 0 18px 48px rgba(0, 0, 0, .45); }
  .lob-window-titlebar { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 8px 12px; border-bottom: 1px solid var(--border); cursor: move; user-select: none; }
  .lob-window-title small { display: block; color: var(--muted); }
  .lob-window-tools { display: flex; gap: 4px; }
  .lob-window-tools button { min-height: 0; padding: 2px 8px; font-size: 12px; }
  .lob-window-body { flex: 1; overflow: auto; }
  .lob-window-empty { padding: 16px; }
  /* table-layout:fixed + <colgroup> (planning.js) e que faz corpo e cabecalho
     concordarem na largura -- sem isto o navegador dimensiona por conteudo e
     as barras deslizam para debaixo da coluna DEMANDA ao rolar.
     Fix round 1 (achado por pixel, nao por asserts de texto): a tabela
     herda `.planning-table` (class="planning-table planning-lob-window-table"),
     entao TODA regra daqui que precisa vencer uma regra generica da grade
     principal usa o prefixo `table.planning-lob-window-table` (soma um
     seletor de TIPO) em vez de so `.planning-lob-window-table` -- empate de
     classes decidido por ordem no arquivo e fragil demais para depender.
     `border-collapse: collapse` tambem precisa disso: `.planning-table` (mais
     abaixo) define `separate` com a MESMA especificidade e vinha depois. */
  table.planning-lob-window-table { border-collapse: collapse; table-layout: fixed; }
  /* A largura da coluna DEMANDA vem da variavel --lob-colw (na tag <table>,
     posta pelo renderLobWindowBody e ajustada ao vivo pela alca de arrasto --
     pedido do Fabio, 14/08/2026: "permitir ajustar a coluna do nome no LOB").
     col, th e td bebem da MESMA variavel para o colgroup nunca desalinhar. */
  .planning-lob-window-table col.planning-lob-window-col-first { width: var(--lob-colw, 150px); }
  .planning-lob-window-table col.planning-lob-window-col-day { width: 44px; }
  /* Primeira coluna STICKY com fundo OPACO (var(--panel)) por cima das
     celulas do corpo -- as barras rolam por baixo sem "vazar" visualmente
     sob o nome da demanda. z-index acima do resto da linha.
     LARGURA precisa ser explicita e mais especifica que a da grade
     principal (`.planning-table td.planning-person`, 190px, mais abaixo):
     sem isto o TD do corpo (nao o th nem o colgroup) herdava 190px e a
     celula sticky opaca cobria ~40 dos 44px do primeiro dia (medido por
     getBoundingClientRect). */
  table.planning-lob-window-table th.planning-first-col,
  table.planning-lob-window-table td.planning-person {
    position: sticky; left: 0; z-index: 2; background: var(--panel);
    width: var(--lob-colw, 150px); min-width: var(--lob-colw, 150px); max-width: var(--lob-colw, 150px);
  }
  /* Alca de ajuste: um fio na borda direita do cabecalho DEMANDA. touch-action
     none para o arrasto nao brigar com a rolagem da janela em touchpad. */
  .lob-col-resizer {
    position: absolute;
    top: 0;
    right: -3px;
    bottom: 0;
    width: 7px;
    cursor: col-resize;
    touch-action: none;
  }
  .lob-col-resizer:hover { background: rgba(123, 166, 224, 0.35); }
  table.planning-lob-window-table td.planning-lob-cell,
  table.planning-lob-window-table td.planning-person {
    padding: 4px 5px;
    height: 30px;
  }
  /* Pilula da janela: arredondada e com folga da borda da coluna (pedido do
     Fabio, 14/08/2026: "a pilula não está legal, está encavalando na linha
     azul"). min-width menor que os 44px da coluna menos o padding, para a
     pilula nunca tocar o fio do dia de hoje. */
  .planning-lob-window-table .planning-lob-bar {
    font-size: 10px;
    min-width: 30px;
    max-width: 100%;
    height: 20px;
    padding: 0 5px;
    border-radius: 999px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
  }
  /* Fio do HOJE mais fino na janela: o inset de 3px da grade principal
     encavalava na pilula dentro de colunas de 44px. Um lavado azul leve no
     fundo mantem a coluna reconhecivel sem disputar espaco. */
  table.planning-lob-window-table td.today-col {
    box-shadow: inset 2px 0 0 rgba(91, 157, 255, 0.5), inset -2px 0 0 rgba(91, 157, 255, 0.5);
    background: rgba(91, 157, 255, 0.07);
  }
  .planning-lob-window-table .planning-person { font-size: 12px; }
  .planning-lob-window-table th.planning-day-head,
  .planning-lob-window-table th.planning-first-col { font-size: 10px; }
  /* Total do dia: rodape fixo (sticky bottom), fundo opaco, mesmo eixo de
     colunas do corpo. */
  .planning-lob-window-total { position: sticky; bottom: 0; z-index: 3; }
  .planning-lob-window-total td { background: var(--sticky-head); font-weight: 800; }
  .planning-lob-window-total td.planning-person { position: sticky; left: 0; z-index: 4; }
  /* O canto "Total" precisa do MESMO prefixo de tipo do canto "Demanda":
     `table.planning-lob-window-table td.planning-person` (4759, fundo --panel,
     z-index 2) e mais especifico que as duas regras acima e vencia em
     silencio -- a linha de Total ficava com uma emenda de dois tons. */
  table.planning-lob-window-table .planning-lob-window-total td.planning-person {
    background: var(--sticky-head);
    z-index: 4;
  }
  /* Rodada 3 (foto do Fabio 14/08): a grade principal poe as DATAS em top:18px
     porque la existe a faixa de semanas (18px) acima delas; esta janela tem UMA
     linha de cabecalho, entao o 18px herdado empurrava as datas para baixo do
     proprio topo e elas COBRIAM os primeiros 18px da primeira linha do corpo
     (medido: dayHead 18->60, primeira linha comecando em 42). O :last-child
     vem junto -- a regra do ultimo dia da grade re-declara top:18px com
     especificidade maior. */
  table.planning-lob-window-table th.planning-day-head,
  table.planning-lob-window-table th.planning-day-head:last-child { top: 0; }
  /* O canto "Demanda" e sticky nos dois eixos e fica ACIMA das datas (z-index
     4 na regra global de thead th): sem isto as datas deslizavam por cima do
     rotulo na rolagem horizontal. Fundo de cabecalho (--sticky-head), como o
     resto da faixa de datas -- o --panel fica so para a coluna do corpo. */
  table.planning-lob-window-table th.planning-first-col {
    z-index: 6;
    background: var(--sticky-head);
  }
  /* Total em CIRCULO: chip com anel duplo, a mesma linguagem do "Total do dia"
     da grade principal (.planning-total-chip) -- diferencia a SOMA do dia das
     barras retangulares das demandas. Verde = planejado; vermelho = dia em
     conflito. A celula ganha uns pixels a mais para o anel respirar. */
  table.planning-lob-window-table .planning-lob-window-total td { height: 34px; }
  .planning-lob-window-total .planning-total-chip {
    min-width: 24px; height: 24px; padding: 0 6px;
    font-size: 11px;
    color: #7fd39e;
    background: rgba(85, 184, 120, 0.18);
    box-shadow: 0 0 0 3px rgba(85, 184, 120, 0.16), 0 2px 9px rgba(85, 184, 120, 0.42);
  }
  .planning-lob-window-total td.conflict .planning-total-chip {
    color: #f0a0a0;
    background: rgba(216, 92, 92, 0.2);
    box-shadow: 0 0 0 3px rgba(216, 92, 92, 0.18), 0 2px 9px rgba(216, 92, 92, 0.5);
  }
  /* ---- Capacidade x ocupacao da equipe (spec 2026-08-15) ----
     A moldura vem de .planning-lob-window (mesma janela suspensa, mesmo
     arrasto/resize); aqui so as medidas proprias e o miolo. */
  .planning-capacity-window { width: 480px; height: 400px; min-width: 340px; min-height: 240px; }
  /* Setas ‹ › da semana. min-height:0 e obrigatorio: o `button` global (layer
     base) crava 38px e a faixa de navegacao ficaria mais alta que a barra de
     titulo. */
  .planning-capacity-nav {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 10px;
    border-bottom: 1px solid var(--border);
  }
  .planning-capacity-nav button {
    min-height: 0;
    padding: 1px 9px;
    border-radius: 6px;
    font-size: 15px;
    line-height: 1.3;
  }
  .planning-capacity-week { flex: 1; text-align: center; font-size: 12px; font-weight: 700; }
  .planning-capacity-body { padding: 8px 10px; display: grid; gap: 3px; align-content: start; }
  /* A linha da pessoa e um <button> (F6: clicar leva ao quadro filtrado), entao
     precisa desmontar o botao azul global inteiro -- fundo, borda, cor, altura
     e centralizacao vem todos do layer base. */
  .planning-capacity-row {
    display: grid;
    grid-template-columns: 24px minmax(52px, 0.9fr) minmax(64px, 1.4fr) auto 40px;
    align-items: center;
    gap: 8px;
    width: 100%;
    min-height: 0;
    padding: 5px 6px;
    border: 1px solid transparent;
    border-radius: 8px;
    background: transparent;
    box-shadow: none;
    color: var(--text);
    font-size: 12px;
    font-weight: 500;
    text-align: left;
    cursor: pointer;
  }
  .planning-capacity-row:hover,
  .planning-capacity-row:focus-visible {
    border-color: var(--border);
    background: var(--sticky-head);
  }
  /* Avatar proprio (nao o .planning-person-avatar da grade): la existe
     margin-right e vertical-align para conviver com texto corrido; aqui quem
     alinha e o grid. */
  .planning-capacity-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    font-size: 9px;
    font-weight: 800;
    overflow: hidden;
    flex: none;
  }
  .planning-capacity-name {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-weight: 700;
  }
  .planning-capacity-track {
    height: 10px;
    border-radius: 999px;
    background: rgba(148, 163, 184, 0.22);
    overflow: hidden;
  }
  .planning-capacity-fill { display: block; height: 100%; border-radius: 999px; background: #8b98a5; }
  .planning-capacity-hours {
    display: flex;
    flex-direction: column;
    justify-self: end;
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }
  .planning-capacity-absence { color: var(--muted); font-size: 10px; }
  /* A porcentagem em TEXTO acompanha a cor da barra: cor sozinha exclui
     daltonico (defeito ja apontado pela auditoria no quadro). */
  .planning-capacity-pct {
    justify-self: end;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }
  .planning-capacity-fill.is-ok { background: #55b878; }
  .planning-capacity-fill.is-warn { background: #d4ad4a; }
  .planning-capacity-fill.is-over { background: #d85c5c; }
  .planning-capacity-fill.is-idle { background: #8b98a5; }
  .planning-capacity-pct.is-ok { color: #7fd39e; }
  .planning-capacity-pct.is-warn { color: #e3c06a; }
  .planning-capacity-pct.is-over { color: #f0a0a0; }
  .planning-capacity-pct.is-idle { color: var(--muted); }
  html.light .planning-capacity-pct.is-ok { color: #1f7a45; }
  html.light .planning-capacity-pct.is-warn { color: #8a6512; }
  html.light .planning-capacity-pct.is-over { color: #a52a2a; }
  .planning-capacity-note { padding: 12px 4px; font-size: 12px; }
  /* Estado vazio EXPLICITO (§3): uma tela de zeros se confunde com "equipe
     livre", que e exatamente a leitura errada de uma semana sem plano. */
  .planning-capacity-empty {
    margin: 2px 0 6px;
    padding: 9px 10px;
    border: 1px dashed rgba(212, 173, 74, 0.55);
    border-radius: 8px;
    background: rgba(212, 173, 74, 0.1);
    color: var(--text);
    font-size: 12px;
    line-height: 1.4;
  }
  /* F7: falha do GET aparece. Janela vazia em silencio ja foi achado de
     auditoria no quadro. */
  .planning-capacity-error {
    display: grid;
    justify-items: start;
    gap: 7px;
    margin: 4px 0;
    padding: 11px 12px;
    border: 1px solid rgba(216, 92, 92, 0.55);
    border-radius: 8px;
    background: rgba(216, 92, 92, 0.12);
    font-size: 12px;
  }
  .planning-capacity-error strong { color: #f0a0a0; }
  html.light .planning-capacity-error strong { color: #a52a2a; }
  .planning-capacity-foot {
    padding: 7px 10px;
    border-top: 1px solid var(--border);
    color: var(--muted);
    font-size: 11px;
    line-height: 1.35;
  }
  .planning-capacity-warn { color: #e3c06a; font-weight: 700; }
  html.light .planning-capacity-warn { color: #8a6512; }

  /* Slot em modo leitura (Administrativo): mantem a caixinha, mas travada. */
  .planning-cell input.planning-cell-ro,
  .planning-cell input[readonly] {
    pointer-events: none;
    cursor: default;
    caret-color: transparent;
  }
  /* Total do dia: faltando (ambar), completo (verde) ou estourado (vermelho). */
  .planning-total-cell.total-short { background: rgba(212, 173, 74, 0.16); color: #e3c06a; font-weight: 700; }
  .planning-total-cell.total-ok { background: rgba(85, 184, 120, 0.18); color: #7fd39e; font-weight: 700; }
  .planning-total-cell.total-over { background: rgba(216, 92, 92, 0.2); color: #f0a0a0; font-weight: 700; }
  .planning-table-wrap { max-height: calc(100vh - 250px); overflow: auto; overflow-x: auto; }
  /* Largura vem inline do planning.js (190 + 56 por dia) com colgroup. */
  .planning-table { table-layout: fixed; border-collapse: separate; border-spacing: 0; }
  .planning-table .planning-demand-title,
  .planning-table .planning-lob-header td,
  .planning-table .planning-empty-hint { white-space: normal; }
  .planning-table .planning-first-col { width: 190px; min-width: 190px; max-width: 190px; }
  .planning-table th.planning-day-head { width: 56px; min-width: 56px; text-align: center; }
  /* Camada de semanas sobre as datas — faixa fina, so "Semana N". */
  .planning-table th.planning-week-head {
    text-align: center;
    background: color-mix(in srgb, var(--fabim-navy-700) 82%, var(--fabim-bronze));
    color: var(--fabim-bronze-strong);
    border-left: 1px solid var(--fabim-line-strong);
    padding: 2px 4px;
    font-size: 10px;
    line-height: 1.2;
    /* rowspan=2 da 1a coluna divide a altura por igual; a altura fixa
       mantem a faixa de semana fina e joga o resto para a linha dos dias. */
    height: 18px;
  }
  /* Rolagem vertical: semana fica fixa como os dias — semana em top:0 e a
     linha dos dias logo abaixo (18px), senao os dias cobrem a semana. */
  .planning-table th.planning-week-head { top: 0; }
  .planning-table th.planning-day-head { top: 18px; }
  .planning-table th.planning-first-col { top: 0; }
  /* "Total do dia" e a 3a linha do cabecalho e congela abaixo das datas.
     --pl-total-top e MEDIDO por JS (syncTotalOffset): a faixa de semana tem
     altura fixa, mas a das datas cresce com a fonte -- chutar aqui deixaria
     uma fresta por onde as linhas passam, ou taparia a primeira.
     Fundo opaco: sem ele as demandas rolariam por dentro dos numeros.
     z-index abaixo do cabecalho de datas (que a regra generica poe em 4) para
     a data continuar por cima na hora de encostar. */
  .planning-table thead tr.planning-total-row td {
    position: sticky; top: var(--pl-total-top, 54px); z-index: 3;
    background: var(--sticky-head);
    border-top: 1px solid var(--fabim-line-strong);
  }
  /* Divisoria entre os dias, no mesmo traco curto e centrado do cabecalho
     (components.css, `thead th:not(:last-child)::after`). Sem ela os numeros
     ficavam boiando e era facil ler o total de um dia na coluna do vizinho. */
  .planning-table thead tr.planning-total-row td:not(:last-child)::after {
    content: ""; position: absolute; top: 50%; right: 0; transform: translateY(-50%);
    width: 1px; height: 62%; background: var(--fabim-line-strong);
    /* Opacidade CHEIA, ao contrario do traco do Controle. Ali o fundo e claro e
       .55 basta; aqui a faixa e o azul escuro do cabecalho e o traco sumia. O
       cabecalho das datas, logo acima, tambem usa a linha sem transparencia. */
  }
  /* O numero vira uma PILULA e e ELA que carrega a cor do estado. O fundo da
     celula nao serve mais: a linha congelou e precisa de fundo opaco proprio
     (`--sticky-head` acima), que cobriria qualquer tom de estado. A sombra em
     dois aneis -- um fino colado e um difuso -- e o que da o "circulado". */
  .planning-total-chip {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 26px; height: 26px; padding: 0 7px;
    border-radius: var(--r-full); border: 1px solid currentColor;
    font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1;
  }
  /* Faltando horas (ambar), dia completo (verde), acima da capacidade
     (vermelho) -- as mesmas tres leituras que a cor do texto ja tinha. */
  .planning-total-cell.total-short .planning-total-chip {
    background: rgba(212, 173, 74, 0.16);
    box-shadow: 0 0 0 3px rgba(212, 173, 74, 0.16), 0 2px 9px rgba(212, 173, 74, 0.4);
  }
  .planning-total-cell.total-ok .planning-total-chip {
    background: rgba(85, 184, 120, 0.18);
    box-shadow: 0 0 0 3px rgba(85, 184, 120, 0.16), 0 2px 9px rgba(85, 184, 120, 0.42);
  }
  .planning-total-cell.total-over .planning-total-chip {
    background: rgba(216, 92, 92, 0.2);
    box-shadow: 0 0 0 3px rgba(216, 92, 92, 0.18), 0 2px 9px rgba(216, 92, 92, 0.5);
  }
  /* Ultimo dia NAO fica travado a direita: a regra generica de tabela
     (components.css) gruda o :last-child para a coluna Acoes; aqui o ultimo
     dia rola normalmente e a barra horizontal o revela. Os fundos abaixo
     re-afirmam o visual padrao das celulas (a generica pintava diferente). */
  .planning-table td:last-child {
    position: static;
    width: auto;
    min-width: 0;
    border-left: 0;
    box-shadow: none;
  }
  /* Cabecalhos do ultimo dia: continuam fixos no TOPO (rolagem vertical),
     mas soltos da direita (rolagem horizontal). */
  .planning-table th.planning-day-head:last-child {
    position: sticky;
    right: auto;
    top: 18px;
    width: auto;
    min-width: 56px;
    border-left: 0;
    box-shadow: none;
  }
  .planning-table th.planning-week-head:last-child {
    position: sticky;
    right: auto;
    top: 0;
    width: auto;
    min-width: 0;
    border-left: 1px solid var(--fabim-line-strong);
    box-shadow: none;
  }
  .planning-table tbody tr:nth-child(odd) td:last-child { background: var(--zebra-glass); }
  .planning-table tbody tr:nth-child(even) td:last-child { background: transparent; }
  .planning-table tbody tr:hover td:last-child { background: var(--hover-glass); }
  .planning-table tbody tr.planning-demand-row td:last-child { background: color-mix(in srgb, var(--fabim-surface-raised) 88%, var(--fabim-navy-700)); }
  .planning-table tbody tr.planning-lob-header td:last-child { background: color-mix(in srgb, var(--fabim-surface-raised) 88%, var(--fabim-navy-700)); }
  .planning-table tr.planning-total-row td:last-child { background: color-mix(in srgb, var(--fabim-surface-raised) 90%, var(--fabim-navy-700)); }
  .planning-table th.planning-week-head:last-child { background: color-mix(in srgb, var(--fabim-navy-700) 82%, var(--fabim-bronze)); }
  .planning-table tbody tr td.planning-cell.filled:last-child { background: rgba(85, 184, 120, 0.16); }
  .planning-table tbody tr td.planning-cell.over:last-child { background: rgba(216, 92, 92, 0.16); }
  /* Mesma armadilha do verde/vermelho acima: a regra generica de
     `td:last-child` (fundo proprio da coluna colada a direita) apagaria o
     "sem folga" so na ULTIMA coluna de dia -- e a sexta-feira ficaria branca
     no meio de uma semana lotada. */
  .planning-table tbody tr td.planning-cell.sem-folga:last-child { background: rgba(216, 92, 92, 0.16); }
  /* A regra generica de `td:last-child` (fundo proprio, coluna colada a
     direita) apagaria o ambar do real divergente na ULTIMA coluna, e o
     `position: static` dela soltaria a ancora do par `planejado|real` -- o
     numero do real iria parar fora da tabela. */
  .planning-table tbody tr td.planning-cell.real-diverge:last-child { background: rgba(224, 168, 91, 0.14); }
  .planning-table tbody tr td.planning-cell[data-real]:last-child { position: relative; }
  .planning-table tbody tr td.planning-cell.vacation:last-child {
    background: repeating-linear-gradient(
      -45deg,
      rgba(154, 167, 176, 0.16), rgba(154, 167, 176, 0.16) 5px,
      transparent 5px, transparent 10px
    );
  }
  .planning-table tr td.planning-total-cell.total-short:last-child { background: rgba(212, 173, 74, 0.16); }
  .planning-table tr td.planning-total-cell.total-ok:last-child { background: rgba(85, 184, 120, 0.18); }
  .planning-table tr td.planning-total-cell.total-over:last-child { background: rgba(216, 92, 92, 0.2); }
  .planning-table th.planning-day-head small { display: block; font-weight: 600; opacity: 0.8; }
  .planning-table td.planning-person {
    position: sticky;
    left: 0;
    z-index: 2;
    width: 190px;
    min-width: 190px;
    max-width: 190px;
    overflow: hidden;
    text-overflow: ellipsis;
    background: var(--fabim-surface);
    font-size: 12px;
    white-space: nowrap;
  }
  .planning-table td.planning-person small { display: block; color: var(--fabim-muted); font-size: 10px; }
  .planning-demand-row td {
    position: sticky;
    left: 0;
    background: color-mix(in srgb, var(--fabim-surface-raised) 88%, var(--fabim-navy-700));
  }
  .planning-demand-title { padding: 8px 11px; }
  .planning-demand-title > div { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
  .planning-demand-title strong { color: var(--fabim-bronze-strong); font-size: 12px; }
  .planning-demand-total {
    padding: 2px 8px;
    border-radius: 999px;
    background: rgba(91, 157, 255, 0.14);
    color: var(--fabim-bronze-strong);
    font-size: 11px;
    font-weight: 700;
  }
  /* Mesmo tamanho das vizinhas (19/08/2026, pedido dele: "pilula da os tambem
     padronizar o tamanho com as outras"). Era 10px/2px-8px no meio de pilulas
     de 12px/3px-11px -- do lado da situacao e do periodo parecia outra coisa.
     A referencia e `.pd-period`. */
  .planning-os-badge {
    display: inline-flex;
    align-items: center;
    padding: 3px 11px;
    border-radius: 999px;
    background: rgba(91, 157, 255, 0.16);
    color: #7aa9f7;
    font-size: 12px;
    font-weight: 700;
    white-space: nowrap;
  }
  .planning-demand-actions { display: inline-flex; gap: 6px; margin-top: 6px; }
  .planning-mini-button {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    min-height: 26px;
    padding: 2px 9px;
    border: 1px solid var(--fabim-line);
    border-radius: 5px;
    background: transparent;
    color: var(--fabim-muted);
    font-size: 10px;
  }
  .planning-mini-button:hover { color: var(--fabim-text); border-color: var(--fabim-line-strong); }
  .planning-mini-button svg { width: 12px; height: 12px; }
  /* Sem `position` aqui de proposito: por um momento em 07/08/2026 esta regra
     ganhou `position: relative` para ancorar o par da pilula partida, mas isso
     cria contexto de empilhamento em TODA celula do quadro e mexe na coluna
     fixa e nos botoes sobrepostos. A ancora vive em `.planning-cell[data-real]`,
     que atinge so as celulas que tem par. */
  .planning-cell { padding: 3px; text-align: center; font-size: 12px; }
  .planning-cell input {
    width: 46px;
    min-height: 30px;
    padding: 2px 4px;
    text-align: center;
    font-size: 12px;
    -moz-appearance: textfield;
  }
  .planning-cell input::-webkit-outer-spin-button,
  .planning-cell input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
  .planning-empty-hint { color: var(--fabim-muted); font-size: 11px; }

  /* ---- Raia recolhida: linha de resumo do projeto (16/08/2026) ----
     "Recolher" tirava a grade inteira e o cartao ficava sem nenhum numero por
     dia. Agora sobra UMA linha fina com o total do projeto no dia, no mesmo
     visual de pilula partida `planejado|real` da linha da pessoa.
     A altura e o ponto: sem `input` (o `min-height: 30px` de
     `.planning-cell input` e o que engorda a linha da pessoa), a linha cai
     para ~22px -- e a economia de espaco e justamente o motivo de recolher. */
  /* `height` E O QUE MANDA AQUI, nao o padding: `tbody td` (components.css)
     crava `height: 46px` em TODA celula do sistema, e num <td> isso vale como
     altura MINIMA. Baixar so o padding deixava a linha nos mesmos 46px --
     armadilha ja registrada no projeto ("regra existir != regra fazer efeito"). */
  .planning-summary-row td { height: 22px; padding-top: 1px; padding-bottom: 1px; }
  .planning-summary-label {
    color: var(--fabim-muted);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.02em;
  }
  /* O `small` do rotulo vira sufixo NA MESMA LINHA: como bloco (regra global
     de `td.planning-person small`) ele empurraria a linha para duas alturas e
     desfaria o ganho de espaco. */
  .planning-table td.planning-summary-label small {
    display: inline;
    margin-left: 5px;
    font-size: 10px;
    font-weight: 500;
    text-transform: lowercase;
  }
  .planning-summary-cell { padding: 1px 3px; }
  .planning-summary-value {
    display: inline-block;
    width: 46px;
    padding: 1px 4px;
    border-radius: 5px;
    background: rgba(91, 157, 255, 0.1);
    color: var(--fabim-text);
    font-size: 12px;
    font-weight: 700;
    line-height: 18px;
  }
  /* Dia sem hora planejada nao ganha pilula: caixa vazia em toda a janela
     viraria ruido e a linha existe para mostrar ONDE ha carga. */
  .planning-summary-value:empty { background: transparent; }
  /* A metade esquerda da pilula partida: espelha o que
     `.planning-cell[data-real] input` faz na linha da pessoa (o pseudo-elemento
     `::after` com o real ja vem herdado de `.planning-cell[data-real]`). */
  .planning-summary-cell[data-real] .planning-summary-value {
    padding-right: 23px;
    padding-left: 3px;
    text-align: center;
  }
  html.light .planning-summary-value { background: rgba(43, 91, 168, 0.1); }
  /* Regua faltando/completo/estourado: as MESMAS cores do "Total do dia"
     congelado no cabecalho (.planning-total-cell.total-*). Cor nova aqui seria
     um segundo vocabulario para a mesma pergunta. Pinta a PILULA, nao a
     celula: a celula ja carrega o ambar do real divergente, e dois fundos
     brigando na mesma caixa apagam os dois sinais. */
  .planning-summary-cell.total-short .planning-summary-value {
    background: rgba(212, 173, 74, 0.16); color: #e3c06a;
  }
  .planning-summary-cell.total-ok .planning-summary-value {
    background: rgba(85, 184, 120, 0.18); color: #7fd39e;
  }
  .planning-summary-cell.total-over .planning-summary-value {
    background: rgba(216, 92, 92, 0.2); color: #f0a0a0;
  }
  /* Amostras da legenda "Total do dia": as MESMAS cores das celulas de total
     (.planning-total-cell.total-*), so opacas o suficiente para ler num
     quadrado de 12px. Se uma delas mudar, muda aqui junto. */
  .planning-swatch.dia-falta { background: rgba(212, 173, 74, 0.6); }
  .planning-swatch.dia-cheio { background: rgba(85, 184, 120, 0.6); }
  .planning-swatch.dia-acima { background: rgba(216, 92, 92, 0.6); }
  html.light .planning-summary-cell.total-short .planning-summary-value { color: #8a6a12; }
  html.light .planning-summary-cell.total-ok .planning-summary-value { color: #1d6b3f; }
  html.light .planning-summary-cell.total-over .planning-summary-value { color: #9b2c2c; }
  /* Recolhido tambem esconde "Disponível/Meta ... h/folha": no modo compacto o
     que importa e o caminho das horas no tempo, nao a meta de folhas. */
  .planning-demand-row.is-raia-off .pd-status { display: none; }
  .user-lob-footer td { border-top: 1px solid var(--fabim-line-strong); }
  .planning-total-cell, .planning-status-cell { text-align: center; font-size: 11px; }
  .planning-total-row td { background: color-mix(in srgb, var(--fabim-surface-raised) 90%, var(--fabim-navy-700)); }
  .planning-holidays-list { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
  .planning-holiday-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 8px;
    border: 1px solid var(--fabim-line);
    border-radius: 999px;
    font-size: 11px;
  }
  .planning-holiday-chip button { display: inline-flex; padding: 0; border: 0; background: transparent; color: var(--fabim-muted); cursor: pointer; }
  .planning-holiday-chip button svg { width: 11px; height: 11px; }
  .planning-demand-actions-row { display: flex; justify-content: space-between; }
  #planning-demand-delete.danger { border-color: rgba(216, 92, 92, 0.45); color: #e8b8b8; }
  #planning-demand-delete.danger:hover { background: rgba(216, 92, 92, 0.14); color: #ffd1d1; }

  /* F1: OS com prazo estourado — badge vermelha GRANDE no card, com brilho:
   * precisa saltar aos olhos imediatamente. */
  .pd-overdue {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 5px 14px; border-radius: 999px;
    border: 1.5px solid rgba(216, 92, 92, 0.8);
    background: rgba(216, 92, 92, 0.28);
    color: #ffd7d7; font-size: 13px; font-weight: 800; letter-spacing: 0.05em;
    cursor: help; white-space: nowrap;
    box-shadow: 0 0 12px rgba(216, 92, 92, 0.4);
  }
  .pd-overdue svg { width: 16px; height: 16px; }
  html.light .pd-overdue { box-shadow: 0 0 10px rgba(216, 92, 92, 0.25); }


  /* Periodo planejado da demanda (apos o nome do projeto): vermelho quando ja
   * venceu, verde em andamento, azul quando ainda nao comecou. */
  .pd-period {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 3px 11px; border-radius: 999px;
    border: 1px solid; font-size: 12px; font-weight: 800;
    letter-spacing: 0.02em; white-space: nowrap; cursor: help;
    font-variant-numeric: tabular-nums;
  }
  .pd-period svg { width: 14px; height: 14px; }
  .pd-period.ended {
    color: #f2b8b8; background: rgba(216, 92, 92, 0.16); border-color: rgba(216, 92, 92, 0.55);
  }
  .pd-period.running {
    color: #9fdcb4; background: rgba(85, 184, 120, 0.14); border-color: rgba(85, 184, 120, 0.5);
  }
  .pd-period.upcoming {
    color: #a8c7fb; background: rgba(91, 157, 255, 0.16); border-color: rgba(91, 157, 255, 0.55);
  }
  html.light .pd-period.ended { color: #b13a49; }
  html.light .pd-period.running { color: #2e7d4f; }
  html.light .pd-period.upcoming { color: #2b5fc2; }

  /* Situacao da demanda, logo ao lado do periodo: Concluída (verde), Andamento
   * (azul), Atrasada (vermelho) e Em breve (neutro). Mesma pilula do periodo,
   * so que sem numeros — le-se o estado sem interpretar datas. */
  .pd-state {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 3px 11px; border-radius: 999px;
    border: 1px solid; font-size: 12px; font-weight: 800;
    letter-spacing: 0.02em; white-space: nowrap; cursor: help;
    text-transform: uppercase;
  }
  .pd-state svg { width: 14px; height: 14px; }
  /* Concluida nao e mais "boa noticia" (verde): e so um estado inerte, igual
     ao arquivado -- por isso a pilula sai cinza neutra, no formato das vizinhas. */
  .pd-state.done {
    color: #9aa3b2; background: rgba(154, 163, 178, 0.14); border-color: rgba(154, 163, 178, 0.35);
  }
  .pd-state.running {
    color: #a8c7fb; background: rgba(91, 157, 255, 0.16); border-color: rgba(91, 157, 255, 0.55);
  }
  .pd-state.late {
    color: #f2b8b8; background: rgba(216, 92, 92, 0.16); border-color: rgba(216, 92, 92, 0.55);
  }
  .pd-state.upcoming {
    color: var(--fabim-muted); background: rgba(168, 178, 190, 0.12); border-color: rgba(168, 178, 190, 0.4);
  }
  html.light .pd-state.done { color: #5b6472; }
  html.light .pd-state.running { color: #2b5fc2; }
  html.light .pd-state.late { color: #b13a49; }

  /* F3: dias ja passados — aparencia de historico (cinza translucido),
   * valores continuam legiveis; transicao suave na virada do dia. */
  .planning-table th.planning-day-head,
  .planning-table td.planning-cell,
  .planning-table td.planning-total-cell,
  .planning-table td.planning-lob-cell { transition: opacity 0.4s ease, background-color 0.4s ease; }
  /* Cabecalho e STICKY: o fundo precisa continuar OPACO (rolagem por baixo);
   * o "apagado" vem so da cor do texto, sem opacity no th. */
  .planning-table th.planning-day-head.past-day {
    background: color-mix(in srgb, var(--sticky-head) 84%, #9aa7b0);
    color: color-mix(in srgb, var(--thead-text) 45%, transparent);
  }
  .planning-table td.planning-cell.past-day,
  .planning-table td.planning-total-cell.past-day,
  .planning-table td.planning-lob-cell.past-day {
    opacity: 0.7;
    /* Cinza SOLIDO: leitura imediata de "esse dia ja passou". */
    background-color: color-mix(in srgb, var(--fabim-muted) 16%, var(--fabim-surface));
    border-color: rgba(154, 167, 176, 0.16);
  }
  /* Slots passados COM horas mantem um verde/vermelho claro por baixo da
   * hachura: diferencia "tinha programacao" de dia vazio (pedido do Fabio). */
  .planning-table td.planning-cell.past-day.filled {
    background-color: rgba(85, 184, 120, 0.14);
  }
  .planning-table td.planning-cell.past-day.over {
    background-color: rgba(216, 92, 92, 0.14);
  }
  /* Hachura diagonal: o slot passado le-se como encerrado, nao "programado".
   * Vale tambem na linha de balanco do quadro. */
  .planning-table td.planning-cell.past-day,
  .planning-table td.planning-cell.past-day.filled,
  .planning-table td.planning-cell.past-day.over,
  .planning-table td.planning-lob-cell.past-day {
    background-image: repeating-linear-gradient(
      135deg,
      rgba(154, 167, 176, 0.22) 0 3px,
      transparent 3px 8px
    );
  }
  .planning-table td.planning-cell.past-day input {
    border-color: rgba(154, 167, 176, 0.35);
    color: var(--fabim-muted);
    background: transparent;
  }

  /* Faixa vertical AZUL e grossa destacando o dia de HOJE (azul para nao
   * confundir com o verde de "planejado"). */
  .planning-table th.planning-day-head.today-col {
    /* Opaco (tom azul sobre --sticky-head): cabecalho sticky nao deixa o
     * conteudo vazar por baixo ao rolar. */
    background: color-mix(in srgb, var(--sticky-head) 74%, #5b9dff);
    color: #a8c7fb;
    box-shadow: inset 0 0 0 2px rgba(91, 157, 255, 0.7);
  }
  .planning-table td.today-col {
    box-shadow: inset 3px 0 0 rgba(91, 157, 255, 0.55), inset -3px 0 0 rgba(91, 157, 255, 0.55);
  }

  /* Dia Especial: SOMBRA violeta na COLUNA inteira (sabado, domingo ou feriado
   * aberto a mao). Antes era so um sublinhado no cabecalho e ele sumia sempre
   * que a regua de lotacao pintava a mesma celula -- em 07/08/2026 o sabado
   * saia VERDE de day-next-free e o violeta so aparecia no domingo.
   * Este bloco fica DEPOIS de day-full/day-free/past-day/today-col de
   * proposito: todas tem a mesma especificidade, entao quem decide e a ORDEM,
   * e o violeta precisa vencer -- ele diz que a coluna existe por decisao
   * humana, coisa que nenhuma outra cor da grade sabe dizer. */
  .planning-table th.planning-day-head.special-day {
    background: color-mix(in srgb, var(--sticky-head) 72%, #a855f7);
    color: #dcc6ff;
  }
  /* Dia especial que ja passou: continua violeta, mas apagado como qualquer
   * dia vivido -- senao o passado gritava mais que a semana pela frente. */
  .planning-table th.planning-day-head.special-day.past-day {
    background: color-mix(in srgb, var(--sticky-head) 84%, #8b5cf6);
    color: color-mix(in srgb, var(--thead-text) 45%, transparent);
  }
  /* Nas celulas a sombra vem de box-shadow inset com spread grande (preenche a
   * celula) e NAO de background: assim ela se SOMA ao que a celula ja diz --
   * verde de planejado, laranja de atraso contra a base, hachura de dia
   * passado -- em vez de apagar. */
  .planning-table td.planning-cell.special-day,
  .planning-table td.planning-total-cell.special-day,
  .planning-table td.planning-lob-cell.special-day {
    box-shadow: inset 0 0 0 999px rgba(168, 85, 247, 0.14);
  }
  /* Hoje caindo num Dia Especial: os trilhos azuis vem PRIMEIRO na lista para
   * ficarem por cima da sombra violeta (sombra anterior desenha na frente). */
  .planning-table td.today-col.special-day {
    box-shadow:
      inset 3px 0 0 rgba(91, 157, 255, 0.55),
      inset -3px 0 0 rgba(91, 157, 255, 0.55),
      inset 0 0 0 999px rgba(168, 85, 247, 0.14);
  }
  /* A bolinha do total no Dia Especial: violeta FIXO, sem condicionante. Dia
   * especial nao tem limite de horas, entao a regua faltando/completo/estourado
   * nao se aplica -- pintar de ambar "faltando 35h" num sabado seria cobrar
   * uma meta que ninguem definiu. Ver o ramo `special` em planning.js. */
  .planning-total-cell.total-special { color: #c4a7fb; font-weight: 700; }
  .planning-total-cell.total-special .planning-total-chip {
    background: rgba(168, 85, 247, 0.2);
    box-shadow: 0 0 0 3px rgba(168, 85, 247, 0.16), 0 2px 9px rgba(168, 85, 247, 0.45);
  }
  /* Tema claro: o violeta claro sumiria no fundo branco. */
  html.light .planning-table th.planning-day-head.special-day {
    background: color-mix(in srgb, var(--sticky-head) 74%, #a855f7);
    color: #4c1d95;
  }
  html.light .planning-table th.planning-day-head.special-day.past-day {
    background: color-mix(in srgb, var(--sticky-head) 86%, #8b5cf6);
    color: color-mix(in srgb, var(--thead-text) 45%, transparent);
  }
  html.light .planning-table td.planning-cell.special-day,
  html.light .planning-table td.planning-total-cell.special-day,
  html.light .planning-table td.planning-lob-cell.special-day {
    box-shadow: inset 0 0 0 999px rgba(124, 58, 237, 0.12);
  }
  html.light .planning-table td.today-col.special-day {
    box-shadow:
      inset 3px 0 0 rgba(91, 157, 255, 0.55),
      inset -3px 0 0 rgba(91, 157, 255, 0.55),
      inset 0 0 0 999px rgba(124, 58, 237, 0.12);
  }
  html.light .planning-total-cell.total-special { color: #6d28d9; }

  /* F2: lista de planejamentos arquivados (historico consultavel). */
  .planning-execute-summary { font-weight: 700; color: var(--fabim-bronze); }
  .planning-archived-list {
    display: flex; flex-direction: column; gap: 10px;
    max-height: 55vh; overflow-y: auto;
  }
  .planning-archived-item {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 10px 12px; border: 1px solid var(--fabim-line); border-radius: 10px;
    background: rgba(255, 255, 255, 0.03);
  }
  .planning-archived-item strong { font-size: 0.85rem; margin-right: 6px; }
  .planning-archived-item small { display: block; color: var(--muted); margin-top: 2px; }

  /* F4: Linha de Balanco do Usuario — painel sobreposto em tela cheia. */
  /* Janela estilo Windows: nao-modal (dialog.show), flutua sobre o quadro,
   * que continua clicavel; arrasta pela barra de titulo. overflow-x hidden:
   * o balao de tooltip criava rolagem horizontal residual no dialog. */
  .user-lob-dialog {
    width: min(100% - 24px, 1500px); overflow-x: hidden;
    /* Acima do menu lateral (90), topbar (80) e alertas (100): a janela
     * flutua sobre a interface inteira, como janela de verdade. */
    position: fixed; margin: 0; z-index: 120;
    top: 56px; left: max(12px, calc(50% - 750px));
    box-shadow: 0 24px 64px rgba(0, 0, 0, 0.55);
  }
  /* A coluna do grid do formulario NUNCA passa da largura da janela: sem
   * isso o grafico (mais largo) esticava a trilha e empurrava titulo/botoes
   * para a area cortada pelo overflow-x hidden. */
  .user-lob-dialog .entry-form { grid-template-columns: minmax(0, 1fr); }
  .user-lob-dialog .form-title-row { cursor: move; user-select: none; padding-right: 132px; }
  .user-lob-dialog .form-title-row button { cursor: pointer; }
  /* Botoes de janela SEMPRE no canto superior direito, independentes do
   * layout do conteudo (posicao absoluta relativa ao dialog fixo). */
  .user-lob-window-buttons {
    display: inline-flex; gap: 6px;
    position: absolute; top: 12px; right: 14px; z-index: 6;
  }
  /* Maximizado: ocupa a tela inteira e a grade ganha toda a altura. */
  .user-lob-dialog.is-max {
    width: 100vw; max-width: 100vw;
    height: 100vh; max-height: 100vh;
    top: 0; left: 0;
    margin: 0; border-radius: 0;
  }
  .user-lob-dialog.is-max .user-lob-wrap { max-height: calc(100vh - 200px); }
  /* Minimizado: barra compacta no canto inferior direito (como na barra de
   * tarefas); clique restaura. */
  .user-lob-dialog.is-min {
    top: auto; left: auto; right: 12px; bottom: 12px;
    width: 360px; max-height: none; overflow: hidden;
    padding: 0; cursor: pointer;
  }
  .user-lob-dialog.is-min .entry-form { padding: 10px 14px; }
  .user-lob-dialog.is-min .form-title-row { margin: 0; cursor: pointer; }
  .user-lob-dialog.is-min .form-title-row h2 { font-size: 0.9rem; }
  .user-lob-dialog.is-min .user-lob-filters,
  .user-lob-dialog.is-min .user-lob-chart,
  .user-lob-dialog.is-min .user-lob-note { display: none; }
  .user-lob-filters { display: flex; flex-wrap: wrap; align-items: end; gap: 12px; }
  .user-lob-filters label { display: flex; flex-direction: column; gap: 4px; font-size: 0.78rem; }
  .user-lob-legend { margin-left: auto; }
  .planning-swatch.past { background: rgba(154, 167, 176, 0.45); }
  /* Legenda da LOB do usuário: planejado = pílula na COR DO PROJETO (varia),
     período encerrado = listrado diagonal, igual ao fundo da grade. */
  .planning-swatch.project {
    border-radius: var(--r-full);
    background: linear-gradient(100deg, #9d8cf0 0 33%, #6fb0e8 33% 66%, #4cc3b0 66% 100%);
  }
  .planning-swatch.hatch {
    background: repeating-linear-gradient(135deg, rgba(154, 167, 176, 0.42) 0 3px, transparent 3px 7px);
  }
  .user-lob-chart { margin-top: 12px; }
  .user-lob-wrap { max-height: calc(100vh - 260px); overflow: auto; }
  .user-lob-label strong { display: block; font-size: 0.8rem; }
  .user-lob-label small { color: var(--muted); }
  /* Bloco com dados: fundo TRANSLUCIDO na cor do projeto (como antes) e a
   * pilula sobreposta na MESMA cor, porem em destaque fluorescente (brilho). */
  .user-lob-cell.has-block {
    background: color-mix(in srgb, var(--lob-color) 30%, transparent);
    cursor: pointer;
    transition: background-color 0.2s ease;
  }
  .user-lob-cell.has-block:hover { background: color-mix(in srgb, var(--lob-color) 42%, transparent); }
  .user-lob-cell.has-block.conflict { background: rgba(216, 92, 92, 0.28); }
  .user-lob-pill {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 40px; height: 22px; border-radius: 5px;
    font-size: 11px; font-weight: 800; color: #0e1c10;
    /* Cor do projeto clareada (fluorescente) + brilho na mesma cor. */
    background: color-mix(in srgb, var(--lob-color) 82%, #ffffff);
    box-shadow: 0 0 10px 1px color-mix(in srgb, var(--lob-color) 75%, transparent),
                0 0 3px 0 var(--lob-color),
                inset 0 0 0 1px color-mix(in srgb, #ffffff 35%, transparent);
  }
  .user-lob-cell.conflict .user-lob-pill {
    color: #fff;
    background: color-mix(in srgb, #d85c5c 82%, #ffffff);
    box-shadow: 0 0 10px 1px rgba(216, 92, 92, 0.75), 0 0 3px 0 #d85c5c,
                inset 0 0 0 1px rgba(255, 255, 255, 0.35);
  }
  .user-lob-cell.has-block:hover .user-lob-pill { filter: brightness(1.12); }
  /* Dia passado (periodo encerrado): hachura na celula, pilula sem brilho. */
  .planning-table td.user-lob-cell.has-block.past-day {
    opacity: 1;
    background-color: color-mix(in srgb, var(--lob-color) 30%, transparent);
    background-image: repeating-linear-gradient(
      135deg,
      rgba(154, 167, 176, 0.22) 0 3px,
      transparent 3px 8px
    );
  }
  .planning-table td.user-lob-cell.has-block.conflict.past-day {
    background-color: rgba(216, 92, 92, 0.28);
  }
  .user-lob-cell.past-day .user-lob-pill { opacity: 0.82; box-shadow: none; }
  /* Base da grade levemente escurecida, mas TRANSLUCIDA e esfumacada (nao
   * solida): da profundidade e destaca os blocos sem achatar. A coluna de
   * nomes fica como antes (texto legivel no fundo original). */
  .user-lob-wrap {
    background: linear-gradient(180deg, rgba(8, 14, 22, 0.38), rgba(8, 14, 22, 0.22));
  }
  .user-lob-wrap .planning-table tbody tr td:not(.has-block):not(.planning-person) {
    background-color: transparent;
  }
  .user-lob-note { margin-top: 6px; }
  .user-lob-row .user-lob-label { cursor: pointer; }
  /* Rotulo da demanda cabe na coluna: uma linha com reticencias. */
  .user-lob-label strong,
  .user-lob-label small {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* O backdrop-filter do dialog vira containing block dos descendentes
   * posicionados: dentro dele o balao usa absolute (coordenadas relativas
   * ao dialog, calculadas no JS), nunca fixed. */
  .user-lob-dialog .planning-avail-tip { position: absolute; }
  /* Tema claro: texto dos blocos e da badge VENCIDA com contraste real. */
  html.light .user-lob-cell.has-block { color: #1d2733; }
  html.light .user-lob-cell.has-block.conflict { color: #fff; }
  html.light .pd-overdue {
    color: #b13a49;
    background: rgba(216, 92, 92, 0.12);
    border-color: rgba(216, 92, 92, 0.5);
  }
  /* Eixo da linha de balanco do usuario: datas na BASE (semanas abaixo),
   * grudadas no rodape da area de rolagem. */
  .user-lob-wrap tfoot th {
    position: sticky;
    z-index: 3;
    background: var(--sticky-head);
    color: var(--thead-text);
  }
  .user-lob-wrap tfoot tr:first-child th { bottom: 20px; }
  .user-lob-wrap tfoot tr:last-child th { bottom: 0; height: 20px; }
  .user-lob-wrap tfoot th:first-child { left: 0; z-index: 4; }
  /* Situacao do prazo na lista de OS: coluna propria ao lado de Prazo,
   * badge inteira na mesma linha (sem corte com "..."). */
  .so-due-cell { white-space: normal; overflow: visible; }
  .so-due-badge {
    display: inline-flex; width: max-content; align-items: center; gap: 4px;
    margin: 0; padding: 2px 9px; border-radius: 999px;
    font-size: 10px; font-weight: 800; letter-spacing: 0.04em;
    border: 1px solid;
  }
  .so-due-badge svg { width: 12px; height: 12px; }
  .so-due-badge.overdue {
    color: #f2b8b8; background: rgba(216, 92, 92, 0.18); border-color: rgba(216, 92, 92, 0.6);
  }
  .so-due-badge.ontime {
    color: #9fdcb4; background: rgba(85, 184, 120, 0.12); border-color: rgba(85, 184, 120, 0.45);
  }
  html.light .so-due-badge.overdue { color: #b13a49; }
  html.light .so-due-badge.ontime { color: #2e7d4f; }

  /* OS arquivada: linha inteira cinza (fica no rodape da lista), chip cinza
   * com icone de arquivo no lugar do status. */
  .service-orders-table tr.so-archived-row td {
    background: color-mix(in srgb, var(--fabim-muted) 12%, var(--fabim-surface));
    color: var(--fabim-muted);
  }
  .service-orders-table tr.so-archived-row .service-order-number strong { color: var(--fabim-muted); }
  .so-archived-chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 3px 11px; border-radius: 999px;
    border: 1px solid rgba(154, 167, 176, 0.5);
    background: rgba(154, 167, 176, 0.14);
    color: #9aa7b0; font-size: 12px; font-weight: 700;
    white-space: nowrap;
  }
  .so-archived-chip svg { width: 13px; height: 13px; }
  .so-archive-button svg { color: #9aa7b0; }
  .so-delete-button svg { color: var(--fabim-danger); }
  .so-delete-button:hover { background: var(--danger-soft); }
  html.light .so-archived-chip { color: #5d6b77; }

  /* A OS do codigo de apontamento: registro, nao execucao.

     Cor propria, e nao a do chip de status: em 16/08/2026 as OS00 do PR 1000 e
     do 2000 estavam marcadas "Aberta" e subiam ao topo da lista com cara de
     obra em andamento. Segue a forma do chip de arquivada -- a mesma pilula,
     porque tambem e um estado fora do fluxo de execucao. */
  .so-codigo-chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 3px 11px; border-radius: 999px;
    /* Sem fundo e sem azul: registro tem de ser o chip mais quieto da coluna.
       O azul do accent, na primeira versao, puxava o olho como execucao -- o
       mesmo defeito de "Aberta" que este chip veio consertar. E nao herda o
       cinza cheio de .so-archived-chip, senao registro viraria arquivada. */
    border: 1px dashed var(--border);
    background: transparent;
    color: var(--muted); font-size: 12px; font-weight: 600;
    white-space: nowrap;
  }
  .so-codigo-chip svg { width: 13px; height: 13px; }

  /* A fila do que ainda precisa de OS (Administracao).
     Uma linha por demanda, com o botao a direita: e uma lista de trabalho, nao
     uma tabela de consulta -- por isso nao usa .table-wrap. */
  .sem-os-lista { display: flex; flex-direction: column; gap: 0.5rem; }
  .sem-os-item {
    display: flex; align-items: center; justify-content: space-between; gap: 1rem;
    padding: 0.6rem 0.85rem; border-radius: 10px;
    border: 1px solid var(--border); background: var(--surface-2);
  }
  .sem-os-dados { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
  .sem-os-dados strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .sem-os-dados small { color: var(--muted); font-size: var(--fs-1); }
  .sem-os-item button { flex: 0 0 auto; }

  /* ================= Administração ================= */
  .requests-layout,
  .settings-layout,
  .admin-layout { align-items: start; gap: 18px; }

  .admin-layout {
    display: grid;
    grid-template-columns: minmax(310px, 370px) minmax(0, 1fr);
  }

  /* Larguras padrão das colunas (app.js) somam 1040px; min-width abaixo disso
   * espremia a coluna Ações e cortava "Editar"/"Redefinir senha".
   *
   * STATUS = 220px desde 10/09/2026. O crachá "Desligado em 30/09/2026" foi
   * MEDIDO na tela em 196px dentro de uma célula de 162px; com
   * `table-layout: fixed` e o `text-overflow: ellipsis` das células, a data --
   * o dado novo inteiro -- saía cortada ("Desligado em 30/09"). 196px do
   * crachá + 22px do padding horizontal da célula = 218px, arredondado para
   * 220. A largura vai no `th` (regra do projeto: no `td` ela falha calada
   * sob table-layout fixed) e tem de acompanhar o vetor de
   * `defaultColumnWidth` em public/app.js, que monta o <colgroup>. */
  .users-table { min-width: 1060px; }
  .users-table th:nth-child(1), .users-table td:nth-child(1) { width: 180px; }
  .users-table th:nth-child(2), .users-table td:nth-child(2) { width: 260px; }
  .users-table th:nth-child(3), .users-table td:nth-child(3) { width: 150px; }
  .users-table th:nth-child(4), .users-table td:nth-child(4) { width: 220px; }
  .users-table td:nth-child(3), .users-table td:nth-child(4) { min-width: auto; }

  /* Campo Senha do formulário de administração com botão de mostrar/ocultar.
   * Na edição o campo fica somente leitura: trocar senha é só pelo botão
   * "Redefinir senha" da tabela. */
  .password-reveal { display: flex; align-items: center; gap: 6px; }
  .password-reveal input { flex: 1; min-width: 0; }
  .password-reveal input[readonly] { opacity: 0.75; cursor: default; }

  /* ================= Responsivo ================= */
  @media (min-width: 1381px) and (max-width: 1600px) {
    .service-order-filters { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .service-order-filters .filter-actions { grid-column: span 4; }
  }

  @media (max-width: 1380px) {
    .report-topbar { grid-template-columns: minmax(460px, 1fr); }
    .report-period { justify-self: start; }
    .consultation-filters { grid-template-columns: repeat(3, minmax(160px, 1fr)); }
    .service-order-filters { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .service-order-filters .filter-actions { grid-column: span 4; }
    .filter-actions { grid-column: span 3; }
  }

  @media (max-width: 1320px) {
    .report-period { grid-column: 1 / -1; justify-content: center; }

    .report-delivery-row {
      grid-template-columns: 84px minmax(170px, 1.4fr) minmax(110px, 1fr) 62px 62px 54px 100px;
    }
  }

  @media (min-width: 761px) and (max-width: 1320px) {
    .revision-grid { overflow-x: auto; }
    .revision-grid-heading { position: relative; top: auto; }
  }

  @media (max-width: 1240px) {
    .entry-layout,
    .admin-layout { grid-template-columns: minmax(280px, 340px) minmax(0, 1fr); }
    .requests-layout { grid-template-columns: 330px minmax(0, 1fr); }
  }

  @media (max-width: 1100px) {
    .account-identity #user-name,
    .logout-button span { display: none; }

    .logout-button { width: 38px; min-width: 38px; padding: 0; }

    .filters {
      grid-auto-flow: row;
      grid-template-columns: repeat(2, minmax(140px, 1fr));
    }

    .requests-layout,
    .admin-layout { grid-template-columns: 1fr; }

    .request-form,
    .admin-layout > .entry-form { position: static; }
  }

  @media (max-width: 1024px) {
    .topbar { position: relative; }
    .dashboard-content { padding-top: 22px; }

    .entry-layout,
    .admin-layout,
    .requests-layout,
    .settings-layout { grid-template-columns: minmax(0, 1fr); }

    #requests-view .entry-form { position: static; }
    .report-topbar { top: 48px; }
    .consultation-filters { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .filter-actions { grid-column: 1 / -1; }
  }

  @media (max-width: 980px) {
    .report-topbar { position: static; display: flex; flex-wrap: wrap; padding: 14px 18px; }

    .report-nav {
      order: 3;
      width: 100%;
      max-width: none;
      overflow-x: auto;
      grid-template-columns: repeat(6, minmax(92px, 1fr));
    }

    .report-period { order: 4; width: 100%; justify-content: flex-start; flex-wrap: wrap; }

    .report-grid,
    .report-person-grid { grid-template-columns: 1fr; }

    .report-kpi-grid.five { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .report-delivery-week { overflow-x: auto; }
    .report-delivery-list { min-width: 880px; }

    .dashboard-chart-grid,
    .dashboard-chart-grid.three { grid-template-columns: 1fr; }
  }

  @media (max-width: 680px) {
    .login-view { place-content: start center; padding-top: 72px; }
    .topbar { min-height: 66px; padding: 8px 14px; }
    .account { gap: 6px; }
    .dashboard-content { padding: 20px 14px 32px; }

    .view-heading,
    .form-title-row,
    .table-header,
    .view-actions { align-items: flex-start; flex-direction: column; }

    .status-message { text-align: left; }

    .entry-layout,
    .admin-layout,
    .requests-layout,
    .form-grid,
    .consultation-filters { grid-template-columns: 1fr; }

    .consultation-filters { padding: 14px; }

    .form-grid label:nth-child(2),
    .form-grid label:nth-child(3),
    .form-field-wide,
    .filter-actions { grid-column: auto; }

    .filters { width: 100%; }
    .filters label { flex: 1 1 100%; width: auto; }
    .filter-actions { width: 100%; }
    .filter-actions button { flex: 1; }

    .entry-form,
    .entries-panel { padding: var(--sp-4); }

    .request-card-header { align-items: flex-start; }
    .request-card-state span { display: none; }
    .request-message { width: 94%; }
    .request-reply-form { grid-template-columns: 1fr; }

    .requests-panel-header > div {
      align-items: flex-start;
      flex-direction: column;
      gap: 2px;
    }

    .alerts-panel { right: 12px; }

    .password-grid { grid-template-columns: 1fr; }
    .password-grid label:first-child { grid-column: auto; }
    .settings-form { padding: 18px; }

    .report-period-badge { display: none; }
    .report-period-control { width: 100%; }
    .report-period-control label { flex: 1; }
    .report-period-control input { width: 100%; }

    .report-hero-row,
    .report-client-top { align-items: flex-start; flex-direction: column; }

    .report-kpi-grid,
    .report-kpi-grid.five,
    .report-delivery-summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }

    .report-load-row { grid-template-columns: 78px minmax(0, 1fr) 48px; }
    .report-load-pct { display: none; }
    .report-project-item { grid-template-columns: 34px minmax(0, 1fr) 70px; }
    .report-project-item .report-phase-chip { display: none; }
    .report-person-header { grid-template-columns: 42px minmax(0, 1fr); }
    .report-person-total { grid-column: 2; text-align: left; }
  }
}

/* ================= Painel publico: responsivo (celular) =================
   Fora da @layer para vencer as regras do dashboard acopladas ao layout do
   app (sidebar / sticky / margens negativas), que nao existem no painel.
   Escopo .painel-body -> o sistema logado fica intacto. */
.painel-body .report-topbar {
  position: static;
  top: auto;
  margin: 0 0 18px;
  padding-inline: 0;
  padding-block: 8px;
}
.painel-body .report-tab-content { width: 100%; }

@media (max-width: 900px) {
  .painel-body .report-topbar { display: block; }
  .painel-body .report-nav {
    display: flex;
    flex-wrap: wrap;
    width: 100%;
    justify-self: stretch;
  }
  .painel-body .report-nav button { flex: 1 1 30%; text-align: center; }
  .painel-body .report-period { justify-content: flex-start; margin-top: 8px; }
}

@media (max-width: 620px) {
  .painel-shell { padding: 14px 12px 28px; }
  .painel-brand { padding: 4px 2px 12px; gap: 10px; }
  .painel-brand img { height: 30px; }
  .painel-brand-text strong { font-size: var(--fs-4); }
  .painel-body .report-nav button { flex: 1 1 46%; }
  .painel-body .report-week-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: none; }
}

@media (max-width: 400px) {
  .painel-body .report-week-stats { grid-template-columns: 1fr; }
}

/* ================= Efeitos do Dashboard (spec 2026-07-18) =================
 * Portados do relatório "equipe fabio.html": elevação + brilho no hover,
 * badge ao vivo pulsante, hover nas linhas de entrega, barras que crescem
 * e contadores animados (os dois últimos disparados por dashboard.js).
 * Fora do @layer de propósito: sobrepõe as regras base sem brigar de
 * especificidade. Vale para sistema e painel (mesmos arquivos). */

.fabim-report-shell .report-kpi,
.fabim-report-shell .report-stat,
.fabim-report-shell .report-week-card,
.fabim-report-shell .report-chart-card,
.fabim-report-shell .report-panel,
.fabim-report-shell .report-person-card,
.fabim-report-shell .report-client-card {
  transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1), border-color 0.28s, box-shadow 0.28s;
}

.fabim-report-shell .report-kpi:hover,
.fabim-report-shell .report-stat:hover,
.fabim-report-shell .report-week-card:hover,
.fabim-report-shell .report-chart-card:hover,
.fabim-report-shell .report-panel:hover,
.fabim-report-shell .report-person-card:hover,
.fabim-report-shell .report-client-card:hover {
  transform: translateY(-1px);
  border-color: var(--fabim-line-strong);
  box-shadow: var(--shadow-glass-soft);
}

/* Badge "ao vivo" com ponto verde pulsante (pulse 2s do equipe fabio.html). */
.fabim-report-shell .report-period-live { gap: 7px; }
.fabim-report-shell .report-period-live::before {
  content: "";
  width: 7px;
  height: 7px;
  flex: 0 0 auto;
  border-radius: var(--r-full);
  background: var(--report-green);
  box-shadow: 0 0 0 3px rgba(95, 197, 126, 0.18);
  animation: report-live-pulse 2s infinite;
}
@keyframes report-live-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.4; transform: scale(0.72); }
}

/* Linhas de entrega: hover discreto (sem deslocamento). */
.fabim-report-shell .report-delivery-row {
  transition: background 0.2s;
}
.fabim-report-shell .report-delivery-row:hover {
  background: var(--hover-glass);
}

/* Barras que crescem: dashboard.js zera a largura e devolve o valor final;
 * esta transição faz o crescimento (mesma curva do equipe fabio.html). */
.fabim-report-shell .report-load-fill,
.fabim-report-shell .report-rank-fill,
.fabim-report-shell .report-month-fill,
.fabim-report-shell .report-client-progress span {
  transition: width 0.9s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Micro-interações: feedback tátil ao clicar na navegação e ícone ativo
 * com mola suave (cubic-bezier "springy" do equipe fabio.html). */
.fabim-report-shell .report-nav button:active { transform: translateY(0) scale(0.95); }
.fabim-report-shell .report-nav button svg { transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); }
.fabim-report-shell .report-nav button.is-active svg { transform: scale(1.08); }
.painel-body #dashboard-report-nav button:active { transform: scale(0.92); }

/* Skeleton shimmer: substitui o "Carregando indicadores..." por blocos com
 * brilho no formato dos cartões (KPIs + gráfico). */
.fabim-report-shell .report-skeleton {
  display: grid;
  gap: 14px;
  place-items: stretch;
  align-content: start;
  min-height: 340px;
}
.fabim-report-shell .report-skeleton-kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.fabim-report-shell .report-skeleton-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.fabim-report-shell .report-skeleton i {
  display: block;
  border: 1px solid var(--border-glass);
  border-radius: var(--r-2);
  background:
    linear-gradient(100deg, transparent 38%, color-mix(in srgb, var(--report-line) 55%, transparent) 50%, transparent 62%),
    var(--surface-glass);
  background-size: 220% 100%, auto;
  animation: report-shimmer 1.4s linear infinite;
}
.fabim-report-shell .report-skeleton-kpis i { height: 104px; }
.fabim-report-shell .report-skeleton-grid i { height: 240px; }
@keyframes report-shimmer {
  from { background-position: 120% 0, 0 0; }
  to { background-position: -120% 0, 0 0; }
}
@media (max-width: 768px) {
  .fabim-report-shell .report-skeleton-kpis { grid-template-columns: 1fr 1fr; }
  .fabim-report-shell .report-skeleton-grid { grid-template-columns: 1fr; }
}

/* Sem movimento para quem pediu sem movimento. */
@media (prefers-reduced-motion: reduce) {
  .fabim-report-shell .report-period-live::before,
  .fabim-report-shell .report-skeleton i { animation: none; }
  .fabim-report-shell .report-kpi:hover,
  .fabim-report-shell .report-stat:hover,
  .fabim-report-shell .report-week-card:hover,
  .fabim-report-shell .report-chart-card:hover,
  .fabim-report-shell .report-panel:hover,
  .fabim-report-shell .report-person-card:hover,
  .fabim-report-shell .report-client-card:hover,
  .fabim-report-shell .report-delivery-row:hover { transform: none; }
}

/* ================= Página Controle (Kanban) ================= */
.controle-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-4);
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-2); padding: var(--sp-3) var(--sp-4); }
.controle-week { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-4); font-size: var(--fs-3); }
.ctrl-week-num { display: inline-flex; align-items: center; gap: 6px; font-weight: var(--fw-bold); font-size: var(--fs-4); }
.ctrl-week-num i { width: 18px; height: 18px; color: var(--accent); }
.ctrl-week-range { color: var(--muted); }
.ctrl-week-hours { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); }
.ctrl-week-hours i { width: 15px; height: 15px; color: var(--accent); }
.ctrl-week-hours b { color: var(--text); }
.controle-filters {
  display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: flex-end;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-2);
  padding: var(--sp-3) var(--sp-4);
}
.controle-filters label { display: flex; flex-direction: column; gap: var(--sp-1); font-size: var(--fs-1); color: var(--muted); }
.controle-filters input, .controle-filters select {
  background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--r-1);
  color: var(--text); padding: 6px 10px; font-size: var(--fs-3); min-width: 150px;
}
.controle-filter-hold { flex-direction: row !important; align-items: center; gap: var(--sp-2); color: var(--text); }
.controle-result-count { margin-left: auto; color: var(--muted); font-size: var(--fs-2); font-weight: var(--fw-medium); }

.ctrl-columns { display: grid; grid-template-columns: repeat(4, minmax(240px, 1fr)); gap: var(--sp-3); align-items: start; }
.ctrl-column {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-2);
  display: flex; flex-direction: column; min-height: 180px;
}
.ctrl-col-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--sp-3) var(--sp-3) var(--sp-2); border-bottom: 1px solid var(--border);
}
.ctrl-col-head h2 { font-size: var(--fs-3); font-weight: var(--fw-bold); margin: 0; color: var(--text); }
/* Icone ao lado do texto do titulo da raia (lucide troca <i> por <svg>). */
.ctrl-col-title { display: inline-flex; align-items: center; gap: var(--sp-2); }
.ctrl-col-icon, .ctrl-col-icon svg { width: 26px; height: 26px; }
.ctrl-col-icon svg { stroke-width: 1.7; }
.ctrl-col-icon { flex: 0 0 auto; opacity: .85; color: var(--muted); }
.ctrl-column[data-status="doing"] .ctrl-col-icon { color: var(--fabim-success); }
.ctrl-column[data-status="done"] .ctrl-col-icon { color: var(--accent); }
.ctrl-column[data-status="hold"] .ctrl-col-icon { color: #a78bfa; }
.ctrl-column[data-status="arquivados"] .ctrl-col-icon { color: var(--fabim-muted); }
/* Validação do projeto (cabeçalho do detalhe): verde quando já validado. */
.ctrl-validated {
  color: var(--fabim-success);
  border-color: rgba(76, 195, 138, 0.55);
  background: var(--success-soft);
}
.ctrl-count { background: var(--accent-soft); color: var(--accent); border-radius: var(--r-full); padding: 2px 10px; font-size: var(--fs-1); font-weight: var(--fw-bold); }
.ctrl-col-body { padding: var(--sp-3); display: flex; flex-direction: column; gap: var(--sp-3); min-height: 120px; max-height: calc(100vh - 320px); overflow-y: auto; }
.ctrl-col-body.is-drop { background: var(--accent-soft); border-radius: var(--r-1); outline: 2px dashed var(--accent-line); outline-offset: -4px; }
.ctrl-column[data-status="hold"] .ctrl-col-head { border-bottom-color: var(--warning-soft); }
.ctrl-column[data-status="hold"] .ctrl-count { background: var(--warning-soft); color: var(--fabim-warning); }
.ctrl-empty { color: var(--muted); font-size: var(--fs-2); text-align: center; padding: var(--sp-6) var(--sp-3); margin: 0; }

.ctrl-card {
  background: var(--panel-3); border: 1px solid var(--border); border-radius: var(--r-2);
  padding: var(--sp-3); cursor: grab; display: flex; flex-direction: column; gap: var(--sp-2);
  box-shadow: var(--shadow-glass-soft); transition: transform .12s ease, box-shadow .12s ease;
}
.ctrl-card:hover { border-color: var(--accent-line); }
.ctrl-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ctrl-card.ctrl-dragging { opacity: .45; cursor: grabbing; }
.ctrl-card.is-hold { border-left: 3px solid var(--fabim-warning); cursor: default; }
/* Projeto concluido no modo "Exibir Concluidos": consulta apenas. O cadeado e
   o esmaecido avisam antes do clique; a recusa de verdade vem do servidor
   (_require_nao_concluido), entao esconder o botao nao seria seguranca. */
.ctrl-card.is-locked {
  border-left: 3px solid var(--fabim-success);
  opacity: 0.72;
  cursor: default;
}
.ctrl-card.is-locked::after {
  content: "🔒 concluído · somente leitura";
  display: block;
  margin-top: 6px;
  font-size: var(--fs-1);
  color: var(--fabim-muted);
}
#controle-show-done-button.is-active {
  border-color: var(--fabim-success);
  color: var(--fabim-success);
}
.ctrl-placeholder { height: 64px; border: 2px dashed var(--accent-line); border-radius: var(--r-2); background: var(--accent-soft); }
.ctrl-card-top { display: flex; align-items: center; gap: var(--sp-2); }
.ctrl-code { font-size: var(--fs-1); font-weight: var(--fw-bold); color: var(--accent); background: var(--accent-soft); padding: 2px 8px; border-radius: var(--r-full); }
.ctrl-card-title { font-size: var(--fs-3); font-weight: var(--fw-bold); margin: 0; color: var(--text); line-height: 1.3; }
.ctrl-card-meta { display: flex; flex-wrap: wrap; gap: var(--sp-3); font-size: var(--fs-1); color: var(--muted); align-items: center; }
.ctrl-card-meta i { width: 13px; height: 13px; vertical-align: -2px; margin-right: 3px; }
.ctrl-resp { display: inline-flex; align-items: center; gap: 4px; }
.ctrl-avatar { width: 18px; height: 18px; border-radius: var(--r-full); display: inline-flex; align-items: center; justify-content: center; font-size: 9px; font-weight: var(--fw-bold); background: var(--accent-soft); color: var(--accent); }

.ctrl-card-period { display: inline-flex; align-items: center; gap: 5px; align-self: flex-start; font-size: var(--fs-1); font-weight: var(--fw-medium); color: var(--text); background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--r-full); padding: 2px 9px; }
.ctrl-card-period i { width: 13px; height: 13px; }
.ctrl-period-none { color: var(--muted); font-weight: var(--fw-regular); }
.ctrl-period-late { color: var(--fabim-danger); border-color: var(--fabim-danger); background: var(--danger-soft); }
/* Concluido: verde, nunca vermelho — o prazo dele ja parou de correr. */
.ctrl-period-done { color: var(--fabim-success); border-color: var(--fabim-success); background: var(--success-soft); }

/* trilho com contraste real: panel-2/3 somem contra o fundo do card */
.ctrl-progress { height: 7px; background: color-mix(in srgb, var(--muted) 28%, transparent); border-radius: var(--r-full); overflow: hidden; }
.ctrl-progress-bar { height: 100%; background: linear-gradient(90deg, var(--accent), var(--fabim-bronze-strong)); border-radius: var(--r-full); transition: width .2s ease; }
.ctrl-progress-text { font-size: var(--fs-1); color: var(--muted); }
.ctrl-hours { display: flex; flex-wrap: wrap; gap: var(--sp-3); font-size: var(--fs-1); color: var(--muted); }
.ctrl-hours i { width: 13px; height: 13px; vertical-align: -2px; margin-right: 3px; }
.ctrl-hours .ctrl-neg { color: var(--fabim-danger); font-weight: var(--fw-medium); }

.ctrl-sit { display: inline-flex; align-items: center; gap: 4px; font-size: var(--fs-1); font-weight: var(--fw-medium); padding: 2px 8px; border-radius: var(--r-full); white-space: nowrap; }
.ctrl-sit i { width: 12px; height: 12px; }
.ctrl-sit-neutral { background: var(--border-soft); color: var(--muted); }
/* Cores da situacao, pedido do Fabio em 18/08/2026, na letra: *"no prazo deixe
   verde, disponível deixe azul e estouro vermelho"*.

   Ate aqui "No prazo" era AMARELO (`ctrl-sit-warn`), e amarelo na tela dele quer
   dizer atencao -- o quadro alarmava justamente o projeto que esta indo bem.
   Verde = no prazo, azul = ainda ha folga disponivel, vermelho = estourou.
   `--accent-strong` e o mesmo azul dos botoes; os tokens mudam com o tema, entao
   a leitura se mantem no claro e no escuro. */
.ctrl-sit-ok { background: var(--success-soft); color: var(--fabim-success); }
.ctrl-sit-info { background: var(--accent-soft); color: var(--accent-strong); }
.ctrl-sit-warn { background: var(--warning-soft); color: var(--fabim-warning); }
.ctrl-sit-bad { background: var(--danger-soft); color: var(--fabim-danger); }

.ctrl-hold-info { display: flex; align-items: center; gap: 6px; font-size: var(--fs-1); color: var(--fabim-warning); background: var(--warning-soft); padding: 4px 8px; border-radius: var(--r-1); }
.ctrl-hold-info i { width: 13px; height: 13px; }

.ctrl-move { position: relative; margin-left: auto; }
.ctrl-move-list { position: absolute; right: 0; top: 100%; z-index: 5; background: var(--panel-3); border: 1px solid var(--border); border-radius: var(--r-1); box-shadow: var(--shadow-glass); display: flex; flex-direction: column; min-width: 170px; padding: 4px; }
.ctrl-move-list button { text-align: left; background: none; border: none; color: var(--text); padding: 7px 10px; border-radius: var(--r-1); cursor: pointer; font-size: var(--fs-2); }
.ctrl-move-list button:hover { background: var(--hover-glass); }

/* Drawer de detalhe */
.controle-detail-dialog {
  margin: 0 auto; height: 100vh; max-height: 100vh; width: 100vw; max-width: 100vw;
  border: none; border-radius: 0;
  background: var(--panel); color: var(--text); box-shadow: var(--shadow-glass); padding: 0;
}
.controle-detail-dialog::backdrop { background: rgba(4, 10, 18, 0.55); }
/* A gaveta e uma COLUNA: cabecalho em cima, conteudo ocupando o resto.
   Antes o conteudo tinha `height: calc(100vh - 84px)` e 84px era a altura
   CHUTADA do cabecalho. Quando a real passa disso -- e passa, com o eyebrow +
   h2 + subtitulo, ou com um nome de projeto que quebra em duas linhas -- a
   soma ultrapassa 100vh, o proprio <dialog> ganha alguns pixels de rolagem e o
   card de resumo (sticky, z-index 5) subia por cima do subtitulo, comendo a
   linha "Multiplan · PE · N folha(s)". Com flex nao ha altura chutada: o
   conteudo termina onde a gaveta termina e o card para na borda do cabecalho.
   `display` SO no [open]: <dialog> nasce `display: none` e um display solto
   aqui deixaria a gaveta sempre visivel. */
.controle-detail-dialog[open] { display: flex; flex-direction: column; }
/* z-index acima do card (5): se algum dia voltarem a se tocar, quem fica por
   cima e o cabecalho -- e o texto dele que nao pode ser comido. */
.controle-detail-header { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-3); padding: var(--sp-4); border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 11; flex: 0 0 auto; background: var(--panel); }
.controle-detail-header h2 { margin: 2px 0; font-size: var(--fs-6); }
.controle-detail-tools { display: flex; gap: var(--sp-2); align-items: center; }
/* Rola nos dois eixos AQUI: se a rolagem horizontal ficar no wrap da tabela, ele
   vira o container de rolagem e o thead sticky para de grudar (gruda num box que
   nao rola verticalmente). Sem padding-top: com ele o thead congelado parava
   16px abaixo do topo e as linhas passavam por essa fresta; o respiro volta
   como margem do primeiro filho. */
/* Faixa de aviso DENTRO do drawer: a do quadro fica atras do <dialog>. */
.ctrl-detail-message { margin: 0; padding: 10px var(--sp-4); border-bottom: 1px solid var(--border);
  background: var(--panel-2); font-size: var(--fs-2); color: var(--text); }
.ctrl-detail-message.error { background: color-mix(in srgb, var(--fabim-danger, #e5534b) 16%, var(--panel-2));
  color: var(--text); border-bottom-color: var(--fabim-danger, #e5534b); }
.ctrl-detail-message[hidden] { display: none; }
/* Acao do cabecalho indisponivel: fica apagada e sem cursor de clique.
   Cuidado ao usar `disabled`: botao desabilitado nao dispara clique, entao
   nenhuma explicacao chega ao usuario -- so vale quando nao ha o que dizer. */
.controle-detail-tools .button-secondary:disabled {
  opacity: .45; color: var(--muted); border-color: var(--border); cursor: not-allowed; }
/* `flex: 1` + `min-height: 0` no lugar da altura calculada: o item flex tem
   `min-height: auto` por padrao e, sem zerar, ele cresce com o conteudo em vez
   de rolar por dentro -- a gaveta e que rolaria. */
.controle-detail-content { padding: 0 var(--sp-4) var(--sp-4); overflow: auto; flex: 1 1 auto; min-height: 0; }
.controle-detail-content > *:first-child { margin-top: var(--sp-4); }

/* Filtro por dia (abre por cima do drawer): data/intervalo + pessoa + atividade,
   e a lista do que foi feito, agrupada por dia. */
.controle-day-dialog {
  margin: auto; width: min(1040px, 94vw); max-width: 94vw; max-height: 88vh;
  border: 1px solid var(--border); border-radius: var(--r-2);
  background: var(--panel); color: var(--text); box-shadow: var(--shadow-glass); padding: 0;
}
/* display SO no [open]: os dialogs do Controle vivem fora das .app-view (senao
   showModal() abriria invisivel dentro de uma view oculta), entao um `display`
   na regra base vence o `display: none` que o navegador da ao dialog fechado e
   ele aparece em TODA aba -- foi o que aconteceu na Dashboard em 30/07/2026. */
.controle-day-dialog[open] { display: flex; flex-direction: column; }
.controle-day-dialog::backdrop { background: rgba(4, 10, 18, 0.62); }
.ctrl-day-filters { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--border); }
.ctrl-day-field { display: flex; flex-direction: column; gap: 4px; }
.ctrl-day-field > span { font-size: 10px; text-transform: uppercase; letter-spacing: .03em; color: var(--muted); }
.ctrl-day-field input, .ctrl-day-field select { min-height: 34px; background: var(--panel-2);
  border: 1px solid var(--border); border-radius: var(--r-1); color: var(--text);
  font-size: var(--fs-2); padding: 4px 8px; }
.ctrl-day-acoes { display: flex; gap: var(--sp-2); margin-left: auto; }
.controle-day-content { padding: var(--sp-4); overflow: auto; }
.ctrl-day-resumo { display: flex; flex-wrap: wrap; gap: var(--sp-4); align-items: center;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--r-2);
  padding: var(--sp-3); margin-bottom: var(--sp-4); font-size: var(--fs-2); color: var(--muted); }
.ctrl-day-resumo i, .ctrl-day-resumo svg { width: 14px; height: 14px; vertical-align: -3px; margin-right: 6px; color: var(--accent); }
.ctrl-day-total { margin-left: auto; color: var(--fabim-success); font-weight: var(--fw-bold); font-variant-numeric: tabular-nums; }
.ctrl-day-bloco { margin-bottom: var(--sp-4); }
.ctrl-day-data { display: flex; align-items: center; gap: 8px; margin: 0 0 var(--sp-2);
  font-size: var(--fs-3); font-weight: var(--fw-medium); }
.ctrl-day-data i, .ctrl-day-data svg { width: 15px; height: 15px; color: var(--accent); }
.ctrl-day-data b { margin-left: auto; color: var(--fabim-success); font-variant-numeric: tabular-nums; }
.ctrl-day-table { width: 100%; border-collapse: collapse; font-size: var(--fs-2); }
.ctrl-day-table th { text-align: left; padding: 6px 10px; font-size: 10px; text-transform: uppercase;
  letter-spacing: .03em; color: var(--muted); border-bottom: 1px solid var(--border); }
.ctrl-day-table td { padding: 7px 10px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.ctrl-day-quem { white-space: nowrap; }
.ctrl-day-quem .ctrl-avatar { width: 22px; height: 22px; margin-right: 7px; vertical-align: -6px; }
/* Faixa da pessoa dentro do dia: o relatorio agrupa por QUEM, entao o nome
   aparece uma vez com o total dela, e as linhas abaixo sao o que ela fez. */
.ctrl-day-quem-row > td { background: var(--panel-3, var(--panel-2)); padding: 9px 10px;
  border-top: 2px solid var(--accent); border-bottom: 1px solid var(--border); }
.ctrl-day-quem-row:first-child > td { border-top-width: 0; }
.ctrl-day-quem-row .ctrl-avatar { width: 26px; height: 26px; margin-right: 9px; vertical-align: -8px; }
/* Corpo maior e mais forte que as linhas de detalhe: e o que faz cada
   colaborador saltar da lista em vez de virar mais uma linha igual. */
.ctrl-day-quem-nome { font-size: var(--fs-3); font-weight: var(--fw-bold); color: var(--text); }
.ctrl-day-quem-total { float: right; font-size: var(--fs-3); font-weight: var(--fw-bold);
  color: var(--fabim-success); font-variant-numeric: tabular-nums; }
.ctrl-day-quem-row + tr > td { padding-top: 9px; }
/* Detalhe recuado e mais apagado, para o contraste com a faixa da pessoa. */
.ctrl-day-table td.ctrl-day-folha { padding-left: 38px; color: var(--muted); }
.ctrl-day-table td.ctrl-day-atv { font-size: var(--fs-1); }
.ctrl-day-folha { color: var(--text); }
.ctrl-day-atv { color: var(--muted); }
th.ctrl-day-h, td.ctrl-day-h { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
td.ctrl-day-h { color: var(--fabim-success); font-weight: var(--fw-medium); }

.ctrl-suggest { display: flex; align-items: center; gap: var(--sp-3); background: var(--accent-soft); border: 1px solid var(--accent-line); border-radius: var(--r-2); padding: var(--sp-3); margin-bottom: var(--sp-3); font-size: var(--fs-3); }
.ctrl-suggest button { margin-left: auto; }

/* overflow visivel (a rolagem e do .controle-detail-content) + fit-content para a
   borda continuar envolvendo a tabela inteira quando ela passa da largura util. */
.ctrl-detail-table-wrap { overflow: visible; min-width: fit-content; border: 1px solid var(--border); border-radius: var(--r-2); }
/* Colunas ALINHADAS entre a tabela das folhas e o "Controle diario" de cada
   uma. Sao duas tabelas independentes (a diaria vive num <td colspan> da
   outra), entao nada as alinha sozinho -- e o cabecalho de cima nao batia com
   o de baixo. Layout fixo nas duas + as mesmas larguras nas pontas fazem as
   colunas de atividade (iguais em numero) receberem a mesma sobra.
   A diaria nao tem "H. executadas"/"Progresso": o "Total do dia" ocupa as
   duas, entao o resto casa. */
/* As duas ultimas colunas HOSPEDAM o pill de acoes: juntas (110 + 150 = 260px)
   elas cobrem a pegada dele (--ctrl-pill-w 221 + --ctrl-pill-right 10 = 231px),
   com 29px de sobra.

   Antes somavam 260px, e faltavam 55. O pill nao "as vezes" invadia: como ele
   tem largura fixa e se ancora na direita, a esquerda dele fica SEMPRE a 315px
   da borda -- entao esses 55px saiam, em toda tela, da coluna vizinha, que e
   "Detalhes" (a 7a e ultima etapa). O que mudava com o monitor era a largura de
   "Detalhes", que absorve toda a sobra da tabela: 274px a 2560 e 91px a 1280.
   So nas telas menores o conteudo dela, centralizado, alcancava a faixa do
   pill -- dai o "em alguns monitores" do Fabio (20/08/2026). Medido no Chrome
   151: a caixa de horas era coberta em +10px a 1600, +27px a 1366, +33px a
   1280, e ficava livre a 1920 (-13px) e 2560 (-59px). */
.controle-detail-content {
  --ctrl-col-nome: 350px;
  /* Minimo da coluna de etapa -- medido, ver .ctrl-detail-table .ctrl-stage-head.
     A conta fecha em 113px: a maior PALAVRA indivisivel dos titulos e
     "PADRONIZACAO", que mede 101,2px MEDIDOS NO ALVO (maiuscula, negrito, com
     letter-spacing, Chrome 151), mais os 12px de padding do `th`. Os 124 aqui
     levam ~6px de margem de proposito: a 120 sobravam 1,9px, e ja se viu uma
     fonte um fio mais larga em outra maquina partir a palavra e virar
     "PADRONIZ/ACAO".

     MEDIR NO ALVO, nao num harness simplificado. A primeira tentativa disto
     usou 108px porque um harness com `font-size: 11px` chumbado deu 89px para a
     palavra. Com o CSS real ela mede 101,2 -- e a 108 a coluna dava 91,1px de
     conteudo, ou seja partia de novo.

     Era 146px ate 20/08/2026: os 26px a mais eram espaco RESERVADO para a seta
     de ordenar, que agora desce para uma linha propria e nao ocupa largura --
     ver `.ctrl-stage-head .ctrl-vf-sort`. Sao 44px x 7 etapas a menos na
     largura de projeto, e largura de projeto e o que decide a escala.

     A largura de projeto do quadro (controle.js) e nome + 7x isto + exec +
     prog. Mudou este numero? Refaca a soma la -- ha teste conferindo. */
  --ctrl-stage-min: 124px;
  /* 24/08/2026: 110/150 viraram 115/160 porque o pill ganhou o botao de
     concluir a folha e passou a ocupar 273px com o afastamento -- as duas
     ultimas colunas TEM de somar pelo menos isso, senao o pill volta a cobrir
     a coluna Detalhes. Ha teste conferindo os dois lados da conta. */
  --ctrl-col-exec: 115px;
  --ctrl-col-prog: 160px;
  --ctrl-col-acoes: 150px;
}
.ctrl-detail-table { width: 100%; min-width: 1000px; border-collapse: collapse; font-size: var(--fs-2); table-layout: fixed; }
/* Acoes recolhidas, como nas Ordens de Servico: a coluna colapsa (a largura
   volta para os dados) e os botoes viram um "pill" sobreposto a direita, que
   aparece ao passar o mouse na linha. Na folha o pill leva tambem a data do
   dia vigente. O `position: relative` na <tr> e o que ancora o pill na LINHA
   -- sem ele o absolute subiria ate o container de rolagem. */
.ctrl-item-row, .ctrl-daily-row { position: relative; }
.ctrl-detail-table th.row-actions-head,
.ctrl-detail-table td.row-actions-cell,
.ctrl-daily-table th.row-actions-head,
.ctrl-daily-table td.row-actions-cell { width: 0; min-width: 0; padding: 0; border-left: 0; }
/* O rotulo "Ações" sai de vista (a coluna tem 0px e o texto vazaria para fora
   da tabela), mas continua no DOM para o leitor de tela. O `overflow` fica SO
   no <th>: na celula ele recortaria o pill flutuante. */
.ctrl-detail-table th.row-actions-head,
.ctrl-daily-table th.row-actions-head { overflow: hidden; text-indent: -9999px; white-space: nowrap; }
.ctrl-acoes-pill { gap: 4px; }
/* Aba Horas, coluna de acoes: no lugar do ✏️/🗑️ da linha que veio do Controle.
   E um ROTULO, nao um botao -- a acao dela mora na outra tela. Discreto de
   proposito: quem procura o botao precisa ler o motivo, nao ganhar um alvo
   novo para clicar. O texto completo esta no `title`. */
.ctrl-origem-aviso {
  display: inline-block; font-size: var(--fs-1); color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.04em; white-space: nowrap;
  padding: 2px 8px; border: 1px dashed var(--border); border-radius: var(--r-1);
  cursor: help;
}
/* Acao indisponivel: translucida e cinza. Sem isto o botao bloqueado ficava
   identico ao ativo -- nao havia nenhuma regra de :disabled no projeto. O
   "porque" vai no title (ex.: nao ha apontamento seu naquele dia). */
.ctrl-detail-table .icon-button:disabled,
.ctrl-daily-table .icon-button:disabled,
.table-row-actions .icon-button:disabled {
  opacity: .35; color: var(--muted); border-color: var(--border);
  background: transparent; cursor: not-allowed; box-shadow: none;
}
.ctrl-detail-table .icon-button:disabled:hover,
.ctrl-daily-table .icon-button:disabled:hover,
.table-row-actions .icon-button:disabled:hover { background: transparent; color: var(--muted); }
.ctrl-detail-table .icon-button:disabled i, .ctrl-detail-table .icon-button:disabled svg,
.ctrl-daily-table .icon-button:disabled i, .ctrl-daily-table .icon-button:disabled svg { color: var(--muted); }
.ctrl-acoes-pill .ctrl-acoes-dia { margin: 0 2px 0 4px; }
.ctrl-nome-h, .ctrl-daily-date-h { width: var(--ctrl-col-nome); }
.ctrl-exec-h { width: var(--ctrl-col-exec); }
.ctrl-prog-h { width: var(--ctrl-col-prog); }
.ctrl-acoes-h, .ctrl-daily-acoes-h { width: var(--ctrl-col-acoes); }
.ctrl-daily-dia-h { width: calc(var(--ctrl-col-exec) + var(--ctrl-col-prog)); }
.ctrl-detail-table th, .ctrl-detail-table td { padding: 8px 10px; border-bottom: 1px solid var(--border); text-align: center; }
/* Cabecalho congelado: fundo OPACO (o --thead-glass sozinho e translucido e
   deixaria as linhas aparecerem por baixo ao rolar). Filho DIRETO: a tabela do
   "Controle diario" fica dentro desta, e o seletor descendente prendia o thead
   dela tambem, fazendo o cabecalho flutuar por cima das linhas dos dias. */
.ctrl-detail-table > thead > tr > th {
  position: sticky; top: calc(var(--ctrl-sum-h, 0px) + var(--ctrl-bar-h, 0px)); z-index: 3;
  background: linear-gradient(var(--thead-glass), var(--thead-glass)), var(--panel);
  box-shadow: inset 0 -1px 0 var(--border);
  color: var(--thead-text); font-weight: var(--fw-bold);
}
.ctrl-detail-table th:first-child, .ctrl-item-name { text-align: left; width: var(--ctrl-col-nome); min-width: 0; white-space: normal; word-break: break-word; font-weight: var(--fw-medium); color: var(--text); }
/* Titulos das 6 etapas na horizontal, quebrando em varias linhas */
/* LARGURA MINIMA DA COLUNA DE ETAPA -- 140px, e o numero e medido, nao chutado.
   A maior PALAVRA indivisivel dos titulos e "PADRONIZAÇÃO": 102px em maiuscula,
   negrito, com o espacamento de letra do cabecalho (medido no Chrome 151). Mais
   12px do respiro da celula e 26px do respiro do botao de ordenar (que abriga a
   seta) = 140px. Abaixo disso o `word-break` do span parte a palavra no meio --
   foi o "REFERÊNCI/A" e "PADRONIZ/AÇÃO" que o Fabio mostrou em 20/08/2026.
   E daqui que sai a largura de projeto do quadro (controle.js).

   O `padding` precisa da especificidade de `.ctrl-detail-table`: sozinho,
   `.ctrl-stage-head` perde para `.ctrl-detail-table th { padding: 8px 10px }` e
   os 6px NUNCA valeram -- a regra existia e nao fazia efeito. Recuperar os 4px
   de cada lado devolve 56px a tabela (8px x 7 colunas).

   O `max-width: 134px` saiu: era menor que o minimo real (contradicao) e nunca
   fez efeito nenhum -- em `table-layout: fixed` a sobra e distribuida por cima
   dele (medido: a coluna chega a 274px num monitor de 2560). */
.ctrl-detail-table .ctrl-stage-head { min-width: var(--ctrl-stage-min); padding: 8px 6px; vertical-align: bottom; }
.ctrl-stage-head span { display: inline-block; white-space: normal; line-height: 1.15; word-break: break-word; font-weight: var(--fw-bold); }
.ctrl-stage-cell { white-space: nowrap; vertical-align: middle; }
/* Divisoria entre as colunas de ETAPAS, no MESMO desenho do cabecalho
   (components.css, `thead th:not(:last-child)::after`): traco curto, centrado e
   translucido -- de proposito sem cara de grade Excel. Pega o nome da folha e
   cada etapa, fechando tambem contra "H. executadas"/"Detalhes". Como as duas
   caixas ("Em andamento" e "Concluídas") compartilham .ctrl-detail-table, uma
   regra so cobre os dois grupos.
   O `position: relative` tem de ir na CELULA: `.ctrl-item-row` ja e relative
   (ancora o pill de acoes) e, sem isto, o traco se prenderia na LINHA inteira
   -- os seis apareceriam empilhados na borda direita da folha. */
.ctrl-detail-table tbody td.ctrl-item-name,
.ctrl-detail-table tbody td.ctrl-stage-cell { position: relative; }
.ctrl-detail-table tbody td.ctrl-item-name::after,
.ctrl-detail-table tbody td.ctrl-stage-cell::after {
  content: ""; position: absolute; top: 50%; right: 0; transform: translateY(-50%);
  width: 1px; height: 40%; background: var(--fabim-line-strong); opacity: .55;
}
.ctrl-stage-wrap { display: flex; flex-direction: column; align-items: center; gap: 6px; }
/* Pilula de STATUS (clicavel) — distinta da caixa de horas */
.ctrl-stage { display: inline-flex; align-items: center; gap: 4px; max-width: 118px; padding: 3px 10px; height: 24px; border: 1px solid var(--border); background: var(--panel-2); color: var(--muted); border-radius: var(--r-full); cursor: pointer; font-size: 10px; text-transform: uppercase; letter-spacing: .02em; white-space: nowrap; }
.ctrl-stage i { width: 13px; height: 13px; flex: 0 0 auto; }
.ctrl-stage .ctrl-stage-text { overflow: hidden; text-overflow: ellipsis; }
.ctrl-stage-doing { background: var(--warning-soft); color: var(--fabim-warning); border-color: transparent; }
.ctrl-stage-done { background: var(--success-soft); color: var(--fabim-success); border-color: transparent; }
/* Caixa de HORAS — relogio + valor HH:MM + setas de 30 em 30 min */
.ctrl-stage-hours { display: inline-flex; align-items: center; gap: 6px; background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-2); padding: 6px 6px 6px 10px; }
/* lucide troca <i data-lucide> por <svg>: dimensionar os dois, senão o svg fica em 24px e a caixa cresce */
.ctrl-stage-hours > i, .ctrl-stage-hours > svg { width: 15px; height: 15px; color: var(--accent); flex: 0 0 auto; }
.ctrl-hours-val { min-width: 42px; text-align: right; font-size: var(--fs-3); font-variant-numeric: tabular-nums; }
.ctrl-hours-steps { display: inline-flex; flex-direction: column; }
.ctrl-hours-step { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 12px; min-height: 0; padding: 0; border: none; background: transparent; color: var(--muted); cursor: pointer; border-radius: 3px; }
.ctrl-hours-step:hover { background: var(--hover-glass); color: var(--text); }
.ctrl-hours-step i, .ctrl-hours-step svg { width: 11px; height: 11px; }
/* Reuniao de validacao: tempo gasto + participantes. */
.controle-reuniao-dialog { margin: auto; width: min(940px, 96vw); max-height: 88vh;
  border: 1px solid var(--border); border-radius: var(--r-2); background: var(--panel);
  color: var(--text); box-shadow: var(--shadow-glass); padding: 0; overflow: hidden; }
/* Duas colunas: o formulario a esquerda, as reunioes ja lancadas a direita.
   Um projeto pode ter varias, entao a lista precisa estar sempre a vista. */
/* `grid-template-rows: minmax(0, 1fr)` e o que faz o `max-height` valer para
   DENTRO. Sem essa linha o `overflow-y: auto` das duas colunas existia sem
   efeito nenhum: a linha do grid crescia com o conteudo (1161px medidos com 9
   registros), a caixa era cortada em 88vh e nao aparecia barra de rolagem --
   os ultimos registros simplesmente sumiam. Achado medindo no navegador
   (`scrollHeight === clientHeight`), nao lendo o arquivo. */
.ctrl-reu-colunas { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 340px);
  grid-template-rows: minmax(0, 1fr); max-height: 88vh; }
.ctrl-reu-lista-box { border-left: 1px solid var(--border); background: var(--panel-2);
  padding: var(--sp-4); overflow-y: auto; min-width: 0; }
.ctrl-reu-lista-box h3 { display: flex; align-items: center; gap: 7px; margin: 0 0 var(--sp-3);
  font-size: var(--fs-2); text-transform: uppercase; letter-spacing: .03em; color: var(--muted); }
.ctrl-reu-lista-box h3 i, .ctrl-reu-lista-box h3 svg { width: 14px; height: 14px; }
.ctrl-reu-contador:not(:empty) { display: inline-grid; place-items: center; min-width: 19px; height: 19px;
  padding: 0 5px; border-radius: var(--r-full); background: var(--accent); color: #06101d;
  font-size: 11px; font-weight: 700; letter-spacing: 0; }
/* `minmax(0, 1fr)`, e nao a faixa `auto` implicita: com `auto` a largura da
   coluna sai do CONTEUDO, e texto `nowrap` (o centro, desde 18/08/2026) conta
   inteiro nessa conta -- antes de qualquer encolhimento. O cartao nascia mais
   largo que a caixa e o `ellipsis` nunca chegava a agir. Medido: caixa de
   347px, faixa resolvida em 569px. */
.ctrl-reu-lista { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; }
.ctrl-reu-vazio { margin: 0; font-size: var(--fs-2); color: var(--muted); }
.ctrl-reu-item { border: 1px solid var(--border); border-radius: var(--r-2);
  background: var(--panel); padding: 9px 10px; }
.ctrl-reu-item.is-editando { border-color: var(--accent); box-shadow: inset 2px 0 0 var(--accent); }
.ctrl-reu-item > header { display: flex; align-items: center; gap: 8px; }
.ctrl-reu-data { display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-2);
  font-weight: 600; color: var(--text); }
.ctrl-reu-data i, .ctrl-reu-data svg { width: 13px; height: 13px; color: var(--muted); }
/* O centro de apontamento do lancamento (18/08/2026). Fica entre a data e as
   horas, discreto: e um rotulo de "para onde foi", nao um numero a comparar.
   `min-width: 0` + ellipsis porque o nome do centro pode crescer, e sem isso
   ele empurraria as horas para fora do cartao. */
.ctrl-reu-centro {
  min-width: 0;
  overflow: hidden;
  font-size: var(--fs-1);
  color: var(--muted);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ctrl-reu-horas { margin-left: auto; font-size: var(--fs-2); font-weight: 700; color: var(--fabim-success, #4cc38a); }
.ctrl-reu-acoes { display: inline-flex; gap: 2px; }
.ctrl-reu-acoes .icon-button { width: 26px; height: 26px; min-height: 0; }
.ctrl-reu-acoes .icon-button i, .ctrl-reu-acoes .icon-button svg { width: 13px; height: 13px; }
.ctrl-reu-tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 7px; }
.ctrl-reu-tag { display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px 2px 3px;
  border-radius: var(--r-full); background: var(--panel-2); border: 1px solid var(--border);
  font-size: 11px; color: var(--muted); }
.ctrl-reu-tag .ctrl-avatar { width: 18px; height: 18px; }
.ctrl-reu-tag.is-vazio { padding: 2px 8px; font-style: italic; }
/* Marcada para excluir: ainda esta no banco. So o OK confirma. */
.ctrl-reu-item.is-marcada { border-color: var(--fabim-danger, #e5534b);
  background: color-mix(in srgb, var(--fabim-danger, #e5534b) 12%, var(--panel)); }
.ctrl-reu-item.is-marcada .ctrl-reu-data,
.ctrl-reu-item.is-marcada .ctrl-reu-horas { text-decoration: line-through; opacity: .65; }
.ctrl-reu-marcada { margin: 7px 0 0; font-size: 11px; color: var(--fabim-danger, #e5534b); }
.ctrl-reu-excluir-bar { margin-top: var(--sp-3); padding: 10px; border-radius: var(--r-2);
  border: 1px solid var(--fabim-danger, #e5534b);
  background: color-mix(in srgb, var(--fabim-danger, #e5534b) 14%, var(--panel)); }
.ctrl-reu-excluir-bar[hidden] { display: none; }
.ctrl-reu-excluir-bar p { display: flex; align-items: center; gap: 6px; margin: 0 0 3px;
  font-size: var(--fs-2); font-weight: 600; color: var(--text); }
.ctrl-reu-excluir-bar p i, .ctrl-reu-excluir-bar p svg { width: 14px; height: 14px;
  color: var(--fabim-danger, #e5534b); flex: none; }
.ctrl-reu-excluir-bar small { display: block; font-size: 11px; color: var(--muted); }
.ctrl-reu-excluir-acoes { display: flex; justify-content: flex-end; gap: 7px; margin-top: 9px; }
.ctrl-reu-ok { display: inline-flex; align-items: center; gap: 6px;
  background: var(--fabim-danger, #e5534b); border: 1px solid var(--fabim-danger, #e5534b);
  color: #fff; border-radius: var(--r-1); padding: 5px 14px; font-size: var(--fs-2); font-weight: 600; }
.ctrl-reu-ok i, .ctrl-reu-ok svg { width: 14px; height: 14px; }
.controle-reuniao-dialog::backdrop { background: rgba(4, 10, 18, 0.62); }
.ctrl-reu-form { padding: var(--sp-4); display: grid; gap: var(--sp-3);
  align-content: start; overflow-y: auto; min-width: 0; }
/* O .form-title-row padrao poe titulo e texto lado a lado; aqui o titulo ficava
   espremido em tres linhas. Empilha. */
.ctrl-reu-form .form-title-row { display: block; }
.ctrl-reu-form .form-title-row h2 { margin: 0 0 6px; }
.ctrl-reu-form .form-title-row p { margin: 0; font-size: var(--fs-2); }
.ctrl-reu-linha { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
.ctrl-reu-campo { display: flex; flex-direction: column; gap: 4px; }
.ctrl-reu-campo > span { font-size: 10px; text-transform: uppercase; letter-spacing: .03em; color: var(--muted); }
.ctrl-reu-campo small { font-size: 10px; color: var(--muted); }
.ctrl-reu-campo input { min-height: 34px; background: var(--panel-2); border: 1px solid var(--border);
  border-radius: var(--r-1); color: var(--text); font-size: var(--fs-2); padding: 4px 8px; }
.ctrl-reu-pessoas-box { border: 1px solid var(--border); border-radius: var(--r-2); padding: var(--sp-3); margin: 0; }
.ctrl-reu-pessoas-box legend { font-size: 10px; text-transform: uppercase; letter-spacing: .03em; color: var(--muted); padding: 0 6px; }
.ctrl-reu-pessoas { display: flex; flex-wrap: wrap; gap: 8px; max-height: 34vh; overflow-y: auto; }
.ctrl-reu-pessoa { display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--r-full);
  padding: 3px 12px 3px 8px; font-size: var(--fs-2); }
.ctrl-reu-pessoa:hover { border-color: var(--accent); }
.ctrl-reu-pessoa.is-eu { border-color: var(--accent); color: var(--accent); cursor: default; }
.ctrl-reu-pessoa input { width: 15px; height: 15px; min-height: 0; flex: none; }
.ctrl-reu-pessoa .ctrl-avatar { width: 22px; height: 22px; }
/* Participante GRAVADO que saiu do roster ativo (desligado, ou o Gerente no
   form do Lider): a caixa dele continua no form -- sem ela o PUT subia sem o
   id e o servidor apagava a participacao e a hora da pessoa (24/08/2026). O
   selo diz por que o nome nao esta na lista da equipe. */
.ctrl-reu-pessoa.is-fora { border-style: dashed; }
.ctrl-reu-pessoa .ctrl-reu-fora { color: var(--muted); font-size: 10px; text-transform: uppercase; letter-spacing: .03em; }
.ctrl-reu-erro { min-height: 16px; margin: 0; color: var(--fabim-danger, #e5534b); font-size: var(--fs-2); }

/* Folha de que o usuario NAO participou: nome so leitura, engrenagem e lixeira
   travadas. A raia continua legivel -- so nao editavel. */
.ctrl-item-row.is-alheia .ctrl-item-name-input { color: var(--muted); cursor: default; }
/* Folha que ja nao casa com o filtro mas ficou porque tem alteracao pendente:
   marca a raia para nao parecer filtro furado. Sai sozinha depois de salvar. */
.ctrl-item-row.is-fora-filtro > td:first-child { box-shadow: inset 3px 0 0 var(--fabim-warning); }
.ctrl-item-row.is-fora-filtro .ctrl-item-save.is-dirty { border-color: var(--fabim-warning); }
.ctrl-item-row.is-alheia .ctrl-item-name-input:focus { outline: none; border-color: var(--border); }
/* Mudar a data leva so as horas de quem edita: avisa o que fica para tras. */
.ctrl-daily-split { display: block; margin-top: 5px; max-width: 260px; white-space: normal;
  font-size: 10px; line-height: 1.35; color: var(--fabim-warning); }
.ctrl-daily-split i, .ctrl-daily-split svg { width: 11px; height: 11px; vertical-align: -2px; margin-right: 4px; }

/* Etapa que esta com OUTRA pessoa: cadeado e tom apagado. Clicar avisa de quem
   e (o admin ainda pode assumir, com confirmacao). */
.ctrl-stage.is-de-outro { opacity: .72; border-style: dashed; }
.ctrl-stage.is-de-outro:hover { opacity: .92; }
/* Celula do dia que e de outra pessoa: travada, so leitura. */
.ctrl-daily-cell.is-de-outro { color: var(--muted); font-variant-numeric: tabular-nums; }
.ctrl-daily-cell.is-de-outro i, .ctrl-daily-cell.is-de-outro svg {
  width: 11px; height: 11px; vertical-align: -1px; margin-right: 5px; opacity: .8; }

/* Barra "Filtrar folhas": reduz as raias exibidas no detalhe. */
.ctrl-folha-filtros { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--sp-3);
  background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--r-2);
  padding: var(--sp-3); margin-bottom: var(--sp-3); }
.ctrl-ff-titulo { display: inline-flex; align-items: center; gap: 7px; align-self: center;
  font-size: var(--fs-2); font-weight: var(--fw-medium); color: var(--text); }
.ctrl-ff-titulo i, .ctrl-ff-titulo svg { width: 15px; height: 15px; color: var(--accent); }
.ctrl-ff-campo { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.ctrl-ff-campo > span { font-size: 10px; text-transform: uppercase; letter-spacing: .03em; color: var(--muted); }
.ctrl-ff-campo select { min-height: 32px; max-width: 230px; background: var(--panel);
  border: 1px solid var(--border); border-radius: var(--r-1); color: var(--text);
  font-size: var(--fs-2); padding: 3px 8px; }
.ctrl-ff-conta { margin-left: auto; align-self: center; font-size: var(--fs-2); color: var(--muted);
  font-variant-numeric: tabular-nums; }
#controle-folha-filter.is-ativo { border-color: var(--accent); color: var(--accent); }

/* Quem fez a atividade: pilula de LEITURA (avatar + nome), abaixo das horas.
   Nao ha seletor — quem clica em "A fazer" assume a etapa, e o nome continua
   na celula depois de concluida. */
.ctrl-stage-exec { display: inline-flex; align-items: center; gap: 5px; max-width: 120px;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--r-full);
  padding: 1px 9px 1px 1px; }
/* Para lider/gerente o chip e um <button> (trocar quem fez). O min-height
   global de button esticaria a pilula, entao ele e anulado aqui -- e o icone
   precisa de tamanho proprio porque o Lucide troca o <i> por <svg>. */
button.ctrl-stage-exec { min-height: 0; height: 24px; cursor: pointer; font: inherit; }
button.ctrl-stage-exec:hover { border-color: var(--accent); }
button.ctrl-stage-exec.is-vazio { padding: 1px 9px; border-style: dashed; color: var(--muted); opacity: .8; }
button.ctrl-stage-exec.is-vazio:hover { opacity: 1; color: var(--text); }
button.ctrl-stage-exec i, button.ctrl-stage-exec svg { width: 13px; height: 13px; flex: 0 0 auto; }
.ctrl-stage-exec .ctrl-avatar { flex: 0 0 auto; width: 20px; height: 20px; }

/* Caixa "Quem fez esta atividade": lista da equipe + a pergunta sobre as horas
   ja lancadas (so aparece quando ha hora de outra pessoa para corrigir). */
.controle-exec-dialog { margin: auto; width: min(560px, 94vw); max-height: 88vh;
  border: 1px solid var(--border); border-radius: var(--r-2); background: var(--panel);
  color: var(--text); box-shadow: var(--shadow-glass); padding: 0; overflow: hidden; }
.controle-exec-dialog::backdrop { background: rgba(4, 10, 18, 0.62); }
.controle-exec-dialog .entry-form { padding: var(--sp-4); display: grid; gap: var(--sp-3);
  align-content: start; max-height: 88vh; overflow-y: auto; }
/* Titulo em cima, contexto embaixo: o .form-title-row padrao poe os dois lado a
   lado e o nome da folha esmagava o titulo em duas linhas. */
.controle-exec-dialog .form-title-row { display: block; }
.controle-exec-dialog .form-title-row h2 { margin: 0 0 2px; }
.controle-exec-dialog .form-title-row p { margin: 0; font-size: var(--fs-2); }
.ctrl-exec-pessoas-box, .ctrl-exec-horas-box { border: 1px solid var(--border);
  border-radius: var(--r-2); padding: var(--sp-3); margin: 0; }
.ctrl-exec-pessoas-box legend, .ctrl-exec-horas-box legend { font-size: 10px;
  text-transform: uppercase; letter-spacing: .03em; color: var(--muted); padding: 0 6px; }
/* Pilulas que quebram linha, como nos participantes da reuniao: nome curto cabe
   inteiro e a caixa acompanha o tamanho da equipe. */
.ctrl-exec-pessoas { display: flex; flex-wrap: wrap; gap: 8px; max-height: 34vh; overflow-y: auto; }
.ctrl-exec-pessoa { display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--r-full);
  padding: 3px 12px 3px 8px; font-size: var(--fs-2); white-space: nowrap; }
.ctrl-exec-pessoa:hover { border-color: var(--accent); }
/* base.css estica todo input (width: 100%; min-height: 38px) -- sem isto o
   radio vira um disco enorme e empurra o texto para fora da caixa. */
.ctrl-exec-pessoa input, .ctrl-exec-opcao input { width: 15px; height: 15px;
  min-height: 0; padding: 0; flex: none; box-shadow: none; }
.ctrl-exec-pessoa .ctrl-avatar { width: 22px; height: 22px; flex: 0 0 auto; }
.ctrl-exec-pessoa i, .ctrl-exec-pessoa svg { width: 16px; height: 16px; flex: 0 0 auto; color: var(--muted); }
.ctrl-exec-horas-texto { margin: 0 0 6px; font-weight: var(--fw-bold); }
.ctrl-exec-opcao { display: flex; align-items: flex-start; gap: 9px; padding: 5px 2px;
  cursor: pointer; line-height: 1.4; font-size: var(--fs-2); }
.ctrl-exec-opcao input { margin-top: 3px; }
.ctrl-stage-exec-nome { font-size: 10px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Atividade que NAO SE APLICA a esta folha: celula so com o aviso, apagada.
   Fora da conta do % e do "x/x etapas" (ver engrenagem da linha da folha). */
/* "Não se aplica" NAO leva fundo proprio -- nem cinza nem `transparent`.
   O zebrado do sistema mora na CELULA (`tbody tr:nth-child(odd) td`, em
   components.css), entao qualquer background aqui vence a listra e a celula
   destoa das vizinhas na mesma linha: com o cinza virava um bloco claro; com
   `transparent` ficava um buraco escuro nas linhas impares. Sem regra nenhuma
   ela recebe exatamente a mesma listra que as irmas.
   O rotulo com o icone de menos ja diz o que e, e a divisoria da coluna
   delimita a celula. */
/* 30px = altura real da pilula de status (o min-height global do button vence
   o height: 24px dela); sem isso a celula "nao se aplica" fica mais baixa. */
.ctrl-stage-na { display: inline-flex; align-items: center; gap: 4px; max-width: 118px; padding: 3px 10px; height: 30px;
  border: 1px dashed var(--border); border-radius: var(--r-full); color: var(--muted); opacity: .75;
  font-size: 10px; text-transform: uppercase; letter-spacing: .02em; white-space: nowrap; }
.ctrl-stage-na i, .ctrl-stage-na svg { width: 13px; height: 13px; flex: 0 0 auto; }

/* Caixa "Atividades da folha" (engrenagem ao lado do salvar) */
.ctrl-atv-dialog { width: min(420px, 92vw); padding: 0; border: 1px solid var(--border); border-radius: var(--r-2); background: var(--panel); color: var(--text); }
.ctrl-atv-dialog::backdrop { background: rgb(0 0 0 / .55); }
.ctrl-atv-form { padding: var(--sp-4); }
.ctrl-atv-titulo { display: flex; align-items: center; gap: 8px; margin: 0; font-size: var(--fs-4); }
.ctrl-atv-titulo i, .ctrl-atv-titulo svg { width: 17px; height: 17px; color: var(--accent); }
.ctrl-atv-folha { margin: 6px 0 0; color: var(--text); font-weight: var(--fw-bold); word-break: break-word; }
.ctrl-atv-dica { margin: 4px 0 var(--sp-3); color: var(--muted); font-size: var(--fs-1); }
.ctrl-atv-lista { display: grid; gap: 2px; }
.ctrl-atv-linha { display: grid; grid-template-columns: 16px minmax(0, 1fr) auto; align-items: center; gap: 9px;
  padding: 7px 9px; border-radius: var(--r-2); cursor: pointer; }
.ctrl-atv-linha:hover { background: var(--hover-glass); }
.ctrl-atv-linha.is-locked { cursor: default; opacity: .8; }
/* min-height global dos inputs (alvo de toque) esticava a caixinha para 38px */
.ctrl-atv-linha input { width: 16px; height: 16px; min-height: 0; margin: 0; accent-color: var(--accent); cursor: inherit; }
.ctrl-atv-nome { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ctrl-atv-horas { display: inline-flex; align-items: center; gap: 4px; color: var(--muted); font-size: var(--fs-1); font-variant-numeric: tabular-nums; }
.ctrl-atv-horas i, .ctrl-atv-horas svg { width: 12px; height: 12px; }
.ctrl-atv-acoes { display: flex; justify-content: flex-end; gap: var(--sp-2); margin: var(--sp-4) 0 0; padding: 0; }

/* Revisar folha: mesma familia da caixa de atividades, so um pouco mais larga
   por causa do campo de observacao. */
.ctrl-rev-dialog { width: min(460px, 92vw); padding: 0; border: 1px solid var(--border); border-radius: var(--r-2); background: var(--panel); color: var(--text); }
.ctrl-rev-dialog::backdrop { background: rgb(0 0 0 / .55); }
.ctrl-rev-form { padding: var(--sp-4); }
.ctrl-rev-titulo { display: flex; align-items: center; gap: 8px; margin: 0; font-size: var(--fs-4); }
.ctrl-rev-titulo i, .ctrl-rev-titulo svg { width: 17px; height: 17px; color: var(--accent); }
.ctrl-rev-folha { margin: 6px 0 0; color: var(--text); font-weight: var(--fw-bold); word-break: break-word; }
.ctrl-rev-dica { margin: 4px 0 var(--sp-3); color: var(--muted); font-size: var(--fs-1); }
.ctrl-rev-campo { display: grid; gap: 4px; margin: 0 0 var(--sp-3); }
.ctrl-rev-campo > span { color: var(--muted); font-size: var(--fs-1); }
/* A revisao e um codigo curto (R01, V00): campo largo daria a impressao de
   caber texto, e e ela que vai impressa na prancha. */
/* `.ctrl-rev-numero` e `.ctrl-rev-obs` sairam em 20/08/2026 com o botao
   "Revisar folha". O RESTO da familia `.ctrl-rev-*` fica: "Cancelar emissão"
   reusa a mesma caixa de proposito (ver `abrirCancelar` em controle.js). */
.ctrl-rev-acoes { display: flex; justify-content: flex-end; gap: var(--sp-2); margin: var(--sp-4) 0 0; padding: 0; }

/* Trazer folhas da OS anterior: mesma familia, mais larga porque o nome da
   folha e longo (o padrao do cliente costuma passar de 30 caracteres). */
.ctrl-trazer-dialog { width: min(620px, 94vw); padding: 0; border: 1px solid var(--border); border-radius: var(--r-2); background: var(--panel); color: var(--text); }
.ctrl-trazer-dialog::backdrop { background: rgb(0 0 0 / .55); }
.ctrl-trazer-form { padding: var(--sp-4); }
.ctrl-trazer-titulo { display: flex; align-items: center; gap: 8px; margin: 0; font-size: var(--fs-4); }
.ctrl-trazer-titulo i, .ctrl-trazer-titulo svg { width: 17px; height: 17px; color: var(--accent); }
.ctrl-trazer-dica { margin: 6px 0 var(--sp-3); color: var(--muted); font-size: var(--fs-1); }
/* Lista rolavel: projeto grande passa de 20 folhas, e sem limite a caixa saia
   da tela levando os botoes junto. */
.ctrl-trazer-lista { max-height: min(46vh, 380px); overflow-y: auto; border: 1px solid var(--border); border-radius: var(--r-2); background: var(--panel-2); }
.ctrl-trazer-item { display: flex; align-items: center; gap: var(--sp-2); padding: 6px 10px; border-bottom: 1px solid var(--border); }
.ctrl-trazer-item:last-child { border-bottom: 0; }
.ctrl-trazer-item:hover { background: var(--panel); }
.ctrl-trazer-check { width: 15px; height: 15px; min-height: 0; flex: 0 0 auto; margin: 0; }
.ctrl-trazer-nome { flex: 1 1 auto; word-break: break-word; }
/* O nome e editavel: quando a fase muda, ele nasce com o codigo da fase nova e
   o Fabio confere. `min-height: 0` porque a regra global de input impoe altura
   de campo de formulario -- aqui sao 20 linhas numa caixa rolavel. */
.ctrl-trazer-nome-input { flex: 1 1 auto; min-width: 0; min-height: 0; padding: 4px 7px; border: 1px solid transparent; border-radius: var(--r-1); background: transparent; color: var(--text); font: inherit; }
.ctrl-trazer-nome-input:hover { border-color: var(--border); background: var(--panel); }
.ctrl-trazer-nome-input:focus { border-color: var(--accent); background: var(--panel); outline: none; }
.ctrl-trazer-meta { flex: 0 0 auto; color: var(--muted); font-size: var(--fs-1); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Marca so nas linhas em que o SISTEMA mexeu no nome. `--accent` e `--accent-soft`
   existem em tokens.css -- conferido, e nao chutado: `var(--x)` inexistente nao
   da erro, so nasce sem efeito (foi assim que o crachá de divergência saiu branco). */
.ctrl-trazer-marca { flex: 0 0 auto; padding: 1px 7px; border: 1px solid var(--accent); border-radius: var(--r-full); background: var(--accent-soft); color: var(--accent); font-size: var(--fs-1); white-space: nowrap; }
.ctrl-trazer-acoes { display: flex; justify-content: flex-end; gap: var(--sp-2); margin: var(--sp-4) 0 0; padding: 0; }

/* ================= Detalhe redesenhado (mockup) ================= */
.ctrl-badge { display: inline-block; margin-left: 8px; padding: 2px 10px; border-radius: var(--r-full); font-size: var(--fs-1); font-weight: var(--fw-bold); vertical-align: 2px; }
.ctrl-badge-ativo { background: var(--success-soft); color: var(--fabim-success); }
.ctrl-badge-done { background: var(--accent-soft); color: var(--accent); }
.ctrl-badge-hold { background: var(--warning-soft); color: var(--fabim-warning); }

/* Congelado junto com o cabecalho da tabela: fica no topo e o thead gruda logo
   abaixo dele (--ctrl-sum-h e a altura real, medida por JS a cada render). */
.ctrl-summary-card { display: flex; flex-wrap: wrap; align-items: stretch; gap: var(--sp-4); margin-bottom: var(--sp-4); padding: var(--sp-4); background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--r-2); position: sticky; top: 0; z-index: 10; }
.ctrl-sum-metric { display: flex; align-items: center; gap: var(--sp-3); min-width: 150px; }
.ctrl-sum-metric > i, .ctrl-sum-metric > svg { width: 24px; height: 24px; color: var(--accent); flex: 0 0 auto; }
.ctrl-sum-metric strong { display: block; font-size: var(--fs-5); font-weight: var(--fw-bold); line-height: 1.1; }
.ctrl-sum-metric small { color: var(--muted); font-size: var(--fs-1); }
/* Explica de onde vem a diferenca entre o total e a soma das folhas visiveis:
   a folha cancelada sai da relacao e as horas continuam no projeto. Sem isto,
   a gaveta e o card mostravam numeros diferentes sem justificativa na tela
   (auditoria 21/08/2026, ALTO). So aparece quando ha hora cancelada. */
.ctrl-sum-canceladas { color: var(--muted); font-style: italic; white-space: nowrap; }
.ctrl-sum-progress { flex: 1 1 220px; min-width: 190px; display: flex; flex-direction: column; justify-content: center; gap: 5px; padding: 0 var(--sp-3); border-left: 1px solid var(--border); }
.ctrl-sum-prog-label { color: var(--muted); font-size: var(--fs-1); letter-spacing: .04em; }
.ctrl-sum-prog-row { display: flex; align-items: center; gap: var(--sp-3); }
.ctrl-sum-prog-row .ctrl-progress { flex: 1 1 auto; }
.ctrl-sum-prog-row .ctrl-progress-bar { background: var(--fabim-success); }
.ctrl-sum-prog-pct { font-size: var(--fs-5); font-weight: var(--fw-bold); color: var(--fabim-success); }
.ctrl-sum-prog-foot { color: var(--muted); font-size: var(--fs-1); white-space: nowrap; }
/* Barra de ETAPAS: mesma anatomia da "Progresso geral", mas em azul FABIM. */
.ctrl-sum-progress--etapas .ctrl-progress-bar { background: var(--accent); }
.ctrl-sum-progress--etapas .ctrl-sum-prog-pct { color: var(--accent); }
.ctrl-sum-period { display: flex; align-items: center; gap: var(--sp-3); padding-left: var(--sp-3); border-left: 1px solid var(--border); }
.ctrl-sum-period > i { width: 22px; height: 22px; color: var(--muted); flex: 0 0 auto; }
.ctrl-sum-period small { display: block; color: var(--muted); font-size: var(--fs-1); letter-spacing: .04em; }
.ctrl-sum-period strong { font-size: var(--fs-4); }
.ctrl-sum-days { background: var(--panel-3); border-radius: var(--r-full); padding: 2px 10px; font-size: var(--fs-1); color: var(--muted); }

.ctrl-item-name i { width: 15px; height: 15px; color: var(--accent); margin-right: 6px; vertical-align: -3px; }
/* Nome da folha editavel na propria linha: parece texto ate hover/foco.
   Sem flex no <td> (quebra a tabela): largura = celula menos o icone DWG.
   E <textarea> (nao input) porque o codigo da folha e longo e precisa quebrar
   em varias linhas como antes; a altura e ajustada por JS (autoGrowName). */
.ctrl-item-name-input {
  display: inline-block; width: calc(100% - 44px); min-height: 0; height: auto;
  padding: 4px 6px; vertical-align: middle; resize: none; overflow: hidden;
  line-height: 1.25; word-break: break-word;
  border: 1px solid transparent; border-radius: var(--r-1); background: transparent;
  color: var(--text); font: inherit; font-weight: var(--fw-medium);
}
.ctrl-item-name-input:hover { border-color: var(--border); background: var(--panel-2); }
.ctrl-item-name-input:focus { outline: none; border-color: var(--accent); background: var(--panel); }
/* Nome + engrenagem na mesma celula: o flex e no wrapper (nao no <td>, que
   quebraria a tabela). A engrenagem ficou aqui para liberar a coluna Acoes. */
.ctrl-item-name-wrap { display: flex; align-items: center; gap: 4px; }
.ctrl-item-name-wrap .ctrl-item-name-input { flex: 1 1 auto; width: auto; min-width: 0; }
.ctrl-item-name-wrap .ctrl-item-atv { flex: 0 0 auto; }
/* Os dois botoes da folha empilhados: ABRIR/RECOLHER o controle diario em cima,
   atividades embaixo. Em coluna porque a celula do nome e estreita e alta -- lado
   a lado eles roubariam largura justamente do codigo da folha, que e longo. */
.ctrl-item-btns { display: flex; flex-direction: column; gap: 4px; flex: 0 0 auto; }
/* Botao que abre a raia de datas. Fechado e discreto; aberto acende no accent
   para a folha expandida se achar de relance numa lista longa.
   Dimensiona `i, svg`: o Lucide troca o <i> por <svg> depois do render. */
.ctrl-item-diaria { min-height: 0; }
.ctrl-item-diaria i, .ctrl-item-diaria svg { width: 16px; height: 16px; }
.ctrl-item-diaria.is-aberta { color: var(--accent); border-color: var(--accent); }
/* Folha recolhida: a linha dela e a unica na tela, entao carrega o separador
   grosso que normalmente fica no rodape da tabela diaria (.ctrl-item-daily).
   Sem isto, uma folha encosta na seguinte e a raia perde o contorno. */
.ctrl-item-row.is-diaria-recolhida > td { border-bottom: 2px solid var(--border); }
/* Grupos recolhiveis das folhas: "Em andamento" e "Concluídas". O botao ocupa a
   faixa inteira e abre/fecha a lista logo abaixo. */
.ctrl-group-head > td { padding: 0; text-align: left; background: var(--panel-2); border-bottom: 1px solid var(--border); }
.ctrl-group-toggle {
  display: flex; align-items: center; gap: var(--sp-2); width: 100%; min-height: 0;
  padding: 10px var(--sp-4); border: 0; border-radius: 0; background: transparent;
  color: var(--text); cursor: pointer;
  font-size: var(--fs-2); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: .03em;
}
.ctrl-group-toggle:hover { background: var(--hover-glass); }
/* lucide troca <i> por <svg>: dimensionar os dois (senao vira 24px/17px do base.css) */
.ctrl-group-toggle i, .ctrl-group-toggle svg { width: 16px; height: 16px; flex: 0 0 auto; }
.ctrl-group-caret { color: var(--muted); }
.ctrl-group-icon { color: var(--accent); }
/* A faixa passou a ter DOIS controles: o titulo (abre/fecha o grupo) e o
   "Abrir/Recolher todas" (as raias de datas das folhas). Lado a lado num flex --
   aninhar um <button> dentro do outro seria HTML invalido. */
/* A faixa CONGELA junto: rolando uma lista longa, some da tela o nome do grupo
   a que a folha pertence. Fica logo abaixo do card de resumo, e o cabecalho das
   colunas gruda abaixo dela (--ctrl-bar-h, medido por JS).
   Fundo OPACO obrigatorio: `.ctrl-group-toggle` e transparente e, congelado, as
   linhas passariam por dentro do texto da faixa.
   z-index 4: acima do thead (3), abaixo do card de resumo (5). */
.ctrl-group-bar {
  display: flex; align-items: center; gap: var(--sp-2);
  position: sticky; background: var(--panel-2);
  /* O DEGRAU. `--ordem` vem inline (0 = Em andamento, 1 = Concluidas, 2 = Visao
     geral): cada faixa para uma altura de faixa abaixo da anterior, entao a
     anterior e o limite da seguinte e nenhuma cobre nenhuma. */
  top: calc(var(--ctrl-sum-h, 0px) + var(--ordem, 0) * var(--ctrl-bar-h, 0px));
  /* Cresce com a ordem: durante a troca, a faixa que chega passa por cima do
     cabecalho de colunas do grupo anterior (z 3) em vez de por baixo. Fica
     abaixo do card de resumo (10) e do cabecalho da gaveta (11). */
  z-index: calc(4 + var(--ordem, 0));
  /* O quadro era do wrapper que sumiu: agora a faixa faz o topo da caixa e o
     `.ctrl-grupo-corpo` fecha embaixo. */
  border: 1px solid var(--border); border-radius: var(--r-2) var(--r-2) 0 0;
}
/* Grupo recolhido: a faixa E a caixa inteira -- arredonda embaixo tambem. */
.ctrl-group-bar.is-fechada { border-radius: var(--r-2); margin-bottom: var(--sp-4); }
.ctrl-grupo-corpo {
  min-width: fit-content; margin-bottom: var(--sp-4); background: var(--panel);
  border: 1px solid var(--border); border-top: 0; border-radius: 0 0 var(--r-2) var(--r-2);
}
/* O cabecalho das colunas gruda um degrau abaixo da SUA faixa. */
.ctrl-grupo-corpo .ctrl-detail-table > thead > tr > th,
.ctrl-grupo-corpo .ctrl-vf-table thead th {
  top: calc(var(--ctrl-sum-h, 0px) + (var(--ordem, 0) + 1) * var(--ctrl-bar-h, 0px));
}
.ctrl-group-bar .ctrl-group-toggle { flex: 1 1 auto; width: auto; }
.ctrl-group-todas {
  display: flex; align-items: center; gap: 6px; flex: 0 0 auto; min-height: 0;
  margin-right: var(--sp-4); padding: 5px 10px;
  border: 1px solid var(--border); border-radius: var(--r-full); background: transparent;
  color: var(--muted); cursor: pointer; white-space: nowrap;
  font-size: var(--fs-1); font-weight: var(--fw-medium); letter-spacing: .02em;
}
.ctrl-group-todas:hover { border-color: var(--accent); color: var(--accent); background: var(--hover-glass); }
/* lucide troca <i> por <svg>: dimensionar os dois, senao herda 24px do base.css */
.ctrl-group-todas i, .ctrl-group-todas svg { width: 14px; height: 14px; flex: 0 0 auto; }
.ctrl-group-bar[data-group="concluidas"] .ctrl-group-icon { color: var(--fabim-success); }
/* Quadro separado das concluidas (fica depois do "Adicionar folha"): a faixa do
   grupo e o cabecalho da caixa; a tabela so existe no DOM quando expandida. */
/* As DUAS caixas de grupo saem do mesmo helper e usam o mesmo quadro. */
/* O arredondamento saiu do BOTAO e foi para a FAIXA: e ela que encosta na borda
   agora, porque o botao divide a faixa com o "Abrir todas" -- arredondar so o
   botao deixava um canto reto sobrando ao lado dele. */
/* A visao geral das folhas usa a mesma faixa recolhivel do "Concluídas" -- e,
   como elas, CONGELA no topo (fundo opaco: o botao e transparente e as linhas
   passariam por dentro do texto). */
/* O botao da visao geral e so o TITULO da faixa, como nos outros dois grupos:
   quem congela e o `.ctrl-group-bar` que o envolve. Um sticky proprio aqui
   brigaria com o da faixa e voltaria a prende-lo ao quadro antigo. */
.ctrl-vf-head { width: 100%; }
.ctrl-group-count { margin-left: 6px; padding: 1px 9px; border-radius: var(--r-full); background: var(--panel-3); color: var(--muted); font-size: var(--fs-1); }

/* Cada folha e uma raia fechada: linha da folha + o "Controle diario" dela logo
   abaixo, recuado, e um separador mais forte antes da proxima folha. */
.ctrl-item-daily > td { padding: 0 0 var(--sp-3); text-align: left; background: var(--panel-2); border-bottom: 2px solid var(--border); }
.ctrl-item-daily .ctrl-daily { background: var(--panel); }
/* Ícone de arquivo com "DWG" escrito (referência) — não é chip de texto. */
.ctrl-dwg { position: relative; display: inline-flex; margin-right: 7px; vertical-align: middle; flex: 0 0 auto; }
.ctrl-dwg i, .ctrl-dwg svg { width: 32px; height: 32px; color: var(--accent); }
.ctrl-dwg b { position: absolute; left: 50%; bottom: 7px; transform: translateX(-50%); font-size: 8px; font-weight: var(--fw-bold); letter-spacing: .02em; color: var(--accent); white-space: nowrap; }
/* Acumulado da atividade (soma de todos os dias), entre as horas de hoje e o
   "quem fez". Continua visivel quando a etapa esta concluida. */
.ctrl-stage-total {
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  padding: 2px 9px; border-radius: var(--r-full);
  background: var(--panel-3); color: var(--text);
  font-size: var(--fs-1); font-weight: var(--fw-bold); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.ctrl-stage-total i, .ctrl-stage-total svg { width: 11px; height: 11px; color: var(--muted); flex: 0 0 auto; }
.ctrl-stage-total.is-zero { color: var(--muted); }
/* H. executadas: total de HOJE em cima, total da folha embaixo. */
.ctrl-exec-cell { font-variant-numeric: tabular-nums; }
.ctrl-exec-cell > span { display: block; line-height: 1.15; }
.ctrl-exec-hoje { color: var(--fabim-success); font-size: var(--fs-5); font-weight: var(--fw-bold); }
.ctrl-exec-hoje.is-zero { color: var(--muted); }
.ctrl-exec-folha { margin-top: 4px; color: var(--text); font-size: var(--fs-4); font-weight: var(--fw-bold); }
.ctrl-exec-cell small { display: block; color: var(--muted); font-size: 10px; text-transform: uppercase; letter-spacing: .04em; font-weight: var(--fw-medium); }
/* "A fazer": o slot de horas aparece, mas bloqueado (so lanca em "Fazendo"). */
.ctrl-stage-hours.is-locked { opacity: .5; }
.ctrl-stage-hours.is-locked .ctrl-hours-step { cursor: not-allowed; color: var(--border); }
.ctrl-stage-hours.is-locked .ctrl-hours-step:hover { background: transparent; }

/* Alvo = horas PLANEJADAS (padrao em todo o sistema). Dimensiona i e svg: o
   lucide troca a tag e o svg cairia no tamanho padrao. */
.ctrl-week-hours i[data-lucide="target"], .ctrl-week-hours svg.lucide-target,
.pd-estimate i[data-lucide="target"], .pd-estimate svg.lucide-target {
  width: 13px; height: 13px; margin: 0 3px -2px 2px; color: var(--accent);
}

/* Visao geral das folhas (abaixo do "Adicionar folha"): tabela de verdade --
   o texto e o TITULO da coluna e a celula fica so com o indicador. */
/* O quadro proprio da visao geral SAIU: ele prendia a faixa dela (sticky nunca
   passa do bloco que a contem) e a fazia sumir ao fim da lista. Agora a visao
   geral e a terceira caixa de grupo, com faixa e corpo irmaos como as outras --
   quem desenha o quadro sao `.ctrl-group-bar` + `.ctrl-grupo-corpo`. */
/* Colunas ALINHADAS com o quadro de folhas: mesmos tokens de largura, mesmo
   `table-layout: fixed` e o mesmo min-width. Sem isto a visao geral distribuia
   sozinha (nome 260px, progresso 132px) e nenhuma coluna caia sob o titulo
   correspondente la de cima. A coluna de Acoes nao existe aqui, mas la ela e
   colapsada para 0 -- entao o que sobra para as etapas e o mesmo nos dois. */
.ctrl-vf-table { width: 100%; min-width: 1000px; table-layout: fixed; border-collapse: collapse; font-size: var(--fs-2); }
/* Mesmo respiro do quadro de folhas (.ctrl-detail-table th, td): 9px 8px
   deixava a visao geral com as celulas mais estreitas que as dos grupos. */
.ctrl-vf-table th, .ctrl-vf-table td { padding: 8px 10px; text-align: center; border-bottom: 1px solid var(--border); }
.ctrl-vf-table tbody tr:last-child td { border-bottom: 0; }
.ctrl-vf-table tbody tr:hover { background: var(--panel-2); }
/* Divisorias nas LINHAS, no mesmo traco do cabecalho. A ultima coluna fica de
   fora: o traco cairia sobre a borda do quadro. */
.ctrl-vf-table tbody td:not(:last-child) { position: relative; }
.ctrl-vf-table tbody td:not(:last-child)::after {
  content: ""; position: absolute; top: 50%; right: 0; transform: translateY(-50%);
  width: 1px; height: 40%; background: var(--fabim-line-strong); opacity: .55;
}
/* Cabecalho CONGELADO, no mesmo offset do quadro de folhas (--ctrl-sum-h e a
   altura do card de resumo, medida por JS). Ficou `static` por um tempo porque
   o quadro era curto; com muitas folhas a lista passa da tela e a linha some do
   contexto, entao gruda como nas outras tabelas.
   Efeito colateral bem-vindo: `thead th::after` (components.css, o traco entre
   colunas) e ABSOLUTO -- com `static` ele se ancorava fora da celula e nao
   aparecia. Posicionado, as divisorias do cabecalho voltam sozinhas. */
.ctrl-vf-table thead th {
  position: sticky; top: calc(var(--ctrl-sum-h, 0px) + var(--ctrl-bar-h, 0px)); z-index: 3; height: auto;
  /* Base OPACA + vidro: so o --thead-glass (translucido) caia no mesmo tom da
     barra "Visão geral" e os dois viravam um bloco unico. */
  background: linear-gradient(var(--thead-glass), var(--thead-glass)), var(--panel-3, var(--panel));
  color: var(--thead-text);
  /* MESMA tipografia do cabecalho dos outros grupos: font-size --fs-1 e
     letter-spacing .045em vem da regra global de `thead th` (components.css).
     Havia aqui um tamanho fixo e um letter-spacing menor, e a visao geral saia
     com o titulo visivelmente menor e mais apertado que "Em andamento" e
     "Concluídas" -- as tres estao uma embaixo da outra, a diferenca salta. */
  font-weight: var(--fw-bold); text-transform: uppercase;
}
.ctrl-vf-h span { display: inline-block; line-height: 1.15; white-space: normal; word-break: break-word; }
/* Cabecalho da visao geral clicavel: ordena pela coluna, e o segundo clique
   inverte. A seta indica a direcao; sem ordenacao ela fica neutra. */
/* TITULO CENTRADO NA COLUNA (queixa do Fabio, 20/08/2026: "as colunas com
   titulos nao estao centralizadas").

   Era `justify-content: inherit`, e isso nunca centralizou nada: `justify-
   content` NAO e propriedade herdada, entao `inherit` copia o valor computado
   do <th> -- que e `normal`, ou seja, empacota tudo a ESQUERDA. Como o botao
   tem `width: 100%`, ele cobre a coluna inteira e o `text-align: center` do
   <th> nao alcanca o conteudo flex. Medido: o rotulo caia 46px a esquerda do
   centro da coluna de dados.

   Centrado agora e o ROTULO, nao o conjunto rotulo+seta: com a seta no fluxo, o
   grupo fica centrado mas o texto sozinho ainda escorrega metade da seta mais a
   folga (7px medidos). Por isso a seta sai do fluxo, para o respiro da direita,
   e o respiro e simetrico -- e o que faz o texto cair no centro exato (medido:
   desvio 0px em todas as colunas).

   O `width: 100%` fica: e ele que faz a coluna INTEIRA ser clicavel para
   ordenar. */
.ctrl-vf-sort {
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  position: relative; width: 100%; padding: 0 13px; border: 0; background: transparent; cursor: pointer;
  color: inherit; font: inherit; text-align: inherit; text-transform: inherit; letter-spacing: inherit;
}
.ctrl-vf-sort:hover { color: var(--text); }
.ctrl-vf-sort i, .ctrl-vf-sort svg {
  position: absolute; right: 0; top: 50%; transform: translateY(-50%);
  width: 11px; height: 11px; flex: 0 0 auto; opacity: .45;
}
.ctrl-vf-table th.is-ordenada .ctrl-vf-sort { color: var(--fabim-success); }
.ctrl-vf-table th.is-ordenada .ctrl-vf-sort i, .ctrl-vf-table th.is-ordenada .ctrl-vf-sort svg { opacity: 1; }
/* Os grupos "Em andamento"/"Concluídas" ganharam os MESMOS cabecalhos
   ordenaveis da visao geral -- o realce da coluna ativa vale la tambem. */
.ctrl-detail-table th.is-ordenada .ctrl-vf-sort { color: var(--fabim-success); }
.ctrl-detail-table th.is-ordenada .ctrl-vf-sort i, .ctrl-detail-table th.is-ordenada .ctrl-vf-sort svg { opacity: 1; }
/* A coluna do NOME continua a esquerda, alinhada com os nomes de folha abaixo
   dela -- centralizar so ela ficaria torto. Vale nas DUAS tabelas: a visao geral
   usa `.ctrl-vf-nome-h` e a do detalhe usa `.ctrl-nome-h` (nomes diferentes para
   o mesmo papel; faltando a segunda, o titulo "Folha / Item" ia para o meio). */
.ctrl-vf-nome-h .ctrl-vf-sort,
.ctrl-nome-h .ctrl-vf-sort { justify-content: flex-start; padding-left: 0; }

/* COLUNA DE ETAPA: a seta desce para uma linha propria, e para de RESERVAR
   largura (20/08/2026). O `padding: 0 13px` do botao existia para a seta
   absoluta nao cair em cima do texto -- 26px por coluna, vezes 7 etapas, 182px
   de largura de projeto gastos com espaco para uma seta que fica apagada em 6
   das 7. Como a largura do quadro e o que define a escala, esses 182px saiam do
   TAMANHO DO TEXTO em monitor de notebook.

   Medido no Chrome 151, com os 7 rotulos reais: a fila de etapas cai de 739px
   para 557px e a coluna mais larga de 128px para 102px, com ZERO colisao entre
   seta e texto. Custa 13px de altura de cabecalho -- pagos com juros pela
   escala, que sobe de 0,82 para 0,98 numa tela de 1366px.

   Nao tentar de novo a versao "seta absoluta sem padding": foi medida e colide
   em 6 dos 7 rotulos. So "Limpeza + Padronizacao" escapa, por sorte da quebra
   dela -- a primeira linha fica curta e a seta cai no vazio. As outras seis sao
   de uma linha so, que ocupa a coluna inteira.

   Vale nas DUAS tabelas: `.ctrl-stage-head` no detalhe, `.ctrl-vf-h` na visao
   geral. O cabecalho do NOME fica de fora de proposito: ele e largo, tem folga
   de sobra, e empilhar a seta la so o deixaria mais alto a troco de nada. */
.ctrl-stage-head .ctrl-vf-sort,
.ctrl-vf-h .ctrl-vf-sort { flex-direction: column; gap: 2px; padding: 0; }
.ctrl-stage-head .ctrl-vf-sort i, .ctrl-stage-head .ctrl-vf-sort svg,
.ctrl-vf-h .ctrl-vf-sort i, .ctrl-vf-h .ctrl-vf-sort svg {
  position: static; transform: none;
}
.ctrl-vf-nome-h, .ctrl-vf-nome { text-align: left; width: var(--ctrl-col-nome); }
.ctrl-vf-nome { color: var(--text); font-weight: var(--fw-medium); word-break: break-word; }
.ctrl-vf-nome .ctrl-dwg { margin-right: 5px; vertical-align: middle; }
.ctrl-vf-dot { width: 19px; height: 19px; color: var(--muted); opacity: .5; vertical-align: middle; }
.ctrl-vf-dot.is-done { color: var(--fabim-success); opacity: 1; }
.ctrl-vf-dot.is-doing { color: var(--fabim-warning); opacity: 1; }
.ctrl-vf-dot.is-na { opacity: .3; }
.ctrl-vf-horas-h, .ctrl-vf-horas { width: var(--ctrl-col-exec); }
.ctrl-vf-horas { color: var(--text); font-weight: var(--fw-bold); font-variant-numeric: tabular-nums; }
.ctrl-vf-prog-h, .ctrl-vf-prog { width: var(--ctrl-col-prog); }
.ctrl-vf-pct { color: var(--fabim-success); font-weight: var(--fw-bold); }
.ctrl-vf-etapas { margin-left: 6px; color: var(--muted); font-size: var(--fs-1); }
.ctrl-vf-prog .ctrl-prog-mini { margin-top: 4px; }

/* Resumo do projeto + Horas por responsavel lado a lado */
/* A margem de topo e do grid: nos filhos, desalinhava os dois cards. */
.ctrl-painel-duplo { display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); gap: var(--sp-4); align-items: stretch; margin-top: var(--sp-4); }
.ctrl-painel-duplo > .ctrl-resumo-total,
.ctrl-painel-duplo > .ctrl-horas-resp { margin: 0; }
.ctrl-horas-resp { padding: var(--sp-4); border: 1px solid var(--border); border-radius: var(--r-2); background: var(--panel-2); }
/* Cabecalho do painel: titulo com icone + subtitulo + alerta a direita */
.ctrl-hr-head-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ctrl-hr-head .ctrl-resumo-title { display: flex; align-items: center; gap: 7px; }
.ctrl-hr-head .ctrl-resumo-title i, .ctrl-hr-head .ctrl-resumo-title svg { width: 16px; height: 16px; color: var(--fabim-success); }
.ctrl-hr-sub { display: block; margin-top: 3px; color: var(--muted); font-size: var(--fs-1); }
/* Alerta: ha horas lancadas sem "quem fez". Triangulo vermelho neon que pulsa. */
.ctrl-hr-alert { flex: 0 0 auto; display: inline-grid; place-items: center; width: 28px; height: 28px; padding: 0; min-height: 0;
  border: 0; border-radius: var(--r-full); cursor: help; color: #ff4d4f;
  background: color-mix(in srgb, #ff4d4f 14%, transparent);
  animation: ctrl-hr-pulse 1.25s ease-in-out infinite; }
.ctrl-hr-alert i, .ctrl-hr-alert svg { width: 16px; height: 16px; }
.ctrl-hr-alert:hover, .ctrl-hr-alert:focus-visible { color: #ff6b6b; outline: none; }
.ctrl-hr-vazio-alert { color: #ff6b6b; }
@keyframes ctrl-hr-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, #ff4d4f 50%, transparent), 0 0 5px color-mix(in srgb, #ff4d4f 45%, transparent); }
  50% { box-shadow: 0 0 0 6px color-mix(in srgb, #ff4d4f 0%, transparent), 0 0 13px color-mix(in srgb, #ff4d4f 80%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .ctrl-hr-alert { animation: none; } }
/* Tooltip (hover) do painel: folhas/atividades/horas da pessoa, ou o alerta. */
.ctrl-hr-tip { position: fixed; z-index: 60; max-width: 320px; max-height: 260px; overflow: auto;
  padding: 9px 11px; border-radius: var(--r-2); border: 1px solid var(--border);
  background: color-mix(in srgb, var(--panel) 94%, #000); box-shadow: 0 10px 28px rgb(0 0 0 / .45);
  color: var(--text); font-size: var(--fs-1); pointer-events: none; }
.ctrl-hr-tip[hidden] { display: none; }
.ctrl-hr-tip-head { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; padding-bottom: 5px;
  border-bottom: 1px solid var(--border); font-weight: var(--fw-bold); font-size: var(--fs-2); }
.ctrl-hr-tip-head b { margin-left: auto; color: var(--fabim-success); font-variant-numeric: tabular-nums; }
.ctrl-hr-tip-head.is-alert { color: #ff6b6b; }
.ctrl-hr-tip-head.is-alert b { color: #ff6b6b; }
.ctrl-hr-tip-head i, .ctrl-hr-tip-head svg { width: 14px; height: 14px; }
.ctrl-hr-tip-row { display: flex; justify-content: space-between; gap: 14px; padding: 2px 0; }
.ctrl-hr-tip-row span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); }
.ctrl-hr-tip-row b { flex: 0 0 auto; color: var(--text); font-variant-numeric: tabular-nums; }
.ctrl-hr-tip-foot { margin-top: 6px; padding-top: 5px; border-top: 1px solid var(--border); color: var(--muted); }
.ctrl-hr-seg, .ctrl-hr-item[data-hr-nome] { cursor: help; }
/* Fixado no clique: fica parado e rolavel (pode entrar com o mouse). Maior que
   o de hover para caber mais folhas de uma vez; ainda rola se passar. */
.ctrl-hr-tip.is-pinned { pointer-events: auto; width: 440px; max-width: 92vw; max-height: min(74vh, 560px);
  border-color: color-mix(in srgb, var(--accent) 55%, var(--border));
  box-shadow: 0 12px 32px rgb(0 0 0 / .5), 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent); }
/* Fixado mostra tudo: a linha quebra (folha + etapa inteiras), sem reticencia. */
.ctrl-hr-tip.is-pinned .ctrl-hr-tip-row span { white-space: normal; overflow: visible; text-overflow: clip; }
.ctrl-hr-tip-close { position: absolute; top: 6px; right: 6px; display: none; place-items: center; width: 22px; height: 22px;
  min-height: 0; padding: 0; border: 0; border-radius: var(--r-1); background: transparent; color: var(--muted); cursor: pointer; }
.ctrl-hr-tip.is-pinned .ctrl-hr-tip-close { display: grid; }
.ctrl-hr-tip-close:hover { background: var(--hover-glass); color: var(--text); }
.ctrl-hr-tip-close i, .ctrl-hr-tip-close svg { width: 14px; height: 14px; }
/* espaco pro X nao cobrir o total do cabecalho */
.ctrl-hr-tip.is-pinned .ctrl-hr-tip-head { padding-right: 22px; }
/* "NN% / Total da equipe" centralizado sobre a barra */
.ctrl-hr-total { text-align: center; margin-top: var(--sp-3); }
.ctrl-hr-total b { display: block; color: var(--fabim-success); font-size: var(--fs-6); font-weight: var(--fw-bold); font-variant-numeric: tabular-nums; line-height: 1.1; }
.ctrl-hr-total small { color: var(--muted); font-size: var(--fs-1); }
/* Barra empilhada de 100%: cada fatia = participacao de um responsavel.
   Fatias arredondadas com neon (borda + brilho na cor) e preenchimento
   translucido; crescem proporcional as horas (flex-grow inline) e preenchem a
   barra com um vao entre elas. --seg = cor da pessoa (inline). */
.ctrl-hr-stack { display: flex; gap: 6px; height: 40px; margin: var(--sp-2) 0 var(--sp-4); padding: 1px; }
.ctrl-hr-seg { flex-basis: 0; flex-shrink: 1; min-width: 0; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-weight: var(--fw-bold); font-size: var(--fs-2); font-variant-numeric: tabular-nums; white-space: nowrap;
  border-radius: var(--r-2); border: 2px solid var(--seg);
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--seg) 52%, transparent),
    color-mix(in srgb, var(--seg) 26%, transparent));
  box-shadow: 0 0 14px color-mix(in srgb, var(--seg) 60%, transparent),
    0 0 4px color-mix(in srgb, var(--seg) 90%, transparent),
    inset 0 1px 0 rgb(255 255 255 / .22);
  text-shadow: 0 1px 3px rgb(0 0 0 / .55); }
/* Legenda: dot da cor + avatar (anel da cor) + nome/horas/% empilhados.
   Divisoria entre os responsaveis vem da borda esquerda de cada item. */
.ctrl-hr-lista { display: flex; flex-wrap: wrap; gap: 0; }
.ctrl-hr-item { flex: 1 1 auto; min-width: 148px;
  display: grid; grid-template-columns: 10px 34px minmax(0, 1fr); align-items: center; column-gap: 8px; row-gap: 0;
  padding: 4px var(--sp-3); border-left: 1px solid var(--border); }
.ctrl-hr-item:first-child { border-left: 0; padding-left: 0; }
.ctrl-hr-dot { width: 10px; height: 10px; border-radius: var(--r-full); grid-row: 1 / span 3; align-self: center; }
.ctrl-hr-av { grid-column: 2; grid-row: 1 / span 2; display: inline-flex; }
.ctrl-hr-av .ctrl-avatar { width: 34px; height: 34px; box-shadow: 0 0 0 2px var(--cor); }
.ctrl-hr-nome { grid-column: 3; grid-row: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-1); font-weight: var(--fw-bold); color: var(--text); }
.ctrl-hr-horas { grid-column: 3; grid-row: 2; font-size: var(--fs-3); font-weight: var(--fw-bold); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ctrl-hr-pct { grid-column: 2 / -1; grid-row: 3; margin-top: 1px; color: var(--muted); font-size: 10px; font-weight: var(--fw-bold); }
.ctrl-hr-vazio { color: var(--muted); font-size: var(--fs-2); margin-top: var(--sp-3); }

/* Total do dia na tabela de registro */
.ctrl-daily-dia, .ctrl-daily-dia-h { border-left: 1px solid var(--border); font-weight: var(--fw-bold); }
/* Divisorias na tabela de datas, mesmo traco curto do quadro de folhas.
   `:has(+ .ctrl-daily-dia)` tira o traco da ULTIMA etapa: "Total do dia" ja
   abre com uma borda de altura cheia (acima), e os dois cairiam no mesmo 1px --
   ficaria uma linha cheia com o meio mais escuro.
   Fora tambem a coluna de Acoes, que tem largura 0 e o pill flutuante. */
.ctrl-daily-table tbody td.ctrl-daily-date,
.ctrl-daily-table tfoot td.ctrl-daily-total-label,
.ctrl-daily-table td.ctrl-daily-cell:not(.ctrl-daily-dia):not(:has(+ .ctrl-daily-dia)) { position: relative; }
.ctrl-daily-table tbody td.ctrl-daily-date::after,
.ctrl-daily-table tfoot td.ctrl-daily-total-label::after,
.ctrl-daily-table td.ctrl-daily-cell:not(.ctrl-daily-dia):not(:has(+ .ctrl-daily-dia))::after {
  content: ""; position: absolute; top: 50%; right: 0; transform: translateY(-50%);
  width: 1px; height: 40%; background: var(--fabim-line-strong); opacity: .55;
}
.ctrl-daily-dia { color: var(--fabim-success); }
.ctrl-daily-dia.is-zero { color: var(--muted); }
/* Quem trabalhou no dia: uma pilula por pessoa (avatar + nome + as horas dela),
   agora uma por LINHA — cada pessoa tem a sua, e ninguem edita por cima da
   outra. A soma do dia fica na celula da data, que faz rowspan nas linhas.

   Raia da DATA: fica com o traco solido da tabela (o border-bottom padrao das
   celulas). Pessoa de uma mesma data separa por pontilhado fino, na mesma cor
   de borda do resto — nao um traco proprio, que saltava do layout. Por isso a
   regra mexe no border-BOTTOM da linha que ainda tem gente embaixo, e nao num
   border-top novo: com border-collapse, um topo novo brigava com o rodape
   solido de cima e vencia com a espessura padrao (a linha branca grossa).

   A data e as acoes ficam de fora: como fazem rowspan, o rodape delas cai no
   fim do grupo e e ele que fecha a raia da data.

   A faixa reservada a direita saiu junto com o pill flutuante: com coluna
   propria para as acoes, nada mais passa por cima da pilula da pessoa. */
.ctrl-daily-row-pessoa.is-continuada > td:not(.ctrl-daily-date):not(.ctrl-daily-actions) {
  border-bottom: 1px dotted var(--border);
}
.ctrl-daily-row-pessoa.is-minha .ctrl-dia-quem { border-color: var(--fabim-success); }
/* Editando um dia, o pill de acoes (Descartar/Salvar/Excluir) para de depender
   do hover: sumir ao tirar o mouse era o jeito mais facil de perder o que foi
   digitado. Vale so na linha em edicao — as outras datas nem renderizam pill. */
.ctrl-daily-table .table-row-actions.is-fixo {
  opacity: 1; transform: translate(0, -50%); pointer-events: auto;
}
.ctrl-day-save.is-dirty { color: var(--fabim-success); }
/* Pill da folha fora de cena enquanto um dia esta aberto: dois saves parecidos
   com datas diferentes ao lado um do outro so geram engano. */
.table-row-actions.ctrl-acoes-pill.is-oculto { display: none; }
/* Acoes da raia do dia: pill FLUTUANTE, como no resto do sistema -- dar coluna
   propria a elas desalinhava a diaria da tabela da folha (as duas compartilham
   as larguras --ctrl-col-*). O que fazia os botoes sumirem era outra coisa:

   1) a celula rowspan das acoes nao era o ancoradouro, entao o pill se
      posicionava pela LINHA e escapava do grupo -> `position: relative` aqui;
   2) sem z-index ele ficava atras da pilula de quem trabalhou (fundo proprio);
   3) so `tr:hover` acendia o pill, e a linha que segura a celula rowspan e a
      PRIMEIRA do grupo: passar o mouse na linha de baixo apagava os botoes.
      Os `:has()` abaixo acendem o pill do grupo a partir de qualquer linha
      dele (ate 4 pessoas no mesmo dia, que ja e mais que a equipe inteira). */
/* O pill se ancora na LINHA, nao na celula com rowspan.
   Ancorado na celula ele ficava centrado no GRUPO inteiro e caia bem na
   fronteira entre as duas pessoas -- metade dele em cima da linha de baixo,
   que pinta depois e o encobria. Foi o "so no Fernando, quando a cor muda":
   a linha de baixo do grupo. Na linha, ele fica inteiro dentro da primeira. */
.ctrl-daily-table .table-row-actions { z-index: 4; }
.ctrl-daily-table tbody tr:has(+ tr.is-continuacao:hover) .table-row-actions,
.ctrl-daily-table tbody tr:has(+ tr.is-continuacao + tr.is-continuacao:hover) .table-row-actions,
.ctrl-daily-table tbody tr:has(+ tr.is-continuacao + tr.is-continuacao + tr.is-continuacao:hover) .table-row-actions {
  opacity: 1; transform: translate(0, -50%); pointer-events: auto;
}
/* Trocar a pessoa da linha clicando na foto, e "+"/"−" para inserir/remover. */
.ctrl-dia-quem.is-trocavel { cursor: pointer; }
.ctrl-dia-quem.is-trocavel:hover { border-color: var(--fabim-success); }
.ctrl-dia-acoes-pessoa { display: inline-flex; align-items: center; gap: 2px; margin-left: 4px; vertical-align: middle; }
.ctrl-dia-mini {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; padding: 0; border-radius: var(--r-full);
  background: transparent; border: 1px solid var(--border); color: var(--muted); cursor: pointer;
}
.ctrl-dia-mini:hover { color: var(--text); border-color: var(--fabim-success); }
.ctrl-dia-mini i, .ctrl-dia-mini svg { width: 12px; height: 12px; }
.ctrl-dia-quem-select { font-size: 11px; padding: 2px 6px; max-width: 150px; }
/* Descartar/Salvar do dia moram na celula da DATA (larga, a esquerda, rowspan
   no grupo). Como pill flutuante a direita eles viviam disputando espaco com a
   pilula de quem trabalhou e sumiam. */
.ctrl-dia-edit-acoes { display: flex; align-items: center; justify-content: center; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
.ctrl-dia-edit-acoes button { font-size: 11px; padding: 4px 10px; min-height: 0; }
.ctrl-dia-edit-acoes button i, .ctrl-dia-edit-acoes button svg { width: 13px; height: 13px; }
.ctrl-dia-edit-acoes .icon-button { padding: 4px; width: 26px; height: 26px; }
/* A soma do dia embaixo da data saiu: quem trabalhou aparece pessoa a pessoa
   na coluna "Total do dia", e o numero agregado ali so gerava duvida. */
/* Editando um dia, as outras datas apagam: o destaque vai para a raia aberta e
   ninguem confunde a linha que esta mexendo com as que estao paradas. */
.ctrl-daily-row.is-apagada { opacity: 0.38; }
.ctrl-daily-row.is-apagada .ctrl-dia-quem { filter: grayscale(0.6); }
/* Filtro por pessoa do Planejamento: fica na mesma faixa dos outros filtros e
   se parece com eles (era so o foco numa celula que isolava o recurso, o que
   servia para editar mas nao para olhar a agenda de alguem). */
.planning-person-filter {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 0 10px; border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--panel-2); color: var(--muted);
}
.planning-person-filter i, .planning-person-filter svg { width: 14px; height: 14px; }
/* `background: transparent` aqui deixava o MENU do select branco: sem cor
   propria o Chrome desenha a lista suspensa com o padrao do sistema. As cores
   vao no select E nas <option> -- a lista nao herda o fundo do pai. */
.planning-person-filter select {
  border: 0; background: var(--panel-2); color: var(--text);
  font-size: var(--fs-1); padding: 6px 0; min-height: 0; cursor: pointer;
}
.planning-person-filter select option,
select.ctrl-stage option,
.ctrl-dia-quem-select option { background: var(--panel); color: var(--text); }
/* Status da etapa como SELETOR: qualquer um muda sem entrar na atividade.
   Herda a aparencia do botao antigo (.ctrl-stage) para a celula nao mudar de
   cara -- so o controle por baixo e que e outro. */
select.ctrl-stage {
  appearance: none; -webkit-appearance: none; text-align: center; text-align-last: center;
  cursor: pointer; padding-right: 10px;
}
/* Entrar/sair da atividade: "+" ao lado das fotos. So vale em "Fazendo"; com
   hora lancada ele trava (sair de la e tirar as horas, no lapis do dia). */
.ctrl-stage-participar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; min-height: 0; padding: 0; margin-left: 4px; vertical-align: middle;
  border-radius: var(--r-full); border: 1px solid var(--border);
  background: var(--panel-2); color: var(--muted); cursor: pointer;
}
.ctrl-stage-participar:hover:not(:disabled) { color: var(--text); border-color: var(--fabim-success); }
.ctrl-stage-participar.is-dentro { color: var(--fabim-success); border-color: var(--fabim-success); }
.ctrl-stage-participar:disabled { opacity: .35; cursor: not-allowed; }
.ctrl-stage-participar i, .ctrl-stage-participar svg { width: 12px; height: 12px; }
/* Etapa com mais de uma pessoa: todas as fotos juntas, do mesmo tamanho, sem
   nome -- com duas ou mais, um nome escrito daria a entender que aquela pessoa
   vale mais que as outras. Com uma so, o nome acompanha a foto. */
.ctrl-stage-exec.is-varios { gap: 3px; padding-right: 8px; }
.ctrl-stage-exec.is-varios .ctrl-avatar { width: 20px; height: 20px; }
/* O "pill" de acoes flutua sobre a direita da linha (coluna Acoes recolhida).
   Antes a ultima coluna era so um numero e a sobreposicao passava despercebida;
   com a pilula de quem trabalhou ela cobria o nome e as horas. Reserva-se a
   faixa da direita para o pill cair em espaco vazio, e a pilula encosta a
   esquerda em vez de centralizar. O rodape (Total da atividade) fica de fora:
   la nao ha pill nenhum. */
/* Faixa reservada a direita para o pill flutuante cair em espaco vazio. E
   padding (dentro da celula), nao largura de coluna: nao mexe no alinhamento
   com a tabela da folha. Dois botoes ocupam ~92px; editando sao tres (~137px),
   por isso a raia aberta reserva mais. */
.ctrl-daily-table tbody td.ctrl-daily-dia { padding-right: 96px; text-align: left; }
/* Editando, o pill da direita nem existe (os botoes estao na celula da data),
   entao a pilula da pessoa usa a largura toda -- com os +/− ela precisa. */
.ctrl-daily-table tbody tr.is-editing td.ctrl-daily-dia { padding-right: 10px; }
/* Botoes menores SO na diaria: a coluna "Total do dia" tem ~200px e precisa
   caber a pilula da pessoa; com os icones do tamanho padrao os tres botoes da
   edicao espremiam o nome a 45px. */
.ctrl-daily-table .table-row-actions { gap: 4px; padding: 3px 5px; }
.ctrl-daily-table .table-row-actions .icon-button { width: 26px; height: 26px; min-height: 0; padding: 0; }
.ctrl-daily-table .table-row-actions .icon-button i,
.ctrl-daily-table .table-row-actions .icon-button svg { width: 14px; height: 14px; }
.ctrl-daily-table tbody td.ctrl-daily-dia .ctrl-dia-quem { max-width: 100%; }
/* Hora de outra pessoa: visivel, somada no dia, e fora do meu alcance. */
.ctrl-daily-cell.is-travada { color: var(--muted); font-style: italic; }
.ctrl-daily-edit.is-de-outro .ctrl-hours-val { color: var(--fabim-warning); }
/* .ctrl-add-pessoa saiu com a faixa "Lançar no nome de": a troca de pessoa
   agora acontece na propria pilula (ver .ctrl-dia-quem.is-trocavel). */
.ctrl-dia-quem { display: inline-flex; align-items: center; gap: 6px; max-width: 190px;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--r-full);
  padding: 2px 10px 2px 2px; font-weight: var(--fw-normal); }
.ctrl-dia-quem .ctrl-avatar { flex: 0 0 auto; width: 20px; height: 20px; }
.ctrl-dia-quem-nome { flex: 1 1 auto; text-align: left; font-size: 11px; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ctrl-dia-quem-h { flex: 0 0 auto; font-size: 11px; color: var(--fabim-success); font-variant-numeric: tabular-nums; }
.ctrl-dia-quem.is-sem-dono .ctrl-dia-quem-nome { color: var(--muted); }
.ctrl-dia-quem.is-sem-dono .ctrl-dia-quem-h { color: var(--fabim-warning); }
.ctrl-dia-sem { background: var(--panel); color: var(--muted); border: 1px dashed var(--border); }
.ctrl-dia-sem i, .ctrl-dia-sem svg { width: 11px; height: 11px; }
/* .ctrl-dia-soma saiu: a hora do dia aparece pessoa a pessoa, sem agregado. */
/* Coluna Acoes: a data deixa explicito que a linha e o formulario do dia. */
.ctrl-acoes-dia { display: flex; align-items: center; justify-content: center; gap: 5px; margin-bottom: 5px;
  color: var(--accent); font-size: var(--fs-1); font-weight: var(--fw-bold); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ctrl-acoes-dia i, .ctrl-acoes-dia svg { width: 13px; height: 13px; flex: 0 0 auto; }
.ctrl-acoes-btns { display: inline-flex; align-items: center; gap: 2px; }
.ctrl-prog-cell { min-width: 92px; }
.ctrl-prog-pct { font-weight: var(--fw-bold); color: var(--fabim-success); }
.ctrl-prog-etapas { margin-left: 6px; color: var(--muted); font-size: var(--fs-1); white-space: nowrap; }
/* quantas atividades ficaram de fora da conta ("nao se aplica") */
.ctrl-prog-na { margin-left: 4px; padding: 0 4px; border-radius: var(--r-1);
  background: color-mix(in srgb, var(--muted) 22%, transparent); color: var(--muted); font-size: 10px; }
.ctrl-prog-mini { display: block; height: 5px; margin-top: 4px; background: color-mix(in srgb, var(--muted) 28%, transparent); border-radius: var(--r-full); overflow: hidden; }
.ctrl-prog-mini > span { display: block; height: 100%; background: var(--fabim-success); border-radius: var(--r-full); }

.ctrl-acoes-cell { white-space: nowrap; }
.ctrl-item-save.is-dirty { background: var(--accent); color: #fff; }
.ctrl-item-save.is-dirty:hover { filter: brightness(1.08); }
.ctrl-item-save:disabled { opacity: .35; cursor: default; }

.ctrl-resumo-total { margin-top: var(--sp-4); padding: var(--sp-4); background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--r-2); }
.ctrl-resumo-title { display: block; font-size: var(--fs-2); margin-bottom: var(--sp-3); text-transform: uppercase; letter-spacing: .07em; }
/* Metricas em colunas: icone num circulo da cor, valor grande, rotulo. */
.ctrl-rt-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--sp-3); align-items: end; margin: var(--sp-4) 0; }
.ctrl-rt-metric { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 7px; --c: var(--muted); }
.ctrl-rt-metric.is-plan { --c: #4cc38a; }
.ctrl-rt-metric.is-exec { --c: #3b82f6; }
.ctrl-rt-metric.is-rest { --c: #9d8cf0; }
.ctrl-rt-ico { display: grid; place-items: center; width: 46px; height: 46px; border-radius: var(--r-full);
  color: var(--c); border: 1.5px solid color-mix(in srgb, var(--c) 65%, transparent);
  background: color-mix(in srgb, var(--c) 12%, transparent);
  box-shadow: 0 0 10px color-mix(in srgb, var(--c) 28%, transparent); }
.ctrl-rt-ico i, .ctrl-rt-ico svg { width: 22px; height: 22px; }
.ctrl-rt-val { color: var(--c); font-size: var(--fs-6); font-weight: var(--fw-bold); font-variant-numeric: tabular-nums; line-height: 1; }
.ctrl-rt-metric small { color: var(--muted); font-size: var(--fs-1); }
/* Anel de progresso (donut) via conic-gradient + mask que recorta o miolo. */
.ctrl-rt-ring { position: relative; width: 66px; height: 66px; display: grid; place-items: center; }
.ctrl-rt-ring::before { content: ""; position: absolute; inset: 0; border-radius: var(--r-full);
  background: conic-gradient(var(--fabim-success) calc(var(--pct) * 1%), color-mix(in srgb, var(--muted) 22%, transparent) 0);
  -webkit-mask: radial-gradient(farthest-side, #0000 calc(100% - 8px), #000 calc(100% - 7px));
          mask: radial-gradient(farthest-side, #0000 calc(100% - 8px), #000 calc(100% - 7px));
  filter: drop-shadow(0 0 5px color-mix(in srgb, var(--fabim-success) 40%, transparent)); }
.ctrl-rt-ring b { position: relative; color: var(--fabim-success); font-size: var(--fs-4); font-weight: var(--fw-bold); font-variant-numeric: tabular-nums; }
/* Barra linear com brilho neon (mesmo verde do progresso). */
.ctrl-rt-bar-row { display: flex; align-items: center; gap: var(--sp-3); }
.ctrl-rt-bar { flex: 1; height: 10px; border-radius: var(--r-full); background: color-mix(in srgb, var(--muted) 22%, transparent); overflow: hidden; }
.ctrl-rt-bar > span { display: block; height: 100%; border-radius: var(--r-full);
  background: linear-gradient(90deg, color-mix(in srgb, var(--fabim-success) 65%, transparent), var(--fabim-success));
  box-shadow: 0 0 10px color-mix(in srgb, var(--fabim-success) 55%, transparent); }
.ctrl-rt-bar-pct { color: var(--fabim-success); font-weight: var(--fw-bold); font-variant-numeric: tabular-nums; }

.ctrl-dica-legend { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: var(--sp-3); margin-top: var(--sp-3); padding: var(--sp-3) var(--sp-4); background: var(--panel-2); border-radius: var(--r-2); font-size: var(--fs-2); color: var(--muted); }
.ctrl-dica i { width: 15px; height: 15px; vertical-align: -3px; margin: 0 4px; color: var(--accent); }
.ctrl-legend { display: inline-flex; gap: var(--sp-3); }
.ctrl-lg { display: inline-flex; align-items: center; gap: 4px; }
.ctrl-lg i { width: 14px; height: 14px; }
.ctrl-lg-done { color: var(--fabim-success); }
.ctrl-lg-doing { color: var(--fabim-warning); }
.ctrl-lg-todo { color: var(--muted); }
.ctrl-projetista { background: var(--panel-2); border: 1px solid var(--border); color: var(--text); border-radius: var(--r-1); padding: 4px 6px; font-size: var(--fs-1); max-width: 150px; }
.ctrl-planned { width: 60px; background: var(--panel-2); border: 1px solid var(--border); color: var(--text); border-radius: var(--r-1); padding: 4px 6px; font-size: var(--fs-2); text-align: right; }

/* Alinhado a direita e simetrico com o "Acrescentar dia" (mesmo botao 178x38,
   mesmo respiro de 16px+borda da caixa do controle diario). */
/* O "fora do ciclo" saiu em 20/08/2026 e levou junto o esmaecido da linha e a
   faixa de "mostrar as N ocultas" -- ver a nota no schema do controle.py. */

/* O seletor de revisao por folha saiu em 20/08/2026: a revisao e apontada na
   IMPORTACAO de folhas (le do nome do arquivo) e pelo botao "Revisar folha". */

.ctrl-add-item { display: flex; gap: var(--sp-3); align-items: center; justify-content: flex-end; margin-top: var(--sp-4); margin-bottom: var(--sp-4); padding-right: calc(var(--sp-4) + 1px); }
.ctrl-add-item input { width: auto; flex: 0 0 340px; min-height: 0; background: var(--panel-2); border: 1px solid var(--border); color: var(--text); border-radius: var(--r-1); padding: 7px 10px; }
.ctrl-add-item button { justify-content: center; min-width: 178px; height: 38px; min-height: 0; white-space: nowrap; }

.ctrl-hold-block { margin-top: var(--sp-4); padding: var(--sp-3); background: var(--warning-soft); border-radius: var(--r-2); font-size: var(--fs-2); }
.ctrl-hold-current { display: flex; align-items: center; gap: 6px; color: var(--text); }
.ctrl-hold-history { margin-top: var(--sp-2); }
.ctrl-hold-history summary { cursor: pointer; color: var(--muted); }
.ctrl-hold-row { display: flex; flex-wrap: wrap; gap: var(--sp-3); padding: 4px 0; border-top: 1px solid var(--border); color: var(--muted); }

.ctrl-error { color: var(--fabim-danger); }

/* Hold (retirar) — radios no diálogo do Planejamento */
.hold-return { display: flex; gap: var(--sp-4); margin: var(--sp-2) 0; }
.hold-return label { display: flex; align-items: center; gap: var(--sp-2); }
.planning-mini-button.pd-hold-on { color: var(--fabim-warning); }
/* Folha ja concluida: o botao vira "reabrir" e fica verde, para o estado se ler
   sem passar o mouse. O icone tambem troca (check-check -> rotate-ccw); a cor
   existe porque dois icones parecidos numa fileira de seis botoes nao bastam. */
.ctrl-item-concluir.is-concluida { color: var(--fabim-success); }
/* Aviso de erro DENTRO do dialogo (varredura de 24/08/2026: a mensagem morava
   fora e o backdrop do <dialog> modal a escondia). Vazio nao ocupa espaco --
   `:empty` em vez de altura fixa, senao sobra um vao acima do botao Salvar em
   todo formulario que nunca falhou. */
.dialog-status { margin: 2px 0 0; font-size: var(--fs-2); color: var(--fabim-danger); }
.dialog-status:empty { display: none; }
/* Salvar/descartar por raia: digitar vira rascunho; nada vai para o servidor
   sem clique. Os botoes so acendem quando existe alteracao NESTE projeto. */
/* Total do dia na Linha de Balanço do usuário: a MESMA bolinha do quadro
   (.planning-total-chip) com a régua faltando/completo/estourado — a cor mora
   na bolinha; o fundo da célula fica transparente pela regra do .user-lob-wrap. */
.user-lob-total .planning-person small { display: block; color: var(--fabim-muted); font-weight: 600; }
.user-lob-total-cell { font-weight: 800; font-variant-numeric: tabular-nums; text-align: center; }

/* Barra do Planejamento em dois grupos (filtros | ações) com o menu "Mais",
   para a fileira de botões parar de crescer sem fim. */
.planning-tool-group { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.planning-tool-group + .planning-tool-group {
  padding-left: 12px; margin-left: 4px; border-left: 1px solid var(--border);
}
.planning-more { position: relative; display: inline-flex; }
.planning-more-menu {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 40;
  display: flex; flex-direction: column; gap: 6px; padding: 8px;
  min-width: 200px; border-radius: 12px;
  border: 1px solid var(--border); background: var(--panel-3);
  box-shadow: 0 18px 40px rgba(2, 6, 12, 0.45);
}
.planning-more-menu[hidden] { display: none; }
.planning-more-menu .button-secondary { justify-content: flex-start; width: 100%; }

/* Filtro de projetos: lista rolável de caixas de seleção. */
.planning-projects-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.planning-projects-list { max-height: 46vh; overflow-y: auto; display: grid; gap: 2px; margin-bottom: 14px; }
.planning-project-item {
  display: flex; align-items: center; gap: 10px; padding: 7px 10px;
  border-radius: 8px; font-size: 13px; cursor: pointer;
}
.planning-project-item:hover { background: var(--surface-glass); }
.planning-project-item input { width: 16px; height: 16px; min-height: 0; flex: none; }

/* Lista de planos não salvos, com um Salvar por projeto. */
.planning-unsaved-list { display: grid; gap: 8px; margin: 4px 0 14px; max-height: 44vh; overflow-y: auto; }
.planning-unsaved-item {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 12px; border-radius: 10px;
  border: 1px solid rgba(227, 179, 65, 0.45); background: rgba(227, 179, 65, 0.1);
}
.planning-unsaved-item small { display: block; color: var(--fabim-muted); font-size: 11px; }

.planning-draft-bar[hidden] { display: none; }
.planning-draft-bar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 8px; padding-top: 8px;
  border-top: 1px dashed var(--border);
}
.planning-draft-hint { font-size: 11px; color: var(--fabim-muted); }
.planning-draft-bar.is-dirty .planning-draft-hint { color: var(--fabim-warning); font-weight: 700; }
.planning-draft-bar.is-dirty .pd-save {
  color: var(--fabim-success);
  border-color: rgba(76, 195, 138, 0.55);
  background: var(--success-soft);
}
/* Celula com valor ainda nao salvo: contorno ambar, para o olho achar o que falta. */
.planning-table td.planning-cell input.cell-dirty {
  outline: 2px solid var(--fabim-warning);
  outline-offset: -2px;
  border-radius: 4px;
}
/* "Concluído" e um interruptor: verde = concluida (mas ainda na programacao),
   cinza padrao = em aberto. Arquivar e o botao ao lado. */
.planning-mini-button.pd-done-on {
  color: var(--fabim-success);
  border-color: rgba(76, 195, 138, 0.55);
  background: var(--success-soft);
}
/* Rodada 2 (14/08/2026): projeto concluido/travado troca o verde por cinza
   neutro (mesma familia do .pd-state.done) -- o botao continua clicavel
   (reabre), so muda a cor. Precisa morar FORA do @layer views, junto da
   regra verde acima: uma regra dentro do layer nunca vence uma de fora,
   mesmo com especificidade maior. */
.planning-demand-row.is-locked .pd-done-on {
  color: #9aa3b2; border-color: rgba(154, 163, 178, .35); background: rgba(154, 163, 178, .14);
}
html.light .planning-demand-row.is-locked .pd-done-on {
  color: #5b6472;
}

/* Responsivo: tablet mantém 4 colunas roláveis; telas menores rolam na horizontal */
@media (max-width: 1100px) {
  .ctrl-columns { grid-template-columns: repeat(4, minmax(220px, 1fr)); overflow-x: auto; }
}
@media (max-width: 780px) {
  .ctrl-columns { display: flex; overflow-x: auto; scroll-snap-type: x proximity; padding-bottom: var(--sp-2); }
  .ctrl-column { flex: 0 0 82vw; scroll-snap-align: start; }
  .controle-detail-dialog { width: 100vw; max-width: 100vw; }
}

@media (prefers-reduced-motion: reduce) {
  .ctrl-card, .ctrl-progress-bar { transition: none; }
}

/* ===== Fase (da OS) nos cards e cabeçalhos ===== */
.ctrl-fase { display: inline-flex; align-items: center; gap: 4px; font-size: var(--fs-1); font-weight: var(--fw-medium); color: var(--accent); background: var(--accent-soft); border-radius: var(--r-full); padding: 2px 9px; }
.ctrl-fase i { width: 12px; height: 12px; }
/* A OS do card (19/08/2026). Mesmo tamanho da pilula de fase, que e a vizinha
   imediata: as duas se leem como um par ("OS07 · LO"), e tamanho diferente
   faria uma parecer mais importante que a outra. `i, svg` porque lucide TROCA
   o <i> por um <svg> ao renderizar -- regra so em `i` nao pega. */
.ctrl-os { display: inline-flex; align-items: center; gap: 4px; font-size: var(--fs-1); font-weight: var(--fw-bold); color: var(--accent); background: var(--accent-soft); border-radius: var(--r-full); padding: 2px 9px; }
.ctrl-os i, .ctrl-os svg { width: 12px; height: 12px; opacity: 0.75; }
/* Projeto com mais de uma OS: o contorno e o unico sinal de que ha historico
   atras deste card. O resto esta no title -- ele pediu sem ocupar espaco. */
.ctrl-os.has-serie { box-shadow: inset 0 0 0 1px var(--accent); cursor: help; }
/* Sem OS e ANOMALIA (a regra dele: toda demanda tem OS), entao nao pode passar
   com a cor de tudo o mais. */
.ctrl-os.is-sem-os { color: var(--fabim-warning); background: var(--warning-soft); font-weight: var(--fw-medium); }
/* Abas por OS na gaveta do Controle. As pilulas sao o `.os-tab` da tela de OS;
   so o contorno e proprio, porque a `.service-order-tabs` tem margem negativa
   casada com o padding daquele dialogo e aqui isso vazaria para fora. */
.ctrl-os-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 14px; padding-bottom: 12px; border-bottom: 1px solid var(--fabim-line); }
.ctrl-os-tabs .os-tab:disabled { opacity: 0.45; cursor: not-allowed; }
.ctrl-fase-inline { display: inline-flex; align-items: center; gap: 4px; color: var(--accent); }
.ctrl-fase-inline i { width: 13px; height: 13px; vertical-align: -2px; }
/* Mesmo tamanho das outras pilulas da raia (19/08/2026) -- ver
   `.planning-os-badge`. `i, svg` porque lucide TROCA o <i> por um <svg> ao
   desenhar: regra so em `i` nao pega depois do render. */
.planning-fase-badge { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 700; color: var(--accent); background: var(--accent-soft); border-radius: var(--r-full); padding: 3px 11px; margin-left: 6px; white-space: nowrap; }
.planning-fase-badge i, .planning-fase-badge svg { width: 13px; height: 13px; }

/* ===== Botão de horas travado (só lança horas em "Fazendo") ===== */

/* ===== Controle diário de horas (uma linha por dia, coluna por atividade) ===== */
.ctrl-daily { border: 1px solid var(--border); border-radius: var(--r-2); background: var(--panel); overflow: hidden; }
/* Sem rolagem propria: a diaria acompanha a tabela de cima no mesmo scroller
   (a do .controle-detail-content), senao as colunas desalinham ao rolar. */
.ctrl-daily-wrap { overflow-x: visible; }
.ctrl-daily-table { width: 100%; min-width: 1000px; border-collapse: collapse; font-size: var(--fs-2); table-layout: fixed; }
.ctrl-daily-table th, .ctrl-daily-table td { padding: 7px 10px; border-bottom: 1px solid var(--border); text-align: center; }
.ctrl-daily-table thead th { background: var(--thead-glass); color: var(--thead-text); font-weight: var(--fw-bold); font-size: 10px; text-transform: uppercase; letter-spacing: .02em; }
.ctrl-daily-date-h, .ctrl-daily-date { text-align: left; white-space: nowrap; }
.ctrl-daily-date { color: var(--text); font-variant-numeric: tabular-nums; }
.ctrl-daily-date i, .ctrl-daily-date svg { width: 14px; height: 14px; color: var(--accent); vertical-align: -3px; margin-right: 7px; }
.ctrl-daily-cell { font-variant-numeric: tabular-nums; }
.ctrl-daily-cell.is-zero { color: var(--muted); }
.ctrl-hours-mini { display: inline-flex; align-items: center; gap: 2px; background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--r-1); padding: 1px 3px 1px 6px; }
.ctrl-hours-mini .ctrl-hours-val { min-width: 40px; }
.ctrl-daily-row.is-editing { background: var(--accent-soft); }
/* Zebra por DIA, nao por linha: um dia pode ocupar varias linhas (uma por
   pessoa), entao zebrar linha a linha separaria pessoas em vez de datas. O
   tom e bem leve -- e so para o olho achar onde a data comeca e acaba. A cor
   das pilulas de nome nao muda: elas identificam a pessoa. */
.ctrl-daily-table tbody tr.ctrl-daily-row.is-alternada > td { background: rgba(255, 255, 255, 0.028); }
.ctrl-daily-table tbody tr.ctrl-daily-row.is-alternada.is-editing > td { background: var(--accent-soft); }
.ctrl-daily-table tfoot td { border-top: 2px solid var(--border); border-bottom: none; font-weight: var(--fw-bold); color: var(--text); }
.ctrl-daily-total-label { text-align: left; text-transform: uppercase; font-size: 10px; letter-spacing: .03em; color: var(--muted); }
.ctrl-daily-total { color: var(--fabim-success); }
.ctrl-daily-total.is-zero { color: var(--text); }
.ctrl-daily-empty-row td { color: var(--muted); text-align: center; padding: var(--sp-4); }
.ctrl-daily-actions { white-space: nowrap; }
/* base.css poe width:100% em input: sem o flex fixo, a data engole a linha toda */
.ctrl-daily-date-input { background: var(--panel); border: 1px solid var(--accent-line); color: var(--text); border-radius: var(--r-1); padding: 3px 6px; font-size: var(--fs-1); font-variant-numeric: tabular-nums; }
.ctrl-daily-moved { color: var(--accent); font-weight: var(--fw-bold); }
.ctrl-item-discard:not(:disabled) { color: var(--fabim-warning); }
.ctrl-item-discard:disabled { opacity: .35; cursor: default; }

/* ===== Apontamento: tipo de lançamento (manual x automático) ===== */
.filter-tipo { display: inline-flex; gap: 4px; align-items: flex-end; }
.filter-tipo-btn { display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; border: 1px solid var(--border); background: var(--panel-2); color: var(--muted); border-radius: var(--r-1); cursor: pointer; }
.filter-tipo-btn:hover { color: var(--text); border-color: var(--accent-line); }
.filter-tipo-btn.is-active { background: var(--accent-soft); color: var(--accent); border-color: var(--accent); }
.filter-tipo-btn i { width: 16px; height: 16px; }
/* 52px e o MINIMO que mostra o rotulo "TIPO" inteiro (medido em 21/08/2026,
   pedido de coluna justa) — mesma largura do mapa da .hours-table. */
.tipo-head { width: 52px; text-align: center; }
.tipo-cell { text-align: center; }
.tipo-badge { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; border-radius: var(--r-full); }
.tipo-badge i { width: 15px; height: 15px; }
.tipo-manual { color: var(--muted); background: var(--panel-2); }
.tipo-auto { color: var(--accent); background: var(--accent-soft); }

/* ===== Lista mestra de pranchas ===== */
/* display SO no [open]: uma regra base com `display` vence o display:none
   que o navegador da ao dialog fechado e ele aparece em todas as abas --
   foi o que aconteceu na Dashboard em 30/07/2026. */
/* display SO no [open]: uma regra base com `display` vence o display:none que
   o navegador da ao dialog fechado e ele aparece em TODA aba -- foi o que
   aconteceu na Dashboard em 30/07/2026. */
.lista-mestra-dialog[open] { display: flex; flex-direction: column; gap: var(--sp-6); width: min(1400px, 96vw); max-height: 92vh; overflow: auto; padding: var(--sp-8); background: var(--fabim-canvas); }

/* Faixa de topo: marca a esquerda, passos no meio, fechar a direita. */
.lista-mestra-barra { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: var(--sp-4); padding-bottom: var(--sp-4); border-bottom: 1px solid var(--fabim-line); }
.lista-mestra-barra > button { justify-self: end; }
.lista-mestra-marca { display: flex; align-items: center; gap: var(--sp-3); }
.lista-mestra-marca img { height: 34px; width: auto; }
.lista-mestra-marca div { display: flex; flex-direction: column; line-height: 1.15; }
.lista-mestra-marca b { font-size: var(--fs-5); font-weight: var(--fw-strong); letter-spacing: .02em; }
.lista-mestra-marca span { font-size: var(--fs-1); text-transform: uppercase; letter-spacing: .1em; color: var(--fabim-muted); }

/* Projeto: titulo com barra azul, nao campo de formulario. */
.lista-mestra-projeto-faixa { border-left: 3px solid var(--accent-strong); padding-left: var(--sp-4); }
.lista-mestra-projeto-faixa h2 { margin: 0; font-size: var(--fs-6); font-weight: var(--fw-bold); }
.lista-mestra-projeto-faixa p { margin: 2px 0 0; font-size: var(--fs-2); color: var(--fabim-muted); }

/* Passos: indicadores, nao navegacao -- tudo vive numa tela so. */
.lista-mestra-passos { display: flex; align-items: center; justify-content: center; gap: var(--sp-4); list-style: none; margin: 0; padding: 0; flex-wrap: wrap; }
.lista-mestra-passos li { display: flex; align-items: center; gap: var(--sp-2); color: var(--fabim-steel); font-size: var(--fs-2); font-weight: var(--fw-medium); text-transform: uppercase; letter-spacing: .04em; }
.lista-mestra-passos li + li::before { content: ""; width: 120px; max-width: 12vw; height: 1px; background: var(--fabim-line-strong); margin-right: var(--sp-4); }
.lista-mestra-passos b { display: grid; place-items: center; width: 26px; height: 26px; border-radius: var(--r-full); background: var(--fabim-surface-soft); color: var(--fabim-muted); font-size: var(--fs-1); font-weight: var(--fw-bold); flex: none; }
.lista-mestra-passos li.ativo { color: var(--accent-strong); }
.lista-mestra-passos li.ativo b { background: var(--accent-strong); color: #fff; }

/* Paineis: fundo elevado + barra azul no titulo, como o resto do sistema. */
.lista-mestra-painel { background: var(--fabim-surface); border: 1px solid var(--fabim-line); border-radius: var(--r-2); padding: var(--sp-6); }
.lista-mestra-painel h3 { display: flex; align-items: center; gap: var(--sp-3); margin: 0 0 var(--sp-6); font-size: var(--fs-3); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: .06em; color: var(--fabim-text); }
.lista-mestra-painel h3::before { content: ""; width: 3px; align-self: stretch; min-height: 16px; border-radius: var(--r-full); background: var(--accent-strong); }

.lista-mestra-topo { display: grid; grid-template-columns: minmax(0, 2.1fr) minmax(0, 1fr); gap: var(--sp-6); align-items: start; }
/* Grade de 12 para dar as proporcoes do desenho: a folha ocupa metade da
   primeira linha, REV. e estreita, a descricao toma a linha inteira, e
   tipo/escala/desenhista/formato dividem a ultima em quatro iguais. */
.lista-mestra-campos { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--sp-4) var(--sp-6); align-items: start; }
.lista-mestra-campos > label { grid-column: span 3; }
.lista-mestra-campos .lm-folha { grid-column: span 6; }
.lista-mestra-campos .lm-rev { grid-column: span 2; }
.lista-mestra-campos .lm-data { grid-column: span 4; }
.lista-mestra-campos .lm-desc { grid-column: 1 / -1; }
.lista-mestra-campos .lm-desc textarea { resize: vertical; min-height: 62px; font-family: inherit; }
/* O rotulo tem de ser UM item flex, senao o asterisco vira item proprio e
   cai na linha de baixo. O min-height de duas linhas mantem os campos da
   mesma linha alinhados quando um rotulo quebra ("Formato da folha -
   detalhes") e os vizinhos nao. */
.lista-mestra-campos .lm-rot { display: block; line-height: 1.35; min-height: 2.7em; }
.lista-mestra-campos em { font-style: normal; color: #f87171; }
.lista-mestra-campos label { display: flex; flex-direction: column; gap: var(--sp-2); font-size: var(--fs-1); font-weight: var(--fw-medium); text-transform: uppercase; letter-spacing: .06em; color: var(--fabim-muted); }
.lista-mestra-campos input, .lista-mestra-campos select, .lista-mestra-campos textarea { width: 100%; text-transform: none; letter-spacing: normal; }
.lista-mestra-col-incluir input[type="checkbox"] { min-height: 0; height: 14px; width: 14px; margin: 0; vertical-align: middle; }
.lista-mestra-campos small { font-size: var(--fs-1); font-weight: var(--fw-normal); text-transform: none; letter-spacing: normal; color: var(--fabim-steel); }

/* Nome do projeto: vem do projeto e nao se edita -- cadeado a direita. */
.lista-mestra-fixo { position: relative; display: block; }
.lista-mestra-fixo input { padding-right: 34px; background: var(--fabim-surface-soft); color: var(--fabim-muted); cursor: default; }
.lista-mestra-fixo i, .lista-mestra-fixo svg { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); width: 15px; height: 15px; color: var(--fabim-steel); pointer-events: none; }

.lista-mestra-infos ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-4); }
.lista-mestra-infos li { display: flex; align-items: flex-start; gap: var(--sp-3); color: var(--fabim-muted); font-size: var(--fs-2); line-height: 1.45; }
/* Lucide troca o <i> por <svg>: dimensionar os dois, senao o icone estica. */
.lista-mestra-infos i, .lista-mestra-infos svg { width: 18px; height: 18px; flex: none; color: var(--accent-strong); margin-top: 1px; }

.lista-mestra-previa .table-wrap { border: 1px solid var(--fabim-line); border-radius: var(--r-1); overflow: auto; }
/* max-content + min-width 100%: com width:100% a tabela espremia as colunas e
   cortava "NOME DO ARQUIVO (PLA...". Assim cada coluna cabe o seu conteudo e
   o .table-wrap rola na horizontal quando precisa. */
.lista-mestra-previa table { width: 100%; border-collapse: collapse; font-size: var(--fs-2); }
.lista-mestra-previa thead th { position: sticky; top: 0; background: var(--fabim-navy-800); color: var(--fabim-text); font-size: var(--fs-1); font-weight: var(--fw-bold); letter-spacing: .05em; text-align: center; padding: var(--sp-2) var(--sp-3); white-space: nowrap; border-bottom: 1px solid var(--fabim-line-strong); border-right: 1px solid var(--fabim-line-strong); }
.lista-mestra-previa thead th:last-child { border-right: 0; }
/* Cabecalho ordenavel (17/08/2026). O th e um controle: responde ao mouse e
   ao teclado, e a coluna ativa fica marcada na cor de destaque. */
.lista-mestra-previa thead th[data-lm-ordem] { cursor: pointer; user-select: none; }
.lista-mestra-previa thead th[data-lm-ordem]:hover { color: var(--accent-strong); }
.lista-mestra-previa thead th[data-lm-ordem]:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: -2px; }
.lista-mestra-previa thead th[aria-sort="ascending"],
.lista-mestra-previa thead th[aria-sort="descending"] { color: var(--accent-strong); }
/* A seta anda COLADA no titulo, nao na borda da coluna: em NOME DA FOLHA, que
   e larga (26%) e alinhada a esquerda, uma seta presa a direita ficaria a
   300px do texto e nao se leria como indicador daquela coluna.
   Colar no texto tem um preco: a tabela herda `table-layout: fixed` e as
   colunas tem largura em px com `white-space: nowrap` -- a seta some para
   FORA do fluxo (`position: absolute`) para nao empurrar o titulo e estourar
   a coluna estreita (REV. tem 62px). O ancoramento e um `<span>` inline
   (`.lm-ordem-marca`), que fica no fim do texto e serve de referencia; sem
   ele a seta se penduraria no th, que e a coluna inteira. */
.lista-mestra-previa thead th[data-lm-ordem] .lm-ordem-marca { position: relative; }
.lista-mestra-previa thead th[aria-sort="ascending"] .lm-ordem-marca::after,
.lista-mestra-previa thead th[aria-sort="descending"] .lm-ordem-marca::after { position: absolute; left: 2px; top: 50%; transform: translateY(-50%); font-size: 9px; line-height: 1; pointer-events: none; }
.lista-mestra-previa thead th[aria-sort="ascending"] .lm-ordem-marca::after { content: "▲"; }
.lista-mestra-previa thead th[aria-sort="descending"] .lm-ordem-marca::after { content: "▼"; }
/* A tabela generica corta celula com ellipsis num max-width fixo, o que
   comia o nome da prancha ("0872-KL-IMP-PE-0001-PL..."). Aqui o nome tem de
   aparecer inteiro -- o .table-wrap rola na horizontal se precisar. */
.lista-mestra-previa th, .lista-mestra-previa td { max-width: none; overflow: hidden; text-overflow: ellipsis; }
/* Linhas enxutas de proposito: 13+ pranchas tem de caber na tela sem rolar
   meia pagina. Altura vem do padding, entao ele fica no minimo legivel. */
.lista-mestra-previa tbody td { height: auto; padding: var(--sp-1) var(--sp-3); line-height: 1.35; text-align: center; white-space: nowrap; border-bottom: 1px solid var(--fabim-line); border-right: 1px solid var(--fabim-line); color: var(--fabim-text); }
.lista-mestra-previa tbody td:last-child { border-right: 0; }
/* O input global tem min-height 38px, e era ELE que esticava a linha para
   47px -- nao o padding. Sem anular isso, mexer no padding nao muda nada. */
.lista-mestra-previa tbody input[type="checkbox"] { min-height: 0; height: 14px; width: 14px; margin: 0; padding: 0; vertical-align: middle; }
/* Larguras: o nome e a descricao mandam, o resto encolhe ao conteudo.
   `width: 1%` + nowrap e o jeito de dizer "so o necessario" numa tabela. */
.lista-mestra-previa tbody td:first-child { text-align: left; font-variant-numeric: tabular-nums; }
.lista-mestra-previa thead th:first-child { text-align: left; }
/* A tabela herda `table-layout: fixed`: aqui a largura declarada e a
   largura FINAL, e `width: 1%` vira 1% literal (12px) com o texto vazando
   por cima do vizinho. Por isso os valores sao explicitos, e a DESCRICAO
   fica sem width para absorver a sobra. */
.lista-mestra-previa .lm-c-nome { width: 26%; }
.lista-mestra-previa th:nth-child(3) { width: 78px; }
.lista-mestra-previa th:nth-child(4) { width: 86px; }
.lista-mestra-previa th:nth-child(5) { width: 158px; }
.lista-mestra-previa th:nth-child(6) { width: 96px; }
.lista-mestra-previa th:nth-child(7) { width: 62px; }
.lista-mestra-previa th:nth-child(8) { width: 128px; }
.lista-mestra-previa tbody tr:last-child td { border-bottom: 0; }
/* A linha e o seletor da prancha: clicar nela carrega os campos de cima.
   Por isso ela responde ao mouse e ao teclado como um controle. */
.lista-mestra-previa tbody tr.lm-linha { cursor: pointer; }
.lista-mestra-previa tbody tr.lm-linha:hover td { background: var(--fabim-surface-soft); }
.lista-mestra-previa tbody tr.lm-linha:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: -2px; }
.lista-mestra-previa tbody tr.ativa td { background: var(--accent-soft); }
.lista-mestra-previa tbody tr.ativa td:first-child { box-shadow: inset 3px 0 0 var(--accent-strong); }
.lista-mestra-col-incluir { width: 40px; }

.lista-mestra-rodape { display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-4); flex-wrap: wrap; }
.lista-mestra-contador { display: flex; align-items: center; gap: var(--sp-4); margin-right: auto; padding: var(--sp-3) var(--sp-6); background: var(--fabim-surface); border: 1px solid var(--fabim-line); border-radius: var(--r-2); }
.lista-mestra-contador > i, .lista-mestra-contador > svg { width: 26px; height: 26px; flex: none; color: var(--accent-strong); }
.lista-mestra-contador > div { display: flex; flex-direction: column; line-height: 1.15; }
.lista-mestra-contador-rotulo { font-size: var(--fs-1); font-weight: var(--fw-medium); text-transform: uppercase; letter-spacing: .06em; color: var(--fabim-muted); }
.lista-mestra-contador b { font-size: var(--fs-6); font-weight: var(--fw-strong); color: var(--fabim-text); }
.lista-mestra-contador small { font-size: var(--fs-1); color: var(--fabim-steel); }
.lista-mestra-rodape button { text-transform: uppercase; letter-spacing: .05em; font-weight: var(--fw-bold); padding: var(--sp-3) var(--sp-6); }
/* Sem isso o atributo disabled bloqueia o clique mas o botao continua com a
   mesma cor -- zero selecionadas parecia clicavel. */
#lista-mestra-gerar:disabled { opacity: 0.35; cursor: not-allowed; }

/* Celula de acoes da entrega: e-mail + lista mestra. O `overflow: visible` e
   `text-overflow: clip` sao obrigatorios -- o ellipsis herdado de `tbody td`
   engolia o segundo botao e desenhava um "..." no lugar dele. Regra de topo de
   proposito: a versao anterior ficou dentro de um @media que nao casava, e nao
   valia nada. A LARGURA fica no bloco logo abaixo. */
.deliveries-table td.delivery-email-cell,
td.delivery-email-cell {
  overflow: visible;
  text-overflow: clip;
  white-space: nowrap;
  text-align: center;
}
td.delivery-email-cell .icon-button { display: inline-flex; vertical-align: middle; }

/* ---- Entregas: coluna de acoes espremida e leitura por alinhamento -------
   A coluna de acoes so precisa caber DOIS botoes; os 104px vinham do tamanho
   padrao do .icon-button (38px) mais o respiro de td (11px de cada lado). Aqui
   a CAIXA do botao cai para 26px (o icone dentro nao muda) e o respiro vai a 1px
   largura que sobra vai para o nome do projeto, que e o que se procura na
   linha. Nao mexer no .icon-button global: ele e usado na tela inteira. */
.deliveries-table th.email-head { width: 56px; min-width: 56px; }
.deliveries-table td.delivery-email-cell {
  min-width: 56px;
  /* Respiro ZERO: dois botoes de 38px ja somam 76px e sao o piso fisico da
     coluna. Cada pixel de padding aqui sai do nome do projeto, entao os 2px que
     sobram sao so a folga contra o corte do ellipsis herdado de `tbody td`. */
  padding-left: 1px;
  padding-right: 1px;
}
/* A tabela e `table-layout: fixed`, e nesse modo a sobra de largura e
   redistribuida por TODAS as colunas -- os 68px acima viravam 146px sozinhos.
   Para a coluna ficar magra de verdade, as demais precisam de largura fixa e a
   sobra tem de ter para onde ir: PROJETO e ESCOPO ficam de proposito SEM
   largura, entao sao eles que engordam. E o que se quer -- o nome do projeto e
   o que se procura na linha.
   A ordem abaixo e a do <thead> em index.html; test_entregas_ui.mjs trava essa
   ordem, entao mexer no cabecalho sem mexer aqui quebra o teste, nao a tela. */
.deliveries-table thead th:nth-child(1)  { width: 112px; }  /* Status  */
.deliveries-table thead th:nth-child(2)  { width: 56px; }   /* Ações   */
.deliveries-table thead th:nth-child(3)  { width: 96px; }   /* Data    */
.deliveries-table thead th:nth-child(5)  { width: 170px; }  /* Cliente */
.deliveries-table thead th:nth-child(6)  { width: 74px; }   /* PR      */
.deliveries-table thead th:nth-child(7)  { width: 78px; }   /* OS      */
.deliveries-table thead th:nth-child(8)  { width: 66px; }   /* Fase    */
.deliveries-table thead th:nth-child(9)  { width: 78px; }   /* Quadro  */
.deliveries-table thead th:nth-child(10) { width: 78px; }   /* Plantas */
.deliveries-table thead th:nth-child(11) { width: 82px; }   /* Detalhes*/
.deliveries-table thead th:nth-child(13) { width: 78px; }   /* Semana  */
/* Botao de volta aos 38px do padrao, a pedido do Fabio: em 28px ficavam
   pequenos demais para acertar o clique. O ganho de largura vem do que esta AO
   REDOR deles -- padding da celula e margem entre os botoes, ambos no minimo --,
   nao do tamanho do alvo. Sem margem lateral: os 76px dos dois botoes sao o
   piso, e 1px de cada lado ja custa 2px do nome do projeto. */
/* O ICONE nao muda -- muda a CAIXA em volta dele. Um .icon-button de 38px
   carrega ~13px de vazio de cada lado do glifo; e esse vazio, nao o icone, que
   estava roubando a largura do nome do projeto. A caixa cai para 26x30 e sobram
   ~4px de folga por lado, suficientes para o alvo do clique continuar honesto.
   Nada de regra para o `svg` aqui: e justamente o que NAO pode encolher. */
.deliveries-table td.delivery-email-cell .icon-button {
  width: 26px; min-width: 26px;
  height: 30px; min-height: 30px;
  padding: 0;
  margin: 0;
}

/* Valor curto e comparavel (data, PR, OS, fase, Sim/Nao, semana, status) fica
   CENTRADO: a coluna vira uma pilha alinhada e a diferenca salta. Texto que se
   le em sequencia -- projeto, cliente, escopo -- fica a esquerda, senao o olho
   perde onde cada linha comeca. */
.deliveries-table th.dl-center,
.deliveries-table td.dl-center { text-align: center; }

/* O nome do projeto e o que se procura na linha: mais peso e o texto cheio,
   enquanto o resto da linha usa o tom normal da tabela.
   14/08/2026: caiu a variante `html.light` que usava --fabim-navy-700 -- no
   tema claro esse token vira SUPERFICIE (#dfe6ee) e o nome sumia sobre o
   branco. --fabim-text ja e o navy escuro no claro e o texto claro no escuro. */
.deliveries-table td.dl-project {
  color: var(--fabim-text);
  font-weight: var(--fw-strong);
  font-size: var(--fs-2);
}

/* Estado do backup externo, na tela de Administração. Existe porque o envio
   noturno para o Drive falhou 15 noites seguidas (01→15/08/2026) sem ninguém
   ver: a informação só morava num log dentro da própria VM que o backup
   deveria proteger. Agora o sistema diz na cara. */
.backup-offsite {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 8px 0 0;
  padding: 3px 10px;
  border: 1px solid transparent;
  border-radius: 999px;
  font-size: var(--fs-2);
  font-weight: var(--fw-medium);
}

.backup-offsite.is-ok {
  color: #7fd39e;
  background: rgba(85, 184, 120, 0.14);
  border-color: rgba(85, 184, 120, 0.3);
}

.backup-offsite.is-alerta {
  color: #e3c06a;
  background: rgba(212, 173, 74, 0.14);
  border-color: rgba(212, 173, 74, 0.32);
}

.backup-offsite.is-falha {
  color: #f0a0a0;
  background: rgba(216, 92, 92, 0.16);
  border-color: rgba(216, 92, 92, 0.34);
}

/* Tema claro: os três tons acima nasceram sobre o navy e no branco ficam
   abaixo do 4,5:1 do WCAG. Aqui vão as versões escuras; o vermelho é o mesmo
   #b63b44 que a auditoria de 14/08 aprovou para .error. Os fundos rgba
   continuam servindo nos dois temas. */
html.light .backup-offsite.is-ok { color: #1c6b3f; }
html.light .backup-offsite.is-alerta { color: #7a5710; }
html.light .backup-offsite.is-falha { color: #b63b44; }

/* Pendencias de projeto (Administracao). A coluna do texto e a unica que pode
   crescer; as outras ficam presas ao conteudo. As larguras vao no th porque as
   regras globais de tabela deste projeto ignoram largura posta no td -- ja
   custou tempo antes. */
.pendencias-table { width: 100%; }
.pendencias-table .pd-quantas { width: 9rem; }
.pendencias-table .pd-projeto { width: 22rem; }
.pendencias-table .pd-acao { width: 7rem; }
.pendencias-table .pd-center { text-align: center; }
.pendencias-table .pd-select { width: 100%; }
.pendencias-table .pd-dica { display: block; opacity: 0.7; font-size: 0.78rem; }
.pendencias-table .pd-sem { font-style: italic; }
.pendencias-table .pd-novo { font-weight: 600; }
.pendencias-table .pd-vazio { text-align: center; opacity: 0.75; padding: 1.25rem 0; }

/* Cadastro de projetos. Mesma regra da tabela acima: a largura vai no th. O
   PR nao tem campo -- ele e a identidade e so aparece. */
.projetos-table { width: 100%; }
.projetos-table .pj-pr { width: 7rem; }
.projetos-table .pj-cliente { width: 14rem; }
.projetos-table .pj-uso { width: 16rem; }
.projetos-table .pj-acao { width: 13rem; }
.projetos-table .pj-center { text-align: center; }
.projetos-table .pj-campo { width: 100%; }
.projetos-table .pj-dica { display: block; opacity: 0.7; font-size: 0.78rem; font-style: italic; }
.projetos-table .pj-acao button + button { margin-left: 0.4rem; }

/* Codigo de apontamento novo. Uma linha so: o codigo, o nome, o cliente
   (opcional) e o botao -- e ele cria projeto e OS de uma vez. */
.codigo-form { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 0.75rem; }
.codigo-form input { flex: 1 1 10rem; min-width: 8rem; }
.codigo-form input[name="pr"] { flex: 0 0 10rem; }
.codigo-form button { flex: 0 0 auto; }

/* O PR resolvido pelo cadastro (Bloco 3, peca 3).

   O paragrafo e criado pelo JS logo abaixo do campo de PR, em quatro
   formularios: hora, entrega, demanda e OS. Como tres deles ficam dentro de um
   .form-grid, ele precisa atravessar a linha inteira -- posto numa celula so, o
   texto quebraria em duas palavras por linha. */
.projeto-pr-aviso {
  margin: 0.35rem 0 0;
  font-size: var(--fs-1);
  line-height: 1.35;
  color: var(--muted);
}
.form-grid > .projeto-pr-aviso { grid-column: 1 / -1; }
/* PR que ainda nao existe: vai ser cadastrado ao salvar, com o nome que estiver
   na tela. Sem um estado proprio, "conhecido" e "novo" ficariam com a mesma
   cara e o aviso viraria enfeite. */
.projeto-pr-aviso.novo { color: var(--fabim-warning); }
.projeto-pr-aviso[hidden] { display: none; }

/* No assistente de OS o aviso tem lugar FIXO: o passo 1 ja nasce com o <p>
   dentro de um SLOT de altura reservada, abaixo do par PR/Buscar e fora da
   grade. Aparecer/sumir nao pode empurrar o formulario (Fabio, 21/08/2026:
   "quanto digito o pr o layout muda, pula para baixo"). O espaco vem do
   involucro porque o base.css esconde [hidden] com !important -- regra no
   proprio <p> nunca venceria. */
.pr-aviso-slot { min-height: 25px; display: grid; align-items: center; }
/* Margem zero de proposito: margin-top de filho colapsa para FORA do slot e
   o formulario pulava 8px quando o aviso aparecia (grid nao colapsa, e o
   respiro vem do min-height do slot). */
.pr-aviso-slot .projeto-pr-aviso { margin: 0; }
